diff options
61 files changed, 1431 insertions, 692 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4b1a8e3d292..9d8b7f9bca1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -33,6 +33,11 @@ config GENERIC_CLOCKEVENTS bool default n +config GENERIC_CLOCKEVENTS_BROADCAST + bool + depends on GENERIC_CLOCKEVENTS + default y if SMP && !LOCAL_TIMERS + config MMU bool default y @@ -168,6 +173,8 @@ config ARCH_REALVIEW bool "ARM Ltd. RealView family" select ARM_AMBA select ICST307 + select GENERIC_TIME + select GENERIC_CLOCKEVENTS help This enables support for ARM Ltd RealView boards. @@ -604,7 +611,7 @@ source "kernel/time/Kconfig" config SMP bool "Symmetric Multi-Processing (EXPERIMENTAL)" - depends on EXPERIMENTAL && REALVIEW_MPCORE + depends on EXPERIMENTAL && REALVIEW_EB_ARM11MP help This enables support for systems with more than one CPU. If you have a system with only one CPU, like most personal computers, say N. If @@ -638,7 +645,7 @@ config HOTPLUG_CPU config LOCAL_TIMERS bool "Use local timer interrupts" - depends on SMP && REALVIEW_MPCORE + depends on SMP && REALVIEW_EB_ARM11MP default y help Enable support for local timers on SMP platforms, rather then the @@ -894,6 +901,13 @@ config KEXEC initially work for you. It may help to enable device hotplugging support. +config ATAGS_PROC + bool "Export atags in procfs" + default n + help + Should the atags used to boot the kernel be exported in an "atags" + file in procfs. Useful with kexec. + endmenu if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX || ARCH_PXA) diff --git a/arch/arm/common/time-acorn.c b/arch/arm/common/time-acorn.c index 34038eccbba..d544da41473 100644 --- a/arch/arm/common/time-acorn.c +++ b/arch/arm/common/time-acorn.c @@ -69,9 +69,7 @@ void __init ioctime_init(void) static irqreturn_t ioc_timer_interrupt(int irq, void *dev_id) { - write_seqlock(&xtime_lock); timer_tick(); - write_sequnlock(&xtime_lock); return IRQ_HANDLED; } diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index faa76192115..00d44c6fbfe 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_PCI) += bios32.o isa.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o obj-$(CONFIG_KPROBES) += kprobes.o kprobes-decode.o +obj-$(CONFIG_ATAGS_PROC) += atags.o obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c new file mode 100644 index 00000000000..e2e934c3808 --- /dev/null +++ b/arch/arm/kernel/atags.c @@ -0,0 +1,86 @@ +#include <linux/slab.h> +#include <linux/kexec.h> +#include <linux/proc_fs.h> +#include <asm/setup.h> +#include <asm/types.h> +#include <asm/page.h> + +struct buffer { + size_t size; + char *data; +}; +static struct buffer tags_buffer; + +static int +read_buffer(char* page, char** start, off_t off, int count, + int* eof, void* data) +{ + struct buffer *buffer = (struct buffer *)data; + + if (off >= buffer->size) { + *eof = 1; + return 0; + } + + count = min((int) (buffer->size - off), count); + + memcpy(page, &buffer->data[off], count); + + return count; +} + + +static int +create_proc_entries(void) +{ + struct proc_dir_entry* tags_entry; + + tags_entry = create_proc_read_entry("atags", 0400, &proc_root, read_buffer, &tags_buffer); + if (!tags_entry) + return -ENOMEM; + + return 0; +} + + +static char __initdata atags_copy_buf[KEXEC_BOOT_PARAMS_SIZE]; +static char __initdata *atags_copy; + +void __init save_atags(const struct tag *tags) +{ + atags_copy = atags_copy_buf; + memcpy(atags_copy, tags, KEXEC_BOOT_PARAMS_SIZE); +} + + +static int __init init_atags_procfs(void) +{ + struct tag *tag; + int error; + + if (!atags_copy) { + printk(KERN_WARNING "Exporting ATAGs: No saved tags found\n"); + return -EIO; + } + + for (tag = (struct tag *) atags_copy; tag->hdr.size; tag = tag_next(tag)) + ; + + tags_buffer.size = ((char *) tag - atags_copy) + sizeof(tag->hdr); + tags_buffer.data = kmalloc(tags_buffer.size, GFP_KERNEL); + if (tags_buffer.data == NULL) + return -ENOMEM; + memcpy(tags_buffer.data, atags_copy, tags_buffer.size); + + error = create_proc_entries(); + if (error) { + printk(KERN_ERR "Exporting ATAGs: not enough memory\n"); + kfree(tags_buffer.data); + tags_buffer.size = 0; + tags_buffer.data = NULL; + } + + return error; +} + +arch_initcall(init_atags_procfs); diff --git a/arch/arm/kernel/atags.h b/arch/arm/kernel/atags.h new file mode 100644 index 00000000000..e5f028d214a --- /dev/null +++ b/arch/arm/kernel/atags.h @@ -0,0 +1,5 @@ +#ifdef CONFIG_ATAGS_PROC +extern void save_atags(struct tag *tags); +#else +static inline void save_atags(struct tag *tags) { } +#endif diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 863c66454f2..db8f54a3451 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -21,6 +21,7 @@ extern void setup_mm_for_reboot(char mode); extern unsigned long kexec_start_address; extern unsigned long kexec_indirection_page; extern unsigned long kexec_mach_type; +extern unsigned long kexec_boot_atags; /* * Provide a dummy crash_notes definition while crash dump arrives to arm. @@ -62,6 +63,7 @@ void machine_kexec(struct kimage *image) kexec_start_address = image->start; kexec_indirection_page = page_list; kexec_mach_type = machine_arch_type; + kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; /* copy our kernel relocation code to the control code page */ memcpy(reboot_code_buffer, diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S index 062c111c572..61930eb0902 100644 --- a/arch/arm/kernel/relocate_kernel.S +++ b/arch/arm/kernel/relocate_kernel.S @@ -7,23 +7,6 @@ .globl relocate_new_kernel relocate_new_kernel: - /* Move boot params back to where the kernel expects them */ - - ldr r0,kexec_boot_params_address - teq r0,#0 - beq 8f - - ldr r1,kexec_boot_params_copy - mov r6,#KEXEC_BOOT_PARAMS_SIZE/4 -7: - ldr r5,[r1],#4 - str r5,[r0],#4 - subs r6,r6,#1 - bne 7b - -8: - /* Boot params moved, now go on with the kernel */ - ldr r0,kexec_indirection_page ldr r1,kexec_start_address @@ -67,7 +50,7 @@ relocate_new_kernel: mov lr,r1 mov r0,#0 ldr r1,kexec_mach_type - ldr r2,kexec_boot_params_address + ldr r2,kexec_boot_atags mov pc,lr .globl kexec_start_address @@ -82,14 +65,9 @@ kexec_indirection_page: kexec_mach_type: .long 0x0 - /* phy addr where new kernel will expect to find boot params */ - .globl kexec_boot_params_address -kexec_boot_params_address: - .long 0x0 - - /* phy addr where old kernel put a copy of orig boot params */ - .globl kexec_boot_params_copy -kexec_boot_params_copy: + /* phy addr of the atags for the new kernel */ + .globl kexec_boot_atags +kexec_boot_atags: .long 0x0 relocate_new_kernel_end: diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index dd37901f786..d3941a7b045 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -24,7 +24,6 @@ #include <linux/interrupt.h> #include <linux/smp.h> #include <linux/fs.h> -#include <linux/kexec.h> #include <asm/cpu.h> #include <asm/elf.h> @@ -39,6 +38,7 @@ #include <asm/mach/time.h> #include "compat.h" +#include "atags.h" #ifndef MEM_SIZE #define MEM_SIZE (16*1024*1024) @@ -785,23 +785,6 @@ static int __init customize_machine(void) } arch_initcall(customize_machine); -#ifdef CONFIG_KEXEC - -/* Physical addr of where the boot params should be for this machine */ -extern unsigned long kexec_boot_params_address; - -/* Physical addr of the buffer into which the boot params are copied */ -extern unsigned long kexec_boot_params_copy; - -/* Pointer to the boot params buffer, for manipulation and display */ -unsigned long kexec_boot_params; -EXPORT_SYMBOL(kexec_boot_params); - -/* The buffer itself - make sure it is sized correctly */ -static unsigned long kexec_boot_params_buf[(KEXEC_BOOT_PARAMS_SIZE + 3) / 4]; - -#endif - void __init setup_arch(char **cmdline_p) { struct tag *tags = (struct tag *)&init_tags; @@ -820,18 +803,6 @@ void __init setup_arch(char **cmdline_p) else if (mdesc->boot_params) tags = phys_to_virt(mdesc->boot_params); -#ifdef CONFIG_KEXEC - kexec_boot_params_copy = virt_to_phys(kexec_boot_params_buf); - kexec_boot_params = (unsigned long)kexec_boot_params_buf; - if (__atags_pointer) { - kexec_boot_params_address = __atags_pointer; - memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE); - } else if (mdesc->boot_params) { - kexec_boot_params_address = mdesc->boot_params; - memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE); - } -#endif - /* * If we have the old style parameters, convert them to * a tag list. @@ -847,6 +818,7 @@ void __init setup_arch(char **cmdline_p) if (tags->hdr.tag == ATAG_CORE) { if (meminfo.nr_banks != 0) squash_mem_tags(tags); + save_atags(tags); parse_tags(tags); } diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index eafbb2b05eb..e9dfbab46cb 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -290,6 +290,11 @@ asmlinkage void __cpuinit secondary_start_kernel(void) local_irq_enable(); local_fiq_enable(); + /* + * Setup local timer for this CPU. + */ + local_timer_setup(cpu); + calibrate_delay(); smp_store_cpu_info(cpu); @@ -300,11 +305,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void) cpu_set(cpu, cpu_online_map); /* - * Setup local timer for this CPU. - */ - local_timer_setup(cpu); - - /* * OK, it's off to the idle thread for us */ cpu_idle(); @@ -454,6 +454,27 @@ int smp_call_function(void (*func)(void *info), void *info, int retry, } EXPORT_SYMBOL_GPL(smp_call_function); +int smp_call_function_single(int cpu, void (*func)(void *info), void *info, + int retry, int wait) +{ + /* prevent preemption and reschedule on another processor */ + int current_cpu = get_cpu(); + int ret = 0; + + if (cpu == current_cpu) { + local_irq_disable(); + func(info); + local_irq_enable(); + } else + ret = smp_call_function_on_cpu(func, info, retry, wait, + cpumask_of_cpu(cpu)); + + put_cpu(); + + return ret; +} +EXPORT_SYMBOL_GPL(smp_call_function_single); + void show_ipi_list(struct seq_file *p) { unsigned int cpu; @@ -481,8 +502,7 @@ void show_local_irqs(struct seq_file *p) static void ipi_timer(void) { irq_enter(); - profile_tick(CPU_PROFILING); - update_process_times(user_mode(get_irq_regs())); + local_timer_interrupt(); irq_exit(); } @@ -621,6 +641,11 @@ void smp_send_timer(void) send_ipi_message(mask, IPI_TIMER); } +void smp_timer_broadcast(cpumask_t mask) +{ + send_ipi_message(mask, IPI_TIMER); +} + void smp_send_stop(void) { cpumask_t mask = cpu_online_map; diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 5b0422cdde7..074dcd5d9a7 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -253,6 +253,36 @@ config AT91_TIMER_HZ system clock (of at least several MHz), rounding is less of a problem so it can be safer to use a decimal values like 100. +choice + prompt "Select a UART for early kernel messages" + +config AT91_EARLY_DBGU + bool "DBGU" + +config AT91_EARLY_USART0 + bool "USART0" + +config AT91_EARLY_USART1 + bool "USART1" + +config AT91_EARLY_USART2 + bool "USART2" + depends on ! ARCH_AT91X40 + +config AT91_EARLY_USART3 + bool "USART3" + depends on (ARCH_AT91RM9200 || ARCH_AT91SAM9RL || ARCH_AT91SAM9260) + +config AT91_EARLY_USART4 + bool "USART4" + depends on ARCH_AT91SAM9260 + +config AT91_EARLY_USART5 + bool "USART5" + depends on ARCH_AT91SAM9260 + +endchoice + endmenu endif diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c index 5c090c9442f..e38d2377099 100644 --- a/arch/arm/mach-at91/at91sam926x_time.c +++ b/arch/arm/mach-at91/at91sam926x_time.c @@ -49,8 +49,6 @@ static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id) volatile long nr_ticks; if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) { /* This is a shared interrupt */ - write_seqlock(&xtime_lock); - /* Get number to ticks performed before interrupt and clear PIT interrupt */ nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR)); do { @@ -58,7 +56,6 @@ static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id) nr_ticks--; } while (nr_ticks); - write_sequnlock(&xtime_lock); return IRQ_HANDLED; } else return IRQ_NONE; /* not handled */ diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index b5daf7f5e01..7b9ce7a336b 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -47,6 +47,9 @@ extern void at91_irq_resume(void); #define AT91RM9200_BGA 4 /* AT91RM9200 BGA package has 4 banks */ struct at91_gpio_bank { + unsigned chipbase; /* bank's first GPIO number */ + void __iomem *regbase; /* base of register bank */ + struct at91_gpio_bank *next; /* bank sharing same IRQ/clock/... */ unsigned short id; /* peripheral ID */ unsigned long offset; /* offset from system peripheral base */ struct clk *clock; /* associated clock */ diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c index 6aeddd68d8a..f629c2b5f0c 100644 --- a/arch/arm/mach-at91/gpio.c +++ b/arch/arm/mach-at91/gpio.c @@ -33,12 +33,10 @@ static int gpio_banks; static inline void __iomem *pin_to_controller(unsigned pin) { - void __iomem *sys_base = (void __iomem *) AT91_VA_BASE_SYS; - pin -= PIN_BASE; pin /= 32; if (likely(pin < gpio_banks)) - return sys_base + gpio[pin].offset; + return gpio[pin].regbase; return NULL; } @@ -294,11 +292,11 @@ void at91_gpio_suspend(void) int i; for (i = 0; i < gpio_banks; i++) { - u32 pio = gpio[i].offset; + void __iomem *pio = gpio[i].regbase; - backups[i] = at91_sys_read(pio + PIO_IMR); - at91_sys_write(pio + PIO_IDR, backups[i]); - at91_sys_write(pio + PIO_IER, wakeups[i]); + backups[i] = __raw_readl(pio + PIO_IMR); + __raw_writel(backups[i], pio + PIO_IDR); + __raw_writel(wakeups[i], pio + PIO_IER); if (!wakeups[i]) clk_disable(gpio[i].clock); @@ -315,13 +313,13 @@ void at91_gpio_resume(void) int i; for (i = 0; i < gpio_banks; i++) { - u32 pio = gpio[i].offset; + void __iomem *pio = gpio[i].regbase; if (!wakeups[i]) clk_enable(gpio[i].clock); - at91_sys_write(pio + PIO_IDR, wakeups[i]); - at91_sys_write(pio + PIO_IER, backups[i]); + __raw_writel(wakeups[i], pio + PIO_IDR); + __raw_writel(backups[i], pio + PIO_IER); } } @@ -361,7 +359,13 @@ static void gpio_irq_unmask(unsigned pin) static int gpio_irq_type(unsigned pin, unsigned type) { - return (type == IRQT_BOTHEDGE) ? 0 : -EINVAL; + switch (type) { + case IRQ_TYPE_NONE: + case IRQ_TYPE_EDGE_BOTH: + return 0; + default: + return -EINVAL; + } } static struct irq_chip gpio_irqchip = { @@ -376,20 +380,30 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) { unsigned pin; struct irq_desc *gpio; + struct at91_gpio_bank *bank; void __iomem *pio; u32 isr; - pio = get_irq_chip_data(irq); + bank = get_irq_chip_data(irq); + pio = bank->regbase; /* temporarily mask (level sensitive) parent IRQ */ desc->chip->ack(irq); for (;;) { - /* reading ISR acks the pending (edge triggered) GPIO interrupt */ + /* Reading ISR acks pending (edge triggered) GPIO interrupts. + * When there none are pending, we're finished unless we need + * to process multiple banks (like ID_PIOCDE on sam9263). + */ isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR); - if (!isr) - break; + if (!isr) { + if (!bank->next) + break; + bank = bank->next; + pio = bank->regbase; + continue; + } - pin = (unsigned) get_irq_data(irq); + pin = bank->chipbase; gpio = &irq_desc[pin]; while (isr) { @@ -481,24 +495,21 @@ postcore_initcall(at91_gpio_debugfs_init); */ void __init at91_gpio_irq_setup(void) { - unsigned pioc, pin; + unsigned pioc, pin; + struct at91_gpio_bank *this, *prev; - for (pioc = 0, pin = PIN_BASE; - pioc < gpio_banks; - pioc++) { - void __iomem *controller; - unsigned id = gpio[pioc].id; + for (pioc = 0, pin = PIN_BASE, this = gpio, prev = NULL; + pioc++ < gpio_banks; + prev = this, this++) { + unsigned id = this->id; unsigned i; - clk_enable(gpio[pioc].clock); /* enable PIO controller's clock */ - - controller = (void __iomem *) AT91_VA_BASE_SYS + gpio[pioc].offset; - __raw_writel(~0, controller + PIO_IDR); + /* enable PIO controller's clock */ + clk_enable(this->clock); - set_irq_data(id, (void *) pin); - set_irq_chip_data(id, controller); + __raw_writel(~0, this->regbase + PIO_IDR); - for (i = 0; i < 32; i++, pin++) { + for (i = 0, pin = this->chipbase; i < 32; i++, pin++) { /* * Can use the "simple" and not "edge" handler since it's * shorter, and the AIC handles interrupts sanely. @@ -508,6 +519,14 @@ void __init at91_gpio_irq_setup(void) set_irq_flags(pin, IRQF_VALID); } + /* The toplevel handler handles one bank of GPIOs, except + * AT91SAM9263_ID_PIOCDE handles three... PIOC is first in + * the list, so we only set up that handler. + */ + if (prev && prev->next == this) + continue; + + set_irq_chip_data(id, this); set_irq_chained_handler(id, gpio_irq_handler); } pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, gpio_banks); @@ -518,8 +537,20 @@ void __init at91_gpio_irq_setup(void) */ void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks) { + unsigned i; + struct at91_gpio_bank *last; + BUG_ON(nr_banks > MAX_GPIO_BANKS); gpio = data; gpio_banks = nr_banks; + + for (i = 0, last = NULL; i < nr_banks; i++, last = data, data++) { + data->chipbase = PIN_BASE + i * 32; + data->regbase = data->offset + (void __iomem *)AT91_VA_BASE_SYS; + + /* AT91SAM9263_ID_PIOCDE groups PIOC, PIOD, PIOE */ + if (last && last->id == data->id) + last->next = data; + } } diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index b5c916c0747..8604938bd94 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -6,7 +6,7 @@ obj-y += clock.o devices.o generic.o irq.o dma.o time.o obj-$(CONFIG_PXA25x) += pxa25x.o obj-$(CONFIG_PXA27x) += pxa27x.o -obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o +obj-$(CONFIG_PXA3xx) += pxa3xx.o mfp.o smemc.o obj-$(CONFIG_CPU_PXA300) += pxa300.o obj-$(CONFIG_CPU_PXA320) += pxa320.o diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c index 28cfd71c032..6012177a29a 100644 --- a/arch/arm/mach-pxa/cm-x270.c +++ b/arch/arm/mach-pxa/cm-x270.c @@ -29,6 +29,7 @@ #include <asm/mach/map.h> #include <asm/arch/pxa-regs.h> +#include <asm/arch/pxa2xx-regs.h> #include <asm/arch/pxafb.h> #include <asm/arch/ohci.h> #include <asm/arch/mmc.h> diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index 50ff453ad37..bfccb80ac8e 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -10,6 +10,7 @@ #include <asm/arch/mmc.h> #include <asm/arch/irda.h> #include <asm/arch/i2c.h> +#include <asm/arch/ohci.h> #include "devices.h" diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 698aeec5296..76970598f55 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -23,6 +23,7 @@ #include <linux/ioport.h> #include <linux/pm.h> #include <linux/string.h> +#include <linux/sysdev.h> #include <asm/hardware.h> #include <asm/irq.h> @@ -226,3 +227,59 @@ void __init pxa_map_io(void) iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc)); get_clk_frequency_khz(1); } + +#ifdef CONFIG_PM + +static unsigned long saved_gplr[4]; +static unsigned long saved_gpdr[4]; +static unsigned long saved_grer[4]; +static unsigned long saved_gfer[4]; + +static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state) +{ + int i, gpio; + + for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) { + saved_gplr[i] = GPLR(gpio); + saved_gpdr[i] = GPDR(gpio); + saved_grer[i] = GRER(gpio); + saved_gfer[i] = GFER(gpio); + + /* Clear GPIO transition detect bits */ + GEDR(gpio) = GEDR(gpio); + } + return 0; +} + +static int pxa_gpio_resume(struct sys_device *dev) +{ + int i, gpio; + + for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) { + /* restore level with set/clear */ + GPSR(gpio) = saved_gplr[i]; + GPCR(gpio) = ~saved_gplr[i]; + + GRER(gpio) = saved_grer[i]; + GFER(gpio) = saved_gfer[i]; + GPDR(gpio) = saved_gpdr[i]; + } + return 0; +} +#else +#define pxa_gpio_suspend NULL +#define pxa_gpio_resume NULL +#endif + +struct sysdev_class pxa_gpio_sysclass = { + .name = "gpio", + .suspend = pxa_gpio_suspend, + .resume = pxa_gpio_resume, +}; + +static int __init pxa_gpio_init(void) +{ + return sysdev_class_register(&pxa_gpio_sysclass); +} + +core_initcall(pxa_gpio_init); diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index b30f240a16c..1a16ad3ecee 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -52,3 +52,6 @@ extern unsigned pxa3xx_get_memclk_frequency_10khz(void); #define pxa3xx_get_clk_frequency_khz(x) (0) #define pxa3xx_get_memclk_frequency_10khz() (0) #endif + +extern struct sysdev_class pxa_irq_sysclass; +extern struct sysdev_class pxa_gpio_sysclass; diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 07acb45b16e..5a1d5eef10a 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/interrupt.h> +#include <linux/sysdev.h> #include <asm/hardware.h> #include <asm/irq.h> @@ -321,3 +322,64 @@ void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int)) pxa_low_gpio_chip.set_wake = set_wake; pxa_muxed_gpio_chip.set_wake = set_wake; } + +#ifdef CONFIG_PM +static unsigned long saved_icmr[2]; + +static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state) +{ + switch (dev->id) { + case 0: + saved_icmr[0] = ICMR; + ICMR = 0; + break; +#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) + case 1: + saved_icmr[1] = ICMR2; + ICMR2 = 0; + break; +#endif + default: + return -EINVAL; + } + + return 0; +} + +static int pxa_irq_resume(struct sys_device *dev) +{ + switch (dev->id) { + case 0: + ICMR = saved_icmr[0]; + ICLR = 0; + ICCR = 1; + break; +#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) + case 1: + ICMR2 = saved_icmr[1]; + ICLR2 = 0; + break; +#endif + default: + return -EINVAL; + } + + return 0; +} +#else +#define pxa_irq_suspend NULL +#define pxa_irq_resume NULL +#endif + +struct sysdev_class pxa_irq_sysclass = { + .name = "irq", + .suspend = pxa_irq_suspend, + .resume = pxa_irq_resume, +}; + +static int __init pxa_irq_init(void) +{ + return sysdev_class_register(&pxa_irq_sysclass); +} + +core_initcall(pxa_irq_init); diff --git a/arch/arm/mach-pxa/mfp.c b/arch/arm/mach-pxa/mfp.c index ec1b2d8f61c..f5809adce29 100644 --- a/arch/arm/mach-pxa/mfp.c +++ b/arch/arm/mach-pxa/mfp.c @@ -22,6 +22,7 @@ #include <asm/hardware.h> #include <asm/arch/mfp.h> #include <asm/arch/mfp-pxa3xx.h> +#include <asm/arch/pxa3xx-regs.h> /* mfp_spin_lock is used to ensure that MFP register configuration * (most likely a read-modify-write operation) is atomic, and that @@ -223,11 +224,19 @@ static int pxa3xx_mfp_resume(struct sys_device *d) struct pxa3xx_mfp_pin *p = &mfp_table[pin]; __mfp_config_run(p); } + + /* clear RDH bit when MFP settings are restored + * + * NOTE: the last 3 bits DxS are write-1-to-clear so carefully + * preserve them here in case they will be referenced later + */ + ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S); + return 0; } static struct sysdev_class mfp_sysclass = { - set_kset_name("mfp"), + .name = "mfp", .suspend = pxa3xx_mfp_suspend, .resume = pxa3xx_mfp_resume, }; diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c index 540c3bba5f9..c14696b9979 100644 --- a/arch/arm/mach-pxa/pcm027.c +++ b/arch/arm/mach-pxa/pcm027.c @@ -29,6 +29,7 @@ #include <asm/mach/arch.h> #include <asm/arch/hardware.h> #include <asm/arch/pxa-regs.h> +#include <asm/arch/pxa2xx-regs.h> #include <asm/arch/pxa2xx_spi.h> #include <asm/arch/pcm027.h> #include "generic.h" diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index dd54496083c..209eabf0ed3 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -164,7 +164,7 @@ static struct resource poodlets_resources[] = { }, }; -static unsigned long poodle_get_hsync_len(void) +static unsigned long poodle_get_hsync_invperiod(void) { return 0; } @@ -174,9 +174,9 @@ static void poodle_null_hsync(void) } static struct corgits_machinfo poodle_ts_machinfo = { - .get_hsync_len = poodle_get_hsync_len, - .put_hsync = poodle_null_hsync, - .wait_hsync = poodle_null_hsync, + .get_hsync_invperiod = poodle_get_hsync_invperiod, + .put_hsync = poodle_null_hsync, + .wait_hsync = poodle_null_hsync, }; static struct platform_device poodle_ts_device = { diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index ddd05bf78e0..599e53fcc2c 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/suspend.h> +#include <linux/sysdev.h> #include <asm/hardware.h> #include <asm/arch/irqs.h> @@ -141,11 +142,6 @@ static struct clk pxa25x_clks[] = { #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] -#define RESTORE_GPLEVEL(n) do { \ - GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \ - GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \ -} while (0) - /* * List of global PXA peripheral registers to preserve. * More ones like CP and general purpose register values are preserved @@ -153,10 +149,6 @@ static struct clk pxa25x_clks[] = { */ enum { SLEEP_SAVE_START = 0, - SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, - SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, - SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, - SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, @@ -165,7 +157,6 @@ enum { SLEEP_SAVE_START = 0, SLEEP_SAVE_PSTR, - SLEEP_SAVE_ICMR, SLEEP_SAVE_CKEN, SLEEP_SAVE_SIZE @@ -174,17 +165,12 @@ enum { SLEEP_SAVE_START = 0, static void pxa25x_cpu_pm_save(unsigned long *sleep_save) { - SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); - SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); - SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); - SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); SAVE(GAFR0_L); SAVE(GAFR0_U); SAVE(GAFR1_L); SAVE(GAFR1_U); SAVE(GAFR2_L); SAVE(GAFR2_U); - SAVE(ICMR); ICMR = 0; SAVE(CKEN); SAVE(PSTR); @@ -198,22 +184,14 @@ static void pxa25x_cpu_pm_restore(unsigned long *sleep_save) PSPR = 0; /* restore registers */ - RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2); - RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); RESTORE(GAFR0_L); RESTORE(GAFR0_U); RESTORE(GAFR1_L); RESTORE(GAFR1_U); RESTORE(GAFR2_L); RESTORE(GAFR2_U); - RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); - RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); PSSR = PSSR_RDH | PSSR_PH; RESTORE(CKEN); - - ICLR = 0; - ICCR = 1; - RESTORE(ICMR); RESTORE(PSTR); } @@ -304,9 +282,17 @@ static struct platform_device *pxa25x_devices[] __initdata = { &pxa25x_device_assp, }; +static struct sys_device pxa25x_sysdev[] = { + { + .cls = &pxa_irq_sysclass, + }, { + .cls = &pxa_gpio_sysclass, + }, +}; + static int __init pxa25x_init(void) { - int ret = 0; + int i, ret = 0; /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */ if (cpu_is_pxa25x()) @@ -320,9 +306,18 @@ static int __init pxa25x_init(void) pxa25x_init_pm(); + for (i = 0; i < ARRAY_SIZE(pxa25x_sysdev); i++) { + ret = sysdev_register(&pxa25x_sysdev[i]); + if (ret) + pr_err("failed to register sysdev[%d]\n", i); + } + ret = platform_add_devices(pxa25x_devices, ARRAY_SIZE(pxa25x_devices)); + if (ret) + return ret; } + /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */ if (cpu_is_pxa25x()) ret = platform_device_register(&pxa_device_hwuart); diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 96cf274ec7c..46a951c3e5a 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/suspend.h> #include <linux/platform_device.h> +#include <linux/sysdev.h> #include <asm/hardware.h> #include <asm/irq.h> @@ -171,11 +172,6 @@ static struct clk pxa27x_clks[] = { #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] -#define RESTORE_GPLEVEL(n) do { \ - GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \ - GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \ -} while (0) - /* * List of global PXA peripheral registers to preserve. * More ones like CP and general purpose register values are preserved @@ -183,10 +179,6 @@ static struct clk pxa27x_clks[] = { */ enum { SLEEP_SAVE_START = 0, - SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3, - SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3, - SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3, - SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3, SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3, SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U, @@ -196,7 +188,6 @@ enum { SLEEP_SAVE_START = 0, SLEEP_SAVE_PSTR, - SLEEP_SAVE_ICMR, SLEEP_SAVE_CKEN, SLEEP_SAVE_MDREFR, @@ -208,10 +199,6 @@ enum { SLEEP_SAVE_START = 0, void pxa27x_cpu_pm_save(unsigned long *sleep_save) { - SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); SAVE(GPLR3); - SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); SAVE(GPDR3); - SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); SAVE(GRER3); - SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); SAVE(GFER3); SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); SAVE(PGSR3); SAVE(GAFR0_L); SAVE(GAFR0_U); @@ -223,12 +210,8 @@ void pxa27x_cpu_pm_save(unsigned long *sleep_save) SAVE(PWER); SAVE(PCFR); SAVE(PRER); SAVE(PFER); SAVE(PKWR); - SAVE(ICMR); ICMR = 0; SAVE(CKEN); SAVE(PSTR); - - /* Clear GPIO transition detect bits */ - GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; GEDR3 = GEDR3; } void pxa27x_cpu_pm_restore(unsigned long *sleep_save) @@ -237,15 +220,10 @@ void pxa27x_cpu_pm_restore(unsigned long *sleep_save) PSPR = 0; /* restore registers */ - RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); - RESTORE_GPLEVEL(2); RESTORE_GPLEVEL(3); - RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); RESTORE(GPDR3); RESTORE(GAFR0_L); RESTORE(GAFR0_U); RESTORE(GAFR1_L); RESTORE(GAFR1_U); RESTORE(GAFR2_L); RESTORE(GAFR2_U); RESTORE(GAFR3_L); RESTORE(GAFR3_U); - RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); RESTORE(GRER3); - RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); RESTORE(GFER3); RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); RESTORE(PGSR3); RESTORE(MDREFR); @@ -256,9 +234,6 @@ void pxa27x_cpu_pm_restore(unsigned long *sleep_save) RESTORE(CKEN); - ICLR = 0; - ICCR = 1; - RESTORE(ICMR); RESTORE(PSTR); } @@ -409,9 +384,22 @@ static struct platform_device *devices[] __initdata = { &pxa27x_device_ssp3, }; +static struct sys_device pxa27x_sysdev[] = { + { + .id = 0, + .cls = &pxa_irq_sysclass, + }, { + .id = 1, + .cls = &pxa_irq_sysclass, + }, { + .cls = &pxa_gpio_sysclass, + }, +}; + static int __init pxa27x_init(void) { - int ret = 0; + int i, ret = 0; + if (cpu_is_pxa27x()) { clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks)); @@ -420,8 +408,15 @@ static int __init pxa27x_init(void) pxa27x_init_pm(); + for (i = 0; i < ARRAY_SIZE(pxa27x_sysdev); i++) { + ret = sysdev_register(&pxa27x_sysdev[i]); + if (ret) + pr_err("failed to register sysdev[%d]\n", i); + } + ret = platform_add_devices(devices, ARRAY_SIZE(devices)); } + return ret; } diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 5cbf057a1b3..e47e67c11af 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -20,6 +20,7 @@ #include <linux/platform_device.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/sysdev.h> #include <asm/hardware.h> #include <asm/arch/pxa3xx-regs.h> @@ -39,6 +40,7 @@ #define RO_CLK 60000000 #define ACCR_D0CS (1 << 26) +#define ACCR_PCCE (1 << 11) /* crystal frequency to static memory controller multiplier (SMCFS) */ static unsigned char smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, }; @@ -203,7 +205,6 @@ static struct clk pxa3xx_clks[] = { }; #ifdef CONFIG_PM -#define SLEEP_SAVE_SIZE 4 #define ISRAM_START 0x5c000000 #define ISRAM_SIZE SZ_256K @@ -211,25 +212,29 @@ static struct clk pxa3xx_clks[] = { static void __iomem *sram; static unsigned long wakeup_src; -static void pxa3xx_cpu_pm_save(unsigned long *sleep_save) -{ - pr_debug("PM: CKENA=%08x CKENB=%08x\n", CKENA, CKENB); +#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x +#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] - if (CKENA & (1 << CKEN_USBH)) { - printk(KERN_ERR "PM: USB host clock not stopped?\n"); - CKENA &= ~(1 << CKEN_USBH); - } -// CKENA |= 1 << (CKEN_ISC & 31); +enum { SLEEP_SAVE_START = 0, + SLEEP_SAVE_CKENA, + SLEEP_SAVE_CKENB, + SLEEP_SAVE_ACCR, - /* - * Low power modes require the HSIO2 clock to be enabled. - */ - CKENB |= 1 << (CKEN_HSIO2 & 31); + SLEEP_SAVE_SIZE, +}; + +static void pxa3xx_cpu_pm_save(unsigned long *sleep_save) +{ + SAVE(CKENA); + SAVE(CKENB); + SAVE(ACCR); } static void pxa3xx_cpu_pm_restore(unsigned long *sleep_save) { - CKENB &= ~(1 << (CKEN_HSIO2 & 31)); + RESTORE(ACCR); + RESTORE(CKENA); + RESTORE(CKENB); } /* @@ -265,6 +270,46 @@ static void pxa3xx_cpu_standby(unsigned int pwrmode) printk("PM: AD2D0SR=%08x ASCR=%08x\n", AD2D0SR, ASCR); } +/* + * NOTE: currently, the OBM (OEM Boot Module) binary comes along with + * PXA3xx development kits assumes that the resuming process continues + * with the address stored within the first 4 bytes of SDRAM. The PSPR + * register is used privately by BootROM and OBM, and _must_ be set to + * 0x5c014000 for the moment. + */ +static void pxa3xx_cpu_pm_suspend(void) +{ + volatile unsigned long *p = (volatile void *)0xc0000000; + unsigned long saved_data = *p; + + extern void pxa3xx_cpu_suspend(void); + extern void pxa3xx_cpu_resume(void); + + /* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */ + CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM); + CKENB |= 1 << (CKEN_HSIO2 & 0x1f); + + /* clear and setup wakeup source */ + AD3SR = ~0; + AD3ER = wakeup_src; + ASCR = ASCR; + ARSR = ARSR; + + PCFR |= (1u << 13); /* L1_DIS */ + PCFR &= ~((1u << 12) | (1u << 1)); /* L0_EN | SL_ROD */ + + PSPR = 0x5c014000; + + /* overwrite with the resume address */ + *p = virt_to_phys(pxa3xx_cpu_resume); + + pxa3xx_cpu_suspend(); + + *p = saved_data; + + AD3ER = 0; +} + static void pxa3xx_cpu_pm_enter(suspend_state_t state) { /* @@ -279,6 +324,7 @@ static void pxa3xx_cpu_pm_enter(suspend_state_t state) break; case PM_SUSPEND_MEM: + pxa3xx_cpu_pm_suspend(); break; } } @@ -452,9 +498,21 @@ static struct platform_device *devices[] __initdata = { &pxa3xx_device_ssp4, }; +static struct sys_device pxa3xx_sysdev[] = { + { + .id = 0, + .cls = &pxa_irq_sysclass, + }, { + .id = 1, + .cls = &pxa_irq_sysclass, + }, { + .cls = &pxa_gpio_sysclass, + }, +}; + static int __init pxa3xx_init(void) { - int ret = 0; + int i, ret = 0; if (cpu_is_pxa3xx()) { clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks)); @@ -464,9 +522,16 @@ static int __init pxa3xx_init(void) pxa3xx_init_pm(); - return platform_add_devices(devices, ARRAY_SIZE(devices)); + for (i = 0; i < ARRAY_SIZE(pxa3xx_sysdev); i++) { + ret = sysdev_register(&pxa3xx_sysdev[i]); + if (ret) + pr_err("failed to register sysdev[%d]\n", i); + } + + ret = platform_add_devices(devices, ARRAY_SIZE(devices)); } - return 0; + + return ret; } subsys_initcall(pxa3xx_init); diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S index 14bb4a93ea5..784716eb7fc 100644 --- a/arch/arm/mach-pxa/sleep.S +++ b/arch/arm/mach-pxa/sleep.S @@ -50,6 +50,108 @@ pxa_cpu_save_sp: str r0, [r1] ldr pc, [sp], #4 +#ifdef CONFIG_PXA3xx +/* + * pxa3xx_cpu_suspend() - forces CPU into sleep state (S2D3C4) + * + * NOTE: unfortunately, pxa_cpu_save_cp can not be reused here since + * the auxiliary control register address is different between pxa3xx + * and pxa{25x,27x} + */ + +ENTRY(pxa3xx_cpu_suspend) + +#ifndef CONFIG_IWMMXT + mra r2, r3, acc0 +#endif + stmfd sp!, {r2 - r12, lr} @ save registers on stack + + mrc p14, 0, r3, c6, c0, 0 @ clock configuration, for turbo mode + mrc p15, 0, r4, c15, c1, 0 @ CP access reg + mrc p15, 0, r5, c13, c0, 0 @ PID + mrc p15, 0, r6, c3, c0, 0 @ domain ID + mrc p15, 0, r7, c2, c0, 0 @ translation table base addr + mrc p15, 0, r8, c1, c0, 1 @ auxiliary control reg + mrc p15, 0, r9, c1, c0, 0 @ control reg + + bic r3, r3, #2 @ clear frequency change bit + + @ store them plus current virtual stack ptr on stack + mov r10, sp + stmfd sp!, {r3 - r10} + + @ store physical address of stack pointer + mov r0, sp + bl sleep_phys_sp + ldr r1, =sleep_save_sp + str r0, [r1] + + @ clean data cache + bl xsc3_flush_kern_cache_all + + mov r0, #0x06 @ S2D3C4 mode + mcr p14, 0, r0, c7, c0, 0 @ enter sleep + +20: b 20b @ waiting for sleep + + .data + .align 5 +/* + * pxa3xx_cpu_resume + */ + +ENTRY(pxa3xx_cpu_resume) + + mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off + msr cpsr_c, r0 + + ldr r0, sleep_save_sp @ stack phys addr + ldmfd r0, {r3 - r9, sp} @ CP regs + virt stack ptr + + mov r1, #0 + mcr p15, 0, r1, c7, c7, 0 @ invalidate I & D caches, BTB + mcr p15, 0, r1, c7, c10, 4 @ drain write (&fill) buffer + mcr p15, 0, r1, c7, c5, 4 @ flush prefetch buffer + mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs + + mcr p14, 0, r3, c6, c0, 0 @ clock configuration, turbo mode. + mcr p15, 0, r4, c15, c1, 0 @ CP access reg + mcr p15, 0, r5, c13, c0, 0 @ PID + mcr p15, 0, r6, c3, c0, 0 @ domain ID + mcr p15, 0, r7, c2, c0, 0 @ translation table base addr + mcr p15, 0, r8, c1, c0, 1 @ auxiliary control reg + + @ temporarily map resume_turn_on_mmu into the page table, + @ otherwise prefetch abort occurs after MMU is turned on + mov r1, r7 + bic r1, r1, #0x00ff + bic r1, r1, #0x3f00 + ldr r2, =0x542e + + adr r3, resume_turn_on_mmu + mov r3, r3, lsr #20 + orr r4, r2, r3, lsl #20 + ldr r5, [r1, r3, lsl #2] + str r4, [r1, r3, lsl #2] + + @ Mapping page table address in the page table + mov r6, r1, lsr #20 + orr r7, r2, r6, lsl #20 + ldr r8, [r1, r6, lsl #2] + str r7, [r1, r6, lsl #2] + + ldr r2, =pxa3xx_resume_after_mmu @ absolute virtual address + b resume_turn_on_mmu @ cache align execution + + .text +pxa3xx_resume_after_mmu: + /* restore the temporary mapping */ + str r5, [r1, r3, lsl #2] + str r8, [r1, r6, lsl #2] + b resume_after_mmu + +#endif /* CONFIG_PXA3xx */ + #ifdef CONFIG_PXA27x /* * pxa27x_cpu_suspend() diff --git a/arch/arm/mach-pxa/smemc.c b/arch/arm/mach-pxa/smemc.c new file mode 100644 index 00000000000..ad346addc02 --- /dev/null +++ b/arch/arm/mach-pxa/smemc.c @@ -0,0 +1,88 @@ +/* + * Static Memory Controller + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/sysdev.h> + +#define SMEMC_PHYS_BASE (0x4A000000) +#define SMEMC_PHYS_SIZE (0x90) + +#define MSC0 (0x08) /* Static Memory Controller Register 0 */ +#define MSC1 (0x0C) /* Static Memory Controller Register 1 */ +#define SXCNFG (0x1C) /* Synchronous Static Memory Control Register */ +#define MEMCLKCFG (0x68) /* Clock Configuration */ +#define CSADRCFG0 (0x80) /* Address Configuration Register for CS0 */ +#define CSADRCFG1 (0x84) /* Address Configuration Register for CS1 */ +#define CSADRCFG2 (0x88) /* Address Configuration Register for CS2 */ +#define CSADRCFG3 (0x8C) /* Address Configuration Register for CS3 */ + +#ifdef CONFIG_PM +static void __iomem *smemc_mmio_base; + +static unsigned long msc[2]; +static unsigned long sxcnfg, memclkcfg; +static unsigned long csadrcfg[4]; + +static int pxa3xx_smemc_suspend(struct sys_device *dev, pm_message_t state) +{ + msc[0] = __raw_readl(smemc_mmio_base + MSC0); + msc[1] = __raw_readl(smemc_mmio_base + MSC1); + sxcnfg = __raw_readl(smemc_mmio_base + SXCNFG); + memclkcfg = __raw_readl(smemc_mmio_base + MEMCLKCFG); + csadrcfg[0] = __raw_readl(smemc_mmio_base + CSADRCFG0); + csadrcfg[1] = __raw_readl(smemc_mmio_base + CSADRCFG1); + csadrcfg[2] = __raw_readl(smemc_mmio_base + CSADRCFG2); + csadrcfg[3] = __raw_readl(smemc_mmio_base + CSADRCFG3); + + return 0; +} + +static int pxa3xx_smemc_resume(struct sys_device *dev) +{ + __raw_writel(msc[0], smemc_mmio_base + MSC0); + __raw_writel(msc[1], smemc_mmio_base + MSC1); + __raw_writel(sxcnfg, smemc_mmio_base + SXCNFG); + __raw_writel(memclkcfg, smemc_mmio_base + MEMCLKCFG); + __raw_writel(csadrcfg[0], smemc_mmio_base + CSADRCFG0); + __raw_writel(csadrcfg[1], smemc_mmio_base + CSADRCFG1); + __raw_writel(csadrcfg[2], smemc_mmio_base + CSADRCFG2); + __raw_writel(csadrcfg[3], smemc_mmio_base + CSADRCFG3); + + return 0; +} + +static struct sysdev_class smemc_sysclass = { + .name = "smemc", + .suspend = pxa3xx_smemc_suspend, + .resume = pxa3xx_smemc_resume, +}; + +static struct sys_device smemc_sysdev = { + .id = 0, + .cls = &smemc_sysclass, +}; + +static int __init smemc_init(void) +{ + int ret = 0; + + if (cpu_is_pxa3xx()) { + smemc_mmio_base = ioremap(SMEMC_PHYS_BASE, SMEMC_PHYS_SIZE); + if (smemc_mmio_base == NULL) + return -ENODEV; + + ret = sysdev_class_register(&smemc_sysclass); + if (ret) + return ret; + + ret = sysdev_register(&smemc_sysdev); + } + + return ret; +} +subsys_initcall(smemc_init); +#endif diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 5078edeadf9..9e7773fca01 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -36,6 +36,7 @@ #include <asm/mach/irq.h> #include <asm/arch/pxa-regs.h> +#include <asm/arch/pxa2xx-regs.h> #include <asm/arch/irda.h> #include <asm/arch/mmc.h> #include <asm/arch/ohci.h> diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 1a9c844ac7e..9b26fa5edad 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -29,6 +29,7 @@ #include <asm/irq.h> #include <asm/system.h> #include <asm/arch/pxa-regs.h> +#include <asm/arch/pxa2xx-regs.h> #include <asm/arch/irda.h> #include <asm/arch/mmc.h> #include <asm/arch/udc.h> diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index 35156ca39df..39b3bb7f102 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -7,24 +7,21 @@ config MACH_REALVIEW_EB help Include support for the ARM(R) RealView Emulation Baseboard platform. -config REALVIEW_MPCORE - bool "Support MPcore tile" +config REALVIEW_EB_ARM11MP + bool "Support ARM11MPCore tile" depends on MACH_REALVIEW_EB select CACHE_L2X0 help - Enable support for the MPCore tile on the Realview platform. - Since there are device address and interrupt differences, a - kernel built with this option enabled is not compatible with - other tiles. + Enable support for the ARM11MPCore tile on the Realview platform. -config REALVIEW_MPCORE_REVB - bool "Support MPcore RevB tile" - depends on REALVIEW_MPCORE +config REALVIEW_EB_ARM11MP_REVB + bool "Support ARM11MPCore RevB tile" + depends on REALVIEW_EB_ARM11MP default n help - Enable support for the MPCore RevB tile on the Realview platform. - Since there are device address differences, a + Enable support for the ARM11MPCore RevB tile on the Realview + platform. Since there are device address differences, a kernel built with this option enabled is not compatible with - other tiles. + other revisions of the ARM11MPCore tile. endmenu diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile index 36e76ba937f..ca1e390c3c2 100644 --- a/arch/arm/mach-realview/Makefile +++ b/arch/arm/mach-realview/Makefile @@ -4,6 +4,5 @@ obj-y := core.o clock.o obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o -obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o -obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 61d70218f1e..98aefc9f4df 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -25,6 +25,8 @@ #include <linux/interrupt.h> #include <linux/amba/bus.h> #include <linux/amba/clcd.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> #include <asm/system.h> #include <asm/hardware.h> @@ -37,7 +39,6 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> #include <asm/mach/irq.h> -#include <asm/mach/time.h> #include <asm/mach/map.h> #include <asm/mach/mmc.h> @@ -48,6 +49,9 @@ #define REALVIEW_REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET) +/* used by entry-macro.S */ +void __iomem *gic_cpu_base_addr; + /* * This is the RealView sched_clock implementation. This has * a resolution of 41.7ns, and a maximum value of about 179s. @@ -121,26 +125,6 @@ struct platform_device realview_flash_device = { .resource = &realview_flash_resource, }; -static struct resource realview_smc91x_resources[] = { - [0] = { - .start = REALVIEW_ETH_BASE, - .end = REALVIEW_ETH_BASE + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_ETH, - .end = IRQ_ETH, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device realview_smc91x_device = { - .name = "smc91x", - .id = 0, - .num_resources = ARRAY_SIZE(realview_smc91x_resources), - .resource = realview_smc91x_resources, -}; - static struct resource realview_i2c_resource = { .start = REALVIEW_I2C_BASE, .end = REALVIEW_I2C_BASE + SZ_4K - 1, @@ -484,45 +468,64 @@ void realview_leds_event(led_event_t ledevt) #define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) #endif -/* - * Returns number of ms since last clock interrupt. Note that interrupts - * will have been disabled by do_gettimeoffset() - */ -static unsigned long realview_gettimeoffset(void) +static void timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) { - unsigned long ticks1, ticks2, status; + unsigned long ctrl; - /* - * Get the current number of ticks. Note that there is a race - * condition between us reading the timer and checking for - * an interrupt. We get around this by ensuring that the - * counter has not reloaded between our two reads. - */ - ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; - do { - ticks1 = ticks2; - status = __raw_readl(__io_address(REALVIEW_GIC_DIST_BASE + GIC_DIST_PENDING_SET) - + ((IRQ_TIMERINT0_1 >> 5) << 2)); - ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; - } while (ticks2 > ticks1); + switch(mode) { + case CLOCK_EVT_MODE_PERIODIC: + writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD); - /* - * Number of ticks since last interrupt. - */ - ticks1 = TIMER_RELOAD - ticks2; + ctrl = TIMER_CTRL_PERIODIC; + ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE; + break; + case CLOCK_EVT_MODE_ONESHOT: + /* period set, and timer enabled in 'next_event' hook */ + ctrl = TIMER_CTRL_ONESHOT; + ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE; + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + default: + ctrl = 0; + } - /* - * Interrupt pending? If so, we've reloaded once already. - * - * FIXME: Need to check this is effectively timer 0 that expires - */ - if (status & IRQMASK_TIMERINT0_1) - ticks1 += TIMER_RELOAD; + writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL); +} - /* - * Convert the ticks to usecs - */ - return TICKS2USECS(ticks1); +static int timer_set_next_event(unsigned long evt, + struct clock_event_device *unused) +{ + unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL); + + writel(evt, TIMER0_VA_BASE + TIMER_LOAD); + writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL); + + return 0; +} + +static struct clock_event_device timer0_clockevent = { + .name = "timer0", + .shift = 32, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_mode = timer_set_mode, + .set_next_event = timer_set_next_event, + .rating = 300, + .cpumask = CPU_MASK_ALL, +}; + +static void __init realview_clockevents_init(unsigned int timer_irq) +{ + timer0_clockevent.irq = timer_irq; + timer0_clockevent.mult = + div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift); + timer0_clockevent.max_delta_ns = + clockevent_delta2ns(0xffffffff, &timer0_clockevent); + timer0_clockevent.min_delta_ns = + clockevent_delta2ns(0xf, &timer0_clockevent); + + clockevents_register_device(&timer0_clockevent); } /* @@ -530,15 +533,12 @@ static unsigned long realview_gettimeoffset(void) */ static irqreturn_t realview_timer_interrupt(int irq, void *dev_id) { - // ...clear the interrupt + struct clock_event_device *evt = &timer0_clockevent; + + /* clear the interrupt */ writel(1, TIMER0_VA_BASE + TIMER_INTCLR); - timer_tick(); - -#if defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS) - smp_send_timer(); - update_process_times(user_mode(get_irq_regs())); -#endif + evt->event_handler(evt); return IRQ_HANDLED; } @@ -549,13 +549,49 @@ static struct irqaction realview_timer_irq = { .handler = realview_timer_interrupt, }; +static cycle_t realview_get_cycles(void) +{ + return ~readl(TIMER3_VA_BASE + TIMER_VALUE); +} + +static struct clocksource clocksource_realview = { + .name = "timer3", + .rating = 200, + .read = realview_get_cycles, + .mask = CLOCKSOURCE_MASK(32), + .shift = 20, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void __init realview_clocksource_init(void) +{ + /* setup timer 0 as free-running clocksource */ + writel(0, TIMER3_VA_BASE + TIMER_CTRL); + writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD); + writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE); + writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, + TIMER3_VA_BASE + TIMER_CTRL); + + clocksource_realview.mult = + clocksource_khz2mult(1000, clocksource_realview.shift); + clocksource_register(&clocksource_realview); +} + /* - * Set up timer interrupt, and return the current time in seconds. + * Set up the clock source and clock events devices */ -static void __init realview_timer_init(void) +void __init realview_timer_init(unsigned int timer_irq) { u32 val; +#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST + /* + * The dummy clock device has to be registered before the main device + * so that the latter will broadcast the clock events + */ + local_timer_setup(smp_processor_id()); +#endif + /* * set clock frequency: * REALVIEW_REFCLK is 32KHz @@ -576,18 +612,11 @@ static void __init realview_timer_init(void) writel(0, TIMER2_VA_BASE + TIMER_CTRL); writel(0, TIMER3_VA_BASE + TIMER_CTRL); - writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD); - writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE); - writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC | - TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL); - /* * Make irqs happen for the system timer */ - setup_irq(IRQ_TIMERINT0_1, &realview_timer_irq); -} + setup_irq(timer_irq, &realview_timer_irq); -struct sys_timer realview_timer = { - .init = realview_timer_init, - .offset = realview_gettimeoffset, -}; + realview_clocksource_init(); + realview_clockevents_init(timer_irq); +} diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h index 2b53420f9c1..492a14c0d60 100644 --- a/arch/arm/mach-realview/core.h +++ b/arch/arm/mach-realview/core.h @@ -27,8 +27,6 @@ #include <asm/leds.h> #include <asm/io.h> -extern struct sys_timer realview_timer; - #define AMBA_DEVICE(name,busid,base,plat) \ static struct amba_device name##_device = { \ .dev = { \ @@ -38,7 +36,7 @@ static struct amba_device name##_device = { \ }, \ .res = { \ .start = REALVIEW_##base##_BASE, \ - .end = (REALVIEW_##base##_BASE) + SZ_4K - 1,\ + .end = (REALVIEW_##base##_BASE) + SZ_4K - 1, \ .flags = IORESOURCE_MEM, \ }, \ .dma_mask = ~0, \ @@ -46,74 +44,19 @@ static struct amba_device name##_device = { \ /* .dma = base##_DMA,*/ \ } -/* - * These devices are connected via the core APB bridge - */ -#define GPIO2_IRQ { IRQ_GPIOINT2, NO_IRQ } -#define GPIO2_DMA { 0, 0 } -#define GPIO3_IRQ { IRQ_GPIOINT3, NO_IRQ } -#define GPIO3_DMA { 0, 0 } - -#define AACI_IRQ { IRQ_AACI, NO_IRQ } -#define AACI_DMA { 0x80, 0x81 } -#define MMCI0_IRQ { IRQ_MMCI0A,IRQ_MMCI0B } -#define MMCI0_DMA { 0x84, 0 } -#define KMI0_IRQ { IRQ_KMI0, NO_IRQ } -#define KMI0_DMA { 0, 0 } -#define KMI1_IRQ { IRQ_KMI1, NO_IRQ } -#define KMI1_DMA { 0, 0 } - -/* - * These devices are connected directly to the multi-layer AHB switch - */ -#define SMC_IRQ { NO_IRQ, NO_IRQ } -#define SMC_DMA { 0, 0 } -#define MPMC_IRQ { NO_IRQ, NO_IRQ } -#define MPMC_DMA { 0, 0 } -#define CLCD_IRQ { IRQ_CLCDINT, NO_IRQ } -#define CLCD_DMA { 0, 0 } -#define DMAC_IRQ { IRQ_DMAINT, NO_IRQ } -#define DMAC_DMA { 0, 0 } - -/* - * These devices are connected via the core APB bridge - */ -#define SCTL_IRQ { NO_IRQ, NO_IRQ } -#define SCTL_DMA { 0, 0 } -#define WATCHDOG_IRQ { IRQ_WDOGINT, NO_IRQ } -#define WATCHDOG_DMA { 0, 0 } -#define GPIO0_IRQ { IRQ_GPIOINT0, NO_IRQ } -#define GPIO0_DMA { 0, 0 } -#define GPIO1_IRQ { IRQ_GPIOINT1, NO_IRQ } -#define GPIO1_DMA { 0, 0 } -#define RTC_IRQ { IRQ_RTCINT, NO_IRQ } -#define RTC_DMA { 0, 0 } - -/* - * These devices are connected via the DMA APB bridge - */ -#define SCI_IRQ { IRQ_SCIINT, NO_IRQ } -#define SCI_DMA { 7, 6 } -#define UART0_IRQ { IRQ_UARTINT0, NO_IRQ } -#define UART0_DMA { 15, 14 } -#define UART1_IRQ { IRQ_UARTINT1, NO_IRQ } -#define UART1_DMA { 13, 12 } -#define UART2_IRQ { IRQ_UARTINT2, NO_IRQ } -#define UART2_DMA { 11, 10 } -#define UART3_IRQ { IRQ_UART3, NO_IRQ } -#define UART3_DMA { 0x86, 0x87 } -#define SSP_IRQ { IRQ_SSPINT, NO_IRQ } -#define SSP_DMA { 9, 8 } - - extern struct platform_device realview_flash_device; -extern struct platform_device realview_smc91x_device; extern struct platform_device realview_i2c_device; extern struct mmc_platform_data realview_mmc0_plat_data; extern struct mmc_platform_data realview_mmc1_plat_data; extern struct clk realview_clcd_clk; extern struct clcd_board clcd_plat_data; +extern void __iomem *gic_cpu_base_addr; +#ifdef CONFIG_LOCAL_TIMERS +extern void __iomem *twd_base_addr; +extern unsigned int twd_size; +#endif extern void realview_leds_event(led_event_t ledevt); +extern void realview_timer_init(unsigned int timer_irq); #endif diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c index c7bdf04ab09..50604360479 100644 --- a/arch/arm/mach-realview/localtimer.c +++ b/arch/arm/mach-realview/localtimer.c @@ -14,19 +14,75 @@ #include <linux/device.h> #include <linux/smp.h> #include <linux/jiffies.h> +#include <linux/percpu.h> +#include <linux/clockchips.h> +#include <linux/irq.h> -#include <asm/mach/time.h> #include <asm/hardware/arm_twd.h> #include <asm/hardware/gic.h> #include <asm/hardware.h> #include <asm/io.h> #include <asm/irq.h> -#define TWD_BASE(cpu) (__io_address(REALVIEW_TWD_BASE) + \ - ((cpu) * REALVIEW_TWD_SIZE)) +static DEFINE_PER_CPU(struct clock_event_device, local_clockevent); + +/* + * Used on SMP for either the local timer or IPI_TIMER + */ +void local_timer_interrupt(void) +{ + struct clock_event_device *clk = &__get_cpu_var(local_clockevent); + + clk->event_handler(clk); +} + +#ifdef CONFIG_LOCAL_TIMERS + +#define TWD_BASE(cpu) (twd_base_addr + (cpu) * twd_size) + +/* set up by the platform code */ +void __iomem *twd_base_addr; +unsigned int twd_size; static unsigned long mpcore_timer_rate; +static void local_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + void __iomem *base = TWD_BASE(smp_processor_id()); + unsigned long ctrl; + + switch(mode) { + case CLOCK_EVT_MODE_PERIODIC: + /* timer load already set up */ + ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE + | TWD_TIMER_CONTROL_PERIODIC; + break; + case CLOCK_EVT_MODE_ONESHOT: + /* period set, and timer enabled in 'next_event' hook */ + ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT; + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + default: + ctrl = 0; + } + + __raw_writel(ctrl, base + TWD_TIMER_CONTROL); +} + +static int local_timer_set_next_event(unsigned long evt, + struct clock_event_device *unused) +{ + void __iomem *base = TWD_BASE(smp_processor_id()); + unsigned long ctrl = __raw_readl(base + TWD_TIMER_CONTROL); + + __raw_writel(evt, base + TWD_TIMER_COUNTER); + __raw_writel(ctrl | TWD_TIMER_CONTROL_ENABLE, base + TWD_TIMER_CONTROL); + + return 0; +} + /* * local_timer_ack: checks for a local timer interrupt. * @@ -45,12 +101,11 @@ int local_timer_ack(void) return 0; } -void __cpuinit local_timer_setup(unsigned int cpu) +static void __cpuinit twd_calibrate_rate(unsigned int cpu) { void __iomem *base = TWD_BASE(cpu); - unsigned int load, offset; + unsigned long load, count; u64 waitjiffies; - unsigned int count; /* * If this is the first time round, we need to work out how fast @@ -88,36 +143,36 @@ void __cpuinit local_timer_setup(unsigned int cpu) load = mpcore_timer_rate / HZ; __raw_writel(load, base + TWD_TIMER_LOAD); - __raw_writel(0x7, base + TWD_TIMER_CONTROL); - - /* - * Now maneuver our local tick into the right part of the jiffy. - * Start by working out where within the tick our local timer - * interrupt should go. - */ - offset = ((mpcore_timer_rate / HZ) / (NR_CPUS + 1)) * (cpu + 1); - - /* - * gettimeoffset() will return a number of us since the last tick. - * Convert this number of us to a local timer tick count. - * Be careful of integer overflow whilst keeping maximum precision. - * - * with HZ=100 and 1MHz (fpga) ~ 1GHz processor: - * load = 1 ~ 10,000 - * mpcore_timer_rate/10000 = 100 ~ 100,000 - * - * so the multiply value will be less than 10^9 always. - */ - load = (system_timer->offset() * (mpcore_timer_rate / 10000)) / 100; - - /* Add on our offset to get the load value */ - load = (load + offset) % (mpcore_timer_rate / HZ); +} - __raw_writel(load, base + TWD_TIMER_COUNTER); +/* + * Setup the local clock events for a CPU. + */ +void __cpuinit local_timer_setup(unsigned int cpu) +{ + struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); + unsigned long flags; + + twd_calibrate_rate(cpu); + + clk->name = "local_timer"; + clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; + clk->rating = 350; + clk->set_mode = local_timer_set_mode; + clk->set_next_event = local_timer_set_next_event; + clk->irq = IRQ_LOCALTIMER; + clk->cpumask = cpumask_of_cpu(cpu); + clk->shift = 20; + clk->mult = div_sc(mpcore_timer_rate, NSEC_PER_SEC, clk->shift); + clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk); + clk->min_delta_ns = clockevent_delta2ns(0xf, clk); /* Make sure our local interrupt controller has this enabled */ - __raw_writel(1 << IRQ_LOCALTIMER, - __io_address(REALVIEW_GIC_DIST_BASE) + GIC_DIST_ENABLE_SET); + local_irq_save(flags); + get_irq_chip(IRQ_LOCALTIMER)->unmask(IRQ_LOCALTIMER); + local_irq_restore(flags); + + clockevents_register_device(clk); } /* @@ -127,3 +182,26 @@ void __cpuexit local_timer_stop(unsigned int cpu) { __raw_writel(0, TWD_BASE(cpu) + TWD_TIMER_CONTROL); } + +#else /* CONFIG_LOCAL_TIMERS */ + +static void dummy_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ +} + +void __cpuinit local_timer_setup(unsigned int cpu) +{ + struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); + + clk->name = "dummy_timer"; + clk->features = CLOCK_EVT_FEAT_DUMMY; + clk->rating = 200; + clk->set_mode = dummy_timer_set_mode; + clk->broadcast = smp_timer_broadcast; + clk->cpumask = cpumask_of_cpu(cpu); + + clockevents_register_device(clk); +} + +#endif /* !CONFIG_LOCAL_TIMERS */ diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index fce3596f995..de2b7159557 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -18,6 +18,7 @@ #include <asm/hardware/arm_scu.h> #include <asm/hardware.h> #include <asm/io.h> +#include <asm/mach-types.h> extern void realview_secondary_startup(void); @@ -31,9 +32,13 @@ static unsigned int __init get_core_count(void) { unsigned int ncores; - ncores = __raw_readl(__io_address(REALVIEW_MPCORE_SCU_BASE) + SCU_CONFIG); + if (machine_is_realview_eb() && core_tile_eb11mp()) { + ncores = __raw_readl(__io_address(REALVIEW_EB11MP_SCU_BASE) + SCU_CONFIG); + ncores = (ncores & 0x03) + 1; + } else + ncores = 1; - return (ncores & 0x03) + 1; + return ncores; } static DEFINE_SPINLOCK(boot_lock); @@ -52,7 +57,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) * core (e.g. timer irq), then they will not have been enabled * for us: do so */ - gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE)); + gic_cpu_init(0, __io_address(REALVIEW_EB11MP_GIC_CPU_BASE)); /* * let the primary processor know we're out of the @@ -187,10 +192,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus) if (max_cpus > ncores) max_cpus = ncores; +#ifdef CONFIG_LOCAL_TIMERS /* - * Enable the local timer for primary CPU + * Enable the local timer for primary CPU. If the device is + * dummy (!CONFIG_LOCAL_TIMERS), it was already registers in + * realview_timer_init */ - local_timer_setup(cpu); + if (machine_is_realview_eb() && core_tile_eb11mp()) + local_timer_setup(cpu); +#endif /* * Initialise the present map, which describes the set of CPUs diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index ecec2f85c4c..60d9eb81024 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -36,7 +36,9 @@ #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/mmc.h> +#include <asm/mach/time.h> +#include <asm/arch/board-eb.h> #include <asm/arch/irqs.h> #include "core.h" @@ -58,26 +60,7 @@ static struct map_desc realview_eb_io_desc[] __initdata = { .pfn = __phys_to_pfn(REALVIEW_GIC_DIST_BASE), .length = SZ_4K, .type = MT_DEVICE, - }, -#ifdef CONFIG_REALVIEW_MPCORE - { - .virtual = IO_ADDRESS(REALVIEW_GIC1_CPU_BASE), - .pfn = __phys_to_pfn(REALVIEW_GIC1_CPU_BASE), - .length = SZ_4K, - .type = MT_DEVICE, }, { - .virtual = IO_ADDRESS(REALVIEW_GIC1_DIST_BASE), - .pfn = __phys_to_pfn(REALVIEW_GIC1_DIST_BASE), - .length = SZ_4K, - .type = MT_DEVICE, - }, { - .virtual = IO_ADDRESS(REALVIEW_MPCORE_L220_BASE), - .pfn = __phys_to_pfn(REALVIEW_MPCORE_L220_BASE), - .length = SZ_8K, - .type = MT_DEVICE, - }, -#endif - { .virtual = IO_ADDRESS(REALVIEW_SCTL_BASE), .pfn = __phys_to_pfn(REALVIEW_SCTL_BASE), .length = SZ_4K, @@ -103,11 +86,95 @@ static struct map_desc realview_eb_io_desc[] __initdata = { #endif }; +static struct map_desc realview_eb11mp_io_desc[] __initdata = { + { + .virtual = IO_ADDRESS(REALVIEW_EB11MP_GIC_CPU_BASE), + .pfn = __phys_to_pfn(REALVIEW_EB11MP_GIC_CPU_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(REALVIEW_EB11MP_GIC_DIST_BASE), + .pfn = __phys_to_pfn(REALVIEW_EB11MP_GIC_DIST_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(REALVIEW_EB11MP_L220_BASE), + .pfn = __phys_to_pfn(REALVIEW_EB11MP_L220_BASE), + .length = SZ_8K, + .type = MT_DEVICE, + } +}; + static void __init realview_eb_map_io(void) { iotable_init(realview_eb_io_desc, ARRAY_SIZE(realview_eb_io_desc)); + if (core_tile_eb11mp()) + iotable_init(realview_eb11mp_io_desc, ARRAY_SIZE(realview_eb11mp_io_desc)); } +/* + * RealView EB AMBA devices + */ + +/* + * These devices are connected via the core APB bridge + */ +#define GPIO2_IRQ { IRQ_EB_GPIO2, NO_IRQ } +#define GPIO2_DMA { 0, 0 } +#define GPIO3_IRQ { IRQ_EB_GPIO3, NO_IRQ } +#define GPIO3_DMA { 0, 0 } + +#define AACI_IRQ { IRQ_EB_AACI, NO_IRQ } +#define AACI_DMA { 0x80, 0x81 } +#define MMCI0_IRQ { IRQ_EB_MMCI0A, IRQ_EB_MMCI0B } +#define MMCI0_DMA { 0x84, 0 } +#define KMI0_IRQ { IRQ_EB_KMI0, NO_IRQ } +#define KMI0_DMA { 0, 0 } +#define KMI1_IRQ { IRQ_EB_KMI1, NO_IRQ } +#define KMI1_DMA { 0, 0 } + +/* + * These devices are connected directly to the multi-layer AHB switch + */ +#define SMC_IRQ { NO_IRQ, NO_IRQ } +#define SMC_DMA { 0, 0 } +#define MPMC_IRQ { NO_IRQ, NO_IRQ } +#define MPMC_DMA { 0, 0 } +#define CLCD_IRQ { IRQ_EB_CLCD, NO_IRQ } +#define CLCD_DMA { 0, 0 } +#define DMAC_IRQ { IRQ_EB_DMA, NO_IRQ } +#define DMAC_DMA { 0, 0 } + +/* + * These devices are connected via the core APB bridge + */ +#define SCTL_IRQ { NO_IRQ, NO_IRQ } +#define SCTL_DMA { 0, 0 } +#define WATCHDOG_IRQ { IRQ_EB_WDOG, NO_IRQ } +#define WATCHDOG_DMA { 0, 0 } +#define GPIO0_IRQ { IRQ_EB_GPIO0, NO_IRQ } +#define GPIO0_DMA { 0, 0 } +#define GPIO1_IRQ { IRQ_EB_GPIO1, NO_IRQ } +#define GPIO1_DMA { 0, 0 } +#define RTC_IRQ { IRQ_EB_RTC, NO_IRQ } +#define RTC_DMA { 0, 0 } + +/* + * These devices are connected via the DMA APB bridge + */ +#define SCI_IRQ { IRQ_EB_SCI, NO_IRQ } +#define SCI_DMA { 7, 6 } +#define UART0_IRQ { IRQ_EB_UART0, NO_IRQ } +#define UART0_DMA { 15, 14 } +#define UART1_IRQ { IRQ_EB_UART1, NO_IRQ } +#define UART1_DMA { 13, 12 } +#define UART2_IRQ { IRQ_EB_UART2, NO_IRQ } +#define UART2_DMA { 11, 10 } +#define UART3_IRQ { IRQ_EB_UART3, NO_IRQ } +#define UART3_DMA { 0x86, 0x87 } +#define SSP_IRQ { IRQ_EB_SSP, NO_IRQ } +#define SSP_DMA { 9, 8 } + /* FPGA Primecells */ AMBA_DEVICE(aaci, "fpga:04", AACI, NULL); AMBA_DEVICE(mmc0, "fpga:05", MMCI0, &realview_mmc0_plat_data); @@ -153,38 +220,127 @@ static struct amba_device *amba_devs[] __initdata = { &kmi1_device, }; +/* + * RealView EB platform devices + */ + +static struct resource realview_eb_smc91x_resources[] = { + [0] = { + .start = REALVIEW_ETH_BASE, + .end = REALVIEW_ETH_BASE + SZ_64K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_EB_ETH, + .end = IRQ_EB_ETH, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device realview_eb_smc91x_device = { + .name = "smc91x", + .id = 0, + .num_resources = ARRAY_SIZE(realview_eb_smc91x_resources), + .resource = realview_eb_smc91x_resources, +}; + static void __init gic_init_irq(void) { -#ifdef CONFIG_REALVIEW_MPCORE - unsigned int pldctrl; - writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK)); - pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1); - pldctrl |= 0x00800000; /* New irq mode */ - writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1); - writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); + if (core_tile_eb11mp()) { + unsigned int pldctrl; + + /* new irq mode */ + writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK)); + pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_EB11MP_SYS_PLD_CTRL1); + pldctrl |= 0x00800000; + writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_EB11MP_SYS_PLD_CTRL1); + writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); + + /* core tile GIC, primary */ + gic_cpu_base_addr = __io_address(REALVIEW_EB11MP_GIC_CPU_BASE); + gic_dist_init(0, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), 29); + gic_cpu_init(0, gic_cpu_base_addr); + +#ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB + /* board GIC, secondary */ + gic_dist_init(1, __io_address(REALVIEW_GIC_DIST_BASE), 64); + gic_cpu_init(1, __io_address(REALVIEW_GIC_CPU_BASE)); + gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1); #endif - gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29); - gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE)); -#if defined(CONFIG_REALVIEW_MPCORE) && !defined(CONFIG_REALVIEW_MPCORE_REVB) - gic_dist_init(1, __io_address(REALVIEW_GIC1_DIST_BASE), 64); - gic_cpu_init(1, __io_address(REALVIEW_GIC1_CPU_BASE)); - gic_cascade_irq(1, IRQ_EB_IRQ1); + } else { + /* board GIC, primary */ + gic_cpu_base_addr = __io_address(REALVIEW_GIC_CPU_BASE); + gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29); + gic_cpu_init(0, gic_cpu_base_addr); + } +} + +/* + * Fix up the IRQ numbers for the RealView EB/ARM11MPCore tile + */ +static void realview_eb11mp_fixup(void) +{ + /* AMBA devices */ + dmac_device.irq[0] = IRQ_EB11MP_DMA; + uart0_device.irq[0] = IRQ_EB11MP_UART0; + uart1_device.irq[0] = IRQ_EB11MP_UART1; + uart2_device.irq[0] = IRQ_EB11MP_UART2; + uart3_device.irq[0] = IRQ_EB11MP_UART3; + clcd_device.irq[0] = IRQ_EB11MP_CLCD; + wdog_device.irq[0] = IRQ_EB11MP_WDOG; + gpio0_device.irq[0] = IRQ_EB11MP_GPIO0; + gpio1_device.irq[0] = IRQ_EB11MP_GPIO1; + gpio2_device.irq[0] = IRQ_EB11MP_GPIO2; + rtc_device.irq[0] = IRQ_EB11MP_RTC; + sci0_device.irq[0] = IRQ_EB11MP_SCI; + ssp0_device.irq[0] = IRQ_EB11MP_SSP; + aaci_device.irq[0] = IRQ_EB11MP_AACI; + mmc0_device.irq[0] = IRQ_EB11MP_MMCI0A; + mmc0_device.irq[1] = IRQ_EB11MP_MMCI0B; + kmi0_device.irq[0] = IRQ_EB11MP_KMI0; + kmi1_device.irq[0] = IRQ_EB11MP_KMI1; + + /* platform devices */ + realview_eb_smc91x_resources[1].start = IRQ_EB11MP_ETH; + realview_eb_smc91x_resources[1].end = IRQ_EB11MP_ETH; +} + +static void __init realview_eb_timer_init(void) +{ + unsigned int timer_irq; + + if (core_tile_eb11mp()) { +#ifdef CONFIG_LOCAL_TIMERS + twd_base_addr = __io_address(REALVIEW_EB11MP_TWD_BASE); + twd_size = REALVIEW_EB11MP_TWD_SIZE; #endif + timer_irq = IRQ_EB11MP_TIMER0_1; + } else + timer_irq = IRQ_EB_TIMER0_1; + + realview_timer_init(timer_irq); } +static struct sys_timer realview_eb_timer = { + .init = realview_eb_timer_init, +}; + static void __init realview_eb_init(void) { int i; -#ifdef CONFIG_REALVIEW_MPCORE - /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled - * Bits: .... ...0 0111 1001 0000 .... .... .... */ - l2x0_init(__io_address(REALVIEW_MPCORE_L220_BASE), 0x00790000, 0xfe000fff); -#endif + if (core_tile_eb11mp()) { + realview_eb11mp_fixup(); + + /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled + * Bits: .... ...0 0111 1001 0000 .... .... .... */ + l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff); + } + clk_register(&realview_clcd_clk); platform_device_register(&realview_flash_device); - platform_device_register(&realview_smc91x_device); + platform_device_register(&realview_eb_smc91x_device); platform_device_register(&realview_i2c_device); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { @@ -204,6 +360,6 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB") .boot_params = 0x00000100, .map_io = realview_eb_map_io, .init_irq = gic_init_irq, - .timer = &realview_timer, + .timer = &realview_eb_timer, .init_machine = realview_eb_init, MACHINE_END diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 9e13c8358ea..5c84c604ed8 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -470,7 +470,7 @@ void __init sa1110_mb_disable(void) * If the system is going to use the SA-1111 DMA engines, set up * the memory bus request/grant pins. */ -void __init sa1110_mb_enable(void) +void __devinit sa1110_mb_enable(void) { unsigned long flags; diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c index ba3d21d8fba..6fe481ff4fd 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c @@ -57,8 +57,6 @@ unsigned long iop_gettimeoffset(void) static irqreturn_t iop_timer_interrupt(int irq, void *dev_id) { - write_seqlock(&xtime_lock); - write_tisr(1); while ((signed long)(next_jiffy_time - read_tcr1()) @@ -67,8 +65,6 @@ iop_timer_interrupt(int irq, void *dev_id) next_jiffy_time -= ticks_per_jiffy; } - write_sequnlock(&xtime_lock); - return IRQ_HANDLED; } diff --git a/arch/arm/plat-s3c24xx/time.c b/arch/arm/plat-s3c24xx/time.c index 2ec1daaa0e5..766473b3f98 100644 --- a/arch/arm/plat-s3c24xx/time.c +++ b/arch/arm/plat-s3c24xx/time.c @@ -130,9 +130,7 @@ static unsigned long s3c2410_gettimeoffset (void) static irqreturn_t s3c2410_timer_interrupt(int irq, void *dev_id) { - write_seqlock(&xtime_lock); timer_tick(); - write_sequnlock(&xtime_lock); return IRQ_HANDLED; } diff --git a/drivers/pcmcia/sa1100_jornada720.c b/drivers/pcmcia/sa1100_jornada720.c index af485ae3860..6284c35dabc 100644 --- a/drivers/pcmcia/sa1100_jornada720.c +++ b/drivers/pcmcia/sa1100_jornada720.c @@ -101,7 +101,7 @@ static struct pcmcia_low_level jornada720_pcmcia_ops = { .socket_suspend = sa1111_pcmcia_socket_suspend, }; -int __init pcmcia_jornada720_init(struct device *dev) +int __devinit pcmcia_jornada720_init(struct device *dev) { int ret = -ENODEV; diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 6a48dfa1efe..0276471cb25 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -237,6 +237,12 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios, baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); quot = uart_get_divisor(port, baud); + if (port->info && port->info->tty) { + struct tty_struct *tty = port->info->tty; + unsigned int b = port->uartclk / (16 * quot); + tty_encode_baud_rate(tty, b, b); + } + switch (termios->c_cflag & CSIZE) { case CS5: h_lcr = 0x00; @@ -277,8 +283,6 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios, if (termios->c_iflag & INPCK) port->read_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY; - tty_encode_baud_rate(tty, baud, baud); - /* * Which character status flags should we ignore? */ diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 111da57f533..60f52904aad 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -34,6 +34,7 @@ #include <linux/tty_flip.h> #include <linux/platform_device.h> #include <linux/atmel_pdc.h> +#include <linux/atmel_serial.h> #include <asm/io.h> @@ -45,8 +46,6 @@ #include <asm/arch/gpio.h> #endif -#include "atmel_serial.h" - #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ #endif diff --git a/include/asm-arm/arch-at91/at91_mci.h b/include/asm-arm/arch-at91/at91_mci.h index c2e11cc374b..1551fc24eb4 100644 --- a/include/asm-arm/arch-at91/at91_mci.h +++ b/include/asm-arm/arch-at91/at91_mci.h @@ -89,7 +89,7 @@ #define AT91_MCI_ENDRX (1 << 6) /* End of RX Buffer */ #define AT91_MCI_ENDTX (1 << 7) /* End fo TX Buffer */ #define AT91_MCI_SDIOIRQA (1 << 8) /* SDIO Interrupt for Slot A */ -#define At91_MCI_SDIOIRQB (1 << 9) /* SDIO Interrupt for Slot B [AT91RM9200 only] */ +#define AT91_MCI_SDIOIRQB (1 << 9) /* SDIO Interrupt for Slot B */ #define AT91_MCI_RXBUFF (1 << 14) /* RX Buffer Full */ #define AT91_MCI_TXBUFE (1 << 15) /* TX Buffer Empty */ #define AT91_MCI_RINDE (1 << 16) /* Response Index Error */ diff --git a/include/asm-arm/arch-at91/at91rm9200.h b/include/asm-arm/arch-at91/at91rm9200.h index 802891a9cd8..e8fc0b1c33f 100644 --- a/include/asm-arm/arch-at91/at91rm9200.h +++ b/include/asm-arm/arch-at91/at91rm9200.h @@ -93,6 +93,11 @@ #define AT91_RTC (0xfffffe00 - AT91_BASE_SYS) /* Real-Time Clock */ #define AT91_MC (0xffffff00 - AT91_BASE_SYS) /* Memory Controllers */ +#define AT91_USART0 AT91RM9200_BASE_US0 +#define AT91_USART1 AT91RM9200_BASE_US1 +#define AT91_USART2 AT91RM9200_BASE_US2 +#define AT91_USART3 AT91RM9200_BASE_US3 + #define AT91_MATRIX 0 /* not supported */ /* diff --git a/include/asm-arm/arch-at91/at91sam9260.h b/include/asm-arm/arch-at91/at91sam9260.h index 0427f8698c0..c8934fe34dc 100644 --- a/include/asm-arm/arch-at91/at91sam9260.h +++ b/include/asm-arm/arch-at91/at91sam9260.h @@ -99,6 +99,13 @@ #define AT91_WDT (0xfffffd40 - AT91_BASE_SYS) #define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS) +#define AT91_USART0 AT91SAM9260_BASE_US0 +#define AT91_USART1 AT91SAM9260_BASE_US1 +#define AT91_USART2 AT91SAM9260_BASE_US2 +#define AT91_USART3 AT91SAM9260_BASE_US3 +#define AT91_USART4 AT91SAM9260_BASE_US4 +#define AT91_USART5 AT91SAM9260_BASE_US5 + /* * Internal Memory. diff --git a/include/asm-arm/arch-at91/at91sam9261.h b/include/asm-arm/arch-at91/at91sam9261.h index 9eb45957033..c7c4778dac4 100644 --- a/include/asm-arm/arch-at91/at91sam9261.h +++ b/include/asm-arm/arch-at91/at91sam9261.h @@ -84,6 +84,10 @@ #define AT91_WDT (0xfffffd40 - AT91_BASE_SYS) #define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS) +#define AT91_USART0 AT91SAM9261_BASE_US0 +#define AT91_USART1 AT91SAM9261_BASE_US1 +#define AT91_USART2 AT91SAM9261_BASE_US2 + /* * Internal Memory. diff --git a/include/asm-arm/arch-at91/at91sam9263.h b/include/asm-arm/arch-at91/at91sam9263.h index 115c47ac7eb..018a647311d 100644 --- a/include/asm-arm/arch-at91/at91sam9263.h +++ b/include/asm-arm/arch-at91/at91sam9263.h @@ -101,6 +101,10 @@ #define AT91_RTT1 (0xfffffd50 - AT91_BASE_SYS) #define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS) +#define AT91_USART0 AT91SAM9263_BASE_US0 +#define AT91_USART1 AT91SAM9263_BASE_US1 +#define AT91_USART2 AT91SAM9263_BASE_US2 + #define AT91_SMC AT91_SMC0 /* diff --git a/include/asm-arm/arch-at91/at91sam9rl.h b/include/asm-arm/arch-at91/at91sam9rl.h index 8a9708a370c..16d2832f6c0 100644 --- a/include/asm-arm/arch-at91/at91sam9rl.h +++ b/include/asm-arm/arch-at91/at91sam9rl.h @@ -94,6 +94,11 @@ #define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS) #define AT91_RTC (0xfffffe00 - AT91_BASE_SYS) +#define AT91_USART0 AT91SAM9RL_BASE_US0 +#define AT91_USART1 AT91SAM9RL_BASE_US1 +#define AT91_USART2 AT91SAM9RL_BASE_US2 +#define AT91_USART3 AT91SAM9RL_BASE_US3 + /* * Internal Memory. diff --git a/include/asm-arm/arch-at91/uncompress.h b/include/asm-arm/arch-at91/uncompress.h index 272a7e0dc6c..f5636a8f613 100644 --- a/include/asm-arm/arch-at91/uncompress.h +++ b/include/asm-arm/arch-at91/uncompress.h @@ -22,7 +22,23 @@ #define __ASM_ARCH_UNCOMPRESS_H #include <asm/io.h> -#include <asm/arch/at91_dbgu.h> +#include <linux/atmel_serial.h> + +#if defined(CONFIG_AT91_EARLY_DBGU) +#define UART_OFFSET (AT91_DBGU + AT91_BASE_SYS) +#elif defined(CONFIG_AT91_EARLY_USART0) +#define UART_OFFSET AT91_USART0 +#elif defined(CONFIG_AT91_EARLY_USART1) +#define UART_OFFSET AT91_USART1 +#elif defined(CONFIG_AT91_EARLY_USART2) +#define UART_OFFSET AT91_USART2 +#elif defined(CONFIG_AT91_EARLY_USART3) +#define UART_OFFSET AT91_USART3 +#elif defined(CONFIG_AT91_EARLY_USART4) +#define UART_OFFSET AT91_USART4 +#elif defined(CONFIG_AT91_EARLY_USART5) +#define UART_OFFSET AT91_USART5 +#endif /* * The following code assumes the serial port has already been @@ -33,22 +49,22 @@ */ static void putc(int c) { -#ifdef AT91_DBGU - void __iomem *sys = (void __iomem *) AT91_BASE_SYS; /* physical address */ +#ifdef UART_OFFSET + void __iomem *sys = (void __iomem *) UART_OFFSET; /* physical address */ - while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY)) + while (!(__raw_readl(sys + ATMEL_US_CSR) & ATMEL_US_TXRDY)) barrier(); - __raw_writel(c, sys + AT91_DBGU_THR); + __raw_writel(c, sys + ATMEL_US_THR); #endif } static inline void flush(void) { -#ifdef AT91_DBGU - void __iomem *sys = (void __iomem *) AT91_BASE_SYS; /* physical address */ +#ifdef UART_OFFSET + void __iomem *sys = (void __iomem *) UART_OFFSET; /* physical address */ /* wait for transmission to complete */ - while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY)) + while (!(__raw_readl(sys + ATMEL_US_CSR) & ATMEL_US_TXEMPTY)) barrier(); #endif } diff --git a/include/asm-arm/arch-pxa/pxa3xx-regs.h b/include/asm-arm/arch-pxa/pxa3xx-regs.h index 66d54119757..8e1b3ead827 100644 --- a/include/asm-arm/arch-pxa/pxa3xx-regs.h +++ b/include/asm-arm/arch-pxa/pxa3xx-regs.h @@ -12,6 +12,19 @@ #ifndef __ASM_ARCH_PXA3XX_REGS_H #define __ASM_ARCH_PXA3XX_REGS_H +/* + * Service Power Management Unit (MPMU) + */ +#define PMCR __REG(0x40F50000) /* Power Manager Control Register */ +#define PSR __REG(0x40F50004) /* Power Manager S2 Status Register */ +#define PSPR __REG(0x40F50008) /* Power Manager Scratch Pad Register */ +#define PCFR __REG(0x40F5000C) /* Power Manager General Configuration Register */ +#define PWER __REG(0x40F50010) /* Power Manager Wake-up Enable Register */ +#define PWSR __REG(0x40F50014) /* Power Manager Wake-up Status Register */ +#define PECR __REG(0x40F50018) /* Power Manager EXT_WAKEUP[1:0] Control Register */ +#define DCDCSR __REG(0x40F50080) /* DC-DC Controller Status Register */ +#define PVCR __REG(0x40F50100) /* Power Manager Voltage Change Control Register */ +#define PCMD(x) __REG(0x40F50110 + ((x) << 2)) /* * Slave Power Managment Unit diff --git a/include/asm-arm/arch-realview/board-eb.h b/include/asm-arm/arch-realview/board-eb.h new file mode 100644 index 00000000000..3e437b7f425 --- /dev/null +++ b/include/asm-arm/arch-realview/board-eb.h @@ -0,0 +1,171 @@ +/* + * include/asm-arm/arch-realview/board-eb.h + * + * Copyright (C) 2007 ARM Limited + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef __ASM_ARCH_BOARD_EB_H +#define __ASM_ARCH_BOARD_EB_H + +#include <asm/arch/platform.h> + +/* + * RealView EB + ARM11MPCore peripheral addresses + */ +#ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB +#define REALVIEW_EB11MP_SCU_BASE 0x10100000 /* SCU registers */ +#define REALVIEW_EB11MP_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */ +#define REALVIEW_EB11MP_TWD_BASE 0x10100700 +#define REALVIEW_EB11MP_TWD_SIZE 0x00000100 +#define REALVIEW_EB11MP_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */ +#define REALVIEW_EB11MP_L220_BASE 0x10102000 /* L220 registers */ +#define REALVIEW_EB11MP_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */ +#else +#define REALVIEW_EB11MP_SCU_BASE 0x1F000000 /* SCU registers */ +#define REALVIEW_EB11MP_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */ +#define REALVIEW_EB11MP_TWD_BASE 0x1F000700 +#define REALVIEW_EB11MP_TWD_SIZE 0x00000100 +#define REALVIEW_EB11MP_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */ +#define REALVIEW_EB11MP_L220_BASE 0x1F002000 /* L220 registers */ +#define REALVIEW_EB11MP_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */ +#endif + +#define IRQ_EB_GIC_START 32 + +/* + * RealView EB interrupt sources + */ +#define IRQ_EB_WDOG (IRQ_EB_GIC_START + 0) /* Watchdog timer */ +#define IRQ_EB_SOFT (IRQ_EB_GIC_START + 1) /* Software interrupt */ +#define IRQ_EB_COMMRx (IRQ_EB_GIC_START + 2) /* Debug Comm Rx interrupt */ +#define IRQ_EB_COMMTx (IRQ_EB_GIC_START + 3) /* Debug Comm Tx interrupt */ +#define IRQ_EB_TIMER0_1 (IRQ_EB_GIC_START + 4) /* Timer 0 and 1 */ +#define IRQ_EB_TIMER2_3 (IRQ_EB_GIC_START + 5) /* Timer 2 and 3 */ +#define IRQ_EB_GPIO0 (IRQ_EB_GIC_START + 6) /* GPIO 0 */ +#define IRQ_EB_GPIO1 (IRQ_EB_GIC_START + 7) /* GPIO 1 */ +#define IRQ_EB_GPIO2 (IRQ_EB_GIC_START + 8) /* GPIO 2 */ + /* 9 reserved */ +#define IRQ_EB_RTC (IRQ_EB_GIC_START + 10) /* Real Time Clock */ +#define IRQ_EB_SSP (IRQ_EB_GIC_START + 11) /* Synchronous Serial Port */ +#define IRQ_EB_UART0 (IRQ_EB_GIC_START + 12) /* UART 0 on development chip */ +#define IRQ_EB_UART1 (IRQ_EB_GIC_START + 13) /* UART 1 on development chip */ +#define IRQ_EB_UART2 (IRQ_EB_GIC_START + 14) /* UART 2 on development chip */ +#define IRQ_EB_UART3 (IRQ_EB_GIC_START + 15) /* UART 3 on development chip */ +#define IRQ_EB_SCI (IRQ_EB_GIC_START + 16) /* Smart Card Interface */ +#define IRQ_EB_MMCI0A (IRQ_EB_GIC_START + 17) /* Multimedia Card 0A */ +#define IRQ_EB_MMCI0B (IRQ_EB_GIC_START + 18) /* Multimedia Card 0B */ +#define IRQ_EB_AACI (IRQ_EB_GIC_START + 19) /* Audio Codec */ +#define IRQ_EB_KMI0 (IRQ_EB_GIC_START + 20) /* Keyboard/Mouse port 0 */ +#define IRQ_EB_KMI1 (IRQ_EB_GIC_START + 21) /* Keyboard/Mouse port 1 */ +#define IRQ_EB_CHARLCD (IRQ_EB_GIC_START + 22) /* Character LCD */ +#define IRQ_EB_CLCD (IRQ_EB_GIC_START + 23) /* CLCD controller */ +#define IRQ_EB_DMA (IRQ_EB_GIC_START + 24) /* DMA controller */ +#define IRQ_EB_PWRFAIL (IRQ_EB_GIC_START + 25) /* Power failure */ +#define IRQ_EB_PISMO (IRQ_EB_GIC_START + 26) /* PISMO interface */ +#define IRQ_EB_DoC (IRQ_EB_GIC_START + 27) /* Disk on Chip memory controller */ +#define IRQ_EB_ETH (IRQ_EB_GIC_START + 28) /* Ethernet controller */ +#define IRQ_EB_USB (IRQ_EB_GIC_START + 29) /* USB controller */ +#define IRQ_EB_TSPEN (IRQ_EB_GIC_START + 30) /* Touchscreen pen */ +#define IRQ_EB_TSKPAD (IRQ_EB_GIC_START + 31) /* Touchscreen keypad */ + +/* + * RealView EB + ARM11MPCore interrupt sources (primary GIC on the core tile) + */ +#define IRQ_EB11MP_AACI (IRQ_EB_GIC_START + 0) +#define IRQ_EB11MP_TIMER0_1 (IRQ_EB_GIC_START + 1) +#define IRQ_EB11MP_TIMER2_3 (IRQ_EB_GIC_START + 2) +#define IRQ_EB11MP_USB (IRQ_EB_GIC_START + 3) +#define IRQ_EB11MP_UART0 (IRQ_EB_GIC_START + 4) +#define IRQ_EB11MP_UART1 (IRQ_EB_GIC_START + 5) +#define IRQ_EB11MP_RTC (IRQ_EB_GIC_START + 6) +#define IRQ_EB11MP_KMI0 (IRQ_EB_GIC_START + 7) +#define IRQ_EB11MP_KMI1 (IRQ_EB_GIC_START + 8) +#define IRQ_EB11MP_ETH (IRQ_EB_GIC_START + 9) +#define IRQ_EB11MP_EB_IRQ1 (IRQ_EB_GIC_START + 10) /* main GIC */ +#define IRQ_EB11MP_EB_IRQ2 (IRQ_EB_GIC_START + 11) /* tile GIC */ +#define IRQ_EB11MP_EB_FIQ1 (IRQ_EB_GIC_START + 12) /* main GIC */ +#define IRQ_EB11MP_EB_FIQ2 (IRQ_EB_GIC_START + 13) /* tile GIC */ +#define IRQ_EB11MP_MMCI0A (IRQ_EB_GIC_START + 14) +#define IRQ_EB11MP_MMCI0B (IRQ_EB_GIC_START + 15) + +#define IRQ_EB11MP_PMU_CPU0 (IRQ_EB_GIC_START + 17) +#define IRQ_EB11MP_PMU_CPU1 (IRQ_EB_GIC_START + 18) +#define IRQ_EB11MP_PMU_CPU2 (IRQ_EB_GIC_START + 19) +#define IRQ_EB11MP_PMU_CPU3 (IRQ_EB_GIC_START + 20) +#define IRQ_EB11MP_PMU_SCU0 (IRQ_EB_GIC_START + 21) +#define IRQ_EB11MP_PMU_SCU1 (IRQ_EB_GIC_START + 22) +#define IRQ_EB11MP_PMU_SCU2 (IRQ_EB_GIC_START + 23) +#define IRQ_EB11MP_PMU_SCU3 (IRQ_EB_GIC_START + 24) +#define IRQ_EB11MP_PMU_SCU4 (IRQ_EB_GIC_START + 25) +#define IRQ_EB11MP_PMU_SCU5 (IRQ_EB_GIC_START + 26) +#define IRQ_EB11MP_PMU_SCU6 (IRQ_EB_GIC_START + 27) +#define IRQ_EB11MP_PMU_SCU7 (IRQ_EB_GIC_START + 28) + +#define IRQ_EB11MP_L220_EVENT (IRQ_EB_GIC_START + 29) +#define IRQ_EB11MP_L220_SLAVE (IRQ_EB_GIC_START + 30) +#define IRQ_EB11MP_L220_DECODE (IRQ_EB_GIC_START + 31) + +#define IRQ_EB11MP_UART2 -1 +#define IRQ_EB11MP_UART3 -1 +#define IRQ_EB11MP_CLCD -1 +#define IRQ_EB11MP_DMA -1 +#define IRQ_EB11MP_WDOG -1 +#define IRQ_EB11MP_GPIO0 -1 +#define IRQ_EB11MP_GPIO1 -1 +#define IRQ_EB11MP_GPIO2 -1 +#define IRQ_EB11MP_SCI -1 +#define IRQ_EB11MP_SSP -1 + +#define NR_GIC_EB11MP 2 + +/* + * Only define NR_IRQS if less than NR_IRQS_EB + */ +#define NR_IRQS_EB (IRQ_EB_GIC_START + 96) + +#if defined(CONFIG_MACH_REALVIEW_EB) \ + && (!defined(NR_IRQS) || (NR_IRQS < NR_IRQS_EB)) +#undef NR_IRQS +#define NR_IRQS NR_IRQS_EB +#endif + +#if defined(CONFIG_REALVIEW_EB_ARM11MP) \ + && (!defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_EB11MP)) +#undef MAX_GIC_NR +#define MAX_GIC_NR NR_GIC_EB11MP +#endif + +/* + * Core tile identification (REALVIEW_SYS_PROCID) + */ +#define REALVIEW_EB_PROC_MASK 0xFF000000 +#define REALVIEW_EB_PROC_ARM7TDMI 0x00000000 +#define REALVIEW_EB_PROC_ARM9 0x02000000 +#define REALVIEW_EB_PROC_ARM11 0x04000000 +#define REALVIEW_EB_PROC_ARM11MP 0x06000000 + +#define check_eb_proc(proc_type) \ + ((readl(__io_address(REALVIEW_SYS_PROCID)) & REALVIEW_EB_PROC_MASK) \ + == proc_type) + +#ifdef CONFIG_REALVIEW_EB_ARM11MP +#define core_tile_eb11mp() check_eb_proc(REALVIEW_EB_PROC_ARM11MP) +#else +#define core_tile_eb11mp() 0 +#endif + +#endif /* __ASM_ARCH_BOARD_EB_H */ diff --git a/include/asm-arm/arch-realview/entry-macro.S b/include/asm-arm/arch-realview/entry-macro.S index 3b4e2076603..cd26306d8e5 100644 --- a/include/asm-arm/arch-realview/entry-macro.S +++ b/include/asm-arm/arch-realview/entry-macro.S @@ -14,7 +14,8 @@ .endm .macro get_irqnr_preamble, base, tmp - ldr \base, =IO_ADDRESS(REALVIEW_GIC_CPU_BASE) + ldr \base, =gic_cpu_base_addr + ldr \base, [\base] .endm .macro arch_ret_to_user, tmp1, tmp2 diff --git a/include/asm-arm/arch-realview/hardware.h b/include/asm-arm/arch-realview/hardware.h index aa78fe087ab..bad8d7ce9bf 100644 --- a/include/asm-arm/arch-realview/hardware.h +++ b/include/asm-arm/arch-realview/hardware.h @@ -23,7 +23,6 @@ #define __ASM_ARCH_HARDWARE_H #include <asm/sizes.h> -#include <asm/arch/platform.h> /* macro to get at IO space when running virtually */ #define IO_ADDRESS(x) ((((x) & 0x0effffff) | (((x) >> 4) & 0x0f000000)) + 0xf0000000) diff --git a/include/asm-arm/arch-realview/irqs.h b/include/asm-arm/arch-realview/irqs.h index 5a5db56f86b..ad0c911002f 100644 --- a/include/asm-arm/arch-realview/irqs.h +++ b/include/asm-arm/arch-realview/irqs.h @@ -19,103 +19,18 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <asm/arch/platform.h> +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H -#define IRQ_LOCALTIMER 29 -#define IRQ_LOCALWDOG 30 +#include <asm/arch/board-eb.h> -/* - * IRQ interrupts definitions are the same the INT definitions - * held within platform.h - */ -#define IRQ_GIC_START 32 -#define IRQ_WDOGINT (IRQ_GIC_START + INT_WDOGINT) -#define IRQ_SOFTINT (IRQ_GIC_START + INT_SOFTINT) -#define IRQ_COMMRx (IRQ_GIC_START + INT_COMMRx) -#define IRQ_COMMTx (IRQ_GIC_START + INT_COMMTx) -#define IRQ_TIMERINT0_1 (IRQ_GIC_START + INT_TIMERINT0_1) -#define IRQ_TIMERINT2_3 (IRQ_GIC_START + INT_TIMERINT2_3) -#define IRQ_GPIOINT0 (IRQ_GIC_START + INT_GPIOINT0) -#define IRQ_GPIOINT1 (IRQ_GIC_START + INT_GPIOINT1) -#define IRQ_GPIOINT2 (IRQ_GIC_START + INT_GPIOINT2) -#define IRQ_GPIOINT3 (IRQ_GIC_START + INT_GPIOINT3) -#define IRQ_RTCINT (IRQ_GIC_START + INT_RTCINT) -#define IRQ_SSPINT (IRQ_GIC_START + INT_SSPINT) -#define IRQ_UARTINT0 (IRQ_GIC_START + INT_UARTINT0) -#define IRQ_UARTINT1 (IRQ_GIC_START + INT_UARTINT1) -#define IRQ_UARTINT2 (IRQ_GIC_START + INT_UARTINT2) -#define IRQ_UART3 (IRQ_GIC_START + INT_UARTINT3) -#define IRQ_SCIINT (IRQ_GIC_START + INT_SCIINT) -#define IRQ_CLCDINT (IRQ_GIC_START + INT_CLCDINT) -#define IRQ_DMAINT (IRQ_GIC_START + INT_DMAINT) -#define IRQ_PWRFAILINT (IRQ_GIC_START + INT_PWRFAILINT) -#define IRQ_MBXINT (IRQ_GIC_START + INT_MBXINT) -#define IRQ_GNDINT (IRQ_GIC_START + INT_GNDINT) -#define IRQ_MMCI0B (IRQ_GIC_START + INT_MMCI0B) -#define IRQ_MMCI1B (IRQ_GIC_START + INT_MMCI1B) -#define IRQ_KMI0 (IRQ_GIC_START + INT_KMI0) -#define IRQ_KMI1 (IRQ_GIC_START + INT_KMI1) -#define IRQ_SCI3 (IRQ_GIC_START + INT_SCI3) -#define IRQ_CLCD (IRQ_GIC_START + INT_CLCD) -#define IRQ_TOUCH (IRQ_GIC_START + INT_TOUCH) -#define IRQ_KEYPAD (IRQ_GIC_START + INT_KEYPAD) -#define IRQ_DoC (IRQ_GIC_START + INT_DoC) -#define IRQ_MMCI0A (IRQ_GIC_START + INT_MMCI0A) -#define IRQ_MMCI1A (IRQ_GIC_START + INT_MMCI1A) -#define IRQ_AACI (IRQ_GIC_START + INT_AACI) -#define IRQ_ETH (IRQ_GIC_START + INT_ETH) -#define IRQ_USB (IRQ_GIC_START + INT_USB) -#define IRQ_PMU_CPU0 (IRQ_GIC_START + INT_PMU_CPU0) -#define IRQ_PMU_CPU1 (IRQ_GIC_START + INT_PMU_CPU1) -#define IRQ_PMU_CPU2 (IRQ_GIC_START + INT_PMU_CPU2) -#define IRQ_PMU_CPU3 (IRQ_GIC_START + INT_PMU_CPU3) -#define IRQ_PMU_SCU0 (IRQ_GIC_START + INT_PMU_SCU0) -#define IRQ_PMU_SCU1 (IRQ_GIC_START + INT_PMU_SCU1) -#define IRQ_PMU_SCU2 (IRQ_GIC_START + INT_PMU_SCU2) -#define IRQ_PMU_SCU3 (IRQ_GIC_START + INT_PMU_SCU3) -#define IRQ_PMU_SCU4 (IRQ_GIC_START + INT_PMU_SCU4) -#define IRQ_PMU_SCU5 (IRQ_GIC_START + INT_PMU_SCU5) -#define IRQ_PMU_SCU6 (IRQ_GIC_START + INT_PMU_SCU6) -#define IRQ_PMU_SCU7 (IRQ_GIC_START + INT_PMU_SCU7) +#define IRQ_LOCALTIMER 29 +#define IRQ_LOCALWDOG 30 -#define IRQ_EB_IRQ1 (IRQ_GIC_START + INT_EB_IRQ1) -#define IRQ_EB_IRQ2 (IRQ_GIC_START + INT_EB_IRQ2) +#define IRQ_GIC_START 32 -#define IRQMASK_WDOGINT INTMASK_WDOGINT -#define IRQMASK_SOFTINT INTMASK_SOFTINT -#define IRQMASK_COMMRx INTMASK_COMMRx -#define IRQMASK_COMMTx INTMASK_COMMTx -#define IRQMASK_TIMERINT0_1 INTMASK_TIMERINT0_1 -#define IRQMASK_TIMERINT2_3 INTMASK_TIMERINT2_3 -#define IRQMASK_GPIOINT0 INTMASK_GPIOINT0 -#define IRQMASK_GPIOINT1 INTMASK_GPIOINT1 -#define IRQMASK_GPIOINT2 INTMASK_GPIOINT2 -#define IRQMASK_GPIOINT3 INTMASK_GPIOINT3 -#define IRQMASK_RTCINT INTMASK_RTCINT -#define IRQMASK_SSPINT INTMASK_SSPINT -#define IRQMASK_UARTINT0 INTMASK_UARTINT0 -#define IRQMASK_UARTINT1 INTMASK_UARTINT1 -#define IRQMASK_UARTINT2 INTMASK_UARTINT2 -#define IRQMASK_SCIINT INTMASK_SCIINT -#define IRQMASK_CLCDINT INTMASK_CLCDINT -#define IRQMASK_DMAINT INTMASK_DMAINT -#define IRQMASK_PWRFAILINT INTMASK_PWRFAILINT -#define IRQMASK_MBXINT INTMASK_MBXINT -#define IRQMASK_GNDINT INTMASK_GNDINT -#define IRQMASK_MMCI0B INTMASK_MMCI0B -#define IRQMASK_MMCI1B INTMASK_MMCI1B -#define IRQMASK_KMI0 INTMASK_KMI0 -#define IRQMASK_KMI1 INTMASK_KMI1 -#define IRQMASK_SCI3 INTMASK_SCI3 -#define IRQMASK_UART3 INTMASK_UART3 -#define IRQMASK_CLCD INTMASK_CLCD -#define IRQMASK_TOUCH INTMASK_TOUCH -#define IRQMASK_KEYPAD INTMASK_KEYPAD -#define IRQMASK_DoC INTMASK_DoC -#define IRQMASK_MMCI0A INTMASK_MMCI0A -#define IRQMASK_MMCI1A INTMASK_MMCI1A -#define IRQMASK_AACI INTMASK_AACI -#define IRQMASK_ETH INTMASK_ETH -#define IRQMASK_USB INTMASK_USB +#ifndef NR_IRQS +#error "NR_IRQS not defined by the board-specific files" +#endif -#define NR_IRQS (IRQ_GIC_START + 96) +#endif diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h index 6e0eab95a3a..4fd351b5e4a 100644 --- a/include/asm-arm/arch-realview/platform.h +++ b/include/asm-arm/arch-realview/platform.h @@ -18,8 +18,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __address_h -#define __address_h 1 +#ifndef __ASM_ARCH_PLATFORM_H +#define __ASM_ARCH_PLATFORM_H /* * Memory definitions @@ -81,11 +81,12 @@ #define REALVIEW_SYS_24MHz_OFFSET 0x5C #define REALVIEW_SYS_MISC_OFFSET 0x60 #define REALVIEW_SYS_IOSEL_OFFSET 0x70 -#define REALVIEW_SYS_TEST_OSC0_OFFSET 0x80 -#define REALVIEW_SYS_TEST_OSC1_OFFSET 0x84 -#define REALVIEW_SYS_TEST_OSC2_OFFSET 0x88 -#define REALVIEW_SYS_TEST_OSC3_OFFSET 0x8C -#define REALVIEW_SYS_TEST_OSC4_OFFSET 0x90 +#define REALVIEW_SYS_PROCID_OFFSET 0x84 +#define REALVIEW_SYS_TEST_OSC0_OFFSET 0xC0 +#define REALVIEW_SYS_TEST_OSC1_OFFSET 0xC4 +#define REALVIEW_SYS_TEST_OSC2_OFFSET 0xC8 +#define REALVIEW_SYS_TEST_OSC3_OFFSET 0xCC +#define REALVIEW_SYS_TEST_OSC4_OFFSET 0xD0 #define REALVIEW_SYS_BASE 0x10000000 #define REALVIEW_SYS_ID (REALVIEW_SYS_BASE + REALVIEW_SYS_ID_OFFSET) @@ -114,6 +115,7 @@ #define REALVIEW_SYS_24MHz (REALVIEW_SYS_BASE + REALVIEW_SYS_24MHz_OFFSET) #define REALVIEW_SYS_MISC (REALVIEW_SYS_BASE + REALVIEW_SYS_MISC_OFFSET) #define REALVIEW_SYS_IOSEL (REALVIEW_SYS_BASE + REALVIEW_SYS_IOSEL_OFFSET) +#define REALVIEW_SYS_PROCID (REALVIEW_SYS_BASE + REALVIEW_SYS_PROCID_OFFSET) #define REALVIEW_SYS_TEST_OSC0 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC0_OFFSET) #define REALVIEW_SYS_TEST_OSC1 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC1_OFFSET) #define REALVIEW_SYS_TEST_OSC2 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC2_OFFSET) @@ -203,30 +205,8 @@ /* Reserved 0x1001A000 - 0x1001FFFF */ #define REALVIEW_CLCD_BASE 0x10020000 /* CLCD */ #define REALVIEW_DMAC_BASE 0x10030000 /* DMA controller */ -#ifndef CONFIG_REALVIEW_MPCORE #define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */ #define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */ -#else -#ifdef CONFIG_REALVIEW_MPCORE_REVB -#define REALVIEW_MPCORE_SCU_BASE 0x10100000 /* SCU registers */ -#define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */ -#define REALVIEW_TWD_BASE 0x10100700 -#define REALVIEW_TWD_SIZE 0x00000100 -#define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */ -#define REALVIEW_MPCORE_L220_BASE 0x10102000 /* L220 registers */ -#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */ -#else -#define REALVIEW_MPCORE_SCU_BASE 0x1F000000 /* SCU registers */ -#define REALVIEW_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */ -#define REALVIEW_TWD_BASE 0x1F000700 -#define REALVIEW_TWD_SIZE 0x00000100 -#define REALVIEW_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */ -#define REALVIEW_MPCORE_L220_BASE 0x1F002000 /* L220 registers */ -#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */ -#endif -#define REALVIEW_GIC1_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */ -#define REALVIEW_GIC1_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */ -#endif #define REALVIEW_SMC_BASE 0x10080000 /* SMC */ /* Reserved 0x10090000 - 0x100EFFFF */ @@ -283,134 +263,6 @@ #define REALVIEW_INTREG_OFFSET 0x8 /* Interrupt control */ #define REALVIEW_DECODE_OFFSET 0xC /* Fitted logic modules */ -/* ------------------------------------------------------------------------ - * Interrupts - bit assignment (primary) - * ------------------------------------------------------------------------ - */ -#ifndef CONFIG_REALVIEW_MPCORE -#define INT_WDOGINT 0 /* Watchdog timer */ -#define INT_SOFTINT 1 /* Software interrupt */ -#define INT_COMMRx 2 /* Debug Comm Rx interrupt */ -#define INT_COMMTx 3 /* Debug Comm Tx interrupt */ -#define INT_TIMERINT0_1 4 /* Timer 0 and 1 */ -#define INT_TIMERINT2_3 5 /* Timer 2 and 3 */ -#define INT_GPIOINT0 6 /* GPIO 0 */ -#define INT_GPIOINT1 7 /* GPIO 1 */ -#define INT_GPIOINT2 8 /* GPIO 2 */ -/* 9 reserved */ -#define INT_RTCINT 10 /* Real Time Clock */ -#define INT_SSPINT 11 /* Synchronous Serial Port */ -#define INT_UARTINT0 12 /* UART 0 on development chip */ -#define INT_UARTINT1 13 /* UART 1 on development chip */ -#define INT_UARTINT2 14 /* UART 2 on development chip */ -#define INT_UARTINT3 15 /* UART 3 on development chip */ -#define INT_SCIINT 16 /* Smart Card Interface */ -#define INT_MMCI0A 17 /* Multimedia Card 0A */ -#define INT_MMCI0B 18 /* Multimedia Card 0B */ -#define INT_AACI 19 /* Audio Codec */ -#define INT_KMI0 20 /* Keyboard/Mouse port 0 */ -#define INT_KMI1 21 /* Keyboard/Mouse port 1 */ -#define INT_CHARLCD 22 /* Character LCD */ -#define INT_CLCDINT 23 /* CLCD controller */ -#define INT_DMAINT 24 /* DMA controller */ -#define INT_PWRFAILINT 25 /* Power failure */ -#define INT_PISMO 26 -#define INT_DoC 27 /* Disk on Chip memory controller */ -#define INT_ETH 28 /* Ethernet controller */ -#define INT_USB 29 /* USB controller */ -#define INT_TSPENINT 30 /* Touchscreen pen */ -#define INT_TSKPADINT 31 /* Touchscreen keypad */ - -#else - -#define MAX_GIC_NR 2 - -#define INT_AACI 0 -#define INT_TIMERINT0_1 1 -#define INT_TIMERINT2_3 2 -#define INT_USB 3 -#define INT_UARTINT0 4 -#define INT_UARTINT1 5 -#define INT_RTCINT 6 -#define INT_KMI0 7 -#define INT_KMI1 8 -#define INT_ETH 9 -#define INT_EB_IRQ1 10 /* main GIC */ -#define INT_EB_IRQ2 11 /* tile GIC */ -#define INT_EB_FIQ1 12 /* main GIC */ -#define INT_EB_FIQ2 13 /* tile GIC */ -#define INT_MMCI0A 14 -#define INT_MMCI0B 15 - -#define INT_PMU_CPU0 17 -#define INT_PMU_CPU1 18 -#define INT_PMU_CPU2 19 -#define INT_PMU_CPU3 20 -#define INT_PMU_SCU0 21 -#define INT_PMU_SCU1 22 -#define INT_PMU_SCU2 23 -#define INT_PMU_SCU3 24 -#define INT_PMU_SCU4 25 -#define INT_PMU_SCU5 26 -#define INT_PMU_SCU6 27 -#define INT_PMU_SCU7 28 - -#define INT_L220_EVENT 29 -#define INT_L220_SLAVE 30 -#define INT_L220_DECODE 31 - -#define INT_UARTINT2 -1 -#define INT_UARTINT3 -1 -#define INT_CLCDINT -1 -#define INT_DMAINT -1 -#define INT_WDOGINT -1 -#define INT_GPIOINT0 -1 -#define INT_GPIOINT1 -1 -#define INT_GPIOINT2 -1 -#define INT_SCIINT -1 -#define INT_SSPINT -1 -#endif - -/* - * Interrupt bit positions - * - */ -#define INTMASK_WDOGINT (1 << INT_WDOGINT) -#define INTMASK_SOFTINT (1 << INT_SOFTINT) -#define INTMASK_COMMRx (1 << INT_COMMRx) -#define INTMASK_COMMTx (1 << INT_COMMTx) -#define INTMASK_TIMERINT0_1 (1 << INT_TIMERINT0_1) -#define INTMASK_TIMERINT2_3 (1 << INT_TIMERINT2_3) -#define INTMASK_GPIOINT0 (1 << INT_GPIOINT0) -#define INTMASK_GPIOINT1 (1 << INT_GPIOINT1) -#define INTMASK_GPIOINT2 (1 << INT_GPIOINT2) -#define INTMASK_RTCINT (1 << INT_RTCINT) -#define INTMASK_SSPINT (1 << INT_SSPINT) -#define INTMASK_UARTINT0 (1 << INT_UARTINT0) -#define INTMASK_UARTINT1 (1 << INT_UARTINT1) -#define INTMASK_UARTINT2 (1 << INT_UARTINT2) -#define INTMASK_UARTINT3 (1 << INT_UARTINT3) -#define INTMASK_SCIINT (1 << INT_SCIINT) -#define INTMASK_MMCI0A (1 << INT_MMCI0A) -#define INTMASK_MMCI0B (1 << INT_MMCI0B) -#define INTMASK_AACI (1 << INT_AACI) -#define INTMASK_KMI0 (1 << INT_KMI0) -#define INTMASK_KMI1 (1 << INT_KMI1) -#define INTMASK_CHARLCD (1 << INT_CHARLCD) -#define INTMASK_CLCDINT (1 << INT_CLCDINT) -#define INTMASK_DMAINT (1 << INT_DMAINT) -#define INTMASK_PWRFAILINT (1 << INT_PWRFAILINT) -#define INTMASK_PISMO (1 << INT_PISMO) -#define INTMASK_DoC (1 << INT_DoC) -#define INTMASK_ETH (1 << INT_ETH) -#define INTMASK_USB (1 << INT_USB) -#define INTMASK_TSPENINT (1 << INT_TSPENINT) -#define INTMASK_TSKPADINT (1 << INT_TSKPADINT) - -#define MAXIRQNUM 31 -#define MAXFIQNUM 31 -#define MAXSWINUM 31 - /* * Application Flash * @@ -463,6 +315,4 @@ #define REALVIEW_CSR_BASE 0x10000000 #define REALVIEW_CSR_SIZE 0x10000000 -#endif - -/* END */ +#endif /* __ASM_ARCH_PLATFORM_H */ diff --git a/include/asm-arm/arch-realview/scu.h b/include/asm-arm/arch-realview/scu.h index cc293640178..08b3db883c3 100644 --- a/include/asm-arm/arch-realview/scu.h +++ b/include/asm-arm/arch-realview/scu.h @@ -1,8 +1,8 @@ #ifndef __ASMARM_ARCH_SCU_H #define __ASMARM_ARCH_SCU_H -#include <asm/arch/platform.h> +#include <asm/arch/board-eb.h> -#define SCU_BASE REALVIEW_MPCORE_SCU_BASE +#define SCU_BASE REALVIEW_EB11MP_SCU_BASE #endif diff --git a/include/asm-arm/arch-realview/uncompress.h b/include/asm-arm/arch-realview/uncompress.h index f05631d7674..3d5c2db07a2 100644 --- a/include/asm-arm/arch-realview/uncompress.h +++ b/include/asm-arm/arch-realview/uncompress.h @@ -19,6 +19,8 @@ */ #include <asm/hardware.h> +#include <asm/arch/platform.h> + #define AMBA_UART_DR (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x00)) #define AMBA_UART_LCRH (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x2c)) #define AMBA_UART_CR (*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x30)) diff --git a/include/asm-arm/hardware/arm_twd.h b/include/asm-arm/hardware/arm_twd.h index 131d5b40e07..e521b70713c 100644 --- a/include/asm-arm/hardware/arm_twd.h +++ b/include/asm-arm/hardware/arm_twd.h @@ -1,7 +1,7 @@ #ifndef __ASM_HARDWARE_TWD_H #define __ASM_HARDWARE_TWD_H -#define TWD_TIMER_LOAD 0x00 +#define TWD_TIMER_LOAD 0x00 #define TWD_TIMER_COUNTER 0x04 #define TWD_TIMER_CONTROL 0x08 #define TWD_TIMER_INTSTAT 0x0C @@ -13,4 +13,9 @@ #define TWD_WDOG_RESETSTAT 0x30 #define TWD_WDOG_DISABLE 0x34 +#define TWD_TIMER_CONTROL_ENABLE (1 << 0) +#define TWD_TIMER_CONTROL_ONESHOT (0 << 1) +#define TWD_TIMER_CONTROL_PERIODIC (1 << 1) +#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2) + #endif diff --git a/include/asm-arm/kexec.h b/include/asm-arm/kexec.h index 46dcc4d0b9b..1ee17b6951d 100644 --- a/include/asm-arm/kexec.h +++ b/include/asm-arm/kexec.h @@ -16,6 +16,9 @@ #define KEXEC_BOOT_PARAMS_SIZE 1536 +#define KEXEC_ARM_ATAGS_OFFSET 0x1000 +#define KEXEC_ARM_ZIMAGE_OFFSET 0x8000 + #ifndef __ASSEMBLY__ struct kimage; diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h index f67acce387e..af99636db40 100644 --- a/include/asm-arm/smp.h +++ b/include/asm-arm/smp.h @@ -61,6 +61,11 @@ extern void smp_cross_call(cpumask_t callmap); extern void smp_send_timer(void); /* + * Broadcast a clock event to other CPUs. + */ +extern void smp_timer_broadcast(cpumask_t mask); + +/* * Boot a secondary CPU, and assign it the specified idle task. * This also gives us the initial stack to use for this CPU. */ @@ -96,11 +101,12 @@ extern void platform_cpu_die(unsigned int cpu); extern int platform_cpu_kill(unsigned int cpu); extern void platform_cpu_enable(unsigned int cpu); -#ifdef CONFIG_LOCAL_TIMERS /* - * Setup a local timer interrupt for a CPU. + * Local timer interrupt handling function (can be IPI'ed). */ -extern void local_timer_setup(unsigned int cpu); +extern void local_timer_interrupt(void); + +#ifdef CONFIG_LOCAL_TIMERS /* * Stop a local timer interrupt. @@ -114,10 +120,6 @@ extern int local_timer_ack(void); #else -static inline void local_timer_setup(unsigned int cpu) -{ -} - static inline void local_timer_stop(unsigned int cpu) { } @@ -125,6 +127,11 @@ static inline void local_timer_stop(unsigned int cpu) #endif /* + * Setup a local timer interrupt for a CPU. + */ +extern void local_timer_setup(unsigned int cpu); + +/* * show local interrupt info */ extern void show_local_irqs(struct seq_file *); diff --git a/drivers/serial/atmel_serial.h b/include/linux/atmel_serial.h index e0141776517..fd6833764d7 100644 --- a/drivers/serial/atmel_serial.h +++ b/include/linux/atmel_serial.h @@ -1,5 +1,5 @@ /* - * drivers/serial/atmel_serial.h + * include/linux/atmel_serial.h * * Copyright (C) 2005 Ivan Kokshaysky * Copyright (C) SAN People |