diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-01-12 02:14:03 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-01-12 02:14:03 -0800 |
commit | c5a379cdb48cf7f77195e2f714c3239fc895c12c (patch) | |
tree | e2212bc36189d9051ccf1b2c0389002c810465b2 /arch | |
parent | f95e6dae6522e0c403bef92405a3577ebd8baee9 (diff) | |
parent | 8aaf5f19fd6ada03688a6c465c75eb80f285ebad (diff) | |
download | history-c5a379cdb48cf7f77195e2f714c3239fc895c12c.tar.gz |
Merge bk://bk.arm.linux.org.uk/linux-2.6-rmk
into ppc970.osdl.org:/home/torvalds/v2.6/linux
Diffstat (limited to 'arch')
28 files changed, 556 insertions, 134 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index dc5864554f0ca2..1fddb764b48558 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -418,20 +418,6 @@ config XIP_PHYS_ADDR be linked for and stored to. This address is dependent on your own flash usage. - Please note that, if you're using MTD, you must use a flash chip - that is NOT handled by MTD or the flash will be turned into non - data mode for status and query purposes which will instantaneously - crash the kernel. - - MTD can however be used with a XIP kernel on the same flash chip - but only if the flash memory supports multiple partitions in - hardware, like with the Intel K3 flash parts, and only if the - kernel is not stored within the firrst hardware partition of the - chip. - - In any case, make sure that MTD support is configured out for - the first attempt. - if (ARCH_SA1100 || ARCH_INTEGRATOR) source "drivers/cpufreq/Kconfig" diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index 141dd460732f0c..dd41da34b0c977 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c @@ -100,11 +100,13 @@ int __init scoop_probe(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) return -EINVAL; + if (!mem) + return -EINVAL; inf = dev->platform_data; scoop_io_base = ioremap(mem->start, 0x1000); - if (!scoop_io_base) return -ENOMEM; + if (!scoop_io_base) + return -ENOMEM; SCOOP_REG(SCOOP_MCR) = 0x0140; diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 5b35e76c3ce44d..5e0656e889185e 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -32,6 +32,7 @@ #include <linux/errno.h> #include <linux/list.h> #include <linux/kallsyms.h> +#include <linux/proc_fs.h> #include <asm/irq.h> #include <asm/system.h> @@ -85,6 +86,23 @@ static struct irqdesc bad_irq_desc = { .disable_depth = 1, }; +#ifdef CONFIG_SMP +void synchronize_irq(unsigned int irq) +{ + struct irqdesc *desc = irq_desc + irq; + + while (desc->running) + barrier(); +} +EXPORT_SYMBOL(synchronize_irq); + +#define smp_set_running(desc) do { desc->running = 1; } while (0) +#define smp_clear_running(desc) do { desc->running = 0; } while (0) +#else +#define smp_set_running(desc) do { } while (0) +#define smp_clear_running(desc) do { } while (0) +#endif + /** * disable_irq_nosync - disable an irq without waiting * @irq: Interrupt to disable @@ -232,6 +250,9 @@ unlock: #ifdef CONFIG_ARCH_ACORN show_fiq_list(p, v); #endif +#ifdef CONFIG_SMP + show_ipi_list(p); +#endif seq_printf(p, "Err: %10lu\n", irq_err_count); } return 0; @@ -329,18 +350,22 @@ void do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { struct irqaction *action; - const int cpu = smp_processor_id(); + const unsigned int cpu = smp_processor_id(); desc->triggered = 1; kstat_cpu(cpu).irqs[irq]++; + smp_set_running(desc); + action = desc->action; if (action) { int ret = __do_irq(irq, action, regs); if (ret != IRQ_HANDLED) report_bad_irq(irq, regs, desc, ret); } + + smp_clear_running(desc); } /* @@ -350,7 +375,7 @@ do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) void do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { - const int cpu = smp_processor_id(); + const unsigned int cpu = smp_processor_id(); desc->triggered = 1; @@ -414,7 +439,7 @@ void do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { struct irqaction *action; - const int cpu = smp_processor_id(); + const unsigned int cpu = smp_processor_id(); desc->triggered = 1; @@ -426,6 +451,8 @@ do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) if (likely(!desc->disable_depth)) { kstat_cpu(cpu).irqs[irq]++; + smp_set_running(desc); + /* * Return with this interrupt masked if no action */ @@ -440,6 +467,8 @@ do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) !check_irq_lock(desc, irq, regs))) desc->chip->unmask(irq); } + + smp_clear_running(desc); } } @@ -878,8 +907,97 @@ out: EXPORT_SYMBOL(probe_irq_off); +#ifdef CONFIG_SMP +static void route_irq(struct irqdesc *desc, unsigned int irq, unsigned int cpu) +{ + pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->cpu, cpu); + + spin_lock_irq(&irq_controller_lock); + desc->cpu = cpu; + desc->chip->set_cpu(desc, irq, cpu); + spin_unlock_irq(&irq_controller_lock); +} + +#ifdef CONFIG_PROC_FS +static int +irq_affinity_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + struct irqdesc *desc = irq_desc + ((int)data); + int len = cpumask_scnprintf(page, count, desc->affinity); + + if (count - len < 2) + return -EINVAL; + page[len++] = '\n'; + page[len] = '\0'; + + return len; +} + +static int +irq_affinity_write_proc(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + unsigned int irq = (unsigned int)data; + struct irqdesc *desc = irq_desc + irq; + cpumask_t affinity, tmp; + int ret = -EIO; + + if (!desc->chip->set_cpu) + goto out; + + ret = cpumask_parse(buffer, count, affinity); + if (ret) + goto out; + + cpus_and(tmp, affinity, cpu_online_map); + if (cpus_empty(tmp)) { + ret = -EINVAL; + goto out; + } + + desc->affinity = affinity; + route_irq(desc, irq, first_cpu(tmp)); + ret = count; + + out: + return ret; +} +#endif +#endif + void __init init_irq_proc(void) { +#if defined(CONFIG_SMP) && defined(CONFIG_PROC_FS) + struct proc_dir_entry *dir; + int irq; + + dir = proc_mkdir("irq", 0); + if (!dir) + return; + + for (irq = 0; irq < NR_IRQS; irq++) { + struct proc_dir_entry *entry; + struct irqdesc *desc; + char name[16]; + + desc = irq_desc + irq; + memset(name, 0, sizeof(name)); + snprintf(name, sizeof(name) - 1, "%u", irq); + + desc->procdir = proc_mkdir(name, dir); + if (!desc->procdir) + continue; + + entry = create_proc_entry("smp_affinity", 0600, desc->procdir); + if (entry) { + entry->nlink = 1; + entry->data = (void *)irq; + entry->read_proc = irq_affinity_read_proc; + entry->write_proc = irq_affinity_write_proc; + } + } +#endif } void __init init_IRQ(void) @@ -888,6 +1006,11 @@ void __init init_IRQ(void) extern void init_dma(void); int irq; +#ifdef CONFIG_SMP + bad_irq_desc.affinity = CPU_MASK_ALL; + bad_irq_desc.cpu = smp_processor_id(); +#endif + for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) { *desc = bad_irq_desc; INIT_LIST_HEAD(&desc->pend); diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c index c232d37772ded2..02cc6793417fac 100644 --- a/arch/arm/kernel/semaphore.c +++ b/arch/arm/kernel/semaphore.c @@ -178,7 +178,7 @@ int __down_trylock(struct semaphore * sem) * registers (r0 to r3 and lr), but not ip, as we use it as a return * value in some cases.. */ -asm(" .section .sched.text \n\ +asm(" .section .sched.text,\"ax\" \n\ .align 5 \n\ .globl __down_failed \n\ __down_failed: \n\ diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 9c7874cebb43e6..9f0079305449b9 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -17,16 +17,16 @@ #include <linux/profile.h> #include <linux/errno.h> #include <linux/mm.h> +#include <linux/cpu.h> +#include <linux/smp.h> #include <linux/seq_file.h> #include <asm/atomic.h> +#include <asm/cacheflush.h> #include <asm/cpu.h> #include <asm/processor.h> -#include <asm/smp.h> -#include <asm/ptrace.h> - -#include <asm/cacheflush.h> #include <asm/tlbflush.h> +#include <asm/ptrace.h> /* * bitmask of present and online CPUs. @@ -42,6 +42,7 @@ cpumask_t cpu_online_map; */ struct ipi_data { spinlock_t lock; + unsigned long ipi_count; unsigned long bits; }; @@ -242,12 +243,12 @@ int smp_call_function(void (*func)(void *info), void *info, int retry, void show_ipi_list(struct seq_file *p) { - int cpu; + unsigned int cpu; - seq_printf(p, "IPI: "); + seq_puts(p, "IPI:"); for_each_online_cpu(cpu) - seq_printf(p, "%10lu ", per_cpu(cpu_data, cpu).ipi_count); + seq_printf(p, " %10lu", per_cpu(ipi_data, cpu).ipi_count); seq_putc(p, '\n'); } @@ -316,12 +317,11 @@ static void ipi_cpu_stop(unsigned int cpu) void do_IPI(unsigned int ipimask, struct pt_regs *regs) { unsigned int cpu = smp_processor_id(); + struct ipi_data *ipi = &per_cpu(ipi_data, cpu); - per_cpu(cpu_data, cpu).ipi_count++; + ipi->ipi_count++; if (ipimask & (1 << 0)) { - struct ipi_data *ipi = &per_cpu(ipi_data, cpu); - for (;;) { unsigned long msgs; diff --git a/arch/arm/lib/io-readsw-armv4.S b/arch/arm/lib/io-readsw-armv4.S index 28c8a351119cd0..c92b66ecbe863f 100644 --- a/arch/arm/lib/io-readsw-armv4.S +++ b/arch/arm/lib/io-readsw-armv4.S @@ -18,25 +18,14 @@ #endif .endm -.insw_bad_alignment: - adr r0, .insw_bad_align_msg - mov r2, lr - b panic -.insw_bad_align_msg: - .asciz "insw: bad buffer alignment (0x%p, lr=0x%08lX)\n" - .align - -.insw_align: tst r1, #1 - bne .insw_bad_alignment - - ldrh r3, [r0] - strh r3, [r1], #2 - - subs r2, r2, #1 - RETINSTR(moveq, pc, lr) +.insw_align: movs ip, r1, lsl #31 + bne .insw_noalign + ldrh ip, [r0] + sub r2, r2, #1 + strh ip, [r1], #2 ENTRY(__raw_readsw) - teq r2, #0 @ do we have to check for the zero len? + teq r2, #0 moveq pc, lr tst r1, #3 bne .insw_align @@ -62,14 +51,10 @@ ENTRY(__raw_readsw) ldrh lr, [r0] pack ip, ip, lr - stmia r1!, {r3 - r5, ip} - subs r2, r2, #8 + stmia r1!, {r3 - r5, ip} bpl .insw_8_lp - tst r2, #7 - LOADREGS(eqfd, sp!, {r4, r5, pc}) - .no_insw_8: tst r2, #4 beq .no_insw_4 @@ -83,17 +68,63 @@ ENTRY(__raw_readsw) stmia r1!, {r3, r4} -.no_insw_4: tst r2, #2 - beq .no_insw_2 +.no_insw_4: movs r2, r2, lsl #31 + bcc .no_insw_2 ldrh r3, [r0] ldrh ip, [r0] pack r3, r3, ip - str r3, [r1], #4 -.no_insw_2: tst r2, #1 - ldrneh r3, [r0] +.no_insw_2: ldrneh r3, [r0] strneh r3, [r1] - LOADREGS(fd, sp!, {r4, r5, pc}) + ldmfd sp!, {r4, r5, pc} + +#ifdef __ARMEB__ +#define _BE_ONLY_(code...) code +#define _LE_ONLY_(code...) +#define push_hbyte0 lsr #8 +#define pull_hbyte1 lsl #24 +#else +#define _BE_ONLY_(code...) +#define _LE_ONLY_(code...) code +#define push_hbyte0 lsl #24 +#define pull_hbyte1 lsr #8 +#endif + +.insw_noalign: stmfd sp!, {r4, lr} + ldrccb ip, [r1, #-1]! + bcc 1f + + ldrh ip, [r0] + sub r2, r2, #1 + _BE_ONLY_( mov ip, ip, ror #8 ) + strb ip, [r1], #1 + _LE_ONLY_( mov ip, ip, lsr #8 ) + _BE_ONLY_( mov ip, ip, lsr #24 ) + +1: subs r2, r2, #2 + bmi 3f + _BE_ONLY_( mov ip, ip, lsl #24 ) + +2: ldrh r3, [r0] + ldrh r4, [r0] + subs r2, r2, #2 + orr ip, ip, r3, lsl #8 + orr ip, ip, r4, push_hbyte0 + str ip, [r1], #4 + mov ip, r4, pull_hbyte1 + bpl 2b + + _BE_ONLY_( mov ip, ip, lsr #24 ) + +3: tst r2, #1 + strb ip, [r1], #1 + ldrneh ip, [r0] + _BE_ONLY_( movne ip, ip, ror #8 ) + strneb ip, [r1], #1 + _LE_ONLY_( movne ip, ip, lsr #8 ) + _BE_ONLY_( movne ip, ip, lsr #24 ) + strneb ip, [r1] + ldmfd sp!, {r4, pc} diff --git a/arch/arm/lib/io-writesw-armv4.S b/arch/arm/lib/io-writesw-armv4.S index a4a444e11ba3cf..6d1d7c27806e40 100644 --- a/arch/arm/lib/io-writesw-armv4.S +++ b/arch/arm/lib/io-writesw-armv4.S @@ -22,27 +22,17 @@ #endif .endm -.outsw_bad_alignment: - adr r0, .outsw_bad_align_msg - mov r2, lr - b panic -.outsw_bad_align_msg: - .asciz "outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n" - .align - -.outsw_align: tst r1, #1 - bne .outsw_bad_alignment +.outsw_align: movs ip, r1, lsl #31 + bne .outsw_noalign ldrh r3, [r1], #2 + sub r2, r2, #1 strh r3, [r0] - subs r2, r2, #1 - RETINSTR(moveq, pc, lr) - ENTRY(__raw_writesw) - teq r2, #0 @ do we have to check for the zero len? + teq r2, #0 moveq pc, lr - tst r1, #3 + ands r3, r1, #3 bne .outsw_align stmfd sp!, {r4, r5, lr} @@ -51,16 +41,13 @@ ENTRY(__raw_writesw) bmi .no_outsw_8 .outsw_8_lp: ldmia r1!, {r3, r4, r5, ip} + subs r2, r2, #8 outword r3 outword r4 outword r5 outword ip - subs r2, r2, #8 bpl .outsw_8_lp - tst r2, #7 - LOADREGS(eqfd, sp!, {r4, r5, pc}) - .no_outsw_8: tst r2, #4 beq .no_outsw_4 @@ -68,14 +55,41 @@ ENTRY(__raw_writesw) outword r3 outword ip -.no_outsw_4: tst r2, #2 - beq .no_outsw_2 +.no_outsw_4: movs r2, r2, lsl #31 + bcc .no_outsw_2 ldr r3, [r1], #4 outword r3 -.no_outsw_2: tst r2, #1 - ldrneh r3, [r1] +.no_outsw_2: ldrneh r3, [r1] strneh r3, [r0] - LOADREGS(fd, sp!, {r4, r5, pc}) + ldmfd sp!, {r4, r5, pc} + +#ifdef __ARMEB__ +#define pull_hbyte0 lsl #8 +#define push_hbyte1 lsr #24 +#else +#define pull_hbyte0 lsr #24 +#define push_hbyte1 lsl #8 +#endif + +.outsw_noalign: ldr r3, [r1, -r3]! + subcs r2, r2, #1 + bcs 2f + subs r2, r2, #2 + bmi 3f + +1: mov ip, r3, lsr #8 + strh ip, [r0] +2: mov ip, r3, pull_hbyte0 + ldr r3, [r1, #4]! + subs r2, r2, #2 + orr ip, ip, r3, push_hbyte1 + strh ip, [r0] + bpl 2b + +3: tst r2, #1 +2: movne ip, r3, lsr #8 + strneh ip, [r0] + mov pc, lr diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c index b46c743516a9f5..afafb42ae12951 100644 --- a/arch/arm/mach-ixp4xx/coyote-pci.c +++ b/arch/arm/mach-ixp4xx/coyote-pci.c @@ -14,6 +14,7 @@ * */ +#include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c index 651ff67a575480..1d06d364c34ed7 100644 --- a/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/arch/arm/mach-ixp4xx/coyote-setup.c @@ -8,6 +8,7 @@ * Author: Deepak Saxena <dsaxena@plexity.net> */ +#include <linux/kernel.h> #include <linux/init.h> #include <linux/device.h> #include <linux/serial.h> diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c index 2b8d2c731f1830..c2ab9ebb5980ca 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-pci.c +++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c @@ -14,6 +14,7 @@ * */ +#include <linux/kernel.h> #include <linux/config.h> #include <linux/pci.h> #include <linux/init.h> diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index 4aafd8e6e98aa8..77006d96aacfde 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -8,6 +8,7 @@ * Author: Deepak Saxena <dsaxena@plexity.net> */ +#include <linux/kernel.h> #include <linux/init.h> #include <linux/device.h> #include <linux/serial.h> diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c index 0f9043362a605a..ce4563f006766b 100644 --- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c +++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c @@ -13,6 +13,7 @@ * */ +#include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> diff --git a/arch/arm/mach-ixp4xx/prpmc1100-pci.c b/arch/arm/mach-ixp4xx/prpmc1100-pci.c index a0aed9ca38342a..9ee0ab9dac3a6c 100644 --- a/arch/arm/mach-ixp4xx/prpmc1100-pci.c +++ b/arch/arm/mach-ixp4xx/prpmc1100-pci.c @@ -19,6 +19,7 @@ * */ +#include <linux/kernel.h> #include <linux/config.h> #include <linux/pci.h> #include <linux/init.h> diff --git a/arch/arm/mach-ixp4xx/prpmc1100-setup.c b/arch/arm/mach-ixp4xx/prpmc1100-setup.c index 68f679a4152838..ed4281565bcd83 100644 --- a/arch/arm/mach-ixp4xx/prpmc1100-setup.c +++ b/arch/arm/mach-ixp4xx/prpmc1100-setup.c @@ -8,6 +8,7 @@ * Author: Deepak Saxena <dsaxena@plexity.net> */ +#include <linux/kernel.h> #include <linux/init.h> #include <linux/device.h> #include <linux/serial.h> diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 0464f512de9530..d480bd54c95d78 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_PXA27x) += pxa27x.o obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o obj-$(CONFIG_ARCH_PXA_IDP) += idp.o -obj-$(CONFIG_PXA_SHARPSL) += corgi.o +obj-$(CONFIG_PXA_SHARPSL) += corgi.o corgi_ssp.o ssp.o # Support for blinky lights led-y := leds.o diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 8173808121f77f..716643c7df2a4f 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -68,8 +68,14 @@ static struct platform_device corgiscoop_device = { .resource = corgi_scoop_resources, }; +static struct platform_device corgissp_device = { + .name = "corgi-ssp", + .id = -1, +}; + static struct platform_device *devices[] __initdata = { &corgiscoop_device, + &corgissp_device, }; static struct sharpsl_flash_param_info sharpsl_flash_param; diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c new file mode 100644 index 00000000000000..1d2a881f3b7e6b --- /dev/null +++ b/arch/arm/mach-pxa/corgi_ssp.c @@ -0,0 +1,247 @@ +/* + * SSP control code for Sharp Corgi devices + * + * Copyright (c) 2004 Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <asm/hardware.h> + +#include <asm/arch/ssp.h> +#include <asm/arch/corgi.h> +#include <asm/arch/pxa-regs.h> + +static spinlock_t corgi_ssp_lock = SPIN_LOCK_UNLOCKED; +static struct ssp_dev corgi_ssp_dev; +static struct ssp_state corgi_ssp_state; + +/* + * There are three devices connected to the SSP interface: + * 1. A touchscreen controller (TI ADS7846 compatible) + * 2. An LCD contoller (with some Backlight functionality) + * 3. A battery moinitoring IC (Maxim MAX1111) + * + * Each device uses a different speed/mode of communication. + * + * The touchscreen is very sensitive and the most frequently used + * so the port is left configured for this. + * + * Devices are selected using Chip Selects on GPIOs. + */ + +/* + * ADS7846 Routines + */ +unsigned long corgi_ssp_ads7846_putget(ulong data) +{ + unsigned long ret,flag; + + spin_lock_irqsave(&corgi_ssp_lock, flag); + GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); + + ssp_write_word(&corgi_ssp_dev,data); + ret = ssp_read_word(&corgi_ssp_dev); + + GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); + spin_unlock_irqrestore(&corgi_ssp_lock, flag); + + return ret; +} + +/* + * NOTE: These functions should always be called in interrupt context + * and use the _lock and _unlock functions. They are very time sensitive. + */ +void corgi_ssp_ads7846_lock(void) +{ + spin_lock(&corgi_ssp_lock); + GPCR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); +} + +void corgi_ssp_ads7846_unlock(void) +{ + GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); + spin_unlock(&corgi_ssp_lock); +} + +void corgi_ssp_ads7846_put(ulong data) +{ + ssp_write_word(&corgi_ssp_dev,data); +} + +unsigned long corgi_ssp_ads7846_get(void) +{ + return ssp_read_word(&corgi_ssp_dev); +} + +EXPORT_SYMBOL(corgi_ssp_ads7846_putget); +EXPORT_SYMBOL(corgi_ssp_ads7846_lock); +EXPORT_SYMBOL(corgi_ssp_ads7846_unlock); +EXPORT_SYMBOL(corgi_ssp_ads7846_put); +EXPORT_SYMBOL(corgi_ssp_ads7846_get); + + +/* + * LCD/Backlight Routines + */ +unsigned long corgi_ssp_dac_put(ulong data) +{ + unsigned long flag; + + spin_lock_irqsave(&corgi_ssp_lock, flag); + GPCR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); + + ssp_disable(&corgi_ssp_dev); + ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), SSCR1_SPH, 0, SSCR0_SerClkDiv(76)); + ssp_enable(&corgi_ssp_dev); + + ssp_write_word(&corgi_ssp_dev,data); + /* Read null data back from device to prevent SSP overflow */ + ssp_read_word(&corgi_ssp_dev); + + ssp_disable(&corgi_ssp_dev); + ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2)); + ssp_enable(&corgi_ssp_dev); + GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); + spin_unlock_irqrestore(&corgi_ssp_lock, flag); + + return 0; +} + +void corgi_ssp_lcdtg_send(u8 adrs, u8 data) +{ + corgi_ssp_dac_put(((adrs & 0x07) << 5) | (data & 0x1f)); +} + +void corgi_ssp_blduty_set(int duty) +{ + corgi_ssp_lcdtg_send(0x02,duty); +} + +EXPORT_SYMBOL(corgi_ssp_lcdtg_send); +EXPORT_SYMBOL(corgi_ssp_blduty_set); + +/* + * Max1111 Routines + */ +int corgi_ssp_max1111_get(ulong data) +{ + unsigned long flag; + int voltage,voltage1,voltage2; + + spin_lock_irqsave(&corgi_ssp_lock, flag); + GPCR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); + ssp_disable(&corgi_ssp_dev); + ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(8)); + ssp_enable(&corgi_ssp_dev); + + udelay(1); + + /* TB1/RB1 */ + ssp_write_word(&corgi_ssp_dev,data); + ssp_read_word(&corgi_ssp_dev); /* null read */ + + /* TB12/RB2 */ + ssp_write_word(&corgi_ssp_dev,0); + voltage1=ssp_read_word(&corgi_ssp_dev); + + /* TB13/RB3*/ + ssp_write_word(&corgi_ssp_dev,0); + voltage2=ssp_read_word(&corgi_ssp_dev); + + ssp_disable(&corgi_ssp_dev); + ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2)); + ssp_enable(&corgi_ssp_dev); + GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); + spin_unlock_irqrestore(&corgi_ssp_lock, flag); + + if (voltage1 & 0xc0 || voltage2 & 0x3f) + voltage = -1; + else + voltage = ((voltage1 << 2) & 0xfc) | ((voltage2 >> 6) & 0x03); + + return voltage; +} + +EXPORT_SYMBOL(corgi_ssp_max1111_get); + +/* + * Support Routines + */ +int __init corgi_ssp_probe(struct device *dev) +{ + int ret; + + /* Chip Select - Disable All */ + GPDR0 |= GPIO_bit(CORGI_GPIO_LCDCON_CS); /* output */ + GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */ + GPDR0 |= GPIO_bit(CORGI_GPIO_MAX1111_CS); /* output */ + GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/ + GPDR0 |= GPIO_bit(CORGI_GPIO_ADS7846_CS); /* output */ + GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/ + + ret=ssp_init(&corgi_ssp_dev,1); + + if (ret) + printk(KERN_ERR "Unable to register SSP handler!\n"); + else { + ssp_disable(&corgi_ssp_dev); + ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(2)); + ssp_enable(&corgi_ssp_dev); + } + + return ret; +} + +static int corgi_ssp_remove(struct device *dev) +{ + ssp_exit(&corgi_ssp_dev); + return 0; +} + +static int corgi_ssp_suspend(struct device *dev, u32 state, u32 level) +{ + if (level == SUSPEND_POWER_DOWN) { + ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state); + } + return 0; +} + +static int corgi_ssp_resume(struct device *dev, u32 level) +{ + if (level == RESUME_POWER_ON) { + GPSR0 = GPIO_bit(CORGI_GPIO_LCDCON_CS); /* High - Disable LCD Control/Timing Gen */ + GPSR0 = GPIO_bit(CORGI_GPIO_MAX1111_CS); /* High - Disable MAX1111*/ + GPSR0 = GPIO_bit(CORGI_GPIO_ADS7846_CS); /* High - Disable ADS7846*/ + ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state); + ssp_enable(&corgi_ssp_dev); + } + return 0; +} + +static struct device_driver corgissp_driver = { + .name = "corgi-ssp", + .bus = &platform_bus_type, + .probe = corgi_ssp_probe, + .remove = corgi_ssp_remove, + .suspend = corgi_ssp_suspend, + .resume = corgi_ssp_resume, +}; + +int __init corgi_ssp_init(void) +{ + return driver_register(&corgissp_driver); +} + +arch_initcall(corgi_ssp_init); diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h index 7c90dab27098a0..d7b2c61d11c674 100644 --- a/arch/arm/mach-s3c2410/cpu.h +++ b/arch/arm/mach-s3c2410/cpu.h @@ -13,6 +13,7 @@ * 24-Aug-2004 BJD Start of generic S3C24XX support * 18-Oct-2004 BJD Moved board struct into this file * 04-Jan-2005 BJD New uart initialisation + * 10-Jan-2005 BJD Moved generic init here, specific to cpu headers */ #define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE } @@ -26,25 +27,9 @@ /* forward declaration */ struct s3c2410_uartcfg; -#ifdef CONFIG_CPU_S3C2410 -extern int s3c2410_init(void); -extern void s3c2410_map_io(struct map_desc *mach_desc, int size); -extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no); -#else -#define s3c2410_init_uarts NULL -#define s3c2410_map_io NULL -#define s3c2410_init NULL -#endif +/* core initialisation functions */ -#ifdef CONFIG_CPU_S3C2440 -extern int s3c2440_init(void); -extern void s3c2440_map_io(struct map_desc *mach_desc, int size); -extern void s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no); -#else -#define s3c2440_init_uarts NULL -#define s3c2440_map_io NULL -#define s3c2440_init NULL -#endif +extern void s3c24xx_init_irq(void); extern void s3c24xx_init_io(struct map_desc *mach_desc, int size); @@ -65,3 +50,8 @@ struct s3c24xx_board { }; extern void s3c24xx_set_board(struct s3c24xx_board *board); + +/* timer for 2410/2440 */ + +struct sys_timer; +extern struct sys_timer s3c24xx_timer; diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c index a8a48f743047d2..6b0b93e5aa4157 100644 --- a/arch/arm/mach-s3c2410/irq.c +++ b/arch/arm/mach-s3c2410/irq.c @@ -628,12 +628,12 @@ s3c_irq_demux_uart2(unsigned int irq, s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs); } -/* s3c2410_init_irq +/* s3c24xx_init_irq * * Initialise S3C2410 IRQ system */ -void __init s3c2410_init_irq(void) +void __init s3c24xx_init_irq(void) { unsigned long pend; unsigned long last; diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 3126b641248d16..a6c05555445f5e 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -20,7 +20,8 @@ * 18-Jan-2003 BJD Added serial port configuration * 05-Oct-2004 BJD Power management code * 04-Nov-2004 BJD Updated serial port clocks - * 04-Jan-2004 BJD New uart init call + * 04-Jan-2006 BJD New uart init call + * 10-Jan-2005 BJD Removed include of s3c2410.h */ #include <linux/kernel.h> @@ -48,7 +49,6 @@ #include <asm/arch/regs-gpio.h> #include <asm/arch/regs-mem.h> -#include "s3c2410.h" #include "clock.h" #include "devs.h" #include "cpu.h" @@ -270,7 +270,7 @@ void __init bast_map_io(void) void __init bast_init_irq(void) { - s3c2410_init_irq(); + s3c24xx_init_irq(); } #ifdef CONFIG_PM @@ -307,5 +307,5 @@ MACHINE_START(BAST, "Simtec-BAST") MAPIO(bast_map_io) INITIRQ(bast_init_irq) .init_machine = bast_init_machine, - .timer = &s3c2410_timer, + .timer = &s3c24xx_timer, MACHINE_END diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index ae200e86833bbf..9044d287e03a03 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -21,6 +21,7 @@ * 18-Oct-2004 BJD Updated new board structure name * 04-Nov-2004 BJD Change for new serial clock * 04-Jan-2005 BJD Updated uart init call + * 10-Jan-2005 BJD Removed include of s3c2410.h */ #include <linux/kernel.h> @@ -45,7 +46,6 @@ #include <linux/serial_core.h> -#include "s3c2410.h" #include "clock.h" #include "devs.h" #include "cpu.h" @@ -109,7 +109,7 @@ void __init h1940_map_io(void) void __init h1940_init_irq(void) { - s3c2410_init_irq(); + s3c24xx_init_irq(); } @@ -119,5 +119,5 @@ MACHINE_START(H1940, "IPAQ-H1940") BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) MAPIO(h1940_map_io) INITIRQ(h1940_init_irq) - .timer = &s3c2410_timer, + .timer = &s3c24xx_timer, MACHINE_END diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c index 763aeaf6be44a1..38241c908bbd9c 100644 --- a/arch/arm/mach-s3c2410/mach-rx3715.c +++ b/arch/arm/mach-s3c2410/mach-rx3715.c @@ -12,6 +12,7 @@ * Modifications: * 16-Sep-2004 BJD Copied from mach-h1940.c * 25-Oct-2004 BJD Updates for 2.6.10-rc1 + * 10-Jan-2005 BJD Removed include of s3c2410.h s3c2440.h */ #include <linux/kernel.h> @@ -38,8 +39,6 @@ #include <asm/arch/regs-serial.h> #include <asm/arch/regs-gpio.h> -#include "s3c2410.h" -#include "s3c2440.h" #include "clock.h" #include "devs.h" #include "cpu.h" @@ -101,7 +100,7 @@ void __init rx3715_map_io(void) void __init rx3715_init_irq(void) { - s3c2410_init_irq(); + s3c24xx_init_irq(); } #ifdef CONFIG_PM @@ -120,5 +119,5 @@ MACHINE_START(RX3715, "IPAQ-RX3715") MAPIO(rx3715_map_io) INITIRQ(rx3715_init_irq) INIT_MACHINE(rx3715_init_machine) - .timer = &s3c2410_timer, + .timer = &s3c24xx_timer, MACHINE_END diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c index 16f9d59cd65ba8..ac95647362f674 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2410.c +++ b/arch/arm/mach-s3c2410/mach-smdk2410.c @@ -46,7 +46,6 @@ #include <asm/arch/regs-serial.h> -#include "s3c2410.h" #include "devs.h" #include "cpu.h" @@ -104,7 +103,7 @@ void __init smdk2410_map_io(void) void __init smdk2410_init_irq(void) { - s3c2410_init_irq(); + s3c24xx_init_irq(); } MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch @@ -114,7 +113,7 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) MAPIO(smdk2410_map_io) INITIRQ(smdk2410_init_irq) - .timer = &s3c2410_timer, + .timer = &s3c24xx_timer, MACHINE_END diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index 2804fe5a0be5c9..47108f13f652a5 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -18,7 +18,8 @@ * 05-Apr-2004 BJD Copied to make mach-vr1000.c * 18-Oct-2004 BJD Updated board struct * 04-Nov-2004 BJD Clock and serial configuration update - * 04-Jan-2004 BJD Updated uart init call + * 04-Jan-2005 BJD Updated uart init call + * 10-Jan-2005 BJD Removed include of s3c2410.h */ #include <linux/kernel.h> @@ -43,7 +44,6 @@ //#include <asm/debug-ll.h> #include <asm/arch/regs-serial.h> -#include "s3c2410.h" #include "clock.h" #include "devs.h" #include "cpu.h" @@ -212,7 +212,7 @@ void __init vr1000_map_io(void) void __init vr1000_init_irq(void) { - s3c2410_init_irq(); + s3c24xx_init_irq(); } MACHINE_START(VR1000, "Thorcom-VR1000") @@ -221,5 +221,5 @@ MACHINE_START(VR1000, "Thorcom-VR1000") BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100) MAPIO(vr1000_map_io) INITIRQ(vr1000_init_irq) - .timer = &s3c2410_timer, + .timer = &s3c24xx_timer, MACHINE_END diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h index d13c300a7de427..93f7a27e3cb80c 100644 --- a/arch/arm/mach-s3c2410/s3c2410.h +++ b/arch/arm/mach-s3c2410/s3c2410.h @@ -1,7 +1,7 @@ /* arch/arm/mach-s3c2410/s3c2410.h * * Copyright (c) 2004 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> + * Ben Dooks <ben@simtec.co.uk> * * Header file for s3c2410 machine directory * @@ -15,13 +15,19 @@ * 04-Sep-2004 BJD Added s3c2410_init_uarts() call * 17-Oct-2004 BJD Moved board out to cpu * 04-Jan-2005 BJD Changed uart init + * 10-Jan-2005 BJD Removed timer to cpu.h, moved 2410 specific bits here */ -extern void s3c2410_map_io(struct map_desc *, int count); +#ifdef CONFIG_CPU_S3C2410 -extern void s3c2410_init_irq(void); +extern int s3c2410_init(void); -struct sys_timer; -extern struct sys_timer s3c2410_timer; +extern void s3c2410_map_io(struct map_desc *mach_desc, int size); +extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no); +#else +#define s3c2410_init_uarts NULL +#define s3c2410_map_io NULL +#define s3c2410_init NULL +#endif diff --git a/arch/arm/mach-s3c2410/s3c2440-dsc.c b/arch/arm/mach-s3c2410/s3c2440-dsc.c index bc11fbfb25265a..50ccc673ff0530 100644 --- a/arch/arm/mach-s3c2410/s3c2440-dsc.c +++ b/arch/arm/mach-s3c2410/s3c2440-dsc.c @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2410/s3c2440-dsc.c * - * Copyright (c) 2004 Simtec Electronics + * Copyright (c) 2004-2005 Simtec Electronics * Ben Dooks <ben@simtec.co.uk> * * Samsung S3C2440 Drive Strength Control support @@ -12,6 +12,7 @@ * Modifications: * 29-Aug-2004 BJD Start of drive-strength control * 09-Nov-2004 BJD Added symbol export + * 11-Jan-2005 BJD Include fix */ #include <linux/kernel.h> @@ -31,8 +32,8 @@ #include <asm/arch/regs-gpio.h> #include <asm/arch/regs-dsc.h> -#include "s3c2440.h" #include "cpu.h" +#include "s3c2440.h" int s3c2440_set_dsc(unsigned int pin, unsigned int value) { diff --git a/arch/arm/mach-s3c2410/s3c2440.h b/arch/arm/mach-s3c2410/s3c2440.h index 4eb19a8797633e..760cee377c8892 100644 --- a/arch/arm/mach-s3c2410/s3c2440.h +++ b/arch/arm/mach-s3c2410/s3c2440.h @@ -1,7 +1,7 @@ /* arch/arm/mach-s3c2410/s3c2440.h * - * Copyright (c) 2004 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> + * Copyright (c) 2004-2005 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> * * Header file for s3c2440 cpu support * @@ -12,9 +12,20 @@ * Modifications: * 24-Aug-2004 BJD Start of S3C2440 CPU support * 04-Nov-2004 BJD Added s3c2440_init_uarts() - * 04-Jan-2004 BJD Moved uart init to cpu code + * 04-Jan-2005 BJD Moved uart init to cpu code + * 10-Jan-2005 BJD Moved 2440 specific init here */ -extern void s3c2440_init_irq(void); +#ifdef CONFIG_CPU_S3C2440 -extern void s3c2440_init_time(void); +extern int s3c2440_init(void); + +extern void s3c2440_map_io(struct map_desc *mach_desc, int size); + +extern void s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no); + +#else +#define s3c2440_init_uarts NULL +#define s3c2440_map_io NULL +#define s3c2440_init NULL +#endif diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c index ccd16044354e84..715d65a40341b2 100644 --- a/arch/arm/mach-s3c2410/time.c +++ b/arch/arm/mach-s3c2410/time.c @@ -232,7 +232,7 @@ static void __init s3c2410_timer_init (void) setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); } -struct sys_timer s3c2410_timer = { +struct sys_timer s3c24xx_timer = { .init = s3c2410_timer_init, .offset = s3c2410_gettimeoffset, .resume = s3c2410_timer_setup |