diff options
Diffstat (limited to 'arch/arm')
175 files changed, 1586 insertions, 2435 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c9f69e0b1f55..9dd61014864b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -297,6 +297,7 @@ config ARCH_BCMRING depends on MMU select CPU_V6 select ARM_AMBA + select ARM_TIMER_SP804 select CLKDEV_LOOKUP select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB @@ -366,6 +367,7 @@ config ARCH_MXC select GENERIC_CLOCKEVENTS select ARCH_REQUIRE_GPIOLIB select CLKDEV_LOOKUP + select CLKSRC_MMIO select HAVE_SCHED_CLOCK help Support for Freescale MXC/iMX-based family of processors @@ -375,11 +377,13 @@ config ARCH_MXS select GENERIC_CLOCKEVENTS select ARCH_REQUIRE_GPIOLIB select CLKDEV_LOOKUP + select CLKSRC_MMIO help Support for Freescale MXS-based family of processors config ARCH_NETX bool "Hilscher NetX based" + select CLKSRC_MMIO select CPU_ARM926T select ARM_VIC select GENERIC_CLOCKEVENTS @@ -447,6 +451,7 @@ config ARCH_IXP2000 config ARCH_IXP4XX bool "IXP4xx-based" depends on MMU + select CLKSRC_MMIO select CPU_XSCALE select GENERIC_GPIO select GENERIC_CLOCKEVENTS @@ -487,6 +492,7 @@ config ARCH_LOKI config ARCH_LPC32XX bool "NXP LPC32XX" + select CLKSRC_MMIO select CPU_ARM926T select ARCH_REQUIRE_GPIOLIB select HAVE_IDE @@ -561,6 +567,7 @@ config ARCH_W90X900 select CPU_ARM926T select ARCH_REQUIRE_GPIOLIB select CLKDEV_LOOKUP + select CLKSRC_MMIO select GENERIC_CLOCKEVENTS help Support for Nuvoton (Winbond logic dept.) ARM9 processor, @@ -582,6 +589,7 @@ config ARCH_NUC93X config ARCH_TEGRA bool "NVIDIA Tegra" select CLKDEV_LOOKUP + select CLKSRC_MMIO select GENERIC_TIME select GENERIC_CLOCKEVENTS select GENERIC_GPIO @@ -607,6 +615,7 @@ config ARCH_PXA select ARCH_MTD_XIP select ARCH_HAS_CPUFREQ select CLKDEV_LOOKUP + select CLKSRC_MMIO select ARCH_REQUIRE_GPIOLIB select GENERIC_CLOCKEVENTS select HAVE_SCHED_CLOCK @@ -657,6 +666,7 @@ config ARCH_RPC config ARCH_SA1100 bool "SA1100-based" + select CLKSRC_MMIO select CPU_SA1100 select ISA select ARCH_SPARSEMEM_ENABLE @@ -793,6 +803,7 @@ config ARCH_SHARK config ARCH_TCC_926 bool "Telechips TCC ARM926-based systems" + select CLKSRC_MMIO select CPU_ARM926T select HAVE_CLK select CLKDEV_LOOKUP @@ -803,6 +814,7 @@ config ARCH_TCC_926 config ARCH_U300 bool "ST-Ericsson U300 Series" depends on MMU + select CLKSRC_MMIO select CPU_ARM926T select HAVE_SCHED_CLOCK select HAVE_TCM @@ -864,6 +876,7 @@ config PLAT_SPEAR select ARM_AMBA select ARCH_REQUIRE_GPIOLIB select CLKDEV_LOOKUP + select CLKSRC_MMIO select GENERIC_CLOCKEVENTS select HAVE_CLK help @@ -1021,6 +1034,7 @@ config PLAT_IOP config PLAT_ORION bool + select CLKSRC_MMIO select HAVE_SCHED_CLOCK config PLAT_PXA @@ -1031,6 +1045,7 @@ config PLAT_VERSATILE config ARM_TIMER_SP804 bool + select CLKSRC_MMIO source arch/arm/mm/Kconfig diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 8ebbb511c783..0c6852d93506 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -74,7 +74,7 @@ ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT) ZBSSADDR := $(CONFIG_ZBOOT_ROM_BSS) else ZTEXTADDR := 0 -ZBSSADDR := ALIGN(4) +ZBSSADDR := ALIGN(8) endif SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index adf583cd0c35..49f5b2eaaa87 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -179,15 +179,14 @@ not_angel: bl cache_on restart: adr r0, LC0 - ldmia r0, {r1, r2, r3, r5, r6, r9, r11, r12} - ldr sp, [r0, #32] + ldmia r0, {r1, r2, r3, r6, r9, r11, r12} + ldr sp, [r0, #28] /* * We might be running at a different address. We need * to fix up various pointers. */ sub r0, r0, r1 @ calculate the delta offset - add r5, r5, r0 @ _start add r6, r6, r0 @ _edata #ifndef CONFIG_ZBOOT_ROM @@ -206,31 +205,40 @@ restart: adr r0, LC0 /* * Check to see if we will overwrite ourselves. * r4 = final kernel address - * r5 = start of this image * r9 = size of decompressed image * r10 = end of this image, including bss/stack/malloc space if non XIP * We basically want: - * r4 >= r10 -> OK - * r4 + image length <= r5 -> OK + * r4 - 16k page directory >= r10 -> OK + * r4 + image length <= current position (pc) -> OK */ + add r10, r10, #16384 cmp r4, r10 bhs wont_overwrite add r10, r4, r9 - cmp r10, r5 + ARM( cmp r10, pc ) + THUMB( mov lr, pc ) + THUMB( cmp r10, lr ) bls wont_overwrite /* * Relocate ourselves past the end of the decompressed kernel. - * r5 = start of this image * r6 = _edata * r10 = end of the decompressed kernel * Because we always copy ahead, we need to do it from the end and go * backward in case the source and destination overlap. */ - /* Round up to next 256-byte boundary. */ - add r10, r10, #256 + /* + * Bump to the next 256-byte boundary with the size of + * the relocation code added. This avoids overwriting + * ourself when the offset is small. + */ + add r10, r10, #((reloc_code_end - restart + 256) & ~255) bic r10, r10, #255 + /* Get start of code we want to copy and align it down. */ + adr r5, restart + bic r5, r5, #31 + sub r9, r6, r5 @ size to copy add r9, r9, #31 @ rounded up to a multiple bic r9, r9, #31 @ ... of 32 bytes @@ -245,6 +253,11 @@ restart: adr r0, LC0 /* Preserve offset to relocated code. */ sub r6, r9, r6 +#ifndef CONFIG_ZBOOT_ROM + /* cache_clean_flush may use the stack, so relocate it */ + add sp, sp, r6 +#endif + bl cache_clean_flush adr r0, BSYM(restart) @@ -333,7 +346,6 @@ not_relocated: mov r0, #0 LC0: .word LC0 @ r1 .word __bss_start @ r2 .word _end @ r3 - .word _start @ r5 .word _edata @ r6 .word _image_size @ r9 .word _got_start @ r11 @@ -1062,6 +1074,7 @@ memdump: mov r12, r0 #endif .ltorg +reloc_code_end: .align .section ".stack", "aw", %nobits diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in index 5309909d7282..ea80abe78844 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.in +++ b/arch/arm/boot/compressed/vmlinux.lds.in @@ -54,6 +54,7 @@ SECTIONS .bss : { *(.bss) } _end = .; + . = ALIGN(8); /* the stack must be 64-bit aligned */ .stack : { *(.stack) } .stab 0 : { *(.stab) } diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index a12b33c0dc42..9c49a46a2b7a 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -185,14 +185,6 @@ static struct sa1111_dev_info sa1111_devices[] = { }, }; -void __init sa1111_adjust_zones(unsigned long *size, unsigned long *holes) -{ - unsigned int sz = SZ_1M >> PAGE_SHIFT; - - size[1] = size[0] - sz; - size[0] = sz; -} - /* * SA1111 interrupt support. Since clearing an IRQ while there are * active IRQs causes the interrupt output to pulse, the upper levels diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index 6ef3342153b9..41df47875122 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c @@ -18,53 +18,67 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/clk.h> #include <linux/clocksource.h> #include <linux/clockchips.h> +#include <linux/err.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/io.h> #include <asm/hardware/arm_timer.h> -/* - * These timers are currently always setup to be clocked at 1MHz. - */ -#define TIMER_FREQ_KHZ (1000) -#define TIMER_RELOAD (TIMER_FREQ_KHZ * 1000 / HZ) +static long __init sp804_get_clock_rate(const char *name) +{ + struct clk *clk; + long rate; + int err; + + clk = clk_get_sys("sp804", name); + if (IS_ERR(clk)) { + pr_err("sp804: %s clock not found: %d\n", name, + (int)PTR_ERR(clk)); + return PTR_ERR(clk); + } -static void __iomem *clksrc_base; + err = clk_enable(clk); + if (err) { + pr_err("sp804: %s clock failed to enable: %d\n", name, err); + clk_put(clk); + return err; + } -static cycle_t sp804_read(struct clocksource *cs) -{ - return ~readl(clksrc_base + TIMER_VALUE); -} + rate = clk_get_rate(clk); + if (rate < 0) { + pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate); + clk_disable(clk); + clk_put(clk); + } -static struct clocksource clocksource_sp804 = { - .name = "timer3", - .rating = 200, - .read = sp804_read, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; + return rate; +} -void __init sp804_clocksource_init(void __iomem *base) +void __init sp804_clocksource_init(void __iomem *base, const char *name) { - struct clocksource *cs = &clocksource_sp804; + long rate = sp804_get_clock_rate(name); - clksrc_base = base; + if (rate < 0) + return; /* setup timer 0 as free-running clocksource */ - writel(0, clksrc_base + TIMER_CTRL); - writel(0xffffffff, clksrc_base + TIMER_LOAD); - writel(0xffffffff, clksrc_base + TIMER_VALUE); + writel(0, base + TIMER_CTRL); + writel(0xffffffff, base + TIMER_LOAD); + writel(0xffffffff, base + TIMER_VALUE); writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, - clksrc_base + TIMER_CTRL); + base + TIMER_CTRL); - clocksource_register_khz(cs, TIMER_FREQ_KHZ); + clocksource_mmio_init(base + TIMER_VALUE, name, + rate, 200, 32, clocksource_mmio_readl_down); } static void __iomem *clkevt_base; +static unsigned long clkevt_reload; /* * IRQ handler for the timer @@ -90,7 +104,7 @@ static void sp804_set_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - writel(TIMER_RELOAD, clkevt_base + TIMER_LOAD); + writel(clkevt_reload, clkevt_base + TIMER_LOAD); ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; break; @@ -120,7 +134,6 @@ static int sp804_set_next_event(unsigned long next, } static struct clock_event_device sp804_clockevent = { - .name = "timer0", .shift = 32, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_mode = sp804_set_mode, @@ -136,17 +149,24 @@ static struct irqaction sp804_timer_irq = { .dev_id = &sp804_clockevent, }; -void __init sp804_clockevents_init(void __iomem *base, unsigned int timer_irq) +void __init sp804_clockevents_init(void __iomem *base, unsigned int irq, + const char *name) { struct clock_event_device *evt = &sp804_clockevent; + long rate = sp804_get_clock_rate(name); + + if (rate < 0) + return; clkevt_base = base; + clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ); - evt->irq = timer_irq; - evt->mult = div_sc(TIMER_FREQ_KHZ, NSEC_PER_MSEC, evt->shift); + evt->name = name; + evt->irq = irq; + evt->mult = div_sc(rate, NSEC_PER_SEC, evt->shift); evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt); evt->min_delta_ns = clockevent_delta2ns(0xf, evt); - setup_irq(timer_irq, &sp804_timer_irq); + setup_irq(irq, &sp804_timer_irq); clockevents_register_device(evt); } diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index 113085a77123..7aa4262ada7a 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c @@ -22,17 +22,16 @@ #include <linux/init.h> #include <linux/list.h> #include <linux/io.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/device.h> #include <linux/amba/bus.h> #include <asm/mach/irq.h> #include <asm/hardware/vic.h> -#if defined(CONFIG_PM) +#ifdef CONFIG_PM /** * struct vic_device - VIC PM device - * @sysdev: The system device which is registered. * @irq: The IRQ number for the base of the VIC. * @base: The register base for the VIC. * @resume_sources: A bitmask of interrupts for resume. @@ -43,8 +42,6 @@ * @protect: Save for VIC_PROTECT. */ struct vic_device { - struct sys_device sysdev; - void __iomem *base; int irq; u32 resume_sources; @@ -59,11 +56,6 @@ struct vic_device { static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; static int vic_id; - -static inline struct vic_device *to_vic(struct sys_device *sys) -{ - return container_of(sys, struct vic_device, sysdev); -} #endif /* CONFIG_PM */ /** @@ -85,10 +77,9 @@ static void vic_init2(void __iomem *base) writel(32, base + VIC_PL190_DEF_VECT_ADDR); } -#if defined(CONFIG_PM) -static int vic_class_resume(struct sys_device *dev) +#ifdef CONFIG_PM +static void resume_one_vic(struct vic_device *vic) { - struct vic_device *vic = to_vic(dev); void __iomem *base = vic->base; printk(KERN_DEBUG "%s: resuming vic at %p\n", __func__, base); @@ -107,13 +98,18 @@ static int vic_class_resume(struct sys_device *dev) writel(vic->soft_int, base + VIC_INT_SOFT); writel(~vic->soft_int, base + VIC_INT_SOFT_CLEAR); +} - return 0; +static void vic_resume(void) +{ + int id; + + for (id = vic_id - 1; id >= 0; id--) + resume_one_vic(vic_devices + id); } -static int vic_class_suspend(struct sys_device *dev, pm_message_t state) +static void suspend_one_vic(struct vic_device *vic) { - struct vic_device *vic = to_vic(dev); void __iomem *base = vic->base; printk(KERN_DEBUG "%s: suspending vic at %p\n", __func__, base); @@ -128,14 +124,21 @@ static int vic_class_suspend(struct sys_device *dev, pm_message_t state) writel(vic->resume_irqs, base + VIC_INT_ENABLE); writel(~vic->resume_irqs, base + VIC_INT_ENABLE_CLEAR); +} + +static int vic_suspend(void) +{ + int id; + + for (id = 0; id < vic_id; id++) + suspend_one_vic(vic_devices + id); return 0; } -struct sysdev_class vic_class = { - .name = "vic", - .suspend = vic_class_suspend, - .resume = vic_class_resume, +struct syscore_ops vic_syscore_ops = { + .suspend = vic_suspend, + .resume = vic_resume, }; /** @@ -147,30 +150,8 @@ struct sysdev_class vic_class = { */ static int __init vic_pm_init(void) { - struct vic_device *dev = vic_devices; - int err; - int id; - - if (vic_id == 0) - return 0; - - err = sysdev_class_register(&vic_class); - if (err) { - printk(KERN_ERR "%s: cannot register class\n", __func__); - return err; - } - - for (id = 0; id < vic_id; id++, dev++) { - dev->sysdev.id = id; - dev->sysdev.cls = &vic_class; - - err = sysdev_register(&dev->sysdev); - if (err) { - printk(KERN_ERR "%s: failed to register device\n", - __func__); - return err; - } - } + if (vic_id > 0) + register_syscore_ops(&vic_syscore_ops); return 0; } diff --git a/arch/arm/configs/at91x40_defconfig b/arch/arm/configs/at91x40_defconfig new file mode 100644 index 000000000000..c55e9212fcbb --- /dev/null +++ b/arch/arm/configs/at91x40_defconfig @@ -0,0 +1,48 @@ +CONFIG_EXPERIMENTAL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_EMBEDDED=y +# CONFIG_HOTPLUG is not set +# CONFIG_ELF_CORE is not set +# CONFIG_FUTEX is not set +# CONFIG_TIMERFD is not set +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_MMU is not set +CONFIG_ARCH_AT91=y +CONFIG_ARCH_AT91X40=y +CONFIG_MACH_AT91EB01=y +CONFIG_AT91_EARLY_USART0=y +CONFIG_CPU_ARM7TDMI=y +CONFIG_SET_MEM_PARAM=y +CONFIG_DRAM_BASE=0x01000000 +CONFIG_DRAM_SIZE=0x00400000 +CONFIG_FLASH_MEM_BASE=0x01400000 +CONFIG_PROCESSOR_ID=0x14000040 +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_BINFMT_FLAT=y +# CONFIG_SUSPEND is not set +# CONFIG_FW_LOADER is not set +CONFIG_MTD=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_RAM=y +CONFIG_MTD_ROM=y +CONFIG_BLK_DEV_RAM=y +# CONFIG_INPUT is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_DEVKMEM is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_EXT2_FS=y +# CONFIG_DNOTIFY is not set +CONFIG_ROMFS_FS=y +# CONFIG_ENABLE_MUST_CHECK is not set diff --git a/arch/arm/configs/realview-smp_defconfig b/arch/arm/configs/realview-smp_defconfig index 5ca7a61f7c01..abe61bf379d2 100644 --- a/arch/arm/configs/realview-smp_defconfig +++ b/arch/arm/configs/realview-smp_defconfig @@ -38,7 +38,7 @@ CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_ARM_INTEGRATOR=y +CONFIG_MTD_PHYSMAP=y CONFIG_ARM_CHARLCD=y CONFIG_NETDEVICES=y CONFIG_SMSC_PHY=y diff --git a/arch/arm/configs/realview_defconfig b/arch/arm/configs/realview_defconfig index fcaa60328051..7079cbe898a8 100644 --- a/arch/arm/configs/realview_defconfig +++ b/arch/arm/configs/realview_defconfig @@ -37,7 +37,7 @@ CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_INTELEXT=y CONFIG_MTD_CFI_AMDSTD=y -CONFIG_MTD_ARM_INTEGRATOR=y +CONFIG_MTD_PHYSMAP=y CONFIG_ARM_CHARLCD=y CONFIG_NETDEVICES=y CONFIG_SMSC_PHY=y diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig index 0ce710f47500..cdd4d2bd3962 100644 --- a/arch/arm/configs/versatile_defconfig +++ b/arch/arm/configs/versatile_defconfig @@ -32,7 +32,7 @@ CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_ADV_OPTIONS=y CONFIG_MTD_CFI_INTELEXT=y -CONFIG_MTD_ARM_INTEGRATOR=y +CONFIG_MTD_PHYSMAP=y CONFIG_BLK_DEV_RAM=y CONFIG_EEPROM_LEGACY=m CONFIG_NETDEVICES=y diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h index ca51143f97f1..42005542932b 100644 --- a/arch/arm/include/asm/dma.h +++ b/arch/arm/include/asm/dma.h @@ -6,8 +6,10 @@ /* * This is the maximum virtual address which can be DMA'd from. */ -#ifndef MAX_DMA_ADDRESS +#ifndef ARM_DMA_ZONE_SIZE #define MAX_DMA_ADDRESS 0xffffffff +#else +#define MAX_DMA_ADDRESS (PAGE_OFFSET + ARM_DMA_ZONE_SIZE) #endif #ifdef CONFIG_ISA_DMA_API diff --git a/arch/arm/include/asm/hardware/timer-sp.h b/arch/arm/include/asm/hardware/timer-sp.h index 21e75e30d497..4384d81eee79 100644 --- a/arch/arm/include/asm/hardware/timer-sp.h +++ b/arch/arm/include/asm/hardware/timer-sp.h @@ -1,2 +1,2 @@ -void sp804_clocksource_init(void __iomem *); -void sp804_clockevents_init(void __iomem *, unsigned int); +void sp804_clocksource_init(void __iomem *, const char *); +void sp804_clockevents_init(void __iomem *, unsigned int, const char *); diff --git a/arch/arm/include/asm/i8253.h b/arch/arm/include/asm/i8253.h new file mode 100644 index 000000000000..70656b69d5ce --- /dev/null +++ b/arch/arm/include/asm/i8253.h @@ -0,0 +1,15 @@ +#ifndef __ASMARM_I8253_H +#define __ASMARM_I8253_H + +/* i8253A PIT registers */ +#define PIT_MODE 0x43 +#define PIT_CH0 0x40 + +#define PIT_LATCH ((PIT_TICK_RATE + HZ / 2) / HZ) + +extern raw_spinlock_t i8253_lock; + +#define outb_pit outb_p +#define inb_pit inb_p + +#endif diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h index bb8a19bd5822..e46bdd0097eb 100644 --- a/arch/arm/include/asm/kprobes.h +++ b/arch/arm/include/asm/kprobes.h @@ -39,10 +39,13 @@ typedef u32 kprobe_opcode_t; struct kprobe; typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *); +typedef unsigned long (kprobe_check_cc)(unsigned long); + /* Architecture specific copy of original instruction. */ struct arch_specific_insn { kprobe_opcode_t *insn; kprobe_insn_handler_t *insn_handler; + kprobe_check_cc *insn_check_cc; }; struct prev_kprobe { diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h index 883f6be5117a..d5adaae5ee2c 100644 --- a/arch/arm/include/asm/mach/time.h +++ b/arch/arm/include/asm/mach/time.h @@ -34,7 +34,6 @@ * timer interrupt which may be pending. */ struct sys_timer { - struct sys_device dev; void (*init)(void); void (*suspend)(void); void (*resume)(void); diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 431077c5a867..af44a8fb3480 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -209,14 +209,10 @@ static inline unsigned long __phys_to_virt(unsigned long x) * allocations. This must be the smallest DMA mask in the system, * so a successful GFP_DMA allocation will always satisfy this. */ -#ifndef ISA_DMA_THRESHOLD +#ifndef ARM_DMA_ZONE_SIZE #define ISA_DMA_THRESHOLD (0xffffffffULL) -#endif - -#ifndef arch_adjust_zones -#define arch_adjust_zones(size,holes) do { } while (0) -#elif !defined(CONFIG_ZONE_DMA) -#error "custom arch_adjust_zones() requires CONFIG_ZONE_DMA" +#else +#define ISA_DMA_THRESHOLD (PHYS_OFFSET + ARM_DMA_ZONE_SIZE - 1) #endif /* diff --git a/arch/arm/include/asm/sizes.h b/arch/arm/include/asm/sizes.h index 316bb2b2be3d..154b89b81d3e 100644 --- a/arch/arm/include/asm/sizes.h +++ b/arch/arm/include/asm/sizes.h @@ -16,44 +16,6 @@ /* Size definitions * Copyright (C) ARM Limited 1998. All rights reserved. */ +#include <asm-generic/sizes.h> -#ifndef __sizes_h -#define __sizes_h 1 - -/* handy sizes */ -#define SZ_16 0x00000010 -#define SZ_32 0x00000020 -#define SZ_64 0x00000040 -#define SZ_128 0x00000080 -#define SZ_256 0x00000100 -#define SZ_512 0x00000200 - -#define SZ_1K 0x00000400 -#define SZ_2K 0x00000800 -#define SZ_4K 0x00001000 -#define SZ_8K 0x00002000 -#define SZ_16K 0x00004000 -#define SZ_32K 0x00008000 -#define SZ_64K 0x00010000 -#define SZ_128K 0x00020000 -#define SZ_256K 0x00040000 -#define SZ_512K 0x00080000 - -#define SZ_1M 0x00100000 -#define SZ_2M 0x00200000 -#define SZ_4M 0x00400000 -#define SZ_8M 0x00800000 -#define SZ_16M 0x01000000 -#define SZ_32M 0x02000000 -#define SZ_48M 0x03000000 -#define SZ_64M 0x04000000 -#define SZ_128M 0x08000000 -#define SZ_256M 0x10000000 -#define SZ_512M 0x20000000 - -#define SZ_1G 0x40000000 -#define SZ_2G 0x80000000 - -#endif - -/* END */ +#define SZ_48M (SZ_32M + SZ_16M) diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index 96ed521f2408..a87664f54f93 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -14,8 +14,6 @@ #include <linux/cpumask.h> #include <linux/thread_info.h> -#include <mach/smp.h> - #ifndef CONFIG_SMP # error "<asm/smp.h> included in non-SMP build" #endif @@ -47,9 +45,9 @@ extern void smp_init_cpus(void); /* - * Raise an IPI cross call on CPUs in callmap. + * Provide a function to raise an IPI cross call on CPUs in callmap. */ -extern void smp_cross_call(const struct cpumask *mask, int ipi); +extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int)); /* * Boot a secondary CPU, and assign it the specified idle task. diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 885be097769d..832888d0c20c 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -159,7 +159,7 @@ extern unsigned int user_debug; #include <mach/barriers.h> #elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP) #define mb() do { dsb(); outer_sync(); } while (0) -#define rmb() dmb() +#define rmb() dsb() #define wmb() mb() #else #include <asm/memory.h> diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c index 23891317dc4b..15eeff6aea0e 100644 --- a/arch/arm/kernel/kprobes-decode.c +++ b/arch/arm/kernel/kprobes-decode.c @@ -34,9 +34,6 @@ * * *) If the PC is written to by the instruction, the * instruction must be fully simulated in software. - * If it is a conditional instruction, the handler - * will use insn[0] to copy its condition code to - * set r0 to 1 and insn[1] to "mov pc, lr" to return. * * *) Otherwise, a modified form of the instruction is * directly executed. Its handler calls the @@ -68,13 +65,17 @@ #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25) +#define is_r15(insn, bitpos) (((insn) & (0xf << bitpos)) == (0xf << bitpos)) + +/* + * Test if load/store instructions writeback the address register. + * if P (bit 24) == 0 or W (bit 21) == 1 + */ +#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000) + #define PSR_fs (PSR_f|PSR_s) #define KPROBE_RETURN_INSTRUCTION 0xe1a0f00e /* mov pc, lr */ -#define SET_R0_TRUE_INSTRUCTION 0xe3a00001 /* mov r0, #1 */ - -#define truecc_insn(insn) (((insn) & 0xf0000000) | \ - (SET_R0_TRUE_INSTRUCTION & 0x0fffffff)) typedef long (insn_0arg_fn_t)(void); typedef long (insn_1arg_fn_t)(long); @@ -419,14 +420,10 @@ insnslot_llret_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr, static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs) { - insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; kprobe_opcode_t insn = p->opcode; long iaddr = (long)p->addr; int disp = branch_displacement(insn); - if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn)) - return; - if (insn & (1 << 24)) regs->ARM_lr = iaddr + 4; @@ -446,14 +443,10 @@ static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs) static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs) { - insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; kprobe_opcode_t insn = p->opcode; int rm = insn & 0xf; long rmv = regs->uregs[rm]; - if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn)) - return; - if (insn & (1 << 5)) regs->ARM_lr = (long)p->addr + 4; @@ -463,9 +456,16 @@ static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs) regs->ARM_cpsr |= PSR_T_BIT; } +static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs) +{ + kprobe_opcode_t insn = p->opcode; + int rd = (insn >> 12) & 0xf; + unsigned long mask = 0xf8ff03df; /* Mask out execution state */ + regs->uregs[rd] = regs->ARM_cpsr & mask; +} + static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs) { - insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; kprobe_opcode_t insn = p->opcode; int rn = (insn >> 16) & 0xf; int lbit = insn & (1 << 20); @@ -476,9 +476,6 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs) int reg_bit_vector; int reg_count; - if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn)) - return; - reg_count = 0; reg_bit_vector = insn & 0xffff; while (reg_bit_vector) { @@ -510,11 +507,6 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs) static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs) { - insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; - - if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn)) - return; - regs->ARM_pc = (long)p->addr + str_pc_offset; simulate_ldm1stm1(p, regs); regs->ARM_pc = (long)p->addr + 4; @@ -525,24 +517,16 @@ static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs) regs->uregs[12] = regs->uregs[13]; } -static void __kprobes emulate_ldcstc(struct kprobe *p, struct pt_regs *regs) -{ - insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rn = (insn >> 16) & 0xf; - long rnv = regs->uregs[rn]; - - /* Save Rn in case of writeback. */ - regs->uregs[rn] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn); -} - static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs) { insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0]; kprobe_opcode_t insn = p->opcode; + long ppc = (long)p->addr + 8; int rd = (insn >> 12) & 0xf; int rn = (insn >> 16) & 0xf; int rm = insn & 0xf; /* rm may be invalid, don't care. */ + long rmv = (rm == 15) ? ppc : regs->uregs[rm]; + long rnv = (rn == 15) ? ppc : regs->uregs[rn]; /* Not following the C calling convention here, so need asm(). */ __asm__ __volatile__ ( @@ -554,29 +538,36 @@ static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs) "str r0, %[rn] \n\t" /* in case of writeback */ "str r2, %[rd0] \n\t" "str r3, %[rd1] \n\t" - : [rn] "+m" (regs->uregs[rn]), + : [rn] "+m" (rnv), [rd0] "=m" (regs->uregs[rd]), [rd1] "=m" (regs->uregs[rd+1]) - : [rm] "m" (regs->uregs[rm]), + : [rm] "m" (rmv), [cpsr] "r" (regs->ARM_cpsr), [i_fn] "r" (i_fn) : "r0", "r1", "r2", "r3", "lr", "cc" ); + if (is_writeback(insn)) + regs->uregs[rn] = rnv; } static void __kprobes emulate_strd(struct kprobe *p, struct pt_regs *regs) { insn_4arg_fn_t *i_fn = (insn_4arg_fn_t *)&p->ainsn.insn[0]; kprobe_opcode_t insn = p->opcode; + long ppc = (long)p->addr + 8; int rd = (insn >> 12) & 0xf; int rn = (insn >> 16) & 0xf; int rm = insn & 0xf; - long rnv = regs->uregs[rn]; - long rmv = regs->uregs[rm]; /* rm/rmv may be invalid, don't care. */ + long rnv = (rn == 15) ? ppc : regs->uregs[rn]; + /* rm/rmv may be invalid, don't care. */ + long rmv = (rm == 15) ? ppc : regs->uregs[rm]; + long rnv_wb; - regs->uregs[rn] = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd], + rnv_wb = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd], regs->uregs[rd+1], regs->ARM_cpsr, i_fn); + if (is_writeback(insn)) + regs->uregs[rn] = rnv_wb; } static void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs) @@ -630,31 +621,6 @@ static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs) regs->uregs[rn] = rnv_wb; /* Save Rn in case of writeback. */ } -static void __kprobes emulate_mrrc(struct kprobe *p, struct pt_regs *regs) -{ - insn_llret_0arg_fn_t *i_fn = (insn_llret_0arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - union reg_pair fnr; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - - fnr.dr = insnslot_llret_0arg_rflags(regs->ARM_cpsr, i_fn); - regs->uregs[rn] = fnr.r0; - regs->uregs[rd] = fnr.r1; -} - -static void __kprobes emulate_mcrr(struct kprobe *p, struct pt_regs *regs) -{ - insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - long rnv = regs->uregs[rn]; - long rdv = regs->uregs[rd]; - - insnslot_2arg_rflags(rnv, rdv, regs->ARM_cpsr, i_fn); -} - static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs) { insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; @@ -688,32 +654,32 @@ static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs) insnslot_0arg_rflags(regs->ARM_cpsr, i_fn); } -static void __kprobes emulate_rd12(struct kprobe *p, struct pt_regs *regs) +static void __kprobes emulate_nop(struct kprobe *p, struct pt_regs *regs) { - insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0]; - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 12) & 0xf; - - regs->uregs[rd] = insnslot_0arg_rflags(regs->ARM_cpsr, i_fn); } -static void __kprobes emulate_ird12(struct kprobe *p, struct pt_regs *regs) +static void __kprobes +emulate_rd12_modify(struct kprobe *p, struct pt_regs *regs) { insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; kprobe_opcode_t insn = p->opcode; - int ird = (insn >> 12) & 0xf; + int rd = (insn >> 12) & 0xf; + long rdv = regs->uregs[rd]; - insnslot_1arg_rflags(regs->uregs[ird], regs->ARM_cpsr, i_fn); + regs->uregs[rd] = insnslot_1arg_rflags(rdv, regs->ARM_cpsr, i_fn); } -static void __kprobes emulate_rn16(struct kprobe *p, struct pt_regs *regs) +static void __kprobes +emulate_rd12rn0_modify(struct kprobe *p, struct pt_regs *regs) { - insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; + insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0]; kprobe_opcode_t insn = p->opcode; - int rn = (insn >> 16) & 0xf; + int rd = (insn >> 12) & 0xf; + int rn = insn & 0xf; + long rdv = regs->uregs[rd]; long rnv = regs->uregs[rn]; - insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn); + regs->uregs[rd] = insnslot_2arg_rflags(rdv, rnv, regs->ARM_cpsr, i_fn); } static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs) @@ -819,6 +785,17 @@ emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs) } static void __kprobes +emulate_alu_tests_imm(struct kprobe *p, struct pt_regs *regs) +{ + insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; + kprobe_opcode_t insn = p->opcode; + int rn = (insn >> 16) & 0xf; + long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn]; + + insnslot_1arg_rwflags(rnv, ®s->ARM_cpsr, i_fn); +} + +static void __kprobes emulate_alu_rflags(struct kprobe *p, struct pt_regs *regs) { insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0]; @@ -854,14 +831,34 @@ emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs) insnslot_3arg_rwflags(rnv, rmv, rsv, ®s->ARM_cpsr, i_fn); } +static void __kprobes +emulate_alu_tests(struct kprobe *p, struct pt_regs *regs) +{ + insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0]; + kprobe_opcode_t insn = p->opcode; + long ppc = (long)p->addr + 8; + int rn = (insn >> 16) & 0xf; + int rs = (insn >> 8) & 0xf; /* rs/rsv may be invalid, don't care. */ + int rm = insn & 0xf; + long rnv = (rn == 15) ? ppc : regs->uregs[rn]; + long rmv = (rm == 15) ? ppc : regs->uregs[rm]; + long rsv = regs->uregs[rs]; + + insnslot_3arg_rwflags(rnv, rmv, rsv, ®s->ARM_cpsr, i_fn); +} + static enum kprobe_insn __kprobes prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi) { - int ibit = (insn & (1 << 26)) ? 25 : 22; + int not_imm = (insn & (1 << 26)) ? (insn & (1 << 25)) + : (~insn & (1 << 22)); + + if (is_writeback(insn) && is_r15(insn, 16)) + return INSN_REJECTED; /* Writeback to PC */ insn &= 0xfff00fff; insn |= 0x00001000; /* Rn = r0, Rd = r1 */ - if (insn & (1 << ibit)) { + if (not_imm) { insn &= ~0xf; insn |= 2; /* Rm = r2 */ } @@ -871,20 +868,40 @@ prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi) } static enum kprobe_insn __kprobes -prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi) +prep_emulate_rd12_modify(kprobe_opcode_t insn, struct arch_specific_insn *asi) { - insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */ + if (is_r15(insn, 12)) + return INSN_REJECTED; /* Rd is PC */ + + insn &= 0xffff0fff; /* Rd = r0 */ asi->insn[0] = insn; - asi->insn_handler = emulate_rd12rm0; + asi->insn_handler = emulate_rd12_modify; return INSN_GOOD; } static enum kprobe_insn __kprobes -prep_emulate_rd12(kprobe_opcode_t insn, struct arch_specific_insn *asi) +prep_emulate_rd12rn0_modify(kprobe_opcode_t insn, + struct arch_specific_insn *asi) { - insn &= 0xffff0fff; /* Rd = r0 */ + if (is_r15(insn, 12)) + return INSN_REJECTED; /* Rd is PC */ + + insn &= 0xffff0ff0; /* Rd = r0 */ + insn |= 0x00000001; /* Rn = r1 */ + asi->insn[0] = insn; + asi->insn_handler = emulate_rd12rn0_modify; + return INSN_GOOD; +} + +static enum kprobe_insn __kprobes +prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi) +{ + if (is_r15(insn, 12)) + return INSN_REJECTED; /* Rd is PC */ + + insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */ asi->insn[0] = insn; - asi->insn_handler = emulate_rd12; + asi->insn_handler = emulate_rd12rm0; return INSN_GOOD; } @@ -892,6 +909,9 @@ static enum kprobe_insn __kprobes prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn, struct arch_specific_insn *asi) { + if (is_r15(insn, 12)) + return INSN_REJECTED; /* Rd is PC */ + insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */ insn |= 0x00000001; /* Rm = r1 */ asi->insn[0] = insn; @@ -903,6 +923,9 @@ static enum kprobe_insn __kprobes prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn, struct arch_specific_insn *asi) { + if (is_r15(insn, 16)) + return INSN_REJECTED; /* Rd is PC */ + insn &= 0xfff0f0f0; /* Rd = r0, Rs = r0 */ insn |= 0x00000001; /* Rm = r1 */ asi->insn[0] = insn; @@ -914,6 +937,9 @@ static enum kprobe_insn __kprobes prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn, struct arch_specific_insn *asi) { + if (is_r15(insn, 16)) + return INSN_REJECTED; /* Rd is PC */ + insn &= 0xfff000f0; /* Rd = r0, Rn = r0 */ insn |= 0x00000102; /* Rs = r1, Rm = r2 */ asi->insn[0] = insn; @@ -925,6 +951,9 @@ static enum kprobe_insn __kprobes prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn, struct arch_specific_insn *asi) { + if (is_r15(insn, 16) || is_r15(insn, 12)) + return INSN_REJECTED; /* RdHi or RdLo is PC */ + insn &= 0xfff000f0; /* RdHi = r0, RdLo = r1 */ insn |= 0x00001203; /* Rs = r2, Rm = r3 */ asi->insn[0] = insn; @@ -945,20 +974,13 @@ prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn, static enum kprobe_insn __kprobes space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi) { - /* CPS mmod == 1 : 1111 0001 0000 xx10 xxxx xxxx xx0x xxxx */ - /* RFE : 1111 100x x0x1 xxxx xxxx 1010 xxxx xxxx */ - /* SRS : 1111 100x x1x0 1101 xxxx 0101 xxxx xxxx */ - if ((insn & 0xfff30020) == 0xf1020000 || - (insn & 0xfe500f00) == 0xf8100a00 || - (insn & 0xfe5f0f00) == 0xf84d0500) - return INSN_REJECTED; - - /* PLD : 1111 01x1 x101 xxxx xxxx xxxx xxxx xxxx : */ - if ((insn & 0xfd700000) == 0xf4500000) { - insn &= 0xfff0ffff; /* Rn = r0 */ - asi->insn[0] = insn; - asi->insn_handler = emulate_rn16; - return INSN_GOOD; + /* memory hint : 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx : */ + /* PLDI : 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx : */ + /* PLDW : 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx : */ + /* PLD : 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx : */ + if ((insn & 0xfe300000) == 0xf4100000) { + asi->insn_handler = emulate_nop; + return INSN_GOOD_NO_SLOT; } /* BLX(1) : 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx : */ @@ -967,41 +989,22 @@ space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi) return INSN_GOOD_NO_SLOT; } - /* SETEND : 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */ - /* CDP2 : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ - if ((insn & 0xffff00f0) == 0xf1010000 || - (insn & 0xff000010) == 0xfe000000) { - asi->insn[0] = insn; - asi->insn_handler = emulate_none; - return INSN_GOOD; - } + /* CPS : 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */ + /* SETEND: 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */ + /* SRS : 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ + /* RFE : 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ + + /* Coprocessor instructions... */ /* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */ /* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */ - if ((insn & 0xffe00000) == 0xfc400000) { - insn &= 0xfff00fff; /* Rn = r0 */ - insn |= 0x00001000; /* Rd = r1 */ - asi->insn[0] = insn; - asi->insn_handler = - (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr; - return INSN_GOOD; - } + /* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ + /* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ + /* CDP2 : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ + /* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ + /* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ - /* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ - /* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ - if ((insn & 0xfe000000) == 0xfc000000) { - insn &= 0xfff0ffff; /* Rn = r0 */ - asi->insn[0] = insn; - asi->insn_handler = emulate_ldcstc; - return INSN_GOOD; - } - - /* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ - /* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ - insn &= 0xffff0fff; /* Rd = r0 */ - asi->insn[0] = insn; - asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12; - return INSN_GOOD; + return INSN_REJECTED; } static enum kprobe_insn __kprobes @@ -1010,19 +1013,18 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx xxx0 xxxx */ if ((insn & 0x0f900010) == 0x01000000) { - /* BXJ : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */ - /* MSR : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */ - if ((insn & 0x0ff000f0) == 0x01200020 || - (insn & 0x0fb000f0) == 0x01200000) - return INSN_REJECTED; - - /* MRS : cccc 0001 0x00 xxxx xxxx xxxx 0000 xxxx */ - if ((insn & 0x0fb00010) == 0x01000000) - return prep_emulate_rd12(insn, asi); + /* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */ + if ((insn & 0x0ff000f0) == 0x01000000) { + if (is_r15(insn, 12)) + return INSN_REJECTED; /* Rd is PC */ + asi->insn_handler = simulate_mrs; + return INSN_GOOD_NO_SLOT; + } /* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */ if ((insn & 0x0ff00090) == 0x01400080) - return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi); + return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, + asi); /* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */ /* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */ @@ -1031,24 +1033,29 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) return prep_emulate_rd16rs8rm0_wflags(insn, asi); /* SMLAxy : cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx : Q */ - /* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 0x00 xxxx : Q */ - return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi); + /* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx : Q */ + if ((insn & 0x0ff00090) == 0x01000080 || + (insn & 0x0ff000b0) == 0x01200080) + return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi); + + /* BXJ : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */ + /* MSR : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */ + /* MRS spsr : cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */ + /* Other instruction encodings aren't yet defined */ + return INSN_REJECTED; } /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx 0xx1 xxxx */ else if ((insn & 0x0f900090) == 0x01000010) { - /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */ - if ((insn & 0xfff000f0) == 0xe1200070) - return INSN_REJECTED; - /* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */ /* BX : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */ if ((insn & 0x0ff000d0) == 0x01200010) { - asi->insn[0] = truecc_insn(insn); + if ((insn & 0x0ff000ff) == 0x0120003f) + return INSN_REJECTED; /* BLX pc */ asi->insn_handler = simulate_blx2bx; - return INSN_GOOD; + return INSN_GOOD_NO_SLOT; } /* CLZ : cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */ @@ -1059,17 +1066,27 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) /* QSUB : cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx :Q */ /* QDADD : cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx :Q */ /* QDSUB : cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx :Q */ - return prep_emulate_rd12rn16rm0_wflags(insn, asi); + if ((insn & 0x0f9000f0) == 0x01000050) + return prep_emulate_rd12rn16rm0_wflags(insn, asi); + + /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */ + /* SMC : cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */ + + /* Other instruction encodings aren't yet defined */ + return INSN_REJECTED; } /* cccc 0000 xxxx xxxx xxxx xxxx xxxx 1001 xxxx */ - else if ((insn & 0x0f000090) == 0x00000090) { + else if ((insn & 0x0f0000f0) == 0x00000090) { /* MUL : cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx : */ /* MULS : cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx :cc */ /* MLA : cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx : */ /* MLAS : cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx :cc */ /* UMAAL : cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx : */ + /* undef : cccc 0000 0101 xxxx xxxx xxxx 1001 xxxx : */ + /* MLS : cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx : */ + /* undef : cccc 0000 0111 xxxx xxxx xxxx 1001 xxxx : */ /* UMULL : cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx : */ /* UMULLS : cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx :cc */ /* UMLAL : cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx : */ @@ -1078,13 +1095,15 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) /* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */ /* SMLAL : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx : */ /* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */ - if ((insn & 0x0fe000f0) == 0x00000090) { - return prep_emulate_rd16rs8rm0_wflags(insn, asi); - } else if ((insn & 0x0fe000f0) == 0x00200090) { - return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi); - } else { - return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi); - } + if ((insn & 0x00d00000) == 0x00500000) + return INSN_REJECTED; + else if ((insn & 0x00e00000) == 0x00000000) + return prep_emulate_rd16rs8rm0_wflags(insn, asi); + else if ((insn & 0x00a00000) == 0x00200000) + return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi); + else + return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, + asi); } /* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */ @@ -1092,23 +1111,45 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) /* SWP : cccc 0001 0000 xxxx xxxx xxxx 1001 xxxx */ /* SWPB : cccc 0001 0100 xxxx xxxx xxxx 1001 xxxx */ - /* LDRD : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */ - /* STRD : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */ + /* ??? : cccc 0001 0x01 xxxx xxxx xxxx 1001 xxxx */ + /* ??? : cccc 0001 0x10 xxxx xxxx xxxx 1001 xxxx */ + /* ??? : cccc 0001 0x11 xxxx xxxx xxxx 1001 xxxx */ /* STREX : cccc 0001 1000 xxxx xxxx xxxx 1001 xxxx */ /* LDREX : cccc 0001 1001 xxxx xxxx xxxx 1001 xxxx */ + /* STREXD: cccc 0001 1010 xxxx xxxx xxxx 1001 xxxx */ + /* LDREXD: cccc 0001 1011 xxxx xxxx xxxx 1001 xxxx */ + /* STREXB: cccc 0001 1100 xxxx xxxx xxxx 1001 xxxx */ + /* LDREXB: cccc 0001 1101 xxxx xxxx xxxx 1001 xxxx */ + /* STREXH: cccc 0001 1110 xxxx xxxx xxxx 1001 xxxx */ + /* LDREXH: cccc 0001 1111 xxxx xxxx xxxx 1001 xxxx */ + + /* LDRD : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */ + /* STRD : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */ /* LDRH : cccc 000x xxx1 xxxx xxxx xxxx 1011 xxxx */ /* STRH : cccc 000x xxx0 xxxx xxxx xxxx 1011 xxxx */ /* LDRSB : cccc 000x xxx1 xxxx xxxx xxxx 1101 xxxx */ /* LDRSH : cccc 000x xxx1 xxxx xxxx xxxx 1111 xxxx */ - if ((insn & 0x0fb000f0) == 0x01000090) { - /* SWP/SWPB */ - return prep_emulate_rd12rn16rm0_wflags(insn, asi); + if ((insn & 0x0f0000f0) == 0x01000090) { + if ((insn & 0x0fb000f0) == 0x01000090) { + /* SWP/SWPB */ + return prep_emulate_rd12rn16rm0_wflags(insn, + asi); + } else { + /* STREX/LDREX variants and unallocaed space */ + return INSN_REJECTED; + } + } else if ((insn & 0x0e1000d0) == 0x00000d0) { /* STRD/LDRD */ + if ((insn & 0x0000e000) == 0x0000e000) + return INSN_REJECTED; /* Rd is LR or PC */ + if (is_writeback(insn) && is_r15(insn, 16)) + return INSN_REJECTED; /* Writeback to PC */ + insn &= 0xfff00fff; insn |= 0x00002000; /* Rn = r0, Rd = r2 */ - if (insn & (1 << 22)) { - /* I bit */ + if (!(insn & (1 << 22))) { + /* Register index */ insn &= ~0xf; insn |= 1; /* Rm = r1 */ } @@ -1118,6 +1159,9 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) return INSN_GOOD; } + /* LDRH/STRH/LDRSB/LDRSH */ + if (is_r15(insn, 12)) + return INSN_REJECTED; /* Rd is PC */ return prep_emulate_ldr_str(insn, asi); } @@ -1125,7 +1169,7 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) /* * ALU op with S bit and Rd == 15 : - * cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx + * cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */ if ((insn & 0x0e10f000) == 0x0010f000) return INSN_REJECTED; @@ -1154,22 +1198,61 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi) insn |= 0x00000200; /* Rs = r2 */ } asi->insn[0] = insn; - asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */ + + if ((insn & 0x0f900000) == 0x01100000) { + /* + * TST : cccc 0001 0001 xxxx xxxx xxxx xxxx xxxx + * TEQ : cccc 0001 0011 xxxx xxxx xxxx xxxx xxxx + * CMP : cccc 0001 0101 xxxx xxxx xxxx xxxx xxxx + * CMN : cccc 0001 0111 xxxx xxxx xxxx xxxx xxxx + */ + asi->insn_handler = emulate_alu_tests; + } else { + /* ALU ops which write to Rd */ + asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */ emulate_alu_rwflags : emulate_alu_rflags; + } return INSN_GOOD; } static enum kprobe_insn __kprobes space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi) { + /* MOVW : cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ + /* MOVT : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ + if ((insn & 0x0fb00000) == 0x03000000) + return prep_emulate_rd12_modify(insn, asi); + + /* hints : cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ + if ((insn & 0x0fff0000) == 0x03200000) { + unsigned op2 = insn & 0x000000ff; + if (op2 == 0x01 || op2 == 0x04) { + /* YIELD : cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ + /* SEV : cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ + asi->insn[0] = insn; + asi->insn_handler = emulate_none; + return INSN_GOOD; + } else if (op2 <= 0x03) { + /* NOP : cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ + /* WFE : cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ + /* WFI : cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ + /* + * We make WFE and WFI true NOPs to avoid stalls due + * to missing events whilst processing the probe. + */ + asi->insn_handler = emulate_nop; + return INSN_GOOD_NO_SLOT; + } + /* For DBG and unallocated hints it's safest to reject them */ + return INSN_REJECTED; + } + /* * MSR : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx - * Undef : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx * ALU op with S bit and Rd == 15 : * cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */ if ((insn & 0x0fb00000) == 0x03200000 || /* MSR */ - (insn & 0x0ff00000) == 0x03400000 || /* Undef */ (insn & 0x0e10f000) == 0x0210f000) /* ALU s-bit, R15 */ return INSN_REJECTED; @@ -1180,10 +1263,22 @@ space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi) * *S (bit 20) updates condition codes * ADC/SBC/RSC reads the C flag */ - insn &= 0xffff0fff; /* Rd = r0 */ + insn &= 0xfff00fff; /* Rn = r0 and Rd = r0 */ asi->insn[0] = insn; - asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */ + + if ((insn & 0x0f900000) == 0x03100000) { + /* + * TST : cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx + * TEQ : cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx + * CMP : cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx + * CMN : cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx + */ + asi->insn_handler = emulate_alu_tests_imm; + } else { + /* ALU ops which write to Rd */ + asi->insn_handler = (insn & (1 << 20)) ? /* S-bit */ emulate_alu_imm_rwflags : emulate_alu_imm_rflags; + } return INSN_GOOD; } @@ -1192,6 +1287,8 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi) { /* SEL : cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx GE: !!! */ if ((insn & 0x0ff000f0) == 0x068000b0) { + if (is_r15(insn, 12)) + return INSN_REJECTED; /* Rd is PC */ insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */ insn |= 0x00000001; /* Rm = r1 */ asi->insn[0] = insn; @@ -1205,6 +1302,8 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi) /* USAT16 : cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx :Q */ if ((insn & 0x0fa00030) == 0x06a00010 || (insn & 0x0fb000f0) == 0x06a00030) { + if (is_r15(insn, 12)) + return INSN_REJECTED; /* Rd is PC */ insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */ asi->insn[0] = insn; asi->insn_handler = emulate_sat; @@ -1213,57 +1312,101 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi) /* REV : cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */ /* REV16 : cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */ + /* RBIT : cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */ /* REVSH : cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */ if ((insn & 0x0ff00070) == 0x06b00030 || - (insn & 0x0ff000f0) == 0x06f000b0) + (insn & 0x0ff00070) == 0x06f00030) return prep_emulate_rd12rm0(insn, asi); + /* ??? : cccc 0110 0000 xxxx xxxx xxxx xxx1 xxxx : */ /* SADD16 : cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx :GE */ /* SADDSUBX : cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx :GE */ /* SSUBADDX : cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx :GE */ /* SSUB16 : cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx :GE */ /* SADD8 : cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx :GE */ + /* ??? : cccc 0110 0001 xxxx xxxx xxxx 1011 xxxx : */ + /* ??? : cccc 0110 0001 xxxx xxxx xxxx 1101 xxxx : */ /* SSUB8 : cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx :GE */ /* QADD16 : cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx : */ /* QADDSUBX : cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx : */ /* QSUBADDX : cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx : */ /* QSUB16 : cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx : */ /* QADD8 : cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx : */ + /* ??? : cccc 0110 0010 xxxx xxxx xxxx 1011 xxxx : */ + /* ??? : cccc 0110 0010 xxxx xxxx xxxx 1101 xxxx : */ /* QSUB8 : cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx : */ /* SHADD16 : cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx : */ /* SHADDSUBX : cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx : */ /* SHSUBADDX : cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx : */ /* SHSUB16 : cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx : */ /* SHADD8 : cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx : */ + /* ??? : cccc 0110 0011 xxxx xxxx xxxx 1011 xxxx : */ + /* ??? : cccc 0110 0011 xxxx xxxx xxxx 1101 xxxx : */ /* SHSUB8 : cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx : */ + /* ??? : cccc 0110 0100 xxxx xxxx xxxx xxx1 xxxx : */ /* UADD16 : cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx :GE */ /* UADDSUBX : cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx :GE */ /* USUBADDX : cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx :GE */ /* USUB16 : cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx :GE */ /* UADD8 : cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx :GE */ + /* ??? : cccc 0110 0101 xxxx xxxx xxxx 1011 xxxx : */ + /* ??? : cccc 0110 0101 xxxx xxxx xxxx 1101 xxxx : */ /* USUB8 : cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx :GE */ /* UQADD16 : cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx : */ /* UQADDSUBX : cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx : */ /* UQSUBADDX : cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx : */ /* UQSUB16 : cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx : */ /* UQADD8 : cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx : */ + /* ??? : cccc 0110 0110 xxxx xxxx xxxx 1011 xxxx : */ + /* ??? : cccc 0110 0110 xxxx xxxx xxxx 1101 xxxx : */ /* UQSUB8 : cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx : */ /* UHADD16 : cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx : */ /* UHADDSUBX : cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx : */ /* UHSUBADDX : cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx : */ /* UHSUB16 : cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx : */ /* UHADD8 : cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx : */ + /* ??? : cccc 0110 0111 xxxx xxxx xxxx 1011 xxxx : */ + /* ??? : cccc 0110 0111 xxxx xxxx xxxx 1101 xxxx : */ /* UHSUB8 : cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx : */ + if ((insn & 0x0f800010) == 0x06000010) { + if ((insn & 0x00300000) == 0x00000000 || + (insn & 0x000000e0) == 0x000000a0 || + (insn & 0x000000e0) == 0x000000c0) + return INSN_REJECTED; /* Unallocated space */ + return prep_emulate_rd12rn16rm0_wflags(insn, asi); + } + /* PKHBT : cccc 0110 1000 xxxx xxxx xxxx x001 xxxx : */ /* PKHTB : cccc 0110 1000 xxxx xxxx xxxx x101 xxxx : */ + if ((insn & 0x0ff00030) == 0x06800010) + return prep_emulate_rd12rn16rm0_wflags(insn, asi); + /* SXTAB16 : cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx : */ - /* SXTB : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx : */ + /* SXTB16 : cccc 0110 1000 1111 xxxx xxxx 0111 xxxx : */ + /* ??? : cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx : */ /* SXTAB : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx : */ + /* SXTB : cccc 0110 1010 1111 xxxx xxxx 0111 xxxx : */ /* SXTAH : cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx : */ + /* SXTH : cccc 0110 1011 1111 xxxx xxxx 0111 xxxx : */ /* UXTAB16 : cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx : */ + /* UXTB16 : cccc 0110 1100 1111 xxxx xxxx 0111 xxxx : */ + /* ??? : cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx : */ /* UXTAB : cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx : */ + /* UXTB : cccc 0110 1110 1111 xxxx xxxx 0111 xxxx : */ /* UXTAH : cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx : */ - return prep_emulate_rd12rn16rm0_wflags(insn, asi); + /* UXTH : cccc 0110 1111 1111 xxxx xxxx 0111 xxxx : */ + if ((insn & 0x0f8000f0) == 0x06800070) { + if ((insn & 0x00300000) == 0x00100000) + return INSN_REJECTED; /* Unallocated space */ + + if ((insn & 0x000f0000) == 0x000f0000) + return prep_emulate_rd12rm0(insn, asi); + else + return prep_emulate_rd12rn16rm0_wflags(insn, asi); + } + + /* Other instruction encodings aren't yet defined */ + return INSN_REJECTED; } static enum kprobe_insn __kprobes @@ -1273,29 +1416,49 @@ space_cccc_0111__1(kprobe_opcode_t insn, struct arch_specific_insn *asi) if ((insn & 0x0ff000f0) == 0x03f000f0) return INSN_REJECTED; - /* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */ - /* USAD8 : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */ - if ((insn & 0x0ff000f0) == 0x07800010) - return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi); - /* SMLALD : cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */ /* SMLSLD : cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */ if ((insn & 0x0ff00090) == 0x07400010) return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi); /* SMLAD : cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx :Q */ + /* SMUAD : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */ /* SMLSD : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :Q */ + /* SMUSD : cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx : */ /* SMMLA : cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx : */ - /* SMMLS : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx : */ + /* SMMUL : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx : */ + /* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx : */ + /* USAD8 : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx : */ if ((insn & 0x0ff00090) == 0x07000010 || (insn & 0x0ff000d0) == 0x07500010 || - (insn & 0x0ff000d0) == 0x075000d0) + (insn & 0x0ff000f0) == 0x07800010) { + + if ((insn & 0x0000f000) == 0x0000f000) + return prep_emulate_rd16rs8rm0_wflags(insn, asi); + else + return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi); + } + + /* SMMLS : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx : */ + if ((insn & 0x0ff000d0) == 0x075000d0) return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi); - /* SMUSD : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx : */ - /* SMUAD : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */ - /* SMMUL : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx : */ - return prep_emulate_rd16rs8rm0_wflags(insn, asi); + /* SBFX : cccc 0111 101x xxxx xxxx xxxx x101 xxxx : */ + /* UBFX : cccc 0111 111x xxxx xxxx xxxx x101 xxxx : */ + if ((insn & 0x0fa00070) == 0x07a00050) + return prep_emulate_rd12rm0(insn, asi); + + /* BFI : cccc 0111 110x xxxx xxxx xxxx x001 xxxx : */ + /* BFC : cccc 0111 110x xxxx xxxx xxxx x001 1111 : */ + if ((insn & 0x0fe00070) == 0x07c00010) { + + if ((insn & 0x0000000f) == 0x0000000f) + return prep_emulate_rd12_modify(insn, asi); + else + return prep_emulate_rd12rn0_modify(insn, asi); + } + + return INSN_REJECTED; } static enum kprobe_insn __kprobes @@ -1309,6 +1472,10 @@ space_cccc_01xx(kprobe_opcode_t insn, struct arch_specific_insn *asi) /* STRB : cccc 01xx x1x0 xxxx xxxx xxxx xxxx xxxx */ /* STRBT : cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */ /* STRT : cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */ + + if ((insn & 0x00500000) == 0x00500000 && is_r15(insn, 12)) + return INSN_REJECTED; /* LDRB into PC */ + return prep_emulate_ldr_str(insn, asi); } @@ -1323,10 +1490,9 @@ space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi) /* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ /* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */ - asi->insn[0] = truecc_insn(insn); asi->insn_handler = ((insn & 0x108000) == 0x008000) ? /* STM & R15 */ simulate_stm1_pc : simulate_ldm1stm1; - return INSN_GOOD; + return INSN_GOOD_NO_SLOT; } static enum kprobe_insn __kprobes @@ -1334,58 +1500,117 @@ space_cccc_101x(kprobe_opcode_t insn, struct arch_specific_insn *asi) { /* B : cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */ /* BL : cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */ - asi->insn[0] = truecc_insn(insn); asi->insn_handler = simulate_bbl; - return INSN_GOOD; + return INSN_GOOD_NO_SLOT; } static enum kprobe_insn __kprobes -space_cccc_1100_010x(kprobe_opcode_t insn, struct arch_specific_insn *asi) +space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi) { + /* Coprocessor instructions... */ /* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */ /* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */ - insn &= 0xfff00fff; - insn |= 0x00001000; /* Rn = r0, Rd = r1 */ - asi->insn[0] = insn; - asi->insn_handler = (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr; - return INSN_GOOD; + /* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ + /* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ + /* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ + /* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ + /* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ + + /* SVC : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */ + + return INSN_REJECTED; } -static enum kprobe_insn __kprobes -space_cccc_110x(kprobe_opcode_t insn, struct arch_specific_insn *asi) +static unsigned long __kprobes __check_eq(unsigned long cpsr) { - /* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ - /* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ - insn &= 0xfff0ffff; /* Rn = r0 */ - asi->insn[0] = insn; - asi->insn_handler = emulate_ldcstc; - return INSN_GOOD; + return cpsr & PSR_Z_BIT; } -static enum kprobe_insn __kprobes -space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi) +static unsigned long __kprobes __check_ne(unsigned long cpsr) { - /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */ - /* SWI : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */ - if ((insn & 0xfff000f0) == 0xe1200070 || - (insn & 0x0f000000) == 0x0f000000) - return INSN_REJECTED; + return (~cpsr) & PSR_Z_BIT; +} - /* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ - if ((insn & 0x0f000010) == 0x0e000000) { - asi->insn[0] = insn; - asi->insn_handler = emulate_none; - return INSN_GOOD; - } +static unsigned long __kprobes __check_cs(unsigned long cpsr) +{ + return cpsr & PSR_C_BIT; +} - /* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ - /* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ - insn &= 0xffff0fff; /* Rd = r0 */ - asi->insn[0] = insn; - asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12; - return INSN_GOOD; +static unsigned long __kprobes __check_cc(unsigned long cpsr) +{ + return (~cpsr) & PSR_C_BIT; +} + +static unsigned long __kprobes __check_mi(unsigned long cpsr) +{ + return cpsr & PSR_N_BIT; +} + +static unsigned long __kprobes __check_pl(unsigned long cpsr) +{ + return (~cpsr) & PSR_N_BIT; +} + +static unsigned long __kprobes __check_vs(unsigned long cpsr) +{ + return cpsr & PSR_V_BIT; +} + +static unsigned long __kprobes __check_vc(unsigned long cpsr) +{ + return (~cpsr) & PSR_V_BIT; +} + +static unsigned long __kprobes __check_hi(unsigned long cpsr) +{ + cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ + return cpsr & PSR_C_BIT; } +static unsigned long __kprobes __check_ls(unsigned long cpsr) +{ + cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ + return (~cpsr) & PSR_C_BIT; +} + +static unsigned long __kprobes __check_ge(unsigned long cpsr) +{ + cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ + return (~cpsr) & PSR_N_BIT; +} + +static unsigned long __kprobes __check_lt(unsigned long cpsr) +{ + cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ + return cpsr & PSR_N_BIT; +} + +static unsigned long __kprobes __check_gt(unsigned long cpsr) +{ + unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ + temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ + return (~temp) & PSR_N_BIT; +} + +static unsigned long __kprobes __check_le(unsigned long cpsr) +{ + unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ + temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ + return temp & PSR_N_BIT; +} + +static unsigned long __kprobes __check_al(unsigned long cpsr) +{ + return true; +} + +static kprobe_check_cc * const condition_checks[16] = { + &__check_eq, &__check_ne, &__check_cs, &__check_cc, + &__check_mi, &__check_pl, &__check_vs, &__check_vc, + &__check_hi, &__check_ls, &__check_ge, &__check_lt, + &__check_gt, &__check_le, &__check_al, &__check_al +}; + /* Return: * INSN_REJECTED If instruction is one not allowed to kprobe, * INSN_GOOD If instruction is supported and uses instruction slot, @@ -1401,133 +1626,45 @@ space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi) enum kprobe_insn __kprobes arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) { + asi->insn_check_cc = condition_checks[insn>>28]; asi->insn[1] = KPROBE_RETURN_INSTRUCTION; - if ((insn & 0xf0000000) == 0xf0000000) { + if ((insn & 0xf0000000) == 0xf0000000) return space_1111(insn, asi); - } else if ((insn & 0x0e000000) == 0x00000000) { + else if ((insn & 0x0e000000) == 0x00000000) return space_cccc_000x(insn, asi); - } else if ((insn & 0x0e000000) == 0x02000000) { + else if ((insn & 0x0e000000) == 0x02000000) return space_cccc_001x(insn, asi); - } else if ((insn & 0x0f000010) == 0x06000010) { + else if ((insn & 0x0f000010) == 0x06000010) return space_cccc_0110__1(insn, asi); - } else if ((insn & 0x0f000010) == 0x07000010) { + else if ((insn & 0x0f000010) == 0x07000010) return space_cccc_0111__1(insn, asi); - } else if ((insn & 0x0c000000) == 0x04000000) { + else if ((insn & 0x0c000000) == 0x04000000) return space_cccc_01xx(insn, asi); - } else if ((insn & 0x0e000000) == 0x08000000) { + else if ((insn & 0x0e000000) == 0x08000000) return space_cccc_100x(insn, asi); - } else if ((insn & 0x0e000000) == 0x0a000000) { + else if ((insn & 0x0e000000) == 0x0a000000) return space_cccc_101x(insn, asi); - } else if ((insn & 0x0fe00000) == 0x0c400000) { - - return space_cccc_1100_010x(insn, asi); - - } else if ((insn & 0x0e000000) == 0x0c000000) { - - return space_cccc_110x(insn, asi); - - } - - return space_cccc_111x(insn, asi); + return space_cccc_11xx(insn, asi); } void __init arm_kprobe_decode_init(void) { find_str_pc_offset(); } - - -/* - * All ARM instructions listed below. - * - * Instructions and their general purpose registers are given. - * If a particular register may not use R15, it is prefixed with a "!". - * If marked with a "*" means the value returned by reading R15 - * is implementation defined. - * - * ADC/ADD/AND/BIC/CMN/CMP/EOR/MOV/MVN/ORR/RSB/RSC/SBC/SUB/TEQ - * TST: Rd, Rn, Rm, !Rs - * BX: Rm - * BLX(2): !Rm - * BX: Rm (R15 legal, but discouraged) - * BXJ: !Rm, - * CLZ: !Rd, !Rm - * CPY: Rd, Rm - * LDC/2,STC/2 immediate offset & unindex: Rn - * LDC/2,STC/2 immediate pre/post-indexed: !Rn - * LDM(1/3): !Rn, register_list - * LDM(2): !Rn, !register_list - * LDR,STR,PLD immediate offset: Rd, Rn - * LDR,STR,PLD register offset: Rd, Rn, !Rm - * LDR,STR,PLD scaled register offset: Rd, !Rn, !Rm - * LDR,STR immediate pre/post-indexed: Rd, !Rn - * LDR,STR register pre/post-indexed: Rd, !Rn, !Rm - * LDR,STR scaled register pre/post-indexed: Rd, !Rn, !Rm - * LDRB,STRB immediate offset: !Rd, Rn - * LDRB,STRB register offset: !Rd, Rn, !Rm - * LDRB,STRB scaled register offset: !Rd, !Rn, !Rm - * LDRB,STRB immediate pre/post-indexed: !Rd, !Rn - * LDRB,STRB register pre/post-indexed: !Rd, !Rn, !Rm - * LDRB,STRB scaled register pre/post-indexed: !Rd, !Rn, !Rm - * LDRT,LDRBT,STRBT immediate pre/post-indexed: !Rd, !Rn - * LDRT,LDRBT,STRBT register pre/post-indexed: !Rd, !Rn, !Rm - * LDRT,LDRBT,STRBT scaled register pre/post-indexed: !Rd, !Rn, !Rm - * LDRH/SH/SB/D,STRH/SH/SB/D immediate offset: !Rd, Rn - * LDRH/SH/SB/D,STRH/SH/SB/D register offset: !Rd, Rn, !Rm - * LDRH/SH/SB/D,STRH/SH/SB/D immediate pre/post-indexed: !Rd, !Rn - * LDRH/SH/SB/D,STRH/SH/SB/D register pre/post-indexed: !Rd, !Rn, !Rm - * LDREX: !Rd, !Rn - * MCR/2: !Rd - * MCRR/2,MRRC/2: !Rd, !Rn - * MLA: !Rd, !Rn, !Rm, !Rs - * MOV: Rd - * MRC/2: !Rd (if Rd==15, only changes cond codes, not the register) - * MRS,MSR: !Rd - * MUL: !Rd, !Rm, !Rs - * PKH{BT,TB}: !Rd, !Rn, !Rm - * QDADD,[U]QADD/16/8/SUBX: !Rd, !Rm, !Rn - * QDSUB,[U]QSUB/16/8/ADDX: !Rd, !Rm, !Rn - * REV/16/SH: !Rd, !Rm - * RFE: !Rn - * {S,U}[H]ADD{16,8,SUBX},{S,U}[H]SUB{16,8,ADDX}: !Rd, !Rn, !Rm - * SEL: !Rd, !Rn, !Rm - * SMLA<x><y>,SMLA{D,W<y>},SMLSD,SMML{A,S}: !Rd, !Rn, !Rm, !Rs - * SMLAL<x><y>,SMLA{D,LD},SMLSLD,SMMULL,SMULW<y>: !RdHi, !RdLo, !Rm, !Rs - * SMMUL,SMUAD,SMUL<x><y>,SMUSD: !Rd, !Rm, !Rs - * SSAT/16: !Rd, !Rm - * STM(1/2): !Rn, register_list* (R15 in reg list not recommended) - * STRT immediate pre/post-indexed: Rd*, !Rn - * STRT register pre/post-indexed: Rd*, !Rn, !Rm - * STRT scaled register pre/post-indexed: Rd*, !Rn, !Rm - * STREX: !Rd, !Rn, !Rm - * SWP/B: !Rd, !Rn, !Rm - * {S,U}XTA{B,B16,H}: !Rd, !Rn, !Rm - * {S,U}XT{B,B16,H}: !Rd, !Rm - * UM{AA,LA,UL}L: !RdHi, !RdLo, !Rm, !Rs - * USA{D8,A8,T,T16}: !Rd, !Rm, !Rs - * - * May transfer control by writing R15 (possible mode changes or alternate - * mode accesses marked by "*"): - * ALU op (* with s-bit), B, BL, BKPT, BLX(1/2), BX, BXJ, CPS*, CPY, - * LDM(1), LDM(2/3)*, LDR, MOV, RFE*, SWI* - * - * Instructions that do not take general registers, nor transfer control: - * CDP/2, SETEND, SRS* - */ diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c index 2ba7deb3072e..1656c87501c0 100644 --- a/arch/arm/kernel/kprobes.c +++ b/arch/arm/kernel/kprobes.c @@ -134,7 +134,8 @@ static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) { regs->ARM_pc += 4; - p->ainsn.insn_handler(p, regs); + if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) + p->ainsn.insn_handler(p, regs); } /* diff --git a/arch/arm/kernel/leds.c b/arch/arm/kernel/leds.c index 31a316c1777b..0f107dcb0347 100644 --- a/arch/arm/kernel/leds.c +++ b/arch/arm/kernel/leds.c @@ -10,6 +10,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <asm/leds.h> @@ -69,36 +70,37 @@ static ssize_t leds_store(struct sys_device *dev, static SYSDEV_ATTR(event, 0200, NULL, leds_store); -static int leds_suspend(struct sys_device *dev, pm_message_t state) +static struct sysdev_class leds_sysclass = { + .name = "leds", +}; + +static struct sys_device leds_device = { + .id = 0, + .cls = &leds_sysclass, +}; + +static int leds_suspend(void) { leds_event(led_stop); return 0; } -static int leds_resume(struct sys_device *dev) +static void leds_resume(void) { leds_event(led_start); - return 0; } -static int leds_shutdown(struct sys_device *dev) +static void leds_shutdown(void) { leds_event(led_halted); - return 0; } -static struct sysdev_class leds_sysclass = { - .name = "leds", +static struct syscore_ops leds_syscore_ops = { .shutdown = leds_shutdown, .suspend = leds_suspend, .resume = leds_resume, }; -static struct sys_device leds_device = { - .id = 0, - .cls = &leds_sysclass, -}; - static int __init leds_init(void) { int ret; @@ -107,6 +109,8 @@ static int __init leds_init(void) ret = sysdev_register(&leds_device); if (ret == 0) ret = sysdev_create_file(&leds_device, &attr_event); + if (ret == 0) + register_syscore_ops(&leds_syscore_ops); return ret; } diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 979da3947f42..139e3c827369 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -746,7 +746,8 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) tail = (struct frame_tail __user *)regs->ARM_fp - 1; - while (tail && !((unsigned long)tail & 0x3)) + while ((entry->nr < PERF_MAX_STACK_DEPTH) && + tail && !((unsigned long)tail & 0x3)) tail = user_backtrace(tail, entry); } diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 2bf27f364d09..8182f45ca493 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -767,12 +767,20 @@ long arch_ptrace(struct task_struct *child, long request, #ifdef CONFIG_HAVE_HW_BREAKPOINT case PTRACE_GETHBPREGS: + if (ptrace_get_breakpoints(child) < 0) + return -ESRCH; + ret = ptrace_gethbpregs(child, addr, (unsigned long __user *)data); + ptrace_put_breakpoints(child); break; case PTRACE_SETHBPREGS: + if (ptrace_get_breakpoints(child) < 0) + return -ESRCH; + ret = ptrace_sethbpregs(child, addr, (unsigned long __user *)data); + ptrace_put_breakpoints(child); break; #endif diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index cb8398317644..0340224cf73c 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -597,19 +597,13 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, return err; } -static inline void setup_syscall_restart(struct pt_regs *regs) -{ - regs->ARM_r0 = regs->ARM_ORIG_r0; - regs->ARM_pc -= thumb_mode(regs) ? 2 : 4; -} - /* * OK, we're invoking a handler */ static int handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs, int syscall) + struct pt_regs * regs) { struct thread_info *thread = current_thread_info(); struct task_struct *tsk = current; @@ -617,26 +611,6 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, int ret; /* - * If we were from a system call, check for system call restarting... - */ - if (syscall) { - switch (regs->ARM_r0) { - case -ERESTART_RESTARTBLOCK: - case -ERESTARTNOHAND: - regs->ARM_r0 = -EINTR; - break; - case -ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->ARM_r0 = -EINTR; - break; - } - /* fallthrough */ - case -ERESTARTNOINTR: - setup_syscall_restart(regs); - } - } - - /* * translate the signal */ if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap) @@ -685,6 +659,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, */ static void do_signal(struct pt_regs *regs, int syscall) { + unsigned int retval = 0, continue_addr = 0, restart_addr = 0; struct k_sigaction ka; siginfo_t info; int signr; @@ -698,18 +673,61 @@ static void do_signal(struct pt_regs *regs, int syscall) if (!user_mode(regs)) return; + /* + * If we were from a system call, check for system call restarting... + */ + if (syscall) { + continue_addr = regs->ARM_pc; + restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4); + retval = regs->ARM_r0; + + /* + * Prepare for system call restart. We do this here so that a + * debugger will see the already changed PSW. + */ + switch (retval) { + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: + regs->ARM_r0 = regs->ARM_ORIG_r0; + regs->ARM_pc = restart_addr; + break; + case -ERESTART_RESTARTBLOCK: + regs->ARM_r0 = -EINTR; + break; + } + } + if (try_to_freeze()) goto no_signal; + /* + * Get the signal to deliver. When running under ptrace, at this + * point the debugger may change all our registers ... + */ signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { sigset_t *oldset; + /* + * Depending on the signal settings we may need to revert the + * decision to restart the system call. But skip this if a + * debugger has chosen to restart at a different PC. + */ + if (regs->ARM_pc == restart_addr) { + if (retval == -ERESTARTNOHAND + || (retval == -ERESTARTSYS + && !(ka.sa.sa_flags & SA_RESTART))) { + regs->ARM_r0 = -EINTR; + regs->ARM_pc = continue_addr; + } + } + if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; - if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) { + if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { /* * A signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, @@ -723,11 +741,14 @@ static void do_signal(struct pt_regs *regs, int syscall) } no_signal: - /* - * No signal to deliver to the process - restart the syscall. - */ if (syscall) { - if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { + /* + * Handle restarting a different system call. As above, + * if a debugger has chosen to restart at a different PC, + * ignore the restart. + */ + if (retval == -ERESTART_RESTARTBLOCK + && regs->ARM_pc == continue_addr) { if (thumb_mode(regs)) { regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; regs->ARM_pc -= 2; @@ -750,11 +771,6 @@ static void do_signal(struct pt_regs *regs, int syscall) #endif } } - if (regs->ARM_r0 == -ERESTARTNOHAND || - regs->ARM_r0 == -ERESTARTSYS || - regs->ARM_r0 == -ERESTARTNOINTR) { - setup_syscall_restart(regs); - } /* If there's no signal to deliver, we just put the saved sigmask * back. diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 8fe05ad932e4..d439a8f4c078 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -376,6 +376,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus) } } +static void (*smp_cross_call)(const struct cpumask *, unsigned int); + +void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int)) +{ + smp_cross_call = fn; +} + void arch_send_call_function_ipi_mask(const struct cpumask *mask) { smp_cross_call(mask, IPI_CALL_FUNC); @@ -479,7 +486,7 @@ static void broadcast_timer_set_mode(enum clock_event_mode mode, { } -static void broadcast_timer_setup(struct clock_event_device *evt) +static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt) { evt->name = "dummy_timer"; evt->features = CLOCK_EVT_FEAT_ONESHOT | @@ -560,10 +567,7 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) break; case IPI_RESCHEDULE: - /* - * nothing more to do - eveything is - * done on the interrupt return path - */ + scheduler_ipi(); break; case IPI_CALL_FUNC: diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index 4ad8da15ef2b..af0aaebf4de6 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c @@ -311,7 +311,7 @@ asmlinkage long sys_oabi_semtimedop(int semid, long err; int i; - if (nsops < 1) + if (nsops < 1 || nsops > SEMOPM) return -EINVAL; sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL); if (!sops) diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 1ff46cabc7ef..cb634c3e28e9 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -21,7 +21,7 @@ #include <linux/timex.h> #include <linux/errno.h> #include <linux/profile.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/timer.h> #include <linux/irq.h> @@ -115,48 +115,37 @@ void timer_tick(void) #endif #if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS) -static int timer_suspend(struct sys_device *dev, pm_message_t state) +static int timer_suspend(void) { - struct sys_timer *timer = container_of(dev, struct sys_timer, dev); - - if (timer->suspend != NULL) - timer->suspend(); + if (system_timer->suspend) + system_timer->suspend(); return 0; } -static int timer_resume(struct sys_device *dev) +static void timer_resume(void) { - struct sys_timer *timer = container_of(dev, struct sys_timer, dev); - - if (timer->resume != NULL) - timer->resume(); - - return 0; + if (system_timer->resume) + system_timer->resume(); } #else #define timer_suspend NULL #define timer_resume NULL #endif -static struct sysdev_class timer_sysclass = { - .name = "timer", +static struct syscore_ops timer_syscore_ops = { .suspend = timer_suspend, .resume = timer_resume, }; -static int __init timer_init_sysfs(void) +static int __init timer_init_syscore_ops(void) { - int ret = sysdev_class_register(&timer_sysclass); - if (ret == 0) { - system_timer->dev.cls = &timer_sysclass; - ret = sysdev_register(&system_timer->dev); - } + register_syscore_ops(&timer_syscore_ops); - return ret; + return 0; } -device_initcall(timer_init_sysfs); +device_initcall(timer_init_syscore_ops); void __init time_init(void) { diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 3b54ad19d489..d52eec268b47 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -234,7 +234,6 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n", str, err, ++die_counter); - sysfs_printk_last_file(); /* trap and error numbers are mostly meaningless on ARM */ ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 19390231a0e9..2d299bf5d72f 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -83,6 +83,7 @@ config ARCH_AT91CAP9 select CPU_ARM926T select GENERIC_CLOCKEVENTS select HAVE_FB_ATMEL + select HAVE_NET_MACB config ARCH_AT572D940HF bool "AT572D940HF" diff --git a/arch/arm/mach-at91/board-eb01.c b/arch/arm/mach-at91/board-eb01.c index 1f9d3cb64c50..d8df59a3426d 100644 --- a/arch/arm/mach-at91/board-eb01.c +++ b/arch/arm/mach-at91/board-eb01.c @@ -30,6 +30,11 @@ #include <mach/board.h> #include "generic.h" +static void __init at91eb01_init_irq(void) +{ + at91x40_init_interrupts(NULL); +} + static void __init at91eb01_map_io(void) { at91x40_initialize(40000000); @@ -38,7 +43,7 @@ static void __init at91eb01_map_io(void) MACHINE_START(AT91EB01, "Atmel AT91 EB01") /* Maintainer: Greg Ungerer <gerg@snapgear.com> */ .timer = &at91x40_timer, - .init_irq = at91x40_init_interrupts, + .init_irq = at91eb01_init_irq, .map_io = at91eb01_map_io, MACHINE_END diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h index 3bef931d0b1c..0700f2125305 100644 --- a/arch/arm/mach-at91/include/mach/cpu.h +++ b/arch/arm/mach-at91/include/mach/cpu.h @@ -27,6 +27,7 @@ #define ARCH_ID_AT91SAM9G45 0x819b05a0 #define ARCH_ID_AT91SAM9G45MRL 0x819b05a2 /* aka 9G45-ES2 & non ES lots */ #define ARCH_ID_AT91SAM9G45ES 0x819b05a1 /* 9G45-ES (Engineering Sample) */ +#define ARCH_ID_AT91SAM9X5 0x819a05a0 #define ARCH_ID_AT91CAP9 0x039A03A0 #define ARCH_ID_AT91SAM9XE128 0x329973a0 @@ -55,6 +56,12 @@ static inline unsigned long at91_cpu_fully_identify(void) #define ARCH_EXID_AT91SAM9G46 0x00000003 #define ARCH_EXID_AT91SAM9G45 0x00000004 +#define ARCH_EXID_AT91SAM9G15 0x00000000 +#define ARCH_EXID_AT91SAM9G35 0x00000001 +#define ARCH_EXID_AT91SAM9X35 0x00000002 +#define ARCH_EXID_AT91SAM9G25 0x00000003 +#define ARCH_EXID_AT91SAM9X25 0x00000004 + static inline unsigned long at91_exid_identify(void) { return at91_sys_read(AT91_DBGU_EXID); @@ -143,6 +150,27 @@ static inline unsigned long at91cap9_rev_identify(void) #define cpu_is_at91sam9m11() (0) #endif +#ifdef CONFIG_ARCH_AT91SAM9X5 +#define cpu_is_at91sam9x5() (at91_cpu_identify() == ARCH_ID_AT91SAM9X5) +#define cpu_is_at91sam9g15() (cpu_is_at91sam9x5() && \ + (at91_exid_identify() == ARCH_EXID_AT91SAM9G15)) +#define cpu_is_at91sam9g35() (cpu_is_at91sam9x5() && \ + (at91_exid_identify() == ARCH_EXID_AT91SAM9G35)) +#define cpu_is_at91sam9x35() (cpu_is_at91sam9x5() && \ + (at91_exid_identify() == ARCH_EXID_AT91SAM9X35)) +#define cpu_is_at91sam9g25() (cpu_is_at91sam9x5() && \ + (at91_exid_identify() == ARCH_EXID_AT91SAM9G25)) +#define cpu_is_at91sam9x25() (cpu_is_at91sam9x5() && \ + (at91_exid_identify() == ARCH_EXID_AT91SAM9X25)) +#else +#define cpu_is_at91sam9x5() (0) +#define cpu_is_at91sam9g15() (0) +#define cpu_is_at91sam9g35() (0) +#define cpu_is_at91sam9x35() (0) +#define cpu_is_at91sam9g25() (0) +#define cpu_is_at91sam9x25() (0) +#endif + #ifdef CONFIG_ARCH_AT91CAP9 #define cpu_is_at91cap9() (at91_cpu_identify() == ARCH_ID_AT91CAP9) #define cpu_is_at91cap9_revB() (at91cap9_rev_identify() == ARCH_REVISION_CAP9_B) diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c index 73eb066d2329..a604b9ebb501 100644 --- a/arch/arm/mach-bcmring/arch.c +++ b/arch/arm/mach-bcmring/arch.c @@ -169,6 +169,7 @@ MACHINE_START(BCMRING, "BCMRING") /* Maintainer: Broadcom Corporation */ .fixup = bcmring_fixup, .map_io = bcmring_map_io, + .init_early = bcmring_init_early, .init_irq = bcmring_init_irq, .timer = &bcmring_timer, .init_machine = bcmring_init_machine diff --git a/arch/arm/mach-bcmring/core.c b/arch/arm/mach-bcmring/core.c index 8fc2035759fb..43eadbcc29ed 100644 --- a/arch/arm/mach-bcmring/core.c +++ b/arch/arm/mach-bcmring/core.c @@ -28,8 +28,6 @@ #include <linux/sysdev.h> #include <linux/interrupt.h> #include <linux/amba/bus.h> -#include <linux/clocksource.h> -#include <linux/clockchips.h> #include <linux/clkdev.h> #include <mach/csp/mm_addr.h> @@ -37,6 +35,7 @@ #include <linux/io.h> #include <asm/irq.h> #include <asm/hardware/arm_timer.h> +#include <asm/hardware/timer-sp.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -97,6 +96,35 @@ static struct clk dummy_apb_pclk = { .mode = CLK_MODE_XTAL, }; +/* Timer 0 - 25 MHz, Timer3 at bus clock rate, typically 150-166 MHz */ +#if defined(CONFIG_ARCH_FPGA11107) +/* fpga cpu/bus are currently 30 times slower so scale frequency as well to */ +/* slow down Linux's sense of time */ +#define TIMER0_FREQUENCY_MHZ (tmrHw_LOW_FREQUENCY_MHZ * 30) +#define TIMER1_FREQUENCY_MHZ (tmrHw_LOW_FREQUENCY_MHZ * 30) +#define TIMER3_FREQUENCY_MHZ (tmrHw_HIGH_FREQUENCY_MHZ * 30) +#define TIMER3_FREQUENCY_KHZ (tmrHw_HIGH_FREQUENCY_HZ / 1000 * 30) +#else +#define TIMER0_FREQUENCY_MHZ tmrHw_LOW_FREQUENCY_MHZ +#define TIMER1_FREQUENCY_MHZ tmrHw_LOW_FREQUENCY_MHZ +#define TIMER3_FREQUENCY_MHZ tmrHw_HIGH_FREQUENCY_MHZ +#define TIMER3_FREQUENCY_KHZ (tmrHw_HIGH_FREQUENCY_HZ / 1000) +#endif + +static struct clk sp804_timer012_clk = { + .name = "sp804-timer-0,1,2", + .type = CLK_TYPE_PRIMARY, + .mode = CLK_MODE_XTAL, + .rate_hz = TIMER1_FREQUENCY_MHZ * 1000000, +}; + +static struct clk sp804_timer3_clk = { + .name = "sp804-timer-3", + .type = CLK_TYPE_PRIMARY, + .mode = CLK_MODE_XTAL, + .rate_hz = TIMER3_FREQUENCY_KHZ * 1000, +}; + static struct clk_lookup lookups[] = { { /* Bus clock */ .con_id = "apb_pclk", @@ -107,6 +135,18 @@ static struct clk_lookup lookups[] = { }, { /* UART1 */ .dev_id = "uartb", .clk = &uart_clk, + }, { /* SP804 timer 0 */ + .dev_id = "sp804", + .con_id = "timer0", + .clk = &sp804_timer012_clk, + }, { /* SP804 timer 1 */ + .dev_id = "sp804", + .con_id = "timer1", + .clk = &sp804_timer012_clk, + }, { /* SP804 timer 3 */ + .dev_id = "sp804", + .con_id = "timer3", + .clk = &sp804_timer3_clk, } }; @@ -151,8 +191,6 @@ void __init bcmring_amba_init(void) chipcHw_busInterfaceClockEnable(bus_clock); - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; amba_device_register(d, &iomem_resource); @@ -162,170 +200,18 @@ void __init bcmring_amba_init(void) /* * Where is the timer (VA)? */ -#define TIMER0_VA_BASE MM_IO_BASE_TMR -#define TIMER1_VA_BASE (MM_IO_BASE_TMR + 0x20) -#define TIMER2_VA_BASE (MM_IO_BASE_TMR + 0x40) -#define TIMER3_VA_BASE (MM_IO_BASE_TMR + 0x60) - -/* Timer 0 - 25 MHz, Timer3 at bus clock rate, typically 150-166 MHz */ -#if defined(CONFIG_ARCH_FPGA11107) -/* fpga cpu/bus are currently 30 times slower so scale frequency as well to */ -/* slow down Linux's sense of time */ -#define TIMER0_FREQUENCY_MHZ (tmrHw_LOW_FREQUENCY_MHZ * 30) -#define TIMER1_FREQUENCY_MHZ (tmrHw_LOW_FREQUENCY_MHZ * 30) -#define TIMER3_FREQUENCY_MHZ (tmrHw_HIGH_FREQUENCY_MHZ * 30) -#define TIMER3_FREQUENCY_KHZ (tmrHw_HIGH_FREQUENCY_HZ / 1000 * 30) -#else -#define TIMER0_FREQUENCY_MHZ tmrHw_LOW_FREQUENCY_MHZ -#define TIMER1_FREQUENCY_MHZ tmrHw_LOW_FREQUENCY_MHZ -#define TIMER3_FREQUENCY_MHZ tmrHw_HIGH_FREQUENCY_MHZ -#define TIMER3_FREQUENCY_KHZ (tmrHw_HIGH_FREQUENCY_HZ / 1000) -#endif - -#define TICKS_PER_uSEC TIMER0_FREQUENCY_MHZ - -/* - * These are useconds NOT ticks. - * - */ -#define mSEC_1 1000 -#define mSEC_5 (mSEC_1 * 5) -#define mSEC_10 (mSEC_1 * 10) -#define mSEC_25 (mSEC_1 * 25) -#define SEC_1 (mSEC_1 * 1000) - -/* - * How long is the timer interval? - */ -#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) -#if TIMER_INTERVAL >= 0x100000 -#define TIMER_RELOAD (TIMER_INTERVAL >> 8) -#define TIMER_DIVISOR (TIMER_CTRL_DIV256) -#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC) -#elif TIMER_INTERVAL >= 0x10000 -#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */ -#define TIMER_DIVISOR (TIMER_CTRL_DIV16) -#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC) -#else -#define TIMER_RELOAD (TIMER_INTERVAL) -#define TIMER_DIVISOR (TIMER_CTRL_DIV1) -#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) -#endif - -static void timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *clk) -{ - unsigned long ctrl; - - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD); - - ctrl = TIMER_CTRL_PERIODIC; - ctrl |= - TIMER_DIVISOR | 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_DIVISOR | TIMER_CTRL_32BIT | TIMER_CTRL_IE; - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - default: - ctrl = 0; - } - - writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL); -} - -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, -}; - -/* - * IRQ handler for the timer - */ -static irqreturn_t bcmring_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = &timer0_clockevent; - - writel(1, TIMER0_VA_BASE + TIMER_INTCLR); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct irqaction bcmring_timer_irq = { - .name = "bcmring Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = bcmring_timer_interrupt, -}; - -static cycle_t bcmring_get_cycles_timer1(struct clocksource *cs) -{ - return ~readl(TIMER1_VA_BASE + TIMER_VALUE); -} - -static cycle_t bcmring_get_cycles_timer3(struct clocksource *cs) -{ - return ~readl(TIMER3_VA_BASE + TIMER_VALUE); -} - -static struct clocksource clocksource_bcmring_timer1 = { - .name = "timer1", - .rating = 200, - .read = bcmring_get_cycles_timer1, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static struct clocksource clocksource_bcmring_timer3 = { - .name = "timer3", - .rating = 100, - .read = bcmring_get_cycles_timer3, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; +#define TIMER0_VA_BASE ((void __iomem *)MM_IO_BASE_TMR) +#define TIMER1_VA_BASE ((void __iomem *)(MM_IO_BASE_TMR + 0x20)) +#define TIMER2_VA_BASE ((void __iomem *)(MM_IO_BASE_TMR + 0x40)) +#define TIMER3_VA_BASE ((void __iomem *)(MM_IO_BASE_TMR + 0x60)) static int __init bcmring_clocksource_init(void) { /* setup timer1 as free-running clocksource */ - writel(0, TIMER1_VA_BASE + TIMER_CTRL); - writel(0xffffffff, TIMER1_VA_BASE + TIMER_LOAD); - writel(0xffffffff, TIMER1_VA_BASE + TIMER_VALUE); - writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, - TIMER1_VA_BASE + TIMER_CTRL); - - clocksource_register_khz(&clocksource_bcmring_timer1, - TIMER1_FREQUENCY_MHZ * 1000); + sp804_clocksource_init(TIMER1_VA_BASE, "timer1"); /* setup timer3 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_register_khz(&clocksource_bcmring_timer3, - TIMER3_FREQUENCY_KHZ); + sp804_clocksource_init(TIMER3_VA_BASE, "timer3"); return 0; } @@ -347,21 +233,16 @@ void __init bcmring_init_timer(void) /* * Make irqs happen for the system timer */ - setup_irq(IRQ_TIMER0, &bcmring_timer_irq); - bcmring_clocksource_init(); - 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); - - timer0_clockevent.cpumask = cpumask_of(0); - clockevents_register_device(&timer0_clockevent); + sp804_clockevents_register(TIMER0_VA_BASE, IRQ_TIMER0, "timer0"); } struct sys_timer bcmring_timer = { .init = bcmring_init_timer, }; + +void __init bcmring_init_early(void) +{ + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); +} diff --git a/arch/arm/mach-bcmring/core.h b/arch/arm/mach-bcmring/core.h index b197ba48e36e..e0e02c48f9b1 100644 --- a/arch/arm/mach-bcmring/core.h +++ b/arch/arm/mach-bcmring/core.h @@ -25,6 +25,7 @@ void __init bcmring_amba_init(void); void __init bcmring_map_io(void); void __init bcmring_init_irq(void); +void __init bcmring_init_early(void); extern struct sys_timer bcmring_timer; #endif diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 32f147998cd9..c0deacae778d 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -63,6 +63,7 @@ config MACH_DAVINCI_EVM depends on ARCH_DAVINCI_DM644x select MISC_DEVICES select EEPROM_AT24 + select I2C help Configure this option to specify the whether the board used for development is a DM644x EVM @@ -72,6 +73,7 @@ config MACH_SFFSDR depends on ARCH_DAVINCI_DM644x select MISC_DEVICES select EEPROM_AT24 + select I2C help Say Y here to select the Lyrtech Small Form Factor Software Defined Radio (SFFSDR) board. @@ -105,6 +107,7 @@ config MACH_DAVINCI_DM6467_EVM select MACH_DAVINCI_DM6467TEVM select MISC_DEVICES select EEPROM_AT24 + select I2C help Configure this option to specify the whether the board used for development is a DM6467 EVM @@ -118,6 +121,7 @@ config MACH_DAVINCI_DM365_EVM depends on ARCH_DAVINCI_DM365 select MISC_DEVICES select EEPROM_AT24 + select I2C help Configure this option to specify whether the board used for development is a DM365 EVM @@ -129,6 +133,7 @@ config MACH_DAVINCI_DA830_EVM select GPIO_PCF857X select MISC_DEVICES select EEPROM_AT24 + select I2C help Say Y here to select the TI DA830/OMAP-L137/AM17x Evaluation Module. @@ -205,6 +210,7 @@ config MACH_MITYOMAPL138 depends on ARCH_DAVINCI_DA850 select MISC_DEVICES select EEPROM_AT24 + select I2C help Say Y here to select the Critical Link MityDSP-L138/MityARM-1808 System on Module. Information on this SoM may be found at diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index 2aa79c54f98e..606a6f27ed6c 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -29,7 +29,7 @@ #include <mach/mux.h> #include <mach/spi.h> -#define MITYOMAPL138_PHY_ID "0:03" +#define MITYOMAPL138_PHY_ID "" #define FACTORY_CONFIG_MAGIC 0x012C0138 #define FACTORY_CONFIG_VERSION 0x00010001 @@ -414,7 +414,7 @@ static struct resource mityomapl138_nandflash_resource[] = { static struct platform_device mityomapl138_nandflash_device = { .name = "davinci_nand", - .id = 0, + .id = 1, .dev = { .platform_data = &mityomapl138_nandflash_data, }, diff --git a/arch/arm/mach-davinci/cpufreq.c b/arch/arm/mach-davinci/cpufreq.c index 0a95be1512bb..41669ecc1f91 100644 --- a/arch/arm/mach-davinci/cpufreq.c +++ b/arch/arm/mach-davinci/cpufreq.c @@ -94,9 +94,7 @@ static int davinci_target(struct cpufreq_policy *policy, if (freqs.old == freqs.new) return ret; - cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, - dev_driver_string(cpufreq.dev), - "transition: %u --> %u\n", freqs.old, freqs.new); + dev_dbg(&cpufreq.dev, "transition: %u --> %u\n", freqs.old, freqs.new); ret = cpufreq_frequency_table_target(policy, pdata->freq_table, freqs.new, relation, &idx); diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 625d4b66718b..58a02dc7b15a 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -39,7 +39,8 @@ #define DA8XX_GPIO_BASE 0x01e26000 #define DA8XX_I2C1_BASE 0x01e28000 #define DA8XX_SPI0_BASE 0x01c41000 -#define DA8XX_SPI1_BASE 0x01f0e000 +#define DA830_SPI1_BASE 0x01e12000 +#define DA850_SPI1_BASE 0x01f0e000 #define DA8XX_EMAC_CTRL_REG_OFFSET 0x3000 #define DA8XX_EMAC_MOD_REG_OFFSET 0x2000 @@ -762,8 +763,8 @@ static struct resource da8xx_spi0_resources[] = { static struct resource da8xx_spi1_resources[] = { [0] = { - .start = DA8XX_SPI1_BASE, - .end = DA8XX_SPI1_BASE + SZ_4K - 1, + .start = DA830_SPI1_BASE, + .end = DA830_SPI1_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -832,5 +833,10 @@ int __init da8xx_register_spi(int instance, struct spi_board_info *info, da8xx_spi_pdata[instance].num_chipselect = len; + if (instance == 1 && cpu_is_davinci_da850()) { + da8xx_spi1_resources[0].start = DA850_SPI1_BASE; + da8xx_spi1_resources[0].end = DA850_SPI1_BASE + SZ_4K - 1; + } + return platform_device_register(&da8xx_spi_device[instance]); } diff --git a/arch/arm/mach-davinci/include/mach/debug-macro.S b/arch/arm/mach-davinci/include/mach/debug-macro.S index 9f1befc5ac38..f8b7ea4f6235 100644 --- a/arch/arm/mach-davinci/include/mach/debug-macro.S +++ b/arch/arm/mach-davinci/include/mach/debug-macro.S @@ -24,6 +24,9 @@ #define UART_SHIFT 2 +#define davinci_uart_v2p(x) ((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET) +#define davinci_uart_p2v(x) ((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET) + .pushsection .data davinci_uart_phys: .word 0 davinci_uart_virt: .word 0 @@ -34,7 +37,7 @@ davinci_uart_virt: .word 0 /* Use davinci_uart_phys/virt if already configured */ 10: mrc p15, 0, \rp, c1, c0 tst \rp, #1 @ MMU enabled? - ldreq \rp, =__virt_to_phys(davinci_uart_phys) + ldreq \rp, =davinci_uart_v2p(davinci_uart_phys) ldrne \rp, =davinci_uart_phys add \rv, \rp, #4 @ davinci_uart_virt ldr \rp, [\rp, #0] @@ -48,18 +51,18 @@ davinci_uart_virt: .word 0 tst \rp, #1 @ MMU enabled? /* Copy uart phys address from decompressor uart info */ - ldreq \rv, =__virt_to_phys(davinci_uart_phys) + ldreq \rv, =davinci_uart_v2p(davinci_uart_phys) ldrne \rv, =davinci_uart_phys ldreq \rp, =DAVINCI_UART_INFO - ldrne \rp, =__phys_to_virt(DAVINCI_UART_INFO) + ldrne \rp, =davinci_uart_p2v(DAVINCI_UART_INFO) ldr \rp, [\rp, #0] str \rp, [\rv] /* Copy uart virt address from decompressor uart info */ - ldreq \rv, =__virt_to_phys(davinci_uart_virt) + ldreq \rv, =davinci_uart_v2p(davinci_uart_virt) ldrne \rv, =davinci_uart_virt ldreq \rp, =DAVINCI_UART_INFO - ldrne \rp, =__phys_to_virt(DAVINCI_UART_INFO) + ldrne \rp, =davinci_uart_p2v(DAVINCI_UART_INFO) ldr \rp, [\rp, #4] str \rp, [\rv] diff --git a/arch/arm/mach-davinci/include/mach/memory.h b/arch/arm/mach-davinci/include/mach/memory.h index 78822723f382..491249ef209c 100644 --- a/arch/arm/mach-davinci/include/mach/memory.h +++ b/arch/arm/mach-davinci/include/mach/memory.h @@ -41,27 +41,11 @@ */ #define CONSISTENT_DMA_SIZE (14<<20) -#ifndef __ASSEMBLY__ /* * Restrict DMA-able region to workaround silicon bug. The bug * restricts buffers available for DMA to video hardware to be * below 128M */ -static inline void -__arch_adjust_zones(unsigned long *size, unsigned long *holes) -{ - unsigned int sz = (128<<20) >> PAGE_SHIFT; - - size[1] = size[0] - sz; - size[0] = sz; -} - -#define arch_adjust_zones(zone_size, holes) \ - if ((meminfo.bank[0].size >> 20) > 128) __arch_adjust_zones(zone_size, holes) - -#define ISA_DMA_THRESHOLD (PHYS_OFFSET + (128<<20) - 1) -#define MAX_DMA_ADDRESS (PAGE_OFFSET + (128<<20)) - -#endif +#define ARM_DMA_ZONE_SIZE SZ_128M #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/arch/arm/mach-davinci/include/mach/serial.h b/arch/arm/mach-davinci/include/mach/serial.h index 8051110b8ac3..c9e6ce185a66 100644 --- a/arch/arm/mach-davinci/include/mach/serial.h +++ b/arch/arm/mach-davinci/include/mach/serial.h @@ -22,7 +22,7 @@ * * This area sits just below the page tables (see arch/arm/kernel/head.S). */ -#define DAVINCI_UART_INFO (PHYS_OFFSET + 0x3ff8) +#define DAVINCI_UART_INFO (PLAT_PHYS_OFFSET + 0x3ff8) #define DAVINCI_UART0_BASE (IO_PHYS + 0x20000) #define DAVINCI_UART1_BASE (IO_PHYS + 0x20400) diff --git a/arch/arm/mach-exynos4/include/mach/smp.h b/arch/arm/mach-exynos4/include/mach/smp.h deleted file mode 100644 index a463dcebcfd3..000000000000 --- a/arch/arm/mach-exynos4/include/mach/smp.h +++ /dev/null @@ -1,19 +0,0 @@ -/* linux/arch/arm/mach-exynos4/include/mach/smp.h - * - * Cloned from arch/arm/mach-realview/include/mach/smp.h -*/ - -#ifndef ASM_ARCH_SMP_H -#define ASM_ARCH_SMP_H __FILE__ - -#include <asm/hardware/gic.h> - -/* - * We use IRQ1 as the IPI - */ -static inline void smp_cross_call(const struct cpumask *mask, int ipi) -{ - gic_raise_softirq(mask, ipi); -} - -#endif diff --git a/arch/arm/mach-exynos4/platsmp.c b/arch/arm/mach-exynos4/platsmp.c index 6d35878ec1aa..c5e65a02be8d 100644 --- a/arch/arm/mach-exynos4/platsmp.c +++ b/arch/arm/mach-exynos4/platsmp.c @@ -22,6 +22,7 @@ #include <linux/io.h> #include <asm/cacheflush.h> +#include <asm/hardware/gic.h> #include <asm/smp_scu.h> #include <asm/unified.h> @@ -104,7 +105,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) * the boot monitor to read the system wide flags register, * and branch to the address found there. */ - smp_cross_call(cpumask_of(cpu), 1); + gic_raise_softirq(cpumask_of(cpu), 1); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { @@ -147,6 +148,8 @@ void __init smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); + + set_smp_cross_call(gic_raise_softirq); } void __init platform_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c index 10d917d9e3ad..8755ca8dd48d 100644 --- a/arch/arm/mach-exynos4/pm.c +++ b/arch/arm/mach-exynos4/pm.c @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/suspend.h> +#include <linux/syscore_ops.h> #include <linux/io.h> #include <asm/cacheflush.h> @@ -372,7 +373,27 @@ void exynos4_scu_enable(void __iomem *scu_base) flush_cache_all(); } -static int exynos4_pm_resume(struct sys_device *dev) +static struct sysdev_driver exynos4_pm_driver = { + .add = exynos4_pm_add, +}; + +static __init int exynos4_pm_drvinit(void) +{ + unsigned int tmp; + + s3c_pm_init(); + + /* All wakeup disable */ + + tmp = __raw_readl(S5P_WAKEUP_MASK); + tmp |= ((0xFF << 8) | (0x1F << 1)); + __raw_writel(tmp, S5P_WAKEUP_MASK); + + return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver); +} +arch_initcall(exynos4_pm_drvinit); + +static void exynos4_pm_resume(void) { /* For release retention */ @@ -394,27 +415,15 @@ static int exynos4_pm_resume(struct sys_device *dev) /* enable L2X0*/ writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL); #endif - - return 0; } -static struct sysdev_driver exynos4_pm_driver = { - .add = exynos4_pm_add, +static struct syscore_ops exynos4_pm_syscore_ops = { .resume = exynos4_pm_resume, }; -static __init int exynos4_pm_drvinit(void) +static __init int exynos4_pm_syscore_init(void) { - unsigned int tmp; - - s3c_pm_init(); - - /* All wakeup disable */ - - tmp = __raw_readl(S5P_WAKEUP_MASK); - tmp |= ((0xFF << 8) | (0x1F << 1)); - __raw_writel(tmp, S5P_WAKEUP_MASK); - - return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver); + register_syscore_ops(&exynos4_pm_syscore_ops); + return 0; } -arch_initcall(exynos4_pm_drvinit); +arch_initcall(exynos4_pm_syscore_init); diff --git a/arch/arm/mach-footbridge/Kconfig b/arch/arm/mach-footbridge/Kconfig index bdd257921cfb..46adca068f2c 100644 --- a/arch/arm/mach-footbridge/Kconfig +++ b/arch/arm/mach-footbridge/Kconfig @@ -4,6 +4,7 @@ menu "Footbridge Implementations" config ARCH_CATS bool "CATS" + select CLKSRC_I8253 select FOOTBRIDGE_HOST select ISA select ISA_DMA @@ -59,6 +60,7 @@ config ARCH_EBSA285_HOST config ARCH_NETWINDER bool "NetWinder" + select CLKSRC_I8253 select FOOTBRIDGE_HOST select ISA select ISA_DMA diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c index 441c6ce0d555..7020f1a3feca 100644 --- a/arch/arm/mach-footbridge/isa-timer.c +++ b/arch/arm/mach-footbridge/isa-timer.c @@ -10,53 +10,16 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/spinlock.h> #include <linux/timex.h> #include <asm/irq.h> - +#include <asm/i8253.h> #include <asm/mach/time.h> #include "common.h" -#define PIT_MODE 0x43 -#define PIT_CH0 0x40 - -#define PIT_LATCH ((PIT_TICK_RATE + HZ / 2) / HZ) - -static cycle_t pit_read(struct clocksource *cs) -{ - unsigned long flags; - static int old_count; - static u32 old_jifs; - int count; - u32 jifs; - - raw_local_irq_save(flags); - - jifs = jiffies; - outb_p(0x00, PIT_MODE); /* latch the count */ - count = inb_p(PIT_CH0); /* read the latched count */ - count |= inb_p(PIT_CH0) << 8; - - if (count > old_count && jifs == old_jifs) - count = old_count; - - old_count = count; - old_jifs = jifs; - - raw_local_irq_restore(flags); - - count = (PIT_LATCH - 1) - count; - - return (cycle_t)(jifs * PIT_LATCH) + count; -} - -static struct clocksource pit_cs = { - .name = "pit", - .rating = 110, - .read = pit_read, - .mask = CLOCKSOURCE_MASK(32), -}; +DEFINE_RAW_SPINLOCK(i8253_lock); static void pit_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) @@ -121,7 +84,7 @@ static void __init isa_timer_init(void) pit_ce.max_delta_ns = clockevent_delta2ns(0x7fff, &pit_ce); pit_ce.min_delta_ns = clockevent_delta2ns(0x000f, &pit_ce); - clocksource_register_hz(&pit_cs, PIT_TICK_RATE); + clocksource_i8253_init(); setup_irq(pit_ce.irq, &pit_timer_irq); clockevents_register_device(&pit_ce); diff --git a/arch/arm/mach-h720x/include/mach/memory.h b/arch/arm/mach-h720x/include/mach/memory.h index 9d3687651462..b0b3baec9acf 100644 --- a/arch/arm/mach-h720x/include/mach/memory.h +++ b/arch/arm/mach-h720x/include/mach/memory.h @@ -13,7 +13,6 @@ * There should not be more than (0xd0000000 - 0xc0000000) * bytes of RAM. */ -#define ISA_DMA_THRESHOLD (PHYS_OFFSET + SZ_256M - 1) -#define MAX_DMA_ADDRESS (PAGE_OFFSET + SZ_256M) +#define ARM_DMA_ZONE_SIZE SZ_256M #endif diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig index d701d32a07f1..dfd18f3b50e8 100644 --- a/arch/arm/mach-integrator/Kconfig +++ b/arch/arm/mach-integrator/Kconfig @@ -4,6 +4,7 @@ menu "Integrator Options" config ARCH_INTEGRATOR_AP bool "Support Integrator/AP and Integrator/PP2 platforms" + select CLKSRC_MMIO select MIGHT_HAVE_PCI help Include support for the ARM(R) Integrator/AP and diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 980803ff348c..2fbbdd5eac35 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -24,13 +24,14 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/string.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/amba/bus.h> #include <linux/amba/kmi.h> #include <linux/clocksource.h> #include <linux/clockchips.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/mtd/physmap.h> #include <mach/hardware.h> #include <mach/platform.h> @@ -43,7 +44,6 @@ #include <mach/lm.h> #include <asm/mach/arch.h> -#include <asm/mach/flash.h> #include <asm/mach/irq.h> #include <asm/mach/map.h> #include <asm/mach/time.h> @@ -180,13 +180,13 @@ static void __init ap_init_irq(void) #ifdef CONFIG_PM static unsigned long ic_irq_enable; -static int irq_suspend(struct sys_device *dev, pm_message_t state) +static int irq_suspend(void) { ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE); return 0; } -static int irq_resume(struct sys_device *dev) +static void irq_resume(void) { /* disable all irq sources */ writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR); @@ -194,33 +194,25 @@ static int irq_resume(struct sys_device *dev) writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR); writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET); - return 0; } #else #define irq_suspend NULL #define irq_resume NULL #endif -static struct sysdev_class irq_class = { - .name = "irq", +static struct syscore_ops irq_syscore_ops = { .suspend = irq_suspend, .resume = irq_resume, }; -static struct sys_device irq_device = { - .id = 0, - .cls = &irq_class, -}; - -static int __init irq_init_sysfs(void) +static int __init irq_syscore_init(void) { - int ret = sysdev_class_register(&irq_class); - if (ret == 0) - ret = sysdev_register(&irq_device); - return ret; + register_syscore_ops(&irq_syscore_ops); + + return 0; } -device_initcall(irq_init_sysfs); +device_initcall(irq_syscore_init); /* * Flash handling. @@ -230,7 +222,7 @@ device_initcall(irq_init_sysfs); #define EBI_CSR1 (VA_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET) #define EBI_LOCK (VA_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET) -static int ap_flash_init(void) +static int ap_flash_init(struct platform_device *dev) { u32 tmp; @@ -247,7 +239,7 @@ static int ap_flash_init(void) return 0; } -static void ap_flash_exit(void) +static void ap_flash_exit(struct platform_device *dev) { u32 tmp; @@ -263,15 +255,14 @@ static void ap_flash_exit(void) } } -static void ap_flash_set_vpp(int on) +static void ap_flash_set_vpp(struct platform_device *pdev, int on) { void __iomem *reg = on ? SC_CTRLS : SC_CTRLC; writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg); } -static struct flash_platform_data ap_flash_data = { - .map_name = "cfi_probe", +static struct physmap_flash_data ap_flash_data = { .width = 4, .init = ap_flash_init, .exit = ap_flash_exit, @@ -285,7 +276,7 @@ static struct resource cfi_flash_resource = { }; static struct platform_device cfi_flash_device = { - .name = "armflash", + .name = "physmap-flash", .id = 0, .dev = { .platform_data = &ap_flash_data, @@ -343,25 +334,9 @@ static void __init ap_init(void) static unsigned long timer_reload; -static void __iomem * const clksrc_base = (void __iomem *)TIMER2_VA_BASE; - -static cycle_t timersp_read(struct clocksource *cs) -{ - return ~(readl(clksrc_base + TIMER_VALUE) & 0xffff); -} - -static struct clocksource clocksource_timersp = { - .name = "timer2", - .rating = 200, - .read = timersp_read, - .mask = CLOCKSOURCE_MASK(16), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - static void integrator_clocksource_init(u32 khz) { - struct clocksource *cs = &clocksource_timersp; - void __iomem *base = clksrc_base; + void __iomem *base = (void __iomem *)TIMER2_VA_BASE; u32 ctrl = TIMER_CTRL_ENABLE; if (khz >= 1500) { @@ -372,7 +347,8 @@ static void integrator_clocksource_init(u32 khz) writel(ctrl, base + TIMER_CTRL); writel(0xffff, base + TIMER_LOAD); - clocksource_register_khz(cs, khz); + clocksource_mmio_init(base + TIMER_VALUE, "timer2", + khz * 1000, 200, 16, clocksource_mmio_readl_down); } static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE; diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 9e3ce26023e8..4eb03ab5cb46 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -22,6 +22,7 @@ #include <linux/io.h> #include <linux/gfp.h> #include <linux/clkdev.h> +#include <linux/mtd/physmap.h> #include <mach/hardware.h> #include <mach/platform.h> @@ -35,7 +36,6 @@ #include <mach/lm.h> #include <asm/mach/arch.h> -#include <asm/mach/flash.h> #include <asm/mach/irq.h> #include <asm/mach/map.h> #include <asm/mach/time.h> @@ -229,17 +229,24 @@ static struct clk cp_auxclk = { .vcoreg = CM_AUXOSC, }; +static struct clk sp804_clk = { + .rate = 1000000, +}; + static struct clk_lookup cp_lookups[] = { { /* CLCD */ .dev_id = "mb:c0", .clk = &cp_auxclk, + }, { /* SP804 timers */ + .dev_id = "sp804", + .clk = &sp804_clk, }, }; /* * Flash handling. */ -static int intcp_flash_init(void) +static int intcp_flash_init(struct platform_device *dev) { u32 val; @@ -250,7 +257,7 @@ static int intcp_flash_init(void) return 0; } -static void intcp_flash_exit(void) +static void intcp_flash_exit(struct platform_device *dev) { u32 val; @@ -259,7 +266,7 @@ static void intcp_flash_exit(void) writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); } -static void intcp_flash_set_vpp(int on) +static void intcp_flash_set_vpp(struct platform_device *pdev, int on) { u32 val; @@ -271,8 +278,7 @@ static void intcp_flash_set_vpp(int on) writel(val, INTCP_VA_CTRL_BASE + INTCP_FLASHPROG); } -static struct flash_platform_data intcp_flash_data = { - .map_name = "cfi_probe", +static struct physmap_flash_data intcp_flash_data = { .width = 4, .init = intcp_flash_init, .exit = intcp_flash_exit, @@ -286,7 +292,7 @@ static struct resource intcp_flash_resource = { }; static struct platform_device intcp_flash_device = { - .name = "armflash", + .name = "physmap-flash", .id = 0, .dev = { .platform_data = &intcp_flash_data, @@ -476,8 +482,8 @@ static void __init intcp_timer_init(void) writel(0, TIMER1_VA_BASE + TIMER_CTRL); writel(0, TIMER2_VA_BASE + TIMER_CTRL); - sp804_clocksource_init(TIMER2_VA_BASE); - sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1); + sp804_clocksource_init(TIMER2_VA_BASE, "timer2"); + sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1, "timer1"); } static struct sys_timer cp_timer = { diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c index a54b3db80366..e9a589395723 100644 --- a/arch/arm/mach-ixp4xx/common-pci.c +++ b/arch/arm/mach-ixp4xx/common-pci.c @@ -342,29 +342,6 @@ int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) return (dev->bus == &pci_bus_type ) && ((dma_addr + size) >= SZ_64M); } -/* - * Only first 64MB of memory can be accessed via PCI. - * We use GFP_DMA to allocate safe buffers to do map/unmap. - * This is really ugly and we need a better way of specifying - * DMA-capable regions of memory. - */ -void __init ixp4xx_adjust_zones(unsigned long *zone_size, - unsigned long *zhole_size) -{ - unsigned int sz = SZ_64M >> PAGE_SHIFT; - - /* - * Only adjust if > 64M on current system - */ - if (zone_size[0] <= sz) - return; - - zone_size[1] = zone_size[0] - sz; - zone_size[0] = sz; - zhole_size[1] = zhole_size[0]; - zhole_size[0] = 0; -} - void __init ixp4xx_pci_preinit(void) { unsigned long cpuid = read_cpuid_id(); diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index ed19bc314318..74ed81a3cb1a 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -419,26 +419,14 @@ static void notrace ixp4xx_update_sched_clock(void) /* * clocksource */ -static cycle_t ixp4xx_get_cycles(struct clocksource *cs) -{ - return *IXP4XX_OSTS; -} - -static struct clocksource clocksource_ixp4xx = { - .name = "OSTS", - .rating = 200, - .read = ixp4xx_get_cycles, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ; EXPORT_SYMBOL(ixp4xx_timer_freq); static void __init ixp4xx_clocksource_init(void) { init_sched_clock(&cd, ixp4xx_update_sched_clock, 32, ixp4xx_timer_freq); - clocksource_register_hz(&clocksource_ixp4xx, ixp4xx_timer_freq); + clocksource_mmio_init(&IXP4XX_OSTS, "OSTS", ixp4xx_timer_freq, 200, 32, + clocksource_mmio_readl_up); } /* diff --git a/arch/arm/mach-ixp4xx/include/mach/memory.h b/arch/arm/mach-ixp4xx/include/mach/memory.h index 6d388c9d0e20..34e79404671a 100644 --- a/arch/arm/mach-ixp4xx/include/mach/memory.h +++ b/arch/arm/mach-ixp4xx/include/mach/memory.h @@ -14,16 +14,8 @@ */ #define PLAT_PHYS_OFFSET UL(0x00000000) -#if !defined(__ASSEMBLY__) && defined(CONFIG_PCI) - -void ixp4xx_adjust_zones(unsigned long *size, unsigned long *holes); - -#define arch_adjust_zones(size, holes) \ - ixp4xx_adjust_zones(size, holes) - -#define ISA_DMA_THRESHOLD (SZ_64M - 1) -#define MAX_DMA_ADDRESS (PAGE_OFFSET + SZ_64M) - +#ifdef CONFIG_PCI +#define ARM_DMA_ZONE_SIZE SZ_64M #endif #endif diff --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c index 6162ac308c20..b42c909bbeeb 100644 --- a/arch/arm/mach-lpc32xx/timer.c +++ b/arch/arm/mach-lpc32xx/timer.c @@ -31,19 +31,6 @@ #include <mach/platform.h> #include "common.h" -static cycle_t lpc32xx_clksrc_read(struct clocksource *cs) -{ - return (cycle_t)__raw_readl(LCP32XX_TIMER_TC(LPC32XX_TIMER1_BASE)); -} - -static struct clocksource lpc32xx_clksrc = { - .name = "lpc32xx_clksrc", - .rating = 300, - .read = lpc32xx_clksrc_read, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - static int lpc32xx_clkevt_next_event(unsigned long delta, struct clock_event_device *dev) { @@ -170,7 +157,9 @@ static void __init lpc32xx_timer_init(void) __raw_writel(0, LCP32XX_TIMER_MCR(LPC32XX_TIMER1_BASE)); __raw_writel(LCP32XX_TIMER_CNTR_TCR_EN, LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE)); - clocksource_register_hz(&lpc32xx_clksrc, clkrate); + + clocksource_mmio_init(LCP32XX_TIMER_TC(LPC32XX_TIMER1_BASE), + "lpc32xx_clksrc", clkrate, 300, 32, clocksource_mmio_readl_up); } struct sys_timer lpc32xx_timer = { diff --git a/arch/arm/mach-msm/include/mach/smp.h b/arch/arm/mach-msm/include/mach/smp.h deleted file mode 100644 index 3c01000ecc80..000000000000 --- a/arch/arm/mach-msm/include/mach/smp.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only 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. - */ - -#ifndef __ASM_ARCH_MSM_SMP_H -#define __ASM_ARCH_MSM_SMP_H - -#include <asm/hardware/gic.h> - -static inline void smp_cross_call(const struct cpumask *mask, int ipi) -{ - gic_raise_softirq(mask, ipi); -} - -#endif diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index 0f427bc94447..2034098cf015 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -119,7 +119,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) * the boot monitor to read the system wide flags register, * and branch to the address found there. */ - smp_cross_call(cpumask_of(cpu), 1); + gic_raise_softirq(cpumask_of(cpu), 1); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { @@ -151,6 +151,8 @@ void __init smp_init_cpus(void) for (i = 0; i < NR_CPUS; i++) set_cpu_possible(i, true); + + set_smp_cross_call(gic_raise_softirq); } void __init platform_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-mx3/mach-vpr200.c b/arch/arm/mach-mx3/mach-vpr200.c index 2cf390fbd980..47a69cbc31a8 100644 --- a/arch/arm/mach-mx3/mach-vpr200.c +++ b/arch/arm/mach-mx3/mach-vpr200.c @@ -257,11 +257,16 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = { .workaround = FLS_USB2_WORKAROUND_ENGCM09152, }; +static int vpr200_usbh_init(struct platform_device *pdev) +{ + return mx35_initialize_usb_hw(pdev->id, + MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY); +} + /* USB HOST config */ static const struct mxc_usbh_platform_data usb_host_pdata __initconst = { - .portsc = MXC_EHCI_MODE_SERIAL, - .flags = MXC_EHCI_INTERFACE_SINGLE_UNI | - MXC_EHCI_INTERNAL_PHY, + .init = vpr200_usbh_init, + .portsc = MXC_EHCI_MODE_SERIAL, }; static struct platform_device *devices[] __initdata = { diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c index 10a1bea10548..6206b1191fe8 100644 --- a/arch/arm/mach-mx5/board-mx53_loco.c +++ b/arch/arm/mach-mx5/board-mx53_loco.c @@ -193,7 +193,7 @@ static iomux_v3_cfg_t mx53_loco_pads[] = { .wakeup = wake, \ } -static const struct gpio_keys_button loco_buttons[] __initconst = { +static struct gpio_keys_button loco_buttons[] = { GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0), GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0), GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0), diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c index 1ad97fed1e94..5dcc59d5b9ec 100644 --- a/arch/arm/mach-mxs/clock-mx28.c +++ b/arch/arm/mach-mxs/clock-mx28.c @@ -295,11 +295,11 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \ unsigned long diff, parent_rate, calc_rate; \ int i; \ \ - parent_rate = clk_get_rate(clk->parent); \ div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV; \ bm_busy = BM_CLKCTRL_##dr##_BUSY; \ \ if (clk->parent == &ref_xtal_clk) { \ + parent_rate = clk_get_rate(clk->parent); \ div = DIV_ROUND_UP(parent_rate, rate); \ if (clk == &cpu_clk) { \ div_max = BM_CLKCTRL_CPU_DIV_XTAL >> \ @@ -309,6 +309,11 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \ if (div == 0 || div > div_max) \ return -EINVAL; \ } else { \ + /* \ + * hack alert: this block modifies clk->parent, too, \ + * so the base to use it the grand parent. \ + */ \ + parent_rate = clk_get_rate(clk->parent->parent); \ rate >>= PARENT_RATE_SHIFT; \ parent_rate >>= PARENT_RATE_SHIFT; \ diff = parent_rate; \ diff --git a/arch/arm/mach-mxs/timer.c b/arch/arm/mach-mxs/timer.c index 13647f301860..cace0d2e5a55 100644 --- a/arch/arm/mach-mxs/timer.c +++ b/arch/arm/mach-mxs/timer.c @@ -101,11 +101,6 @@ static cycle_t timrotv1_get_cycles(struct clocksource *cs) & 0xffff0000) >> 16); } -static cycle_t timrotv2_get_cycles(struct clocksource *cs) -{ - return ~__raw_readl(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1)); -} - static int timrotv1_set_next_event(unsigned long evt, struct clock_event_device *dev) { @@ -230,8 +225,8 @@ static int __init mxs_clockevent_init(struct clk *timer_clk) static struct clocksource clocksource_mxs = { .name = "mxs_timer", .rating = 200, - .read = timrotv2_get_cycles, - .mask = CLOCKSOURCE_MASK(32), + .read = timrotv1_get_cycles, + .mask = CLOCKSOURCE_MASK(16), .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; @@ -239,12 +234,11 @@ static int __init mxs_clocksource_init(struct clk *timer_clk) { unsigned int c = clk_get_rate(timer_clk); - if (timrot_is_v1()) { - clocksource_mxs.read = timrotv1_get_cycles; - clocksource_mxs.mask = CLOCKSOURCE_MASK(16); - } - - clocksource_register_hz(&clocksource_mxs, c); + if (timrot_is_v1()) + clocksource_register_hz(&clocksource_mxs, c); + else + clocksource_mmio_init(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1), + "mxs_timer", c, 200, 32, clocksource_mmio_readl_down); return 0; } diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c index f12f22d09b6c..e24c141ba489 100644 --- a/arch/arm/mach-netx/time.c +++ b/arch/arm/mach-netx/time.c @@ -104,19 +104,6 @@ static struct irqaction netx_timer_irq = { .handler = netx_timer_interrupt, }; -cycle_t netx_get_cycles(struct clocksource *cs) -{ - return readl(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE)); -} - -static struct clocksource clocksource_netx = { - .name = "netx_timer", - .rating = 200, - .read = netx_get_cycles, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - /* * Set up timer interrupt */ @@ -150,7 +137,8 @@ static void __init netx_timer_init(void) writel(NETX_GPIO_COUNTER_CTRL_RUN, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE)); - clocksource_register_hz(&clocksource_netx, CLOCK_TICK_RATE); + clocksource_mmio_init(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE), + "netx_timer", CLOCK_TICK_RATE, 200, 32, clocksource_mmio_readl_up); netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, netx_clockevent.shift); diff --git a/arch/arm/mach-omap1/flash.c b/arch/arm/mach-omap1/flash.c index acd161666408..1749cb37dda0 100644 --- a/arch/arm/mach-omap1/flash.c +++ b/arch/arm/mach-omap1/flash.c @@ -13,7 +13,7 @@ #include <plat/tc.h> #include <plat/flash.h> -void omap1_set_vpp(struct map_info *map, int enable) +void omap1_set_vpp(struct platform_device *pdev, int enable) { static int count; u32 l; diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c index 6588c22b8a64..fe31d933f0ed 100644 --- a/arch/arm/mach-omap1/pm_bus.c +++ b/arch/arm/mach-omap1/pm_bus.c @@ -24,75 +24,50 @@ #ifdef CONFIG_PM_RUNTIME static int omap1_pm_runtime_suspend(struct device *dev) { - struct clk *iclk, *fclk; - int ret = 0; + int ret; dev_dbg(dev, "%s\n", __func__); ret = pm_generic_runtime_suspend(dev); + if (ret) + return ret; - fclk = clk_get(dev, "fck"); - if (!IS_ERR(fclk)) { - clk_disable(fclk); - clk_put(fclk); - } - - iclk = clk_get(dev, "ick"); - if (!IS_ERR(iclk)) { - clk_disable(iclk); - clk_put(iclk); + ret = pm_runtime_clk_suspend(dev); + if (ret) { + pm_generic_runtime_resume(dev); + return ret; } return 0; -}; +} static int omap1_pm_runtime_resume(struct device *dev) { - struct clk *iclk, *fclk; - dev_dbg(dev, "%s\n", __func__); - iclk = clk_get(dev, "ick"); - if (!IS_ERR(iclk)) { - clk_enable(iclk); - clk_put(iclk); - } + pm_runtime_clk_resume(dev); + return pm_generic_runtime_resume(dev); +} - fclk = clk_get(dev, "fck"); - if (!IS_ERR(fclk)) { - clk_enable(fclk); - clk_put(fclk); - } +static struct dev_power_domain default_power_domain = { + .ops = { + .runtime_suspend = omap1_pm_runtime_suspend, + .runtime_resume = omap1_pm_runtime_resume, + USE_PLATFORM_PM_SLEEP_OPS + }, +}; - return pm_generic_runtime_resume(dev); +static struct pm_clk_notifier_block platform_bus_notifier = { + .pwr_domain = &default_power_domain, + .con_ids = { "ick", "fck", NULL, }, }; static int __init omap1_pm_runtime_init(void) { - const struct dev_pm_ops *pm; - struct dev_pm_ops *omap_pm; - if (!cpu_class_is_omap1()) return -ENODEV; - pm = platform_bus_get_pm_ops(); - if (!pm) { - pr_err("%s: unable to get dev_pm_ops from platform_bus\n", - __func__); - return -ENODEV; - } - - omap_pm = kmemdup(pm, sizeof(struct dev_pm_ops), GFP_KERNEL); - if (!omap_pm) { - pr_err("%s: unable to alloc memory for new dev_pm_ops\n", - __func__); - return -ENOMEM; - } - - omap_pm->runtime_suspend = omap1_pm_runtime_suspend; - omap_pm->runtime_resume = omap1_pm_runtime_resume; - - platform_bus_set_pm_ops(omap_pm); + pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier); return 0; } diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index 6885d2fac183..03e1e1062ad4 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c @@ -68,49 +68,50 @@ typedef struct { } omap_mpu_timer_regs_t; #define omap_mpu_timer_base(n) \ -((volatile omap_mpu_timer_regs_t*)OMAP1_IO_ADDRESS(OMAP_MPU_TIMER_BASE + \ +((omap_mpu_timer_regs_t __iomem *)OMAP1_IO_ADDRESS(OMAP_MPU_TIMER_BASE + \ (n)*OMAP_MPU_TIMER_OFFSET)) static inline unsigned long notrace omap_mpu_timer_read(int nr) { - volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); - return timer->read_tim; + omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr); + return readl(&timer->read_tim); } static inline void omap_mpu_set_autoreset(int nr) { - volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); + omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr); - timer->cntl = timer->cntl | MPU_TIMER_AR; + writel(readl(&timer->cntl) | MPU_TIMER_AR, &timer->cntl); } static inline void omap_mpu_remove_autoreset(int nr) { - volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); + omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr); - timer->cntl = timer->cntl & ~MPU_TIMER_AR; + writel(readl(&timer->cntl) & ~MPU_TIMER_AR, &timer->cntl); } static inline void omap_mpu_timer_start(int nr, unsigned long load_val, int autoreset) { - volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); - unsigned int timerflags = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_ST); + omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr); + unsigned int timerflags = MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_ST; - if (autoreset) timerflags |= MPU_TIMER_AR; + if (autoreset) + timerflags |= MPU_TIMER_AR; - timer->cntl = MPU_TIMER_CLOCK_ENABLE; + writel(MPU_TIMER_CLOCK_ENABLE, &timer->cntl); udelay(1); - timer->load_tim = load_val; + writel(load_val, &timer->load_tim); udelay(1); - timer->cntl = timerflags; + writel(timerflags, &timer->cntl); } static inline void omap_mpu_timer_stop(int nr) { - volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); + omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr); - timer->cntl &= ~MPU_TIMER_ST; + writel(readl(&timer->cntl) & ~MPU_TIMER_ST, &timer->cntl); } /* @@ -189,38 +190,11 @@ static __init void omap_init_mpu_timer(unsigned long rate) * --------------------------------------------------------------------------- */ -static unsigned long omap_mpu_timer2_overflows; - -static irqreturn_t omap_mpu_timer2_interrupt(int irq, void *dev_id) -{ - omap_mpu_timer2_overflows++; - return IRQ_HANDLED; -} - -static struct irqaction omap_mpu_timer2_irq = { - .name = "mpu_timer2", - .flags = IRQF_DISABLED, - .handler = omap_mpu_timer2_interrupt, -}; - -static cycle_t mpu_read(struct clocksource *cs) -{ - return ~omap_mpu_timer_read(1); -} - -static struct clocksource clocksource_mpu = { - .name = "mpu_timer2", - .rating = 300, - .read = mpu_read, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - static DEFINE_CLOCK_DATA(cd); static inline unsigned long long notrace _omap_mpu_sched_clock(void) { - u32 cyc = mpu_read(&clocksource_mpu); + u32 cyc = ~omap_mpu_timer_read(1); return cyc_to_sched_clock(&cd, cyc, (u32)~0); } @@ -238,21 +212,22 @@ static unsigned long long notrace omap_mpu_sched_clock(void) static void notrace mpu_update_sched_clock(void) { - u32 cyc = mpu_read(&clocksource_mpu); + u32 cyc = ~omap_mpu_timer_read(1); update_sched_clock(&cd, cyc, (u32)~0); } static void __init omap_init_clocksource(unsigned long rate) { + omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(1); static char err[] __initdata = KERN_ERR "%s: can't register clocksource!\n"; - setup_irq(INT_TIMER2, &omap_mpu_timer2_irq); omap_mpu_timer_start(1, ~0, 1); init_sched_clock(&cd, mpu_update_sched_clock, 32, rate); - if (clocksource_register_hz(&clocksource_mpu, rate)) - printk(err, clocksource_mpu.name); + if (clocksource_mmio_init(&timer->read_tim, "mpu_timer2", rate, + 300, 32, clocksource_mmio_readl_down)) + printk(err, "mpu_timer2"); } static void __init omap_mpu_timer_init(void) diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 512b15204450..66dfbccacd25 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -59,10 +59,10 @@ endif # Power Management ifeq ($(CONFIG_PM),y) obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o -obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o +obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o \ - cpuidle34xx.o pm_bus.o -obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o pm_bus.o + cpuidle34xx.o +obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o obj-$(CONFIG_PM_DEBUG) += pm-debug.o obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c index b2b1e37bb6bb..d6e34dd9e7e7 100644 --- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c +++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c @@ -115,6 +115,7 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla, sdrc_cs0->actim_ctrlb, sdrc_cs0->mr, 0, 0, 0, 0); + clk->rate = rate; return 0; } diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h index de441c05a6a6..e4bd87619734 100644 --- a/arch/arm/mach-omap2/include/mach/omap4-common.h +++ b/arch/arm/mach-omap2/include/mach/omap4-common.h @@ -33,4 +33,11 @@ extern void __iomem *gic_dist_base_addr; extern void __init gic_init_irq(void); extern void omap_smc1(u32 fn, u32 arg); +#ifdef CONFIG_SMP +/* Needed for secondary core boot */ +extern void omap_secondary_startup(void); +extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask); +extern void omap_auxcoreboot_addr(u32 cpu_addr); +extern u32 omap_read_auxcoreboot0(void); +#endif #endif diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index b66cfe8bc464..ecfe93c4b585 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -21,6 +21,7 @@ #include <linux/io.h> #include <asm/cacheflush.h> +#include <asm/hardware/gic.h> #include <asm/smp_scu.h> #include <mach/hardware.h> #include <mach/omap4-common.h> @@ -63,7 +64,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) omap_modify_auxcoreboot0(0x200, 0xfffffdff); flush_cache_all(); smp_wmb(); - smp_cross_call(cpumask_of(cpu), 1); + gic_raise_softirq(cpumask_of(cpu), 1); /* * Now the secondary core is starting up let it run its @@ -118,6 +119,8 @@ void __init smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); + + set_smp_cross_call(gic_raise_softirq); } void __init platform_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-omap2/pm_bus.c b/arch/arm/mach-omap2/pm_bus.c deleted file mode 100644 index 5acd2ab298b1..000000000000 --- a/arch/arm/mach-omap2/pm_bus.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Runtime PM support code for OMAP - * - * Author: Kevin Hilman, Deep Root Systems, LLC - * - * Copyright (C) 2010 Texas Instruments, Inc. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/io.h> -#include <linux/pm_runtime.h> -#include <linux/platform_device.h> -#include <linux/mutex.h> - -#include <plat/omap_device.h> -#include <plat/omap-pm.h> - -#ifdef CONFIG_PM_RUNTIME -static int omap_pm_runtime_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - int r, ret = 0; - - dev_dbg(dev, "%s\n", __func__); - - ret = pm_generic_runtime_suspend(dev); - - if (!ret && dev->parent == &omap_device_parent) { - r = omap_device_idle(pdev); - WARN_ON(r); - } - - return ret; -}; - -static int omap_pm_runtime_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - int r; - - dev_dbg(dev, "%s\n", __func__); - - if (dev->parent == &omap_device_parent) { - r = omap_device_enable(pdev); - WARN_ON(r); - } - - return pm_generic_runtime_resume(dev); -}; -#else -#define omap_pm_runtime_suspend NULL -#define omap_pm_runtime_resume NULL -#endif /* CONFIG_PM_RUNTIME */ - -static int __init omap_pm_runtime_init(void) -{ - const struct dev_pm_ops *pm; - struct dev_pm_ops *omap_pm; - - pm = platform_bus_get_pm_ops(); - if (!pm) { - pr_err("%s: unable to get dev_pm_ops from platform_bus\n", - __func__); - return -ENODEV; - } - - omap_pm = kmemdup(pm, sizeof(struct dev_pm_ops), GFP_KERNEL); - if (!omap_pm) { - pr_err("%s: unable to alloc memory for new dev_pm_ops\n", - __func__); - return -ENOMEM; - } - - omap_pm->runtime_suspend = omap_pm_runtime_suspend; - omap_pm->runtime_resume = omap_pm_runtime_resume; - - platform_bus_set_pm_ops(omap_pm); - - return 0; -} -core_initcall(omap_pm_runtime_init); diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index bfbecec6d05f..810a982a66f8 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c @@ -15,7 +15,6 @@ #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/sysdev.h> #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/bitops.h> diff --git a/arch/arm/mach-pxa/clock-pxa2xx.c b/arch/arm/mach-pxa/clock-pxa2xx.c index 1ce090448493..1d5859d9a0e3 100644 --- a/arch/arm/mach-pxa/clock-pxa2xx.c +++ b/arch/arm/mach-pxa/clock-pxa2xx.c @@ -9,7 +9,7 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <mach/pxa2xx-regs.h> @@ -33,32 +33,22 @@ const struct clkops clk_pxa2xx_cken_ops = { #ifdef CONFIG_PM static uint32_t saved_cken; -static int pxa2xx_clock_suspend(struct sys_device *d, pm_message_t state) +static int pxa2xx_clock_suspend(void) { saved_cken = CKEN; return 0; } -static int pxa2xx_clock_resume(struct sys_device *d) +static void pxa2xx_clock_resume(void) { CKEN = saved_cken; - return 0; } #else #define pxa2xx_clock_suspend NULL #define pxa2xx_clock_resume NULL #endif -struct sysdev_class pxa2xx_clock_sysclass = { - .name = "pxa2xx-clock", +struct syscore_ops pxa2xx_clock_syscore_ops = { .suspend = pxa2xx_clock_suspend, .resume = pxa2xx_clock_resume, }; - -static int __init pxa2xx_clock_init(void) -{ - if (cpu_is_pxa2xx()) - return sysdev_class_register(&pxa2xx_clock_sysclass); - return 0; -} -postcore_initcall(pxa2xx_clock_init); diff --git a/arch/arm/mach-pxa/clock-pxa3xx.c b/arch/arm/mach-pxa/clock-pxa3xx.c index 3f864cd0bd28..2a37a9a8f621 100644 --- a/arch/arm/mach-pxa/clock-pxa3xx.c +++ b/arch/arm/mach-pxa/clock-pxa3xx.c @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/syscore_ops.h> #include <mach/smemc.h> #include <mach/pxa3xx-regs.h> @@ -182,7 +183,7 @@ const struct clkops clk_pxa3xx_pout_ops = { static uint32_t cken[2]; static uint32_t accr; -static int pxa3xx_clock_suspend(struct sys_device *d, pm_message_t state) +static int pxa3xx_clock_suspend(void) { cken[0] = CKENA; cken[1] = CKENB; @@ -190,28 +191,18 @@ static int pxa3xx_clock_suspend(struct sys_device *d, pm_message_t state) return 0; } -static int pxa3xx_clock_resume(struct sys_device *d) +static void pxa3xx_clock_resume(void) { ACCR = accr; CKENA = cken[0]; CKENB = cken[1]; - return 0; } #else #define pxa3xx_clock_suspend NULL #define pxa3xx_clock_resume NULL #endif -struct sysdev_class pxa3xx_clock_sysclass = { - .name = "pxa3xx-clock", +struct syscore_ops pxa3xx_clock_syscore_ops = { .suspend = pxa3xx_clock_suspend, .resume = pxa3xx_clock_resume, }; - -static int __init pxa3xx_clock_init(void) -{ - if (cpu_is_pxa3xx() || cpu_is_pxa95x()) - return sysdev_class_register(&pxa3xx_clock_sysclass); - return 0; -} -postcore_initcall(pxa3xx_clock_init); diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h index f9f349a21b54..1f2fb9c43f06 100644 --- a/arch/arm/mach-pxa/clock.h +++ b/arch/arm/mach-pxa/clock.h @@ -1,5 +1,5 @@ #include <linux/clkdev.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> struct clkops { void (*enable)(struct clk *); @@ -54,7 +54,7 @@ extern const struct clkops clk_pxa2xx_cken_ops; void clk_pxa2xx_cken_enable(struct clk *clk); void clk_pxa2xx_cken_disable(struct clk *clk); -extern struct sysdev_class pxa2xx_clock_sysclass; +extern struct syscore_ops pxa2xx_clock_syscore_ops; #if defined(CONFIG_PXA3xx) || defined(CONFIG_PXA95x) #define DEFINE_PXA3_CKEN(_name, _cken, _rate, _delay) \ @@ -74,5 +74,6 @@ extern const struct clkops clk_pxa3xx_smemc_ops; extern void clk_pxa3xx_cken_enable(struct clk *); extern void clk_pxa3xx_cken_disable(struct clk *); -extern struct sysdev_class pxa3xx_clock_sysclass; +extern struct syscore_ops pxa3xx_clock_syscore_ops; + #endif diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c index b88d601a8090..13518a705399 100644 --- a/arch/arm/mach-pxa/cm-x270.c +++ b/arch/arm/mach-pxa/cm-x270.c @@ -10,7 +10,6 @@ */ #include <linux/platform_device.h> -#include <linux/sysdev.h> #include <linux/irq.h> #include <linux/gpio.h> #include <linux/delay.h> diff --git a/arch/arm/mach-pxa/cm-x2xx-pci.c b/arch/arm/mach-pxa/cm-x2xx-pci.c index 8b1a30959fae..1afc0fb7d6d5 100644 --- a/arch/arm/mach-pxa/cm-x2xx-pci.c +++ b/arch/arm/mach-pxa/cm-x2xx-pci.c @@ -29,33 +29,6 @@ unsigned long it8152_base_address; static int cmx2xx_it8152_irq_gpio; -/* - * Only first 64MB of memory can be accessed via PCI. - * We use GFP_DMA to allocate safe buffers to do map/unmap. - * This is really ugly and we need a better way of specifying - * DMA-capable regions of memory. - */ -void __init cmx2xx_pci_adjust_zones(unsigned long *zone_size, - unsigned long *zhole_size) -{ - unsigned int sz = SZ_64M >> PAGE_SHIFT; - - if (machine_is_armcore()) { - pr_info("Adjusting zones for CM-X2XX\n"); - - /* - * Only adjust if > 64M on current system - */ - if (zone_size[0] <= sz) - return; - - zone_size[1] = zone_size[0] - sz; - zone_size[0] = sz; - zhole_size[1] = zhole_size[0]; - zhole_size[0] = 0; - } -} - static void cmx2xx_it8152_irq_demux(unsigned int irq, struct irq_desc *desc) { /* clear our parent irq */ diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c index 8225e2e58c6e..a10996782476 100644 --- a/arch/arm/mach-pxa/cm-x2xx.c +++ b/arch/arm/mach-pxa/cm-x2xx.c @@ -10,7 +10,7 @@ */ #include <linux/platform_device.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/irq.h> #include <linux/gpio.h> @@ -388,7 +388,7 @@ static inline void cmx2xx_init_display(void) {} #ifdef CONFIG_PM static unsigned long sleep_save_msc[10]; -static int cmx2xx_suspend(struct sys_device *dev, pm_message_t state) +static int cmx2xx_suspend(void) { cmx2xx_pci_suspend(); @@ -412,7 +412,7 @@ static int cmx2xx_suspend(struct sys_device *dev, pm_message_t state) return 0; } -static int cmx2xx_resume(struct sys_device *dev) +static void cmx2xx_resume(void) { cmx2xx_pci_resume(); @@ -420,27 +420,18 @@ static int cmx2xx_resume(struct sys_device *dev) __raw_writel(sleep_save_msc[0], MSC0); __raw_writel(sleep_save_msc[1], MSC1); __raw_writel(sleep_save_msc[2], MSC2); - - return 0; } -static struct sysdev_class cmx2xx_pm_sysclass = { - .name = "pm", +static struct syscore_ops cmx2xx_pm_syscore_ops = { .resume = cmx2xx_resume, .suspend = cmx2xx_suspend, }; -static struct sys_device cmx2xx_pm_device = { - .cls = &cmx2xx_pm_sysclass, -}; - static int __init cmx2xx_pm_init(void) { - int error; - error = sysdev_class_register(&cmx2xx_pm_sysclass); - if (error == 0) - error = sysdev_register(&cmx2xx_pm_device); - return error; + register_syscore_ops(&cmx2xx_pm_syscore_ops); + + return 0; } #else static int __init cmx2xx_pm_init(void) { return 0; } diff --git a/arch/arm/mach-pxa/colibri-evalboard.c b/arch/arm/mach-pxa/colibri-evalboard.c index 81c3c433e2d6..d28e802e2448 100644 --- a/arch/arm/mach-pxa/colibri-evalboard.c +++ b/arch/arm/mach-pxa/colibri-evalboard.c @@ -13,7 +13,6 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/platform_device.h> -#include <linux/sysdev.h> #include <linux/interrupt.h> #include <linux/gpio.h> #include <asm/mach-types.h> diff --git a/arch/arm/mach-pxa/colibri-pxa270-income.c b/arch/arm/mach-pxa/colibri-pxa270-income.c index 44c1b77ece67..80538b8806ed 100644 --- a/arch/arm/mach-pxa/colibri-pxa270-income.c +++ b/arch/arm/mach-pxa/colibri-pxa270-income.c @@ -22,7 +22,6 @@ #include <linux/platform_device.h> #include <linux/pwm_backlight.h> #include <linux/i2c/pxa-i2c.h> -#include <linux/sysdev.h> #include <asm/irq.h> #include <asm/mach-types.h> diff --git a/arch/arm/mach-pxa/colibri-pxa270.c b/arch/arm/mach-pxa/colibri-pxa270.c index 6fc5d328ba7f..7545a48ed88b 100644 --- a/arch/arm/mach-pxa/colibri-pxa270.c +++ b/arch/arm/mach-pxa/colibri-pxa270.c @@ -17,7 +17,6 @@ #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> #include <linux/platform_device.h> -#include <linux/sysdev.h> #include <linux/ucb1400.h> #include <asm/mach/arch.h> diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index a079d8baa45a..e6c9344a95ae 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -61,10 +61,10 @@ extern unsigned pxa3xx_get_clk_frequency_khz(int); #define pxa3xx_get_clk_frequency_khz(x) (0) #endif -extern struct sysdev_class pxa_irq_sysclass; -extern struct sysdev_class pxa_gpio_sysclass; -extern struct sysdev_class pxa2xx_mfp_sysclass; -extern struct sysdev_class pxa3xx_mfp_sysclass; +extern struct syscore_ops pxa_irq_syscore_ops; +extern struct syscore_ops pxa_gpio_syscore_ops; +extern struct syscore_ops pxa2xx_mfp_syscore_ops; +extern struct syscore_ops pxa3xx_mfp_syscore_ops; void __init pxa_set_ffuart_info(void *info); void __init pxa_set_btuart_info(void *info); diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c index 6de0ad0eea65..f941a495a4a8 100644 --- a/arch/arm/mach-pxa/hx4700.c +++ b/arch/arm/mach-pxa/hx4700.c @@ -711,7 +711,7 @@ static struct regulator_consumer_supply bq24022_consumers[] = { static struct regulator_init_data bq24022_init_data = { .constraints = { .max_uA = 500000, - .valid_ops_mask = REGULATOR_CHANGE_CURRENT, + .valid_ops_mask = REGULATOR_CHANGE_CURRENT|REGULATOR_CHANGE_STATUS, }, .num_consumer_supplies = ARRAY_SIZE(bq24022_consumers), .consumer_supplies = bq24022_consumers, @@ -735,7 +735,7 @@ static struct platform_device bq24022 = { * StrataFlash */ -static void hx4700_set_vpp(struct map_info *map, int vpp) +static void hx4700_set_vpp(struct platform_device *pdev, int vpp) { gpio_set_value(GPIO91_HX4700_FLASH_VPEN, vpp); } diff --git a/arch/arm/mach-pxa/include/mach/memory.h b/arch/arm/mach-pxa/include/mach/memory.h index 7f68724dcc27..07734f37f8fd 100644 --- a/arch/arm/mach-pxa/include/mach/memory.h +++ b/arch/arm/mach-pxa/include/mach/memory.h @@ -17,14 +17,8 @@ */ #define PLAT_PHYS_OFFSET UL(0xa0000000) -#if !defined(__ASSEMBLY__) && defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI) -void cmx2xx_pci_adjust_zones(unsigned long *size, unsigned long *holes); - -#define arch_adjust_zones(size, holes) \ - cmx2xx_pci_adjust_zones(size, holes) - -#define ISA_DMA_THRESHOLD (PHYS_OFFSET + SZ_64M - 1) -#define MAX_DMA_ADDRESS (PAGE_OFFSET + SZ_64M) +#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI) +#define ARM_DMA_ZONE_SIZE SZ_64M #endif #endif diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 6251e3f5c62c..32ed551bf9c5 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -15,7 +15,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/interrupt.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/io.h> #include <linux/irq.h> @@ -183,7 +183,7 @@ void __init pxa_init_irq(int irq_nr, set_wake_t fn) static unsigned long saved_icmr[MAX_INTERNAL_IRQS/32]; static unsigned long saved_ipr[MAX_INTERNAL_IRQS]; -static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state) +static int pxa_irq_suspend(void) { int i; @@ -202,7 +202,7 @@ static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state) return 0; } -static int pxa_irq_resume(struct sys_device *dev) +static void pxa_irq_resume(void) { int i; @@ -218,22 +218,13 @@ static int pxa_irq_resume(struct sys_device *dev) __raw_writel(saved_ipr[i], IRQ_BASE + IPR(i)); __raw_writel(1, IRQ_BASE + ICCR); - return 0; } #else #define pxa_irq_suspend NULL #define pxa_irq_resume NULL #endif -struct sysdev_class pxa_irq_sysclass = { - .name = "irq", +struct syscore_ops pxa_irq_syscore_ops = { .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/lpd270.c b/arch/arm/mach-pxa/lpd270.c index f5de541725b1..6cf8180bf5bd 100644 --- a/arch/arm/mach-pxa/lpd270.c +++ b/arch/arm/mach-pxa/lpd270.c @@ -15,7 +15,7 @@ #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/bitops.h> @@ -159,30 +159,22 @@ static void __init lpd270_init_irq(void) #ifdef CONFIG_PM -static int lpd270_irq_resume(struct sys_device *dev) +static void lpd270_irq_resume(void) { __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK); - return 0; } -static struct sysdev_class lpd270_irq_sysclass = { - .name = "cpld_irq", +static struct syscore_ops lpd270_irq_syscore_ops = { .resume = lpd270_irq_resume, }; -static struct sys_device lpd270_irq_device = { - .cls = &lpd270_irq_sysclass, -}; - static int __init lpd270_irq_device_init(void) { - int ret = -ENODEV; if (machine_is_logicpd_pxa270()) { - ret = sysdev_class_register(&lpd270_irq_sysclass); - if (ret == 0) - ret = sysdev_register(&lpd270_irq_device); + register_syscore_ops(&lpd270_irq_syscore_ops); + return 0; } - return ret; + return -ENODEV; } device_initcall(lpd270_irq_device_init); diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 3ede978c83d9..e10ddb827147 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -15,7 +15,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/major.h> #include <linux/fb.h> #include <linux/interrupt.h> @@ -176,31 +176,22 @@ static void __init lubbock_init_irq(void) #ifdef CONFIG_PM -static int lubbock_irq_resume(struct sys_device *dev) +static void lubbock_irq_resume(void) { LUB_IRQ_MASK_EN = lubbock_irq_enabled; - return 0; } -static struct sysdev_class lubbock_irq_sysclass = { - .name = "cpld_irq", +static struct syscore_ops lubbock_irq_syscore_ops = { .resume = lubbock_irq_resume, }; -static struct sys_device lubbock_irq_device = { - .cls = &lubbock_irq_sysclass, -}; - static int __init lubbock_irq_device_init(void) { - int ret = -ENODEV; - if (machine_is_lubbock()) { - ret = sysdev_class_register(&lubbock_irq_sysclass); - if (ret == 0) - ret = sysdev_register(&lubbock_irq_device); + register_syscore_ops(&lubbock_irq_syscore_ops); + return 0; } - return ret; + return -ENODEV; } device_initcall(lubbock_irq_device_init); diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index a72993dde2b3..e1920572948a 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -599,7 +599,7 @@ static struct regulator_consumer_supply bq24022_consumers[] = { static struct regulator_init_data bq24022_init_data = { .constraints = { .max_uA = 500000, - .valid_ops_mask = REGULATOR_CHANGE_CURRENT, + .valid_ops_mask = REGULATOR_CHANGE_CURRENT | REGULATOR_CHANGE_STATUS, }, .num_consumer_supplies = ARRAY_SIZE(bq24022_consumers), .consumer_supplies = bq24022_consumers, @@ -662,7 +662,7 @@ static struct pxaohci_platform_data magician_ohci_info = { * StrataFlash */ -static void magician_set_vpp(struct map_info *map, int vpp) +static void magician_set_vpp(struct platform_device *pdev, int vpp) { gpio_set_value(EGPIO_MAGICIAN_FLASH_VPP, vpp); } diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index 95163baca29e..3479e2b3b511 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -15,7 +15,7 @@ #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/bitops.h> @@ -185,31 +185,21 @@ static void __init mainstone_init_irq(void) #ifdef CONFIG_PM -static int mainstone_irq_resume(struct sys_device *dev) +static void mainstone_irq_resume(void) { MST_INTMSKENA = mainstone_irq_enabled; - return 0; } -static struct sysdev_class mainstone_irq_sysclass = { - .name = "cpld_irq", +static struct syscore_ops mainstone_irq_syscore_ops = { .resume = mainstone_irq_resume, }; -static struct sys_device mainstone_irq_device = { - .cls = &mainstone_irq_sysclass, -}; - static int __init mainstone_irq_device_init(void) { - int ret = -ENODEV; + if (machine_is_mainstone()) + register_syscore_ops(&mainstone_irq_syscore_ops); - if (machine_is_mainstone()) { - ret = sysdev_class_register(&mainstone_irq_sysclass); - if (ret == 0) - ret = sysdev_register(&mainstone_irq_device); - } - return ret; + return 0; } device_initcall(mainstone_irq_device_init); diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c index 1d1419b73457..87ae3129f4f7 100644 --- a/arch/arm/mach-pxa/mfp-pxa2xx.c +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c @@ -16,7 +16,7 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <mach/gpio.h> #include <mach/pxa2xx-regs.h> @@ -338,7 +338,7 @@ static unsigned long saved_gafr[2][4]; static unsigned long saved_gpdr[4]; static unsigned long saved_pgsr[4]; -static int pxa2xx_mfp_suspend(struct sys_device *d, pm_message_t state) +static int pxa2xx_mfp_suspend(void) { int i; @@ -365,7 +365,7 @@ static int pxa2xx_mfp_suspend(struct sys_device *d, pm_message_t state) return 0; } -static int pxa2xx_mfp_resume(struct sys_device *d) +static void pxa2xx_mfp_resume(void) { int i; @@ -376,15 +376,13 @@ static int pxa2xx_mfp_resume(struct sys_device *d) PGSR(i) = saved_pgsr[i]; } PSSR = PSSR_RDH | PSSR_PH; - return 0; } #else #define pxa2xx_mfp_suspend NULL #define pxa2xx_mfp_resume NULL #endif -struct sysdev_class pxa2xx_mfp_sysclass = { - .name = "mfp", +struct syscore_ops pxa2xx_mfp_syscore_ops = { .suspend = pxa2xx_mfp_suspend, .resume = pxa2xx_mfp_resume, }; @@ -409,6 +407,6 @@ static int __init pxa2xx_mfp_init(void) for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) gpdr_lpm[i] = GPDR(i * 32); - return sysdev_class_register(&pxa2xx_mfp_sysclass); + return 0; } postcore_initcall(pxa2xx_mfp_init); diff --git a/arch/arm/mach-pxa/mfp-pxa3xx.c b/arch/arm/mach-pxa/mfp-pxa3xx.c index 7a270eecd480..89863a01ecd7 100644 --- a/arch/arm/mach-pxa/mfp-pxa3xx.c +++ b/arch/arm/mach-pxa/mfp-pxa3xx.c @@ -17,7 +17,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/io.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <mach/hardware.h> #include <mach/mfp-pxa3xx.h> @@ -31,13 +31,13 @@ * a pull-down mode if they're an active low chip select, and we're * just entering standby. */ -static int pxa3xx_mfp_suspend(struct sys_device *d, pm_message_t state) +static int pxa3xx_mfp_suspend(void) { mfp_config_lpm(); return 0; } -static int pxa3xx_mfp_resume(struct sys_device *d) +static void pxa3xx_mfp_resume(void) { mfp_config_run(); @@ -47,24 +47,13 @@ static int pxa3xx_mfp_resume(struct sys_device *d) * preserve them here in case they will be referenced later */ ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S); - return 0; } #else #define pxa3xx_mfp_suspend NULL #define pxa3xx_mfp_resume NULL #endif -struct sysdev_class pxa3xx_mfp_sysclass = { - .name = "mfp", +struct syscore_ops pxa3xx_mfp_syscore_ops = { .suspend = pxa3xx_mfp_suspend, - .resume = pxa3xx_mfp_resume, + .resume = pxa3xx_mfp_resume, }; - -static int __init mfp_init_devicefs(void) -{ - if (cpu_is_pxa3xx()) - return sysdev_class_register(&pxa3xx_mfp_sysclass); - - return 0; -} -postcore_initcall(mfp_init_devicefs); diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index 23925db8ff74..e3470137c934 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -22,7 +22,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/input.h> #include <linux/delay.h> #include <linux/gpio_keys.h> @@ -488,7 +488,7 @@ static void install_bootstrap(void) } -static int mioa701_sys_suspend(struct sys_device *sysdev, pm_message_t state) +static int mioa701_sys_suspend(void) { int i = 0, is_bt_on; u32 *mem_resume_vector = phys_to_virt(RESUME_VECTOR_ADDR); @@ -514,7 +514,7 @@ static int mioa701_sys_suspend(struct sys_device *sysdev, pm_message_t state) return 0; } -static int mioa701_sys_resume(struct sys_device *sysdev) +static void mioa701_sys_resume(void) { int i = 0; u32 *mem_resume_vector = phys_to_virt(RESUME_VECTOR_ADDR); @@ -527,43 +527,18 @@ static int mioa701_sys_resume(struct sys_device *sysdev) *mem_resume_enabler = save_buffer[i++]; *mem_resume_bt = save_buffer[i++]; *mem_resume_unknown = save_buffer[i++]; - - return 0; } -static struct sysdev_class mioa701_sysclass = { - .name = "mioa701", -}; - -static struct sys_device sysdev_bootstrap = { - .cls = &mioa701_sysclass, -}; - -static struct sysdev_driver driver_bootstrap = { - .suspend = &mioa701_sys_suspend, - .resume = &mioa701_sys_resume, +static struct syscore_ops mioa701_syscore_ops = { + .suspend = mioa701_sys_suspend, + .resume = mioa701_sys_resume, }; static int __init bootstrap_init(void) { - int rc; int save_size = mioa701_bootstrap_lg + (sizeof(u32) * 3); - rc = sysdev_class_register(&mioa701_sysclass); - if (rc) { - printk(KERN_ERR "Failed registering mioa701 sys class\n"); - return -ENODEV; - } - rc = sysdev_register(&sysdev_bootstrap); - if (rc) { - printk(KERN_ERR "Failed registering mioa701 sys device\n"); - return -ENODEV; - } - rc = sysdev_driver_register(&mioa701_sysclass, &driver_bootstrap); - if (rc) { - printk(KERN_ERR "Failed registering PMU sys driver\n"); - return -ENODEV; - } + register_syscore_ops(&mioa701_syscore_ops); save_buffer = kmalloc(save_size, GFP_KERNEL); if (!save_buffer) @@ -576,9 +551,7 @@ static int __init bootstrap_init(void) static void bootstrap_exit(void) { kfree(save_buffer); - sysdev_driver_unregister(&mioa701_sysclass, &driver_bootstrap); - sysdev_unregister(&sysdev_bootstrap); - sysdev_class_unregister(&mioa701_sysclass); + unregister_syscore_ops(&mioa701_syscore_ops); printk(KERN_CRIT "Unregistering mioa701 suspend will hang next" "resume !!!\n"); diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c index a6f898cbfac9..4061ecddee70 100644 --- a/arch/arm/mach-pxa/palmld.c +++ b/arch/arm/mach-pxa/palmld.c @@ -24,7 +24,6 @@ #include <linux/gpio.h> #include <linux/wm97xx.h> #include <linux/power_supply.h> -#include <linux/sysdev.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c index 8aadad55fbe4..20d1b18b1733 100644 --- a/arch/arm/mach-pxa/palmtreo.c +++ b/arch/arm/mach-pxa/palmtreo.c @@ -25,7 +25,6 @@ #include <linux/pwm_backlight.h> #include <linux/gpio.h> #include <linux/power_supply.h> -#include <linux/sysdev.h> #include <linux/w1-gpio.h> #include <asm/mach-types.h> diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c index 3b8a4f37dbbe..65f24f0b77e8 100644 --- a/arch/arm/mach-pxa/palmz72.c +++ b/arch/arm/mach-pxa/palmz72.c @@ -19,7 +19,7 @@ */ #include <linux/platform_device.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/delay.h> #include <linux/irq.h> #include <linux/gpio_keys.h> @@ -233,9 +233,9 @@ static struct palmz72_resume_info palmz72_resume_info = { static unsigned long store_ptr; -/* sys_device for Palm Zire 72 PM */ +/* syscore_ops for Palm Zire 72 PM */ -static int palmz72_pm_suspend(struct sys_device *dev, pm_message_t msg) +static int palmz72_pm_suspend(void) { /* setup the resume_info struct for the original bootloader */ palmz72_resume_info.resume_addr = (u32) cpu_resume; @@ -249,31 +249,23 @@ static int palmz72_pm_suspend(struct sys_device *dev, pm_message_t msg) return 0; } -static int palmz72_pm_resume(struct sys_device *dev) +static void palmz72_pm_resume(void) { *PALMZ72_SAVE_DWORD = store_ptr; - return 0; } -static struct sysdev_class palmz72_pm_sysclass = { - .name = "palmz72_pm", +static struct syscore_ops palmz72_pm_syscore_ops = { .suspend = palmz72_pm_suspend, .resume = palmz72_pm_resume, }; -static struct sys_device palmz72_pm_device = { - .cls = &palmz72_pm_sysclass, -}; - static int __init palmz72_pm_init(void) { - int ret = -ENODEV; if (machine_is_palmz72()) { - ret = sysdev_class_register(&palmz72_pm_sysclass); - if (ret == 0) - ret = sysdev_register(&palmz72_pm_device); + register_syscore_ops(&palmz72_pm_syscore_ops); + return 0; } - return ret; + return -ENODEV; } device_initcall(palmz72_pm_init); diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index a4af8c52d7ee..fed363cec9c6 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -21,7 +21,7 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/suspend.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/irq.h> #include <asm/mach/map.h> @@ -350,21 +350,9 @@ static struct platform_device *pxa25x_devices[] __initdata = { &pxa_device_asoc_platform, }; -static struct sys_device pxa25x_sysdev[] = { - { - .cls = &pxa_irq_sysclass, - }, { - .cls = &pxa2xx_mfp_sysclass, - }, { - .cls = &pxa_gpio_sysclass, - }, { - .cls = &pxa2xx_clock_sysclass, - } -}; - static int __init pxa25x_init(void) { - int i, ret = 0; + int ret = 0; if (cpu_is_pxa25x()) { @@ -377,11 +365,10 @@ 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); - } + register_syscore_ops(&pxa_irq_syscore_ops); + register_syscore_ops(&pxa2xx_mfp_syscore_ops); + register_syscore_ops(&pxa_gpio_syscore_ops); + register_syscore_ops(&pxa2xx_clock_syscore_ops); ret = platform_add_devices(pxa25x_devices, ARRAY_SIZE(pxa25x_devices)); diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 909756eaf4b7..2fecbec58d88 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -16,7 +16,7 @@ #include <linux/init.h> #include <linux/suspend.h> #include <linux/platform_device.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/io.h> #include <linux/irq.h> #include <linux/i2c/pxa-i2c.h> @@ -428,21 +428,9 @@ static struct platform_device *devices[] __initdata = { &pxa27x_device_pwm1, }; -static struct sys_device pxa27x_sysdev[] = { - { - .cls = &pxa_irq_sysclass, - }, { - .cls = &pxa2xx_mfp_sysclass, - }, { - .cls = &pxa_gpio_sysclass, - }, { - .cls = &pxa2xx_clock_sysclass, - } -}; - static int __init pxa27x_init(void) { - int i, ret = 0; + int ret = 0; if (cpu_is_pxa27x()) { @@ -455,11 +443,10 @@ 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); - } + register_syscore_ops(&pxa_irq_syscore_ops); + register_syscore_ops(&pxa2xx_mfp_syscore_ops); + register_syscore_ops(&pxa_gpio_syscore_ops); + register_syscore_ops(&pxa2xx_clock_syscore_ops); ret = platform_add_devices(devices, ARRAY_SIZE(devices)); } diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 8dd107391157..8521d7d6f1da 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -20,7 +20,7 @@ #include <linux/platform_device.h> #include <linux/irq.h> #include <linux/io.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/i2c/pxa-i2c.h> #include <asm/mach/map.h> @@ -427,21 +427,9 @@ static struct platform_device *devices[] __initdata = { &pxa27x_device_pwm1, }; -static struct sys_device pxa3xx_sysdev[] = { - { - .cls = &pxa_irq_sysclass, - }, { - .cls = &pxa3xx_mfp_sysclass, - }, { - .cls = &pxa_gpio_sysclass, - }, { - .cls = &pxa3xx_clock_sysclass, - } -}; - static int __init pxa3xx_init(void) { - int i, ret = 0; + int ret = 0; if (cpu_is_pxa3xx()) { @@ -462,11 +450,10 @@ static int __init pxa3xx_init(void) pxa3xx_init_pm(); - 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); - } + register_syscore_ops(&pxa_irq_syscore_ops); + register_syscore_ops(&pxa3xx_mfp_syscore_ops); + register_syscore_ops(&pxa_gpio_syscore_ops); + register_syscore_ops(&pxa3xx_clock_syscore_ops); ret = platform_add_devices(devices, ARRAY_SIZE(devices)); } diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c index 23b229bd06e9..ecc82a330fad 100644 --- a/arch/arm/mach-pxa/pxa95x.c +++ b/arch/arm/mach-pxa/pxa95x.c @@ -18,7 +18,7 @@ #include <linux/i2c/pxa-i2c.h> #include <linux/irq.h> #include <linux/io.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <mach/hardware.h> #include <mach/gpio.h> @@ -260,16 +260,6 @@ static struct platform_device *devices[] __initdata = { &pxa27x_device_pwm1, }; -static struct sys_device pxa95x_sysdev[] = { - { - .cls = &pxa_irq_sysclass, - }, { - .cls = &pxa_gpio_sysclass, - }, { - .cls = &pxa3xx_clock_sysclass, - } -}; - static int __init pxa95x_init(void) { int ret = 0, i; @@ -293,11 +283,9 @@ static int __init pxa95x_init(void) if ((ret = pxa_init_dma(IRQ_DMA, 32))) return ret; - for (i = 0; i < ARRAY_SIZE(pxa95x_sysdev); i++) { - ret = sysdev_register(&pxa95x_sysdev[i]); - if (ret) - pr_err("failed to register sysdev[%d]\n", i); - } + register_syscore_ops(&pxa_irq_syscore_ops); + register_syscore_ops(&pxa_gpio_syscore_ops); + register_syscore_ops(&pxa3xx_clock_syscore_ops); ret = platform_add_devices(devices, ARRAY_SIZE(devices)); } diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index cd1861351f75..d130f77b6d11 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -18,7 +18,6 @@ #include <linux/init.h> #include <linux/kernel.h> -#include <linux/sysdev.h> #include <linux/platform_device.h> #include <linux/interrupt.h> #include <linux/gpio.h> diff --git a/arch/arm/mach-pxa/smemc.c b/arch/arm/mach-pxa/smemc.c index 232b7316ec08..79923058d10f 100644 --- a/arch/arm/mach-pxa/smemc.c +++ b/arch/arm/mach-pxa/smemc.c @@ -6,7 +6,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/io.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <mach/hardware.h> #include <mach/smemc.h> @@ -16,7 +16,7 @@ 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) +static int pxa3xx_smemc_suspend(void) { msc[0] = __raw_readl(MSC0); msc[1] = __raw_readl(MSC1); @@ -30,7 +30,7 @@ static int pxa3xx_smemc_suspend(struct sys_device *dev, pm_message_t state) return 0; } -static int pxa3xx_smemc_resume(struct sys_device *dev) +static void pxa3xx_smemc_resume(void) { __raw_writel(msc[0], MSC0); __raw_writel(msc[1], MSC1); @@ -40,34 +40,19 @@ static int pxa3xx_smemc_resume(struct sys_device *dev) __raw_writel(csadrcfg[1], CSADRCFG1); __raw_writel(csadrcfg[2], CSADRCFG2); __raw_writel(csadrcfg[3], CSADRCFG3); - - return 0; } -static struct sysdev_class smemc_sysclass = { - .name = "smemc", +static struct syscore_ops smemc_syscore_ops = { .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()) + register_syscore_ops(&smemc_syscore_ops); - if (cpu_is_pxa3xx()) { - ret = sysdev_class_register(&smemc_sysclass); - if (ret) - return ret; - - ret = sysdev_register(&smemc_sysdev); - } - - return ret; + return 0; } subsys_initcall(smemc_init); #endif diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 428da3ff33a5..de684701449c 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -105,19 +105,6 @@ static struct clock_event_device ckevt_pxa_osmr0 = { .set_mode = pxa_osmr0_set_mode, }; -static cycle_t pxa_read_oscr(struct clocksource *cs) -{ - return OSCR; -} - -static struct clocksource cksrc_pxa_oscr0 = { - .name = "oscr0", - .rating = 200, - .read = pxa_read_oscr, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - static struct irqaction pxa_ost0_irq = { .name = "ost0", .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, @@ -134,7 +121,6 @@ static void __init pxa_timer_init(void) init_sched_clock(&cd, pxa_update_sched_clock, 32, clock_tick_rate); - clocksource_calc_mult_shift(&cksrc_pxa_oscr0, clock_tick_rate, 4); clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4); ckevt_pxa_osmr0.max_delta_ns = clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0); @@ -144,7 +130,8 @@ static void __init pxa_timer_init(void) setup_irq(IRQ_OST0, &pxa_ost0_irq); - clocksource_register_hz(&cksrc_pxa_oscr0, clock_tick_rate); + clocksource_mmio_init(&OSCR, "oscr0", clock_tick_rate, 200, 32, + clocksource_mmio_readl_up); clockevents_register_device(&ckevt_pxa_osmr0); } diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c index b9cfbebdfe9c..687417a93698 100644 --- a/arch/arm/mach-pxa/trizeps4.c +++ b/arch/arm/mach-pxa/trizeps4.c @@ -15,7 +15,6 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/platform_device.h> -#include <linux/sysdev.h> #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/bitops.h> diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c index b523f119e0f0..903218eab56d 100644 --- a/arch/arm/mach-pxa/viper.c +++ b/arch/arm/mach-pxa/viper.c @@ -44,6 +44,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> +#include <linux/syscore_ops.h> #include <mach/pxa25x.h> #include <mach/audio.h> @@ -130,20 +131,19 @@ static u8 viper_hw_version(void) return v1; } -/* CPU sysdev */ -static int viper_cpu_suspend(struct sys_device *sysdev, pm_message_t state) +/* CPU system core operations. */ +static int viper_cpu_suspend(void) { viper_icr_set_bit(VIPER_ICR_R_DIS); return 0; } -static int viper_cpu_resume(struct sys_device *sysdev) +static void viper_cpu_resume(void) { viper_icr_clear_bit(VIPER_ICR_R_DIS); - return 0; } -static struct sysdev_driver viper_cpu_sysdev_driver = { +static struct syscore_ops viper_cpu_syscore_ops = { .suspend = viper_cpu_suspend, .resume = viper_cpu_resume, }; @@ -945,7 +945,7 @@ static void __init viper_init(void) viper_init_vcore_gpios(); viper_init_cpufreq(); - sysdev_driver_register(&cpu_sysdev_class, &viper_cpu_sysdev_driver); + register_syscore_ops(&viper_cpu_syscore_ops); if (version) { pr_info("viper: hardware v%di%d detected. " diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index f71d377c8640..67bd41488bf8 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -16,7 +16,6 @@ #include <linux/gpio_keys.h> #include <linux/input.h> #include <linux/gpio.h> -#include <linux/sysdev.h> #include <linux/usb/gpio_vbus.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 75dbc8791d05..5c23450d2d1d 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -31,6 +31,7 @@ #include <linux/amba/mmci.h> #include <linux/gfp.h> #include <linux/clkdev.h> +#include <linux/mtd/physmap.h> #include <asm/system.h> #include <mach/hardware.h> @@ -41,7 +42,6 @@ #include <asm/hardware/icst.h> #include <asm/mach/arch.h> -#include <asm/mach/flash.h> #include <asm/mach/irq.h> #include <asm/mach/map.h> @@ -56,48 +56,9 @@ #include "core.h" -#ifdef CONFIG_ZONE_DMA -/* - * Adjust the zones if there are restrictions for DMA access. - */ -void __init realview_adjust_zones(unsigned long *size, unsigned long *hole) -{ - unsigned long dma_size = SZ_256M >> PAGE_SHIFT; - - if (!machine_is_realview_pbx() || size[0] <= dma_size) - return; - - size[ZONE_NORMAL] = size[0] - dma_size; - size[ZONE_DMA] = dma_size; - hole[ZONE_NORMAL] = hole[0]; - hole[ZONE_DMA] = 0; -} -#endif - - #define REALVIEW_FLASHCTRL (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_FLASH_OFFSET) -static int realview_flash_init(void) -{ - u32 val; - - val = __raw_readl(REALVIEW_FLASHCTRL); - val &= ~REALVIEW_FLASHPROG_FLVPPEN; - __raw_writel(val, REALVIEW_FLASHCTRL); - - return 0; -} - -static void realview_flash_exit(void) -{ - u32 val; - - val = __raw_readl(REALVIEW_FLASHCTRL); - val &= ~REALVIEW_FLASHPROG_FLVPPEN; - __raw_writel(val, REALVIEW_FLASHCTRL); -} - -static void realview_flash_set_vpp(int on) +static void realview_flash_set_vpp(struct platform_device *pdev, int on) { u32 val; @@ -109,16 +70,13 @@ static void realview_flash_set_vpp(int on) __raw_writel(val, REALVIEW_FLASHCTRL); } -static struct flash_platform_data realview_flash_data = { - .map_name = "cfi_probe", +static struct physmap_flash_data realview_flash_data = { .width = 4, - .init = realview_flash_init, - .exit = realview_flash_exit, .set_vpp = realview_flash_set_vpp, }; struct platform_device realview_flash_device = { - .name = "armflash", + .name = "physmap-flash", .id = 0, .dev = { .platform_data = &realview_flash_data, @@ -315,6 +273,10 @@ static struct clk ref24_clk = { .rate = 24000000, }; +static struct clk sp804_clk = { + .rate = 1000000, +}; + static struct clk dummy_apb_pclk; static struct clk_lookup lookups[] = { @@ -357,7 +319,10 @@ static struct clk_lookup lookups[] = { }, { /* SSP */ .dev_id = "dev:ssp0", .clk = &ref24_clk, - } + }, { /* SP804 timers */ + .dev_id = "sp804", + .clk = &sp804_clk, + }, }; void __init realview_init_early(void) @@ -545,8 +510,8 @@ void __init realview_timer_init(unsigned int timer_irq) writel(0, timer2_va_base + TIMER_CTRL); writel(0, timer3_va_base + TIMER_CTRL); - sp804_clocksource_init(timer3_va_base); - sp804_clockevents_init(timer0_va_base, timer_irq); + sp804_clocksource_init(timer3_va_base, "timer3"); + sp804_clockevents_init(timer0_va_base, timer_irq, "timer0"); } /* diff --git a/arch/arm/mach-realview/include/mach/barriers.h b/arch/arm/mach-realview/include/mach/barriers.h index 0c5d749d7b5f..9a732195aa1c 100644 --- a/arch/arm/mach-realview/include/mach/barriers.h +++ b/arch/arm/mach-realview/include/mach/barriers.h @@ -4,5 +4,5 @@ * operation to deadlock the system. */ #define mb() dsb() -#define rmb() dmb() +#define rmb() dsb() #define wmb() mb() diff --git a/arch/arm/mach-realview/include/mach/memory.h b/arch/arm/mach-realview/include/mach/memory.h index e05fc2c4c080..1759fa673eea 100644 --- a/arch/arm/mach-realview/include/mach/memory.h +++ b/arch/arm/mach-realview/include/mach/memory.h @@ -29,13 +29,8 @@ #define PLAT_PHYS_OFFSET UL(0x00000000) #endif -#if !defined(__ASSEMBLY__) && defined(CONFIG_ZONE_DMA) -extern void realview_adjust_zones(unsigned long *size, unsigned long *hole); -#define arch_adjust_zones(size, hole) \ - realview_adjust_zones(size, hole) - -#define ISA_DMA_THRESHOLD (PHYS_OFFSET + SZ_256M - 1) -#define MAX_DMA_ADDRESS (PAGE_OFFSET + SZ_256M) +#ifdef CONFIG_ZONE_DMA +#define ARM_DMA_ZONE_SIZE SZ_256M #endif #ifdef CONFIG_SPARSEMEM diff --git a/arch/arm/mach-realview/include/mach/smp.h b/arch/arm/mach-realview/include/mach/smp.h deleted file mode 100644 index c8221b38ee7c..000000000000 --- a/arch/arm/mach-realview/include/mach/smp.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef ASMARM_ARCH_SMP_H -#define ASMARM_ARCH_SMP_H - -#include <asm/hardware/gic.h> - -/* - * We use IRQ1 as the IPI - */ -static inline void smp_cross_call(const struct cpumask *mask, int ipi) -{ - gic_raise_softirq(mask, ipi); -} - -#endif diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index 23919229e12d..963bf0d8119a 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -14,6 +14,7 @@ #include <linux/io.h> #include <mach/hardware.h> +#include <asm/hardware/gic.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> #include <asm/unified.h> @@ -61,6 +62,8 @@ void __init smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); + + set_smp_cross_call(gic_raise_softirq); } void __init platform_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c index 5e2f35332056..2854129f8cc7 100644 --- a/arch/arm/mach-s3c2410/irq.c +++ b/arch/arm/mach-s3c2410/irq.c @@ -23,38 +23,12 @@ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/ioport.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <plat/cpu.h> #include <plat/pm.h> -static int s3c2410_irq_add(struct sys_device *sysdev) -{ - return 0; -} - -static struct sysdev_driver s3c2410_irq_driver = { - .add = s3c2410_irq_add, +struct syscore_ops s3c24xx_irq_syscore_ops = { .suspend = s3c24xx_irq_suspend, .resume = s3c24xx_irq_resume, }; - -static int __init s3c2410_irq_init(void) -{ - return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver); -} - -arch_initcall(s3c2410_irq_init); - -static struct sysdev_driver s3c2410a_irq_driver = { - .add = s3c2410_irq_add, - .suspend = s3c24xx_irq_suspend, - .resume = s3c24xx_irq_resume, -}; - -static int __init s3c2410a_irq_init(void) -{ - return sysdev_driver_register(&s3c2410a_sysclass, &s3c2410a_irq_driver); -} - -arch_initcall(s3c2410a_irq_init); diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 2970ea9f7c2b..1e2d536adda9 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -17,7 +17,7 @@ #include <linux/timer.h> #include <linux/init.h> #include <linux/gpio.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/serial_core.h> #include <linux/platform_device.h> #include <linux/dm9000.h> @@ -214,17 +214,16 @@ static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = { /* NAND Flash on BAST board */ #ifdef CONFIG_PM -static int bast_pm_suspend(struct sys_device *sd, pm_message_t state) +static int bast_pm_suspend(void) { /* ensure that an nRESET is not generated on resume. */ gpio_direction_output(S3C2410_GPA(21), 1); return 0; } -static int bast_pm_resume(struct sys_device *sd) +static void bast_pm_resume(void) { s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT); - return 0; } #else @@ -232,16 +231,11 @@ static int bast_pm_resume(struct sys_device *sd) #define bast_pm_resume NULL #endif -static struct sysdev_class bast_pm_sysclass = { - .name = "mach-bast", +static struct syscore_ops bast_pm_syscore_ops = { .suspend = bast_pm_suspend, .resume = bast_pm_resume, }; -static struct sys_device bast_pm_sysdev = { - .cls = &bast_pm_sysclass, -}; - static int smartmedia_map[] = { 0 }; static int chip0_map[] = { 1 }; static int chip1_map[] = { 2 }; @@ -642,8 +636,7 @@ static void __init bast_map_io(void) static void __init bast_init(void) { - sysdev_class_register(&bast_pm_sysclass); - sysdev_register(&bast_pm_sysdev); + register_syscore_ops(&bast_pm_syscore_ops); s3c_i2c0_set_platdata(&bast_i2c_info); s3c_nand_set_platdata(&bast_nand_info); diff --git a/arch/arm/mach-s3c2410/nor-simtec.c b/arch/arm/mach-s3c2410/nor-simtec.c index 598d130633dc..ad9f750f1e55 100644 --- a/arch/arm/mach-s3c2410/nor-simtec.c +++ b/arch/arm/mach-s3c2410/nor-simtec.c @@ -32,7 +32,7 @@ #include "nor-simtec.h" -static void simtec_nor_vpp(struct map_info *map, int vpp) +static void simtec_nor_vpp(struct platform_device *pdev, int vpp) { unsigned int val; unsigned long flags; diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c index 725636fc4dc3..4728f9aa7df1 100644 --- a/arch/arm/mach-s3c2410/pm.c +++ b/arch/arm/mach-s3c2410/pm.c @@ -25,6 +25,7 @@ #include <linux/errno.h> #include <linux/time.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/gpio.h> #include <linux/io.h> @@ -92,7 +93,7 @@ static void s3c2410_pm_prepare(void) } } -static int s3c2410_pm_resume(struct sys_device *dev) +static void s3c2410_pm_resume(void) { unsigned long tmp; @@ -104,10 +105,12 @@ static int s3c2410_pm_resume(struct sys_device *dev) if ( machine_is_aml_m5900() ) s3c2410_gpio_setpin(S3C2410_GPF(2), 0); - - return 0; } +struct syscore_ops s3c2410_pm_syscore_ops = { + .resume = s3c2410_pm_resume, +}; + static int s3c2410_pm_add(struct sys_device *dev) { pm_cpu_prep = s3c2410_pm_prepare; @@ -119,7 +122,6 @@ static int s3c2410_pm_add(struct sys_device *dev) #if defined(CONFIG_CPU_S3C2410) static struct sysdev_driver s3c2410_pm_driver = { .add = s3c2410_pm_add, - .resume = s3c2410_pm_resume, }; /* register ourselves */ @@ -133,7 +135,6 @@ arch_initcall(s3c2410_pm_drvinit); static struct sysdev_driver s3c2410a_pm_driver = { .add = s3c2410_pm_add, - .resume = s3c2410_pm_resume, }; static int __init s3c2410a_pm_drvinit(void) @@ -147,7 +148,6 @@ arch_initcall(s3c2410a_pm_drvinit); #if defined(CONFIG_CPU_S3C2440) static struct sysdev_driver s3c2440_pm_driver = { .add = s3c2410_pm_add, - .resume = s3c2410_pm_resume, }; static int __init s3c2440_pm_drvinit(void) @@ -161,7 +161,6 @@ arch_initcall(s3c2440_pm_drvinit); #if defined(CONFIG_CPU_S3C2442) static struct sysdev_driver s3c2442_pm_driver = { .add = s3c2410_pm_add, - .resume = s3c2410_pm_resume, }; static int __init s3c2442_pm_drvinit(void) diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c index adc90a3c5890..f1d3bd8f6f17 100644 --- a/arch/arm/mach-s3c2410/s3c2410.c +++ b/arch/arm/mach-s3c2410/s3c2410.c @@ -19,6 +19,7 @@ #include <linux/gpio.h> #include <linux/clk.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/serial_core.h> #include <linux/platform_device.h> #include <linux/io.h> @@ -40,6 +41,7 @@ #include <plat/devs.h> #include <plat/clock.h> #include <plat/pll.h> +#include <plat/pm.h> #include <plat/gpio-core.h> #include <plat/gpio-cfg.h> @@ -168,6 +170,9 @@ int __init s3c2410_init(void) { printk("S3C2410: Initialising architecture\n"); + register_syscore_ops(&s3c2410_pm_syscore_ops); + register_syscore_ops(&s3c24xx_irq_syscore_ops); + return sysdev_register(&s3c2410_sysdev); } diff --git a/arch/arm/mach-s3c2412/irq.c b/arch/arm/mach-s3c2412/irq.c index f3355d2ec634..1a1aa220972b 100644 --- a/arch/arm/mach-s3c2412/irq.c +++ b/arch/arm/mach-s3c2412/irq.c @@ -202,8 +202,6 @@ static int s3c2412_irq_add(struct sys_device *sysdev) static struct sysdev_driver s3c2412_irq_driver = { .add = s3c2412_irq_add, - .suspend = s3c24xx_irq_suspend, - .resume = s3c24xx_irq_resume, }; static int s3c2412_irq_init(void) diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c index 923e01bdf017..85dcaeb9e62f 100644 --- a/arch/arm/mach-s3c2412/mach-jive.c +++ b/arch/arm/mach-s3c2412/mach-jive.c @@ -17,7 +17,7 @@ #include <linux/timer.h> #include <linux/init.h> #include <linux/gpio.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/serial_core.h> #include <linux/platform_device.h> #include <linux/i2c.h> @@ -486,7 +486,7 @@ static struct s3c2410_udc_mach_info jive_udc_cfg __initdata = { /* Jive power management device */ #ifdef CONFIG_PM -static int jive_pm_suspend(struct sys_device *sd, pm_message_t state) +static int jive_pm_suspend(void) { /* Write the magic value u-boot uses to check for resume into * the INFORM0 register, and ensure INFORM1 is set to the @@ -498,10 +498,9 @@ static int jive_pm_suspend(struct sys_device *sd, pm_message_t state) return 0; } -static int jive_pm_resume(struct sys_device *sd) +static void jive_pm_resume(void) { __raw_writel(0x0, S3C2412_INFORM0); - return 0; } #else @@ -509,16 +508,11 @@ static int jive_pm_resume(struct sys_device *sd) #define jive_pm_resume NULL #endif -static struct sysdev_class jive_pm_sysclass = { - .name = "jive-pm", +static struct syscore_ops jive_pm_syscore_ops = { .suspend = jive_pm_suspend, .resume = jive_pm_resume, }; -static struct sys_device jive_pm_sysdev = { - .cls = &jive_pm_sysclass, -}; - static void __init jive_map_io(void) { s3c24xx_init_io(jive_iodesc, ARRAY_SIZE(jive_iodesc)); @@ -536,10 +530,9 @@ static void jive_power_off(void) static void __init jive_machine_init(void) { - /* register system devices for managing low level suspend */ + /* register system core operations for managing low level suspend */ - sysdev_class_register(&jive_pm_sysclass); - sysdev_register(&jive_pm_sysdev); + register_syscore_ops(&jive_pm_syscore_ops); /* write our sleep configurations for the IO. Pull down all unused * IO, ensure that we have turned off all peripherals we do not diff --git a/arch/arm/mach-s3c2412/pm.c b/arch/arm/mach-s3c2412/pm.c index a7417c479ffe..752b13a7b3db 100644 --- a/arch/arm/mach-s3c2412/pm.c +++ b/arch/arm/mach-s3c2412/pm.c @@ -17,6 +17,7 @@ #include <linux/timer.h> #include <linux/init.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/platform_device.h> #include <linux/io.h> @@ -86,13 +87,24 @@ static struct sleep_save s3c2412_sleep[] = { SAVE_ITEM(S3C2413_GPJSLPCON), }; -static int s3c2412_pm_suspend(struct sys_device *dev, pm_message_t state) +static struct sysdev_driver s3c2412_pm_driver = { + .add = s3c2412_pm_add, +}; + +static __init int s3c2412_pm_init(void) +{ + return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_pm_driver); +} + +arch_initcall(s3c2412_pm_init); + +static int s3c2412_pm_suspend(void) { s3c_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep)); return 0; } -static int s3c2412_pm_resume(struct sys_device *dev) +static void s3c2412_pm_resume(void) { unsigned long tmp; @@ -102,18 +114,9 @@ static int s3c2412_pm_resume(struct sys_device *dev) __raw_writel(tmp, S3C2412_PWRCFG); s3c_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep)); - return 0; } -static struct sysdev_driver s3c2412_pm_driver = { - .add = s3c2412_pm_add, +struct syscore_ops s3c2412_pm_syscore_ops = { .suspend = s3c2412_pm_suspend, .resume = s3c2412_pm_resume, }; - -static __init int s3c2412_pm_init(void) -{ - return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_pm_driver); -} - -arch_initcall(s3c2412_pm_init); diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c index 4c6df51ddf33..ef0958d3e5c6 100644 --- a/arch/arm/mach-s3c2412/s3c2412.c +++ b/arch/arm/mach-s3c2412/s3c2412.c @@ -19,6 +19,7 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/serial_core.h> #include <linux/platform_device.h> #include <linux/io.h> @@ -244,5 +245,8 @@ int __init s3c2412_init(void) { printk("S3C2412: Initialising architecture\n"); + register_syscore_ops(&s3c2412_pm_syscore_ops); + register_syscore_ops(&s3c24xx_irq_syscore_ops); + return sysdev_register(&s3c2412_sysdev); } diff --git a/arch/arm/mach-s3c2416/irq.c b/arch/arm/mach-s3c2416/irq.c index 77b38f2381c1..28ad20d42445 100644 --- a/arch/arm/mach-s3c2416/irq.c +++ b/arch/arm/mach-s3c2416/irq.c @@ -236,8 +236,6 @@ static int __init s3c2416_irq_add(struct sys_device *sysdev) static struct sysdev_driver s3c2416_irq_driver = { .add = s3c2416_irq_add, - .suspend = s3c24xx_irq_suspend, - .resume = s3c24xx_irq_resume, }; static int __init s3c2416_irq_init(void) diff --git a/arch/arm/mach-s3c2416/pm.c b/arch/arm/mach-s3c2416/pm.c index 4a04205b04d5..41db2b21e213 100644 --- a/arch/arm/mach-s3c2416/pm.c +++ b/arch/arm/mach-s3c2416/pm.c @@ -11,6 +11,7 @@ */ #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/io.h> #include <asm/cacheflush.h> @@ -55,30 +56,26 @@ static int s3c2416_pm_add(struct sys_device *sysdev) return 0; } -static int s3c2416_pm_suspend(struct sys_device *dev, pm_message_t state) +static struct sysdev_driver s3c2416_pm_driver = { + .add = s3c2416_pm_add, +}; + +static __init int s3c2416_pm_init(void) { - return 0; + return sysdev_driver_register(&s3c2416_sysclass, &s3c2416_pm_driver); } -static int s3c2416_pm_resume(struct sys_device *dev) +arch_initcall(s3c2416_pm_init); + + +static void s3c2416_pm_resume(void) { /* unset the return-from-sleep amd inform flags */ __raw_writel(0x0, S3C2443_PWRMODE); __raw_writel(0x0, S3C2412_INFORM0); __raw_writel(0x0, S3C2412_INFORM1); - - return 0; } -static struct sysdev_driver s3c2416_pm_driver = { - .add = s3c2416_pm_add, - .suspend = s3c2416_pm_suspend, +struct syscore_ops s3c2416_pm_syscore_ops = { .resume = s3c2416_pm_resume, }; - -static __init int s3c2416_pm_init(void) -{ - return sysdev_driver_register(&s3c2416_sysclass, &s3c2416_pm_driver); -} - -arch_initcall(s3c2416_pm_init); diff --git a/arch/arm/mach-s3c2416/s3c2416.c b/arch/arm/mach-s3c2416/s3c2416.c index ba7fd8737434..494ce913dc95 100644 --- a/arch/arm/mach-s3c2416/s3c2416.c +++ b/arch/arm/mach-s3c2416/s3c2416.c @@ -32,6 +32,7 @@ #include <linux/platform_device.h> #include <linux/serial_core.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/clk.h> #include <linux/io.h> @@ -54,6 +55,7 @@ #include <plat/devs.h> #include <plat/cpu.h> #include <plat/sdhci.h> +#include <plat/pm.h> #include <plat/iic-core.h> #include <plat/fb-core.h> @@ -95,6 +97,9 @@ int __init s3c2416_init(void) s3c_fb_setname("s3c2443-fb"); + register_syscore_ops(&s3c2416_pm_syscore_ops); + register_syscore_ops(&s3c24xx_irq_syscore_ops); + return sysdev_register(&s3c2416_sysdev); } diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c index 14dc67897757..d88536393310 100644 --- a/arch/arm/mach-s3c2440/mach-osiris.c +++ b/arch/arm/mach-s3c2440/mach-osiris.c @@ -17,7 +17,7 @@ #include <linux/init.h> #include <linux/gpio.h> #include <linux/device.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/serial_core.h> #include <linux/clk.h> #include <linux/i2c.h> @@ -284,7 +284,7 @@ static struct platform_device osiris_pcmcia = { #ifdef CONFIG_PM static unsigned char pm_osiris_ctrl0; -static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state) +static int osiris_pm_suspend(void) { unsigned int tmp; @@ -304,7 +304,7 @@ static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state) return 0; } -static int osiris_pm_resume(struct sys_device *sd) +static void osiris_pm_resume(void) { if (pm_osiris_ctrl0 & OSIRIS_CTRL0_FIX8) __raw_writeb(OSIRIS_CTRL1_FIX8, OSIRIS_VA_CTRL1); @@ -312,8 +312,6 @@ static int osiris_pm_resume(struct sys_device *sd) __raw_writeb(pm_osiris_ctrl0, OSIRIS_VA_CTRL0); s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT); - - return 0; } #else @@ -321,16 +319,11 @@ static int osiris_pm_resume(struct sys_device *sd) #define osiris_pm_resume NULL #endif -static struct sysdev_class osiris_pm_sysclass = { - .name = "mach-osiris", +static struct syscore_ops osiris_pm_syscore_ops = { .suspend = osiris_pm_suspend, .resume = osiris_pm_resume, }; -static struct sys_device osiris_pm_sysdev = { - .cls = &osiris_pm_sysclass, -}; - /* Link for DVS driver to TPS65011 */ static void osiris_tps_release(struct device *dev) @@ -439,8 +432,7 @@ static void __init osiris_map_io(void) static void __init osiris_init(void) { - sysdev_class_register(&osiris_pm_sysclass); - sysdev_register(&osiris_pm_sysdev); + register_syscore_ops(&osiris_pm_syscore_ops); s3c_i2c0_set_platdata(NULL); s3c_nand_set_platdata(&osiris_nand_info); diff --git a/arch/arm/mach-s3c2440/s3c2440.c b/arch/arm/mach-s3c2440/s3c2440.c index f7663f731ea0..ce99ff72838d 100644 --- a/arch/arm/mach-s3c2440/s3c2440.c +++ b/arch/arm/mach-s3c2440/s3c2440.c @@ -19,6 +19,7 @@ #include <linux/platform_device.h> #include <linux/serial_core.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/gpio.h> #include <linux/clk.h> #include <linux/io.h> @@ -33,6 +34,7 @@ #include <plat/devs.h> #include <plat/cpu.h> #include <plat/s3c244x.h> +#include <plat/pm.h> #include <plat/gpio-core.h> #include <plat/gpio-cfg.h> @@ -51,6 +53,12 @@ int __init s3c2440_init(void) s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT; s3c_device_wdt.resource[1].end = IRQ_S3C2440_WDT; + /* register suspend/resume handlers */ + + register_syscore_ops(&s3c2410_pm_syscore_ops); + register_syscore_ops(&s3c244x_pm_syscore_ops); + register_syscore_ops(&s3c24xx_irq_syscore_ops); + /* register our system device for everything else */ return sysdev_register(&s3c2440_sysdev); diff --git a/arch/arm/mach-s3c2440/s3c2442.c b/arch/arm/mach-s3c2440/s3c2442.c index ecf813546554..6224bad4d604 100644 --- a/arch/arm/mach-s3c2440/s3c2442.c +++ b/arch/arm/mach-s3c2440/s3c2442.c @@ -29,6 +29,7 @@ #include <linux/err.h> #include <linux/device.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/mutex.h> @@ -45,6 +46,7 @@ #include <plat/clock.h> #include <plat/cpu.h> #include <plat/s3c244x.h> +#include <plat/pm.h> #include <plat/gpio-core.h> #include <plat/gpio-cfg.h> @@ -167,6 +169,10 @@ int __init s3c2442_init(void) { printk("S3C2442: Initialising architecture\n"); + register_syscore_ops(&s3c2410_pm_syscore_ops); + register_syscore_ops(&s3c244x_pm_syscore_ops); + register_syscore_ops(&s3c24xx_irq_syscore_ops); + return sysdev_register(&s3c2442_sysdev); } diff --git a/arch/arm/mach-s3c2440/s3c244x-irq.c b/arch/arm/mach-s3c2440/s3c244x-irq.c index de07c2feaa32..c63e8f26d901 100644 --- a/arch/arm/mach-s3c2440/s3c244x-irq.c +++ b/arch/arm/mach-s3c2440/s3c244x-irq.c @@ -116,8 +116,6 @@ static int s3c244x_irq_add(struct sys_device *sysdev) static struct sysdev_driver s3c2440_irq_driver = { .add = s3c244x_irq_add, - .suspend = s3c24xx_irq_suspend, - .resume = s3c24xx_irq_resume, }; static int s3c2440_irq_init(void) @@ -129,8 +127,6 @@ arch_initcall(s3c2440_irq_init); static struct sysdev_driver s3c2442_irq_driver = { .add = s3c244x_irq_add, - .suspend = s3c24xx_irq_suspend, - .resume = s3c24xx_irq_resume, }; diff --git a/arch/arm/mach-s3c2440/s3c244x.c b/arch/arm/mach-s3c2440/s3c244x.c index 90c1707b9c95..7e8a23d2098a 100644 --- a/arch/arm/mach-s3c2440/s3c244x.c +++ b/arch/arm/mach-s3c2440/s3c244x.c @@ -19,6 +19,7 @@ #include <linux/serial_core.h> #include <linux/platform_device.h> #include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/clk.h> #include <linux/io.h> @@ -134,45 +135,14 @@ void __init s3c244x_init_clocks(int xtal) s3c2410_baseclk_add(); } -#ifdef CONFIG_PM - -static struct sleep_save s3c244x_sleep[] = { - SAVE_ITEM(S3C2440_DSC0), - SAVE_ITEM(S3C2440_DSC1), - SAVE_ITEM(S3C2440_GPJDAT), - SAVE_ITEM(S3C2440_GPJCON), - SAVE_ITEM(S3C2440_GPJUP) -}; - -static int s3c244x_suspend(struct sys_device *dev, pm_message_t state) -{ - s3c_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep)); - return 0; -} - -static int s3c244x_resume(struct sys_device *dev) -{ - s3c_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep)); - return 0; -} - -#else -#define s3c244x_suspend NULL -#define s3c244x_resume NULL -#endif - /* Since the S3C2442 and S3C2440 share items, put both sysclasses here */ struct sysdev_class s3c2440_sysclass = { .name = "s3c2440-core", - .suspend = s3c244x_suspend, - .resume = s3c244x_resume }; struct sysdev_class s3c2442_sysclass = { .name = "s3c2442-core", - .suspend = s3c244x_suspend, - .resume = s3c244x_resume }; /* need to register class before we actually register the device, and @@ -194,3 +164,33 @@ static int __init s3c2442_core_init(void) } core_initcall(s3c2442_core_init); + + +#ifdef CONFIG_PM +static struct sleep_save s3c244x_sleep[] = { + SAVE_ITEM(S3C2440_DSC0), + SAVE_ITEM(S3C2440_DSC1), + SAVE_ITEM(S3C2440_GPJDAT), + SAVE_ITEM(S3C2440_GPJCON), + SAVE_ITEM(S3C2440_GPJUP) +}; + +static int s3c244x_suspend(void) +{ + s3c_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep)); + return 0; +} + +static void s3c244x_resume(void) +{ + s3c_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep)); +} +#else +#define s3c244x_suspend NULL +#define s3c244x_resume NULL +#endif + +struct syscore_ops s3c244x_pm_syscore_ops = { + .suspend = s3c244x_suspend, + .resume = s3c244x_resume, +}; diff --git a/arch/arm/mach-s3c64xx/irq-pm.c b/arch/arm/mach-s3c64xx/irq-pm.c index da1bec64b9da..8bec61e242c7 100644 --- a/arch/arm/mach-s3c64xx/irq-pm.c +++ b/arch/arm/mach-s3c64xx/irq-pm.c @@ -13,7 +13,7 @@ */ #include <linux/kernel.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/interrupt.h> #include <linux/serial_core.h> #include <linux/irq.h> @@ -54,7 +54,7 @@ static struct irq_grp_save { static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS]; -static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state) +static int s3c64xx_irq_pm_suspend(void) { struct irq_grp_save *grp = eint_grp_save; int i; @@ -75,7 +75,7 @@ static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state) return 0; } -static int s3c64xx_irq_pm_resume(struct sys_device *dev) +static void s3c64xx_irq_pm_resume(void) { struct irq_grp_save *grp = eint_grp_save; int i; @@ -94,18 +94,18 @@ static int s3c64xx_irq_pm_resume(struct sys_device *dev) } S3C_PMDBG("%s: IRQ configuration restored\n", __func__); - return 0; } -static struct sysdev_driver s3c64xx_irq_driver = { +struct syscore_ops s3c64xx_irq_syscore_ops = { .suspend = s3c64xx_irq_pm_suspend, .resume = s3c64xx_irq_pm_resume, }; -static int __init s3c64xx_irq_pm_init(void) +static __init int s3c64xx_syscore_init(void) { - return sysdev_driver_register(&s3c64xx_sysclass, &s3c64xx_irq_driver); -} + register_syscore_ops(&s3c64xx_irq_syscore_ops); -arch_initcall(s3c64xx_irq_pm_init); + return 0; +} +core_initcall(s3c64xx_syscore_init); diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c index 549d7924fd4c..24febae3d4c0 100644 --- a/arch/arm/mach-s5pv210/pm.c +++ b/arch/arm/mach-s5pv210/pm.c @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/suspend.h> +#include <linux/syscore_ops.h> #include <linux/io.h> #include <plat/cpu.h> @@ -140,7 +141,17 @@ static int s5pv210_pm_add(struct sys_device *sysdev) return 0; } -static int s5pv210_pm_resume(struct sys_device *dev) +static struct sysdev_driver s5pv210_pm_driver = { + .add = s5pv210_pm_add, +}; + +static __init int s5pv210_pm_drvinit(void) +{ + return sysdev_driver_register(&s5pv210_sysclass, &s5pv210_pm_driver); +} +arch_initcall(s5pv210_pm_drvinit); + +static void s5pv210_pm_resume(void) { u32 tmp; @@ -150,17 +161,15 @@ static int s5pv210_pm_resume(struct sys_device *dev) __raw_writel(tmp , S5P_OTHERS); s3c_pm_do_restore_core(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save)); - - return 0; } -static struct sysdev_driver s5pv210_pm_driver = { - .add = s5pv210_pm_add, +static struct syscore_ops s5pv210_pm_syscore_ops = { .resume = s5pv210_pm_resume, }; -static __init int s5pv210_pm_drvinit(void) +static __init int s5pv210_pm_syscore_init(void) { - return sysdev_driver_register(&s5pv210_sysclass, &s5pv210_pm_driver); + register_syscore_ops(&s5pv210_pm_syscore_ops); + return 0; } -arch_initcall(s5pv210_pm_drvinit); +arch_initcall(s5pv210_pm_syscore_init); diff --git a/arch/arm/mach-sa1100/include/mach/memory.h b/arch/arm/mach-sa1100/include/mach/memory.h index a44da6a2916c..cff31ee246b7 100644 --- a/arch/arm/mach-sa1100/include/mach/memory.h +++ b/arch/arm/mach-sa1100/include/mach/memory.h @@ -14,18 +14,8 @@ */ #define PLAT_PHYS_OFFSET UL(0xc0000000) -#ifndef __ASSEMBLY__ - #ifdef CONFIG_SA1111 -void sa1111_adjust_zones(unsigned long *size, unsigned long *holes); - -#define arch_adjust_zones(size, holes) \ - sa1111_adjust_zones(size, holes) - -#define ISA_DMA_THRESHOLD (PHYS_OFFSET + SZ_1M - 1) -#define MAX_DMA_ADDRESS (PAGE_OFFSET + SZ_1M) - -#endif +#define ARM_DMA_ZONE_SIZE SZ_1M #endif /* diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c index 423ddb3d65e9..dfbf824a69fa 100644 --- a/arch/arm/mach-sa1100/irq.c +++ b/arch/arm/mach-sa1100/irq.c @@ -14,7 +14,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/ioport.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <mach/hardware.h> #include <asm/mach/irq.h> @@ -234,7 +234,7 @@ static struct sa1100irq_state { unsigned int iccr; } sa1100irq_state; -static int sa1100irq_suspend(struct sys_device *dev, pm_message_t state) +static int sa1100irq_suspend(void) { struct sa1100irq_state *st = &sa1100irq_state; @@ -264,7 +264,7 @@ static int sa1100irq_suspend(struct sys_device *dev, pm_message_t state) return 0; } -static int sa1100irq_resume(struct sys_device *dev) +static void sa1100irq_resume(void) { struct sa1100irq_state *st = &sa1100irq_state; @@ -277,24 +277,17 @@ static int sa1100irq_resume(struct sys_device *dev) ICMR = st->icmr; } - return 0; } -static struct sysdev_class sa1100irq_sysclass = { - .name = "sa11x0-irq", +static struct syscore_ops sa1100irq_syscore_ops = { .suspend = sa1100irq_suspend, .resume = sa1100irq_resume, }; -static struct sys_device sa1100irq_device = { - .id = 0, - .cls = &sa1100irq_sysclass, -}; - static int __init sa1100irq_init_devicefs(void) { - sysdev_class_register(&sa1100irq_sysclass); - return sysdev_register(&sa1100irq_device); + register_syscore_ops(&sa1100irq_syscore_ops); + return 0; } device_initcall(sa1100irq_init_devicefs); diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index ae4f3d80416f..fa6602491d54 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -92,25 +92,11 @@ sa1100_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c) static struct clock_event_device ckevt_sa1100_osmr0 = { .name = "osmr0", .features = CLOCK_EVT_FEAT_ONESHOT, - .shift = 32, .rating = 200, .set_next_event = sa1100_osmr0_set_next_event, .set_mode = sa1100_osmr0_set_mode, }; -static cycle_t sa1100_read_oscr(struct clocksource *s) -{ - return OSCR; -} - -static struct clocksource cksrc_sa1100_oscr = { - .name = "oscr", - .rating = 200, - .read = sa1100_read_oscr, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - static struct irqaction sa1100_timer_irq = { .name = "ost0", .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, @@ -120,14 +106,13 @@ static struct irqaction sa1100_timer_irq = { static void __init sa1100_timer_init(void) { - OIER = 0; /* disable any timer interrupts */ - OSSR = 0xf; /* clear status on all timers */ + OIER = 0; + OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; init_fixed_sched_clock(&cd, sa1100_update_sched_clock, 32, 3686400, SC_MULT, SC_SHIFT); - ckevt_sa1100_osmr0.mult = - div_sc(3686400, NSEC_PER_SEC, ckevt_sa1100_osmr0.shift); + clockevents_calc_mult_shift(&ckevt_sa1100_osmr0, 3686400, 4); ckevt_sa1100_osmr0.max_delta_ns = clockevent_delta2ns(0x7fffffff, &ckevt_sa1100_osmr0); ckevt_sa1100_osmr0.min_delta_ns = @@ -136,7 +121,8 @@ static void __init sa1100_timer_init(void) setup_irq(IRQ_OST0, &sa1100_timer_irq); - clocksource_register_hz(&cksrc_sa1100_oscr, CLOCK_TICK_RATE); + clocksource_mmio_init(&OSCR, "oscr", CLOCK_TICK_RATE, 200, 32, + clocksource_mmio_readl_up); clockevents_register_device(&ckevt_sa1100_osmr0); } diff --git a/arch/arm/mach-shark/include/mach/memory.h b/arch/arm/mach-shark/include/mach/memory.h index 9afb17000008..4c0831f83b0c 100644 --- a/arch/arm/mach-shark/include/mach/memory.h +++ b/arch/arm/mach-shark/include/mach/memory.h @@ -17,25 +17,7 @@ */ #define PLAT_PHYS_OFFSET UL(0x08000000) -#ifndef __ASSEMBLY__ - -static inline void __arch_adjust_zones(unsigned long *zone_size, unsigned long *zhole_size) -{ - /* Only the first 4 MB (=1024 Pages) are usable for DMA */ - /* See dev / -> .properties in OpenFirmware. */ - zone_size[1] = zone_size[0] - 1024; - zone_size[0] = 1024; - zhole_size[1] = zhole_size[0]; - zhole_size[0] = 0; -} - -#define arch_adjust_zones(size, holes) \ - __arch_adjust_zones(size, holes) - -#define ISA_DMA_THRESHOLD (PHYS_OFFSET + SZ_4M - 1) -#define MAX_DMA_ADDRESS (PAGE_OFFSET + SZ_4M) - -#endif +#define ARM_DMA_ZONE_SIZE SZ_4M /* * Cache flushing area diff --git a/arch/arm/mach-shmobile/include/mach/smp.h b/arch/arm/mach-shmobile/include/mach/smp.h deleted file mode 100644 index 50db94e927ad..000000000000 --- a/arch/arm/mach-shmobile/include/mach/smp.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __MACH_SMP_H -#define __MACH_SMP_H - -#include <asm/hardware/gic.h> - -/* - * We use IRQ1 as the IPI - */ -static inline void smp_cross_call(const struct cpumask *mask, int ipi) -{ -#if defined(CONFIG_ARM_GIC) - gic_raise_softirq(mask, ipi); -#endif -} - -#endif diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index 65e879bab4dc..f3888feb1c68 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c @@ -16,6 +16,7 @@ #include <linux/device.h> #include <linux/smp.h> #include <linux/io.h> +#include <asm/hardware/gic.h> #include <asm/localtimer.h> #include <asm/mach-types.h> #include <mach/common.h> @@ -57,6 +58,8 @@ void __init smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); + + set_smp_cross_call(gic_raise_softirq); } void __init platform_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-shmobile/pm_runtime.c b/arch/arm/mach-shmobile/pm_runtime.c index 94912d3944d3..2d1b67a59e4a 100644 --- a/arch/arm/mach-shmobile/pm_runtime.c +++ b/arch/arm/mach-shmobile/pm_runtime.c @@ -18,152 +18,41 @@ #include <linux/clk.h> #include <linux/sh_clk.h> #include <linux/bitmap.h> +#include <linux/slab.h> #ifdef CONFIG_PM_RUNTIME -#define BIT_ONCE 0 -#define BIT_ACTIVE 1 -#define BIT_CLK_ENABLED 2 -struct pm_runtime_data { - unsigned long flags; - struct clk *clk; -}; - -static void __devres_release(struct device *dev, void *res) -{ - struct pm_runtime_data *prd = res; - - dev_dbg(dev, "__devres_release()\n"); - - if (test_bit(BIT_CLK_ENABLED, &prd->flags)) - clk_disable(prd->clk); - - if (test_bit(BIT_ACTIVE, &prd->flags)) - clk_put(prd->clk); -} - -static struct pm_runtime_data *__to_prd(struct device *dev) -{ - return devres_find(dev, __devres_release, NULL, NULL); -} - -static void platform_pm_runtime_init(struct device *dev, - struct pm_runtime_data *prd) -{ - if (prd && !test_and_set_bit(BIT_ONCE, &prd->flags)) { - prd->clk = clk_get(dev, NULL); - if (!IS_ERR(prd->clk)) { - set_bit(BIT_ACTIVE, &prd->flags); - dev_info(dev, "clocks managed by runtime pm\n"); - } - } -} - -static void platform_pm_runtime_bug(struct device *dev, - struct pm_runtime_data *prd) -{ - if (prd && !test_and_set_bit(BIT_ONCE, &prd->flags)) - dev_err(dev, "runtime pm suspend before resume\n"); -} - -int platform_pm_runtime_suspend(struct device *dev) -{ - struct pm_runtime_data *prd = __to_prd(dev); - - dev_dbg(dev, "platform_pm_runtime_suspend()\n"); - - platform_pm_runtime_bug(dev, prd); - - if (prd && test_bit(BIT_ACTIVE, &prd->flags)) { - clk_disable(prd->clk); - clear_bit(BIT_CLK_ENABLED, &prd->flags); - } - - return 0; -} - -int platform_pm_runtime_resume(struct device *dev) -{ - struct pm_runtime_data *prd = __to_prd(dev); - - dev_dbg(dev, "platform_pm_runtime_resume()\n"); - - platform_pm_runtime_init(dev, prd); - - if (prd && test_bit(BIT_ACTIVE, &prd->flags)) { - clk_enable(prd->clk); - set_bit(BIT_CLK_ENABLED, &prd->flags); - } - - return 0; -} - -int platform_pm_runtime_idle(struct device *dev) +static int default_platform_runtime_idle(struct device *dev) { /* suspend synchronously to disable clocks immediately */ return pm_runtime_suspend(dev); } -static int platform_bus_notify(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct device *dev = data; - struct pm_runtime_data *prd; - - dev_dbg(dev, "platform_bus_notify() %ld !\n", action); - - if (action == BUS_NOTIFY_BIND_DRIVER) { - prd = devres_alloc(__devres_release, sizeof(*prd), GFP_KERNEL); - if (prd) - devres_add(dev, prd); - else - dev_err(dev, "unable to alloc memory for runtime pm\n"); - } - - return 0; -} - -#else /* CONFIG_PM_RUNTIME */ - -static int platform_bus_notify(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct device *dev = data; - struct clk *clk; +static struct dev_power_domain default_power_domain = { + .ops = { + .runtime_suspend = pm_runtime_clk_suspend, + .runtime_resume = pm_runtime_clk_resume, + .runtime_idle = default_platform_runtime_idle, + USE_PLATFORM_PM_SLEEP_OPS + }, +}; - dev_dbg(dev, "platform_bus_notify() %ld !\n", action); +#define DEFAULT_PWR_DOMAIN_PTR (&default_power_domain) - switch (action) { - case BUS_NOTIFY_BIND_DRIVER: - clk = clk_get(dev, NULL); - if (!IS_ERR(clk)) { - clk_enable(clk); - clk_put(clk); - dev_info(dev, "runtime pm disabled, clock forced on\n"); - } - break; - case BUS_NOTIFY_UNBOUND_DRIVER: - clk = clk_get(dev, NULL); - if (!IS_ERR(clk)) { - clk_disable(clk); - clk_put(clk); - dev_info(dev, "runtime pm disabled, clock forced off\n"); - } - break; - } +#else - return 0; -} +#define DEFAULT_PWR_DOMAIN_PTR NULL #endif /* CONFIG_PM_RUNTIME */ -static struct notifier_block platform_bus_notifier = { - .notifier_call = platform_bus_notify +static struct pm_clk_notifier_block platform_bus_notifier = { + .pwr_domain = DEFAULT_PWR_DOMAIN_PTR, + .con_ids = { NULL, }, }; static int __init sh_pm_runtime_init(void) { - bus_register_notifier(&platform_bus_type, &platform_bus_notifier); + pm_runtime_clk_add_notifier(&platform_bus_type, &platform_bus_notifier); return 0; } core_initcall(sh_pm_runtime_init); diff --git a/arch/arm/mach-tcc8k/time.c b/arch/arm/mach-tcc8k/time.c index e0a8d609afe1..a96babe83771 100644 --- a/arch/arm/mach-tcc8k/time.c +++ b/arch/arm/mach-tcc8k/time.c @@ -25,19 +25,6 @@ static void __iomem *timer_base; -static cycle_t tcc_get_cycles(struct clocksource *cs) -{ - return __raw_readl(timer_base + TC32MCNT_OFFS); -} - -static struct clocksource clocksource_tcc = { - .name = "tcc_tc32", - .rating = 200, - .read = tcc_get_cycles, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - static int tcc_set_next_event(unsigned long evt, struct clock_event_device *unused) { @@ -102,7 +89,8 @@ static int __init tcc_clockevent_init(struct clk *clock) { unsigned int c = clk_get_rate(clock); - clocksource_register_hz(&clocksource_tcc, c); + clocksource_mmio_init(timer_base + TC32MCNT_OFFS, "tcc_tc32", c, + 200, 32, clocksource_mmio_readl_up); clockevent_tcc.mult = div_sc(c, NSEC_PER_SEC, clockevent_tcc.shift); diff --git a/arch/arm/mach-tegra/include/mach/barriers.h b/arch/arm/mach-tegra/include/mach/barriers.h index cc115174899b..425b42e91ef6 100644 --- a/arch/arm/mach-tegra/include/mach/barriers.h +++ b/arch/arm/mach-tegra/include/mach/barriers.h @@ -23,7 +23,7 @@ #include <asm/outercache.h> -#define rmb() dmb() +#define rmb() dsb() #define wmb() do { dsb(); outer_sync(); } while (0) #define mb() wmb() diff --git a/arch/arm/mach-tegra/include/mach/smp.h b/arch/arm/mach-tegra/include/mach/smp.h deleted file mode 100644 index c8221b38ee7c..000000000000 --- a/arch/arm/mach-tegra/include/mach/smp.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef ASMARM_ARCH_SMP_H -#define ASMARM_ARCH_SMP_H - -#include <asm/hardware/gic.h> - -/* - * We use IRQ1 as the IPI - */ -static inline void smp_cross_call(const struct cpumask *mask, int ipi) -{ - gic_raise_softirq(mask, ipi); -} - -#endif diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index ec1f68924edf..b8ae3c978dee 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c @@ -20,6 +20,7 @@ #include <linux/io.h> #include <asm/cacheflush.h> +#include <asm/hardware/gic.h> #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/smp_scu.h> @@ -122,6 +123,8 @@ void __init smp_init_cpus(void) for (i = 0; i < ncores; i++) cpu_set(i, cpu_possible_map); + + set_smp_cross_call(gic_raise_softirq); } void __init platform_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index 0fcb1eb4214d..90350420c4e9 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c @@ -98,11 +98,6 @@ static void tegra_timer_set_mode(enum clock_event_mode mode, } } -static cycle_t tegra_clocksource_read(struct clocksource *cs) -{ - return timer_readl(TIMERUS_CNTR_1US); -} - static struct clock_event_device tegra_clockevent = { .name = "timer0", .rating = 300, @@ -111,14 +106,6 @@ static struct clock_event_device tegra_clockevent = { .set_mode = tegra_timer_set_mode, }; -static struct clocksource tegra_clocksource = { - .name = "timer_us", - .rating = 300, - .read = tegra_clocksource_read, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - static DEFINE_CLOCK_DATA(cd); /* @@ -234,7 +221,8 @@ static void __init tegra_init_timer(void) init_fixed_sched_clock(&cd, tegra_update_sched_clock, 32, 1000000, SC_MULT, SC_SHIFT); - if (clocksource_register_hz(&tegra_clocksource, 1000000)) { + if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US, + "timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) { printk(KERN_ERR "Failed to register clocksource\n"); BUG(); } diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index 3ec58bd2d6e4..891cf44591e0 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c @@ -333,20 +333,6 @@ static struct irqaction u300_timer_irq = { .handler = u300_timer_interrupt, }; -/* Use general purpose timer 2 as clock source */ -static cycle_t u300_get_cycles(struct clocksource *cs) -{ - return (cycles_t) readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC); -} - -static struct clocksource clocksource_u300_1mhz = { - .name = "GPT2", - .rating = 300, /* Reasonably fast and accurate clock source */ - .read = u300_get_cycles, - .mask = CLOCKSOURCE_MASK(32), /* 32 bits */ - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - /* * Override the global weak sched_clock symbol with this * local implementation which uses the clocksource to get some @@ -422,7 +408,9 @@ static void __init u300_timer_init(void) writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE, U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2); - if (clocksource_register_hz(&clocksource_u300_1mhz, rate)) + /* Use general purpose timer 2 as clock source */ + if (clocksource_mmio_init(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC, + "GPT2", rate, 300, 32, clocksource_mmio_readl_up)) printk(KERN_ERR "timer: failed to initialize clock " "source %s\n", clocksource_u300_1mhz.name); diff --git a/arch/arm/mach-ux500/include/mach/smp.h b/arch/arm/mach-ux500/include/mach/smp.h deleted file mode 100644 index ca2b15b1b3b1..000000000000 --- a/arch/arm/mach-ux500/include/mach/smp.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This file is based ARM realview platform. - * Copyright (C) ARM Limited. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ -#ifndef ASMARM_ARCH_SMP_H -#define ASMARM_ARCH_SMP_H - -#include <asm/hardware/gic.h> - -/* This is required to wakeup the secondary core */ -extern void u8500_secondary_startup(void); - -/* - * We use IRQ1 as the IPI - */ -static inline void smp_cross_call(const struct cpumask *mask, int ipi) -{ - gic_raise_softirq(mask, ipi); -} -#endif diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index 4fff4d408417..0c527fe2cebb 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -18,10 +18,14 @@ #include <linux/io.h> #include <asm/cacheflush.h> +#include <asm/hardware/gic.h> #include <asm/smp_scu.h> #include <mach/hardware.h> #include <mach/setup.h> +/* This is called from headsmp.S to wakeup the secondary core */ +extern void u8500_secondary_startup(void); + /* * control for which core is the next to come out of the secondary * boot "holding pen" @@ -94,7 +98,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) */ write_pen_release(cpu); - smp_cross_call(cpumask_of(cpu), 1); + gic_raise_softirq(cpumask_of(cpu), 1); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { @@ -162,6 +166,8 @@ void __init smp_init_cpus(void) for (i = 0; i < ncores; i++) set_cpu_possible(i, true); + + set_smp_cross_call(gic_raise_softirq); } void __init platform_smp_prepare_cpus(unsigned int max_cpus) diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index eb7ffa0ee8b5..0c99cf076c63 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -32,6 +32,7 @@ #include <linux/io.h> #include <linux/gfp.h> #include <linux/clkdev.h> +#include <linux/mtd/physmap.h> #include <asm/system.h> #include <asm/irq.h> @@ -42,7 +43,6 @@ #include <asm/mach-types.h> #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> @@ -190,27 +190,7 @@ void __init versatile_map_io(void) #define VERSATILE_FLASHCTRL (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_FLASH_OFFSET) -static int versatile_flash_init(void) -{ - u32 val; - - val = __raw_readl(VERSATILE_FLASHCTRL); - val &= ~VERSATILE_FLASHPROG_FLVPPEN; - __raw_writel(val, VERSATILE_FLASHCTRL); - - return 0; -} - -static void versatile_flash_exit(void) -{ - u32 val; - - val = __raw_readl(VERSATILE_FLASHCTRL); - val &= ~VERSATILE_FLASHPROG_FLVPPEN; - __raw_writel(val, VERSATILE_FLASHCTRL); -} - -static void versatile_flash_set_vpp(int on) +static void versatile_flash_set_vpp(struct platform_device *pdev, int on) { u32 val; @@ -222,11 +202,8 @@ static void versatile_flash_set_vpp(int on) __raw_writel(val, VERSATILE_FLASHCTRL); } -static struct flash_platform_data versatile_flash_data = { - .map_name = "cfi_probe", +static struct physmap_flash_data versatile_flash_data = { .width = 4, - .init = versatile_flash_init, - .exit = versatile_flash_exit, .set_vpp = versatile_flash_set_vpp, }; @@ -237,7 +214,7 @@ static struct resource versatile_flash_resource = { }; static struct platform_device versatile_flash_device = { - .name = "armflash", + .name = "physmap-flash", .id = 0, .dev = { .platform_data = &versatile_flash_data, @@ -375,6 +352,10 @@ static struct clk ref24_clk = { .rate = 24000000, }; +static struct clk sp804_clk = { + .rate = 1000000, +}; + static struct clk dummy_apb_pclk; static struct clk_lookup lookups[] = { @@ -411,7 +392,10 @@ static struct clk_lookup lookups[] = { }, { /* CLCD */ .dev_id = "dev:20", .clk = &osc4_clk, - } + }, { /* SP804 timers */ + .dev_id = "sp804", + .clk = &sp804_clk, + }, }; /* @@ -764,8 +748,8 @@ static void __init versatile_timer_init(void) writel(0, TIMER2_VA_BASE + TIMER_CTRL); writel(0, TIMER3_VA_BASE + TIMER_CTRL); - sp804_clocksource_init(TIMER3_VA_BASE); - sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMERINT0_1); + sp804_clocksource_init(TIMER3_VA_BASE, "timer3"); + sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMERINT0_1, "timer0"); } struct sys_timer versatile_timer = { diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index ebc22e759325..765a71ff7f3b 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -71,8 +71,9 @@ static void __init ct_ca9x4_timer_init(void) writel(0, MMIO_P2V(CT_CA9X4_TIMER0) + TIMER_CTRL); writel(0, MMIO_P2V(CT_CA9X4_TIMER1) + TIMER_CTRL); - sp804_clocksource_init(MMIO_P2V(CT_CA9X4_TIMER1)); - sp804_clockevents_init(MMIO_P2V(CT_CA9X4_TIMER0), IRQ_CT_CA9X4_TIMER0); + sp804_clocksource_init(MMIO_P2V(CT_CA9X4_TIMER1), "ct-timer1"); + sp804_clockevents_init(MMIO_P2V(CT_CA9X4_TIMER0), IRQ_CT_CA9X4_TIMER0, + "ct-timer0"); } static struct sys_timer ct_ca9x4_timer = { @@ -141,10 +142,22 @@ static struct clk osc1_clk = { .rate = 24000000, }; +static struct clk ct_sp804_clk = { + .rate = 1000000, +}; + static struct clk_lookup lookups[] = { { /* CLCD */ .dev_id = "ct:clcd", .clk = &osc1_clk, + }, { /* SP804 timers */ + .dev_id = "sp804", + .con_id = "ct-timer0", + .clk = &ct_sp804_clk, + }, { /* SP804 timers */ + .dev_id = "sp804", + .con_id = "ct-timer1", + .clk = &ct_sp804_clk, }, }; @@ -210,6 +223,8 @@ static void ct_ca9x4_init_cpu_map(void) for (i = 0; i < ncores; ++i) set_cpu_possible(i, true); + + set_smp_cross_call(gic_raise_softirq); } static void ct_ca9x4_smp_enable(unsigned int max_cpus) diff --git a/arch/arm/mach-vexpress/include/mach/smp.h b/arch/arm/mach-vexpress/include/mach/smp.h deleted file mode 100644 index 4c05e4a9713a..000000000000 --- a/arch/arm/mach-vexpress/include/mach/smp.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __MACH_SMP_H -#define __MACH_SMP_H - -#include <asm/hardware/gic.h> - -/* - * We use IRQ1 as the IPI - */ -static inline void smp_cross_call(const struct cpumask *mask, int ipi) -{ - gic_raise_softirq(mask, ipi); -} -#endif diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index ba46e8e07437..285edcd2da2a 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -13,11 +13,11 @@ #include <linux/sysdev.h> #include <linux/usb/isp1760.h> #include <linux/clkdev.h> +#include <linux/mtd/physmap.h> #include <asm/mach-types.h> #include <asm/sizes.h> #include <asm/mach/arch.h> -#include <asm/mach/flash.h> #include <asm/mach/map.h> #include <asm/mach/time.h> #include <asm/hardware/arm_timer.h> @@ -65,8 +65,9 @@ static void __init v2m_timer_init(void) writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL); writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL); - sp804_clocksource_init(MMIO_P2V(V2M_TIMER1)); - sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0); + sp804_clocksource_init(MMIO_P2V(V2M_TIMER1), "v2m-timer1"); + sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0, + "v2m-timer0"); } static struct sys_timer v2m_timer = { @@ -206,27 +207,13 @@ static struct platform_device v2m_usb_device = { .dev.platform_data = &v2m_usb_config, }; -static int v2m_flash_init(void) -{ - writel(0, MMIO_P2V(V2M_SYS_FLASH)); - return 0; -} - -static void v2m_flash_exit(void) -{ - writel(0, MMIO_P2V(V2M_SYS_FLASH)); -} - -static void v2m_flash_set_vpp(int on) +static void v2m_flash_set_vpp(struct platform_device *pdev, int on) { writel(on != 0, MMIO_P2V(V2M_SYS_FLASH)); } -static struct flash_platform_data v2m_flash_data = { - .map_name = "cfi_probe", +static struct physmap_flash_data v2m_flash_data = { .width = 4, - .init = v2m_flash_init, - .exit = v2m_flash_exit, .set_vpp = v2m_flash_set_vpp, }; @@ -243,7 +230,7 @@ static struct resource v2m_flash_resources[] = { }; static struct platform_device v2m_flash_device = { - .name = "armflash", + .name = "physmap-flash", .id = -1, .resource = v2m_flash_resources, .num_resources = ARRAY_SIZE(v2m_flash_resources), @@ -333,6 +320,10 @@ static struct clk osc2_clk = { .rate = 24000000, }; +static struct clk v2m_sp804_clk = { + .rate = 1000000, +}; + static struct clk dummy_apb_pclk; static struct clk_lookup v2m_lookups[] = { @@ -363,6 +354,14 @@ static struct clk_lookup v2m_lookups[] = { }, { /* CLCD */ .dev_id = "mb:clcd", .clk = &osc1_clk, + }, { /* SP804 timers */ + .dev_id = "sp804", + .con_id = "v2m-timer0", + .clk = &v2m_sp804_clk, + }, { /* SP804 timers */ + .dev_id = "sp804", + .con_id = "v2m-timer1", + .clk = &v2m_sp804_clk, }, }; diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c index 4b089cb930dc..a2c4e2d0a0d4 100644 --- a/arch/arm/mach-w90x900/time.c +++ b/arch/arm/mach-w90x900/time.c @@ -43,7 +43,6 @@ #define PRESCALE 0x63 /* Divider = prescale + 1 */ #define TDR_SHIFT 24 -#define TDR_MASK ((1 << TDR_SHIFT) - 1) static unsigned int timer0_load; @@ -143,19 +142,6 @@ static void __init nuc900_clockevents_init(void) clockevents_register_device(&nuc900_clockevent_device); } -static cycle_t nuc900_get_cycles(struct clocksource *cs) -{ - return (~__raw_readl(REG_TDR1)) & TDR_MASK; -} - -static struct clocksource clocksource_nuc900 = { - .name = "nuc900-timer1", - .rating = 200, - .read = nuc900_get_cycles, - .mask = CLOCKSOURCE_MASK(TDR_SHIFT), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - static void __init nuc900_clocksource_init(void) { unsigned int val; @@ -175,7 +161,8 @@ static void __init nuc900_clocksource_init(void) val |= (COUNTEN | PERIOD | PRESCALE); __raw_writel(val, REG_TCSR1); - clocksource_register_hz(&clocksource_nuc900, rate); + clocksource_mmio_init(REG_TDR1, "nuc900-timer1", rate, 200, + TDR_SHIFT, clocksource_mmio_readl_down); } static void __init nuc900_timer_init(void) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index e5f6fc428348..76f82ae44efb 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -201,6 +201,20 @@ static void __init arm_bootmem_init(unsigned long start_pfn, } } +#ifdef CONFIG_ZONE_DMA +static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole, + unsigned long dma_size) +{ + if (size[0] <= dma_size) + return; + + size[ZONE_NORMAL] = size[0] - dma_size; + size[ZONE_DMA] = dma_size; + hole[ZONE_NORMAL] = hole[0]; + hole[ZONE_DMA] = 0; +} +#endif + static void __init arm_bootmem_free(unsigned long min, unsigned long max_low, unsigned long max_high) { @@ -243,11 +257,18 @@ static void __init arm_bootmem_free(unsigned long min, unsigned long max_low, #endif } +#ifdef ARM_DMA_ZONE_SIZE +#ifndef CONFIG_ZONE_DMA +#error ARM_DMA_ZONE_SIZE set but no DMA zone to limit allocations +#endif + /* * Adjust the sizes according to any special requirements for * this machine type. */ - arch_adjust_zones(zone_size, zhole_size); + arm_adjust_dma_zone(zone_size, zhole_size, + ARM_DMA_ZONE_SIZE >> PAGE_SHIFT); +#endif free_area_init_node(0, zone_size, min, zhole_size); } @@ -392,7 +413,7 @@ free_memmap(unsigned long start_pfn, unsigned long end_pfn) * Convert start_pfn/end_pfn to a struct page pointer. */ start_pg = pfn_to_page(start_pfn - 1) + 1; - end_pg = pfn_to_page(end_pfn); + end_pg = pfn_to_page(end_pfn - 1) + 1; /* * Convert to physical addresses, and @@ -426,6 +447,14 @@ static void __init free_unused_memmap(struct meminfo *mi) bank_start = bank_pfn_start(bank); +#ifdef CONFIG_SPARSEMEM + /* + * Take care not to free memmap entries that don't exist + * due to SPARSEMEM sections which aren't present. + */ + bank_start = min(bank_start, + ALIGN(prev_bank_end, PAGES_PER_SECTION)); +#endif /* * If we had a previous bank, and there is a space * between the current bank and the previous, free it. @@ -440,6 +469,12 @@ static void __init free_unused_memmap(struct meminfo *mi) */ prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES); } + +#ifdef CONFIG_SPARSEMEM + if (!IS_ALIGNED(prev_bank_end, PAGES_PER_SECTION)) + free_memmap(prev_bank_end, + ALIGN(prev_bank_end, PAGES_PER_SECTION)); +#endif } static void __init free_highpages(void) diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index ce233bcbf506..42af97664c9d 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -395,7 +395,7 @@ ENTRY(xscale_dma_a0_map_area) teq r2, #DMA_TO_DEVICE beq xscale_dma_clean_range b xscale_dma_flush_range -ENDPROC(xscsale_dma_a0_map_area) +ENDPROC(xscale_dma_a0_map_area) /* * dma_unmap_area(start, size, dir) diff --git a/arch/arm/plat-mxc/epit.c b/arch/arm/plat-mxc/epit.c index d69d343ff61f..d3467f818c33 100644 --- a/arch/arm/plat-mxc/epit.c +++ b/arch/arm/plat-mxc/epit.c @@ -83,26 +83,12 @@ static void epit_irq_acknowledge(void) __raw_writel(EPITSR_OCIF, timer_base + EPITSR); } -static cycle_t epit_read(struct clocksource *cs) -{ - return 0 - __raw_readl(timer_base + EPITCNR); -} - -static struct clocksource clocksource_epit = { - .name = "epit", - .rating = 200, - .read = epit_read, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - static int __init epit_clocksource_init(struct clk *timer_clk) { unsigned int c = clk_get_rate(timer_clk); - clocksource_register_hz(&clocksource_epit, c); - - return 0; + return clocksource_mmio_init(timer_base + EPITCNR, "epit", c, 200, 32, + clocksource_mmio_readl_down); } /* clock event */ diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index 7a107246fd98..6cd6d7f686f6 100644 --- a/arch/arm/plat-mxc/gpio.c +++ b/arch/arm/plat-mxc/gpio.c @@ -295,6 +295,12 @@ static int mxc_gpio_direction_output(struct gpio_chip *chip, return 0; } +/* + * This lock class tells lockdep that GPIO irqs are in a different + * category than their parents, so it won't report false recursion. + */ +static struct lock_class_key gpio_lock_class; + int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt) { int i, j; @@ -311,6 +317,7 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt) __raw_writel(~0, port[i].base + GPIO_ISR); for (j = port[i].virtual_irq_start; j < port[i].virtual_irq_start + 32; j++) { + irq_set_lockdep_class(j, &gpio_lock_class); irq_set_chip_and_handler(j, &gpio_irq_chip, handle_level_irq); set_irq_flags(j, IRQF_VALID); diff --git a/arch/arm/plat-mxc/ssi-fiq.S b/arch/arm/plat-mxc/ssi-fiq.S index 4ddce565b353..8397a2dd19f2 100644 --- a/arch/arm/plat-mxc/ssi-fiq.S +++ b/arch/arm/plat-mxc/ssi-fiq.S @@ -124,6 +124,8 @@ imx_ssi_fiq_start: 1: @ return from FIQ subs pc, lr, #4 + + .align imx_ssi_fiq_base: .word 0x0 imx_ssi_fiq_rx_buffer: diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c index 2237ff8b434f..e4ac94a86832 100644 --- a/arch/arm/plat-mxc/time.c +++ b/arch/arm/plat-mxc/time.c @@ -106,56 +106,32 @@ static void gpt_irq_acknowledge(void) __raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT); } -static cycle_t dummy_get_cycles(struct clocksource *cs) -{ - return 0; -} - -static cycle_t mx1_2_get_cycles(struct clocksource *cs) -{ - return __raw_readl(timer_base + MX1_2_TCN); -} - -static cycle_t v2_get_cycles(struct clocksource *cs) -{ - return __raw_readl(timer_base + V2_TCN); -} - -static struct clocksource clocksource_mxc = { - .name = "mxc_timer1", - .rating = 200, - .read = dummy_get_cycles, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; +static void __iomem *sched_clock_reg; static DEFINE_CLOCK_DATA(cd); unsigned long long notrace sched_clock(void) { - cycle_t cyc = clocksource_mxc.read(&clocksource_mxc); + cycle_t cyc = sched_clock_reg ? __raw_readl(sched_clock_reg) : 0; return cyc_to_sched_clock(&cd, cyc, (u32)~0); } static void notrace mxc_update_sched_clock(void) { - cycle_t cyc = clocksource_mxc.read(&clocksource_mxc); + cycle_t cyc = sched_clock_reg ? __raw_readl(sched_clock_reg) : 0; update_sched_clock(&cd, cyc, (u32)~0); } static int __init mxc_clocksource_init(struct clk *timer_clk) { unsigned int c = clk_get_rate(timer_clk); + void __iomem *reg = timer_base + (timer_is_v2() ? V2_TCN : MX1_2_TCN); - if (timer_is_v2()) - clocksource_mxc.read = v2_get_cycles; - else - clocksource_mxc.read = mx1_2_get_cycles; + sched_clock_reg = reg; init_sched_clock(&cd, mxc_update_sched_clock, 32, c); - clocksource_register_hz(&clocksource_mxc, c); - - return 0; + return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32, + clocksource_mmio_readl_up); } /* clock event */ diff --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig index 187f4e84bb22..18296ee68802 100644 --- a/arch/arm/plat-nomadik/Kconfig +++ b/arch/arm/plat-nomadik/Kconfig @@ -5,6 +5,7 @@ config PLAT_NOMADIK bool depends on ARCH_NOMADIK || ARCH_U8500 + select CLKSRC_MMIO default y help Common platform code for Nomadik and other ST-Ericsson diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index 41723402006b..ef74e157a9d5 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c @@ -26,29 +26,6 @@ void __iomem *mtu_base; /* Assigned by machine code */ /* - * Kernel assumes that sched_clock can be called early - * but the MTU may not yet be initialized. - */ -static cycle_t nmdk_read_timer_dummy(struct clocksource *cs) -{ - return 0; -} - -/* clocksource: MTU decrements, so we negate the value being read. */ -static cycle_t nmdk_read_timer(struct clocksource *cs) -{ - return -readl(mtu_base + MTU_VAL(0)); -} - -static struct clocksource nmdk_clksrc = { - .name = "mtu_0", - .rating = 200, - .read = nmdk_read_timer_dummy, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -/* * Override the global weak sched_clock symbol with this * local implementation which uses the clocksource to get some * better resolution when scheduling the kernel. @@ -172,12 +149,10 @@ void __init nmdk_timer_init(void) writel(0, mtu_base + MTU_BGLR(0)); writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0)); - /* Now the clock source is ready */ - nmdk_clksrc.read = nmdk_read_timer; - - if (clocksource_register_hz(&nmdk_clksrc, rate)) + if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0", + rate, 200, 32, clocksource_mmio_readl_down)) pr_err("timer: failed to initialize clock source %s\n", - nmdk_clksrc.name); + "mtu_0"); init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate); diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index cd5f993612fd..e9c0efc5d4af 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -12,6 +12,7 @@ choice config ARCH_OMAP1 bool "TI OMAP1" select CLKDEV_LOOKUP + select CLKSRC_MMIO help "Systems based on omap7xx, omap15xx or omap16xx" diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index d2adcdda23cf..bd9e32187eab 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -17,7 +17,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/interrupt.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> @@ -1372,9 +1372,7 @@ static const struct dev_pm_ops omap_mpuio_dev_pm_ops = { .resume_noirq = omap_mpuio_resume_noirq, }; -/* use platform_driver for this, now that there's no longer any - * point to sys_device (other than not disturbing old code). - */ +/* use platform_driver for this. */ static struct platform_driver omap_mpuio_driver = { .driver = { .name = "mpuio", @@ -1745,7 +1743,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) } #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS) -static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg) +static int omap_gpio_suspend(void) { int i; @@ -1795,12 +1793,12 @@ static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg) return 0; } -static int omap_gpio_resume(struct sys_device *dev) +static void omap_gpio_resume(void) { int i; if (!cpu_class_is_omap2() && !cpu_is_omap16xx()) - return 0; + return; for (i = 0; i < gpio_bank_count; i++) { struct gpio_bank *bank = &gpio_bank[i]; @@ -1836,21 +1834,13 @@ static int omap_gpio_resume(struct sys_device *dev) __raw_writel(bank->saved_wakeup, wake_set); spin_unlock_irqrestore(&bank->lock, flags); } - - return 0; } -static struct sysdev_class omap_gpio_sysclass = { - .name = "gpio", +static struct syscore_ops omap_gpio_syscore_ops = { .suspend = omap_gpio_suspend, .resume = omap_gpio_resume, }; -static struct sys_device omap_gpio_device = { - .id = 0, - .cls = &omap_gpio_sysclass, -}; - #endif #ifdef CONFIG_ARCH_OMAP2PLUS @@ -2108,21 +2098,14 @@ postcore_initcall(omap_gpio_drv_reg); static int __init omap_gpio_sysinit(void) { - int ret = 0; - mpuio_init(); #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS) - if (cpu_is_omap16xx() || cpu_class_is_omap2()) { - if (ret == 0) { - ret = sysdev_class_register(&omap_gpio_sysclass); - if (ret == 0) - ret = sysdev_register(&omap_gpio_device); - } - } + if (cpu_is_omap16xx() || cpu_class_is_omap2()) + register_syscore_ops(&omap_gpio_syscore_ops); #endif - return ret; + return 0; } arch_initcall(omap_gpio_sysinit); diff --git a/arch/arm/plat-omap/include/plat/flash.h b/arch/arm/plat-omap/include/plat/flash.h index 3e6327016b40..3083195123ea 100644 --- a/arch/arm/plat-omap/include/plat/flash.h +++ b/arch/arm/plat-omap/include/plat/flash.h @@ -11,6 +11,6 @@ #include <linux/mtd/map.h> -extern void omap1_set_vpp(struct map_info *map, int enable); +extern void omap1_set_vpp(struct platform_device *pdev, int enable); #endif diff --git a/arch/arm/plat-omap/include/plat/smp.h b/arch/arm/plat-omap/include/plat/smp.h deleted file mode 100644 index 7a10257909ef..000000000000 --- a/arch/arm/plat-omap/include/plat/smp.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * OMAP4 machine specific smp.h - * - * Copyright (C) 2009 Texas Instruments, Inc. - * - * Author: - * Santosh Shilimkar <santosh.shilimkar@ti.com> - * - * Interface functions needed for the SMP. This file is based on arm - * realview smp platform. - * Copyright (c) 2003 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. - */ -#ifndef OMAP_ARCH_SMP_H -#define OMAP_ARCH_SMP_H - -#include <asm/hardware/gic.h> - -/* Needed for secondary core boot */ -extern void omap_secondary_startup(void); -extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask); -extern void omap_auxcoreboot_addr(u32 cpu_addr); -extern u32 omap_read_auxcoreboot0(void); - -/* - * We use Soft IRQ1 as the IPI - */ -static inline void smp_cross_call(const struct cpumask *mask, int ipi) -{ - gic_raise_softirq(mask, ipi); -} - -#endif diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index 8a51fd58f656..34fc31ee9081 100644 --- a/arch/arm/plat-omap/iommu.c +++ b/arch/arm/plat-omap/iommu.c @@ -793,6 +793,8 @@ static irqreturn_t iommu_fault_handler(int irq, void *data) clk_enable(obj->clk); errs = iommu_report_fault(obj, &da); clk_disable(obj->clk); + if (errs == 0) + return IRQ_HANDLED; /* Fault callback or TLB/PTE Dynamic loading */ if (obj->isr && !obj->isr(obj, da, errs, obj->isr_priv)) diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index 9bbda9acb73b..a37b8eb65b76 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -536,6 +536,28 @@ int omap_early_device_register(struct omap_device *od) return 0; } +static int _od_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + return omap_device_idle(pdev); +} + +static int _od_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + return omap_device_enable(pdev); +} + +static struct dev_power_domain omap_device_power_domain = { + .ops = { + .runtime_suspend = _od_runtime_suspend, + .runtime_resume = _od_runtime_resume, + USE_PLATFORM_PM_SLEEP_OPS + } +}; + /** * omap_device_register - register an omap_device with one omap_hwmod * @od: struct omap_device * to register @@ -549,6 +571,7 @@ int omap_device_register(struct omap_device *od) pr_debug("omap_device: %s: registering\n", od->pdev.name); od->pdev.dev.parent = &omap_device_parent; + od->pdev.dev.pwr_domain = &omap_device_power_domain; return platform_device_register(&od->pdev); } diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c index 742b0323c57b..69a61367e4b8 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c @@ -81,24 +81,6 @@ static void __init setup_sched_clock(unsigned long tclk) } /* - * Clocksource handling. - */ -static cycle_t orion_clksrc_read(struct clocksource *cs) -{ - return 0xffffffff - readl(timer_base + TIMER0_VAL_OFF); -} - -static struct clocksource orion_clksrc = { - .name = "orion_clocksource", - .rating = 300, - .read = orion_clksrc_read, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - - - -/* * Clockevent handling. */ static int @@ -247,7 +229,8 @@ orion_time_init(u32 _bridge_base, u32 _bridge_timer1_clr_mask, writel(u & ~BRIDGE_INT_TIMER0, bridge_base + BRIDGE_MASK_OFF); u = readl(timer_base + TIMER_CTRL_OFF); writel(u | TIMER0_EN | TIMER0_RELOAD_EN, timer_base + TIMER_CTRL_OFF); - clocksource_register_hz(&orion_clksrc, tclk); + clocksource_mmio_init(timer_base + TIMER0_VAL_OFF, "orion_clocksource", + tclk, 300, 32, clocksource_mmio_readl_down); /* * Setup clockevent timer (interrupt-driven). diff --git a/arch/arm/plat-pxa/gpio.c b/arch/arm/plat-pxa/gpio.c index dce088f45678..48ebb9479b61 100644 --- a/arch/arm/plat-pxa/gpio.c +++ b/arch/arm/plat-pxa/gpio.c @@ -15,7 +15,7 @@ #include <linux/init.h> #include <linux/irq.h> #include <linux/io.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/slab.h> #include <mach/gpio.h> @@ -295,7 +295,7 @@ void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) } #ifdef CONFIG_PM -static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state) +static int pxa_gpio_suspend(void) { struct pxa_gpio_chip *c; int gpio; @@ -312,7 +312,7 @@ static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state) return 0; } -static int pxa_gpio_resume(struct sys_device *dev) +static void pxa_gpio_resume(void) { struct pxa_gpio_chip *c; int gpio; @@ -326,22 +326,13 @@ static int pxa_gpio_resume(struct sys_device *dev) __raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET); __raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET); } - return 0; } #else #define pxa_gpio_suspend NULL #define pxa_gpio_resume NULL #endif -struct sysdev_class pxa_gpio_sysclass = { - .name = "gpio", +struct syscore_ops pxa_gpio_syscore_ops = { .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/plat-pxa/mfp.c b/arch/arm/plat-pxa/mfp.c index a9aa5ad3f4eb..be12eadcce20 100644 --- a/arch/arm/plat-pxa/mfp.c +++ b/arch/arm/plat-pxa/mfp.c @@ -17,7 +17,6 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/io.h> -#include <linux/sysdev.h> #include <plat/mfp.h> diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index 27ea852e3370..c10d10c56e2e 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -22,7 +22,7 @@ #include <linux/sched.h> #include <linux/spinlock.h> #include <linux/interrupt.h> -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> #include <linux/slab.h> #include <linux/errno.h> #include <linux/io.h> @@ -1195,19 +1195,12 @@ int s3c2410_dma_getposition(unsigned int channel, dma_addr_t *src, dma_addr_t *d EXPORT_SYMBOL(s3c2410_dma_getposition); -static inline struct s3c2410_dma_chan *to_dma_chan(struct sys_device *dev) -{ - return container_of(dev, struct s3c2410_dma_chan, dev); -} - -/* system device class */ +/* system core operations */ #ifdef CONFIG_PM -static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state) +static void s3c2410_dma_suspend_chan(s3c2410_dma_chan *cp) { - struct s3c2410_dma_chan *cp = to_dma_chan(dev); - printk(KERN_DEBUG "suspending dma channel %d\n", cp->number); if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) { @@ -1222,13 +1215,21 @@ static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state) s3c2410_dma_dostop(cp); } +} + +static int s3c2410_dma_suspend(void) +{ + struct s3c2410_dma_chan *cp = s3c2410_chans; + int channel; + + for (channel = 0; channel < dma_channels; cp++, channel++) + s3c2410_dma_suspend_chan(cp); return 0; } -static int s3c2410_dma_resume(struct sys_device *dev) +static void s3c2410_dma_resume_chan(struct s3c2410_dma_chan *cp) { - struct s3c2410_dma_chan *cp = to_dma_chan(dev); unsigned int no = cp->number | DMACH_LOW_LEVEL; /* restore channel's hardware configuration */ @@ -1249,13 +1250,21 @@ static int s3c2410_dma_resume(struct sys_device *dev) return 0; } +static void s3c2410_dma_resume(void) +{ + struct s3c2410_dma_chan *cp = s3c2410_chans + dma_channels - 1; + int channel; + + for (channel = dma_channels - 1; channel >= 0; cp++, channel--) + s3c2410_dma_resume_chan(cp); +} + #else #define s3c2410_dma_suspend NULL #define s3c2410_dma_resume NULL #endif /* CONFIG_PM */ -struct sysdev_class dma_sysclass = { - .name = "s3c24xx-dma", +struct syscore_ops dma_syscore_ops = { .suspend = s3c2410_dma_suspend, .resume = s3c2410_dma_resume, }; @@ -1269,39 +1278,14 @@ static void s3c2410_dma_cache_ctor(void *p) /* initialisation code */ -static int __init s3c24xx_dma_sysclass_init(void) +static int __init s3c24xx_dma_syscore_init(void) { - int ret = sysdev_class_register(&dma_sysclass); - - if (ret != 0) - printk(KERN_ERR "dma sysclass registration failed\n"); - - return ret; -} - -core_initcall(s3c24xx_dma_sysclass_init); - -static int __init s3c24xx_dma_sysdev_register(void) -{ - struct s3c2410_dma_chan *cp = s3c2410_chans; - int channel, ret; - - for (channel = 0; channel < dma_channels; cp++, channel++) { - cp->dev.cls = &dma_sysclass; - cp->dev.id = channel; - ret = sysdev_register(&cp->dev); - - if (ret) { - printk(KERN_ERR "error registering dev for dma %d\n", - channel); - return ret; - } - } + register_syscore_ops(&dma_syscore_ops); return 0; } -late_initcall(s3c24xx_dma_sysdev_register); +late_initcall(s3c24xx_dma_syscore_init); int __init s3c24xx_dma_init(unsigned int channels, unsigned int irq, unsigned int stride) diff --git a/arch/arm/plat-s3c24xx/irq-pm.c b/arch/arm/plat-s3c24xx/irq-pm.c index c3624d898630..0efb2e2848c8 100644 --- a/arch/arm/plat-s3c24xx/irq-pm.c +++ b/arch/arm/plat-s3c24xx/irq-pm.c @@ -14,7 +14,6 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/interrupt.h> -#include <linux/sysdev.h> #include <linux/irq.h> #include <plat/cpu.h> @@ -65,7 +64,7 @@ static unsigned long save_extint[3]; static unsigned long save_eintflt[4]; static unsigned long save_eintmask; -int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state) +int s3c24xx_irq_suspend(void) { unsigned int i; @@ -81,7 +80,7 @@ int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state) return 0; } -int s3c24xx_irq_resume(struct sys_device *dev) +void s3c24xx_irq_resume(void) { unsigned int i; @@ -93,6 +92,4 @@ int s3c24xx_irq_resume(struct sys_device *dev) s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); __raw_writel(save_eintmask, S3C24XX_EINTMASK); - - return 0; } diff --git a/arch/arm/plat-s5p/irq-pm.c b/arch/arm/plat-s5p/irq-pm.c index 5259ad458bc8..327acb3a4464 100644 --- a/arch/arm/plat-s5p/irq-pm.c +++ b/arch/arm/plat-s5p/irq-pm.c @@ -16,7 +16,6 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/interrupt.h> -#include <linux/sysdev.h> #include <plat/cpu.h> #include <plat/irqs.h> @@ -77,17 +76,15 @@ static struct sleep_save eint_save[] = { SAVE_ITEM(S5P_EINT_MASK(3)), }; -int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state) +int s3c24xx_irq_suspend(void) { s3c_pm_do_save(eint_save, ARRAY_SIZE(eint_save)); return 0; } -int s3c24xx_irq_resume(struct sys_device *dev) +void s3c24xx_irq_resume(void) { s3c_pm_do_restore(eint_save, ARRAY_SIZE(eint_save)); - - return 0; } diff --git a/arch/arm/plat-s5p/s5p-time.c b/arch/arm/plat-s5p/s5p-time.c index 8090403eec0f..899a8cc011ff 100644 --- a/arch/arm/plat-s5p/s5p-time.c +++ b/arch/arm/plat-s5p/s5p-time.c @@ -290,7 +290,7 @@ static void __init s5p_clockevent_init(void) setup_irq(irq_number, &s5p_clock_event_irq); } -static cycle_t s5p_timer_read(struct clocksource *cs) +static void __iomem *s5p_timer_reg(void) { unsigned long offset = 0; @@ -308,10 +308,17 @@ static cycle_t s5p_timer_read(struct clocksource *cs) default: printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id); - return 0; + return NULL; } - return (cycle_t) ~__raw_readl(S3C_TIMERREG(offset)); + return S3C_TIMERREG(offset); +} + +static cycle_t s5p_timer_read(struct clocksource *cs) +{ + void __iomem *reg = s5p_timer_reg(); + + return (cycle_t) (reg ? ~__raw_readl(reg) : 0); } /* @@ -325,53 +332,22 @@ static DEFINE_CLOCK_DATA(cd); unsigned long long notrace sched_clock(void) { - u32 cyc; - unsigned long offset = 0; - - switch (timer_source.source_id) { - case S5P_PWM0: - case S5P_PWM1: - case S5P_PWM2: - case S5P_PWM3: - offset = (timer_source.source_id * 0x0c) + 0x14; - break; - - case S5P_PWM4: - offset = 0x40; - break; + void __iomem *reg = s5p_timer_reg(); - default: - printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id); + if (!reg) return 0; - } - cyc = ~__raw_readl(S3C_TIMERREG(offset)); - return cyc_to_sched_clock(&cd, cyc, (u32)~0); + return cyc_to_sched_clock(&cd, ~__raw_readl(reg), (u32)~0); } static void notrace s5p_update_sched_clock(void) { - u32 cyc; - unsigned long offset = 0; + void __iomem *reg = s5p_timer_reg(); - switch (timer_source.source_id) { - case S5P_PWM0: - case S5P_PWM1: - case S5P_PWM2: - case S5P_PWM3: - offset = (timer_source.source_id * 0x0c) + 0x14; - break; - - case S5P_PWM4: - offset = 0x40; - break; - - default: - printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id); - } + if (!reg) + return; - cyc = ~__raw_readl(S3C_TIMERREG(offset)); - update_sched_clock(&cd, cyc, (u32)~0); + update_sched_clock(&cd, ~__raw_readl(reg), (u32)~0); } struct clocksource time_clocksource = { diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index cedfff51c82b..3aedac0034ba 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -68,6 +68,12 @@ extern void s3c24xx_init_uartdevs(char *name, struct sys_timer; extern struct sys_timer s3c24xx_timer; +extern struct syscore_ops s3c2410_pm_syscore_ops; +extern struct syscore_ops s3c2412_pm_syscore_ops; +extern struct syscore_ops s3c2416_pm_syscore_ops; +extern struct syscore_ops s3c244x_pm_syscore_ops; +extern struct syscore_ops s3c64xx_irq_syscore_ops; + /* system device classes */ extern struct sysdev_class s3c2410_sysclass; diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h index 937cc2ace517..7fb6f6be8c81 100644 --- a/arch/arm/plat-samsung/include/plat/pm.h +++ b/arch/arm/plat-samsung/include/plat/pm.h @@ -103,14 +103,16 @@ extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count); #ifdef CONFIG_PM extern int s3c_irqext_wake(struct irq_data *data, unsigned int state); -extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state); -extern int s3c24xx_irq_resume(struct sys_device *dev); +extern int s3c24xx_irq_suspend(void); +extern void s3c24xx_irq_resume(void); #else #define s3c_irqext_wake NULL #define s3c24xx_irq_suspend NULL #define s3c24xx_irq_resume NULL #endif +extern struct syscore_ops s3c24xx_irq_syscore_ops; + /* PM debug functions */ #ifdef CONFIG_SAMSUNG_PM_DEBUG diff --git a/arch/arm/plat-spear/time.c b/arch/arm/plat-spear/time.c index dbb6e4fff79d..0c77e4298675 100644 --- a/arch/arm/plat-spear/time.c +++ b/arch/arm/plat-spear/time.c @@ -70,19 +70,6 @@ static void clockevent_set_mode(enum clock_event_mode mode, static int clockevent_next_event(unsigned long evt, struct clock_event_device *clk_event_dev); -static cycle_t clocksource_read_cycles(struct clocksource *cs) -{ - return (cycle_t) readw(gpt_base + COUNT(CLKSRC)); -} - -static struct clocksource clksrc = { - .name = "tmr1", - .rating = 200, /* its a pretty decent clock */ - .read = clocksource_read_cycles, - .mask = 0xFFFF, /* 16 bits */ - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - static void spear_clocksource_init(void) { u32 tick_rate; @@ -103,7 +90,8 @@ static void spear_clocksource_init(void) writew(val, gpt_base + CR(CLKSRC)); /* register the clocksource */ - clocksource_register_hz(&clksrc, tick_rate); + clocksource_mmio_init(gpt_base + COUNT(CLKSRC), "tmr1", tick_rate, + 200, 16, clocksource_mmio_readw_up); } static struct clock_event_device clkevt = { diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c index ba3d471d4bcf..51ecfea09b27 100644 --- a/arch/arm/plat-versatile/platsmp.c +++ b/arch/arm/plat-versatile/platsmp.c @@ -16,6 +16,7 @@ #include <linux/smp.h> #include <asm/cacheflush.h> +#include <asm/hardware/gic.h> /* * control for which core is the next to come out of the secondary @@ -83,7 +84,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) * the boot monitor to read the system wide flags register, * and branch to the address found there. */ - smp_cross_call(cpumask_of(cpu), 1); + gic_raise_softirq(cpumask_of(cpu), 1); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index f74695075e64..f25e7ec89416 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -398,9 +398,9 @@ static void vfp_enable(void *unused) } #ifdef CONFIG_PM -#include <linux/sysdev.h> +#include <linux/syscore_ops.h> -static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state) +static int vfp_pm_suspend(void) { struct thread_info *ti = current_thread_info(); u32 fpexc = fmrx(FPEXC); @@ -420,34 +420,25 @@ static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state) return 0; } -static int vfp_pm_resume(struct sys_device *dev) +static void vfp_pm_resume(void) { /* ensure we have access to the vfp */ vfp_enable(NULL); /* and disable it to ensure the next usage restores the state */ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); - - return 0; } -static struct sysdev_class vfp_pm_sysclass = { - .name = "vfp", +static struct syscore_ops vfp_pm_syscore_ops = { .suspend = vfp_pm_suspend, .resume = vfp_pm_resume, }; -static struct sys_device vfp_pm_sysdev = { - .cls = &vfp_pm_sysclass, -}; - static void vfp_pm_init(void) { - sysdev_class_register(&vfp_pm_sysclass); - sysdev_register(&vfp_pm_sysdev); + register_syscore_ops(&vfp_pm_syscore_ops); } - #else static inline void vfp_pm_init(void) { } #endif /* CONFIG_PM */ |