diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/Kconfig | 4 | ||||
-rw-r--r-- | arch/arm/common/gic.c | 1 | ||||
-rw-r--r-- | arch/arm/kernel/calls.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/entry-common.S | 4 | ||||
-rw-r--r-- | arch/arm/kernel/sys_arm.c | 10 | ||||
-rw-r--r-- | arch/arm/kernel/time.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-ixp4xx/common.c | 155 | ||||
-rw-r--r-- | arch/arm/mach-ixp4xx/coyote-pci.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-ixp4xx/coyote-setup.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-ixp4xx/gtwx5715-pci.c | 28 | ||||
-rw-r--r-- | arch/arm/mach-ixp4xx/gtwx5715-setup.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-ixp4xx/ixdp425-pci.c | 12 | ||||
-rw-r--r-- | arch/arm/mach-ixp4xx/ixdp425-setup.c | 13 | ||||
-rw-r--r-- | arch/arm/mach-ixp4xx/ixdpg425-pci.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-pxa/time.c | 58 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/clock.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2440-clock.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/time.c | 68 | ||||
-rw-r--r-- | arch/arm/mm/alignment.c | 70 | ||||
-rw-r--r-- | arch/arm/mm/mm-armv.c | 30 |
20 files changed, 310 insertions, 198 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4bf0e8737e1..68dfdba71d7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -365,8 +365,8 @@ config NO_IDLE_HZ Please note that dynamic tick may affect the accuracy of timekeeping on some platforms depending on the implementation. - Currently at least OMAP platform is known to have accurate - timekeeping with dynamic tick. + Currently at least OMAP, PXA2xx and SA11x0 platforms are known + to have accurate timekeeping with dynamic tick. config ARCH_DISCONTIGMEM_ENABLE bool diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 51dbf5489b6..d7499071755 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -24,6 +24,7 @@ #include <linux/kernel.h> #include <linux/list.h> #include <linux/smp.h> +#include <linux/cpumask.h> #include <asm/irq.h> #include <asm/io.h> diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 2b6b4c786e6..db07ce42b3b 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -284,7 +284,7 @@ __syscall_start: .long sys_fstatfs64 .long sys_tgkill .long sys_utimes -/* 270 */ .long sys_fadvise64_64 +/* 270 */ .long sys_arm_fadvise64_64_wrapper .long sys_pciconfig_iobase .long sys_pciconfig_read .long sys_pciconfig_write diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 3f8d0e3aefa..6281d488ac9 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -265,6 +265,10 @@ sys_futex_wrapper: str r5, [sp, #4] @ push sixth arg b sys_futex +sys_arm_fadvise64_64_wrapper: + str r5, [sp, #4] @ push r5 to stack + b sys_arm_fadvise64_64 + /* * Note: off_4k (r5) is always units of 4K. If we can't do the requested * offset, we return EINVAL. diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index f897ce2ccf0..42629ff84f5 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -311,3 +311,13 @@ long execve(const char *filename, char **argv, char **envp) return ret; } EXPORT_SYMBOL(execve); + +/* + * Since loff_t is a 64 bit type we avoid a lot of ABI hastle + * with a different argument ordering. + */ +asmlinkage long sys_arm_fadvise64_64(int fd, int advice, + loff_t offset, loff_t len) +{ + return sys_fadvise64_64(fd, offset, len, advice); +} diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 1b7fcd50c3e..8880482dcbf 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -433,10 +433,12 @@ void timer_dyn_reprogram(void) { struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; - write_seqlock(&xtime_lock); - if (dyn_tick->state & DYN_TICK_ENABLED) - dyn_tick->reprogram(next_timer_interrupt() - jiffies); - write_sequnlock(&xtime_lock); + if (dyn_tick) { + write_seqlock(&xtime_lock); + if (dyn_tick->state & DYN_TICK_ENABLED) + dyn_tick->reprogram(next_timer_interrupt() - jiffies); + write_sequnlock(&xtime_lock); + } } static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 04490a9f8f6..0422e906cc9 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -38,90 +38,6 @@ #include <asm/mach/irq.h> #include <asm/mach/time.h> -enum ixp4xx_irq_type { - IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE -}; -static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type); - -/************************************************************************* - * GPIO acces functions - *************************************************************************/ - -/* - * Configure GPIO line for input, interrupt, or output operation - * - * TODO: Enable/disable the irq_desc based on interrupt or output mode. - * TODO: Should these be named ixp4xx_gpio_? - */ -void gpio_line_config(u8 line, u32 style) -{ - static const int gpio2irq[] = { - 6, 7, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 - }; - u32 enable; - volatile u32 *int_reg; - u32 int_style; - enum ixp4xx_irq_type irq_type; - - enable = *IXP4XX_GPIO_GPOER; - - if (style & IXP4XX_GPIO_OUT) { - enable &= ~((1) << line); - } else if (style & IXP4XX_GPIO_IN) { - enable |= ((1) << line); - - switch (style & IXP4XX_GPIO_INTSTYLE_MASK) - { - case (IXP4XX_GPIO_ACTIVE_HIGH): - int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH; - irq_type = IXP4XX_IRQ_LEVEL; - break; - case (IXP4XX_GPIO_ACTIVE_LOW): - int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW; - irq_type = IXP4XX_IRQ_LEVEL; - break; - case (IXP4XX_GPIO_RISING_EDGE): - int_style = IXP4XX_GPIO_STYLE_RISING_EDGE; - irq_type = IXP4XX_IRQ_EDGE; - break; - case (IXP4XX_GPIO_FALLING_EDGE): - int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE; - irq_type = IXP4XX_IRQ_EDGE; - break; - case (IXP4XX_GPIO_TRANSITIONAL): - int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL; - irq_type = IXP4XX_IRQ_EDGE; - break; - default: - int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH; - irq_type = IXP4XX_IRQ_LEVEL; - break; - } - - if (style & IXP4XX_GPIO_INTSTYLE_MASK) - ixp4xx_config_irq(gpio2irq[line], irq_type); - - if (line >= 8) { /* pins 8-15 */ - line -= 8; - int_reg = IXP4XX_GPIO_GPIT2R; - } - else { /* pins 0-7 */ - int_reg = IXP4XX_GPIO_GPIT1R; - } - - /* Clear the style for the appropriate pin */ - *int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR << - (line * IXP4XX_GPIO_STYLE_SIZE)); - - /* Set the new style */ - *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE)); - } - - *IXP4XX_GPIO_GPOER = enable; -} - -EXPORT_SYMBOL(gpio_line_config); - /************************************************************************* * IXP4xx chipset I/O mapping *************************************************************************/ @@ -165,6 +81,69 @@ void __init ixp4xx_map_io(void) * (be it PCI or something else) configures that GPIO line * as an IRQ. **************************************************************************/ +enum ixp4xx_irq_type { + IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE +}; + +static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type); + +/* + * IRQ -> GPIO mapping table + */ +static int irq2gpio[32] = { + -1, -1, -1, -1, -1, -1, 0, 1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, -1, -1, +}; + +static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type) +{ + int line = irq2gpio[irq]; + u32 int_style; + enum ixp4xx_irq_type irq_type; + volatile u32 *int_reg; + + /* + * Only for GPIO IRQs + */ + if (line < 0) + return -EINVAL; + + if (type & IRQT_BOTHEDGE) { + int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL; + irq_type = IXP4XX_IRQ_EDGE; + } else if (type & IRQT_RISING) { + int_style = IXP4XX_GPIO_STYLE_RISING_EDGE; + irq_type = IXP4XX_IRQ_EDGE; + } else if (type & IRQT_FALLING) { + int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE; + irq_type = IXP4XX_IRQ_EDGE; + } else if (type & IRQT_HIGH) { + int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH; + irq_type = IXP4XX_IRQ_LEVEL; + } else if (type & IRQT_LOW) { + int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW; + irq_type = IXP4XX_IRQ_LEVEL; + } + + ixp4xx_config_irq(irq, irq_type); + + if (line >= 8) { /* pins 8-15 */ + line -= 8; + int_reg = IXP4XX_GPIO_GPIT2R; + } else { /* pins 0-7 */ + int_reg = IXP4XX_GPIO_GPIT1R; + } + + /* Clear the style for the appropriate pin */ + *int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR << + (line * IXP4XX_GPIO_STYLE_SIZE)); + + /* Set the new style */ + *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE)); +} + static void ixp4xx_irq_mask(unsigned int irq) { if (cpu_is_ixp46x() && irq >= 32) @@ -183,12 +162,6 @@ static void ixp4xx_irq_unmask(unsigned int irq) static void ixp4xx_irq_ack(unsigned int irq) { - static int irq2gpio[32] = { - -1, -1, -1, -1, -1, -1, 0, 1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, -1, -1, - }; int line = (irq < 32) ? irq2gpio[irq] : -1; if (line >= 0) @@ -209,12 +182,14 @@ static struct irqchip ixp4xx_irq_level_chip = { .ack = ixp4xx_irq_mask, .mask = ixp4xx_irq_mask, .unmask = ixp4xx_irq_level_unmask, + .type = ixp4xx_set_irq_type }; static struct irqchip ixp4xx_irq_edge_chip = { .ack = ixp4xx_irq_ack, .mask = ixp4xx_irq_mask, .unmask = ixp4xx_irq_unmask, + .type = ixp4xx_set_irq_type }; static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type) diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c index afafb42ae12..60de8a94cff 100644 --- a/arch/arm/mach-ixp4xx/coyote-pci.c +++ b/arch/arm/mach-ixp4xx/coyote-pci.c @@ -30,11 +30,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); void __init coyote_pci_preinit(void) { - gpio_line_config(COYOTE_PCI_SLOT0_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - - gpio_line_config(COYOTE_PCI_SLOT1_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); + set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQT_LOW); + set_irq_type(IRQ_COYOTE_PCI_SLOT1, IRQT_LOW); gpio_line_isr_clear(COYOTE_PCI_SLOT0_PIN); gpio_line_isr_clear(COYOTE_PCI_SLOT1_PIN); diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c index 411ea999619..8b2f2532245 100644 --- a/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/arch/arm/mach-ixp4xx/coyote-setup.c @@ -24,11 +24,6 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> -void __init coyote_map_io(void) -{ - ixp4xx_map_io(); -} - static struct flash_platform_data coyote_flash_data = { .map_name = "cfi_probe", .width = 2, @@ -107,7 +102,7 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, - .map_io = coyote_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, @@ -125,7 +120,7 @@ MACHINE_START(IXDPG425, "Intel IXDPG425") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, - .map_io = coyote_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c index b18035824e3..a66484b63d3 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c @@ -35,26 +35,20 @@ extern void ixp4xx_pci_preinit(void); extern int ixp4xx_setup(int nr, struct pci_sys_data *sys); extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); - /* - * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h - * Slot 0 isn't actually populated with a card connector but - * we initialize it anyway in case a future version has the - * slot populated or someone with good soldering skills has - * some free time. - */ - - -static void gtwx5715_init_gpio(u8 pin, u32 style) -{ - gpio_line_config(pin, style | IXP4XX_GPIO_ACTIVE_LOW); - - if (style & IXP4XX_GPIO_IN) gpio_line_isr_clear(pin); -} +/* + * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h + * Slot 0 isn't actually populated with a card connector but + * we initialize it anyway in case a future version has the + * slot populated or someone with good soldering skills has + * some free time. + */ void __init gtwx5715_pci_preinit(void) { - gtwx5715_init_gpio(GTWX5715_PCI_SLOT0_INTA_GPIO, IXP4XX_GPIO_IN); - gtwx5715_init_gpio(GTWX5715_PCI_SLOT1_INTA_GPIO, IXP4XX_GPIO_IN); + set_irq_type(GTWX5715_PCI_SLOT0_INTA_IRQ, IRQT_LOW); + set_irq_type(GTWX5715_PCI_SLOT0_INTB_IRQ, IRQT_LOW); + set_irq_type(GTWX5715_PCI_SLOT1_INTA_IRQ, IRQT_LOW); + set_irq_type(GTWX5715_PCI_SLOT1_INTB_IRQ, IRQT_LOW); ixp4xx_pci_preinit(); } diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c index 333459d6aa4..3fd92c5cbaa 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c @@ -101,12 +101,6 @@ static struct platform_device gtwx5715_uart_device = { .resource = gtwx5715_uart_resources, }; - -void __init gtwx5715_map_io(void) -{ - ixp4xx_map_io(); -} - static struct flash_platform_data gtwx5715_flash_data = { .map_name = "cfi_probe", .width = 2, @@ -144,7 +138,7 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_UART2_BASE_PHYS, .io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc, - .map_io = gtwx5715_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c index c2ab9ebb598..f9a1d3e7d69 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-pci.c +++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c @@ -27,14 +27,10 @@ void __init ixdp425_pci_preinit(void) { - gpio_line_config(IXDP425_PCI_INTA_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - gpio_line_config(IXDP425_PCI_INTB_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - gpio_line_config(IXDP425_PCI_INTC_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - gpio_line_config(IXDP425_PCI_INTD_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); + set_irq_type(IRQ_IXDP425_PCI_INTA, IRQT_LOW); + set_irq_type(IRQ_IXDP425_PCI_INTB, IRQT_LOW); + set_irq_type(IRQ_IXDP425_PCI_INTC, IRQT_LOW); + set_irq_type(IRQ_IXDP425_PCI_INTD, IRQT_LOW); gpio_line_isr_clear(IXDP425_PCI_INTA_PIN); gpio_line_isr_clear(IXDP425_PCI_INTB_PIN); diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index fa0646c8693..6c14ff3c23a 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -24,11 +24,6 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> -void __init ixdp425_map_io(void) -{ - ixp4xx_map_io(); -} - static struct flash_platform_data ixdp425_flash_data = { .map_name = "cfi_probe", .width = 2, @@ -133,7 +128,7 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, - .map_io = ixdp425_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, @@ -145,7 +140,7 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, - .map_io = ixdp425_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, @@ -157,7 +152,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, - .map_io = ixdp425_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, @@ -176,7 +171,7 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, - .map_io = ixdp425_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c index ce4563f0067..fe5e7660de1 100644 --- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c +++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c @@ -29,8 +29,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); void __init ixdpg425_pci_preinit(void) { - gpio_line_config(6, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - gpio_line_config(7, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); + set_irq_type(IRQ_IXP4XX_GPIO6, IRQT_LOW); + set_irq_type(IRQ_IXP4XX_GPIO7, IRQT_LOW); gpio_line_isr_clear(6); gpio_line_isr_clear(7); diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 6e5202154f9..7dad3f1465e 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -70,6 +70,11 @@ static unsigned long pxa_gettimeoffset (void) return usec; } +#ifdef CONFIG_NO_IDLE_HZ +static unsigned long initial_match; +static int match_posponed; +#endif + static irqreturn_t pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { @@ -77,11 +82,19 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) write_seqlock(&xtime_lock); +#ifdef CONFIG_NO_IDLE_HZ + if (match_posponed) { + match_posponed = 0; + OSMR0 = initial_match; + } +#endif + /* Loop until we get ahead of the free running timer. * This ensures an exact clock tick count and time accuracy. - * IRQs are disabled inside the loop to ensure coherence between - * lost_ticks (updated in do_timer()) and the match reg value, so we - * can use do_gettimeofday() from interrupt handlers. + * Since IRQs are disabled at this point, coherence between + * lost_ticks(updated in do_timer()) and the match reg value is + * ensured, hence we can use do_gettimeofday() from interrupt + * handlers. * * HACK ALERT: it seems that the PXA timer regs aren't updated right * away in all cases when a write occurs. We therefore compare with @@ -126,6 +139,42 @@ static void __init pxa_timer_init(void) OSCR = 0; /* initialize free-running timer, force first match */ } +#ifdef CONFIG_NO_IDLE_HZ +static int pxa_dyn_tick_enable_disable(void) +{ + /* nothing to do */ + return 0; +} + +static void pxa_dyn_tick_reprogram(unsigned long ticks) +{ + if (ticks > 1) { + initial_match = OSMR0; + OSMR0 = initial_match + ticks * LATCH; + match_posponed = 1; + } +} + +static irqreturn_t +pxa_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + if (match_posponed) { + match_posponed = 0; + OSMR0 = initial_match; + if ( (signed long)(initial_match - OSCR) <= 8 ) + return pxa_timer_interrupt(irq, dev_id, regs); + } + return IRQ_NONE; +} + +static struct dyn_tick_timer pxa_dyn_tick = { + .enable = pxa_dyn_tick_enable_disable, + .disable = pxa_dyn_tick_enable_disable, + .reprogram = pxa_dyn_tick_reprogram, + .handler = pxa_dyn_tick_handler, +}; +#endif + #ifdef CONFIG_PM static unsigned long osmr[4], oier; @@ -161,4 +210,7 @@ struct sys_timer pxa_timer = { .suspend = pxa_timer_suspend, .resume = pxa_timer_resume, .offset = pxa_gettimeoffset, +#ifdef CONFIG_NO_IDLE_HZ + .dyn_tick = &pxa_dyn_tick, +#endif }; diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c index 9a66050e887..f5960826875 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/mach-s3c2410/clock.c @@ -388,6 +388,7 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, unsigned long hclk, unsigned long pclk) { + unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); struct clk *clkp = init_clocks; int ptr; int ret; @@ -446,5 +447,13 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, } } + /* show the clock-slow value */ + + printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n", + print_mhz(xtal / ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))), + (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast", + (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", + (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); + return 0; } diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c index b018a1f680c..c67e0979aec 100644 --- a/arch/arm/mach-s3c2410/s3c2440-clock.c +++ b/arch/arm/mach-s3c2410/s3c2440-clock.c @@ -68,6 +68,7 @@ static struct clk s3c2440_clk_ac97 = { static int s3c2440_clk_add(struct sys_device *sysdev) { unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); + unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); struct clk *clk_h; struct clk *clk_p; struct clk *clk_xtal; @@ -80,8 +81,9 @@ static int s3c2440_clk_add(struct sys_device *sysdev) s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal->rate); - printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n", - print_mhz(s3c2440_clk_upll.rate)); + printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz, DVS %s\n", + print_mhz(s3c2440_clk_upll.rate), + (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off"); clk_p = clk_get(NULL, "pclk"); clk_h = clk_get(NULL, "hclk"); diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 0eeb3616ffe..47e0420623f 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -70,15 +70,11 @@ static unsigned long sa1100_gettimeoffset (void) return usec; } -/* - * We will be entered with IRQs enabled. - * - * Loop until we get ahead of the free running timer. - * This ensures an exact clock tick count and time accuracy. - * IRQs are disabled inside the loop to ensure coherence between - * lost_ticks (updated in do_timer()) and the match reg value, so we - * can use do_gettimeofday() from interrupt handlers. - */ +#ifdef CONFIG_NO_IDLE_HZ +static unsigned long initial_match; +static int match_posponed; +#endif + static irqreturn_t sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { @@ -86,6 +82,21 @@ sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) write_seqlock(&xtime_lock); +#ifdef CONFIG_NO_IDLE_HZ + if (match_posponed) { + match_posponed = 0; + OSMR0 = initial_match; + } +#endif + + /* + * Loop until we get ahead of the free running timer. + * This ensures an exact clock tick count and time accuracy. + * Since IRQs are disabled at this point, coherence between + * lost_ticks(updated in do_timer()) and the match reg value is + * ensured, hence we can use do_gettimeofday() from interrupt + * handlers. + */ do { timer_tick(regs); OSSR = OSSR_M0; /* Clear match on timer 0 */ @@ -120,6 +131,42 @@ static void __init sa1100_timer_init(void) OSCR = 0; /* initialize free-running timer, force first match */ } +#ifdef CONFIG_NO_IDLE_HZ +static int sa1100_dyn_tick_enable_disable(void) +{ + /* nothing to do */ + return 0; +} + +static void sa1100_dyn_tick_reprogram(unsigned long ticks) +{ + if (ticks > 1) { + initial_match = OSMR0; + OSMR0 = initial_match + ticks * LATCH; + match_posponed = 1; + } +} + +static irqreturn_t +sa1100_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + if (match_posponed) { + match_posponed = 0; + OSMR0 = initial_match; + if ((signed long)(initial_match - OSCR) <= 0) + return sa1100_timer_interrupt(irq, dev_id, regs); + } + return IRQ_NONE; +} + +static struct dyn_tick_timer sa1100_dyn_tick = { + .enable = sa1100_dyn_tick_enable_disable, + .disable = sa1100_dyn_tick_enable_disable, + .reprogram = sa1100_dyn_tick_reprogram, + .handler = sa1100_dyn_tick_handler, +}; +#endif + #ifdef CONFIG_PM unsigned long osmr[4], oier; @@ -156,4 +203,7 @@ struct sys_timer sa1100_timer = { .suspend = sa1100_timer_suspend, .resume = sa1100_timer_resume, .offset = sa1100_gettimeoffset, +#ifdef CONFIG_NO_IDLE_HZ + .dyn_tick = &sa1100_dyn_tick, +#endif }; diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 81f4a8a2d34..4b39d867ac1 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -45,7 +45,7 @@ #define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0) -#define LDSTH_I_BIT(i) (i & (1 << 22)) /* half-word immed */ +#define LDSTHD_I_BIT(i) (i & (1 << 22)) /* double/half-word immed */ #define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */ #define RN_BITS(i) ((i >> 16) & 15) /* Rn */ @@ -68,6 +68,7 @@ static unsigned long ai_sys; static unsigned long ai_skipped; static unsigned long ai_half; static unsigned long ai_word; +static unsigned long ai_dword; static unsigned long ai_multi; static int ai_usermode; @@ -93,6 +94,8 @@ proc_alignment_read(char *page, char **start, off_t off, int count, int *eof, p += sprintf(p, "Skipped:\t%lu\n", ai_skipped); p += sprintf(p, "Half:\t\t%lu\n", ai_half); p += sprintf(p, "Word:\t\t%lu\n", ai_word); + if (cpu_architecture() >= CPU_ARCH_ARMv5TE) + p += sprintf(p, "DWord:\t\t%lu\n", ai_dword); p += sprintf(p, "Multi:\t\t%lu\n", ai_multi); p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode, usermode_action[ai_usermode]); @@ -283,12 +286,6 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r { unsigned int rd = RD_BITS(instr); - if ((instr & 0x01f00ff0) == 0x01000090) - goto swp; - - if ((instr & 0x90) != 0x90 || (instr & 0x60) == 0) - goto bad; - ai_half += 1; if (user_mode(regs)) @@ -323,10 +320,47 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r return TYPE_LDST; - swp: - printk(KERN_ERR "Alignment trap: not handling swp instruction\n"); - bad: - return TYPE_ERROR; + fault: + return TYPE_FAULT; +} + +static int +do_alignment_ldrdstrd(unsigned long addr, unsigned long instr, + struct pt_regs *regs) +{ + unsigned int rd = RD_BITS(instr); + + ai_dword += 1; + + if (user_mode(regs)) + goto user; + + if ((instr & 0xf0) == 0xd0) { + unsigned long val; + get32_unaligned_check(val, addr); + regs->uregs[rd] = val; + get32_unaligned_check(val, addr+4); + regs->uregs[rd+1] = val; + } else { + put32_unaligned_check(regs->uregs[rd], addr); + put32_unaligned_check(regs->uregs[rd+1], addr+4); + } + + return TYPE_LDST; + + user: + if ((instr & 0xf0) == 0xd0) { + unsigned long val; + get32t_unaligned_check(val, addr); + regs->uregs[rd] = val; + get32t_unaligned_check(val, addr+4); + regs->uregs[rd+1] = val; + } else { + put32t_unaligned_check(regs->uregs[rd], addr); + put32t_unaligned_check(regs->uregs[rd+1], addr+4); + } + + return TYPE_LDST; fault: return TYPE_FAULT; @@ -617,12 +651,20 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) regs->ARM_pc += thumb_mode(regs) ? 2 : 4; switch (CODING_BITS(instr)) { - case 0x00000000: /* ldrh or strh */ - if (LDSTH_I_BIT(instr)) + case 0x00000000: /* 3.13.4 load/store instruction extensions */ + if (LDSTHD_I_BIT(instr)) offset.un = (instr & 0xf00) >> 4 | (instr & 15); else offset.un = regs->uregs[RM_BITS(instr)]; - handler = do_alignment_ldrhstrh; + + if ((instr & 0x000000f0) == 0x000000b0 || /* LDRH, STRH */ + (instr & 0x001000f0) == 0x001000f0) /* LDRSH */ + handler = do_alignment_ldrhstrh; + else if ((instr & 0x001000f0) == 0x000000d0 || /* LDRD */ + (instr & 0x001000f0) == 0x000000f0) /* STRD */ + handler = do_alignment_ldrdstrd; + else + goto bad; break; case 0x04000000: /* ldr or str immediate */ diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index 3c655c54e23..d125a3dc061 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -275,11 +275,9 @@ alloc_init_supersection(unsigned long virt, unsigned long phys, int prot) int i; for (i = 0; i < 16; i += 1) { - alloc_init_section(virt, phys & SUPERSECTION_MASK, - prot | PMD_SECT_SUPER); + alloc_init_section(virt, phys, prot | PMD_SECT_SUPER); virt += (PGDIR_SIZE / 2); - phys += (PGDIR_SIZE / 2); } } @@ -297,14 +295,10 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg pte_t *ptep; if (pmd_none(*pmdp)) { - unsigned long pmdval; ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * sizeof(pte_t)); - pmdval = __pa(ptep) | prot_l1; - pmdp[0] = __pmd(pmdval); - pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); - flush_pmd_entry(pmdp); + __pmd_populate(pmdp, __pa(ptep) | prot_l1); } ptep = pte_offset_kernel(pmdp, virt); @@ -459,7 +453,7 @@ static void __init build_mem_type_table(void) for (i = 0; i < 16; i++) { unsigned long v = pgprot_val(protection_map[i]); - v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot; + v = (v & ~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot; protection_map[i] = __pgprot(v); } @@ -583,23 +577,23 @@ static void __init create_mapping(struct map_desc *md) */ void setup_mm_for_reboot(char mode) { - unsigned long pmdval; + unsigned long base_pmdval; pgd_t *pgd; - pmd_t *pmd; int i; - int cpu_arch = cpu_architecture(); if (current->mm && current->mm->pgd) pgd = current->mm->pgd; else pgd = init_mm.pgd; - for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++) { - pmdval = (i << PGDIR_SHIFT) | - PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | - PMD_TYPE_SECT; - if (cpu_arch <= CPU_ARCH_ARMv5TEJ) - pmdval |= PMD_BIT4; + base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT; + if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ) + base_pmdval |= PMD_BIT4; + + for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) { + unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval; + pmd_t *pmd; + pmd = pmd_off(pgd, i << PGDIR_SHIFT); pmd[0] = __pmd(pmdval); pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1))); |