Merge branch 'misc' into devel
authorRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 6 Jan 2011 22:32:52 +0000 (22:32 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 6 Jan 2011 22:32:52 +0000 (22:32 +0000)
Conflicts:
arch/arm/Kconfig
arch/arm/common/Makefile
arch/arm/kernel/Makefile
arch/arm/kernel/smp.c

147 files changed:
Documentation/arm/00-INDEX
Documentation/arm/swp_emulation [new file with mode: 0644]
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/common/Kconfig
arch/arm/common/dmabounce.c
arch/arm/include/asm/assembler.h
arch/arm/include/asm/cache.h
arch/arm/include/asm/clkdev.h
arch/arm/include/asm/dma-mapping.h
arch/arm/include/asm/domain.h
arch/arm/include/asm/entry-macro-multi.S [new file with mode: 0644]
arch/arm/include/asm/futex.h
arch/arm/include/asm/hardirq.h
arch/arm/include/asm/localtimer.h
arch/arm/include/asm/mach/arch.h
arch/arm/include/asm/mach/irq.h
arch/arm/include/asm/mach/time.h
arch/arm/include/asm/smp.h
arch/arm/include/asm/smp_mpidr.h [deleted file]
arch/arm/include/asm/smp_twd.h
arch/arm/include/asm/system.h
arch/arm/include/asm/traps.h
arch/arm/include/asm/uaccess.h
arch/arm/kernel/Makefile
arch/arm/kernel/entry-armv.S
arch/arm/kernel/fiq.c
arch/arm/kernel/head.S
arch/arm/kernel/irq.c
arch/arm/kernel/setup.c
arch/arm/kernel/smp.c
arch/arm/kernel/smp_tlb.c [new file with mode: 0644]
arch/arm/kernel/smp_twd.c
arch/arm/kernel/swp_emulate.c [new file with mode: 0644]
arch/arm/kernel/time.c
arch/arm/kernel/traps.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/lib/getuser.S
arch/arm/lib/putuser.S
arch/arm/lib/uaccess.S
arch/arm/mach-bcmring/clock.c
arch/arm/mach-bcmring/core.c
arch/arm/mach-cns3xxx/Kconfig
arch/arm/mach-davinci/clock.h
arch/arm/mach-ep93xx/clock.c
arch/arm/mach-imx/clock-imx1.c
arch/arm/mach-imx/clock-imx21.c
arch/arm/mach-imx/clock-imx27.c
arch/arm/mach-integrator/Kconfig
arch/arm/mach-integrator/core.c
arch/arm/mach-integrator/impd1.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-iop13xx/include/mach/memory.h
arch/arm/mach-ks8695/Kconfig
arch/arm/mach-ks8695/include/mach/memory.h
arch/arm/mach-lpc32xx/clock.c
arch/arm/mach-mmp/clock.h
arch/arm/mach-msm/include/mach/smp.h
arch/arm/mach-mx25/clock.c
arch/arm/mach-mx3/clock-imx31.c
arch/arm/mach-mx3/clock-imx35.c
arch/arm/mach-mx5/clock-mx51.c
arch/arm/mach-mxc91231/clock.c
arch/arm/mach-nomadik/clock.c
arch/arm/mach-nuc93x/clock.h
arch/arm/mach-omap1/clock.c
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/omap-hotplug.c
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-pnx4008/clock.c
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/clock.c
arch/arm/mach-pxa/clock.h
arch/arm/mach-realview/core.c
arch/arm/mach-realview/hotplug.c
arch/arm/mach-realview/include/mach/smp.h
arch/arm/mach-realview/platsmp.c
arch/arm/mach-s3c2412/Kconfig
arch/arm/mach-s5pv310/hotplug.c
arch/arm/mach-s5pv310/include/mach/smp.h
arch/arm/mach-s5pv310/platsmp.c
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-shmobile/clock-sh7367.c
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/clock-sh7377.c
arch/arm/mach-tcc8k/clock.c
arch/arm/mach-tegra/clock.c
arch/arm/mach-tegra/clock.h
arch/arm/mach-tegra/hotplug.c
arch/arm/mach-tegra/include/mach/smp.h
arch/arm/mach-tegra/platsmp.c
arch/arm/mach-tegra/tegra2_clocks.c
arch/arm/mach-u300/clock.c
arch/arm/mach-ux500/clock.c
arch/arm/mach-ux500/headsmp.S
arch/arm/mach-ux500/hotplug.c
arch/arm/mach-ux500/include/mach/smp.h
arch/arm/mach-ux500/platsmp.c
arch/arm/mach-versatile/Kconfig
arch/arm/mach-versatile/core.c
arch/arm/mach-vexpress/Makefile
arch/arm/mach-vexpress/ct-ca9x4.c
arch/arm/mach-vexpress/hotplug.c [new file with mode: 0644]
arch/arm/mach-vexpress/include/mach/smp.h
arch/arm/mach-vexpress/platsmp.c
arch/arm/mach-vexpress/v2m.c
arch/arm/mach-w90x900/clock.h
arch/arm/mm/Kconfig
arch/arm/mm/dma-mapping.c
arch/arm/mm/ioremap.c
arch/arm/mm/mmu.c
arch/arm/mm/proc-macros.S
arch/arm/mm/proc-v7.S
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/include/plat/clkdev_omap.h
arch/arm/plat-omap/include/plat/memory.h
arch/arm/plat-omap/include/plat/smp.h
arch/arm/plat-spear/include/plat/clock.h
arch/arm/plat-stmp3xxx/clock.c
arch/arm/vfp/vfpmodule.c
arch/sh/Kconfig
arch/sh/boards/mach-highlander/setup.c
arch/sh/include/asm/clkdev.h
arch/sh/kernel/Makefile
arch/sh/kernel/clkdev.c [deleted file]
arch/sh/kernel/cpu/clock-cpg.c
arch/sh/kernel/cpu/clock.c
arch/sh/kernel/cpu/sh4/clock-sh4-202.c
arch/sh/kernel/cpu/sh4a/clock-sh7343.c
arch/sh/kernel/cpu/sh4a/clock-sh7366.c
arch/sh/kernel/cpu/sh4a/clock-sh7722.c
arch/sh/kernel/cpu/sh4a/clock-sh7723.c
arch/sh/kernel/cpu/sh4a/clock-sh7724.c
arch/sh/kernel/cpu/sh4a/clock-sh7757.c
arch/sh/kernel/cpu/sh4a/clock-sh7763.c
arch/sh/kernel/cpu/sh4a/clock-sh7780.c
arch/sh/kernel/cpu/sh4a/clock-sh7785.c
arch/sh/kernel/cpu/sh4a/clock-sh7786.c
arch/sh/kernel/cpu/sh4a/clock-shx3.c
drivers/Kconfig
drivers/Makefile
drivers/amba/bus.c
drivers/clk/Kconfig [new file with mode: 0644]
drivers/clk/Makefile [new file with mode: 0644]
drivers/clk/clkdev.c [moved from arch/arm/common/clkdev.c with 93% similarity]
include/linux/amba/bus.h
include/linux/clkdev.h [new file with mode: 0644]

index ecf7d04..91c24a1 100644 (file)
@@ -34,3 +34,5 @@ memory.txt
        - description of the virtual memory layout
 nwfpe/
        - NWFPE floating point emulator documentation
+swp_emulation
+       - SWP/SWPB emulation handler/logging description
diff --git a/Documentation/arm/swp_emulation b/Documentation/arm/swp_emulation
new file mode 100644 (file)
index 0000000..af903d2
--- /dev/null
@@ -0,0 +1,27 @@
+Software emulation of deprecated SWP instruction (CONFIG_SWP_EMULATE)
+---------------------------------------------------------------------
+
+ARMv6 architecture deprecates use of the SWP/SWPB instructions, and recommeds
+moving to the load-locked/store-conditional instructions LDREX and STREX.
+
+ARMv7 multiprocessing extensions introduce the ability to disable these
+instructions, triggering an undefined instruction exception when executed.
+Trapped instructions are emulated using an LDREX/STREX or LDREXB/STREXB
+sequence. If a memory access fault (an abort) occurs, a segmentation fault is
+signalled to the triggering process.
+
+/proc/cpu/swp_emulation holds some statistics/information, including the PID of
+the last process to trigger the emulation to be invocated. For example:
+---
+Emulated SWP:          12
+Emulated SWPB:         0
+Aborted SWP{B}:                1
+Last process:          314
+---
+
+NOTE: when accessing uncached shared regions, LDREX/STREX rely on an external
+transaction monitoring block called a global monitor to maintain update
+atomicity. If your system does not implement a global monitor, this option can
+cause programs that perform SWP operations to uncached memory to deadlock, as
+the STREX operation will always fail.
+
index 2e86b8f..32cbf3e 100644 (file)
@@ -2,6 +2,7 @@ config ARM
        bool
        default y
        select HAVE_AOUT
+       select HAVE_DMA_API_DEBUG
        select HAVE_IDE
        select HAVE_MEMBLOCK
        select RTC_LIB
@@ -36,6 +37,9 @@ config ARM
 config HAVE_PWM
        bool
 
+config MIGHT_HAVE_PCI
+       bool
+
 config SYS_SUPPORTS_APM_EMULATION
        bool
 
@@ -226,7 +230,7 @@ config ARCH_INTEGRATOR
        bool "ARM Ltd. Integrator family"
        select ARM_AMBA
        select ARCH_HAS_CPUFREQ
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select ICST
        select GENERIC_CLOCKEVENTS
        select PLAT_VERSATILE
@@ -236,7 +240,7 @@ config ARCH_INTEGRATOR
 config ARCH_REALVIEW
        bool "ARM Ltd. RealView family"
        select ARM_AMBA
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select HAVE_SCHED_CLOCK
        select ICST
        select GENERIC_CLOCKEVENTS
@@ -251,7 +255,7 @@ config ARCH_VERSATILE
        bool "ARM Ltd. Versatile family"
        select ARM_AMBA
        select ARM_VIC
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select HAVE_SCHED_CLOCK
        select ICST
        select GENERIC_CLOCKEVENTS
@@ -266,7 +270,7 @@ config ARCH_VEXPRESS
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select ARM_AMBA
        select ARM_TIMER_SP804
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select HAVE_CLK
        select HAVE_SCHED_CLOCK
@@ -288,7 +292,7 @@ config ARCH_BCMRING
        depends on MMU
        select CPU_V6
        select ARM_AMBA
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select ARCH_WANT_OPTIONAL_GPIOLIB
        help
@@ -306,6 +310,7 @@ config ARCH_CNS3XXX
        select CPU_V6
        select GENERIC_CLOCKEVENTS
        select ARM_GIC
+       select MIGHT_HAVE_PCI
        select PCI_DOMAINS if PCI
        help
          Support for Cavium Networks CNS3XXX platform.
@@ -335,7 +340,7 @@ config ARCH_EP93XX
        select CPU_ARM920T
        select ARM_AMBA
        select ARM_VIC
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select ARCH_REQUIRE_GPIOLIB
        select ARCH_HAS_HOLES_MEMORYMODEL
        select ARCH_USES_GETTIMEOFFSET
@@ -355,14 +360,14 @@ config ARCH_MXC
        bool "Freescale MXC/iMX-based"
        select GENERIC_CLOCKEVENTS
        select ARCH_REQUIRE_GPIOLIB
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        help
          Support for Freescale MXC/iMX-based family of processors
 
 config ARCH_STMP3XXX
        bool "Freescale STMP3xxx"
        select CPU_ARM926T
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
        select USB_ARCH_HAS_EHCI
@@ -442,6 +447,7 @@ config ARCH_IXP4XX
        select GENERIC_GPIO
        select GENERIC_CLOCKEVENTS
        select HAVE_SCHED_CLOCK
+       select MIGHT_HAVE_PCI
        select DMABOUNCE if PCI
        help
          Support for Intel's IXP4XX (XScale) family of processors.
@@ -481,7 +487,7 @@ config ARCH_LPC32XX
        select HAVE_IDE
        select ARM_AMBA
        select USB_ARCH_HAS_OHCI
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        help
@@ -515,7 +521,7 @@ config ARCH_MMP
        bool "Marvell PXA168/910/MMP2"
        depends on MMU
        select ARCH_REQUIRE_GPIOLIB
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select HAVE_SCHED_CLOCK
        select TICK_ONESHOT
@@ -549,7 +555,7 @@ config ARCH_W90X900
        bool "Nuvoton W90X900 CPU"
        select CPU_ARM926T
        select ARCH_REQUIRE_GPIOLIB
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        help
          Support for Nuvoton (Winbond logic dept.) ARM9 processor,
@@ -563,19 +569,19 @@ config ARCH_W90X900
 config ARCH_NUC93X
        bool "Nuvoton NUC93X CPU"
        select CPU_ARM926T
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        help
          Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a
          low-power and high performance MPEG-4/JPEG multimedia controller chip.
 
 config ARCH_TEGRA
        bool "NVIDIA Tegra"
+       select CLKDEV_LOOKUP
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        select GENERIC_GPIO
        select HAVE_CLK
        select HAVE_SCHED_CLOCK
-       select COMMON_CLKDEV
        select ARCH_HAS_BARRIERS if CACHE_L2X0
        select ARCH_HAS_CPUFREQ
        help
@@ -585,7 +591,7 @@ config ARCH_TEGRA
 config ARCH_PNX4008
        bool "Philips Nexperia PNX4008 Mobile"
        select CPU_ARM926T
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select ARCH_USES_GETTIMEOFFSET
        help
          This enables support for Philips PNX4008 mobile platform.
@@ -595,7 +601,7 @@ config ARCH_PXA
        depends on MMU
        select ARCH_MTD_XIP
        select ARCH_HAS_CPUFREQ
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
        select HAVE_SCHED_CLOCK
@@ -774,7 +780,7 @@ config ARCH_TCC_926
        bool "Telechips TCC ARM926-based systems"
        select CPU_ARM926T
        select HAVE_CLK
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        help
          Support for Telechips TCC ARM926-based systems.
@@ -799,7 +805,7 @@ config ARCH_U300
        select ARM_AMBA
        select ARM_VIC
        select GENERIC_CLOCKEVENTS
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_GPIO
        help
          Support for ST-Ericsson U300 series mobile platforms.
@@ -809,7 +815,7 @@ config ARCH_U8500
        select CPU_V7
        select ARM_AMBA
        select GENERIC_CLOCKEVENTS
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select ARCH_REQUIRE_GPIOLIB
        help
          Support for ST-Ericsson's Ux500 architecture
@@ -819,7 +825,7 @@ config ARCH_NOMADIK
        select ARM_AMBA
        select ARM_VIC
        select CPU_ARM926T
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select ARCH_REQUIRE_GPIOLIB
        help
@@ -831,7 +837,7 @@ config ARCH_DAVINCI
        select ARCH_REQUIRE_GPIOLIB
        select ZONE_DMA
        select HAVE_IDE
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_ALLOCATOR
        select ARCH_HAS_HOLES_MEMORYMODEL
        help
@@ -852,7 +858,7 @@ config PLAT_SPEAR
        bool "ST SPEAr"
        select ARM_AMBA
        select ARCH_REQUIRE_GPIOLIB
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select HAVE_CLK
        help
@@ -1034,6 +1040,11 @@ config CPU_HAS_PMU
        default y
        bool
 
+config MULTI_IRQ_HANDLER
+       bool
+       help
+         Allow each machine to specify it's own IRQ handler at run time.
+
 if !MMU
 source "arch/arm/Kconfig-nommu"
 endif
@@ -1181,7 +1192,7 @@ config ISA_DMA_API
        bool
 
 config PCI
-       bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX || SA1100_NANOENGINE
+       bool "PCI support" if MIGHT_HAVE_PCI
        help
          Find out whether you have a PCI motherboard. PCI is the name of a
          bus system, i.e. the way the CPU talks to the other stuff inside
@@ -1253,7 +1264,7 @@ config SMP
 config SMP_ON_UP
        bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)"
        depends on EXPERIMENTAL
-       depends on SMP && !XIP && !THUMB2_KERNEL
+       depends on SMP && !XIP
        default y
        help
          SMP kernels contain instructions which fail on non-SMP processors.
@@ -1272,6 +1283,7 @@ config HAVE_ARM_SCU
 config HAVE_ARM_TWD
        bool
        depends on SMP
+       select TICK_ONESHOT
        help
          This options enables support for the ARM timer and watchdog unit
 
@@ -1335,7 +1347,7 @@ config HZ
        default 100
 
 config THUMB2_KERNEL
-       bool "Compile the kernel in Thumb-2 mode"
+       bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)"
        depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL
        select AEABI
        select ARM_ASM_UNIFIED
@@ -1549,6 +1561,7 @@ config SECCOMP
 
 config CC_STACKPROTECTOR
        bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
        help
          This option turns on the -fstack-protector GCC feature. This
          feature puts, at the beginning of functions, a canary value on
@@ -1745,7 +1758,7 @@ config CPU_FREQ_S3C
          Internal configuration node for common cpufreq on Samsung SoC
 
 config CPU_FREQ_S3C24XX
-       bool "CPUfreq driver for Samsung S3C24XX series CPUs"
+       bool "CPUfreq driver for Samsung S3C24XX series CPUs (EXPERIMENTAL)"
        depends on ARCH_S3C2410 && CPU_FREQ && EXPERIMENTAL
        select CPU_FREQ_S3C
        help
@@ -1757,7 +1770,7 @@ config CPU_FREQ_S3C24XX
          If in doubt, say N.
 
 config CPU_FREQ_S3C24XX_PLL
-       bool "Support CPUfreq changing of PLL frequency"
+       bool "Support CPUfreq changing of PLL frequency (EXPERIMENTAL)"
        depends on CPU_FREQ_S3C24XX && EXPERIMENTAL
        help
          Compile in support for changing the PLL frequency from the
index eac6208..494224a 100644 (file)
@@ -31,7 +31,7 @@ config FRAME_POINTER
          reported is severely limited.
 
 config ARM_UNWIND
-       bool "Enable stack unwinding support"
+       bool "Enable stack unwinding support (EXPERIMENTAL)"
        depends on AEABI && EXPERIMENTAL
        default y
        help
index 0a34c81..778655f 100644 (file)
@@ -37,7 +37,3 @@ config SHARP_PARAM
 
 config SHARP_SCOOP
        bool
-
-config COMMON_CLKDEV
-       bool
-       select HAVE_CLK
index cc0a932..e568163 100644 (file)
@@ -328,7 +328,7 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,
  * substitute the safe buffer for the unsafe one.
  * (basically move the buffer from an unsafe area to a safe one)
  */
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+dma_addr_t __dma_map_single(struct device *dev, void *ptr, size_t size,
                enum dma_data_direction dir)
 {
        dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
@@ -338,7 +338,7 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 
        return map_single(dev, ptr, size, dir);
 }
-EXPORT_SYMBOL(dma_map_single);
+EXPORT_SYMBOL(__dma_map_single);
 
 /*
  * see if a mapped address was really a "safe" buffer and if so, copy
@@ -346,7 +346,7 @@ EXPORT_SYMBOL(dma_map_single);
  * the safe buffer.  (basically return things back to the way they
  * should be)
  */
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+void __dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
                enum dma_data_direction dir)
 {
        dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
@@ -354,9 +354,9 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 
        unmap_single(dev, dma_addr, size, dir);
 }
-EXPORT_SYMBOL(dma_unmap_single);
+EXPORT_SYMBOL(__dma_unmap_single);
 
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
+dma_addr_t __dma_map_page(struct device *dev, struct page *page,
                unsigned long offset, size_t size, enum dma_data_direction dir)
 {
        dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n",
@@ -372,7 +372,7 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page,
 
        return map_single(dev, page_address(page) + offset, size, dir);
 }
-EXPORT_SYMBOL(dma_map_page);
+EXPORT_SYMBOL(__dma_map_page);
 
 /*
  * see if a mapped address was really a "safe" buffer and if so, copy
@@ -380,7 +380,7 @@ EXPORT_SYMBOL(dma_map_page);
  * the safe buffer.  (basically return things back to the way they
  * should be)
  */
-void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
+void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
                enum dma_data_direction dir)
 {
        dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
@@ -388,7 +388,7 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
 
        unmap_single(dev, dma_addr, size, dir);
 }
-EXPORT_SYMBOL(dma_unmap_page);
+EXPORT_SYMBOL(__dma_unmap_page);
 
 int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
                unsigned long off, size_t sz, enum dma_data_direction dir)
index 749bb66..bc2d2d7 100644 (file)
@@ -18,6 +18,7 @@
 #endif
 
 #include <asm/ptrace.h>
+#include <asm/domain.h>
 
 /*
  * Endian independent macros for shifting bytes within registers.
 #ifdef CONFIG_SMP
 #define ALT_SMP(instr...)                                      \
 9998:  instr
+/*
+ * Note: if you get assembler errors from ALT_UP() when building with
+ * CONFIG_THUMB2_KERNEL, you almost certainly need to use
+ * ALT_SMP( W(instr) ... )
+ */
 #define ALT_UP(instr...)                                       \
        .pushsection ".alt.smp.init", "a"                       ;\
        .long   9998b                                           ;\
-       instr                                                   ;\
+9997:  instr                                                   ;\
+       .if . - 9997b != 4                                      ;\
+               .error "ALT_UP() content must assemble to exactly 4 bytes";\
+       .endif                                                  ;\
        .popsection
 #define ALT_UP_B(label)                                        \
        .equ    up_b_offset, label - 9998b                      ;\
        .pushsection ".alt.smp.init", "a"                       ;\
        .long   9998b                                           ;\
-       b       . + up_b_offset                                 ;\
+       W(b)    . + up_b_offset                                 ;\
        .popsection
 #else
 #define ALT_SMP(instr...)
 /*
  * SMP data memory barrier
  */
-       .macro  smp_dmb
+       .macro  smp_dmb mode
 #ifdef CONFIG_SMP
 #if __LINUX_ARM_ARCH__ >= 7
+       .ifeqs "\mode","arm"
        ALT_SMP(dmb)
+       .else
+       ALT_SMP(W(dmb))
+       .endif
 #elif __LINUX_ARM_ARCH__ == 6
        ALT_SMP(mcr     p15, 0, r0, c7, c10, 5) @ dmb
 #else
 #error Incompatible SMP platform
 #endif
+       .ifeqs "\mode","arm"
        ALT_UP(nop)
+       .else
+       ALT_UP(W(nop))
+       .endif
 #endif
        .endm
 
  */
 #ifdef CONFIG_THUMB2_KERNEL
 
-       .macro  usraccoff, instr, reg, ptr, inc, off, cond, abort
+       .macro  usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T()
 9999:
        .if     \inc == 1
-       \instr\cond\()bt \reg, [\ptr, #\off]
+       \instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
        .elseif \inc == 4
-       \instr\cond\()t \reg, [\ptr, #\off]
+       \instr\cond\()\t\().w \reg, [\ptr, #\off]
        .else
        .error  "Unsupported inc macro argument"
        .endif
 
 #else  /* !CONFIG_THUMB2_KERNEL */
 
-       .macro  usracc, instr, reg, ptr, inc, cond, rept, abort
+       .macro  usracc, instr, reg, ptr, inc, cond, rept, abort, t=T()
        .rept   \rept
 9999:
        .if     \inc == 1
-       \instr\cond\()bt \reg, [\ptr], #\inc
+       \instr\cond\()b\()\t \reg, [\ptr], #\inc
        .elseif \inc == 4
-       \instr\cond\()t \reg, [\ptr], #\inc
+       \instr\cond\()\t \reg, [\ptr], #\inc
        .else
        .error  "Unsupported inc macro argument"
        .endif
index 9d61220..75fe66b 100644 (file)
@@ -23,4 +23,6 @@
 #define ARCH_SLAB_MINALIGN 8
 #endif
 
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
+
 #endif
index b56c138..765d332 100644 (file)
 #ifndef __ASM_CLKDEV_H
 #define __ASM_CLKDEV_H
 
-struct clk;
-struct device;
+#include <linux/slab.h>
 
-struct clk_lookup {
-       struct list_head        node;
-       const char              *dev_id;
-       const char              *con_id;
-       struct clk              *clk;
-};
+#include <mach/clkdev.h>
 
-struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
-       const char *dev_fmt, ...);
-
-void clkdev_add(struct clk_lookup *cl);
-void clkdev_drop(struct clk_lookup *cl);
-
-void clkdev_add_table(struct clk_lookup *, size_t);
-int clk_add_alias(const char *, const char *, char *, struct device *);
+static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
+{
+       return kzalloc(size, GFP_KERNEL);
+}
 
 #endif
index c568da7..4fff837 100644 (file)
@@ -5,24 +5,29 @@
 
 #include <linux/mm_types.h>
 #include <linux/scatterlist.h>
+#include <linux/dma-debug.h>
 
 #include <asm-generic/dma-coherent.h>
 #include <asm/memory.h>
 
+#ifdef __arch_page_to_dma
+#error Please update to __arch_pfn_to_dma
+#endif
+
 /*
- * page_to_dma/dma_to_virt/virt_to_dma are architecture private functions
- * used internally by the DMA-mapping API to provide DMA addresses. They
- * must not be used by drivers.
+ * dma_to_pfn/pfn_to_dma/dma_to_virt/virt_to_dma are architecture private
+ * functions used internally by the DMA-mapping API to provide DMA
+ * addresses. They must not be used by drivers.
  */
-#ifndef __arch_page_to_dma
-static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
+#ifndef __arch_pfn_to_dma
+static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
 {
-       return (dma_addr_t)__pfn_to_bus(page_to_pfn(page));
+       return (dma_addr_t)__pfn_to_bus(pfn);
 }
 
-static inline struct page *dma_to_page(struct device *dev, dma_addr_t addr)
+static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
 {
-       return pfn_to_page(__bus_to_pfn(addr));
+       return __bus_to_pfn(addr);
 }
 
 static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
@@ -35,14 +40,14 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
        return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
 }
 #else
-static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
+static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
 {
-       return __arch_page_to_dma(dev, page);
+       return __arch_pfn_to_dma(dev, pfn);
 }
 
-static inline struct page *dma_to_page(struct device *dev, dma_addr_t addr)
+static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
 {
-       return __arch_dma_to_page(dev, addr);
+       return __arch_dma_to_pfn(dev, addr);
 }
 
 static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
@@ -293,13 +298,13 @@ extern int dma_needs_bounce(struct device*, dma_addr_t, size_t);
 /*
  * The DMA API, implemented by dmabounce.c.  See below for descriptions.
  */
-extern dma_addr_t dma_map_single(struct device *, void *, size_t,
+extern dma_addr_t __dma_map_single(struct device *, void *, size_t,
                enum dma_data_direction);
-extern void dma_unmap_single(struct device *, dma_addr_t, size_t,
+extern void __dma_unmap_single(struct device *, dma_addr_t, size_t,
                enum dma_data_direction);
-extern dma_addr_t dma_map_page(struct device *, struct page *,
+extern dma_addr_t __dma_map_page(struct device *, struct page *,
                unsigned long, size_t, enum dma_data_direction);
-extern void dma_unmap_page(struct device *, dma_addr_t, size_t,
+extern void __dma_unmap_page(struct device *, dma_addr_t, size_t,
                enum dma_data_direction);
 
 /*
@@ -323,6 +328,34 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
 }
 
 
+static inline dma_addr_t __dma_map_single(struct device *dev, void *cpu_addr,
+               size_t size, enum dma_data_direction dir)
+{
+       __dma_single_cpu_to_dev(cpu_addr, size, dir);
+       return virt_to_dma(dev, cpu_addr);
+}
+
+static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
+            unsigned long offset, size_t size, enum dma_data_direction dir)
+{
+       __dma_page_cpu_to_dev(page, offset, size, dir);
+       return pfn_to_dma(dev, page_to_pfn(page)) + offset;
+}
+
+static inline void __dma_unmap_single(struct device *dev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir)
+{
+       __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
+}
+
+static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir)
+{
+       __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
+               handle & ~PAGE_MASK, size, dir);
+}
+#endif /* CONFIG_DMABOUNCE */
+
 /**
  * dma_map_single - map a single buffer for streaming DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@ -340,11 +373,16 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
 static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
                size_t size, enum dma_data_direction dir)
 {
+       dma_addr_t addr;
+
        BUG_ON(!valid_dma_direction(dir));
 
-       __dma_single_cpu_to_dev(cpu_addr, size, dir);
+       addr = __dma_map_single(dev, cpu_addr, size, dir);
+       debug_dma_map_page(dev, virt_to_page(cpu_addr),
+                       (unsigned long)cpu_addr & ~PAGE_MASK, size,
+                       dir, addr, true);
 
-       return virt_to_dma(dev, cpu_addr);
+       return addr;
 }
 
 /**
@@ -364,11 +402,14 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
 static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
             unsigned long offset, size_t size, enum dma_data_direction dir)
 {
+       dma_addr_t addr;
+
        BUG_ON(!valid_dma_direction(dir));
 
-       __dma_page_cpu_to_dev(page, offset, size, dir);
+       addr = __dma_map_page(dev, page, offset, size, dir);
+       debug_dma_map_page(dev, page, offset, size, dir, addr, false);
 
-       return page_to_dma(dev, page) + offset;
+       return addr;
 }
 
 /**
@@ -388,7 +429,8 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
 static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir)
 {
-       __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
+       debug_dma_unmap_page(dev, handle, size, dir, true);
+       __dma_unmap_single(dev, handle, size, dir);
 }
 
 /**
@@ -408,10 +450,9 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
 static inline void dma_unmap_page(struct device *dev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir)
 {
-       __dma_page_dev_to_cpu(dma_to_page(dev, handle), handle & ~PAGE_MASK,
-               size, dir);
+       debug_dma_unmap_page(dev, handle, size, dir, false);
+       __dma_unmap_page(dev, handle, size, dir);
 }
-#endif /* CONFIG_DMABOUNCE */
 
 /**
  * dma_sync_single_range_for_cpu
@@ -437,6 +478,8 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev,
 {
        BUG_ON(!valid_dma_direction(dir));
 
+       debug_dma_sync_single_for_cpu(dev, handle + offset, size, dir);
+
        if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir))
                return;
 
@@ -449,6 +492,8 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
 {
        BUG_ON(!valid_dma_direction(dir));
 
+       debug_dma_sync_single_for_device(dev, handle + offset, size, dir);
+
        if (!dmabounce_sync_for_device(dev, handle, offset, size, dir))
                return;
 
index cc7ef40..af18cea 100644 (file)
  */
 #define DOMAIN_NOACCESS        0
 #define DOMAIN_CLIENT  1
+#ifdef CONFIG_CPU_USE_DOMAINS
 #define DOMAIN_MANAGER 3
+#else
+#define DOMAIN_MANAGER 1
+#endif
 
 #define domain_val(dom,type)   ((type) << (2*(dom)))
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_MMU
+#ifdef CONFIG_CPU_USE_DOMAINS
 #define set_domain(x)                                  \
        do {                                            \
        __asm__ __volatile__(                           \
 #define modify_domain(dom,type)        do { } while (0)
 #endif
 
+/*
+ * Generate the T (user) versions of the LDR/STR and related
+ * instructions (inline assembly)
+ */
+#ifdef CONFIG_CPU_USE_DOMAINS
+#define T(instr)       #instr "t"
+#else
+#define T(instr)       #instr
 #endif
-#endif /* !__ASSEMBLY__ */
+
+#else /* __ASSEMBLY__ */
+
+/*
+ * Generate the T (user) versions of the LDR/STR and related
+ * instructions
+ */
+#ifdef CONFIG_CPU_USE_DOMAINS
+#define T(instr)       instr ## t
+#else
+#define T(instr)       instr
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* !__ASM_PROC_DOMAIN_H */
diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S
new file mode 100644 (file)
index 0000000..ec0bbf7
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Interrupt handling.  Preserves r7, r8, r9
+ */
+       .macro  arch_irq_handler_default
+       get_irqnr_preamble r5, lr
+1:     get_irqnr_and_base r0, r6, r5, lr
+       movne   r1, sp
+       @
+       @ routine called with r0 = irq number, r1 = struct pt_regs *
+       @
+       adrne   lr, BSYM(1b)
+       bne     asm_do_IRQ
+
+#ifdef CONFIG_SMP
+       /*
+        * XXX
+        *
+        * this macro assumes that irqstat (r6) and base (r5) are
+        * preserved from get_irqnr_and_base above
+        */
+       ALT_SMP(test_for_ipi r0, r6, r5, lr)
+       ALT_UP_B(9997f)
+       movne   r1, sp
+       adrne   lr, BSYM(1b)
+       bne     do_IPI
+
+#ifdef CONFIG_LOCAL_TIMERS
+       test_for_ltirq r0, r6, r5, lr
+       movne   r0, sp
+       adrne   lr, BSYM(1b)
+       bne     do_local_timer
+#endif
+#endif
+9997:
+       .endm
+
+       .macro  arch_irq_handler, symbol_name
+       .align  5
+       .global \symbol_name
+\symbol_name:
+       mov     r4, lr
+       arch_irq_handler_default
+       mov     pc, r4
+       .endm
index 540a044..b33fe70 100644 (file)
 #include <linux/preempt.h>
 #include <linux/uaccess.h>
 #include <asm/errno.h>
+#include <asm/domain.h>
 
 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)     \
        __asm__ __volatile__(                                   \
-       "1:     ldrt    %1, [%2]\n"                             \
+       "1:     " T(ldr) "      %1, [%2]\n"                     \
        "       " insn "\n"                                     \
-       "2:     strt    %0, [%2]\n"                             \
+       "2:     " T(str) "      %0, [%2]\n"                     \
        "       mov     %0, #0\n"                               \
        "3:\n"                                                  \
        "       .pushsection __ex_table,\"a\"\n"                \
@@ -97,10 +98,10 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
        pagefault_disable();    /* implies preempt_disable() */
 
        __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
-       "1:     ldrt    %0, [%3]\n"
+       "1:     " T(ldr) "      %0, [%3]\n"
        "       teq     %0, %1\n"
        "       it      eq      @ explicit IT needed for the 2b label\n"
-       "2:     streqt  %2, [%3]\n"
+       "2:     " T(streq) "    %2, [%3]\n"
        "3:\n"
        "       .pushsection __ex_table,\"a\"\n"
        "       .align  3\n"
index 6d7485a..89ad180 100644 (file)
@@ -5,13 +5,31 @@
 #include <linux/threads.h>
 #include <asm/irq.h>
 
+#define NR_IPI 5
+
 typedef struct {
        unsigned int __softirq_pending;
+#ifdef CONFIG_LOCAL_TIMERS
        unsigned int local_timer_irqs;
+#endif
+#ifdef CONFIG_SMP
+       unsigned int ipi_irqs[NR_IPI];
+#endif
 } ____cacheline_aligned irq_cpustat_t;
 
 #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
 
+#define __inc_irq_stat(cpu, member)    __IRQ_STAT(cpu, member)++
+#define __get_irq_stat(cpu, member)    __IRQ_STAT(cpu, member)
+
+#ifdef CONFIG_SMP
+u64 smp_irq_stat_cpu(unsigned int cpu);
+#else
+#define smp_irq_stat_cpu(cpu)  0
+#endif
+
+#define arch_irq_stat_cpu      smp_irq_stat_cpu
+
 #if NR_IRQS > 512
 #define HARDIRQ_BITS   10
 #elif NR_IRQS > 256
index 50c7e7c..6bc63ab 100644 (file)
@@ -30,7 +30,6 @@ asmlinkage void do_local_timer(struct pt_regs *);
 #include "smp_twd.h"
 
 #define local_timer_ack()      twd_timer_ack()
-#define local_timer_stop()     twd_timer_stop()
 
 #else
 
@@ -40,11 +39,6 @@ asmlinkage void do_local_timer(struct pt_regs *);
  */
 int local_timer_ack(void);
 
-/*
- * Stop a local timer interrupt.
- */
-void local_timer_stop(void);
-
 #endif
 
 /*
@@ -52,12 +46,6 @@ void local_timer_stop(void);
  */
 void local_timer_setup(struct clock_event_device *);
 
-#else
-
-static inline void local_timer_stop(void)
-{
-}
-
 #endif
 
 #endif
index d97a964..3a0893a 100644 (file)
@@ -37,11 +37,20 @@ struct machine_desc {
                                         struct meminfo *);
        void                    (*reserve)(void);/* reserve mem blocks  */
        void                    (*map_io)(void);/* IO mapping function  */
+       void                    (*init_early)(void);
        void                    (*init_irq)(void);
        struct sys_timer        *timer;         /* system tick timer    */
        void                    (*init_machine)(void);
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+       void                    (*handle_irq)(struct pt_regs *);
+#endif
 };
 
+/*
+ * Current machine - only accessible during boot.
+ */
+extern struct machine_desc *machine_desc;
+
 /*
  * Set of macros to define architecture features.  This is built into
  * a table by the linker.
index ce3eee9..22ac140 100644 (file)
@@ -17,10 +17,12 @@ struct seq_file;
 /*
  * This is internal.  Do not use it.
  */
-extern unsigned int arch_nr_irqs;
-extern void (*init_arch_irq)(void);
 extern void init_FIQ(void);
-extern int show_fiq_list(struct seq_file *, void *);
+extern int show_fiq_list(struct seq_file *, int);
+
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+extern void (*handle_arch_irq)(struct pt_regs *);
+#endif
 
 /*
  * This is for easy migration, but should be changed in the source
index 35d408f..883f6be 100644 (file)
@@ -43,7 +43,6 @@ struct sys_timer {
 #endif
 };
 
-extern struct sys_timer *system_timer;
 extern void timer_tick(void);
 
 #endif
index 3d05190..96ed521 100644 (file)
@@ -33,27 +33,23 @@ struct seq_file;
 /*
  * generate IPI list text
  */
-extern void show_ipi_list(struct seq_file *p);
+extern void show_ipi_list(struct seq_file *, int);
 
 /*
  * Called from assembly code, this handles an IPI.
  */
-asmlinkage void do_IPI(struct pt_regs *regs);
+asmlinkage void do_IPI(int ipinr, struct pt_regs *regs);
 
 /*
  * Setup the set of possible CPUs (via set_cpu_possible)
  */
 extern void smp_init_cpus(void);
 
-/*
- * Move global data into per-processor storage.
- */
-extern void smp_store_cpu_info(unsigned int cpuid);
 
 /*
  * Raise an IPI cross call on CPUs in callmap.
  */
-extern void smp_cross_call(const struct cpumask *mask);
+extern void smp_cross_call(const struct cpumask *mask, int ipi);
 
 /*
  * Boot a secondary CPU, and assign it the specified idle task.
@@ -72,6 +68,11 @@ asmlinkage void secondary_start_kernel(void);
  */
 extern void platform_secondary_init(unsigned int cpu);
 
+/*
+ * Initialize cpu_possible map, and enable coherency
+ */
+extern void platform_smp_prepare_cpus(unsigned int);
+
 /*
  * Initial data for bringing up a secondary CPU.
  */
@@ -97,6 +98,6 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 /*
  * show local interrupt info
  */
-extern void show_local_irqs(struct seq_file *);
+extern void show_local_irqs(struct seq_file *, int);
 
 #endif /* ifndef __ASM_ARM_SMP_H */
diff --git a/arch/arm/include/asm/smp_mpidr.h b/arch/arm/include/asm/smp_mpidr.h
deleted file mode 100644 (file)
index 6a9307d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef ASMARM_SMP_MIDR_H
-#define ASMARM_SMP_MIDR_H
-
-#define hard_smp_processor_id()                                                \
-       ({                                                              \
-               unsigned int cpunum;                                    \
-               __asm__("\n"                                            \
-                       "1:     mrc p15, 0, %0, c0, c0, 5\n"            \
-                       "       .pushsection \".alt.smp.init\", \"a\"\n"\
-                       "       .long   1b\n"                           \
-                       "       mov     %0, #0\n"                       \
-                       "       .popsection"                            \
-                       : "=r" (cpunum));                               \
-               cpunum &= 0x0F;                                         \
-       })
-
-#endif
index 634f357..fed9981 100644 (file)
@@ -22,7 +22,6 @@ struct clock_event_device;
 
 extern void __iomem *twd_base;
 
-void twd_timer_stop(void);
 int twd_timer_ack(void);
 void twd_timer_setup(struct clock_event_device *);
 
index 3222ab8..97f6d60 100644 (file)
@@ -124,6 +124,13 @@ extern unsigned int user_debug;
 #define vectors_high() (0)
 #endif
 
+#if __LINUX_ARM_ARCH__ >= 7 ||         \
+       (__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K))
+#define sev()  __asm__ __volatile__ ("sev" : : : "memory")
+#define wfe()  __asm__ __volatile__ ("wfe" : : : "memory")
+#define wfi()  __asm__ __volatile__ ("wfi" : : : "memory")
+#endif
+
 #if __LINUX_ARM_ARCH__ >= 7
 #define isb() __asm__ __volatile__ ("isb" : : : "memory")
 #define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
index 124475a..1b960d5 100644 (file)
@@ -46,4 +46,6 @@ static inline int in_exception_text(unsigned long ptr)
 extern void __init early_trap_init(void);
 extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
 
+extern void *vectors_page;
+
 #endif
index 33e4a48..b293616 100644 (file)
@@ -227,7 +227,7 @@ do {                                                                        \
 
 #define __get_user_asm_byte(x,addr,err)                                \
        __asm__ __volatile__(                                   \
-       "1:     ldrbt   %1,[%2]\n"                              \
+       "1:     " T(ldrb) "     %1,[%2],#0\n"                   \
        "2:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
@@ -263,7 +263,7 @@ do {                                                                        \
 
 #define __get_user_asm_word(x,addr,err)                                \
        __asm__ __volatile__(                                   \
-       "1:     ldrt    %1,[%2]\n"                              \
+       "1:     " T(ldr) "      %1,[%2],#0\n"                   \
        "2:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
@@ -308,7 +308,7 @@ do {                                                                        \
 
 #define __put_user_asm_byte(x,__pu_addr,err)                   \
        __asm__ __volatile__(                                   \
-       "1:     strbt   %1,[%2]\n"                              \
+       "1:     " T(strb) "     %1,[%2],#0\n"                   \
        "2:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
@@ -341,7 +341,7 @@ do {                                                                        \
 
 #define __put_user_asm_word(x,__pu_addr,err)                   \
        __asm__ __volatile__(                                   \
-       "1:     strt    %1,[%2]\n"                              \
+       "1:     " T(str) "      %1,[%2],#0\n"                   \
        "2:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
@@ -366,10 +366,10 @@ do {                                                                      \
 
 #define __put_user_asm_dword(x,__pu_addr,err)                  \
        __asm__ __volatile__(                                   \
- ARM(  "1:     strt    " __reg_oper1 ", [%1], #4\n"    )       \
- ARM(  "2:     strt    " __reg_oper0 ", [%1]\n"        )       \
- THUMB(        "1:     strt    " __reg_oper1 ", [%1]\n"        )       \
- THUMB(        "2:     strt    " __reg_oper0 ", [%1, #4]\n"    )       \
+ ARM(  "1:     " T(str) "      " __reg_oper1 ", [%1], #4\n"    )       \
+ ARM(  "2:     " T(str) "      " __reg_oper0 ", [%1]\n"        )       \
+ THUMB(        "1:     " T(str) "      " __reg_oper1 ", [%1]\n"        )       \
+ THUMB(        "2:     " T(str) "      " __reg_oper0 ", [%1, #4]\n"    )       \
        "3:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
index fd3ec49..7c33e6f 100644 (file)
@@ -30,7 +30,7 @@ obj-$(CONFIG_ARTHUR)          += arthur.o
 obj-$(CONFIG_ISA_DMA)          += dma-isa.o
 obj-$(CONFIG_PCI)              += bios32.o isa.o
 obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o
-obj-$(CONFIG_SMP)              += smp.o
+obj-$(CONFIG_SMP)              += smp.o smp_tlb.o
 obj-$(CONFIG_HAVE_ARM_SCU)     += smp_scu.o
 obj-$(CONFIG_HAVE_ARM_TWD)     += smp_twd.o
 obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o
@@ -44,6 +44,8 @@ obj-$(CONFIG_KGDB)            += kgdb.o
 obj-$(CONFIG_ARM_UNWIND)       += unwind.o
 obj-$(CONFIG_HAVE_TCM)         += tcm.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
+obj-$(CONFIG_SWP_EMULATE)      += swp_emulate.o
+CFLAGS_swp_emulate.o           := -Wa,-march=armv7-a
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)       += hw_breakpoint.o
 
 obj-$(CONFIG_CRUNCH)           += crunch.o crunch-bits.o
index bb96a7d..27f6448 100644 (file)
 #include <asm/tls.h>
 
 #include "entry-header.S"
+#include <asm/entry-macro-multi.S>
 
 /*
  * Interrupt handling.  Preserves r7, r8, r9
  */
        .macro  irq_handler
-       get_irqnr_preamble r5, lr
-1:     get_irqnr_and_base r0, r6, r5, lr
-       movne   r1, sp
-       @
-       @ routine called with r0 = irq number, r1 = struct pt_regs *
-       @
-       adrne   lr, BSYM(1b)
-       bne     asm_do_IRQ
-
-#ifdef CONFIG_SMP
-       /*
-        * XXX
-        *
-        * this macro assumes that irqstat (r6) and base (r5) are
-        * preserved from get_irqnr_and_base above
-        */
-       ALT_SMP(test_for_ipi r0, r6, r5, lr)
-       ALT_UP_B(9997f)
-       movne   r0, sp
-       adrne   lr, BSYM(1b)
-       bne     do_IPI
-
-#ifdef CONFIG_LOCAL_TIMERS
-       test_for_ltirq r0, r6, r5, lr
-       movne   r0, sp
-       adrne   lr, BSYM(1b)
-       bne     do_local_timer
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+       ldr     r5, =handle_arch_irq
+       mov     r0, sp
+       ldr     r5, [r5]
+       adr     lr, BSYM(9997f)
+       teq     r5, #0
+       movne   pc, r5
 #endif
+       arch_irq_handler_default
 9997:
-#endif
-
        .endm
 
 #ifdef CONFIG_KPROBES
@@ -735,7 +715,7 @@ ENTRY(__switch_to)
  THUMB(        stmia   ip!, {r4 - sl, fp}         )    @ Store most regs on stack
  THUMB(        str     sp, [ip], #4               )
  THUMB(        str     lr, [ip], #4               )
-#ifdef CONFIG_MMU
+#ifdef CONFIG_CPU_USE_DOMAINS
        ldr     r6, [r2, #TI_CPU_DOMAIN]
 #endif
        set_tls r3, r4, r5
@@ -744,7 +724,7 @@ ENTRY(__switch_to)
        ldr     r8, =__stack_chk_guard
        ldr     r7, [r7, #TSK_STACK_CANARY]
 #endif
-#ifdef CONFIG_MMU
+#ifdef CONFIG_CPU_USE_DOMAINS
        mcr     p15, 0, r6, c3, c0, 0           @ Set domain register
 #endif
        mov     r5, r0
@@ -842,7 +822,7 @@ __kuser_helper_start:
  */
 
 __kuser_memory_barrier:                                @ 0xffff0fa0
-       smp_dmb
+       smp_dmb arm
        usr_ret lr
 
        .align  5
@@ -959,7 +939,7 @@ kuser_cmpxchg_fixup:
 
 #else
 
-       smp_dmb
+       smp_dmb arm
 1:     ldrex   r3, [r2]
        subs    r3, r3, r0
        strexeq r3, r1, [r2]
@@ -1245,3 +1225,9 @@ cr_alignment:
        .space  4
 cr_no_alignment:
        .space  4
+
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+       .globl  handle_arch_irq
+handle_arch_irq:
+       .space  4
+#endif
index 6ff7919..e72dc34 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/fiq.h>
 #include <asm/irq.h>
 #include <asm/system.h>
+#include <asm/traps.h>
 
 static unsigned long no_fiq_insn;
 
@@ -67,17 +68,22 @@ static struct fiq_handler default_owner = {
 
 static struct fiq_handler *current_fiq = &default_owner;
 
-int show_fiq_list(struct seq_file *p, void *v)
+int show_fiq_list(struct seq_file *p, int prec)
 {
        if (current_fiq != &default_owner)
-               seq_printf(p, "FIQ:              %s\n", current_fiq->name);
+               seq_printf(p, "%*s:              %s\n", prec, "FIQ",
+                       current_fiq->name);
 
        return 0;
 }
 
 void set_fiq_handler(void *start, unsigned int length)
 {
+#if defined(CONFIG_CPU_USE_DOMAINS)
        memcpy((void *)0xffff001c, start, length);
+#else
+       memcpy(vectors_page + 0x1c, start, length);
+#endif
        flush_icache_range(0xffff001c, 0xffff001c + length);
        if (!vectors_high())
                flush_icache_range(0x1c, 0x1c + length);
index 6bd82d2..f17d9a0 100644 (file)
@@ -91,6 +91,11 @@ ENTRY(stext)
        movs    r8, r5                          @ invalid machine (r5=0)?
  THUMB( it     eq )            @ force fixup-able long branch encoding
        beq     __error_a                       @ yes, error 'a'
+
+       /*
+        * r1 = machine no, r2 = atags,
+        * r8 = machinfo, r9 = cpuid, r10 = procinfo
+        */
        bl      __vet_atags
 #ifdef CONFIG_SMP_ON_UP
        bl      __fixup_smp
@@ -387,19 +392,19 @@ ENDPROC(__turn_mmu_on)
 
 #ifdef CONFIG_SMP_ON_UP
 __fixup_smp:
-       mov     r7, #0x00070000
-       orr     r6, r7, #0xff000000     @ mask 0xff070000
-       orr     r7, r7, #0x41000000     @ val 0x41070000
-       and     r0, r9, r6
-       teq     r0, r7                  @ ARM CPU and ARMv6/v7?
+       mov     r4, #0x00070000
+       orr     r3, r4, #0xff000000     @ mask 0xff070000
+       orr     r4, r4, #0x41000000     @ val 0x41070000
+       and     r0, r9, r3
+       teq     r0, r4                  @ ARM CPU and ARMv6/v7?
        bne     __fixup_smp_on_up       @ no, assume UP
 
-       orr     r6, r6, #0x0000ff00
-       orr     r6, r6, #0x000000f0     @ mask 0xff07fff0
-       orr     r7, r7, #0x0000b000
-       orr     r7, r7, #0x00000020     @ val 0x4107b020
-       and     r0, r9, r6
-       teq     r0, r7                  @ ARM 11MPCore?
+       orr     r3, r3, #0x0000ff00
+       orr     r3, r3, #0x000000f0     @ mask 0xff07fff0
+       orr     r4, r4, #0x0000b000
+       orr     r4, r4, #0x00000020     @ val 0x4107b020
+       and     r0, r9, r3
+       teq     r0, r4                  @ ARM 11MPCore?
        moveq   pc, lr                  @ yes, assume SMP
 
        mrc     p15, 0, r0, c0, c0, 5   @ read MPIDR
@@ -408,15 +413,22 @@ __fixup_smp:
 
 __fixup_smp_on_up:
        adr     r0, 1f
-       ldmia   r0, {r3, r6, r7}
+       ldmia   r0, {r3 - r5}
        sub     r3, r0, r3
-       add     r6, r6, r3
-       add     r7, r7, r3
-2:     cmp     r6, r7
-       ldmia   r6!, {r0, r4}
-       strlo   r4, [r0, r3]
-       blo     2b
-       mov     pc, lr
+       add     r4, r4, r3
+       add     r5, r5, r3
+2:     cmp     r4, r5
+       movhs   pc, lr
+       ldmia   r4!, {r0, r6}
+ ARM(  str     r6, [r0, r3]    )
+ THUMB(        add     r0, r0, r3      )
+#ifdef __ARMEB__
+ THUMB(        mov     r6, r6, ror #16 )       @ Convert word order for big-endian.
+#endif
+ THUMB(        strh    r6, [r0], #2    )       @ For Thumb-2, store as two halfwords
+ THUMB(        mov     r6, r6, lsr #16 )       @ to be robust against misaligned r3.
+ THUMB(        strh    r6, [r0]        )
+       b       2b
 ENDPROC(__fixup_smp)
 
        .align
index 6d61633..8135438 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/ftrace.h>
 
 #include <asm/system.h>
+#include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
@@ -48,8 +49,6 @@
 #define irq_finish(irq) do { } while (0)
 #endif
 
-unsigned int arch_nr_irqs;
-void (*init_arch_irq)(void) __initdata = NULL;
 unsigned long irq_err_count;
 
 int show_interrupts(struct seq_file *p, void *v)
@@ -58,11 +57,20 @@ int show_interrupts(struct seq_file *p, void *v)
        struct irq_desc *desc;
        struct irqaction * action;
        unsigned long flags;
+       int prec, n;
+
+       for (prec = 3, n = 1000; prec < 10 && n <= nr_irqs; prec++)
+               n *= 10;
+
+#ifdef CONFIG_SMP
+       if (prec < 4)
+               prec = 4;
+#endif
 
        if (i == 0) {
                char cpuname[12];
 
-               seq_printf(p, "    ");
+               seq_printf(p, "%*s ", prec, "");
                for_each_present_cpu(cpu) {
                        sprintf(cpuname, "CPU%d", cpu);
                        seq_printf(p, " %10s", cpuname);
@@ -77,7 +85,7 @@ int show_interrupts(struct seq_file *p, void *v)
                if (!action)
                        goto unlock;
 
-               seq_printf(p, "%3d: ", i);
+               seq_printf(p, "%*d: ", prec, i);
                for_each_present_cpu(cpu)
                        seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
                seq_printf(p, " %10s", desc->chip->name ? : "-");
@@ -90,13 +98,15 @@ unlock:
                raw_spin_unlock_irqrestore(&desc->lock, flags);
        } else if (i == nr_irqs) {
 #ifdef CONFIG_FIQ
-               show_fiq_list(p, v);
+               show_fiq_list(p, prec);
 #endif
 #ifdef CONFIG_SMP
-               show_ipi_list(p);
-               show_local_irqs(p);
+               show_ipi_list(p, prec);
+#endif
+#ifdef CONFIG_LOCAL_TIMERS
+               show_local_irqs(p, prec);
 #endif
-               seq_printf(p, "Err: %10lu\n", irq_err_count);
+               seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
        }
        return 0;
 }
@@ -156,13 +166,13 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
 
 void __init init_IRQ(void)
 {
-       init_arch_irq();
+       machine_desc->init_irq();
 }
 
 #ifdef CONFIG_SPARSE_IRQ
 int __init arch_probe_nr_irqs(void)
 {
-       nr_irqs = arch_nr_irqs ? arch_nr_irqs : NR_IRQS;
+       nr_irqs = machine_desc->nr_irqs ? machine_desc->nr_irqs : NR_IRQS;
        return nr_irqs;
 }
 #endif
index 336f14e..3455ad3 100644 (file)
@@ -75,9 +75,9 @@ extern void reboot_setup(char *str);
 
 unsigned int processor_id;
 EXPORT_SYMBOL(processor_id);
-unsigned int __machine_arch_type;
+unsigned int __machine_arch_type __read_mostly;
 EXPORT_SYMBOL(__machine_arch_type);
-unsigned int cacheid;
+unsigned int cacheid __read_mostly;
 EXPORT_SYMBOL(cacheid);
 
 unsigned int __atags_pointer __initdata;
@@ -91,24 +91,24 @@ EXPORT_SYMBOL(system_serial_low);
 unsigned int system_serial_high;
 EXPORT_SYMBOL(system_serial_high);
 
-unsigned int elf_hwcap;
+unsigned int elf_hwcap __read_mostly;
 EXPORT_SYMBOL(elf_hwcap);
 
 
 #ifdef MULTI_CPU
-struct processor processor;
+struct processor processor __read_mostly;
 #endif
 #ifdef MULTI_TLB
-struct cpu_tlb_fns cpu_tlb;
+struct cpu_tlb_fns cpu_tlb __read_mostly;
 #endif
 #ifdef MULTI_USER
-struct cpu_user_fns cpu_user;
+struct cpu_user_fns cpu_user __read_mostly;
 #endif
 #ifdef MULTI_CACHE
-struct cpu_cache_fns cpu_cache;
+struct cpu_cache_fns cpu_cache __read_mostly;
 #endif
 #ifdef CONFIG_OUTER_CACHE
-struct outer_cache_fns outer_cache;
+struct outer_cache_fns outer_cache __read_mostly;
 EXPORT_SYMBOL(outer_cache);
 #endif
 
@@ -126,6 +126,7 @@ EXPORT_SYMBOL(elf_platform);
 static const char *cpu_name;
 static const char *machine_name;
 static char __initdata cmd_line[COMMAND_LINE_SIZE];
+struct machine_desc *machine_desc __initdata;
 
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
@@ -708,13 +709,11 @@ static struct init_tags {
        { 0, ATAG_NONE }
 };
 
-static void (*init_machine)(void) __initdata;
-
 static int __init customize_machine(void)
 {
        /* customizes platform devices, or adds new ones */
-       if (init_machine)
-               init_machine();
+       if (machine_desc->init_machine)
+               machine_desc->init_machine();
        return 0;
 }
 arch_initcall(customize_machine);
@@ -809,6 +808,7 @@ void __init setup_arch(char **cmdline_p)
 
        setup_processor();
        mdesc = setup_machine(machine_arch_type);
+       machine_desc = mdesc;
        machine_name = mdesc->name;
 
        if (mdesc->soft_reboot)
@@ -868,13 +868,9 @@ void __init setup_arch(char **cmdline_p)
        cpu_init();
        tcm_init();
 
-       /*
-        * Set up various architecture-specific pointers
-        */
-       arch_nr_irqs = mdesc->nr_irqs;
-       init_arch_irq = mdesc->init_irq;
-       system_timer = mdesc->timer;
-       init_machine = mdesc->init_machine;
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+       handle_arch_irq = mdesc->handle_irq;
+#endif
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
@@ -884,6 +880,9 @@ void __init setup_arch(char **cmdline_p)
 #endif
 #endif
        early_trap_init();
+
+       if (mdesc->init_early)
+               mdesc->init_early();
 }
 
 
index b6b78b2..5ec79b4 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/irq.h>
 #include <linux/percpu.h>
 #include <linux/clockchips.h>
+#include <linux/completion.h>
 
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
@@ -38,7 +39,6 @@
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
 #include <asm/localtimer.h>
-#include <asm/smp_plat.h>
 
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
  */
 struct secondary_data secondary_data;
 
-/*
- * structures for inter-processor calls
- * - A collection of single bit ipi messages.
- */
-struct ipi_data {
-       spinlock_t lock;
-       unsigned long ipi_count;
-       unsigned long bits;
-};
-
-static DEFINE_PER_CPU(struct ipi_data, ipi_data) = {
-       .lock   = SPIN_LOCK_UNLOCKED,
-};
-
 enum ipi_msg_type {
-       IPI_TIMER,
+       IPI_TIMER = 2,
        IPI_RESCHEDULE,
        IPI_CALL_FUNC,
        IPI_CALL_FUNC_SINGLE,
@@ -178,8 +164,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
                        barrier();
                }
 
-               if (!cpu_online(cpu))
+               if (!cpu_online(cpu)) {
+                       pr_crit("CPU%u: failed to come online\n", cpu);
                        ret = -EIO;
+               }
+       } else {
+               pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
        }
 
        secondary_data.stack = NULL;
@@ -195,18 +185,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
 
        pgd_free(&init_mm, pgd);
 
-       if (ret) {
-               printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
-
-               /*
-                * FIXME: We need to clean up the new idle thread. --rmk
-                */
-       }
-
        return ret;
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
+static void percpu_timer_stop(void);
+
 /*
  * __cpu_disable runs on the processor to be shutdown.
  */
@@ -234,7 +218,7 @@ int __cpu_disable(void)
        /*
         * Stop the local timer for this CPU.
         */
-       local_timer_stop();
+       percpu_timer_stop();
 
        /*
         * Flush user cache and TLB mappings, and then remove this CPU
@@ -253,12 +237,20 @@ int __cpu_disable(void)
        return 0;
 }
 
+static DECLARE_COMPLETION(cpu_died);
+
 /*
  * called on the thread which is asking for a CPU to be shutdown -
  * waits until shutdown has completed, or it is timed out.
  */
 void __cpu_die(unsigned int cpu)
 {
+       if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) {
+               pr_err("CPU%u: cpu didn't die\n", cpu);
+               return;
+       }
+       printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
+
        if (!platform_cpu_kill(cpu))
                printk("CPU%u: unable to kill\n", cpu);
 }
@@ -275,12 +267,17 @@ void __ref cpu_die(void)
 {
        unsigned int cpu = smp_processor_id();
 
-       local_irq_disable();
        idle_task_exit();
 
+       local_irq_disable();
+       mb();
+
+       /* Tell __cpu_die() that this CPU is now safe to dispose of */
+       complete(&cpu_died);
+
        /*
         * actual CPU shutdown procedure is at least platform (if not
-        * CPU) specific
+        * CPU) specific.
         */
        platform_cpu_die(cpu);
 
@@ -290,12 +287,24 @@ void __ref cpu_die(void)
         * to be repeated to undo the effects of taking the CPU offline.
         */
        __asm__("mov    sp, %0\n"
+       "       mov     fp, #0\n"
        "       b       secondary_start_kernel"
                :
                : "r" (task_stack_page(current) + THREAD_SIZE - 8));
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
+/*
+ * Called by both boot and secondaries to move global data into
+ * per-processor storage.
+ */
+static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
+{
+       struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
+
+       cpu_info->loops_per_jiffy = loops_per_jiffy;
+}
+
 /*
  * This is the secondary CPU boot entry.  We're using this CPUs
  * idle thread stack, but a set of temporary page tables.
@@ -320,6 +329,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
 
        cpu_init();
        preempt_disable();
+       trace_hardirqs_off();
 
        /*
         * Give the platform a chance to do its own initialisation.
@@ -353,17 +363,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
        cpu_idle();
 }
 
-/*
- * Called by both boot and secondaries to move global data into
- * per-processor storage.
- */
-void __cpuinit smp_store_cpu_info(unsigned int cpuid)
-{
-       struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
-
-       cpu_info->loops_per_jiffy = loops_per_jiffy;
-}
-
 void __init smp_cpus_done(unsigned int max_cpus)
 {
        int cpu;
@@ -386,61 +385,80 @@ void __init smp_prepare_boot_cpu(void)
        per_cpu(cpu_data, cpu).idle = current;
 }
 
-static void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg)
+void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-       unsigned long flags;
-       unsigned int cpu;
-
-       local_irq_save(flags);
+       unsigned int ncores = num_possible_cpus();
 
-       for_each_cpu(cpu, mask) {
-               struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
-
-               spin_lock(&ipi->lock);
-               ipi->bits |= 1 << msg;
-               spin_unlock(&ipi->lock);
-       }
+       smp_store_cpu_info(smp_processor_id());
 
        /*
-        * Call the platform specific cross-CPU call function.
+        * are we trying to boot more cores than exist?
         */
-       smp_cross_call(mask);
+       if (max_cpus > ncores)
+               max_cpus = ncores;
+
+       if (max_cpus > 1) {
+               /*
+                * Enable the local timer or broadcast device for the
+                * boot CPU, but only if we have more than one CPU.
+                */
+               percpu_timer_setup();
 
-       local_irq_restore(flags);
+               /*
+                * Initialise the SCU if there are more than one CPU
+                * and let them know where to start.
+                */
+               platform_smp_prepare_cpus(max_cpus);
+       }
 }
 
 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 {
-       send_ipi_message(mask, IPI_CALL_FUNC);
+       smp_cross_call(mask, IPI_CALL_FUNC);
 }
 
 void arch_send_call_function_single_ipi(int cpu)
 {
-       send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+       smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
 }
 
-void show_ipi_list(struct seq_file *p)
+static const char *ipi_types[NR_IPI] = {
+#define S(x,s) [x - IPI_TIMER] = s
+       S(IPI_TIMER, "Timer broadcast interrupts"),
+       S(IPI_RESCHEDULE, "Rescheduling interrupts"),
+       S(IPI_CALL_FUNC, "Function call interrupts"),
+       S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
+       S(IPI_CPU_STOP, "CPU stop interrupts"),
+};
+
+void show_ipi_list(struct seq_file *p, int prec)
 {
-       unsigned int cpu;
+       unsigned int cpu, i;
 
-       seq_puts(p, "IPI:");
+       for (i = 0; i < NR_IPI; i++) {
+               seq_printf(p, "%*s%u: ", prec - 1, "IPI", i);
 
-       for_each_present_cpu(cpu)
-               seq_printf(p, " %10lu", per_cpu(ipi_data, cpu).ipi_count);
+               for_each_present_cpu(cpu)
+                       seq_printf(p, "%10u ",
+                                  __get_irq_stat(cpu, ipi_irqs[i]));
 
-       seq_putc(p, '\n');
+               seq_printf(p, " %s\n", ipi_types[i]);
+       }
 }
 
-void show_local_irqs(struct seq_file *p)
+u64 smp_irq_stat_cpu(unsigned int cpu)
 {
-       unsigned int cpu;
+       u64 sum = 0;
+       int i;
 
-       seq_printf(p, "LOC: ");
+       for (i = 0; i < NR_IPI; i++)
+               sum += __get_irq_stat(cpu, ipi_irqs[i]);
 
-       for_each_present_cpu(cpu)
-               seq_printf(p, "%10u ", irq_stat[cpu].local_timer_irqs);
+#ifdef CONFIG_LOCAL_TIMERS
+       sum += __get_irq_stat(cpu, local_timer_irqs);
+#endif
 
-       seq_putc(p, '\n');
+       return sum;
 }
 
 /*
@@ -463,18 +481,30 @@ asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)
        int cpu = smp_processor_id();
 
        if (local_timer_ack()) {
-               irq_stat[cpu].local_timer_irqs++;
+               __inc_irq_stat(cpu, local_timer_irqs);
                ipi_timer();
        }
 
        set_irq_regs(old_regs);
 }
+
+void show_local_irqs(struct seq_file *p, int prec)
+{
+       unsigned int cpu;
+
+       seq_printf(p, "%*s: ", prec, "LOC");
+
+       for_each_present_cpu(cpu)
+               seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs));
+
+       seq_printf(p, " Local timer interrupts\n");
+}
 #endif
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 static void smp_timer_broadcast(const struct cpumask *mask)
 {
-       send_ipi_message(mask, IPI_TIMER);
+       smp_cross_call(mask, IPI_TIMER);
 }
 #else
 #define smp_timer_broadcast    NULL
@@ -511,6 +541,21 @@ void __cpuinit percpu_timer_setup(void)
        local_timer_setup(evt);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * The generic clock events code purposely does not stop the local timer
+ * on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it
+ * manually here.
+ */
+static void percpu_timer_stop(void)
+{
+       unsigned int cpu = smp_processor_id();
+       struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
+
+       evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+}
+#endif
+
 static DEFINE_SPINLOCK(stop_lock);
 
 /*
@@ -537,216 +582,76 @@ static void ipi_cpu_stop(unsigned int cpu)
 
 /*
  * Main handler for inter-processor interrupts
- *
- * For ARM, the ipimask now only identifies a single
- * category of IPI (Bit 1 IPIs have been replaced by a
- * different mechanism):
- *
- *  Bit 0 - Inter-processor function call
  */
-asmlinkage void __exception_irq_entry do_IPI(struct pt_regs *regs)
+asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
 {
        unsigned int cpu = smp_processor_id();
-       struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
        struct pt_regs *old_regs = set_irq_regs(regs);
 
-       ipi->ipi_count++;
-
-       for (;;) {
-               unsigned long msgs;
+       if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI)
+               __inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]);
 
-               spin_lock(&ipi->lock);
-               msgs = ipi->bits;
-               ipi->bits = 0;
-               spin_unlock(&ipi->lock);
-
-               if (!msgs)
-                       break;
-
-               do {
-                       unsigned nextmsg;
-
-                       nextmsg = msgs & -msgs;
-                       msgs &= ~nextmsg;
-                       nextmsg = ffz(~nextmsg);
-
-                       switch (nextmsg) {
-                       case IPI_TIMER:
-                               ipi_timer();
-                               break;
+       switch (ipinr) {
+       case IPI_TIMER:
+               ipi_timer();
+               break;
 
-                       case IPI_RESCHEDULE:
-                               /*
-                                * nothing more to do - eveything is
-                                * done on the interrupt return path
-                                */
-                               break;
+       case IPI_RESCHEDULE:
+               /*
+                * nothing more to do - eveything is
+                * done on the interrupt return path
+                */
+               break;
 
-                       case IPI_CALL_FUNC:
-                               generic_smp_call_function_interrupt();
-                               break;
+       case IPI_CALL_FUNC:
+               generic_smp_call_function_interrupt();
+               break;
 
-                       case IPI_CALL_FUNC_SINGLE:
-                               generic_smp_call_function_single_interrupt();
-                               break;
+       case IPI_CALL_FUNC_SINGLE:
+               generic_smp_call_function_single_interrupt();
+               break;
 
-                       case IPI_CPU_STOP:
-                               ipi_cpu_stop(cpu);
-                               break;
+       case IPI_CPU_STOP:
+               ipi_cpu_stop(cpu);
+               break;
 
-                       default:
-                               printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
-                                      cpu, nextmsg);
-                               break;
-                       }
-               } while (msgs);
+       default:
+               printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
+                      cpu, ipinr);
+               break;
        }
-
        set_irq_regs(old_regs);
 }
 
 void smp_send_reschedule(int cpu)
 {
-       send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE);
+       smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
 }
 
 void smp_send_stop(void)
 {
-       cpumask_t mask = cpu_online_map;
-       cpu_clear(smp_processor_id(), mask);
-       if (!cpus_empty(mask))
-               send_ipi_message(&mask, IPI_CPU_STOP);
-}
+       unsigned long timeout;
 
-/*
- * not supported here
- */
-int setup_profiling_timer(unsigned int multiplier)
-{
-       return -EINVAL;
-}
+       if (num_online_cpus() > 1) {
+               cpumask_t mask = cpu_online_map;
+               cpu_clear(smp_processor_id(), mask);
 
-static void
-on_each_cpu_mask(void (*func)(void *), void *info, int wait,
-               const struct cpumask *mask)
-{
-       preempt_disable();
+               smp_cross_call(&mask, IPI_CPU_STOP);
+       }
 
-       smp_call_function_many(mask, func, info, wait);
-       if (cpumask_test_cpu(smp_processor_id(), mask))
-               func(info);
+       /* Wait up to one second for other CPUs to stop */
+       timeout = USEC_PER_SEC;
+       while (num_online_cpus() > 1 && timeout--)
+               udelay(1);
 
-       preempt_enable();
+       if (num_online_cpus() > 1)
+               pr_warning("SMP: failed to stop secondary CPUs\n");
 }
 
-/**********************************************************************/
-
 /*
- * TLB operations
+ * not supported here
  */
-struct tlb_args {
-       struct vm_area_struct *ta_vma;
-       unsigned long ta_start;
-       unsigned long ta_end;
-};
-
-static inline void ipi_flush_tlb_all(void *ignored)
-{
-       local_flush_tlb_all();
-}
-
-static inline void ipi_flush_tlb_mm(void *arg)
-{
-       struct mm_struct *mm = (struct mm_struct *)arg;
-
-       local_flush_tlb_mm(mm);
-}
-
-static inline void ipi_flush_tlb_page(void *arg)
-{
-       struct tlb_args *ta = (struct tlb_args *)arg;
-
-       local_flush_tlb_page(ta->ta_vma, ta->ta_start);
-}
-
-static inline void ipi_flush_tlb_kernel_page(void *arg)
-{
-       struct tlb_args *ta = (struct tlb_args *)arg;
-
-       local_flush_tlb_kernel_page(ta->ta_start);
-}
-
-static inline void ipi_flush_tlb_range(void *arg)
-{
-       struct tlb_args *ta = (struct tlb_args *)arg;
-
-       local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
-}
-
-static inline void ipi_flush_tlb_kernel_range(void *arg)
-{
-       struct tlb_args *ta = (struct tlb_args *)arg;
-
-       local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
-}
-
-void flush_tlb_all(void)
-{
-       if (tlb_ops_need_broadcast())
-               on_each_cpu(ipi_flush_tlb_all, NULL, 1);
-       else
-               local_flush_tlb_all();
-}
-
-void flush_tlb_mm(struct mm_struct *mm)
-{
-       if (tlb_ops_need_broadcast())
-               on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm));
-       else
-               local_flush_tlb_mm(mm);
-}
-
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
-{
-       if (tlb_ops_need_broadcast()) {
-               struct tlb_args ta;
-               ta.ta_vma = vma;
-               ta.ta_start = uaddr;
-               on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm));
-       } else
-               local_flush_tlb_page(vma, uaddr);
-}
-
-void flush_tlb_kernel_page(unsigned long kaddr)
-{
-       if (tlb_ops_need_broadcast()) {
-               struct tlb_args ta;
-               ta.ta_start = kaddr;
-               on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
-       } else
-               local_flush_tlb_kernel_page(kaddr);
-}
-
-void flush_tlb_range(struct vm_area_struct *vma,
-                     unsigned long start, unsigned long end)
-{
-       if (tlb_ops_need_broadcast()) {
-               struct tlb_args ta;
-               ta.ta_vma = vma;
-               ta.ta_start = start;
-               ta.ta_end = end;
-               on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm));
-       } else
-               local_flush_tlb_range(vma, start, end);
-}
-
-void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+int setup_profiling_timer(unsigned int multiplier)
 {
-       if (tlb_ops_need_broadcast()) {
-               struct tlb_args ta;
-               ta.ta_start = start;
-               ta.ta_end = end;
-               on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
-       } else
-               local_flush_tlb_kernel_range(start, end);
+       return -EINVAL;
 }
diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
new file mode 100644 (file)
index 0000000..7dcb352
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ *  linux/arch/arm/kernel/smp_tlb.c
+ *
+ *  Copyright (C) 2002 ARM Limited, 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 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/preempt.h>
+#include <linux/smp.h>
+
+#include <asm/smp_plat.h>
+#include <asm/tlbflush.h>
+
+static void on_each_cpu_mask(void (*func)(void *), void *info, int wait,
+       const struct cpumask *mask)
+{
+       preempt_disable();
+
+       smp_call_function_many(mask, func, info, wait);
+       if (cpumask_test_cpu(smp_processor_id(), mask))
+               func(info);
+
+       preempt_enable();
+}
+
+/**********************************************************************/
+
+/*
+ * TLB operations
+ */
+struct tlb_args {
+       struct vm_area_struct *ta_vma;
+       unsigned long ta_start;
+       unsigned long ta_end;
+};
+
+static inline void ipi_flush_tlb_all(void *ignored)
+{
+       local_flush_tlb_all();
+}
+
+static inline void ipi_flush_tlb_mm(void *arg)
+{
+       struct mm_struct *mm = (struct mm_struct *)arg;
+
+       local_flush_tlb_mm(mm);
+}
+
+static inline void ipi_flush_tlb_page(void *arg)
+{
+       struct tlb_args *ta = (struct tlb_args *)arg;
+
+       local_flush_tlb_page(ta->ta_vma, ta->ta_start);
+}
+
+static inline void ipi_flush_tlb_kernel_page(void *arg)
+{
+       struct tlb_args *ta = (struct tlb_args *)arg;
+
+       local_flush_tlb_kernel_page(ta->ta_start);
+}
+
+static inline void ipi_flush_tlb_range(void *arg)
+{
+       struct tlb_args *ta = (struct tlb_args *)arg;
+
+       local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
+}
+
+static inline void ipi_flush_tlb_kernel_range(void *arg)
+{
+       struct tlb_args *ta = (struct tlb_args *)arg;
+
+       local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
+}
+
+void flush_tlb_all(void)
+{
+       if (tlb_ops_need_broadcast())
+               on_each_cpu(ipi_flush_tlb_all, NULL, 1);
+       else
+               local_flush_tlb_all();
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+       if (tlb_ops_need_broadcast())
+               on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm));
+       else
+               local_flush_tlb_mm(mm);
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
+{
+       if (tlb_ops_need_broadcast()) {
+               struct tlb_args ta;
+               ta.ta_vma = vma;
+               ta.ta_start = uaddr;
+               on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm));
+       } else
+               local_flush_tlb_page(vma, uaddr);
+}
+
+void flush_tlb_kernel_page(unsigned long kaddr)
+{
+       if (tlb_ops_need_broadcast()) {
+               struct tlb_args ta;
+               ta.ta_start = kaddr;
+               on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
+       } else
+               local_flush_tlb_kernel_page(kaddr);
+}
+
+void flush_tlb_range(struct vm_area_struct *vma,
+                     unsigned long start, unsigned long end)
+{
+       if (tlb_ops_need_broadcast()) {
+               struct tlb_args ta;
+               ta.ta_vma = vma;
+               ta.ta_start = start;
+               ta.ta_end = end;
+               on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm));
+       } else
+               local_flush_tlb_range(vma, start, end);
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+       if (tlb_ops_need_broadcast()) {
+               struct tlb_args ta;
+               ta.ta_start = start;
+               ta.ta_end = end;
+               on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
+       } else
+               local_flush_tlb_kernel_range(start, end);
+}
+
index 67f933e..dd79074 100644 (file)
@@ -145,13 +145,3 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
 
        clockevents_register_device(clk);
 }
-
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * take a local timer down
- */
-void twd_timer_stop(void)
-{
-       __raw_writel(0, twd_base + TWD_TIMER_CONTROL);
-}
-#endif
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
new file mode 100644 (file)
index 0000000..7a57609
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ *  linux/arch/arm/kernel/swp_emulate.c
+ *
+ *  Copyright (C) 2009 ARM Limited
+ *  __user_* functions adapted from include/asm/uaccess.h
+ *
+ * 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.
+ *
+ *  Implements emulation of the SWP/SWPB instructions using load-exclusive and
+ *  store-exclusive for processors that have them disabled (or future ones that
+ *  might not implement them).
+ *
+ *  Syntax of SWP{B} instruction: SWP{B}<c> <Rt>, <Rt2>, [<Rn>]
+ *  Where: Rt  = destination
+ *        Rt2 = source
+ *        Rn  = address
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/syscalls.h>
+#include <linux/perf_event.h>
+
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+
+/*
+ * Error-checking SWP macros implemented using ldrex{b}/strex{b}
+ */
+#define __user_swpX_asm(data, addr, res, temp, B)              \
+       __asm__ __volatile__(                                   \
+       "       mov             %2, %1\n"                       \
+       "0:     ldrex"B"        %1, [%3]\n"                     \
+       "1:     strex"B"        %0, %2, [%3]\n"                 \
+       "       cmp             %0, #0\n"                       \
+       "       movne           %0, %4\n"                       \
+       "2:\n"                                                  \
+       "       .section         .fixup,\"ax\"\n"               \
+       "       .align          2\n"                            \
+       "3:     mov             %0, %5\n"                       \
+       "       b               2b\n"                           \
+       "       .previous\n"                                    \
+       "       .section         __ex_table,\"a\"\n"            \
+       "       .align          3\n"                            \
+       "       .long           0b, 3b\n"                       \
+       "       .long           1b, 3b\n"                       \
+       "       .previous"                                      \
+       : "=&r" (res), "+r" (data), "=&r" (temp)                \
+       : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT)              \
+       : "cc", "memory")
+
+#define __user_swp_asm(data, addr, res, temp) \
+       __user_swpX_asm(data, addr, res, temp, "")
+#define __user_swpb_asm(data, addr, res, temp) \
+       __user_swpX_asm(data, addr, res, temp, "b")
+
+/*
+ * Macros/defines for extracting register numbers from instruction.
+ */
+#define EXTRACT_REG_NUM(instruction, offset) \
+       (((instruction) & (0xf << (offset))) >> (offset))
+#define RN_OFFSET  16
+#define RT_OFFSET  12
+#define RT2_OFFSET  0
+/*
+ * Bit 22 of the instruction encoding distinguishes between
+ * the SWP and SWPB variants (bit set means SWPB).
+ */
+#define TYPE_SWPB (1 << 22)
+
+static unsigned long swpcounter;
+static unsigned long swpbcounter;
+static unsigned long abtcounter;
+static pid_t         previous_pid;
+
+#ifdef CONFIG_PROC_FS
+static int proc_read_status(char *page, char **start, off_t off, int count,
+                           int *eof, void *data)
+{
+       char *p = page;
+       int len;
+
+       p += sprintf(p, "Emulated SWP:\t\t%lu\n", swpcounter);
+       p += sprintf(p, "Emulated SWPB:\t\t%lu\n", swpbcounter);
+       p += sprintf(p, "Aborted SWP{B}:\t\t%lu\n", abtcounter);
+       if (previous_pid != 0)
+               p += sprintf(p, "Last process:\t\t%d\n", previous_pid);
+
+       len = (p - page) - off;
+       if (len < 0)
+               len = 0;
+
+       *eof = (len <= count) ? 1 : 0;
+       *start = page + off;
+
+       return len;
+}
+#endif
+
+/*
+ * Set up process info to signal segmentation fault - called on access error.
+ */
+static void set_segfault(struct pt_regs *regs, unsigned long addr)
+{
+       siginfo_t info;
+
+       if (find_vma(current->mm, addr) == NULL)
+               info.si_code = SEGV_MAPERR;
+       else
+               info.si_code = SEGV_ACCERR;
+
+       info.si_signo = SIGSEGV;
+       info.si_errno = 0;
+       info.si_addr  = (void *) instruction_pointer(regs);
+
+       pr_debug("SWP{B} emulation: access caused memory abort!\n");
+       arm_notify_die("Illegal memory access", regs, &info, 0, 0);
+
+       abtcounter++;
+}
+
+static int emulate_swpX(unsigned int address, unsigned int *data,
+                       unsigned int type)
+{
+       unsigned int res = 0;
+
+       if ((type != TYPE_SWPB) && (address & 0x3)) {
+               /* SWP to unaligned address not permitted */
+               pr_debug("SWP instruction on unaligned pointer!\n");
+               return -EFAULT;
+       }
+
+       while (1) {
+               unsigned long temp;
+
+               /*
+                * Barrier required between accessing protected resource and
+                * releasing a lock for it. Legacy code might not have done
+                * this, and we cannot determine that this is not the case
+                * being emulated, so insert always.
+                */
+               smp_mb();
+
+               if (type == TYPE_SWPB)
+                       __user_swpb_asm(*data, address, res, temp);
+               else
+                       __user_swp_asm(*data, address, res, temp);
+
+               if (likely(res != -EAGAIN) || signal_pending(current))
+                       break;
+
+               cond_resched();
+       }
+
+       if (res == 0) {
+               /*
+                * Barrier also required between aquiring a lock for a
+                * protected resource and accessing the resource. Inserted for
+                * same reason as above.
+                */
+               smp_mb();
+
+               if (type == TYPE_SWPB)
+                       swpbcounter++;
+               else
+                       swpcounter++;
+       }
+
+       return res;
+}
+
+/*
+ * swp_handler logs the id of calling process, dissects the instruction, sanity
+ * checks the memory location, calls emulate_swpX for the actual operation and
+ * deals with fixup/error handling before returning
+ */
+static int swp_handler(struct pt_regs *regs, unsigned int instr)
+{
+       unsigned int address, destreg, data, type;
+       unsigned int res = 0;
+
+       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, regs->ARM_pc);
+
+       if (current->pid != previous_pid) {
+               pr_debug("\"%s\" (%ld) uses deprecated SWP{B} instruction\n",
+                        current->comm, (unsigned long)current->pid);
+               previous_pid = current->pid;
+       }
+
+       address = regs->uregs[EXTRACT_REG_NUM(instr, RN_OFFSET)];
+       data    = regs->uregs[EXTRACT_REG_NUM(instr, RT2_OFFSET)];
+       destreg = EXTRACT_REG_NUM(instr, RT_OFFSET);
+
+       type = instr & TYPE_SWPB;
+
+       pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n",
+                EXTRACT_REG_NUM(instr, RN_OFFSET), address,
+                destreg, EXTRACT_REG_NUM(instr, RT2_OFFSET), data);
+
+       /* Check access in reasonable access range for both SWP and SWPB */
+       if (!access_ok(VERIFY_WRITE, (address & ~3), 4)) {
+               pr_debug("SWP{B} emulation: access to %p not allowed!\n",
+                        (void *)address);
+               res = -EFAULT;
+       } else {
+               res = emulate_swpX(address, &data, type);
+       }
+
+       if (res == 0) {
+               /*
+                * On successful emulation, revert the adjustment to the PC
+                * made in kernel/traps.c in order to resume execution at the
+                * instruction following the SWP{B}.
+                */
+               regs->ARM_pc += 4;
+               regs->uregs[destreg] = data;
+       } else if (res == -EFAULT) {
+               /*
+                * Memory errors do not mean emulation failed.
+                * Set up signal info to return SEGV, then return OK
+                */
+               set_segfault(regs, address);
+       }
+
+       return 0;
+}
+
+/*
+ * Only emulate SWP/SWPB executed in ARM state/User mode.
+ * The kernel must be SWP free and SWP{B} does not exist in Thumb/ThumbEE.
+ */
+static struct undef_hook swp_hook = {
+       .instr_mask = 0x0fb00ff0,
+       .instr_val  = 0x01000090,
+       .cpsr_mask  = MODE_MASK | PSR_T_BIT | PSR_J_BIT,
+       .cpsr_val   = USR_MODE,
+       .fn         = swp_handler
+};
+
+/*
+ * Register handler and create status file in /proc/cpu
+ * Invoked as late_initcall, since not needed before init spawned.
+ */
+static int __init swp_emulation_init(void)
+{
+#ifdef CONFIG_PROC_FS
+       struct proc_dir_entry *res;
+
+       res = create_proc_entry("cpu/swp_emulation", S_IRUGO, NULL);
+
+       if (!res)
+               return -ENOMEM;
+
+       res->read_proc = proc_read_status;
+#endif /* CONFIG_PROC_FS */
+
+       printk(KERN_NOTICE "Registering SWP/SWPB emulation handler\n");
+       register_undef_hook(&swp_hook);
+
+       return 0;
+}
+
+late_initcall(swp_emulation_init);
index 38c261f..f1e2eb1 100644 (file)
 #include <asm/leds.h>
 #include <asm/thread_info.h>
 #include <asm/stacktrace.h>
+#include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 /*
  * Our system timer.
  */
-struct sys_timer *system_timer;
+static struct sys_timer *system_timer;
 
 #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
 /* this needs a better home */
@@ -160,6 +161,7 @@ device_initcall(timer_init_sysfs);
 
 void __init time_init(void)
 {
+       system_timer = machine_desc->timer;
        system_timer->init();
 }
 
index 446aee9..e02f4f7 100644 (file)
@@ -37,6 +37,8 @@
 
 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
 
+void *vectors_page;
+
 #ifdef CONFIG_DEBUG_USER
 unsigned int user_debug;
 
@@ -756,7 +758,11 @@ static void __init kuser_get_tls_init(unsigned long vectors)
 
 void __init early_trap_init(void)
 {
+#if defined(CONFIG_CPU_USE_DOMAINS)
        unsigned long vectors = CONFIG_VECTORS_BASE;
+#else
+       unsigned long vectors = (unsigned long)vectors_page;
+#endif
        extern char __stubs_start[], __stubs_end[];
        extern char __vectors_start[], __vectors_end[];
        extern char __kuser_helper_start[], __kuser_helper_end[];
@@ -780,10 +786,10 @@ void __init early_trap_init(void)
         * Copy signal return handlers into the vector page, and
         * set sigreturn to be a pointer to these.
         */
-       memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
-              sizeof(sigreturn_codes));
-       memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
-              sizeof(syscall_restart_code));
+       memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
+              sigreturn_codes, sizeof(sigreturn_codes));
+       memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
+              syscall_restart_code, sizeof(syscall_restart_code));
 
        flush_icache_range(vectors, vectors + PAGE_SIZE);
        modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
index 897c1a8..86b66f3 100644 (file)
@@ -168,6 +168,7 @@ SECTIONS
 
                NOSAVE_DATA
                CACHELINE_ALIGNED_DATA(32)
+               READ_MOSTLY_DATA(32)
 
                /*
                 * The exception fixup table (might need resorting at runtime)
index b1631a7..1b049cd 100644 (file)
  */
 #include <linux/linkage.h>
 #include <asm/errno.h>
+#include <asm/domain.h>
 
 ENTRY(__get_user_1)
-1:     ldrbt   r2, [r0]
+1:     T(ldrb) r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__get_user_1)
 
 ENTRY(__get_user_2)
 #ifdef CONFIG_THUMB2_KERNEL
-2:     ldrbt   r2, [r0]
-3:     ldrbt   r3, [r0, #1]
+2:     T(ldrb) r2, [r0]
+3:     T(ldrb) r3, [r0, #1]
 #else
-2:     ldrbt   r2, [r0], #1
-3:     ldrbt   r3, [r0]
+2:     T(ldrb) r2, [r0], #1
+3:     T(ldrb) r3, [r0]
 #endif
 #ifndef __ARMEB__
        orr     r2, r2, r3, lsl #8
@@ -53,7 +54,7 @@ ENTRY(__get_user_2)
 ENDPROC(__get_user_2)
 
 ENTRY(__get_user_4)
-4:     ldrt    r2, [r0]
+4:     T(ldr)  r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__get_user_4)
index 5a01a23..c023fc1 100644 (file)
  */
 #include <linux/linkage.h>
 #include <asm/errno.h>
+#include <asm/domain.h>
 
 ENTRY(__put_user_1)
-1:     strbt   r2, [r0]
+1:     T(strb) r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__put_user_1)
@@ -39,19 +40,19 @@ ENTRY(__put_user_2)
        mov     ip, r2, lsr #8
 #ifdef CONFIG_THUMB2_KERNEL
 #ifndef __ARMEB__
-2:     strbt   r2, [r0]
-3:     strbt   ip, [r0, #1]
+2:     T(strb) r2, [r0]
+3:     T(strb) ip, [r0, #1]
 #else
-2:     strbt   ip, [r0]
-3:     strbt   r2, [r0, #1]
+2:     T(strb) ip, [r0]
+3:     T(strb) r2, [r0, #1]
 #endif
 #else  /* !CONFIG_THUMB2_KERNEL */
 #ifndef __ARMEB__
-2:     strbt   r2, [r0], #1
-3:     strbt   ip, [r0]
+2:     T(strb) r2, [r0], #1
+3:     T(strb) ip, [r0]
 #else
-2:     strbt   ip, [r0], #1
-3:     strbt   r2, [r0]
+2:     T(strb) ip, [r0], #1
+3:     T(strb) r2, [r0]
 #endif
 #endif /* CONFIG_THUMB2_KERNEL */
        mov     r0, #0
@@ -59,18 +60,18 @@ ENTRY(__put_user_2)
 ENDPROC(__put_user_2)
 
 ENTRY(__put_user_4)
-4:     strt    r2, [r0]
+4:     T(str)  r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__put_user_4)
 
 ENTRY(__put_user_8)
 #ifdef CONFIG_THUMB2_KERNEL
-5:     strt    r2, [r0]
-6:     strt    r3, [r0, #4]
+5:     T(str)  r2, [r0]
+6:     T(str)  r3, [r0, #4]
 #else
-5:     strt    r2, [r0], #4
-6:     strt    r3, [r0]
+5:     T(str)  r2, [r0], #4
+6:     T(str)  r3, [r0]
 #endif
        mov     r0, #0
        mov     pc, lr
index fee9f6f..d0ece2a 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/errno.h>
+#include <asm/domain.h>
 
                .text
 
                rsb     ip, ip, #4
                cmp     ip, #2
                ldrb    r3, [r1], #1
-USER(          strbt   r3, [r0], #1)                   @ May fault
+USER(          T(strb) r3, [r0], #1)                   @ May fault
                ldrgeb  r3, [r1], #1
-USER(          strgebt r3, [r0], #1)                   @ May fault
+USER(          T(strgeb) r3, [r0], #1)                 @ May fault
                ldrgtb  r3, [r1], #1
-USER(          strgtbt r3, [r0], #1)                   @ May fault
+USER(          T(strgtb) r3, [r0], #1)                 @ May fault
                sub     r2, r2, ip
                b       .Lc2u_dest_aligned
 
@@ -58,7 +59,7 @@ ENTRY(__copy_to_user)
                addmi   ip, r2, #4
                bmi     .Lc2u_0nowords
                ldr     r3, [r1], #4
-USER(          strt    r3, [r0], #4)                   @ May fault
+USER(          T(str)  r3, [r0], #4)                   @ May fault
                mov     ip, r0, lsl #32 - PAGE_SHIFT    @ On each page, use a ld/st??t instruction
                rsb     ip, ip, #0
                movs    ip, ip, lsr #32 - PAGE_SHIFT
@@ -87,18 +88,18 @@ USER(               strt    r3, [r0], #4)                   @ May fault
                stmneia r0!, {r3 - r4}                  @ Shouldnt fault
                tst     ip, #4
                ldrne   r3, [r1], #4
-               strnet  r3, [r0], #4                    @ Shouldnt fault
+               T(strne) r3, [r0], #4                   @ Shouldnt fault
                ands    ip, ip, #3
                beq     .Lc2u_0fupi
 .Lc2u_0nowords:        teq     ip, #0
                beq     .Lc2u_finished
 .Lc2u_nowords: cmp     ip, #2
                ldrb    r3, [r1], #1
-USER(          strbt   r3, [r0], #1)                   @ May fault
+USER(          T(strb) r3, [r0], #1)                   @ May fault
                ldrgeb  r3, [r1], #1
-USER(          strgebt r3, [r0], #1)                   @ May fault
+USER(          T(strgeb) r3, [r0], #1)                 @ May fault
                ldrgtb  r3, [r1], #1
-USER(          strgtbt r3, [r0], #1)                   @ May fault
+USER(          T(strgtb) r3, [r0], #1)                 @ May fault
                b       .Lc2u_finished
 
 .Lc2u_not_enough:
@@ -119,7 +120,7 @@ USER(               strgtbt r3, [r0], #1)                   @ May fault
                mov     r3, r7, pull #8
                ldr     r7, [r1], #4
                orr     r3, r3, r7, push #24
-USER(          strt    r3, [r0], #4)                   @ May fault
+USER(          T(str)  r3, [r0], #4)                   @ May fault
                mov     ip, r0, lsl #32 - PAGE_SHIFT
                rsb     ip, ip, #0
                movs    ip, ip, lsr #32 - PAGE_SHIFT
@@ -154,18 +155,18 @@ USER(             strt    r3, [r0], #4)                   @ May fault
                movne   r3, r7, pull #8
                ldrne   r7, [r1], #4
                orrne   r3, r3, r7, push #24
-               strnet  r3, [r0], #4                    @ Shouldnt fault
+               T(strne) r3, [r0], #4                   @ Shouldnt fault
                ands    ip, ip, #3
                beq     .Lc2u_1fupi
 .Lc2u_1nowords:        mov     r3, r7, get_byte_1
                teq     ip, #0
                beq     .Lc2u_finished
                cmp     ip, #2
-USER(          strbt   r3, [r0], #1)                   @ May fault
+USER(          T(strb) r3, [r0], #1)                   @ May fault
                movge   r3, r7, get_byte_2
-USER(          strgebt r3, [r0], #1)                   @ May fault
+USER(          T(strgeb) r3, [r0], #1)                 @ May fault
                movgt   r3, r7, get_byte_3
-USER(          strgtbt r3, [r0], #1)                   @ May fault
+USER(          T(strgtb) r3, [r0], #1)                 @ May fault
                b       .Lc2u_finished
 
 .Lc2u_2fupi:   subs    r2, r2, #4
@@ -174,7 +175,7 @@ USER(               strgtbt r3, [r0], #1)                   @ May fault
                mov     r3, r7, pull #16
                ldr     r7, [r1], #4
                orr     r3, r3, r7, push #16
-USER(          strt    r3, [r0], #4)                   @ May fault
+USER(          T(str)  r3, [r0], #4)                   @ May fault
                mov     ip, r0, lsl #32 - PAGE_SHIFT
                rsb     ip, ip, #0
                movs    ip, ip, lsr #32 - PAGE_SHIFT
@@ -209,18 +210,18 @@ USER(             strt    r3, [r0], #4)                   @ May fault
                movne   r3, r7, pull #16
                ldrne   r7, [r1], #4
                orrne   r3, r3, r7, push #16
-               strnet  r3, [r0], #4                    @ Shouldnt fault
+               T(strne) r3, [r0], #4                   @ Shouldnt fault
                ands    ip, ip, #3
                beq     .Lc2u_2fupi
 .Lc2u_2nowords:        mov     r3, r7, get_byte_2
                teq     ip, #0
                beq     .Lc2u_finished
                cmp     ip, #2
-USER(          strbt   r3, [r0], #1)                   @ May fault
+USER(          T(strb) r3, [r0], #1)                   @ May fault
                movge   r3, r7, get_byte_3
-USER(          strgebt r3, [r0], #1)                   @ May fault
+USER(          T(strgeb) r3, [r0], #1)                 @ May fault
                ldrgtb  r3, [r1], #0
-USER(          strgtbt r3, [r0], #1)                   @ May fault
+USER(          T(strgtb) r3, [r0], #1)                 @ May fault
                b       .Lc2u_finished
 
 .Lc2u_3fupi:   subs    r2, r2, #4
@@ -229,7 +230,7 @@ USER(               strgtbt r3, [r0], #1)                   @ May fault
                mov     r3, r7, pull #24
                ldr     r7, [r1], #4
                orr     r3, r3, r7, push #8
-USER(          strt    r3, [r0], #4)                   @ May fault
+USER(          T(str)  r3, [r0], #4)                   @ May fault
                mov     ip, r0, lsl #32 - PAGE_SHIFT
                rsb     ip, ip, #0
                movs    ip, ip, lsr #32 - PAGE_SHIFT
@@ -264,18 +265,18 @@ USER(             strt    r3, [r0], #4)                   @ May fault
                movne   r3, r7, pull #24
                ldrne   r7, [r1], #4
                orrne   r3, r3, r7, push #8
-               strnet  r3, [r0], #4                    @ Shouldnt fault
+               T(strne) r3, [r0], #4                   @ Shouldnt fault
                ands    ip, ip, #3
                beq     .Lc2u_3fupi
 .Lc2u_3nowords:        mov     r3, r7, get_byte_3
                teq     ip, #0
                beq     .Lc2u_finished
                cmp     ip, #2
-USER(          strbt   r3, [r0], #1)                   @ May fault
+USER(          T(strb) r3, [r0], #1)                   @ May fault
                ldrgeb  r3, [r1], #1
-USER(          strgebt r3, [r0], #1)                   @ May fault
+USER(          T(strgeb) r3, [r0], #1)                 @ May fault
                ldrgtb  r3, [r1], #0
-USER(          strgtbt r3, [r0], #1)                   @ May fault
+USER(          T(strgtb) r3, [r0], #1)                 @ May fault
                b       .Lc2u_finished
 ENDPROC(__copy_to_user)
 
@@ -294,11 +295,11 @@ ENDPROC(__copy_to_user)
 .Lcfu_dest_not_aligned:
                rsb     ip, ip, #4
                cmp     ip, #2
-USER(          ldrbt   r3, [r1], #1)                   @ May fault
+USER(          T(ldrb) r3, [r1], #1)                   @ May fault
                strb    r3, [r0], #1
-USER(          ldrgebt r3, [r1], #1)                   @ May fault
+USER(          T(ldrgeb) r3, [r1], #1)                 @ May fault
                strgeb  r3, [r0], #1
-USER(          ldrgtbt r3, [r1], #1)                   @ May fault
+USER(          T(ldrgtb) r3, [r1], #1)                 @ May fault
                strgtb  r3, [r0], #1
                sub     r2, r2, ip
                b       .Lcfu_dest_aligned
@@ -321,7 +322,7 @@ ENTRY(__copy_from_user)
 .Lcfu_0fupi:   subs    r2, r2, #4
                addmi   ip, r2, #4
                bmi     .Lcfu_0nowords
-USER(          ldrt    r3, [r1], #4)
+USER(          T(ldr)  r3, [r1], #4)
                str     r3, [r0], #4
                mov     ip, r1, lsl #32 - PAGE_SHIFT    @ On each page, use a ld/st??t instruction
                rsb     ip, ip, #0
@@ -350,18 +351,18 @@ USER(             ldrt    r3, [r1], #4)
                ldmneia r1!, {r3 - r4}                  @ Shouldnt fault
                stmneia r0!, {r3 - r4}
                tst     ip, #4
-               ldrnet  r3, [r1], #4                    @ Shouldnt fault
+               T(ldrne) r3, [r1], #4                   @ Shouldnt fault
                strne   r3, [r0], #4
                ands    ip, ip, #3
                beq     .Lcfu_0fupi
 .Lcfu_0nowords:        teq     ip, #0
                beq     .Lcfu_finished
 .Lcfu_nowords: cmp     ip, #2
-USER(          ldrbt   r3, [r1], #1)                   @ May fault
+USER(          T(ldrb) r3, [r1], #1)                   @ May fault
                strb    r3, [r0], #1
-USER(          ldrgebt r3, [r1], #1)                   @ May fault
+USER(          T(ldrgeb) r3, [r1], #1)                 @ May fault
                strgeb  r3, [r0], #1
-USER(          ldrgtbt r3, [r1], #1)                   @ May fault
+USER(          T(ldrgtb) r3, [r1], #1)                 @ May fault
                strgtb  r3, [r0], #1
                b       .Lcfu_finished
 
@@ -374,7 +375,7 @@ USER(               ldrgtbt r3, [r1], #1)                   @ May fault
 
 .Lcfu_src_not_aligned:
                bic     r1, r1, #3
-USER(          ldrt    r7, [r1], #4)                   @ May fault
+USER(          T(ldr)  r7, [r1], #4)                   @ May fault
                cmp     ip, #2
                bgt     .Lcfu_3fupi
                beq     .Lcfu_2fupi
@@ -382,7 +383,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                addmi   ip, r2, #4
                bmi     .Lcfu_1nowords
                mov     r3, r7, pull #8
-USER(          ldrt    r7, [r1], #4)                   @ May fault
+USER(          T(ldr)  r7, [r1], #4)                   @ May fault
                orr     r3, r3, r7, push #24
                str     r3, [r0], #4
                mov     ip, r1, lsl #32 - PAGE_SHIFT
@@ -417,7 +418,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                stmneia r0!, {r3 - r4}
                tst     ip, #4
                movne   r3, r7, pull #8
-USER(          ldrnet  r7, [r1], #4)                   @ May fault
+USER(          T(ldrne) r7, [r1], #4)                  @ May fault
                orrne   r3, r3, r7, push #24
                strne   r3, [r0], #4
                ands    ip, ip, #3
@@ -437,7 +438,7 @@ USER(               ldrnet  r7, [r1], #4)                   @ May fault
                addmi   ip, r2, #4
                bmi     .Lcfu_2nowords
                mov     r3, r7, pull #16
-USER(          ldrt    r7, [r1], #4)                   @ May fault
+USER(          T(ldr)  r7, [r1], #4)                   @ May fault
                orr     r3, r3, r7, push #16
                str     r3, [r0], #4
                mov     ip, r1, lsl #32 - PAGE_SHIFT
@@ -473,7 +474,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                stmneia r0!, {r3 - r4}
                tst     ip, #4
                movne   r3, r7, pull #16
-USER(          ldrnet  r7, [r1], #4)                   @ May fault
+USER(          T(ldrne) r7, [r1], #4)                  @ May fault
                orrne   r3, r3, r7, push #16
                strne   r3, [r0], #4
                ands    ip, ip, #3
@@ -485,7 +486,7 @@ USER(               ldrnet  r7, [r1], #4)                   @ May fault
                strb    r3, [r0], #1
                movge   r3, r7, get_byte_3
                strgeb  r3, [r0], #1
-USER(          ldrgtbt r3, [r1], #0)                   @ May fault
+USER(          T(ldrgtb) r3, [r1], #0)                 @ May fault
                strgtb  r3, [r0], #1
                b       .Lcfu_finished
 
@@ -493,7 +494,7 @@ USER(               ldrgtbt r3, [r1], #0)                   @ May fault
                addmi   ip, r2, #4
                bmi     .Lcfu_3nowords
                mov     r3, r7, pull #24
-USER(          ldrt    r7, [r1], #4)                   @ May fault
+USER(          T(ldr)  r7, [r1], #4)                   @ May fault
                orr     r3, r3, r7, push #8
                str     r3, [r0], #4
                mov     ip, r1, lsl #32 - PAGE_SHIFT
@@ -528,7 +529,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                stmneia r0!, {r3 - r4}
                tst     ip, #4
                movne   r3, r7, pull #24
-USER(          ldrnet  r7, [r1], #4)                   @ May fault
+USER(          T(ldrne) r7, [r1], #4)                  @ May fault
                orrne   r3, r3, r7, push #8
                strne   r3, [r0], #4
                ands    ip, ip, #3
@@ -538,9 +539,9 @@ USER(               ldrnet  r7, [r1], #4)                   @ May fault
                beq     .Lcfu_finished
                cmp     ip, #2
                strb    r3, [r0], #1
-USER(          ldrgebt r3, [r1], #1)                   @ May fault
+USER(          T(ldrgeb) r3, [r1], #1)                 @ May fault
                strgeb  r3, [r0], #1
-USER(          ldrgtbt r3, [r1], #1)                   @ May fault
+USER(          T(ldrgtb) r3, [r1], #1)                 @ May fault
                strgtb  r3, [r0], #1
                b       .Lcfu_finished
 ENDPROC(__copy_from_user)
index 14bafc3..ad237a4 100644 (file)
 #include <linux/string.h>
 #include <linux/clk.h>
 #include <linux/spinlock.h>
+#include <linux/clkdev.h>
 #include <mach/csp/hw_cfg.h>
 #include <mach/csp/chipcHw_def.h>
 #include <mach/csp/chipcHw_reg.h>
 #include <mach/csp/chipcHw_inline.h>
 
-#include <asm/clkdev.h>
-
 #include "clock.h"
 
 #define clk_is_primary(x)       ((x)->type & CLK_TYPE_PRIMARY)
index b91b1b0..8fc2035 100644 (file)
 #include <linux/amba/bus.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/clkdev.h>
 
 #include <mach/csp/mm_addr.h>
 #include <mach/hardware.h>
-#include <asm/clkdev.h>
 #include <linux/io.h>
 #include <asm/irq.h>
 #include <asm/hardware/arm_timer.h>
index 9ebfcc4..29b13f2 100644 (file)
@@ -3,6 +3,7 @@ menu "CNS3XXX platform type"
 
 config MACH_CNS3420VB
        bool "Support for CNS3420 Validation Board"
+       select MIGHT_HAVE_PCI
        help
          Include support for the Cavium Networks CNS3420 MPCore Platform
          Baseboard.
index 1109998..0dd2203 100644 (file)
@@ -68,7 +68,7 @@
 #ifndef __ASSEMBLER__
 
 #include <linux/list.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #define PLLSTAT_GOSTAT BIT(0)
 #define PLLCMD_GOSET   BIT(0)
index ef06c66..ca4de71 100644 (file)
 #include <linux/string.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
+#include <linux/clkdev.h>
 
 #include <mach/hardware.h>
 
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 
index daca30b..3938a56 100644 (file)
@@ -22,8 +22,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
index cf15ea5..d705655 100644 (file)
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 #define IO_ADDR_CCM(off)       (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off)))
index 98a25ba..ca1017b 100644 (file)
@@ -21,8 +21,8 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 #include <mach/clock.h>
index 27db275..769b0f1 100644 (file)
@@ -4,6 +4,7 @@ menu "Integrator Options"
 
 config ARCH_INTEGRATOR_AP
        bool "Support Integrator/AP and Integrator/PP2 platforms"
+       select MIGHT_HAVE_PCI
        help
          Include support for the ARM(R) Integrator/AP and
          Integrator/PP2 platforms.
index 8f4fb6d..b8e884b 100644 (file)
@@ -21,9 +21,8 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/serial.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
 #include <asm/irq.h>
index fd684bf..5db574f 100644 (file)
@@ -22,9 +22,8 @@
 #include <linux/amba/clcd.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
 #include <asm/hardware/icst.h>
 #include <mach/lm.h>
 #include <mach/impd1.h>
index 1713ecf..85e48a5 100644 (file)
@@ -21,9 +21,8 @@
 #include <linux/amba/mmci.h>
 #include <linux/io.h>
 #include <linux/gfp.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
 #include <asm/irq.h>
index 7415e43..3ad4553 100644 (file)
@@ -58,13 +58,13 @@ static inline unsigned long __lbus_to_virt(dma_addr_t x)
                __dma;                                                  \
        })
 
-#define __arch_page_to_dma(dev, page)                                  \
+#define __arch_pfn_to_dma(dev, pfn)                                    \
        ({                                                              \
                /* __is_lbus_virt() can never be true for RAM pages */  \
-               (dma_addr_t)page_to_phys(page);                         \
+               (dma_addr_t)__pfn_to_phys(pfn);                         \
        })
 
-#define __arch_dma_to_page(dev, addr)  phys_to_page(addr)
+#define __arch_dma_to_pfn(dev, addr)   __phys_to_pfn(addr)
 
 #endif /* CONFIG_ARCH_IOP13XX */
 #endif /* !ASSEMBLY */
index fe0c82e..f5c39a8 100644 (file)
@@ -4,6 +4,7 @@ menu "Kendin/Micrel KS8695 Implementations"
 
 config MACH_KS8695
        bool "KS8695 development board"
+       select MIGHT_HAVE_PCI
        help
          Say 'Y' here if you want your kernel to run on the original
          Kendin-Micrel KS8695 development board.
index ffa19aa..bace9a6 100644 (file)
@@ -35,17 +35,17 @@ extern struct bus_type platform_bus_type;
                                        __phys_to_virt(x) : __bus_to_virt(x)); })
 #define __arch_virt_to_dma(dev, x)     ({ is_lbus_device(dev) ? \
                                        (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); })
-#define __arch_page_to_dma(dev, x)     \
-       ({ dma_addr_t __dma = page_to_phys(page); \
+#define __arch_pfn_to_dma(dev, pfn)    \
+       ({ dma_addr_t __dma = __pfn_to_phys(pfn); \
           if (!is_lbus_device(dev)) \
                __dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \
           __dma; })
 
-#define __arch_dma_to_page(dev, x)     \
+#define __arch_dma_to_pfn(dev, x)      \
        ({ dma_addr_t __dma = x;                                \
           if (!is_lbus_device(dev))                            \
                __dma += PHYS_OFFSET - KS8695_PCIMEM_PA;        \
-          phys_to_page(__dma);                                 \
+          __phys_to_pfn(__dma);                                \
        })
 
 #endif
index 32d6379..da0e649 100644 (file)
 #include <linux/clk.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
+#include <linux/clkdev.h>
 
 #include <mach/hardware.h>
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
 #include <mach/platform.h>
 #include "clock.h"
 #include "common.h"
index 016ae94..9b027d7 100644 (file)
@@ -6,7 +6,7 @@
  *  published by the Free Software Foundation.
  */
 
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 struct clkops {
        void                    (*enable)(struct clk *);
index 3ff7bf5..a95f7b9 100644 (file)
@@ -31,9 +31,9 @@
 
 #include <asm/hardware/gic.h>
 
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-       gic_raise_softirq(mask, 1);
+       gic_raise_softirq(mask, ipi);
 }
 
 #endif
index 9e4a557..00dcb08 100644 (file)
@@ -21,8 +21,7 @@
 #include <linux/list.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
index 109e98f..1cd8b40 100644 (file)
@@ -23,8 +23,8 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 #include <mach/clock.h>
index 61e4a31..819dd80 100644 (file)
@@ -21,8 +21,7 @@
 #include <linux/list.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
index 8ac36d8..5975edb 100644 (file)
@@ -14,8 +14,8 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 #include <mach/hardware.h>
index 5c85075..9fab505 100644 (file)
@@ -2,12 +2,12 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
 
-#include <asm/clkdev.h>
 #include <asm/bug.h>
 #include <asm/div64.h>
 
index 89f793a..48a59f2 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/clk.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include "clock.h"
 
 /*
index 18e51be..4de1f1d 100644 (file)
@@ -10,7 +10,7 @@
  * the Free Software Foundation; either version 2 of the License.
  */
 
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 void nuc93x_clk_enable(struct clk *clk, int enable);
 void clks_register(struct clk_lookup *clks, size_t num);
index b8c7fb9..84ef704 100644 (file)
@@ -17,9 +17,9 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
 #include <asm/mach-types.h>
-#include <asm/clkdev.h>
 
 #include <plat/cpu.h>
 #include <plat/usb.h>
index ed8d330..ebb888f 100644 (file)
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
+#include <linux/clkdev.h>
 
 #include <plat/cpu.h>
 #include <plat/clock.h>
-#include <asm/clkdev.h>
 
 #include "clock.h"
 #include "prm.h"
index 6cee456..4976b93 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 #include <mach/omap4-common.h>
 
-static DECLARE_COMPLETION(cpu_killed);
-
 int platform_cpu_kill(unsigned int cpu)
 {
-       return wait_for_completion_timeout(&cpu_killed, 5000);
+       return 1;
 }
 
 /*
@@ -35,15 +32,6 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-       unsigned int this_cpu = hard_smp_processor_id();
-
-       if (cpu != this_cpu) {
-               pr_crit("platform_cpu_die running on %u, should be %u\n",
-                          this_cpu, cpu);
-               BUG();
-       }
-       pr_notice("CPU%u: shutdown\n", cpu);
-       complete(&cpu_killed);
        flush_cache_all();
        dsb();
 
index 9fbac2c..b66cfe8 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 #include <mach/hardware.h>
 #include <mach/omap4-common.h>
 /* SCU base address */
 static void __iomem *scu_base;
 
-/*
- * Use SCU config register to count number of cores
- */
-static inline unsigned int get_core_count(void)
-{
-       if (scu_base)
-               return scu_get_core_count(scu_base);
-       return 1;
-}
-
 static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       trace_hardirqs_off();
-
        /*
         * If any interrupts are already enabled for the primary
         * core (e.g. timer irq), then they will not have been enabled
@@ -76,7 +63,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));
+       smp_cross_call(cpumask_of(cpu), 1);
 
        /*
         * Now the secondary core is starting up let it run its
@@ -118,25 +105,9 @@ void __init smp_init_cpus(void)
        scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256);
        BUG_ON(!scu_base);
 
-       ncores = get_core_count();
-
-       for (i = 0; i < ncores; i++)
-               set_cpu_possible(i, true);
-}
-
-void __init smp_prepare_cpus(unsigned int max_cpus)
-{
-       unsigned int ncores = get_core_count();
-       unsigned int cpu = smp_processor_id();
-       int i;
+       ncores = scu_get_core_count(scu_base);
 
        /* sanity check */
-       if (ncores == 0) {
-               printk(KERN_ERR
-                      "OMAP4: strange core count of 0? Default to 1\n");
-               ncores = 1;
-       }
-
        if (ncores > NR_CPUS) {
                printk(KERN_WARNING
                       "OMAP4: no. of cores (%d) greater than configured "
@@ -144,13 +115,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
                       ncores, NR_CPUS);
                ncores = NR_CPUS;
        }
-       smp_store_cpu_info(cpu);
 
-       /*
-        * are we trying to boot more cores than exist?
-        */
-       if (max_cpus > ncores)
-               max_cpus = ncores;
+       for (i = 0; i < ncores; i++)
+               set_cpu_possible(i, true);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+       int i;
 
        /*
         * Initialise the present map, which describes the set of CPUs
@@ -159,18 +131,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        for (i = 0; i < max_cpus; i++)
                set_cpu_present(i, true);
 
-       if (max_cpus > 1) {
-               /*
-                * Enable the local timer or broadcast device for the
-                * boot CPU, but only if we have more than one CPU.
-                */
-               percpu_timer_setup();
-
-               /*
-                * Initialise the SCU and wake up the secondary core using
-                * wakeup_secondary().
-                */
-               scu_enable(scu_base);
-               wakeup_secondary();
-       }
+       /*
+        * Initialise the SCU and wake up the secondary core using
+        * wakeup_secondary().
+        */
+       scu_enable(scu_base);
+       wakeup_secondary();
 }
index 9d1975f..a4a3819 100644 (file)
@@ -21,8 +21,7 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/hardware.h>
 #include <mach/clock.h>
index c93e73d..c98d81f 100644 (file)
@@ -94,6 +94,7 @@ config MACH_ARMCORE
        select PXA27x
        select IWMMXT
        select PXA25x
+       select MIGHT_HAVE_PCI
 
 config MACH_EM_X270
        bool "CompuLab EM-x270 platform"
index abba008..4e4a84b 100644 (file)
@@ -11,8 +11,8 @@
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/hardware.h>
 
index d848874..12cc0e8 100644 (file)
@@ -1,4 +1,4 @@
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 struct clkops {
        void                    (*enable)(struct clk *);
index aad806c..1c6602c 100644 (file)
@@ -30,8 +30,8 @@
 #include <linux/ata_platform.h>
 #include <linux/amba/mmci.h>
 #include <linux/gfp.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
@@ -47,7 +47,6 @@
 
 #include <asm/hardware/gic.h>
 
-#include <mach/clkdev.h>
 #include <mach/platform.h>
 #include <mach/irqs.h>
 #include <asm/hardware/timer-sp.h>
index f95521a..a87523d 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 
 extern volatile int pen_release;
 
-static DECLARE_COMPLETION(cpu_killed);
-
 static inline void cpu_enter_lowpower(void)
 {
        unsigned int v;
@@ -34,10 +31,10 @@ static inline void cpu_enter_lowpower(void)
        "       bic     %0, %0, #0x20\n"
        "       mcr     p15, 0, %0, c1, c0, 1\n"
        "       mrc     p15, 0, %0, c1, c0, 0\n"
-       "       bic     %0, %0, #0x04\n"
+       "       bic     %0, %0, %2\n"
        "       mcr     p15, 0, %0, c1, c0, 0\n"
          : "=&r" (v)
-         : "r" (0)
+         : "r" (0), "Ir" (CR_C)
          : "cc");
 }
 
@@ -46,17 +43,17 @@ static inline void cpu_leave_lowpower(void)
        unsigned int v;
 
        asm volatile(   "mrc    p15, 0, %0, c1, c0, 0\n"
-       "       orr     %0, %0, #0x04\n"
+       "       orr     %0, %0, %1\n"
        "       mcr     p15, 0, %0, c1, c0, 0\n"
        "       mrc     p15, 0, %0, c1, c0, 1\n"
        "       orr     %0, %0, #0x20\n"
        "       mcr     p15, 0, %0, c1, c0, 1\n"
          : "=&r" (v)
-         :
+         : "Ir" (CR_C)
          : "cc");
 }
 
-static inline void platform_do_lowpower(unsigned int cpu)
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 {
        /*
         * there is no power-control hardware on this platform, so all
@@ -80,22 +77,19 @@ static inline void platform_do_lowpower(unsigned int cpu)
                }
 
                /*
-                * getting here, means that we have come out of WFI without
+                * Getting here, means that we have come out of WFI without
                 * having been woken up - this shouldn't happen
                 *
-                * The trouble is, letting people know about this is not really
-                * possible, since we are currently running incoherently, and
-                * therefore cannot safely call printk() or anything else
+                * Just note it happening - when we're woken, we can report
+                * its occurrence.
                 */
-#ifdef DEBUG
-               printk("CPU%u: spurious wakeup call\n", cpu);
-#endif
+               (*spurious)++;
        }
 }
 
 int platform_cpu_kill(unsigned int cpu)
 {
-       return wait_for_completion_timeout(&cpu_killed, 5000);
+       return 1;
 }
 
 /*
@@ -105,30 +99,22 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-#ifdef DEBUG
-       unsigned int this_cpu = hard_smp_processor_id();
-
-       if (cpu != this_cpu) {
-               printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
-                          this_cpu, cpu);
-               BUG();
-       }
-#endif
-
-       printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
-       complete(&cpu_killed);
+       int spurious = 0;
 
        /*
         * we're ready for shutdown now, so do it
         */
        cpu_enter_lowpower();
-       platform_do_lowpower(cpu);
+       platform_do_lowpower(cpu, &spurious);
 
        /*
         * bring this CPU back into the world of cache
         * coherency, and then restore interrupts
         */
        cpu_leave_lowpower();
+
+       if (spurious)
+               pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
 }
 
 int platform_cpu_disable(unsigned int cpu)
index d3cd265..c8221b3 100644 (file)
@@ -2,14 +2,13 @@
 #define ASMARM_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-       gic_raise_softirq(mask, 1);
+       gic_raise_softirq(mask, ipi);
 }
 
 #endif
index 6da8a2e..a22bf67 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/cacheflush.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/localtimer.h>
 #include <asm/unified.h>
 
 #include <mach/board-eb.h>
@@ -37,6 +36,19 @@ extern void realview_secondary_startup(void);
  */
 volatile int __cpuinitdata pen_release = -1;
 
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void write_pen_release(int val)
+{
+       pen_release = val;
+       smp_wmb();
+       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+       outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
 static void __iomem *scu_base_addr(void)
 {
        if (machine_is_realview_eb_mp())
@@ -50,20 +62,10 @@ static void __iomem *scu_base_addr(void)
                return (void __iomem *)0;
 }
 
-static inline unsigned int get_core_count(void)
-{
-       void __iomem *scu_base = scu_base_addr();
-       if (scu_base)
-               return scu_get_core_count(scu_base);
-       return 1;
-}
-
 static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       trace_hardirqs_off();
-
        /*
         * if any interrupts are already enabled for the primary
         * core (e.g. timer irq), then they will not have been enabled
@@ -75,8 +77,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
         * let the primary processor know we're out of the
         * pen, then head off into the C entry point
         */
-       pen_release = -1;
-       smp_wmb();
+       write_pen_release(-1);
 
        /*
         * Synchronise with the boot thread.
@@ -103,20 +104,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         * Note that "pen_release" is the hardware CPU ID, whereas
         * "cpu" is Linux's internal ID.
         */
-       pen_release = cpu;
-       flush_cache_all();
+       write_pen_release(cpu);
 
        /*
-        * XXX
-        *
-        * This is a later addition to the booting protocol: the
-        * bootMonitor now puts secondary cores into WFI, so
-        * poke_milo() no longer gets the cores moving; we need
-        * to send a soft interrupt to wake the secondary core.
-        * Use smp_cross_call() for this, since there's little
-        * point duplicating the code here
+        * Send the secondary CPU a soft interrupt, thereby causing
+        * the boot monitor to read the system wide flags register,
+        * and branch to the address found there.
         */
-       smp_cross_call(cpumask_of(cpu));
+       smp_cross_call(cpumask_of(cpu), 1);
 
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
@@ -136,48 +131,18 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
        return pen_release != -1 ? -ENOSYS : 0;
 }
 
-static void __init poke_milo(void)
-{
-       /* nobody is to be released from the pen yet */
-       pen_release = -1;
-
-       /*
-        * Write the address of secondary startup into the system-wide flags
-        * register. The BootMonitor waits for this register to become
-        * non-zero.
-        */
-       __raw_writel(BSYM(virt_to_phys(realview_secondary_startup)),
-                    __io_address(REALVIEW_SYS_FLAGSSET));
-
-       mb();
-}
-
 /*
  * Initialise the CPU possible map early - this describes the CPUs
  * which may be present or become present in the system.
  */
 void __init smp_init_cpus(void)
 {
-       unsigned int i, ncores = get_core_count();
+       void __iomem *scu_base = scu_base_addr();
+       unsigned int i, ncores;
 
-       for (i = 0; i < ncores; i++)
-               set_cpu_possible(i, true);
-}
-
-void __init smp_prepare_cpus(unsigned int max_cpus)
-{
-       unsigned int ncores = get_core_count();
-       unsigned int cpu = smp_processor_id();
-       int i;
+       ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
        /* sanity check */
-       if (ncores == 0) {
-               printk(KERN_ERR
-                      "Realview: strange CM count of 0? Default to 1\n");
-
-               ncores = 1;
-       }
-
        if (ncores > NR_CPUS) {
                printk(KERN_WARNING
                       "Realview: no. of cores (%d) greater than configured "
@@ -186,13 +151,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
                ncores = NR_CPUS;
        }
 
-       smp_store_cpu_info(cpu);
+       for (i = 0; i < ncores; i++)
+               set_cpu_possible(i, true);
+}
 
-       /*
-        * are we trying to boot more cores than exist?
-        */
-       if (max_cpus > ncores)
-               max_cpus = ncores;
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+       int i;
 
        /*
         * Initialise the present map, which describes the set of CPUs
@@ -201,21 +166,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        for (i = 0; i < max_cpus; i++)
                set_cpu_present(i, true);
 
+       scu_enable(scu_base_addr());
+
        /*
-        * Initialise the SCU if there are more than one CPU and let
-        * them know where to start. Note that, on modern versions of
-        * MILO, the "poke" doesn't actually do anything until each
-        * individual core is sent a soft interrupt to get it out of
-        * WFI
+        * Write the address of secondary startup into the
+        * system-wide flags register. The BootMonitor waits
+        * until it receives a soft interrupt, and then the
+        * secondary CPU branches to this address.
         */
-       if (max_cpus > 1) {
-               /*
-                * Enable the local timer or broadcast device for the
-                * boot CPU, but only if we have more than one CPU.
-                */
-               percpu_timer_setup();
-
-               scu_enable(scu_base_addr());
-               poke_milo();
-       }
+       __raw_writel(BSYM(virt_to_phys(realview_secondary_startup)),
+                    __io_address(REALVIEW_SYS_FLAGSSET));
 }
index 6983cb4..e82ab4a 100644 (file)
@@ -59,7 +59,7 @@ config MACH_JIVE
          Say Y here if you are using the Logitech Jive.
 
 config MACH_JIVE_SHOW_BOOTLOADER
-       bool "Allow access to bootloader partitions in MTD"
+       bool "Allow access to bootloader partitions in MTD (EXPERIMENTAL)"
        depends on MACH_JIVE && EXPERIMENTAL
 
 config MACH_SMDK2413
index 03652c3..afa5392 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 
 extern volatile int pen_release;
 
-static DECLARE_COMPLETION(cpu_killed);
-
 static inline void cpu_enter_lowpower(void)
 {
        unsigned int v;
@@ -33,13 +30,13 @@ static inline void cpu_enter_lowpower(void)
         * Turn off coherency
         */
        "       mrc     p15, 0, %0, c1, c0, 1\n"
-       "       bic     %0, %0, #0x20\n"
+       "       bic     %0, %0, %2\n"
        "       mcr     p15, 0, %0, c1, c0, 1\n"
        "       mrc     p15, 0, %0, c1, c0, 0\n"
        "       bic     %0, %0, #0x04\n"
        "       mcr     p15, 0, %0, c1, c0, 0\n"
          : "=&r" (v)
-         : "r" (0)
+         : "r" (0), "Ir" (CR_C)
          : "cc");
 }
 
@@ -49,17 +46,17 @@ static inline void cpu_leave_lowpower(void)
 
        asm volatile(
        "mrc    p15, 0, %0, c1, c0, 0\n"
-       "       orr     %0, %0, #0x04\n"
+       "       orr     %0, %0, %1\n"
        "       mcr     p15, 0, %0, c1, c0, 0\n"
        "       mrc     p15, 0, %0, c1, c0, 1\n"
        "       orr     %0, %0, #0x20\n"
        "       mcr     p15, 0, %0, c1, c0, 1\n"
          : "=&r" (v)
-         :
+         : "Ir" (CR_C)
          : "cc");
 }
 
-static inline void platform_do_lowpower(unsigned int cpu)
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 {
        /*
         * there is no power-control hardware on this platform, so all
@@ -83,22 +80,19 @@ static inline void platform_do_lowpower(unsigned int cpu)
                }
 
                /*
-                * getting here, means that we have come out of WFI without
+                * Getting here, means that we have come out of WFI without
                 * having been woken up - this shouldn't happen
                 *
-                * The trouble is, letting people know about this is not really
-                * possible, since we are currently running incoherently, and
-                * therefore cannot safely call printk() or anything else
+                * Just note it happening - when we're woken, we can report
+                * its occurrence.
                 */
-#ifdef DEBUG
-               printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
-#endif
+               (*spurious)++;
        }
 }
 
 int platform_cpu_kill(unsigned int cpu)
 {
-       return wait_for_completion_timeout(&cpu_killed, 5000);
+       return 1;
 }
 
 /*
@@ -108,30 +102,22 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-#ifdef DEBUG
-       unsigned int this_cpu = hard_smp_processor_id();
-
-       if (cpu != this_cpu) {
-               printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
-                          this_cpu, cpu);
-               BUG();
-       }
-#endif
-
-       printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
-       complete(&cpu_killed);
+       int spurious = 0;
 
        /*
         * we're ready for shutdown now, so do it
         */
        cpu_enter_lowpower();
-       platform_do_lowpower(cpu);
+       platform_do_lowpower(cpu, &spurious);
 
        /*
         * bring this CPU back into the world of cache
         * coherency, and then restore interrupts
         */
        cpu_leave_lowpower();
+
+       if (spurious)
+               pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
 }
 
 int platform_cpu_disable(unsigned int cpu)
index e1cc6a2..393ccbd 100644 (file)
@@ -7,14 +7,13 @@
 #define ASM_ARCH_SMP_H __FILE__
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-       gic_raise_softirq(mask, 1);
+       gic_raise_softirq(mask, ipi);
 }
 
 #endif
index 15929c1..34093b0 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 #include <asm/unified.h>
 
@@ -38,6 +37,19 @@ extern void s5pv310_secondary_startup(void);
 
 volatile int __cpuinitdata pen_release = -1;
 
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void write_pen_release(int val)
+{
+       pen_release = val;
+       smp_wmb();
+       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+       outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
 static void __iomem *scu_base_addr(void)
 {
        return (void __iomem *)(S5P_VA_SCU);
@@ -47,8 +59,6 @@ static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       trace_hardirqs_off();
-
        /*
         * if any interrupts are already enabled for the primary
         * core (e.g. timer irq), then they will not have been enabled
@@ -60,8 +70,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
         * let the primary processor know we're out of the
         * pen, then head off into the C entry point
         */
-       pen_release = -1;
-       smp_wmb();
+       write_pen_release(-1);
 
        /*
         * Synchronise with the boot thread.
@@ -88,16 +97,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         * Note that "pen_release" is the hardware CPU ID, whereas
         * "cpu" is Linux's internal ID.
         */
-       pen_release = cpu;
-       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-       outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+       write_pen_release(cpu);
 
        /*
         * Send the secondary CPU a soft interrupt, thereby causing
         * the boot monitor to read the system wide flags register,
         * and branch to the address found there.
         */
-       smp_cross_call(cpumask_of(cpu));
+       smp_cross_call(cpumask_of(cpu), 1);
 
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
@@ -130,13 +137,6 @@ void __init smp_init_cpus(void)
        ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
        /* sanity check */
-       if (ncores == 0) {
-               printk(KERN_ERR
-                      "S5PV310: strange CM count of 0? Default to 1\n");
-
-               ncores = 1;
-       }
-
        if (ncores > NR_CPUS) {
                printk(KERN_WARNING
                       "S5PV310: no. of cores (%d) greater than configured "
@@ -149,18 +149,10 @@ void __init smp_init_cpus(void)
                set_cpu_possible(i, true);
 }
 
-void __init smp_prepare_cpus(unsigned int max_cpus)
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-       unsigned int ncores = num_possible_cpus();
-       unsigned int cpu = smp_processor_id();
        int i;
 
-       smp_store_cpu_info(cpu);
-
-       /* are we trying to boot more cores than exist? */
-       if (max_cpus > ncores)
-               max_cpus = ncores;
-
        /*
         * Initialise the present map, which describes the set of CPUs
         * actually populated at the present time.
@@ -168,25 +160,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        for (i = 0; i < max_cpus; i++)
                set_cpu_present(i, true);
 
+       scu_enable(scu_base_addr());
+
        /*
-        * Initialise the SCU if there are more than one CPU and let
-        * them know where to start.
+        * Write the address of secondary startup into the
+        * system-wide flags register. The boot monitor waits
+        * until it receives a soft interrupt, and then the
+        * secondary CPU branches to this address.
         */
-       if (max_cpus > 1) {
-               /*
-                * Enable the local timer or broadcast device for the
-                * boot CPU, but only if we have more than one CPU.
-                */
-               percpu_timer_setup();
-
-               scu_enable(scu_base_addr());
-
-               /*
-                * Write the address of secondary startup into the
-                * system-wide flags register. The boot monitor waits
-                * until it receives a soft interrupt, and then the
-                * secondary CPU branches to this address.
-                */
        __raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_VA_SYSRAM);
-       }
 }
index 51dcd59..6329333 100644 (file)
@@ -6,7 +6,7 @@ config ARCH_SH7367
        bool "SH-Mobile G3 (SH7367)"
        select CPU_V6
        select HAVE_CLK
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select SH_CLK_CPG
        select GENERIC_CLOCKEVENTS
 
@@ -14,7 +14,7 @@ config ARCH_SH7377
        bool "SH-Mobile G4 (SH7377)"
        select CPU_V7
        select HAVE_CLK
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select SH_CLK_CPG
        select GENERIC_CLOCKEVENTS
 
@@ -22,7 +22,7 @@ config ARCH_SH7372
        bool "SH-Mobile AP4 (SH7372)"
        select CPU_V7
        select HAVE_CLK
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select SH_CLK_CPG
        select GENERIC_CLOCKEVENTS
 
index 9f78729..6b186ae 100644 (file)
@@ -20,8 +20,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/sh_clk.h>
+#include <linux/clkdev.h>
 #include <mach/common.h>
-#include <asm/clkdev.h>
 
 /* SH7367 registers */
 #define RTFRQCR    0xe6150000
index 3aa0260..d98deb4 100644 (file)
@@ -20,8 +20,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/sh_clk.h>
+#include <linux/clkdev.h>
 #include <mach/common.h>
-#include <asm/clkdev.h>
 
 /* SH7372 registers */
 #define FRQCRA         0xe6150000
index f91395a..9594246 100644 (file)
@@ -20,8 +20,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/sh_clk.h>
+#include <linux/clkdev.h>
 #include <mach/common.h>
-#include <asm/clkdev.h>
 
 /* SH7377 registers */
 #define RTFRQCR    0xe6150000
index ba32a15..3970a9c 100644 (file)
@@ -12,8 +12,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/irqs.h>
index ae19f95..77948e0 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/slab.h>
 #include <linux/seq_file.h>
 #include <linux/regulator/consumer.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include "clock.h"
 #include "board.h"
index 94fd859..083a4cf 100644 (file)
@@ -21,7 +21,7 @@
 #define __MACH_TEGRA_CLOCK_H
 
 #include <linux/list.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #define DIV_BUS                        (1 << 0)
 #define DIV_U71                        (1 << 1)
index 8e7f115..a5cb1ce 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 
-static DECLARE_COMPLETION(cpu_killed);
-
 static inline void cpu_enter_lowpower(void)
 {
        unsigned int v;
@@ -29,13 +26,13 @@ static inline void cpu_enter_lowpower(void)
         * Turn off coherency
         */
        "       mrc     p15, 0, %0, c1, c0, 1\n"
-       "       bic     %0, %0, #0x20\n"
+       "       bic     %0, %0, %2\n"
        "       mcr     p15, 0, %0, c1, c0, 1\n"
        "       mrc     p15, 0, %0, c1, c0, 0\n"
        "       bic     %0, %0, #0x04\n"
        "       mcr     p15, 0, %0, c1, c0, 0\n"
          : "=&r" (v)
-         : "r" (0)
+         : "r" (0), "Ir" (CR_C)
          : "cc");
 }
 
@@ -45,17 +42,17 @@ static inline void cpu_leave_lowpower(void)
 
        asm volatile(
        "mrc    p15, 0, %0, c1, c0, 0\n"
-       "       orr     %0, %0, #0x04\n"
+       "       orr     %0, %0, %1\n"
        "       mcr     p15, 0, %0, c1, c0, 0\n"
        "       mrc     p15, 0, %0, c1, c0, 1\n"
        "       orr     %0, %0, #0x20\n"
        "       mcr     p15, 0, %0, c1, c0, 1\n"
          : "=&r" (v)
-         :
+         : "Ir" (CR_C)
          : "cc");
 }
 
-static inline void platform_do_lowpower(unsigned int cpu)
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 {
        /*
         * there is no power-control hardware on this platform, so all
@@ -79,22 +76,19 @@ static inline void platform_do_lowpower(unsigned int cpu)
                /*}*/
 
                /*
-                * getting here, means that we have come out of WFI without
+                * Getting here, means that we have come out of WFI without
                 * having been woken up - this shouldn't happen
                 *
-                * The trouble is, letting people know about this is not really
-                * possible, since we are currently running incoherently, and
-                * therefore cannot safely call printk() or anything else
+                * Just note it happening - when we're woken, we can report
+                * its occurrence.
                 */
-#ifdef DEBUG
-               printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
-#endif
+               (*spurious)++;
        }
 }
 
 int platform_cpu_kill(unsigned int cpu)
 {
-       return wait_for_completion_timeout(&cpu_killed, 5000);
+       return 1;
 }
 
 /*
@@ -104,30 +98,22 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-#ifdef DEBUG
-       unsigned int this_cpu = hard_smp_processor_id();
-
-       if (cpu != this_cpu) {
-               printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
-                          this_cpu, cpu);
-               BUG();
-       }
-#endif
-
-       printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
-       complete(&cpu_killed);
+       int spurious = 0;
 
        /*
         * we're ready for shutdown now, so do it
         */
        cpu_enter_lowpower();
-       platform_do_lowpower(cpu);
+       platform_do_lowpower(cpu, &spurious);
 
        /*
         * bring this CPU back into the world of cache
         * coherency, and then restore interrupts
         */
        cpu_leave_lowpower();
+
+       if (spurious)
+               pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
 }
 
 int platform_cpu_disable(unsigned int cpu)
index e4a34a3..c8221b3 100644 (file)
@@ -2,21 +2,13 @@
 #define ASMARM_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
-{
-       gic_raise_softirq(mask, 1);
-}
-
-/*
- * Do nothing on MPcore.
- */
-static inline void smp_cross_call_done(cpumask_t callmap)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
+       gic_raise_softirq(mask, ipi);
 }
 
 #endif
index 3b7376c..ec1f689 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/cacheflush.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 
 #include <mach/iomap.h>
@@ -41,8 +40,6 @@ static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       trace_hardirqs_off();
-
        /*
         * if any interrupts are already enabled for the primary
         * core (e.g. timer irq), then they will not have been enabled
@@ -117,24 +114,20 @@ void __init smp_init_cpus(void)
 {
        unsigned int i, ncores = scu_get_core_count(scu_base);
 
+       if (ncores > NR_CPUS) {
+               printk(KERN_ERR "Tegra: no. of cores (%u) greater than configured (%u), clipping\n",
+                       ncores, NR_CPUS);
+               ncores = NR_CPUS;
+       }
+
        for (i = 0; i < ncores; i++)
                cpu_set(i, cpu_possible_map);
 }
 
-void __init smp_prepare_cpus(unsigned int max_cpus)
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-       unsigned int ncores = scu_get_core_count(scu_base);
-       unsigned int cpu = smp_processor_id();
        int i;
 
-       smp_store_cpu_info(cpu);
-
-       /*
-        * are we trying to boot more cores than exist?
-        */
-       if (max_cpus > ncores)
-               max_cpus = ncores;
-
        /*
         * Initialise the present map, which describes the set of CPUs
         * actually populated at the present time.
@@ -142,15 +135,5 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        for (i = 0; i < max_cpus; i++)
                set_cpu_present(i, true);
 
-       /*
-        * Initialise the SCU if there are more than one CPU and let
-        * them know where to start. Note that, on modern versions of
-        * MILO, the "poke" doesn't actually do anything until each
-        * individual core is sent a soft interrupt to get it out of
-        * WFI
-        */
-       if (max_cpus > 1) {
-               percpu_timer_setup();
-               scu_enable(scu_base);
-       }
+       scu_enable(scu_base);
 }
index ae3b308..f0dae6d 100644 (file)
@@ -24,8 +24,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/hrtimer.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/iomap.h>
 
index 7458fc6..fabcc49 100644 (file)
@@ -25,8 +25,8 @@
 #include <linux/timer.h>
 #include <linux/io.h>
 #include <linux/seq_file.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <mach/hardware.h>
 #include <mach/syscon.h>
 
index 1675047..531de5c 100644 (file)
@@ -13,8 +13,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <plat/mtu.h>
 #include <mach/hardware.h>
index a6be2cd..64fa451 100644 (file)
@@ -23,7 +23,6 @@ ENTRY(u8500_secondary_startup)
        ldmia   r4, {r5, r6}
        sub     r4, r4, r5
        add     r6, r6, r4
-       dsb
 pen:   ldr     r7, [r6]
        cmp     r7, r0
        bne     pen
index b782a03..dd8037e 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 
 extern volatile int pen_release;
 
-static DECLARE_COMPLETION(cpu_killed);
-
 static inline void platform_do_lowpower(unsigned int cpu)
 {
        flush_cache_all();
@@ -38,7 +35,7 @@ static inline void platform_do_lowpower(unsigned int cpu)
 
 int platform_cpu_kill(unsigned int cpu)
 {
-       return wait_for_completion_timeout(&cpu_killed, 5000);
+       return 1;
 }
 
 /*
@@ -48,19 +45,6 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-#ifdef DEBUG
-       unsigned int this_cpu = hard_smp_processor_id();
-
-       if (cpu != this_cpu) {
-               printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
-                          this_cpu, cpu);
-               BUG();
-       }
-#endif
-
-       printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
-       complete(&cpu_killed);
-
        /* directly enter low power state, skipping secure registers */
        platform_do_lowpower(cpu);
 }
index 197e841..ca2b15b 100644 (file)
@@ -10,7 +10,6 @@
 #define ASMARM_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /* This is required to wakeup the secondary core */
 extern void u8500_secondary_startup(void);
@@ -18,8 +17,8 @@ extern void u8500_secondary_startup(void);
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-       gic_raise_softirq(mask, 1);
+       gic_raise_softirq(mask, ipi);
 }
 #endif
index b5077b4..2115a0c 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 #include <mach/hardware.h>
 
  */
 volatile int __cpuinitdata pen_release = -1;
 
-static unsigned int __init get_core_count(void)
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void write_pen_release(int val)
 {
-       return scu_get_core_count(__io_address(UX500_SCU_BASE));
+       pen_release = val;
+       smp_wmb();
+       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+       outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
 }
 
 static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       trace_hardirqs_off();
-
        /*
         * if any interrupts are already enabled for the primary
         * core (e.g. timer irq), then they will not have been enabled
@@ -50,7 +55,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
         * let the primary processor know we're out of the
         * pen, then head off into the C entry point
         */
-       pen_release = -1;
+       write_pen_release(-1);
 
        /*
         * Synchronise with the boot thread.
@@ -74,11 +79,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         * the holding pen - release it, then wait for it to flag
         * that it has been released by resetting pen_release.
         */
-       pen_release = cpu;
-       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-       outer_clean_range(__pa(&pen_release), __pa(&pen_release) + 1);
+       write_pen_release(cpu);
 
-       smp_cross_call(cpumask_of(cpu));
+       smp_cross_call(cpumask_of(cpu), 1);
 
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
@@ -97,9 +100,6 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 static void __init wakeup_secondary(void)
 {
-       /* nobody is to be released from the pen yet */
-       pen_release = -1;
-
        /*
         * write the address of secondary startup into the backup ram register
         * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the
@@ -126,40 +126,26 @@ static void __init wakeup_secondary(void)
  */
 void __init smp_init_cpus(void)
 {
-       unsigned int i, ncores = get_core_count();
+       unsigned int i, ncores;
 
-       for (i = 0; i < ncores; i++)
-               set_cpu_possible(i, true);
-}
-
-void __init smp_prepare_cpus(unsigned int max_cpus)
-{
-       unsigned int ncores = get_core_count();
-       unsigned int cpu = smp_processor_id();
-       int i;
+       ncores = scu_get_core_count(__io_address(UX500_SCU_BASE));
 
        /* sanity check */
-       if (ncores == 0) {
-               printk(KERN_ERR
-                      "U8500: strange CM count of 0? Default to 1\n");
-               ncores = 1;
-       }
-
-       if (ncores > num_possible_cpus())       {
+       if (ncores > NR_CPUS) {
                printk(KERN_WARNING
                       "U8500: no. of cores (%d) greater than configured "
                       "maximum of %d - clipping\n",
-                      ncores, num_possible_cpus());
-               ncores = num_possible_cpus();
+                      ncores, NR_CPUS);
+               ncores = NR_CPUS;
        }
 
-       smp_store_cpu_info(cpu);
+       for (i = 0; i < ncores; i++)
+               set_cpu_possible(i, true);
+}
 
-       /*
-        * are we trying to boot more cores than exist?
-        */
-       if (max_cpus > ncores)
-               max_cpus = ncores;
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+       int i;
 
        /*
         * Initialise the present map, which describes the set of CPUs
@@ -168,13 +154,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        for (i = 0; i < max_cpus; i++)
                set_cpu_present(i, true);
 
-       if (max_cpus > 1) {
-               /*
-                * Enable the local timer or broadcast device for the
-                * boot CPU, but only if we have more than one CPU.
-                */
-               percpu_timer_setup();
-               scu_enable(__io_address(UX500_SCU_BASE));
-               wakeup_secondary();
-       }
+       scu_enable(__io_address(UX500_SCU_BASE));
+       wakeup_secondary();
 }
index c781f30..3f7b5e9 100644 (file)
@@ -4,6 +4,7 @@ menu "Versatile platform type"
 config ARCH_VERSATILE_PB
        bool "Support Versatile/PB platform"
        select CPU_ARM926T
+       select MIGHT_HAVE_PCI
        default y
        help
          Include support for the ARM(R) Versatile/PB platform.
index 40a024c..13a83e4 100644 (file)
@@ -31,8 +31,8 @@
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
 #include <linux/gfp.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/leds.h>
@@ -46,7 +46,6 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/clkdev.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
 #include <asm/hardware/timer-sp.h>
index 1b71b77..2c0ac7d 100644 (file)
@@ -5,4 +5,5 @@
 obj-y                                  := v2m.o
 obj-$(CONFIG_ARCH_VEXPRESS_CA9X4)      += ct-ca9x4.o
 obj-$(CONFIG_SMP)                      += platsmp.o headsmp.o
+obj-$(CONFIG_HOTPLUG_CPU)              += hotplug.o
 obj-$(CONFIG_LOCAL_TIMERS)             += localtimer.o
index cb5793e..e628402 100644 (file)
@@ -8,8 +8,8 @@
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/pgtable.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -18,7 +18,6 @@
 #include <asm/pmu.h>
 #include <asm/smp_twd.h>
 
-#include <mach/clkdev.h>
 #include <mach/ct-ca9x4.h>
 
 #include <asm/hardware/timer-sp.h>
diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c
new file mode 100644 (file)
index 0000000..ea4cbfb
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ *  linux/arch/arm/mach-realview/hotplug.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  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 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+
+extern volatile int pen_release;
+
+static inline void cpu_enter_lowpower(void)
+{
+       unsigned int v;
+
+       flush_cache_all();
+       asm volatile(
+               "mcr    p15, 0, %1, c7, c5, 0\n"
+       "       mcr     p15, 0, %1, c7, c10, 4\n"
+       /*
+        * Turn off coherency
+        */
+       "       mrc     p15, 0, %0, c1, c0, 1\n"
+       "       bic     %0, %0, %3\n"
+       "       mcr     p15, 0, %0, c1, c0, 1\n"
+       "       mrc     p15, 0, %0, c1, c0, 0\n"
+       "       bic     %0, %0, %2\n"
+       "       mcr     p15, 0, %0, c1, c0, 0\n"
+         : "=&r" (v)
+         : "r" (0), "Ir" (CR_C), "Ir" (0x40)
+         : "cc");
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+       unsigned int v;
+
+       asm volatile(
+               "mrc    p15, 0, %0, c1, c0, 0\n"
+       "       orr     %0, %0, %1\n"
+       "       mcr     p15, 0, %0, c1, c0, 0\n"
+       "       mrc     p15, 0, %0, c1, c0, 1\n"
+       "       orr     %0, %0, %2\n"
+       "       mcr     p15, 0, %0, c1, c0, 1\n"
+         : "=&r" (v)
+         : "Ir" (CR_C), "Ir" (0x40)
+         : "cc");
+}
+
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+{
+       /*
+        * there is no power-control hardware on this platform, so all
+        * we can do is put the core into WFI; this is safe as the calling
+        * code will have already disabled interrupts
+        */
+       for (;;) {
+               /*
+                * here's the WFI
+                */
+               asm(".word      0xe320f003\n"
+                   :
+                   :
+                   : "memory", "cc");
+
+               if (pen_release == cpu) {
+                       /*
+                        * OK, proper wakeup, we're done
+                        */
+                       break;
+               }
+
+               /*
+                * Getting here, means that we have come out of WFI without
+                * having been woken up - this shouldn't happen
+                *
+                * Just note it happening - when we're woken, we can report
+                * its occurrence.
+                */
+               (*spurious)++;
+       }
+}
+
+int platform_cpu_kill(unsigned int cpu)
+{
+       return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+       int spurious = 0;
+
+       /*
+        * we're ready for shutdown now, so do it
+        */
+       cpu_enter_lowpower();
+       platform_do_lowpower(cpu, &spurious);
+
+       /*
+        * bring this CPU back into the world of cache
+        * coherency, and then restore interrupts
+        */
+       cpu_leave_lowpower();
+
+       if (spurious)
+               pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+       /*
+        * we don't allow CPU 0 to be shutdown (it is still too special
+        * e.g. clock tick interrupts)
+        */
+       return cpu == 0 ? -EPERM : 0;
+}
index 5a6da4f..4c05e4a 100644 (file)
@@ -2,13 +2,12 @@
 #define __MACH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-       gic_raise_softirq(mask, 1);
+       gic_raise_softirq(mask, ipi);
 }
 #endif
index dfb5910..b1687b6 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 #include <asm/unified.h>
 
@@ -35,6 +34,19 @@ extern void vexpress_secondary_startup(void);
  */
 volatile int __cpuinitdata pen_release = -1;
 
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void write_pen_release(int val)
+{
+       pen_release = val;
+       smp_wmb();
+       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+       outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
 static void __iomem *scu_base_addr(void)
 {
        return MMIO_P2V(A9_MPCORE_SCU);
@@ -44,8 +56,6 @@ static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       trace_hardirqs_off();
-
        /*
         * if any interrupts are already enabled for the primary
         * core (e.g. timer irq), then they will not have been enabled
@@ -57,8 +67,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
         * let the primary processor know we're out of the
         * pen, then head off into the C entry point
         */
-       pen_release = -1;
-       smp_wmb();
+       write_pen_release(-1);
 
        /*
         * Synchronise with the boot thread.
@@ -83,16 +92,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         * since we haven't sent them a soft interrupt, they shouldn't
         * be there.
         */
-       pen_release = cpu;
-       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-       outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+       write_pen_release(cpu);
 
        /*
         * Send the secondary CPU a soft interrupt, thereby causing
         * the boot monitor to read the system wide flags register,
         * and branch to the address found there.
         */
-       smp_cross_call(cpumask_of(cpu));
+       smp_cross_call(cpumask_of(cpu), 1);
 
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
@@ -124,13 +131,6 @@ void __init smp_init_cpus(void)
        ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
        /* sanity check */
-       if (ncores == 0) {
-               printk(KERN_ERR
-                      "vexpress: strange CM count of 0? Default to 1\n");
-
-               ncores = 1;
-       }
-
        if (ncores > NR_CPUS) {
                printk(KERN_WARNING
                       "vexpress: no. of cores (%d) greater than configured "
@@ -143,20 +143,10 @@ void __init smp_init_cpus(void)
                set_cpu_possible(i, true);
 }
 
-void __init smp_prepare_cpus(unsigned int max_cpus)
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-       unsigned int ncores = num_possible_cpus();
-       unsigned int cpu = smp_processor_id();
        int i;
 
-       smp_store_cpu_info(cpu);
-
-       /*
-        * are we trying to boot more cores than exist?
-        */
-       if (max_cpus > ncores)
-               max_cpus = ncores;
-
        /*
         * Initialise the present map, which describes the set of CPUs
         * actually populated at the present time.
@@ -164,27 +154,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        for (i = 0; i < max_cpus; i++)
                set_cpu_present(i, true);
 
+       scu_enable(scu_base_addr());
+
        /*
-        * Initialise the SCU if there are more than one CPU and let
-        * them know where to start.
+        * Write the address of secondary startup into the
+        * system-wide flags register. The boot monitor waits
+        * until it receives a soft interrupt, and then the
+        * secondary CPU branches to this address.
         */
-       if (max_cpus > 1) {
-               /*
-                * Enable the local timer or broadcast device for the
-                * boot CPU, but only if we have more than one CPU.
-                */
-               percpu_timer_setup();
-
-               scu_enable(scu_base_addr());
-
-               /*
-                * Write the address of secondary startup into the
-                * system-wide flags register. The boot monitor waits
-                * until it receives a soft interrupt, and then the
-                * secondary CPU branches to this address.
-                */
-               writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR));
-               writel(BSYM(virt_to_phys(vexpress_secondary_startup)),
-                       MMIO_P2V(V2M_SYS_FLAGSSET));
-       }
+       writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR));
+       writel(BSYM(virt_to_phys(vexpress_secondary_startup)),
+               MMIO_P2V(V2M_SYS_FLAGSSET));
 }
index de13603..a9ed342 100644 (file)
@@ -11,8 +11,8 @@
 #include <linux/spinlock.h>
 #include <linux/sysdev.h>
 #include <linux/usb/isp1760.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/sizes.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
@@ -20,7 +20,6 @@
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/timer-sp.h>
 
-#include <mach/clkdev.h>
 #include <mach/motherboard.h>
 
 #include <plat/sched_clock.h>
index c56ddab..b88a1b1 100644 (file)
@@ -10,7 +10,7 @@
  * the Free Software Foundation; either version 2 of the License.
  */
 
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 void nuc900_clk_enable(struct clk *clk, int enable);
 void nuc900_subclk_enable(struct clk *clk, int enable);
index 4414a01..8493ed0 100644 (file)
@@ -599,6 +599,14 @@ config CPU_CP15_MPU
        help
          Processor has the CP15 register, which has MPU related registers.
 
+config CPU_USE_DOMAINS
+       bool
+       depends on MMU
+       default y if !CPU_32v6K
+       help
+         This option enables or disables the use of domain switching
+         via the set_fs() function.
+
 #
 # CPU supports 36-bit I/O
 #
@@ -628,6 +636,33 @@ config ARM_THUMBEE
          Say Y here if you have a CPU with the ThumbEE extension and code to
          make use of it. Say N for code that can run on CPUs without ThumbEE.
 
+config SWP_EMULATE
+       bool "Emulate SWP/SWPB instructions"
+       depends on CPU_V7
+       select HAVE_PROC_CPU if PROC_FS
+       default y if SMP
+       help
+         ARMv6 architecture deprecates use of the SWP/SWPB instructions.
+         ARMv7 multiprocessing extensions introduce the ability to disable
+         these instructions, triggering an undefined instruction exception
+         when executed. Say Y here to enable software emulation of these
+         instructions for userspace (not kernel) using LDREX/STREX.
+         Also creates /proc/cpu/swp_emulation for statistics.
+
+         In some older versions of glibc [<=2.8] SWP is used during futex
+         trylock() operations with the assumption that the code will not
+         be preempted. This invalid assumption may be more likely to fail
+         with SWP emulation enabled, leading to deadlock of the user
+         application.
+
+         NOTE: when accessing uncached shared regions, LDREX/STREX rely
+         on an external transaction monitoring block called a global
+         monitor to maintain update atomicity. If your system does not
+         implement a global monitor, this option can cause programs that
+         perform SWP operations to uncached memory to deadlock.
+
+         If unsure, say Y.
+
 config CPU_BIG_ENDIAN
        bool "Build big-endian kernel"
        depends on ARCH_SUPPORTS_BIG_ENDIAN
index 809f1bf..6b48e0a 100644 (file)
@@ -312,7 +312,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
                addr = page_address(page);
 
        if (addr)
-               *handle = page_to_dma(dev, page);
+               *handle = pfn_to_dma(dev, page_to_pfn(page));
 
        return addr;
 }
@@ -407,7 +407,7 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
        if (!arch_is_coherent())
                __dma_free_remap(cpu_addr, size);
 
-       __dma_free_buffer(dma_to_page(dev, handle), size);
+       __dma_free_buffer(pfn_to_page(dma_to_pfn(dev, handle)), size);
 }
 EXPORT_SYMBOL(dma_free_coherent);
 
@@ -555,17 +555,20 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
        struct scatterlist *s;
        int i, j;
 
+       BUG_ON(!valid_dma_direction(dir));
+
        for_each_sg(sg, s, nents, i) {
-               s->dma_address = dma_map_page(dev, sg_page(s), s->offset,
+               s->dma_address = __dma_map_page(dev, sg_page(s), s->offset,
                                                s->length, dir);
                if (dma_mapping_error(dev, s->dma_address))
                        goto bad_mapping;
        }
+       debug_dma_map_sg(dev, sg, nents, nents, dir);
        return nents;
 
  bad_mapping:
        for_each_sg(sg, s, i, j)
-               dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+               __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
        return 0;
 }
 EXPORT_SYMBOL(dma_map_sg);
@@ -586,8 +589,10 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
        struct scatterlist *s;
        int i;
 
+       debug_dma_unmap_sg(dev, sg, nents, dir);
+
        for_each_sg(sg, s, nents, i)
-               dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+               __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
 }
 EXPORT_SYMBOL(dma_unmap_sg);
 
@@ -612,6 +617,8 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
                __dma_page_dev_to_cpu(sg_page(s), s->offset,
                                      s->length, dir);
        }
+
+       debug_dma_sync_sg_for_cpu(dev, sg, nents, dir);
 }
 EXPORT_SYMBOL(dma_sync_sg_for_cpu);
 
@@ -636,5 +643,16 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
                __dma_page_cpu_to_dev(sg_page(s), s->offset,
                                      s->length, dir);
        }
+
+       debug_dma_sync_sg_for_device(dev, sg, nents, dir);
 }
 EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+#define PREALLOC_DMA_DEBUG_ENTRIES     4096
+
+static int __init dma_debug_do_init(void)
+{
+       dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+       return 0;
+}
+fs_initcall(dma_debug_do_init);
index 55c17a6..ab50627 100644 (file)
@@ -204,12 +204,8 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
        /*
         * Don't allow RAM to be mapped - this causes problems with ARMv6+
         */
-       if (pfn_valid(pfn)) {
-               printk(KERN_WARNING "BUG: Your driver calls ioremap() on system memory.  This leads\n"
-                      "to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n"
-                      "will fail in the next kernel release.  Please fix your driver.\n");
-               WARN_ON(1);
-       }
+       if (WARN_ON(pfn_valid(pfn)))
+               return NULL;
 
        type = get_mem_type(mtype);
        if (!type)
index 72ad3e1..79c01f5 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/smp_plat.h>
 #include <asm/tlb.h>
 #include <asm/highmem.h>
+#include <asm/traps.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -914,12 +915,11 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
 {
        struct map_desc map;
        unsigned long addr;
-       void *vectors;
 
        /*
         * Allocate the vector page early.
         */
-       vectors = early_alloc(PAGE_SIZE);
+       vectors_page = early_alloc(PAGE_SIZE);
 
        for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
                pmd_clear(pmd_off_k(addr));
@@ -959,7 +959,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
         * location (0xffff0000).  If we aren't using high-vectors, also
         * create a mapping at the low-vectors virtual address.
         */
-       map.pfn = __phys_to_pfn(virt_to_phys(vectors));
+       map.pfn = __phys_to_pfn(virt_to_phys(vectors_page));
        map.virtual = 0xffff0000;
        map.length = PAGE_SIZE;
        map.type = MT_HIGH_VECTORS;
index b795afd..f8f777d 100644 (file)
  *  110x   0   1   0   r/w     r/o
  *  11x0   0   1   0   r/w     r/o
  *  1111   0   1   1   r/w     r/w
+ *
+ * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed:
+ *  110x   1   1   1   r/o     r/o
+ *  11x0   1   1   1   r/o     r/o
  */
        .macro  armv6_mt_table pfx
 \pfx\()_mt_table:
 
        tst     r1, #L_PTE_USER
        orrne   r3, r3, #PTE_EXT_AP1
+#ifdef CONFIG_CPU_USE_DOMAINS
+       @ allow kernel read/write access to read-only user pages
        tstne   r3, #PTE_EXT_APX
        bicne   r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
+#endif
 
        tst     r1, #L_PTE_EXEC
        orreq   r3, r3, #PTE_EXT_XN
index 9b9ff5d..7401f4d 100644 (file)
@@ -148,8 +148,11 @@ ENTRY(cpu_v7_set_pte_ext)
 
        tst     r1, #L_PTE_USER
        orrne   r3, r3, #PTE_EXT_AP1
+#ifdef CONFIG_CPU_USE_DOMAINS
+       @ allow kernel read/write access to read-only user pages
        tstne   r3, #PTE_EXT_APX
        bicne   r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
+#endif
 
        tst     r1, #L_PTE_EXEC
        orreq   r3, r3, #PTE_EXT_XN
@@ -273,8 +276,6 @@ __v7_setup:
        ALT_SMP(orr     r4, r4, #TTB_FLAGS_SMP)
        ALT_UP(orr      r4, r4, #TTB_FLAGS_UP)
        mcr     p15, 0, r4, c2, c0, 1           @ load TTB1
-       mov     r10, #0x1f                      @ domains 0, 1 = manager
-       mcr     p15, 0, r10, c3, c0, 0          @ load domain access register
        /*
         * Memory region attributes with SCTLR.TRE=1
         *
@@ -312,6 +313,10 @@ __v7_setup:
        ldmia   r5, {r5, r6}
 #ifdef CONFIG_CPU_ENDIAN_BE8
        orr     r6, r6, #1 << 25                @ big-endian page tables
+#endif
+#ifdef CONFIG_SWP_EMULATE
+       orr     r5, r5, #(1 << 10)              @ set SW bit in "clear"
+       bic     r6, r6, #(1 << 10)              @ clear it in "mmuset"
 #endif
        mrc     p15, 0, r0, c1, c0, 0           @ read control register
        bic     r0, r0, r5                      @ clear bits them
index 92c5bb7..c940843 100644 (file)
@@ -11,13 +11,13 @@ choice
 
 config ARCH_OMAP1
        bool "TI OMAP1"
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        help
          "Systems based on omap7xx, omap15xx or omap16xx"
 
 config ARCH_OMAP2PLUS
        bool "TI OMAP2/3/4"
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        help
          "Systems based on OMAP2, OMAP3 or OMAP4"
 
index bb937f3..4b2028a 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H
 #define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H
 
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 struct omap_clk {
        u16                             cpu;
index d5306be..f8d922f 100644 (file)
 #define lbus_to_virt(x)                ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
 #define is_lbus_device(dev)    (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))
 
-#define __arch_page_to_dma(dev, page)  \
-       ({ dma_addr_t __dma = page_to_phys(page); \
+#define __arch_pfn_to_dma(dev, pfn)    \
+       ({ dma_addr_t __dma = __pfn_to_phys(pfn); \
           if (is_lbus_device(dev)) \
                __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \
           __dma; })
 
-#define __arch_dma_to_page(dev, addr)  \
+#define __arch_dma_to_pfn(dev, addr)   \
        ({ dma_addr_t __dma = addr;                             \
           if (is_lbus_device(dev))                             \
                __dma += PHYS_OFFSET - OMAP1510_LB_OFFSET;      \
-          phys_to_page(__dma);                                 \
+          __phys_to_pfn(__dma);                                \
        })
 
 #define __arch_dma_to_virt(dev, addr)  ({ (void *) (is_lbus_device(dev) ? \
index ecd6a48..7a10257 100644 (file)
@@ -18,7 +18,6 @@
 #define OMAP_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /* Needed for secondary core boot */
 extern void omap_secondary_startup(void);
@@ -29,9 +28,9 @@ extern u32 omap_read_auxcoreboot0(void);
 /*
  * We use Soft IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-       gic_raise_softirq(mask, 1);
+       gic_raise_softirq(mask, ipi);
 }
 
 #endif
index 298bafc..2572260 100644 (file)
@@ -15,7 +15,7 @@
 #define __PLAT_CLOCK_H
 
 #include <linux/list.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <linux/types.h>
 
 /* clk structure flags */
index e593a2a..2e712e1 100644 (file)
@@ -25,9 +25,9 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
 #include <asm/mach-types.h>
-#include <asm/clkdev.h>
 #include <mach/platform.h>
 #include <mach/regs-clkctrl.h>
 
index 8063a32..0797cb5 100644 (file)
  */
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/cpu.h>
 #include <linux/kernel.h>
+#include <linux/notifier.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/init.h>
 
 #include <asm/cputype.h>
@@ -484,7 +487,24 @@ void vfp_flush_hwstate(struct thread_info *thread)
        put_cpu();
 }
 
-#include <linux/smp.h>
+/*
+ * VFP hardware can lose all context when a CPU goes offline.
+ * Safely clear our held state when a CPU has been killed, and
+ * re-enable access to VFP when the CPU comes back online.
+ *
+ * Both CPU_DYING and CPU_STARTING are called on the CPU which
+ * is being offlined/onlined.
+ */
+static int vfp_hotplug(struct notifier_block *b, unsigned long action,
+       void *hcpu)
+{
+       if (action == CPU_DYING || action == CPU_DYING_FROZEN) {
+               unsigned int cpu = (long)hcpu;
+               last_VFP_context[cpu] = NULL;
+       } else if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
+               vfp_enable(NULL);
+       return NOTIFY_OK;
+}
 
 /*
  * VFP support code initialisation.
@@ -514,6 +534,8 @@ static int __init vfp_init(void)
        else if (vfpsid & FPSID_NODOUBLE) {
                printk("no double precision support\n");
        } else {
+               hotcpu_notifier(vfp_hotplug, 0);
+
                smp_call_function(vfp_enable, NULL, 1);
 
                VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT;  /* Extract the architecture version */
index 2e9d78d..25cf0b3 100644 (file)
@@ -1,7 +1,7 @@
 config SUPERH
        def_bool y
        select EMBEDDED
-       select HAVE_CLK
+       select CLKDEV_LOOKUP
        select HAVE_IDE if HAS_IOPORT
        select HAVE_MEMBLOCK
        select HAVE_OPROFILE
index a5ecfba..87618c9 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/usb/r8a66597.h>
 #include <linux/usb/m66592.h>
+#include <linux/clkdev.h>
 #include <net/ax88796.h>
 #include <asm/machvec.h>
 #include <mach/highlander.h>
-#include <asm/clkdev.h>
 #include <asm/clock.h>
 #include <asm/heartbeat.h>
 #include <asm/io.h>
index 5645f35..6ba9186 100644 (file)
@@ -1,9 +1,5 @@
 /*
- *  arch/sh/include/asm/clkdev.h
- *
- * Cloned from arch/arm/include/asm/clkdev.h:
- *
- *  Copyright (C) 2008 Russell King.
+ *  Copyright (C) 2010 Paul Mundt <lethal@linux-sh.org>
  *
  * 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
  *
  * Helper for the clk API to assist looking up a struct clk.
  */
-#ifndef __ASM_CLKDEV_H
-#define __ASM_CLKDEV_H
 
-struct clk;
+#ifndef __CLKDEV__H_
+#define __CLKDEV__H_
 
-struct clk_lookup {
-       struct list_head        node;
-       const char              *dev_id;
-       const char              *con_id;
-       struct clk              *clk;
-};
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
 
-struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
-       const char *dev_fmt, ...);
+#include <asm/clock.h>
 
-void clkdev_add(struct clk_lookup *cl);
-void clkdev_drop(struct clk_lookup *cl);
+static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
+{
+       if (!slab_is_available())
+               return alloc_bootmem_low_pages(size);
+       else
+               return kzalloc(size, GFP_KERNEL);
+}
 
-void clkdev_add_table(struct clk_lookup *, size_t);
-int clk_add_alias(const char *, const char *, char *, struct device *);
+#define __clk_put(clk)
+#define __clk_get(clk) ({ 1; })
 
-#endif
+#endif /* __CLKDEV_H__ */
index 8eed6a4..cf65221 100644 (file)
@@ -11,7 +11,7 @@ endif
 
 CFLAGS_REMOVE_return_address.o = -pg
 
-obj-y  := clkdev.o debugtraps.o dma-nommu.o dumpstack.o                \
+obj-y  := debugtraps.o dma-nommu.o dumpstack.o                 \
           idle.o io.o irq.o irq_$(BITS).o kdebugfs.o                   \
           machvec.o nmi_debug.o process.o                              \
           process_$(BITS).o ptrace.o ptrace_$(BITS).o                  \
diff --git a/arch/sh/kernel/clkdev.c b/arch/sh/kernel/clkdev.c
deleted file mode 100644 (file)
index 1f800ef..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * arch/sh/kernel/clkdev.c
- *
- * Cloned from arch/arm/common/clkdev.c:
- *
- *  Copyright (C) 2008 Russell King.
- *
- * 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.
- *
- * Helper for the clk API to assist looking up a struct clk.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/mutex.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <asm/clock.h>
-#include <asm/clkdev.h>
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-/*
- * Find the correct struct clk for the device and connection ID.
- * We do slightly fuzzy matching here:
- *  An entry with a NULL ID is assumed to be a wildcard.
- *  If an entry has a device ID, it must match
- *  If an entry has a connection ID, it must match
- * Then we take the most specific entry - with the following
- * order of precedence: dev+con > dev only > con only.
- */
-static struct clk *clk_find(const char *dev_id, const char *con_id)
-{
-       struct clk_lookup *p;
-       struct clk *clk = NULL;
-       int match, best = 0;
-
-       list_for_each_entry(p, &clocks, node) {
-               match = 0;
-               if (p->dev_id) {
-                       if (!dev_id || strcmp(p->dev_id, dev_id))
-                               continue;
-                       match += 2;
-               }
-               if (p->con_id) {
-                       if (!con_id || strcmp(p->con_id, con_id))
-                               continue;
-                       match += 1;
-               }
-               if (match == 0)
-                       continue;
-
-               if (match > best) {
-                       clk = p->clk;
-                       best = match;
-               }
-       }
-       return clk;
-}
-
-struct clk *clk_get_sys(const char *dev_id, const char *con_id)
-{
-       struct clk *clk;
-
-       mutex_lock(&clocks_mutex);
-       clk = clk_find(dev_id, con_id);
-       mutex_unlock(&clocks_mutex);
-
-       return clk ? clk : ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(clk_get_sys);
-
-void clkdev_add(struct clk_lookup *cl)
-{
-       mutex_lock(&clocks_mutex);
-       list_add_tail(&cl->node, &clocks);
-       mutex_unlock(&clocks_mutex);
-}
-EXPORT_SYMBOL(clkdev_add);
-
-void __init clkdev_add_table(struct clk_lookup *cl, size_t num)
-{
-       mutex_lock(&clocks_mutex);
-       while (num--) {
-               list_add_tail(&cl->node, &clocks);
-               cl++;
-       }
-       mutex_unlock(&clocks_mutex);
-}
-
-#define MAX_DEV_ID     20
-#define MAX_CON_ID     16
-
-struct clk_lookup_alloc {
-       struct clk_lookup cl;
-       char    dev_id[MAX_DEV_ID];
-       char    con_id[MAX_CON_ID];
-};
-
-struct clk_lookup * __init_refok
-clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
-{
-       struct clk_lookup_alloc *cla;
-
-       if (!slab_is_available())
-               cla = alloc_bootmem_low_pages(sizeof(*cla));
-       else
-               cla = kzalloc(sizeof(*cla), GFP_KERNEL);
-
-       if (!cla)
-               return NULL;
-
-       cla->cl.clk = clk;
-       if (con_id) {
-               strlcpy(cla->con_id, con_id, sizeof(cla->con_id));
-               cla->cl.con_id = cla->con_id;
-       }
-
-       if (dev_fmt) {
-               va_list ap;
-
-               va_start(ap, dev_fmt);
-               vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
-               cla->cl.dev_id = cla->dev_id;
-               va_end(ap);
-       }
-
-       return &cla->cl;
-}
-EXPORT_SYMBOL(clkdev_alloc);
-
-int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
-       struct device *dev)
-{
-       struct clk *r = clk_get(dev, id);
-       struct clk_lookup *l;
-
-       if (IS_ERR(r))
-               return PTR_ERR(r);
-
-       l = clkdev_alloc(r, alias, alias_dev_name);
-       clk_put(r);
-       if (!l)
-               return -ENODEV;
-       clkdev_add(l);
-       return 0;
-}
-EXPORT_SYMBOL(clk_add_alias);
-
-/*
- * clkdev_drop - remove a clock dynamically allocated
- */
-void clkdev_drop(struct clk_lookup *cl)
-{
-       struct clk_lookup_alloc *cla = container_of(cl, struct clk_lookup_alloc, cl);
-
-       mutex_lock(&clocks_mutex);
-       list_del(&cl->node);
-       mutex_unlock(&clocks_mutex);
-       kfree(cla);
-}
-EXPORT_SYMBOL(clkdev_drop);
index e2f63d6..dd0e0f2 100644 (file)
@@ -2,7 +2,7 @@
 #include <linux/compiler.h>
 #include <linux/slab.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 
 static struct clk master_clk = {
index 50f887d..4187cf4 100644 (file)
@@ -48,20 +48,4 @@ int __init clk_init(void)
        return ret;
 }
 
-/*
- * Returns a clock. Note that we first try to use device id on the bus
- * and clock name. If this fails, we try to use clock name only.
- */
-struct clk *clk_get(struct device *dev, const char *con_id)
-{
-       const char *dev_id = dev ? dev_name(dev) : NULL;
-
-       return clk_get_sys(dev_id, con_id);
-}
-EXPORT_SYMBOL_GPL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL_GPL(clk_put);
 
index 6282a83..3f6f8e9 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 
index 71291ae..93c6460 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 
 /* SH7343 registers */
index 7ce5bbc..049dc06 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 
 /* SH7366 registers */
index 2030f3d..9d23a36 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/hwblk.h>
 #include <cpu/sh7722.h>
index d3938f0..55493cd 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/clk.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/hwblk.h>
 #include <cpu/sh7723.h>
index 271c0b3..d08fa95 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/clk.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/hwblk.h>
 #include <cpu/sh7724.h>
index ce39a2a..e073e3e 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 
index 1f1df48..599630f 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 #include <asm/io.h>
index 62d7063..8894926 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 #include <asm/io.h>
index c3e458a..2d96024 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/cpufreq.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 #include <cpu/sh7785.h>
index 597c9fb..42e403b 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 
index 4f70df6..1afdb93 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 
index a2b902f..3d93b3a 100644 (file)
@@ -111,4 +111,6 @@ source "drivers/xen/Kconfig"
 source "drivers/staging/Kconfig"
 
 source "drivers/platform/Kconfig"
+
+source "drivers/clk/Kconfig"
 endmenu
index f3ebb30..bf15ce7 100644 (file)
@@ -115,3 +115,5 @@ obj-$(CONFIG_VLYNQ)         += vlynq/
 obj-$(CONFIG_STAGING)          += staging/
 obj-y                          += platform/
 obj-y                          += ieee802154/
+#common clk code
+obj-y                          += clk/
index 2737b97..e7df019 100644 (file)
@@ -147,6 +147,39 @@ static void amba_put_disable_pclk(struct amba_device *pcdev)
        clk_put(pclk);
 }
 
+static int amba_get_enable_vcore(struct amba_device *pcdev)
+{
+       struct regulator *vcore = regulator_get(&pcdev->dev, "vcore");
+       int ret;
+
+       pcdev->vcore = vcore;
+
+       if (IS_ERR(vcore)) {
+               /* It is OK not to supply a vcore regulator */
+               if (PTR_ERR(vcore) == -ENODEV)
+                       return 0;
+               return PTR_ERR(vcore);
+       }
+
+       ret = regulator_enable(vcore);
+       if (ret) {
+               regulator_put(vcore);
+               pcdev->vcore = ERR_PTR(-ENODEV);
+       }
+
+       return ret;
+}
+
+static void amba_put_disable_vcore(struct amba_device *pcdev)
+{
+       struct regulator *vcore = pcdev->vcore;
+
+       if (!IS_ERR(vcore)) {
+               regulator_disable(vcore);
+               regulator_put(vcore);
+       }
+}
+
 /*
  * These are the device model conversion veneers; they convert the
  * device model structures to our more specific structures.
@@ -159,6 +192,10 @@ static int amba_probe(struct device *dev)
        int ret;
 
        do {
+               ret = amba_get_enable_vcore(pcdev);
+               if (ret)
+                       break;
+
                ret = amba_get_enable_pclk(pcdev);
                if (ret)
                        break;
@@ -168,6 +205,7 @@ static int amba_probe(struct device *dev)
                        break;
 
                amba_put_disable_pclk(pcdev);
+               amba_put_disable_vcore(pcdev);
        } while (0);
 
        return ret;
@@ -180,6 +218,7 @@ static int amba_remove(struct device *dev)
        int ret = drv->remove(pcdev);
 
        amba_put_disable_pclk(pcdev);
+       amba_put_disable_vcore(pcdev);
 
        return ret;
 }
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
new file mode 100644 (file)
index 0000000..4168c88
--- /dev/null
@@ -0,0 +1,4 @@
+
+config CLKDEV_LOOKUP
+       bool
+       select HAVE_CLK
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
new file mode 100644 (file)
index 0000000..07613fa
--- /dev/null
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_CLKDEV_LOOKUP)    += clkdev.o
similarity index 93%
rename from arch/arm/common/clkdev.c
rename to drivers/clk/clkdev.c
index e2b2bb6..0fc0a79 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  arch/arm/common/clkdev.c
+ * drivers/clk/clkdev.c
  *
  *  Copyright (C) 2008 Russell King.
  *
 #include <linux/string.h>
 #include <linux/mutex.h>
 #include <linux/clk.h>
-#include <linux/slab.h>
-
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
+#include <linux/clkdev.h>
 
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
@@ -120,12 +117,12 @@ struct clk_lookup_alloc {
        char    con_id[MAX_CON_ID];
 };
 
-struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
-       const char *dev_fmt, ...)
+struct clk_lookup * __init_refok
+clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
 {
        struct clk_lookup_alloc *cla;
 
-       cla = kzalloc(sizeof(*cla), GFP_KERNEL);
+       cla = __clkdev_alloc(sizeof(*cla));
        if (!cla)
                return NULL;
 
index c6454cc..9e7f259 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/resource.h>
+#include <linux/regulator/consumer.h>
 
 #define AMBA_NR_IRQS   2
 #define AMBA_CID       0xb105f00d
@@ -28,6 +29,7 @@ struct amba_device {
        struct device           dev;
        struct resource         res;
        struct clk              *pclk;
+       struct regulator        *vcore;
        u64                     dma_mask;
        unsigned int            periphid;
        unsigned int            irq[AMBA_NR_IRQS];
@@ -71,6 +73,12 @@ void amba_release_regions(struct amba_device *);
 #define amba_pclk_disable(d)   \
        do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0)
 
+#define amba_vcore_enable(d)   \
+       (IS_ERR((d)->vcore) ? 0 : regulator_enable((d)->vcore))
+
+#define amba_vcore_disable(d)  \
+       do { if (!IS_ERR((d)->vcore)) regulator_disable((d)->vcore); } while (0)
+
 /* Some drivers don't use the struct amba_device */
 #define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff)
 #define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f)
diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h
new file mode 100644 (file)
index 0000000..457bcb0
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  include/linux/clkdev.h
+ *
+ *  Copyright (C) 2008 Russell King.
+ *
+ * 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.
+ *
+ * Helper for the clk API to assist looking up a struct clk.
+ */
+#ifndef __CLKDEV_H
+#define __CLKDEV_H
+
+#include <asm/clkdev.h>
+
+struct clk;
+struct device;
+
+struct clk_lookup {
+       struct list_head        node;
+       const char              *dev_id;
+       const char              *con_id;
+       struct clk              *clk;
+};
+
+struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
+       const char *dev_fmt, ...);
+
+void clkdev_add(struct clk_lookup *cl);
+void clkdev_drop(struct clk_lookup *cl);
+
+void clkdev_add_table(struct clk_lookup *, size_t);
+int clk_add_alias(const char *, const char *, char *, struct device *);
+
+#endif