提交 4073723a 编写于 作者: R Russell King

Merge branch 'misc' into devel

Conflicts:
	arch/arm/Kconfig
	arch/arm/common/Makefile
	arch/arm/kernel/Makefile
	arch/arm/kernel/smp.c
...@@ -34,3 +34,5 @@ memory.txt ...@@ -34,3 +34,5 @@ memory.txt
- description of the virtual memory layout - description of the virtual memory layout
nwfpe/ nwfpe/
- NWFPE floating point emulator documentation - NWFPE floating point emulator documentation
swp_emulation
- SWP/SWPB emulation handler/logging description
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.
...@@ -2,6 +2,7 @@ config ARM ...@@ -2,6 +2,7 @@ config ARM
bool bool
default y default y
select HAVE_AOUT select HAVE_AOUT
select HAVE_DMA_API_DEBUG
select HAVE_IDE select HAVE_IDE
select HAVE_MEMBLOCK select HAVE_MEMBLOCK
select RTC_LIB select RTC_LIB
...@@ -36,6 +37,9 @@ config ARM ...@@ -36,6 +37,9 @@ config ARM
config HAVE_PWM config HAVE_PWM
bool bool
config MIGHT_HAVE_PCI
bool
config SYS_SUPPORTS_APM_EMULATION config SYS_SUPPORTS_APM_EMULATION
bool bool
...@@ -226,7 +230,7 @@ config ARCH_INTEGRATOR ...@@ -226,7 +230,7 @@ config ARCH_INTEGRATOR
bool "ARM Ltd. Integrator family" bool "ARM Ltd. Integrator family"
select ARM_AMBA select ARM_AMBA
select ARCH_HAS_CPUFREQ select ARCH_HAS_CPUFREQ
select COMMON_CLKDEV select CLKDEV_LOOKUP
select ICST select ICST
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select PLAT_VERSATILE select PLAT_VERSATILE
...@@ -236,7 +240,7 @@ config ARCH_INTEGRATOR ...@@ -236,7 +240,7 @@ config ARCH_INTEGRATOR
config ARCH_REALVIEW config ARCH_REALVIEW
bool "ARM Ltd. RealView family" bool "ARM Ltd. RealView family"
select ARM_AMBA select ARM_AMBA
select COMMON_CLKDEV select CLKDEV_LOOKUP
select HAVE_SCHED_CLOCK select HAVE_SCHED_CLOCK
select ICST select ICST
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
...@@ -251,7 +255,7 @@ config ARCH_VERSATILE ...@@ -251,7 +255,7 @@ config ARCH_VERSATILE
bool "ARM Ltd. Versatile family" bool "ARM Ltd. Versatile family"
select ARM_AMBA select ARM_AMBA
select ARM_VIC select ARM_VIC
select COMMON_CLKDEV select CLKDEV_LOOKUP
select HAVE_SCHED_CLOCK select HAVE_SCHED_CLOCK
select ICST select ICST
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
...@@ -266,7 +270,7 @@ config ARCH_VEXPRESS ...@@ -266,7 +270,7 @@ config ARCH_VEXPRESS
select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_WANT_OPTIONAL_GPIOLIB
select ARM_AMBA select ARM_AMBA
select ARM_TIMER_SP804 select ARM_TIMER_SP804
select COMMON_CLKDEV select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select HAVE_CLK select HAVE_CLK
select HAVE_SCHED_CLOCK select HAVE_SCHED_CLOCK
...@@ -288,7 +292,7 @@ config ARCH_BCMRING ...@@ -288,7 +292,7 @@ config ARCH_BCMRING
depends on MMU depends on MMU
select CPU_V6 select CPU_V6
select ARM_AMBA select ARM_AMBA
select COMMON_CLKDEV select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_WANT_OPTIONAL_GPIOLIB
help help
...@@ -306,6 +310,7 @@ config ARCH_CNS3XXX ...@@ -306,6 +310,7 @@ config ARCH_CNS3XXX
select CPU_V6 select CPU_V6
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select ARM_GIC select ARM_GIC
select MIGHT_HAVE_PCI
select PCI_DOMAINS if PCI select PCI_DOMAINS if PCI
help help
Support for Cavium Networks CNS3XXX platform. Support for Cavium Networks CNS3XXX platform.
...@@ -335,7 +340,7 @@ config ARCH_EP93XX ...@@ -335,7 +340,7 @@ config ARCH_EP93XX
select CPU_ARM920T select CPU_ARM920T
select ARM_AMBA select ARM_AMBA
select ARM_VIC select ARM_VIC
select COMMON_CLKDEV select CLKDEV_LOOKUP
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select ARCH_HAS_HOLES_MEMORYMODEL select ARCH_HAS_HOLES_MEMORYMODEL
select ARCH_USES_GETTIMEOFFSET select ARCH_USES_GETTIMEOFFSET
...@@ -355,14 +360,14 @@ config ARCH_MXC ...@@ -355,14 +360,14 @@ config ARCH_MXC
bool "Freescale MXC/iMX-based" bool "Freescale MXC/iMX-based"
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select COMMON_CLKDEV select CLKDEV_LOOKUP
help help
Support for Freescale MXC/iMX-based family of processors Support for Freescale MXC/iMX-based family of processors
config ARCH_STMP3XXX config ARCH_STMP3XXX
bool "Freescale STMP3xxx" bool "Freescale STMP3xxx"
select CPU_ARM926T select CPU_ARM926T
select COMMON_CLKDEV select CLKDEV_LOOKUP
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select USB_ARCH_HAS_EHCI select USB_ARCH_HAS_EHCI
...@@ -442,6 +447,7 @@ config ARCH_IXP4XX ...@@ -442,6 +447,7 @@ config ARCH_IXP4XX
select GENERIC_GPIO select GENERIC_GPIO
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select HAVE_SCHED_CLOCK select HAVE_SCHED_CLOCK
select MIGHT_HAVE_PCI
select DMABOUNCE if PCI select DMABOUNCE if PCI
help help
Support for Intel's IXP4XX (XScale) family of processors. Support for Intel's IXP4XX (XScale) family of processors.
...@@ -481,7 +487,7 @@ config ARCH_LPC32XX ...@@ -481,7 +487,7 @@ config ARCH_LPC32XX
select HAVE_IDE select HAVE_IDE
select ARM_AMBA select ARM_AMBA
select USB_ARCH_HAS_OHCI select USB_ARCH_HAS_OHCI
select COMMON_CLKDEV select CLKDEV_LOOKUP
select GENERIC_TIME select GENERIC_TIME
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
help help
...@@ -515,7 +521,7 @@ config ARCH_MMP ...@@ -515,7 +521,7 @@ config ARCH_MMP
bool "Marvell PXA168/910/MMP2" bool "Marvell PXA168/910/MMP2"
depends on MMU depends on MMU
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select COMMON_CLKDEV select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select HAVE_SCHED_CLOCK select HAVE_SCHED_CLOCK
select TICK_ONESHOT select TICK_ONESHOT
...@@ -549,7 +555,7 @@ config ARCH_W90X900 ...@@ -549,7 +555,7 @@ config ARCH_W90X900
bool "Nuvoton W90X900 CPU" bool "Nuvoton W90X900 CPU"
select CPU_ARM926T select CPU_ARM926T
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select COMMON_CLKDEV select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
help help
Support for Nuvoton (Winbond logic dept.) ARM9 processor, Support for Nuvoton (Winbond logic dept.) ARM9 processor,
...@@ -563,19 +569,19 @@ config ARCH_W90X900 ...@@ -563,19 +569,19 @@ config ARCH_W90X900
config ARCH_NUC93X config ARCH_NUC93X
bool "Nuvoton NUC93X CPU" bool "Nuvoton NUC93X CPU"
select CPU_ARM926T select CPU_ARM926T
select COMMON_CLKDEV select CLKDEV_LOOKUP
help help
Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a
low-power and high performance MPEG-4/JPEG multimedia controller chip. low-power and high performance MPEG-4/JPEG multimedia controller chip.
config ARCH_TEGRA config ARCH_TEGRA
bool "NVIDIA Tegra" bool "NVIDIA Tegra"
select CLKDEV_LOOKUP
select GENERIC_TIME select GENERIC_TIME
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select GENERIC_GPIO select GENERIC_GPIO
select HAVE_CLK select HAVE_CLK
select HAVE_SCHED_CLOCK select HAVE_SCHED_CLOCK
select COMMON_CLKDEV
select ARCH_HAS_BARRIERS if CACHE_L2X0 select ARCH_HAS_BARRIERS if CACHE_L2X0
select ARCH_HAS_CPUFREQ select ARCH_HAS_CPUFREQ
help help
...@@ -585,7 +591,7 @@ config ARCH_TEGRA ...@@ -585,7 +591,7 @@ config ARCH_TEGRA
config ARCH_PNX4008 config ARCH_PNX4008
bool "Philips Nexperia PNX4008 Mobile" bool "Philips Nexperia PNX4008 Mobile"
select CPU_ARM926T select CPU_ARM926T
select COMMON_CLKDEV select CLKDEV_LOOKUP
select ARCH_USES_GETTIMEOFFSET select ARCH_USES_GETTIMEOFFSET
help help
This enables support for Philips PNX4008 mobile platform. This enables support for Philips PNX4008 mobile platform.
...@@ -595,7 +601,7 @@ config ARCH_PXA ...@@ -595,7 +601,7 @@ config ARCH_PXA
depends on MMU depends on MMU
select ARCH_MTD_XIP select ARCH_MTD_XIP
select ARCH_HAS_CPUFREQ select ARCH_HAS_CPUFREQ
select COMMON_CLKDEV select CLKDEV_LOOKUP
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select HAVE_SCHED_CLOCK select HAVE_SCHED_CLOCK
...@@ -774,7 +780,7 @@ config ARCH_TCC_926 ...@@ -774,7 +780,7 @@ config ARCH_TCC_926
bool "Telechips TCC ARM926-based systems" bool "Telechips TCC ARM926-based systems"
select CPU_ARM926T select CPU_ARM926T
select HAVE_CLK select HAVE_CLK
select COMMON_CLKDEV select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
help help
Support for Telechips TCC ARM926-based systems. Support for Telechips TCC ARM926-based systems.
...@@ -799,7 +805,7 @@ config ARCH_U300 ...@@ -799,7 +805,7 @@ config ARCH_U300
select ARM_AMBA select ARM_AMBA
select ARM_VIC select ARM_VIC
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select COMMON_CLKDEV select CLKDEV_LOOKUP
select GENERIC_GPIO select GENERIC_GPIO
help help
Support for ST-Ericsson U300 series mobile platforms. Support for ST-Ericsson U300 series mobile platforms.
...@@ -809,7 +815,7 @@ config ARCH_U8500 ...@@ -809,7 +815,7 @@ config ARCH_U8500
select CPU_V7 select CPU_V7
select ARM_AMBA select ARM_AMBA
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select COMMON_CLKDEV select CLKDEV_LOOKUP
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
help help
Support for ST-Ericsson's Ux500 architecture Support for ST-Ericsson's Ux500 architecture
...@@ -819,7 +825,7 @@ config ARCH_NOMADIK ...@@ -819,7 +825,7 @@ config ARCH_NOMADIK
select ARM_AMBA select ARM_AMBA
select ARM_VIC select ARM_VIC
select CPU_ARM926T select CPU_ARM926T
select COMMON_CLKDEV select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
help help
...@@ -831,7 +837,7 @@ config ARCH_DAVINCI ...@@ -831,7 +837,7 @@ config ARCH_DAVINCI
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select ZONE_DMA select ZONE_DMA
select HAVE_IDE select HAVE_IDE
select COMMON_CLKDEV select CLKDEV_LOOKUP
select GENERIC_ALLOCATOR select GENERIC_ALLOCATOR
select ARCH_HAS_HOLES_MEMORYMODEL select ARCH_HAS_HOLES_MEMORYMODEL
help help
...@@ -852,7 +858,7 @@ config PLAT_SPEAR ...@@ -852,7 +858,7 @@ config PLAT_SPEAR
bool "ST SPEAr" bool "ST SPEAr"
select ARM_AMBA select ARM_AMBA
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select COMMON_CLKDEV select CLKDEV_LOOKUP
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select HAVE_CLK select HAVE_CLK
help help
...@@ -1034,6 +1040,11 @@ config CPU_HAS_PMU ...@@ -1034,6 +1040,11 @@ config CPU_HAS_PMU
default y default y
bool bool
config MULTI_IRQ_HANDLER
bool
help
Allow each machine to specify it's own IRQ handler at run time.
if !MMU if !MMU
source "arch/arm/Kconfig-nommu" source "arch/arm/Kconfig-nommu"
endif endif
...@@ -1181,7 +1192,7 @@ config ISA_DMA_API ...@@ -1181,7 +1192,7 @@ config ISA_DMA_API
bool bool
config PCI 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 help
Find out whether you have a PCI motherboard. PCI is the name of a 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 bus system, i.e. the way the CPU talks to the other stuff inside
...@@ -1253,7 +1264,7 @@ config SMP ...@@ -1253,7 +1264,7 @@ config SMP
config SMP_ON_UP config SMP_ON_UP
bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)" bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)"
depends on EXPERIMENTAL depends on EXPERIMENTAL
depends on SMP && !XIP && !THUMB2_KERNEL depends on SMP && !XIP
default y default y
help help
SMP kernels contain instructions which fail on non-SMP processors. SMP kernels contain instructions which fail on non-SMP processors.
...@@ -1272,6 +1283,7 @@ config HAVE_ARM_SCU ...@@ -1272,6 +1283,7 @@ config HAVE_ARM_SCU
config HAVE_ARM_TWD config HAVE_ARM_TWD
bool bool
depends on SMP depends on SMP
select TICK_ONESHOT
help help
This options enables support for the ARM timer and watchdog unit This options enables support for the ARM timer and watchdog unit
...@@ -1335,7 +1347,7 @@ config HZ ...@@ -1335,7 +1347,7 @@ config HZ
default 100 default 100
config THUMB2_KERNEL 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 depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL
select AEABI select AEABI
select ARM_ASM_UNIFIED select ARM_ASM_UNIFIED
...@@ -1549,6 +1561,7 @@ config SECCOMP ...@@ -1549,6 +1561,7 @@ config SECCOMP
config CC_STACKPROTECTOR config CC_STACKPROTECTOR
bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
depends on EXPERIMENTAL
help help
This option turns on the -fstack-protector GCC feature. This This option turns on the -fstack-protector GCC feature. This
feature puts, at the beginning of functions, a canary value on feature puts, at the beginning of functions, a canary value on
...@@ -1745,7 +1758,7 @@ config CPU_FREQ_S3C ...@@ -1745,7 +1758,7 @@ config CPU_FREQ_S3C
Internal configuration node for common cpufreq on Samsung SoC Internal configuration node for common cpufreq on Samsung SoC
config CPU_FREQ_S3C24XX 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 depends on ARCH_S3C2410 && CPU_FREQ && EXPERIMENTAL
select CPU_FREQ_S3C select CPU_FREQ_S3C
help help
...@@ -1757,7 +1770,7 @@ config CPU_FREQ_S3C24XX ...@@ -1757,7 +1770,7 @@ config CPU_FREQ_S3C24XX
If in doubt, say N. If in doubt, say N.
config CPU_FREQ_S3C24XX_PLL 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 depends on CPU_FREQ_S3C24XX && EXPERIMENTAL
help help
Compile in support for changing the PLL frequency from the Compile in support for changing the PLL frequency from the
......
...@@ -31,7 +31,7 @@ config FRAME_POINTER ...@@ -31,7 +31,7 @@ config FRAME_POINTER
reported is severely limited. reported is severely limited.
config ARM_UNWIND config ARM_UNWIND
bool "Enable stack unwinding support" bool "Enable stack unwinding support (EXPERIMENTAL)"
depends on AEABI && EXPERIMENTAL depends on AEABI && EXPERIMENTAL
default y default y
help help
......
...@@ -37,7 +37,3 @@ config SHARP_PARAM ...@@ -37,7 +37,3 @@ config SHARP_PARAM
config SHARP_SCOOP config SHARP_SCOOP
bool bool
config COMMON_CLKDEV
bool
select HAVE_CLK
...@@ -328,7 +328,7 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr, ...@@ -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. * substitute the safe buffer for the unsafe one.
* (basically move the buffer from an unsafe area to a safe 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) enum dma_data_direction dir)
{ {
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", 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, ...@@ -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); 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 * see if a mapped address was really a "safe" buffer and if so, copy
...@@ -346,7 +346,7 @@ EXPORT_SYMBOL(dma_map_single); ...@@ -346,7 +346,7 @@ EXPORT_SYMBOL(dma_map_single);
* the safe buffer. (basically return things back to the way they * the safe buffer. (basically return things back to the way they
* should be) * 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) enum dma_data_direction dir)
{ {
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", 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, ...@@ -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); 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) unsigned long offset, size_t size, enum dma_data_direction dir)
{ {
dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n", 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, ...@@ -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); 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 * see if a mapped address was really a "safe" buffer and if so, copy
...@@ -380,7 +380,7 @@ EXPORT_SYMBOL(dma_map_page); ...@@ -380,7 +380,7 @@ EXPORT_SYMBOL(dma_map_page);
* the safe buffer. (basically return things back to the way they * the safe buffer. (basically return things back to the way they
* should be) * 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) enum dma_data_direction dir)
{ {
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", 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, ...@@ -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); 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, int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
unsigned long off, size_t sz, enum dma_data_direction dir) unsigned long off, size_t sz, enum dma_data_direction dir)
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#endif #endif
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/domain.h>
/* /*
* Endian independent macros for shifting bytes within registers. * Endian independent macros for shifting bytes within registers.
...@@ -157,16 +158,24 @@ ...@@ -157,16 +158,24 @@
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#define ALT_SMP(instr...) \ #define ALT_SMP(instr...) \
9998: 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...) \ #define ALT_UP(instr...) \
.pushsection ".alt.smp.init", "a" ;\ .pushsection ".alt.smp.init", "a" ;\
.long 9998b ;\ .long 9998b ;\
instr ;\ 9997: instr ;\
.if . - 9997b != 4 ;\
.error "ALT_UP() content must assemble to exactly 4 bytes";\
.endif ;\
.popsection .popsection
#define ALT_UP_B(label) \ #define ALT_UP_B(label) \
.equ up_b_offset, label - 9998b ;\ .equ up_b_offset, label - 9998b ;\
.pushsection ".alt.smp.init", "a" ;\ .pushsection ".alt.smp.init", "a" ;\
.long 9998b ;\ .long 9998b ;\
b . + up_b_offset ;\ W(b) . + up_b_offset ;\
.popsection .popsection
#else #else
#define ALT_SMP(instr...) #define ALT_SMP(instr...)
...@@ -177,16 +186,24 @@ ...@@ -177,16 +186,24 @@
/* /*
* SMP data memory barrier * SMP data memory barrier
*/ */
.macro smp_dmb .macro smp_dmb mode
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#if __LINUX_ARM_ARCH__ >= 7 #if __LINUX_ARM_ARCH__ >= 7
.ifeqs "\mode","arm"
ALT_SMP(dmb) ALT_SMP(dmb)
.else
ALT_SMP(W(dmb))
.endif
#elif __LINUX_ARM_ARCH__ == 6 #elif __LINUX_ARM_ARCH__ == 6
ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb
#else #else
#error Incompatible SMP platform #error Incompatible SMP platform
#endif #endif
.ifeqs "\mode","arm"
ALT_UP(nop) ALT_UP(nop)
.else
ALT_UP(W(nop))
.endif
#endif #endif
.endm .endm
...@@ -206,12 +223,12 @@ ...@@ -206,12 +223,12 @@
*/ */
#ifdef CONFIG_THUMB2_KERNEL #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: 9999:
.if \inc == 1 .if \inc == 1
\instr\cond\()bt \reg, [\ptr, #\off] \instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
.elseif \inc == 4 .elseif \inc == 4
\instr\cond\()t \reg, [\ptr, #\off] \instr\cond\()\t\().w \reg, [\ptr, #\off]
.else .else
.error "Unsupported inc macro argument" .error "Unsupported inc macro argument"
.endif .endif
...@@ -246,13 +263,13 @@ ...@@ -246,13 +263,13 @@
#else /* !CONFIG_THUMB2_KERNEL */ #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 .rept \rept
9999: 9999:
.if \inc == 1 .if \inc == 1
\instr\cond\()bt \reg, [\ptr], #\inc \instr\cond\()b\()\t \reg, [\ptr], #\inc
.elseif \inc == 4 .elseif \inc == 4
\instr\cond\()t \reg, [\ptr], #\inc \instr\cond\()\t \reg, [\ptr], #\inc
.else .else
.error "Unsupported inc macro argument" .error "Unsupported inc macro argument"
.endif .endif
......
...@@ -23,4 +23,6 @@ ...@@ -23,4 +23,6 @@
#define ARCH_SLAB_MINALIGN 8 #define ARCH_SLAB_MINALIGN 8
#endif #endif
#define __read_mostly __attribute__((__section__(".data..read_mostly")))
#endif #endif
...@@ -12,23 +12,13 @@ ...@@ -12,23 +12,13 @@
#ifndef __ASM_CLKDEV_H #ifndef __ASM_CLKDEV_H
#define __ASM_CLKDEV_H #define __ASM_CLKDEV_H
struct clk; #include <linux/slab.h>
struct device;
struct clk_lookup { #include <mach/clkdev.h>
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, static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
const char *dev_fmt, ...); {
return kzalloc(size, GFP_KERNEL);
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 #endif
...@@ -5,24 +5,29 @@ ...@@ -5,24 +5,29 @@
#include <linux/mm_types.h> #include <linux/mm_types.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/dma-debug.h>
#include <asm-generic/dma-coherent.h> #include <asm-generic/dma-coherent.h>
#include <asm/memory.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 * dma_to_pfn/pfn_to_dma/dma_to_virt/virt_to_dma are architecture private
* used internally by the DMA-mapping API to provide DMA addresses. They * functions used internally by the DMA-mapping API to provide DMA
* must not be used by drivers. * addresses. They must not be used by drivers.
*/ */
#ifndef __arch_page_to_dma #ifndef __arch_pfn_to_dma
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 (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) 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) ...@@ -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)); return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
} }
#else #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) 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); ...@@ -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. * 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); 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); 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); 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); enum dma_data_direction);
/* /*
...@@ -323,6 +328,34 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr, ...@@ -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 * dma_map_single - map a single buffer for streaming DMA
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices * @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, ...@@ -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, static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
size_t size, enum dma_data_direction dir) size_t size, enum dma_data_direction dir)
{ {
dma_addr_t addr;
BUG_ON(!valid_dma_direction(dir)); 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, ...@@ -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, 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) unsigned long offset, size_t size, enum dma_data_direction dir)
{ {
dma_addr_t addr;
BUG_ON(!valid_dma_direction(dir)); 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, ...@@ -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, static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir) 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, ...@@ -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, static inline void dma_unmap_page(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir) size_t size, enum dma_data_direction dir)
{ {
__dma_page_dev_to_cpu(dma_to_page(dev, handle), handle & ~PAGE_MASK, debug_dma_unmap_page(dev, handle, size, dir, false);
size, dir); __dma_unmap_page(dev, handle, size, dir);
} }
#endif /* CONFIG_DMABOUNCE */
/** /**
* dma_sync_single_range_for_cpu * dma_sync_single_range_for_cpu
...@@ -437,6 +478,8 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev, ...@@ -437,6 +478,8 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev,
{ {
BUG_ON(!valid_dma_direction(dir)); 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)) if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir))
return; return;
...@@ -449,6 +492,8 @@ static inline void dma_sync_single_range_for_device(struct device *dev, ...@@ -449,6 +492,8 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
{ {
BUG_ON(!valid_dma_direction(dir)); 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)) if (!dmabounce_sync_for_device(dev, handle, offset, size, dir))
return; return;
......
...@@ -45,13 +45,17 @@ ...@@ -45,13 +45,17 @@
*/ */
#define DOMAIN_NOACCESS 0 #define DOMAIN_NOACCESS 0
#define DOMAIN_CLIENT 1 #define DOMAIN_CLIENT 1
#ifdef CONFIG_CPU_USE_DOMAINS
#define DOMAIN_MANAGER 3 #define DOMAIN_MANAGER 3
#else
#define DOMAIN_MANAGER 1
#endif
#define domain_val(dom,type) ((type) << (2*(dom))) #define domain_val(dom,type) ((type) << (2*(dom)))
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#ifdef CONFIG_MMU #ifdef CONFIG_CPU_USE_DOMAINS
#define set_domain(x) \ #define set_domain(x) \
do { \ do { \
__asm__ __volatile__( \ __asm__ __volatile__( \
...@@ -74,5 +78,28 @@ ...@@ -74,5 +78,28 @@
#define modify_domain(dom,type) do { } while (0) #define modify_domain(dom,type) do { } while (0)
#endif #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
#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 */
/*
* 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
...@@ -13,12 +13,13 @@ ...@@ -13,12 +13,13 @@
#include <linux/preempt.h> #include <linux/preempt.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/domain.h>
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
__asm__ __volatile__( \ __asm__ __volatile__( \
"1: ldrt %1, [%2]\n" \ "1: " T(ldr) " %1, [%2]\n" \
" " insn "\n" \ " " insn "\n" \
"2: strt %0, [%2]\n" \ "2: " T(str) " %0, [%2]\n" \
" mov %0, #0\n" \ " mov %0, #0\n" \
"3:\n" \ "3:\n" \
" .pushsection __ex_table,\"a\"\n" \ " .pushsection __ex_table,\"a\"\n" \
...@@ -97,10 +98,10 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) ...@@ -97,10 +98,10 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
pagefault_disable(); /* implies preempt_disable() */ pagefault_disable(); /* implies preempt_disable() */
__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
"1: ldrt %0, [%3]\n" "1: " T(ldr) " %0, [%3]\n"
" teq %0, %1\n" " teq %0, %1\n"
" it eq @ explicit IT needed for the 2b label\n" " it eq @ explicit IT needed for the 2b label\n"
"2: streqt %2, [%3]\n" "2: " T(streq) " %2, [%3]\n"
"3:\n" "3:\n"
" .pushsection __ex_table,\"a\"\n" " .pushsection __ex_table,\"a\"\n"
" .align 3\n" " .align 3\n"
......
...@@ -5,13 +5,31 @@ ...@@ -5,13 +5,31 @@
#include <linux/threads.h> #include <linux/threads.h>
#include <asm/irq.h> #include <asm/irq.h>
#define NR_IPI 5
typedef struct { typedef struct {
unsigned int __softirq_pending; unsigned int __softirq_pending;
#ifdef CONFIG_LOCAL_TIMERS
unsigned int local_timer_irqs; unsigned int local_timer_irqs;
#endif
#ifdef CONFIG_SMP
unsigned int ipi_irqs[NR_IPI];
#endif
} ____cacheline_aligned irq_cpustat_t; } ____cacheline_aligned irq_cpustat_t;
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ #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 #if NR_IRQS > 512
#define HARDIRQ_BITS 10 #define HARDIRQ_BITS 10
#elif NR_IRQS > 256 #elif NR_IRQS > 256
......
...@@ -30,7 +30,6 @@ asmlinkage void do_local_timer(struct pt_regs *); ...@@ -30,7 +30,6 @@ asmlinkage void do_local_timer(struct pt_regs *);
#include "smp_twd.h" #include "smp_twd.h"
#define local_timer_ack() twd_timer_ack() #define local_timer_ack() twd_timer_ack()
#define local_timer_stop() twd_timer_stop()
#else #else
...@@ -40,11 +39,6 @@ asmlinkage void do_local_timer(struct pt_regs *); ...@@ -40,11 +39,6 @@ asmlinkage void do_local_timer(struct pt_regs *);
*/ */
int local_timer_ack(void); int local_timer_ack(void);
/*
* Stop a local timer interrupt.
*/
void local_timer_stop(void);
#endif #endif
/* /*
...@@ -52,12 +46,6 @@ void local_timer_stop(void); ...@@ -52,12 +46,6 @@ void local_timer_stop(void);
*/ */
void local_timer_setup(struct clock_event_device *); void local_timer_setup(struct clock_event_device *);
#else
static inline void local_timer_stop(void)
{
}
#endif #endif
#endif #endif
...@@ -37,11 +37,20 @@ struct machine_desc { ...@@ -37,11 +37,20 @@ struct machine_desc {
struct meminfo *); struct meminfo *);
void (*reserve)(void);/* reserve mem blocks */ void (*reserve)(void);/* reserve mem blocks */
void (*map_io)(void);/* IO mapping function */ void (*map_io)(void);/* IO mapping function */
void (*init_early)(void);
void (*init_irq)(void); void (*init_irq)(void);
struct sys_timer *timer; /* system tick timer */ struct sys_timer *timer; /* system tick timer */
void (*init_machine)(void); 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 * Set of macros to define architecture features. This is built into
* a table by the linker. * a table by the linker.
......
...@@ -17,10 +17,12 @@ struct seq_file; ...@@ -17,10 +17,12 @@ struct seq_file;
/* /*
* This is internal. Do not use it. * 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 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 * This is for easy migration, but should be changed in the source
......
...@@ -43,7 +43,6 @@ struct sys_timer { ...@@ -43,7 +43,6 @@ struct sys_timer {
#endif #endif
}; };
extern struct sys_timer *system_timer;
extern void timer_tick(void); extern void timer_tick(void);
#endif #endif
...@@ -33,27 +33,23 @@ struct seq_file; ...@@ -33,27 +33,23 @@ struct seq_file;
/* /*
* generate IPI list text * 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. * 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) * Setup the set of possible CPUs (via set_cpu_possible)
*/ */
extern void smp_init_cpus(void); 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. * 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. * Boot a secondary CPU, and assign it the specified idle task.
...@@ -72,6 +68,11 @@ asmlinkage void secondary_start_kernel(void); ...@@ -72,6 +68,11 @@ asmlinkage void secondary_start_kernel(void);
*/ */
extern void platform_secondary_init(unsigned int cpu); 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. * Initial data for bringing up a secondary CPU.
*/ */
...@@ -97,6 +98,6 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); ...@@ -97,6 +98,6 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
/* /*
* show local interrupt info * 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 */ #endif /* ifndef __ASM_ARM_SMP_H */
#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
...@@ -22,7 +22,6 @@ struct clock_event_device; ...@@ -22,7 +22,6 @@ struct clock_event_device;
extern void __iomem *twd_base; extern void __iomem *twd_base;
void twd_timer_stop(void);
int twd_timer_ack(void); int twd_timer_ack(void);
void twd_timer_setup(struct clock_event_device *); void twd_timer_setup(struct clock_event_device *);
......
...@@ -124,6 +124,13 @@ extern unsigned int user_debug; ...@@ -124,6 +124,13 @@ extern unsigned int user_debug;
#define vectors_high() (0) #define vectors_high() (0)
#endif #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 #if __LINUX_ARM_ARCH__ >= 7
#define isb() __asm__ __volatile__ ("isb" : : : "memory") #define isb() __asm__ __volatile__ ("isb" : : : "memory")
#define dsb() __asm__ __volatile__ ("dsb" : : : "memory") #define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
......
...@@ -46,4 +46,6 @@ static inline int in_exception_text(unsigned long ptr) ...@@ -46,4 +46,6 @@ static inline int in_exception_text(unsigned long ptr)
extern void __init early_trap_init(void); extern void __init early_trap_init(void);
extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
extern void *vectors_page;
#endif #endif
...@@ -227,7 +227,7 @@ do { \ ...@@ -227,7 +227,7 @@ do { \
#define __get_user_asm_byte(x,addr,err) \ #define __get_user_asm_byte(x,addr,err) \
__asm__ __volatile__( \ __asm__ __volatile__( \
"1: ldrbt %1,[%2]\n" \ "1: " T(ldrb) " %1,[%2],#0\n" \
"2:\n" \ "2:\n" \
" .pushsection .fixup,\"ax\"\n" \ " .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \ " .align 2\n" \
...@@ -263,7 +263,7 @@ do { \ ...@@ -263,7 +263,7 @@ do { \
#define __get_user_asm_word(x,addr,err) \ #define __get_user_asm_word(x,addr,err) \
__asm__ __volatile__( \ __asm__ __volatile__( \
"1: ldrt %1,[%2]\n" \ "1: " T(ldr) " %1,[%2],#0\n" \
"2:\n" \ "2:\n" \
" .pushsection .fixup,\"ax\"\n" \ " .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \ " .align 2\n" \
...@@ -308,7 +308,7 @@ do { \ ...@@ -308,7 +308,7 @@ do { \
#define __put_user_asm_byte(x,__pu_addr,err) \ #define __put_user_asm_byte(x,__pu_addr,err) \
__asm__ __volatile__( \ __asm__ __volatile__( \
"1: strbt %1,[%2]\n" \ "1: " T(strb) " %1,[%2],#0\n" \
"2:\n" \ "2:\n" \
" .pushsection .fixup,\"ax\"\n" \ " .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \ " .align 2\n" \
...@@ -341,7 +341,7 @@ do { \ ...@@ -341,7 +341,7 @@ do { \
#define __put_user_asm_word(x,__pu_addr,err) \ #define __put_user_asm_word(x,__pu_addr,err) \
__asm__ __volatile__( \ __asm__ __volatile__( \
"1: strt %1,[%2]\n" \ "1: " T(str) " %1,[%2],#0\n" \
"2:\n" \ "2:\n" \
" .pushsection .fixup,\"ax\"\n" \ " .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \ " .align 2\n" \
...@@ -366,10 +366,10 @@ do { \ ...@@ -366,10 +366,10 @@ do { \
#define __put_user_asm_dword(x,__pu_addr,err) \ #define __put_user_asm_dword(x,__pu_addr,err) \
__asm__ __volatile__( \ __asm__ __volatile__( \
ARM( "1: strt " __reg_oper1 ", [%1], #4\n" ) \ ARM( "1: " T(str) " " __reg_oper1 ", [%1], #4\n" ) \
ARM( "2: strt " __reg_oper0 ", [%1]\n" ) \ ARM( "2: " T(str) " " __reg_oper0 ", [%1]\n" ) \
THUMB( "1: strt " __reg_oper1 ", [%1]\n" ) \ THUMB( "1: " T(str) " " __reg_oper1 ", [%1]\n" ) \
THUMB( "2: strt " __reg_oper0 ", [%1, #4]\n" ) \ THUMB( "2: " T(str) " " __reg_oper0 ", [%1, #4]\n" ) \
"3:\n" \ "3:\n" \
" .pushsection .fixup,\"ax\"\n" \ " .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \ " .align 2\n" \
......
...@@ -30,7 +30,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o ...@@ -30,7 +30,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o
obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_ISA_DMA) += dma-isa.o
obj-$(CONFIG_PCI) += bios32.o isa.o obj-$(CONFIG_PCI) += bios32.o isa.o
obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.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_SCU) += smp_scu.o
obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
...@@ -44,6 +44,8 @@ obj-$(CONFIG_KGDB) += kgdb.o ...@@ -44,6 +44,8 @@ obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_ARM_UNWIND) += unwind.o obj-$(CONFIG_ARM_UNWIND) += unwind.o
obj-$(CONFIG_HAVE_TCM) += tcm.o obj-$(CONFIG_HAVE_TCM) += tcm.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.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_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
......
...@@ -25,42 +25,22 @@ ...@@ -25,42 +25,22 @@
#include <asm/tls.h> #include <asm/tls.h>
#include "entry-header.S" #include "entry-header.S"
#include <asm/entry-macro-multi.S>
/* /*
* Interrupt handling. Preserves r7, r8, r9 * Interrupt handling. Preserves r7, r8, r9
*/ */
.macro irq_handler .macro irq_handler
get_irqnr_preamble r5, lr #ifdef CONFIG_MULTI_IRQ_HANDLER
1: get_irqnr_and_base r0, r6, r5, lr ldr r5, =handle_arch_irq
movne r1, sp mov r0, sp
@ ldr r5, [r5]
@ routine called with r0 = irq number, r1 = struct pt_regs * adr lr, BSYM(9997f)
@ teq r5, #0
adrne lr, BSYM(1b) movne pc, r5
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
#endif #endif
arch_irq_handler_default
9997: 9997:
#endif
.endm .endm
#ifdef CONFIG_KPROBES #ifdef CONFIG_KPROBES
...@@ -735,7 +715,7 @@ ENTRY(__switch_to) ...@@ -735,7 +715,7 @@ ENTRY(__switch_to)
THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack
THUMB( str sp, [ip], #4 ) THUMB( str sp, [ip], #4 )
THUMB( str lr, [ip], #4 ) THUMB( str lr, [ip], #4 )
#ifdef CONFIG_MMU #ifdef CONFIG_CPU_USE_DOMAINS
ldr r6, [r2, #TI_CPU_DOMAIN] ldr r6, [r2, #TI_CPU_DOMAIN]
#endif #endif
set_tls r3, r4, r5 set_tls r3, r4, r5
...@@ -744,7 +724,7 @@ ENTRY(__switch_to) ...@@ -744,7 +724,7 @@ ENTRY(__switch_to)
ldr r8, =__stack_chk_guard ldr r8, =__stack_chk_guard
ldr r7, [r7, #TSK_STACK_CANARY] ldr r7, [r7, #TSK_STACK_CANARY]
#endif #endif
#ifdef CONFIG_MMU #ifdef CONFIG_CPU_USE_DOMAINS
mcr p15, 0, r6, c3, c0, 0 @ Set domain register mcr p15, 0, r6, c3, c0, 0 @ Set domain register
#endif #endif
mov r5, r0 mov r5, r0
...@@ -842,7 +822,7 @@ __kuser_helper_start: ...@@ -842,7 +822,7 @@ __kuser_helper_start:
*/ */
__kuser_memory_barrier: @ 0xffff0fa0 __kuser_memory_barrier: @ 0xffff0fa0
smp_dmb smp_dmb arm
usr_ret lr usr_ret lr
.align 5 .align 5
...@@ -959,7 +939,7 @@ kuser_cmpxchg_fixup: ...@@ -959,7 +939,7 @@ kuser_cmpxchg_fixup:
#else #else
smp_dmb smp_dmb arm
1: ldrex r3, [r2] 1: ldrex r3, [r2]
subs r3, r3, r0 subs r3, r3, r0
strexeq r3, r1, [r2] strexeq r3, r1, [r2]
...@@ -1245,3 +1225,9 @@ cr_alignment: ...@@ -1245,3 +1225,9 @@ cr_alignment:
.space 4 .space 4
cr_no_alignment: cr_no_alignment:
.space 4 .space 4
#ifdef CONFIG_MULTI_IRQ_HANDLER
.globl handle_arch_irq
handle_arch_irq:
.space 4
#endif
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include <asm/fiq.h> #include <asm/fiq.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/traps.h>
static unsigned long no_fiq_insn; static unsigned long no_fiq_insn;
...@@ -67,17 +68,22 @@ static struct fiq_handler default_owner = { ...@@ -67,17 +68,22 @@ static struct fiq_handler default_owner = {
static struct fiq_handler *current_fiq = &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) 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; return 0;
} }
void set_fiq_handler(void *start, unsigned int length) void set_fiq_handler(void *start, unsigned int length)
{ {
#if defined(CONFIG_CPU_USE_DOMAINS)
memcpy((void *)0xffff001c, start, length); memcpy((void *)0xffff001c, start, length);
#else
memcpy(vectors_page + 0x1c, start, length);
#endif
flush_icache_range(0xffff001c, 0xffff001c + length); flush_icache_range(0xffff001c, 0xffff001c + length);
if (!vectors_high()) if (!vectors_high())
flush_icache_range(0x1c, 0x1c + length); flush_icache_range(0x1c, 0x1c + length);
......
...@@ -91,6 +91,11 @@ ENTRY(stext) ...@@ -91,6 +91,11 @@ ENTRY(stext)
movs r8, r5 @ invalid machine (r5=0)? movs r8, r5 @ invalid machine (r5=0)?
THUMB( it eq ) @ force fixup-able long branch encoding THUMB( it eq ) @ force fixup-able long branch encoding
beq __error_a @ yes, error 'a' beq __error_a @ yes, error 'a'
/*
* r1 = machine no, r2 = atags,
* r8 = machinfo, r9 = cpuid, r10 = procinfo
*/
bl __vet_atags bl __vet_atags
#ifdef CONFIG_SMP_ON_UP #ifdef CONFIG_SMP_ON_UP
bl __fixup_smp bl __fixup_smp
...@@ -387,19 +392,19 @@ ENDPROC(__turn_mmu_on) ...@@ -387,19 +392,19 @@ ENDPROC(__turn_mmu_on)
#ifdef CONFIG_SMP_ON_UP #ifdef CONFIG_SMP_ON_UP
__fixup_smp: __fixup_smp:
mov r7, #0x00070000 mov r4, #0x00070000
orr r6, r7, #0xff000000 @ mask 0xff070000 orr r3, r4, #0xff000000 @ mask 0xff070000
orr r7, r7, #0x41000000 @ val 0x41070000 orr r4, r4, #0x41000000 @ val 0x41070000
and r0, r9, r6 and r0, r9, r3
teq r0, r7 @ ARM CPU and ARMv6/v7? teq r0, r4 @ ARM CPU and ARMv6/v7?
bne __fixup_smp_on_up @ no, assume UP bne __fixup_smp_on_up @ no, assume UP
orr r6, r6, #0x0000ff00 orr r3, r3, #0x0000ff00
orr r6, r6, #0x000000f0 @ mask 0xff07fff0 orr r3, r3, #0x000000f0 @ mask 0xff07fff0
orr r7, r7, #0x0000b000 orr r4, r4, #0x0000b000
orr r7, r7, #0x00000020 @ val 0x4107b020 orr r4, r4, #0x00000020 @ val 0x4107b020
and r0, r9, r6 and r0, r9, r3
teq r0, r7 @ ARM 11MPCore? teq r0, r4 @ ARM 11MPCore?
moveq pc, lr @ yes, assume SMP moveq pc, lr @ yes, assume SMP
mrc p15, 0, r0, c0, c0, 5 @ read MPIDR mrc p15, 0, r0, c0, c0, 5 @ read MPIDR
...@@ -408,15 +413,22 @@ __fixup_smp: ...@@ -408,15 +413,22 @@ __fixup_smp:
__fixup_smp_on_up: __fixup_smp_on_up:
adr r0, 1f adr r0, 1f
ldmia r0, {r3, r6, r7} ldmia r0, {r3 - r5}
sub r3, r0, r3 sub r3, r0, r3
add r6, r6, r3 add r4, r4, r3
add r7, r7, r3 add r5, r5, r3
2: cmp r6, r7 2: cmp r4, r5
ldmia r6!, {r0, r4} movhs pc, lr
strlo r4, [r0, r3] ldmia r4!, {r0, r6}
blo 2b ARM( str r6, [r0, r3] )
mov pc, lr 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) ENDPROC(__fixup_smp)
.align .align
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/ftrace.h> #include <linux/ftrace.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/mach/arch.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/mach/time.h> #include <asm/mach/time.h>
...@@ -48,8 +49,6 @@ ...@@ -48,8 +49,6 @@
#define irq_finish(irq) do { } while (0) #define irq_finish(irq) do { } while (0)
#endif #endif
unsigned int arch_nr_irqs;
void (*init_arch_irq)(void) __initdata = NULL;
unsigned long irq_err_count; unsigned long irq_err_count;
int show_interrupts(struct seq_file *p, void *v) int show_interrupts(struct seq_file *p, void *v)
...@@ -58,11 +57,20 @@ 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 irq_desc *desc;
struct irqaction * action; struct irqaction * action;
unsigned long flags; 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) { if (i == 0) {
char cpuname[12]; char cpuname[12];
seq_printf(p, " "); seq_printf(p, "%*s ", prec, "");
for_each_present_cpu(cpu) { for_each_present_cpu(cpu) {
sprintf(cpuname, "CPU%d", cpu); sprintf(cpuname, "CPU%d", cpu);
seq_printf(p, " %10s", cpuname); seq_printf(p, " %10s", cpuname);
...@@ -77,7 +85,7 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -77,7 +85,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (!action) if (!action)
goto unlock; goto unlock;
seq_printf(p, "%3d: ", i); seq_printf(p, "%*d: ", prec, i);
for_each_present_cpu(cpu) for_each_present_cpu(cpu)
seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu)); seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
seq_printf(p, " %10s", desc->chip->name ? : "-"); seq_printf(p, " %10s", desc->chip->name ? : "-");
...@@ -90,13 +98,15 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -90,13 +98,15 @@ int show_interrupts(struct seq_file *p, void *v)
raw_spin_unlock_irqrestore(&desc->lock, flags); raw_spin_unlock_irqrestore(&desc->lock, flags);
} else if (i == nr_irqs) { } else if (i == nr_irqs) {
#ifdef CONFIG_FIQ #ifdef CONFIG_FIQ
show_fiq_list(p, v); show_fiq_list(p, prec);
#endif #endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
show_ipi_list(p); show_ipi_list(p, prec);
show_local_irqs(p); #endif
#ifdef CONFIG_LOCAL_TIMERS
show_local_irqs(p, prec);
#endif #endif
seq_printf(p, "Err: %10lu\n", irq_err_count); seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
} }
return 0; return 0;
} }
...@@ -156,13 +166,13 @@ void set_irq_flags(unsigned int irq, unsigned int iflags) ...@@ -156,13 +166,13 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
void __init init_IRQ(void) void __init init_IRQ(void)
{ {
init_arch_irq(); machine_desc->init_irq();
} }
#ifdef CONFIG_SPARSE_IRQ #ifdef CONFIG_SPARSE_IRQ
int __init arch_probe_nr_irqs(void) 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; return nr_irqs;
} }
#endif #endif
......
...@@ -75,9 +75,9 @@ extern void reboot_setup(char *str); ...@@ -75,9 +75,9 @@ extern void reboot_setup(char *str);
unsigned int processor_id; unsigned int processor_id;
EXPORT_SYMBOL(processor_id); EXPORT_SYMBOL(processor_id);
unsigned int __machine_arch_type; unsigned int __machine_arch_type __read_mostly;
EXPORT_SYMBOL(__machine_arch_type); EXPORT_SYMBOL(__machine_arch_type);
unsigned int cacheid; unsigned int cacheid __read_mostly;
EXPORT_SYMBOL(cacheid); EXPORT_SYMBOL(cacheid);
unsigned int __atags_pointer __initdata; unsigned int __atags_pointer __initdata;
...@@ -91,24 +91,24 @@ EXPORT_SYMBOL(system_serial_low); ...@@ -91,24 +91,24 @@ EXPORT_SYMBOL(system_serial_low);
unsigned int system_serial_high; unsigned int system_serial_high;
EXPORT_SYMBOL(system_serial_high); EXPORT_SYMBOL(system_serial_high);
unsigned int elf_hwcap; unsigned int elf_hwcap __read_mostly;
EXPORT_SYMBOL(elf_hwcap); EXPORT_SYMBOL(elf_hwcap);
#ifdef MULTI_CPU #ifdef MULTI_CPU
struct processor processor; struct processor processor __read_mostly;
#endif #endif
#ifdef MULTI_TLB #ifdef MULTI_TLB
struct cpu_tlb_fns cpu_tlb; struct cpu_tlb_fns cpu_tlb __read_mostly;
#endif #endif
#ifdef MULTI_USER #ifdef MULTI_USER
struct cpu_user_fns cpu_user; struct cpu_user_fns cpu_user __read_mostly;
#endif #endif
#ifdef MULTI_CACHE #ifdef MULTI_CACHE
struct cpu_cache_fns cpu_cache; struct cpu_cache_fns cpu_cache __read_mostly;
#endif #endif
#ifdef CONFIG_OUTER_CACHE #ifdef CONFIG_OUTER_CACHE
struct outer_cache_fns outer_cache; struct outer_cache_fns outer_cache __read_mostly;
EXPORT_SYMBOL(outer_cache); EXPORT_SYMBOL(outer_cache);
#endif #endif
...@@ -126,6 +126,7 @@ EXPORT_SYMBOL(elf_platform); ...@@ -126,6 +126,7 @@ EXPORT_SYMBOL(elf_platform);
static const char *cpu_name; static const char *cpu_name;
static const char *machine_name; static const char *machine_name;
static char __initdata cmd_line[COMMAND_LINE_SIZE]; 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 char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
...@@ -708,13 +709,11 @@ static struct init_tags { ...@@ -708,13 +709,11 @@ static struct init_tags {
{ 0, ATAG_NONE } { 0, ATAG_NONE }
}; };
static void (*init_machine)(void) __initdata;
static int __init customize_machine(void) static int __init customize_machine(void)
{ {
/* customizes platform devices, or adds new ones */ /* customizes platform devices, or adds new ones */
if (init_machine) if (machine_desc->init_machine)
init_machine(); machine_desc->init_machine();
return 0; return 0;
} }
arch_initcall(customize_machine); arch_initcall(customize_machine);
...@@ -809,6 +808,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -809,6 +808,7 @@ void __init setup_arch(char **cmdline_p)
setup_processor(); setup_processor();
mdesc = setup_machine(machine_arch_type); mdesc = setup_machine(machine_arch_type);
machine_desc = mdesc;
machine_name = mdesc->name; machine_name = mdesc->name;
if (mdesc->soft_reboot) if (mdesc->soft_reboot)
...@@ -868,13 +868,9 @@ void __init setup_arch(char **cmdline_p) ...@@ -868,13 +868,9 @@ void __init setup_arch(char **cmdline_p)
cpu_init(); cpu_init();
tcm_init(); tcm_init();
/* #ifdef CONFIG_MULTI_IRQ_HANDLER
* Set up various architecture-specific pointers handle_arch_irq = mdesc->handle_irq;
*/ #endif
arch_nr_irqs = mdesc->nr_irqs;
init_arch_irq = mdesc->init_irq;
system_timer = mdesc->timer;
init_machine = mdesc->init_machine;
#ifdef CONFIG_VT #ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE) #if defined(CONFIG_VGA_CONSOLE)
...@@ -884,6 +880,9 @@ void __init setup_arch(char **cmdline_p) ...@@ -884,6 +880,9 @@ void __init setup_arch(char **cmdline_p)
#endif #endif
#endif #endif
early_trap_init(); early_trap_init();
if (mdesc->init_early)
mdesc->init_early();
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/clockchips.h> #include <linux/clockchips.h>
#include <linux/completion.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
...@@ -38,7 +39,6 @@ ...@@ -38,7 +39,6 @@
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/localtimer.h> #include <asm/localtimer.h>
#include <asm/smp_plat.h>
/* /*
* as from 2.5, kernels no longer have an init_tasks structure * as from 2.5, kernels no longer have an init_tasks structure
...@@ -47,22 +47,8 @@ ...@@ -47,22 +47,8 @@
*/ */
struct secondary_data secondary_data; 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 { enum ipi_msg_type {
IPI_TIMER, IPI_TIMER = 2,
IPI_RESCHEDULE, IPI_RESCHEDULE,
IPI_CALL_FUNC, IPI_CALL_FUNC,
IPI_CALL_FUNC_SINGLE, IPI_CALL_FUNC_SINGLE,
...@@ -178,9 +164,13 @@ int __cpuinit __cpu_up(unsigned int cpu) ...@@ -178,9 +164,13 @@ int __cpuinit __cpu_up(unsigned int cpu)
barrier(); barrier();
} }
if (!cpu_online(cpu)) if (!cpu_online(cpu)) {
pr_crit("CPU%u: failed to come online\n", cpu);
ret = -EIO; ret = -EIO;
} }
} else {
pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
}
secondary_data.stack = NULL; secondary_data.stack = NULL;
secondary_data.pgdir = 0; secondary_data.pgdir = 0;
...@@ -195,18 +185,12 @@ int __cpuinit __cpu_up(unsigned int cpu) ...@@ -195,18 +185,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
pgd_free(&init_mm, pgd); 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; return ret;
} }
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
static void percpu_timer_stop(void);
/* /*
* __cpu_disable runs on the processor to be shutdown. * __cpu_disable runs on the processor to be shutdown.
*/ */
...@@ -234,7 +218,7 @@ int __cpu_disable(void) ...@@ -234,7 +218,7 @@ int __cpu_disable(void)
/* /*
* Stop the local timer for this CPU. * Stop the local timer for this CPU.
*/ */
local_timer_stop(); percpu_timer_stop();
/* /*
* Flush user cache and TLB mappings, and then remove this CPU * Flush user cache and TLB mappings, and then remove this CPU
...@@ -253,12 +237,20 @@ int __cpu_disable(void) ...@@ -253,12 +237,20 @@ int __cpu_disable(void)
return 0; return 0;
} }
static DECLARE_COMPLETION(cpu_died);
/* /*
* called on the thread which is asking for a CPU to be shutdown - * called on the thread which is asking for a CPU to be shutdown -
* waits until shutdown has completed, or it is timed out. * waits until shutdown has completed, or it is timed out.
*/ */
void __cpu_die(unsigned int cpu) 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)) if (!platform_cpu_kill(cpu))
printk("CPU%u: unable to kill\n", cpu); printk("CPU%u: unable to kill\n", cpu);
} }
...@@ -275,12 +267,17 @@ void __ref cpu_die(void) ...@@ -275,12 +267,17 @@ void __ref cpu_die(void)
{ {
unsigned int cpu = smp_processor_id(); unsigned int cpu = smp_processor_id();
local_irq_disable();
idle_task_exit(); 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 * actual CPU shutdown procedure is at least platform (if not
* CPU) specific * CPU) specific.
*/ */
platform_cpu_die(cpu); platform_cpu_die(cpu);
...@@ -290,12 +287,24 @@ void __ref cpu_die(void) ...@@ -290,12 +287,24 @@ void __ref cpu_die(void)
* to be repeated to undo the effects of taking the CPU offline. * to be repeated to undo the effects of taking the CPU offline.
*/ */
__asm__("mov sp, %0\n" __asm__("mov sp, %0\n"
" mov fp, #0\n"
" b secondary_start_kernel" " b secondary_start_kernel"
: :
: "r" (task_stack_page(current) + THREAD_SIZE - 8)); : "r" (task_stack_page(current) + THREAD_SIZE - 8));
} }
#endif /* CONFIG_HOTPLUG_CPU */ #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 * This is the secondary CPU boot entry. We're using this CPUs
* idle thread stack, but a set of temporary page tables. * idle thread stack, but a set of temporary page tables.
...@@ -320,6 +329,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) ...@@ -320,6 +329,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
cpu_init(); cpu_init();
preempt_disable(); preempt_disable();
trace_hardirqs_off();
/* /*
* Give the platform a chance to do its own initialisation. * Give the platform a chance to do its own initialisation.
...@@ -353,17 +363,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void) ...@@ -353,17 +363,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
cpu_idle(); 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) void __init smp_cpus_done(unsigned int max_cpus)
{ {
int cpu; int cpu;
...@@ -386,61 +385,80 @@ void __init smp_prepare_boot_cpu(void) ...@@ -386,61 +385,80 @@ void __init smp_prepare_boot_cpu(void)
per_cpu(cpu_data, cpu).idle = current; 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 ncores = num_possible_cpus();
unsigned int cpu;
local_irq_save(flags); smp_store_cpu_info(smp_processor_id());
for_each_cpu(cpu, mask) { /*
struct ipi_data *ipi = &per_cpu(ipi_data, cpu); * are we trying to boot more cores than exist?
*/
spin_lock(&ipi->lock); if (max_cpus > ncores)
ipi->bits |= 1 << msg; max_cpus = ncores;
spin_unlock(&ipi->lock);
}
if (max_cpus > 1) {
/* /*
* Call the platform specific cross-CPU call function. * Enable the local timer or broadcast device for the
* boot CPU, but only if we have more than one CPU.
*/ */
smp_cross_call(mask); 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) 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) 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) for_each_present_cpu(cpu)
seq_printf(p, " %10lu", per_cpu(ipi_data, cpu).ipi_count); 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) #ifdef CONFIG_LOCAL_TIMERS
seq_printf(p, "%10u ", irq_stat[cpu].local_timer_irqs); 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) ...@@ -463,18 +481,30 @@ asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)
int cpu = smp_processor_id(); int cpu = smp_processor_id();
if (local_timer_ack()) { if (local_timer_ack()) {
irq_stat[cpu].local_timer_irqs++; __inc_irq_stat(cpu, local_timer_irqs);
ipi_timer(); ipi_timer();
} }
set_irq_regs(old_regs); 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 #endif
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
static void smp_timer_broadcast(const struct cpumask *mask) static void smp_timer_broadcast(const struct cpumask *mask)
{ {
send_ipi_message(mask, IPI_TIMER); smp_cross_call(mask, IPI_TIMER);
} }
#else #else
#define smp_timer_broadcast NULL #define smp_timer_broadcast NULL
...@@ -511,6 +541,21 @@ void __cpuinit percpu_timer_setup(void) ...@@ -511,6 +541,21 @@ void __cpuinit percpu_timer_setup(void)
local_timer_setup(evt); 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); static DEFINE_SPINLOCK(stop_lock);
/* /*
...@@ -537,40 +582,16 @@ static void ipi_cpu_stop(unsigned int cpu) ...@@ -537,40 +582,16 @@ static void ipi_cpu_stop(unsigned int cpu)
/* /*
* Main handler for inter-processor interrupts * 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(); unsigned int cpu = smp_processor_id();
struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
struct pt_regs *old_regs = set_irq_regs(regs); struct pt_regs *old_regs = set_irq_regs(regs);
ipi->ipi_count++; if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI)
__inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]);
for (;;) {
unsigned long msgs;
spin_lock(&ipi->lock);
msgs = ipi->bits;
ipi->bits = 0;
spin_unlock(&ipi->lock);
if (!msgs)
break;
do {
unsigned nextmsg;
nextmsg = msgs & -msgs; switch (ipinr) {
msgs &= ~nextmsg;
nextmsg = ffz(~nextmsg);
switch (nextmsg) {
case IPI_TIMER: case IPI_TIMER:
ipi_timer(); ipi_timer();
break; break;
...@@ -596,157 +617,41 @@ asmlinkage void __exception_irq_entry do_IPI(struct pt_regs *regs) ...@@ -596,157 +617,41 @@ asmlinkage void __exception_irq_entry do_IPI(struct pt_regs *regs)
default: default:
printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
cpu, nextmsg); cpu, ipinr);
break; break;
} }
} while (msgs);
}
set_irq_regs(old_regs); set_irq_regs(old_regs);
} }
void smp_send_reschedule(int cpu) 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) void smp_send_stop(void)
{ {
unsigned long timeout;
if (num_online_cpus() > 1) {
cpumask_t mask = cpu_online_map; cpumask_t mask = cpu_online_map;
cpu_clear(smp_processor_id(), mask); cpu_clear(smp_processor_id(), mask);
if (!cpus_empty(mask))
send_ipi_message(&mask, IPI_CPU_STOP);
}
/* smp_cross_call(&mask, IPI_CPU_STOP);
* not supported here }
*/
int setup_profiling_timer(unsigned int multiplier)
{
return -EINVAL;
}
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); /* Wait up to one second for other CPUs to stop */
if (cpumask_test_cpu(smp_processor_id(), mask)) timeout = USEC_PER_SEC;
func(info); 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 { int setup_profiling_timer(unsigned int multiplier)
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()) { return -EINVAL;
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);
} }
/*
* 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);
}
...@@ -145,13 +145,3 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) ...@@ -145,13 +145,3 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
clockevents_register_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
/*
* 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);
...@@ -30,12 +30,13 @@ ...@@ -30,12 +30,13 @@
#include <asm/leds.h> #include <asm/leds.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
#include <asm/stacktrace.h> #include <asm/stacktrace.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h> #include <asm/mach/time.h>
/* /*
* Our system timer. * 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) #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
/* this needs a better home */ /* this needs a better home */
...@@ -160,6 +161,7 @@ device_initcall(timer_init_sysfs); ...@@ -160,6 +161,7 @@ device_initcall(timer_init_sysfs);
void __init time_init(void) void __init time_init(void)
{ {
system_timer = machine_desc->timer;
system_timer->init(); system_timer->init();
} }
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
void *vectors_page;
#ifdef CONFIG_DEBUG_USER #ifdef CONFIG_DEBUG_USER
unsigned int user_debug; unsigned int user_debug;
...@@ -756,7 +758,11 @@ static void __init kuser_get_tls_init(unsigned long vectors) ...@@ -756,7 +758,11 @@ static void __init kuser_get_tls_init(unsigned long vectors)
void __init early_trap_init(void) void __init early_trap_init(void)
{ {
#if defined(CONFIG_CPU_USE_DOMAINS)
unsigned long vectors = CONFIG_VECTORS_BASE; unsigned long vectors = CONFIG_VECTORS_BASE;
#else
unsigned long vectors = (unsigned long)vectors_page;
#endif
extern char __stubs_start[], __stubs_end[]; extern char __stubs_start[], __stubs_end[];
extern char __vectors_start[], __vectors_end[]; extern char __vectors_start[], __vectors_end[];
extern char __kuser_helper_start[], __kuser_helper_end[]; extern char __kuser_helper_start[], __kuser_helper_end[];
...@@ -780,10 +786,10 @@ void __init early_trap_init(void) ...@@ -780,10 +786,10 @@ void __init early_trap_init(void)
* Copy signal return handlers into the vector page, and * Copy signal return handlers into the vector page, and
* set sigreturn to be a pointer to these. * set sigreturn to be a pointer to these.
*/ */
memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes, memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
sizeof(sigreturn_codes)); sigreturn_codes, sizeof(sigreturn_codes));
memcpy((void *)KERN_RESTART_CODE, syscall_restart_code, memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
sizeof(syscall_restart_code)); syscall_restart_code, sizeof(syscall_restart_code));
flush_icache_range(vectors, vectors + PAGE_SIZE); flush_icache_range(vectors, vectors + PAGE_SIZE);
modify_domain(DOMAIN_USER, DOMAIN_CLIENT); modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
......
...@@ -168,6 +168,7 @@ SECTIONS ...@@ -168,6 +168,7 @@ SECTIONS
NOSAVE_DATA NOSAVE_DATA
CACHELINE_ALIGNED_DATA(32) CACHELINE_ALIGNED_DATA(32)
READ_MOSTLY_DATA(32)
/* /*
* The exception fixup table (might need resorting at runtime) * The exception fixup table (might need resorting at runtime)
......
...@@ -28,20 +28,21 @@ ...@@ -28,20 +28,21 @@
*/ */
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/domain.h>
ENTRY(__get_user_1) ENTRY(__get_user_1)
1: ldrbt r2, [r0] 1: T(ldrb) r2, [r0]
mov r0, #0 mov r0, #0
mov pc, lr mov pc, lr
ENDPROC(__get_user_1) ENDPROC(__get_user_1)
ENTRY(__get_user_2) ENTRY(__get_user_2)
#ifdef CONFIG_THUMB2_KERNEL #ifdef CONFIG_THUMB2_KERNEL
2: ldrbt r2, [r0] 2: T(ldrb) r2, [r0]
3: ldrbt r3, [r0, #1] 3: T(ldrb) r3, [r0, #1]
#else #else
2: ldrbt r2, [r0], #1 2: T(ldrb) r2, [r0], #1
3: ldrbt r3, [r0] 3: T(ldrb) r3, [r0]
#endif #endif
#ifndef __ARMEB__ #ifndef __ARMEB__
orr r2, r2, r3, lsl #8 orr r2, r2, r3, lsl #8
...@@ -53,7 +54,7 @@ ENTRY(__get_user_2) ...@@ -53,7 +54,7 @@ ENTRY(__get_user_2)
ENDPROC(__get_user_2) ENDPROC(__get_user_2)
ENTRY(__get_user_4) ENTRY(__get_user_4)
4: ldrt r2, [r0] 4: T(ldr) r2, [r0]
mov r0, #0 mov r0, #0
mov pc, lr mov pc, lr
ENDPROC(__get_user_4) ENDPROC(__get_user_4)
......
...@@ -28,9 +28,10 @@ ...@@ -28,9 +28,10 @@
*/ */
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/domain.h>
ENTRY(__put_user_1) ENTRY(__put_user_1)
1: strbt r2, [r0] 1: T(strb) r2, [r0]
mov r0, #0 mov r0, #0
mov pc, lr mov pc, lr
ENDPROC(__put_user_1) ENDPROC(__put_user_1)
...@@ -39,19 +40,19 @@ ENTRY(__put_user_2) ...@@ -39,19 +40,19 @@ ENTRY(__put_user_2)
mov ip, r2, lsr #8 mov ip, r2, lsr #8
#ifdef CONFIG_THUMB2_KERNEL #ifdef CONFIG_THUMB2_KERNEL
#ifndef __ARMEB__ #ifndef __ARMEB__
2: strbt r2, [r0] 2: T(strb) r2, [r0]
3: strbt ip, [r0, #1] 3: T(strb) ip, [r0, #1]
#else #else
2: strbt ip, [r0] 2: T(strb) ip, [r0]
3: strbt r2, [r0, #1] 3: T(strb) r2, [r0, #1]
#endif #endif
#else /* !CONFIG_THUMB2_KERNEL */ #else /* !CONFIG_THUMB2_KERNEL */
#ifndef __ARMEB__ #ifndef __ARMEB__
2: strbt r2, [r0], #1 2: T(strb) r2, [r0], #1
3: strbt ip, [r0] 3: T(strb) ip, [r0]
#else #else
2: strbt ip, [r0], #1 2: T(strb) ip, [r0], #1
3: strbt r2, [r0] 3: T(strb) r2, [r0]
#endif #endif
#endif /* CONFIG_THUMB2_KERNEL */ #endif /* CONFIG_THUMB2_KERNEL */
mov r0, #0 mov r0, #0
...@@ -59,18 +60,18 @@ ENTRY(__put_user_2) ...@@ -59,18 +60,18 @@ ENTRY(__put_user_2)
ENDPROC(__put_user_2) ENDPROC(__put_user_2)
ENTRY(__put_user_4) ENTRY(__put_user_4)
4: strt r2, [r0] 4: T(str) r2, [r0]
mov r0, #0 mov r0, #0
mov pc, lr mov pc, lr
ENDPROC(__put_user_4) ENDPROC(__put_user_4)
ENTRY(__put_user_8) ENTRY(__put_user_8)
#ifdef CONFIG_THUMB2_KERNEL #ifdef CONFIG_THUMB2_KERNEL
5: strt r2, [r0] 5: T(str) r2, [r0]
6: strt r3, [r0, #4] 6: T(str) r3, [r0, #4]
#else #else
5: strt r2, [r0], #4 5: T(str) r2, [r0], #4
6: strt r3, [r0] 6: T(str) r3, [r0]
#endif #endif
mov r0, #0 mov r0, #0
mov pc, lr mov pc, lr
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/assembler.h> #include <asm/assembler.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/domain.h>
.text .text
...@@ -31,11 +32,11 @@ ...@@ -31,11 +32,11 @@
rsb ip, ip, #4 rsb ip, ip, #4
cmp ip, #2 cmp ip, #2
ldrb r3, [r1], #1 ldrb r3, [r1], #1
USER( strbt r3, [r0], #1) @ May fault USER( T(strb) r3, [r0], #1) @ May fault
ldrgeb r3, [r1], #1 ldrgeb r3, [r1], #1
USER( strgebt r3, [r0], #1) @ May fault USER( T(strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #1 ldrgtb r3, [r1], #1
USER( strgtbt r3, [r0], #1) @ May fault USER( T(strgtb) r3, [r0], #1) @ May fault
sub r2, r2, ip sub r2, r2, ip
b .Lc2u_dest_aligned b .Lc2u_dest_aligned
...@@ -58,7 +59,7 @@ ENTRY(__copy_to_user) ...@@ -58,7 +59,7 @@ ENTRY(__copy_to_user)
addmi ip, r2, #4 addmi ip, r2, #4
bmi .Lc2u_0nowords bmi .Lc2u_0nowords
ldr r3, [r1], #4 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 mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
rsb ip, ip, #0 rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT movs ip, ip, lsr #32 - PAGE_SHIFT
...@@ -87,18 +88,18 @@ USER( strt r3, [r0], #4) @ May fault ...@@ -87,18 +88,18 @@ USER( strt r3, [r0], #4) @ May fault
stmneia r0!, {r3 - r4} @ Shouldnt fault stmneia r0!, {r3 - r4} @ Shouldnt fault
tst ip, #4 tst ip, #4
ldrne r3, [r1], #4 ldrne r3, [r1], #4
strnet r3, [r0], #4 @ Shouldnt fault T(strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3 ands ip, ip, #3
beq .Lc2u_0fupi beq .Lc2u_0fupi
.Lc2u_0nowords: teq ip, #0 .Lc2u_0nowords: teq ip, #0
beq .Lc2u_finished beq .Lc2u_finished
.Lc2u_nowords: cmp ip, #2 .Lc2u_nowords: cmp ip, #2
ldrb r3, [r1], #1 ldrb r3, [r1], #1
USER( strbt r3, [r0], #1) @ May fault USER( T(strb) r3, [r0], #1) @ May fault
ldrgeb r3, [r1], #1 ldrgeb r3, [r1], #1
USER( strgebt r3, [r0], #1) @ May fault USER( T(strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #1 ldrgtb r3, [r1], #1
USER( strgtbt r3, [r0], #1) @ May fault USER( T(strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished b .Lc2u_finished
.Lc2u_not_enough: .Lc2u_not_enough:
...@@ -119,7 +120,7 @@ USER( strgtbt r3, [r0], #1) @ May fault ...@@ -119,7 +120,7 @@ USER( strgtbt r3, [r0], #1) @ May fault
mov r3, r7, pull #8 mov r3, r7, pull #8
ldr r7, [r1], #4 ldr r7, [r1], #4
orr r3, r3, r7, push #24 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 mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0 rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT movs ip, ip, lsr #32 - PAGE_SHIFT
...@@ -154,18 +155,18 @@ USER( strt r3, [r0], #4) @ May fault ...@@ -154,18 +155,18 @@ USER( strt r3, [r0], #4) @ May fault
movne r3, r7, pull #8 movne r3, r7, pull #8
ldrne r7, [r1], #4 ldrne r7, [r1], #4
orrne r3, r3, r7, push #24 orrne r3, r3, r7, push #24
strnet r3, [r0], #4 @ Shouldnt fault T(strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3 ands ip, ip, #3
beq .Lc2u_1fupi beq .Lc2u_1fupi
.Lc2u_1nowords: mov r3, r7, get_byte_1 .Lc2u_1nowords: mov r3, r7, get_byte_1
teq ip, #0 teq ip, #0
beq .Lc2u_finished beq .Lc2u_finished
cmp ip, #2 cmp ip, #2
USER( strbt r3, [r0], #1) @ May fault USER( T(strb) r3, [r0], #1) @ May fault
movge r3, r7, get_byte_2 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 movgt r3, r7, get_byte_3
USER( strgtbt r3, [r0], #1) @ May fault USER( T(strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished b .Lc2u_finished
.Lc2u_2fupi: subs r2, r2, #4 .Lc2u_2fupi: subs r2, r2, #4
...@@ -174,7 +175,7 @@ USER( strgtbt r3, [r0], #1) @ May fault ...@@ -174,7 +175,7 @@ USER( strgtbt r3, [r0], #1) @ May fault
mov r3, r7, pull #16 mov r3, r7, pull #16
ldr r7, [r1], #4 ldr r7, [r1], #4
orr r3, r3, r7, push #16 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 mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0 rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT movs ip, ip, lsr #32 - PAGE_SHIFT
...@@ -209,18 +210,18 @@ USER( strt r3, [r0], #4) @ May fault ...@@ -209,18 +210,18 @@ USER( strt r3, [r0], #4) @ May fault
movne r3, r7, pull #16 movne r3, r7, pull #16
ldrne r7, [r1], #4 ldrne r7, [r1], #4
orrne r3, r3, r7, push #16 orrne r3, r3, r7, push #16
strnet r3, [r0], #4 @ Shouldnt fault T(strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3 ands ip, ip, #3
beq .Lc2u_2fupi beq .Lc2u_2fupi
.Lc2u_2nowords: mov r3, r7, get_byte_2 .Lc2u_2nowords: mov r3, r7, get_byte_2
teq ip, #0 teq ip, #0
beq .Lc2u_finished beq .Lc2u_finished
cmp ip, #2 cmp ip, #2
USER( strbt r3, [r0], #1) @ May fault USER( T(strb) r3, [r0], #1) @ May fault
movge r3, r7, get_byte_3 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 ldrgtb r3, [r1], #0
USER( strgtbt r3, [r0], #1) @ May fault USER( T(strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished b .Lc2u_finished
.Lc2u_3fupi: subs r2, r2, #4 .Lc2u_3fupi: subs r2, r2, #4
...@@ -229,7 +230,7 @@ USER( strgtbt r3, [r0], #1) @ May fault ...@@ -229,7 +230,7 @@ USER( strgtbt r3, [r0], #1) @ May fault
mov r3, r7, pull #24 mov r3, r7, pull #24
ldr r7, [r1], #4 ldr r7, [r1], #4
orr r3, r3, r7, push #8 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 mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0 rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT movs ip, ip, lsr #32 - PAGE_SHIFT
...@@ -264,18 +265,18 @@ USER( strt r3, [r0], #4) @ May fault ...@@ -264,18 +265,18 @@ USER( strt r3, [r0], #4) @ May fault
movne r3, r7, pull #24 movne r3, r7, pull #24
ldrne r7, [r1], #4 ldrne r7, [r1], #4
orrne r3, r3, r7, push #8 orrne r3, r3, r7, push #8
strnet r3, [r0], #4 @ Shouldnt fault T(strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3 ands ip, ip, #3
beq .Lc2u_3fupi beq .Lc2u_3fupi
.Lc2u_3nowords: mov r3, r7, get_byte_3 .Lc2u_3nowords: mov r3, r7, get_byte_3
teq ip, #0 teq ip, #0
beq .Lc2u_finished beq .Lc2u_finished
cmp ip, #2 cmp ip, #2
USER( strbt r3, [r0], #1) @ May fault USER( T(strb) r3, [r0], #1) @ May fault
ldrgeb r3, [r1], #1 ldrgeb r3, [r1], #1
USER( strgebt r3, [r0], #1) @ May fault USER( T(strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #0 ldrgtb r3, [r1], #0
USER( strgtbt r3, [r0], #1) @ May fault USER( T(strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished b .Lc2u_finished
ENDPROC(__copy_to_user) ENDPROC(__copy_to_user)
...@@ -294,11 +295,11 @@ ENDPROC(__copy_to_user) ...@@ -294,11 +295,11 @@ ENDPROC(__copy_to_user)
.Lcfu_dest_not_aligned: .Lcfu_dest_not_aligned:
rsb ip, ip, #4 rsb ip, ip, #4
cmp ip, #2 cmp ip, #2
USER( ldrbt r3, [r1], #1) @ May fault USER( T(ldrb) r3, [r1], #1) @ May fault
strb r3, [r0], #1 strb r3, [r0], #1
USER( ldrgebt r3, [r1], #1) @ May fault USER( T(ldrgeb) r3, [r1], #1) @ May fault
strgeb r3, [r0], #1 strgeb r3, [r0], #1
USER( ldrgtbt r3, [r1], #1) @ May fault USER( T(ldrgtb) r3, [r1], #1) @ May fault
strgtb r3, [r0], #1 strgtb r3, [r0], #1
sub r2, r2, ip sub r2, r2, ip
b .Lcfu_dest_aligned b .Lcfu_dest_aligned
...@@ -321,7 +322,7 @@ ENTRY(__copy_from_user) ...@@ -321,7 +322,7 @@ ENTRY(__copy_from_user)
.Lcfu_0fupi: subs r2, r2, #4 .Lcfu_0fupi: subs r2, r2, #4
addmi ip, r2, #4 addmi ip, r2, #4
bmi .Lcfu_0nowords bmi .Lcfu_0nowords
USER( ldrt r3, [r1], #4) USER( T(ldr) r3, [r1], #4)
str r3, [r0], #4 str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
rsb ip, ip, #0 rsb ip, ip, #0
...@@ -350,18 +351,18 @@ USER( ldrt r3, [r1], #4) ...@@ -350,18 +351,18 @@ USER( ldrt r3, [r1], #4)
ldmneia r1!, {r3 - r4} @ Shouldnt fault ldmneia r1!, {r3 - r4} @ Shouldnt fault
stmneia r0!, {r3 - r4} stmneia r0!, {r3 - r4}
tst ip, #4 tst ip, #4
ldrnet r3, [r1], #4 @ Shouldnt fault T(ldrne) r3, [r1], #4 @ Shouldnt fault
strne r3, [r0], #4 strne r3, [r0], #4
ands ip, ip, #3 ands ip, ip, #3
beq .Lcfu_0fupi beq .Lcfu_0fupi
.Lcfu_0nowords: teq ip, #0 .Lcfu_0nowords: teq ip, #0
beq .Lcfu_finished beq .Lcfu_finished
.Lcfu_nowords: cmp ip, #2 .Lcfu_nowords: cmp ip, #2
USER( ldrbt r3, [r1], #1) @ May fault USER( T(ldrb) r3, [r1], #1) @ May fault
strb r3, [r0], #1 strb r3, [r0], #1
USER( ldrgebt r3, [r1], #1) @ May fault USER( T(ldrgeb) r3, [r1], #1) @ May fault
strgeb r3, [r0], #1 strgeb r3, [r0], #1
USER( ldrgtbt r3, [r1], #1) @ May fault USER( T(ldrgtb) r3, [r1], #1) @ May fault
strgtb r3, [r0], #1 strgtb r3, [r0], #1
b .Lcfu_finished b .Lcfu_finished
...@@ -374,7 +375,7 @@ USER( ldrgtbt r3, [r1], #1) @ May fault ...@@ -374,7 +375,7 @@ USER( ldrgtbt r3, [r1], #1) @ May fault
.Lcfu_src_not_aligned: .Lcfu_src_not_aligned:
bic r1, r1, #3 bic r1, r1, #3
USER( ldrt r7, [r1], #4) @ May fault USER( T(ldr) r7, [r1], #4) @ May fault
cmp ip, #2 cmp ip, #2
bgt .Lcfu_3fupi bgt .Lcfu_3fupi
beq .Lcfu_2fupi beq .Lcfu_2fupi
...@@ -382,7 +383,7 @@ USER( ldrt r7, [r1], #4) @ May fault ...@@ -382,7 +383,7 @@ USER( ldrt r7, [r1], #4) @ May fault
addmi ip, r2, #4 addmi ip, r2, #4
bmi .Lcfu_1nowords bmi .Lcfu_1nowords
mov r3, r7, pull #8 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 orr r3, r3, r7, push #24
str r3, [r0], #4 str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT mov ip, r1, lsl #32 - PAGE_SHIFT
...@@ -417,7 +418,7 @@ USER( ldrt r7, [r1], #4) @ May fault ...@@ -417,7 +418,7 @@ USER( ldrt r7, [r1], #4) @ May fault
stmneia r0!, {r3 - r4} stmneia r0!, {r3 - r4}
tst ip, #4 tst ip, #4
movne r3, r7, pull #8 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 orrne r3, r3, r7, push #24
strne r3, [r0], #4 strne r3, [r0], #4
ands ip, ip, #3 ands ip, ip, #3
...@@ -437,7 +438,7 @@ USER( ldrnet r7, [r1], #4) @ May fault ...@@ -437,7 +438,7 @@ USER( ldrnet r7, [r1], #4) @ May fault
addmi ip, r2, #4 addmi ip, r2, #4
bmi .Lcfu_2nowords bmi .Lcfu_2nowords
mov r3, r7, pull #16 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 orr r3, r3, r7, push #16
str r3, [r0], #4 str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT mov ip, r1, lsl #32 - PAGE_SHIFT
...@@ -473,7 +474,7 @@ USER( ldrt r7, [r1], #4) @ May fault ...@@ -473,7 +474,7 @@ USER( ldrt r7, [r1], #4) @ May fault
stmneia r0!, {r3 - r4} stmneia r0!, {r3 - r4}
tst ip, #4 tst ip, #4
movne r3, r7, pull #16 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 orrne r3, r3, r7, push #16
strne r3, [r0], #4 strne r3, [r0], #4
ands ip, ip, #3 ands ip, ip, #3
...@@ -485,7 +486,7 @@ USER( ldrnet r7, [r1], #4) @ May fault ...@@ -485,7 +486,7 @@ USER( ldrnet r7, [r1], #4) @ May fault
strb r3, [r0], #1 strb r3, [r0], #1
movge r3, r7, get_byte_3 movge r3, r7, get_byte_3
strgeb r3, [r0], #1 strgeb r3, [r0], #1
USER( ldrgtbt r3, [r1], #0) @ May fault USER( T(ldrgtb) r3, [r1], #0) @ May fault
strgtb r3, [r0], #1 strgtb r3, [r0], #1
b .Lcfu_finished b .Lcfu_finished
...@@ -493,7 +494,7 @@ USER( ldrgtbt r3, [r1], #0) @ May fault ...@@ -493,7 +494,7 @@ USER( ldrgtbt r3, [r1], #0) @ May fault
addmi ip, r2, #4 addmi ip, r2, #4
bmi .Lcfu_3nowords bmi .Lcfu_3nowords
mov r3, r7, pull #24 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 orr r3, r3, r7, push #8
str r3, [r0], #4 str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT mov ip, r1, lsl #32 - PAGE_SHIFT
...@@ -528,7 +529,7 @@ USER( ldrt r7, [r1], #4) @ May fault ...@@ -528,7 +529,7 @@ USER( ldrt r7, [r1], #4) @ May fault
stmneia r0!, {r3 - r4} stmneia r0!, {r3 - r4}
tst ip, #4 tst ip, #4
movne r3, r7, pull #24 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 orrne r3, r3, r7, push #8
strne r3, [r0], #4 strne r3, [r0], #4
ands ip, ip, #3 ands ip, ip, #3
...@@ -538,9 +539,9 @@ USER( ldrnet r7, [r1], #4) @ May fault ...@@ -538,9 +539,9 @@ USER( ldrnet r7, [r1], #4) @ May fault
beq .Lcfu_finished beq .Lcfu_finished
cmp ip, #2 cmp ip, #2
strb r3, [r0], #1 strb r3, [r0], #1
USER( ldrgebt r3, [r1], #1) @ May fault USER( T(ldrgeb) r3, [r1], #1) @ May fault
strgeb r3, [r0], #1 strgeb r3, [r0], #1
USER( ldrgtbt r3, [r1], #1) @ May fault USER( T(ldrgtb) r3, [r1], #1) @ May fault
strgtb r3, [r0], #1 strgtb r3, [r0], #1
b .Lcfu_finished b .Lcfu_finished
ENDPROC(__copy_from_user) ENDPROC(__copy_from_user)
......
...@@ -21,13 +21,12 @@ ...@@ -21,13 +21,12 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/clkdev.h>
#include <mach/csp/hw_cfg.h> #include <mach/csp/hw_cfg.h>
#include <mach/csp/chipcHw_def.h> #include <mach/csp/chipcHw_def.h>
#include <mach/csp/chipcHw_reg.h> #include <mach/csp/chipcHw_reg.h>
#include <mach/csp/chipcHw_inline.h> #include <mach/csp/chipcHw_inline.h>
#include <asm/clkdev.h>
#include "clock.h" #include "clock.h"
#define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY) #define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY)
......
...@@ -30,10 +30,10 @@ ...@@ -30,10 +30,10 @@
#include <linux/amba/bus.h> #include <linux/amba/bus.h>
#include <linux/clocksource.h> #include <linux/clocksource.h>
#include <linux/clockchips.h> #include <linux/clockchips.h>
#include <linux/clkdev.h>
#include <mach/csp/mm_addr.h> #include <mach/csp/mm_addr.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/clkdev.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/hardware/arm_timer.h> #include <asm/hardware/arm_timer.h>
......
...@@ -3,6 +3,7 @@ menu "CNS3XXX platform type" ...@@ -3,6 +3,7 @@ menu "CNS3XXX platform type"
config MACH_CNS3420VB config MACH_CNS3420VB
bool "Support for CNS3420 Validation Board" bool "Support for CNS3420 Validation Board"
select MIGHT_HAVE_PCI
help help
Include support for the Cavium Networks CNS3420 MPCore Platform Include support for the Cavium Networks CNS3420 MPCore Platform
Baseboard. Baseboard.
......
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
#include <linux/list.h> #include <linux/list.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#define PLLSTAT_GOSTAT BIT(0) #define PLLSTAT_GOSTAT BIT(0)
#define PLLCMD_GOSET BIT(0) #define PLLCMD_GOSET BIT(0)
......
...@@ -19,10 +19,10 @@ ...@@ -19,10 +19,10 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/clkdev.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/clkdev.h>
#include <asm/div64.h> #include <asm/div64.h>
......
...@@ -22,8 +22,7 @@ ...@@ -22,8 +22,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <mach/clock.h> #include <mach/clock.h>
#include <mach/hardware.h> #include <mach/hardware.h>
......
...@@ -21,11 +21,11 @@ ...@@ -21,11 +21,11 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/clkdev.h>
#include <mach/clock.h> #include <mach/clock.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/common.h> #include <mach/common.h>
#include <asm/clkdev.h>
#include <asm/div64.h> #include <asm/div64.h>
#define IO_ADDR_CCM(off) (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off))) #define IO_ADDR_CCM(off) (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off)))
......
...@@ -21,8 +21,8 @@ ...@@ -21,8 +21,8 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <asm/div64.h> #include <asm/div64.h>
#include <mach/clock.h> #include <mach/clock.h>
......
...@@ -4,6 +4,7 @@ menu "Integrator Options" ...@@ -4,6 +4,7 @@ menu "Integrator Options"
config ARCH_INTEGRATOR_AP config ARCH_INTEGRATOR_AP
bool "Support Integrator/AP and Integrator/PP2 platforms" bool "Support Integrator/AP and Integrator/PP2 platforms"
select MIGHT_HAVE_PCI
help help
Include support for the ARM(R) Integrator/AP and Include support for the ARM(R) Integrator/AP and
Integrator/PP2 platforms. Integrator/PP2 platforms.
......
...@@ -21,9 +21,8 @@ ...@@ -21,9 +21,8 @@
#include <linux/amba/bus.h> #include <linux/amba/bus.h>
#include <linux/amba/serial.h> #include <linux/amba/serial.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <mach/clkdev.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/platform.h> #include <mach/platform.h>
#include <asm/irq.h> #include <asm/irq.h>
......
...@@ -22,9 +22,8 @@ ...@@ -22,9 +22,8 @@
#include <linux/amba/clcd.h> #include <linux/amba/clcd.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <mach/clkdev.h>
#include <asm/hardware/icst.h> #include <asm/hardware/icst.h>
#include <mach/lm.h> #include <mach/lm.h>
#include <mach/impd1.h> #include <mach/impd1.h>
......
...@@ -21,9 +21,8 @@ ...@@ -21,9 +21,8 @@
#include <linux/amba/mmci.h> #include <linux/amba/mmci.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <mach/clkdev.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/platform.h> #include <mach/platform.h>
#include <asm/irq.h> #include <asm/irq.h>
......
...@@ -58,13 +58,13 @@ static inline unsigned long __lbus_to_virt(dma_addr_t x) ...@@ -58,13 +58,13 @@ static inline unsigned long __lbus_to_virt(dma_addr_t x)
__dma; \ __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 */ \ /* __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 /* CONFIG_ARCH_IOP13XX */
#endif /* !ASSEMBLY */ #endif /* !ASSEMBLY */
......
...@@ -4,6 +4,7 @@ menu "Kendin/Micrel KS8695 Implementations" ...@@ -4,6 +4,7 @@ menu "Kendin/Micrel KS8695 Implementations"
config MACH_KS8695 config MACH_KS8695
bool "KS8695 development board" bool "KS8695 development board"
select MIGHT_HAVE_PCI
help help
Say 'Y' here if you want your kernel to run on the original Say 'Y' here if you want your kernel to run on the original
Kendin-Micrel KS8695 development board. Kendin-Micrel KS8695 development board.
......
...@@ -35,17 +35,17 @@ extern struct bus_type platform_bus_type; ...@@ -35,17 +35,17 @@ extern struct bus_type platform_bus_type;
__phys_to_virt(x) : __bus_to_virt(x)); }) __phys_to_virt(x) : __bus_to_virt(x)); })
#define __arch_virt_to_dma(dev, x) ({ is_lbus_device(dev) ? \ #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); }) (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); })
#define __arch_page_to_dma(dev, x) \ #define __arch_pfn_to_dma(dev, pfn) \
({ dma_addr_t __dma = page_to_phys(page); \ ({ dma_addr_t __dma = __pfn_to_phys(pfn); \
if (!is_lbus_device(dev)) \ if (!is_lbus_device(dev)) \
__dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \ __dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \
__dma; }) __dma; })
#define __arch_dma_to_page(dev, x) \ #define __arch_dma_to_pfn(dev, x) \
({ dma_addr_t __dma = x; \ ({ dma_addr_t __dma = x; \
if (!is_lbus_device(dev)) \ if (!is_lbus_device(dev)) \
__dma += PHYS_OFFSET - KS8695_PCIMEM_PA; \ __dma += PHYS_OFFSET - KS8695_PCIMEM_PA; \
phys_to_page(__dma); \ __phys_to_pfn(__dma); \
}) })
#endif #endif
......
...@@ -90,10 +90,9 @@ ...@@ -90,10 +90,9 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/amba/bus.h> #include <linux/amba/bus.h>
#include <linux/amba/clcd.h> #include <linux/amba/clcd.h>
#include <linux/clkdev.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/clkdev.h>
#include <mach/clkdev.h>
#include <mach/platform.h> #include <mach/platform.h>
#include "clock.h" #include "clock.h"
#include "common.h" #include "common.h"
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <asm/clkdev.h> #include <linux/clkdev.h>
struct clkops { struct clkops {
void (*enable)(struct clk *); void (*enable)(struct clk *);
......
...@@ -31,9 +31,9 @@ ...@@ -31,9 +31,9 @@
#include <asm/hardware/gic.h> #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 #endif
...@@ -21,8 +21,7 @@ ...@@ -21,8 +21,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <mach/clock.h> #include <mach/clock.h>
#include <mach/hardware.h> #include <mach/hardware.h>
......
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <asm/div64.h> #include <asm/div64.h>
#include <mach/clock.h> #include <mach/clock.h>
......
...@@ -21,8 +21,7 @@ ...@@ -21,8 +21,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <mach/clock.h> #include <mach/clock.h>
#include <mach/hardware.h> #include <mach/hardware.h>
......
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <asm/div64.h> #include <asm/div64.h>
#include <mach/hardware.h> #include <mach/hardware.h>
......
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clkdev.h>
#include <mach/clock.h> #include <mach/clock.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/common.h> #include <mach/common.h>
#include <asm/clkdev.h>
#include <asm/bug.h> #include <asm/bug.h>
#include <asm/div64.h> #include <asm/div64.h>
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include "clock.h" #include "clock.h"
/* /*
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* the Free Software Foundation; either version 2 of the License. * 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 nuc93x_clk_enable(struct clk *clk, int enable);
void clks_register(struct clk_lookup *clks, size_t num); void clks_register(struct clk_lookup *clks, size_t num);
......
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clkdev.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/clkdev.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/usb.h> #include <plat/usb.h>
......
...@@ -26,10 +26,10 @@ ...@@ -26,10 +26,10 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/clkdev.h>
#include <plat/cpu.h> #include <plat/cpu.h>
#include <plat/clock.h> #include <plat/clock.h>
#include <asm/clkdev.h>
#include "clock.h" #include "clock.h"
#include "prm.h" #include "prm.h"
......
...@@ -17,16 +17,13 @@ ...@@ -17,16 +17,13 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/completion.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <mach/omap4-common.h> #include <mach/omap4-common.h>
static DECLARE_COMPLETION(cpu_killed);
int platform_cpu_kill(unsigned int cpu) 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) ...@@ -35,15 +32,6 @@ int platform_cpu_kill(unsigned int cpu)
*/ */
void platform_cpu_die(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(); flush_cache_all();
dsb(); dsb();
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/localtimer.h>
#include <asm/smp_scu.h> #include <asm/smp_scu.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/omap4-common.h> #include <mach/omap4-common.h>
...@@ -29,22 +28,10 @@ ...@@ -29,22 +28,10 @@
/* SCU base address */ /* SCU base address */
static void __iomem *scu_base; 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); static DEFINE_SPINLOCK(boot_lock);
void __cpuinit platform_secondary_init(unsigned int cpu) void __cpuinit platform_secondary_init(unsigned int cpu)
{ {
trace_hardirqs_off();
/* /*
* If any interrupts are already enabled for the primary * If any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled * 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) ...@@ -76,7 +63,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
omap_modify_auxcoreboot0(0x200, 0xfffffdff); omap_modify_auxcoreboot0(0x200, 0xfffffdff);
flush_cache_all(); flush_cache_all();
smp_wmb(); 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 * Now the secondary core is starting up let it run its
...@@ -118,25 +105,9 @@ void __init smp_init_cpus(void) ...@@ -118,25 +105,9 @@ void __init smp_init_cpus(void)
scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256); scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256);
BUG_ON(!scu_base); BUG_ON(!scu_base);
ncores = get_core_count(); ncores = scu_get_core_count(scu_base);
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;
/* sanity check */ /* sanity check */
if (ncores == 0) {
printk(KERN_ERR
"OMAP4: strange core count of 0? Default to 1\n");
ncores = 1;
}
if (ncores > NR_CPUS) { if (ncores > NR_CPUS) {
printk(KERN_WARNING printk(KERN_WARNING
"OMAP4: no. of cores (%d) greater than configured " "OMAP4: no. of cores (%d) greater than configured "
...@@ -144,13 +115,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -144,13 +115,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
ncores, NR_CPUS); ncores, NR_CPUS);
ncores = NR_CPUS; ncores = NR_CPUS;
} }
smp_store_cpu_info(cpu);
/* for (i = 0; i < ncores; i++)
* are we trying to boot more cores than exist? set_cpu_possible(i, true);
*/ }
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 * Initialise the present map, which describes the set of CPUs
...@@ -159,18 +131,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -159,18 +131,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
for (i = 0; i < max_cpus; i++) for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true); 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 * Initialise the SCU and wake up the secondary core using
* wakeup_secondary(). * wakeup_secondary().
*/ */
scu_enable(scu_base); scu_enable(scu_base);
wakeup_secondary(); wakeup_secondary();
}
} }
...@@ -21,8 +21,7 @@ ...@@ -21,8 +21,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/clock.h> #include <mach/clock.h>
......
...@@ -94,6 +94,7 @@ config MACH_ARMCORE ...@@ -94,6 +94,7 @@ config MACH_ARMCORE
select PXA27x select PXA27x
select IWMMXT select IWMMXT
select PXA25x select PXA25x
select MIGHT_HAVE_PCI
config MACH_EM_X270 config MACH_EM_X270
bool "CompuLab EM-x270 platform" bool "CompuLab EM-x270 platform"
......
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <mach/pxa2xx-regs.h> #include <mach/pxa2xx-regs.h>
#include <mach/hardware.h> #include <mach/hardware.h>
......
#include <asm/clkdev.h> #include <linux/clkdev.h>
struct clkops { struct clkops {
void (*enable)(struct clk *); void (*enable)(struct clk *);
......
...@@ -30,8 +30,8 @@ ...@@ -30,8 +30,8 @@
#include <linux/ata_platform.h> #include <linux/ata_platform.h>
#include <linux/amba/mmci.h> #include <linux/amba/mmci.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <asm/system.h> #include <asm/system.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -47,7 +47,6 @@ ...@@ -47,7 +47,6 @@
#include <asm/hardware/gic.h> #include <asm/hardware/gic.h>
#include <mach/clkdev.h>
#include <mach/platform.h> #include <mach/platform.h>
#include <mach/irqs.h> #include <mach/irqs.h>
#include <asm/hardware/timer-sp.h> #include <asm/hardware/timer-sp.h>
......
...@@ -11,14 +11,11 @@ ...@@ -11,14 +11,11 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/completion.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
extern volatile int pen_release; extern volatile int pen_release;
static DECLARE_COMPLETION(cpu_killed);
static inline void cpu_enter_lowpower(void) static inline void cpu_enter_lowpower(void)
{ {
unsigned int v; unsigned int v;
...@@ -34,10 +31,10 @@ static inline void cpu_enter_lowpower(void) ...@@ -34,10 +31,10 @@ static inline void cpu_enter_lowpower(void)
" bic %0, %0, #0x20\n" " bic %0, %0, #0x20\n"
" mcr p15, 0, %0, c1, c0, 1\n" " mcr p15, 0, %0, c1, c0, 1\n"
" mrc p15, 0, %0, c1, c0, 0\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" " mcr p15, 0, %0, c1, c0, 0\n"
: "=&r" (v) : "=&r" (v)
: "r" (0) : "r" (0), "Ir" (CR_C)
: "cc"); : "cc");
} }
...@@ -46,17 +43,17 @@ static inline void cpu_leave_lowpower(void) ...@@ -46,17 +43,17 @@ static inline void cpu_leave_lowpower(void)
unsigned int v; unsigned int v;
asm volatile( "mrc p15, 0, %0, c1, c0, 0\n" 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" " mcr p15, 0, %0, c1, c0, 0\n"
" mrc p15, 0, %0, c1, c0, 1\n" " mrc p15, 0, %0, c1, c0, 1\n"
" orr %0, %0, #0x20\n" " orr %0, %0, #0x20\n"
" mcr p15, 0, %0, c1, c0, 1\n" " mcr p15, 0, %0, c1, c0, 1\n"
: "=&r" (v) : "=&r" (v)
: : "Ir" (CR_C)
: "cc"); : "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 * there is no power-control hardware on this platform, so all
...@@ -80,22 +77,19 @@ static inline void platform_do_lowpower(unsigned int cpu) ...@@ -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 * having been woken up - this shouldn't happen
* *
* The trouble is, letting people know about this is not really * Just note it happening - when we're woken, we can report
* possible, since we are currently running incoherently, and * its occurrence.
* therefore cannot safely call printk() or anything else
*/ */
#ifdef DEBUG (*spurious)++;
printk("CPU%u: spurious wakeup call\n", cpu);
#endif
} }
} }
int platform_cpu_kill(unsigned int cpu) 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) ...@@ -105,30 +99,22 @@ int platform_cpu_kill(unsigned int cpu)
*/ */
void platform_cpu_die(unsigned int cpu) void platform_cpu_die(unsigned int cpu)
{ {
#ifdef DEBUG int spurious = 0;
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);
/* /*
* we're ready for shutdown now, so do it * we're ready for shutdown now, so do it
*/ */
cpu_enter_lowpower(); cpu_enter_lowpower();
platform_do_lowpower(cpu); platform_do_lowpower(cpu, &spurious);
/* /*
* bring this CPU back into the world of cache * bring this CPU back into the world of cache
* coherency, and then restore interrupts * coherency, and then restore interrupts
*/ */
cpu_leave_lowpower(); cpu_leave_lowpower();
if (spurious)
pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
} }
int platform_cpu_disable(unsigned int cpu) int platform_cpu_disable(unsigned int cpu)
......
...@@ -2,14 +2,13 @@ ...@@ -2,14 +2,13 @@
#define ASMARM_ARCH_SMP_H #define ASMARM_ARCH_SMP_H
#include <asm/hardware/gic.h> #include <asm/hardware/gic.h>
#include <asm/smp_mpidr.h>
/* /*
* We use IRQ1 as the IPI * 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 #endif
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/localtimer.h>
#include <asm/unified.h> #include <asm/unified.h>
#include <mach/board-eb.h> #include <mach/board-eb.h>
...@@ -37,6 +36,19 @@ extern void realview_secondary_startup(void); ...@@ -37,6 +36,19 @@ extern void realview_secondary_startup(void);
*/ */
volatile int __cpuinitdata pen_release = -1; 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) static void __iomem *scu_base_addr(void)
{ {
if (machine_is_realview_eb_mp()) if (machine_is_realview_eb_mp())
...@@ -50,20 +62,10 @@ static void __iomem *scu_base_addr(void) ...@@ -50,20 +62,10 @@ static void __iomem *scu_base_addr(void)
return (void __iomem *)0; 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); static DEFINE_SPINLOCK(boot_lock);
void __cpuinit platform_secondary_init(unsigned int cpu) void __cpuinit platform_secondary_init(unsigned int cpu)
{ {
trace_hardirqs_off();
/* /*
* if any interrupts are already enabled for the primary * if any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled * core (e.g. timer irq), then they will not have been enabled
...@@ -75,8 +77,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) ...@@ -75,8 +77,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* let the primary processor know we're out of the * let the primary processor know we're out of the
* pen, then head off into the C entry point * pen, then head off into the C entry point
*/ */
pen_release = -1; write_pen_release(-1);
smp_wmb();
/* /*
* Synchronise with the boot thread. * Synchronise with the boot thread.
...@@ -103,20 +104,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -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 * Note that "pen_release" is the hardware CPU ID, whereas
* "cpu" is Linux's internal ID. * "cpu" is Linux's internal ID.
*/ */
pen_release = cpu; write_pen_release(cpu);
flush_cache_all();
/* /*
* XXX * Send the secondary CPU a soft interrupt, thereby causing
* * the boot monitor to read the system wide flags register,
* This is a later addition to the booting protocol: the * and branch to the address found there.
* 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
*/ */
smp_cross_call(cpumask_of(cpu)); smp_cross_call(cpumask_of(cpu), 1);
timeout = jiffies + (1 * HZ); timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) { while (time_before(jiffies, timeout)) {
...@@ -136,48 +131,18 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -136,48 +131,18 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
return pen_release != -1 ? -ENOSYS : 0; 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 * Initialise the CPU possible map early - this describes the CPUs
* which may be present or become present in the system. * which may be present or become present in the system.
*/ */
void __init smp_init_cpus(void) 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) ncores = scu_base ? scu_get_core_count(scu_base) : 1;
{
unsigned int ncores = get_core_count();
unsigned int cpu = smp_processor_id();
int i;
/* sanity check */ /* sanity check */
if (ncores == 0) {
printk(KERN_ERR
"Realview: strange CM count of 0? Default to 1\n");
ncores = 1;
}
if (ncores > NR_CPUS) { if (ncores > NR_CPUS) {
printk(KERN_WARNING printk(KERN_WARNING
"Realview: no. of cores (%d) greater than configured " "Realview: no. of cores (%d) greater than configured "
...@@ -186,13 +151,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -186,13 +151,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
ncores = NR_CPUS; ncores = NR_CPUS;
} }
smp_store_cpu_info(cpu); for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);
}
/* void __init platform_smp_prepare_cpus(unsigned int max_cpus)
* are we trying to boot more cores than exist? {
*/ int i;
if (max_cpus > ncores)
max_cpus = ncores;
/* /*
* Initialise the present map, which describes the set of CPUs * Initialise the present map, which describes the set of CPUs
...@@ -201,21 +166,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -201,21 +166,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
for (i = 0; i < max_cpus; i++) for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true); set_cpu_present(i, true);
scu_enable(scu_base_addr());
/* /*
* Initialise the SCU if there are more than one CPU and let * Write the address of secondary startup into the
* them know where to start. Note that, on modern versions of * system-wide flags register. The BootMonitor waits
* MILO, the "poke" doesn't actually do anything until each * until it receives a soft interrupt, and then the
* individual core is sent a soft interrupt to get it out of * secondary CPU branches to this address.
* WFI
*/
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(); __raw_writel(BSYM(virt_to_phys(realview_secondary_startup)),
__io_address(REALVIEW_SYS_FLAGSSET));
scu_enable(scu_base_addr());
poke_milo();
}
} }
...@@ -59,7 +59,7 @@ config MACH_JIVE ...@@ -59,7 +59,7 @@ config MACH_JIVE
Say Y here if you are using the Logitech Jive. Say Y here if you are using the Logitech Jive.
config MACH_JIVE_SHOW_BOOTLOADER 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 depends on MACH_JIVE && EXPERIMENTAL
config MACH_SMDK2413 config MACH_SMDK2413
......
...@@ -13,14 +13,11 @@ ...@@ -13,14 +13,11 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/completion.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
extern volatile int pen_release; extern volatile int pen_release;
static DECLARE_COMPLETION(cpu_killed);
static inline void cpu_enter_lowpower(void) static inline void cpu_enter_lowpower(void)
{ {
unsigned int v; unsigned int v;
...@@ -33,13 +30,13 @@ static inline void cpu_enter_lowpower(void) ...@@ -33,13 +30,13 @@ static inline void cpu_enter_lowpower(void)
* Turn off coherency * Turn off coherency
*/ */
" mrc p15, 0, %0, c1, c0, 1\n" " 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" " mcr p15, 0, %0, c1, c0, 1\n"
" mrc p15, 0, %0, c1, c0, 0\n" " mrc p15, 0, %0, c1, c0, 0\n"
" bic %0, %0, #0x04\n" " bic %0, %0, #0x04\n"
" mcr p15, 0, %0, c1, c0, 0\n" " mcr p15, 0, %0, c1, c0, 0\n"
: "=&r" (v) : "=&r" (v)
: "r" (0) : "r" (0), "Ir" (CR_C)
: "cc"); : "cc");
} }
...@@ -49,17 +46,17 @@ static inline void cpu_leave_lowpower(void) ...@@ -49,17 +46,17 @@ static inline void cpu_leave_lowpower(void)
asm volatile( asm volatile(
"mrc p15, 0, %0, c1, c0, 0\n" "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" " mcr p15, 0, %0, c1, c0, 0\n"
" mrc p15, 0, %0, c1, c0, 1\n" " mrc p15, 0, %0, c1, c0, 1\n"
" orr %0, %0, #0x20\n" " orr %0, %0, #0x20\n"
" mcr p15, 0, %0, c1, c0, 1\n" " mcr p15, 0, %0, c1, c0, 1\n"
: "=&r" (v) : "=&r" (v)
: : "Ir" (CR_C)
: "cc"); : "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 * there is no power-control hardware on this platform, so all
...@@ -83,22 +80,19 @@ static inline void platform_do_lowpower(unsigned int cpu) ...@@ -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 * having been woken up - this shouldn't happen
* *
* The trouble is, letting people know about this is not really * Just note it happening - when we're woken, we can report
* possible, since we are currently running incoherently, and * its occurrence.
* therefore cannot safely call printk() or anything else
*/ */
#ifdef DEBUG (*spurious)++;
printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
#endif
} }
} }
int platform_cpu_kill(unsigned int cpu) 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) ...@@ -108,30 +102,22 @@ int platform_cpu_kill(unsigned int cpu)
*/ */
void platform_cpu_die(unsigned int cpu) void platform_cpu_die(unsigned int cpu)
{ {
#ifdef DEBUG int spurious = 0;
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);
/* /*
* we're ready for shutdown now, so do it * we're ready for shutdown now, so do it
*/ */
cpu_enter_lowpower(); cpu_enter_lowpower();
platform_do_lowpower(cpu); platform_do_lowpower(cpu, &spurious);
/* /*
* bring this CPU back into the world of cache * bring this CPU back into the world of cache
* coherency, and then restore interrupts * coherency, and then restore interrupts
*/ */
cpu_leave_lowpower(); cpu_leave_lowpower();
if (spurious)
pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
} }
int platform_cpu_disable(unsigned int cpu) int platform_cpu_disable(unsigned int cpu)
......
...@@ -7,14 +7,13 @@ ...@@ -7,14 +7,13 @@
#define ASM_ARCH_SMP_H __FILE__ #define ASM_ARCH_SMP_H __FILE__
#include <asm/hardware/gic.h> #include <asm/hardware/gic.h>
#include <asm/smp_mpidr.h>
/* /*
* We use IRQ1 as the IPI * 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 #endif
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/localtimer.h>
#include <asm/smp_scu.h> #include <asm/smp_scu.h>
#include <asm/unified.h> #include <asm/unified.h>
...@@ -38,6 +37,19 @@ extern void s5pv310_secondary_startup(void); ...@@ -38,6 +37,19 @@ extern void s5pv310_secondary_startup(void);
volatile int __cpuinitdata pen_release = -1; 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) static void __iomem *scu_base_addr(void)
{ {
return (void __iomem *)(S5P_VA_SCU); return (void __iomem *)(S5P_VA_SCU);
...@@ -47,8 +59,6 @@ static DEFINE_SPINLOCK(boot_lock); ...@@ -47,8 +59,6 @@ static DEFINE_SPINLOCK(boot_lock);
void __cpuinit platform_secondary_init(unsigned int cpu) void __cpuinit platform_secondary_init(unsigned int cpu)
{ {
trace_hardirqs_off();
/* /*
* if any interrupts are already enabled for the primary * if any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled * core (e.g. timer irq), then they will not have been enabled
...@@ -60,8 +70,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) ...@@ -60,8 +70,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* let the primary processor know we're out of the * let the primary processor know we're out of the
* pen, then head off into the C entry point * pen, then head off into the C entry point
*/ */
pen_release = -1; write_pen_release(-1);
smp_wmb();
/* /*
* Synchronise with the boot thread. * Synchronise with the boot thread.
...@@ -88,16 +97,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -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 * Note that "pen_release" is the hardware CPU ID, whereas
* "cpu" is Linux's internal ID. * "cpu" is Linux's internal ID.
*/ */
pen_release = cpu; write_pen_release(cpu);
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
/* /*
* Send the secondary CPU a soft interrupt, thereby causing * Send the secondary CPU a soft interrupt, thereby causing
* the boot monitor to read the system wide flags register, * the boot monitor to read the system wide flags register,
* and branch to the address found there. * and branch to the address found there.
*/ */
smp_cross_call(cpumask_of(cpu)); smp_cross_call(cpumask_of(cpu), 1);
timeout = jiffies + (1 * HZ); timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) { while (time_before(jiffies, timeout)) {
...@@ -130,13 +137,6 @@ void __init smp_init_cpus(void) ...@@ -130,13 +137,6 @@ void __init smp_init_cpus(void)
ncores = scu_base ? scu_get_core_count(scu_base) : 1; ncores = scu_base ? scu_get_core_count(scu_base) : 1;
/* sanity check */ /* sanity check */
if (ncores == 0) {
printk(KERN_ERR
"S5PV310: strange CM count of 0? Default to 1\n");
ncores = 1;
}
if (ncores > NR_CPUS) { if (ncores > NR_CPUS) {
printk(KERN_WARNING printk(KERN_WARNING
"S5PV310: no. of cores (%d) greater than configured " "S5PV310: no. of cores (%d) greater than configured "
...@@ -149,18 +149,10 @@ void __init smp_init_cpus(void) ...@@ -149,18 +149,10 @@ void __init smp_init_cpus(void)
set_cpu_possible(i, true); 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; 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 * Initialise the present map, which describes the set of CPUs
* actually populated at the present time. * actually populated at the present time.
...@@ -168,17 +160,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -168,17 +160,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
for (i = 0; i < max_cpus; i++) for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true); set_cpu_present(i, true);
/*
* Initialise the SCU if there are more than one CPU and let
* them know where to start.
*/
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()); scu_enable(scu_base_addr());
/* /*
...@@ -188,5 +169,4 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -188,5 +169,4 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
* secondary CPU branches to this address. * secondary CPU branches to this address.
*/ */
__raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_VA_SYSRAM); __raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_VA_SYSRAM);
}
} }
...@@ -6,7 +6,7 @@ config ARCH_SH7367 ...@@ -6,7 +6,7 @@ config ARCH_SH7367
bool "SH-Mobile G3 (SH7367)" bool "SH-Mobile G3 (SH7367)"
select CPU_V6 select CPU_V6
select HAVE_CLK select HAVE_CLK
select COMMON_CLKDEV select CLKDEV_LOOKUP
select SH_CLK_CPG select SH_CLK_CPG
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
...@@ -14,7 +14,7 @@ config ARCH_SH7377 ...@@ -14,7 +14,7 @@ config ARCH_SH7377
bool "SH-Mobile G4 (SH7377)" bool "SH-Mobile G4 (SH7377)"
select CPU_V7 select CPU_V7
select HAVE_CLK select HAVE_CLK
select COMMON_CLKDEV select CLKDEV_LOOKUP
select SH_CLK_CPG select SH_CLK_CPG
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
...@@ -22,7 +22,7 @@ config ARCH_SH7372 ...@@ -22,7 +22,7 @@ config ARCH_SH7372
bool "SH-Mobile AP4 (SH7372)" bool "SH-Mobile AP4 (SH7372)"
select CPU_V7 select CPU_V7
select HAVE_CLK select HAVE_CLK
select COMMON_CLKDEV select CLKDEV_LOOKUP
select SH_CLK_CPG select SH_CLK_CPG
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
......
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/sh_clk.h> #include <linux/sh_clk.h>
#include <linux/clkdev.h>
#include <mach/common.h> #include <mach/common.h>
#include <asm/clkdev.h>
/* SH7367 registers */ /* SH7367 registers */
#define RTFRQCR 0xe6150000 #define RTFRQCR 0xe6150000
......
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/sh_clk.h> #include <linux/sh_clk.h>
#include <linux/clkdev.h>
#include <mach/common.h> #include <mach/common.h>
#include <asm/clkdev.h>
/* SH7372 registers */ /* SH7372 registers */
#define FRQCRA 0xe6150000 #define FRQCRA 0xe6150000
......
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/sh_clk.h> #include <linux/sh_clk.h>
#include <linux/clkdev.h>
#include <mach/common.h> #include <mach/common.h>
#include <asm/clkdev.h>
/* SH7377 registers */ /* SH7377 registers */
#define RTFRQCR 0xe6150000 #define RTFRQCR 0xe6150000
......
...@@ -12,8 +12,7 @@ ...@@ -12,8 +12,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <mach/clock.h> #include <mach/clock.h>
#include <mach/irqs.h> #include <mach/irqs.h>
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include "clock.h" #include "clock.h"
#include "board.h" #include "board.h"
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#define __MACH_TEGRA_CLOCK_H #define __MACH_TEGRA_CLOCK_H
#include <linux/list.h> #include <linux/list.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#define DIV_BUS (1 << 0) #define DIV_BUS (1 << 0)
#define DIV_U71 (1 << 1) #define DIV_U71 (1 << 1)
......
...@@ -11,12 +11,9 @@ ...@@ -11,12 +11,9 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/completion.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
static DECLARE_COMPLETION(cpu_killed);
static inline void cpu_enter_lowpower(void) static inline void cpu_enter_lowpower(void)
{ {
unsigned int v; unsigned int v;
...@@ -29,13 +26,13 @@ static inline void cpu_enter_lowpower(void) ...@@ -29,13 +26,13 @@ static inline void cpu_enter_lowpower(void)
* Turn off coherency * Turn off coherency
*/ */
" mrc p15, 0, %0, c1, c0, 1\n" " 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" " mcr p15, 0, %0, c1, c0, 1\n"
" mrc p15, 0, %0, c1, c0, 0\n" " mrc p15, 0, %0, c1, c0, 0\n"
" bic %0, %0, #0x04\n" " bic %0, %0, #0x04\n"
" mcr p15, 0, %0, c1, c0, 0\n" " mcr p15, 0, %0, c1, c0, 0\n"
: "=&r" (v) : "=&r" (v)
: "r" (0) : "r" (0), "Ir" (CR_C)
: "cc"); : "cc");
} }
...@@ -45,17 +42,17 @@ static inline void cpu_leave_lowpower(void) ...@@ -45,17 +42,17 @@ static inline void cpu_leave_lowpower(void)
asm volatile( asm volatile(
"mrc p15, 0, %0, c1, c0, 0\n" "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" " mcr p15, 0, %0, c1, c0, 0\n"
" mrc p15, 0, %0, c1, c0, 1\n" " mrc p15, 0, %0, c1, c0, 1\n"
" orr %0, %0, #0x20\n" " orr %0, %0, #0x20\n"
" mcr p15, 0, %0, c1, c0, 1\n" " mcr p15, 0, %0, c1, c0, 1\n"
: "=&r" (v) : "=&r" (v)
: : "Ir" (CR_C)
: "cc"); : "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 * there is no power-control hardware on this platform, so all
...@@ -79,22 +76,19 @@ static inline void platform_do_lowpower(unsigned int cpu) ...@@ -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 * having been woken up - this shouldn't happen
* *
* The trouble is, letting people know about this is not really * Just note it happening - when we're woken, we can report
* possible, since we are currently running incoherently, and * its occurrence.
* therefore cannot safely call printk() or anything else
*/ */
#ifdef DEBUG (*spurious)++;
printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
#endif
} }
} }
int platform_cpu_kill(unsigned int cpu) 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) ...@@ -104,30 +98,22 @@ int platform_cpu_kill(unsigned int cpu)
*/ */
void platform_cpu_die(unsigned int cpu) void platform_cpu_die(unsigned int cpu)
{ {
#ifdef DEBUG int spurious = 0;
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);
/* /*
* we're ready for shutdown now, so do it * we're ready for shutdown now, so do it
*/ */
cpu_enter_lowpower(); cpu_enter_lowpower();
platform_do_lowpower(cpu); platform_do_lowpower(cpu, &spurious);
/* /*
* bring this CPU back into the world of cache * bring this CPU back into the world of cache
* coherency, and then restore interrupts * coherency, and then restore interrupts
*/ */
cpu_leave_lowpower(); cpu_leave_lowpower();
if (spurious)
pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
} }
int platform_cpu_disable(unsigned int cpu) int platform_cpu_disable(unsigned int cpu)
......
...@@ -2,21 +2,13 @@ ...@@ -2,21 +2,13 @@
#define ASMARM_ARCH_SMP_H #define ASMARM_ARCH_SMP_H
#include <asm/hardware/gic.h> #include <asm/hardware/gic.h>
#include <asm/smp_mpidr.h>
/* /*
* We use IRQ1 as the IPI * 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);
}
/*
* Do nothing on MPcore.
*/
static inline void smp_cross_call_done(cpumask_t callmap)
{ {
gic_raise_softirq(mask, ipi);
} }
#endif #endif
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/localtimer.h>
#include <asm/smp_scu.h> #include <asm/smp_scu.h>
#include <mach/iomap.h> #include <mach/iomap.h>
...@@ -41,8 +40,6 @@ static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE); ...@@ -41,8 +40,6 @@ static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
void __cpuinit platform_secondary_init(unsigned int cpu) void __cpuinit platform_secondary_init(unsigned int cpu)
{ {
trace_hardirqs_off();
/* /*
* if any interrupts are already enabled for the primary * if any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled * core (e.g. timer irq), then they will not have been enabled
...@@ -117,24 +114,20 @@ void __init smp_init_cpus(void) ...@@ -117,24 +114,20 @@ void __init smp_init_cpus(void)
{ {
unsigned int i, ncores = scu_get_core_count(scu_base); 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++) for (i = 0; i < ncores; i++)
cpu_set(i, cpu_possible_map); 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; 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 * Initialise the present map, which describes the set of CPUs
* actually populated at the present time. * actually populated at the present time.
...@@ -142,15 +135,5 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -142,15 +135,5 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
for (i = 0; i < max_cpus; i++) for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true); 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);
}
} }
...@@ -24,8 +24,7 @@ ...@@ -24,8 +24,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/hrtimer.h> #include <linux/hrtimer.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <mach/iomap.h> #include <mach/iomap.h>
......
...@@ -25,8 +25,8 @@ ...@@ -25,8 +25,8 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/syscon.h> #include <mach/syscon.h>
......
...@@ -13,8 +13,7 @@ ...@@ -13,8 +13,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <plat/mtu.h> #include <plat/mtu.h>
#include <mach/hardware.h> #include <mach/hardware.h>
......
...@@ -23,7 +23,6 @@ ENTRY(u8500_secondary_startup) ...@@ -23,7 +23,6 @@ ENTRY(u8500_secondary_startup)
ldmia r4, {r5, r6} ldmia r4, {r5, r6}
sub r4, r4, r5 sub r4, r4, r5
add r6, r6, r4 add r6, r6, r4
dsb
pen: ldr r7, [r6] pen: ldr r7, [r6]
cmp r7, r0 cmp r7, r0
bne pen bne pen
......
...@@ -11,14 +11,11 @@ ...@@ -11,14 +11,11 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/completion.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
extern volatile int pen_release; extern volatile int pen_release;
static DECLARE_COMPLETION(cpu_killed);
static inline void platform_do_lowpower(unsigned int cpu) static inline void platform_do_lowpower(unsigned int cpu)
{ {
flush_cache_all(); flush_cache_all();
...@@ -38,7 +35,7 @@ static inline void platform_do_lowpower(unsigned int cpu) ...@@ -38,7 +35,7 @@ static inline void platform_do_lowpower(unsigned int cpu)
int platform_cpu_kill(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) ...@@ -48,19 +45,6 @@ int platform_cpu_kill(unsigned int cpu)
*/ */
void platform_cpu_die(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 */ /* directly enter low power state, skipping secure registers */
platform_do_lowpower(cpu); platform_do_lowpower(cpu);
} }
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#define ASMARM_ARCH_SMP_H #define ASMARM_ARCH_SMP_H
#include <asm/hardware/gic.h> #include <asm/hardware/gic.h>
#include <asm/smp_mpidr.h>
/* This is required to wakeup the secondary core */ /* This is required to wakeup the secondary core */
extern void u8500_secondary_startup(void); extern void u8500_secondary_startup(void);
...@@ -18,8 +17,8 @@ extern void u8500_secondary_startup(void); ...@@ -18,8 +17,8 @@ extern void u8500_secondary_startup(void);
/* /*
* We use IRQ1 as the IPI * 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 #endif
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/localtimer.h>
#include <asm/smp_scu.h> #include <asm/smp_scu.h>
#include <mach/hardware.h> #include <mach/hardware.h>
...@@ -28,17 +27,23 @@ ...@@ -28,17 +27,23 @@
*/ */
volatile int __cpuinitdata pen_release = -1; 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); static DEFINE_SPINLOCK(boot_lock);
void __cpuinit platform_secondary_init(unsigned int cpu) void __cpuinit platform_secondary_init(unsigned int cpu)
{ {
trace_hardirqs_off();
/* /*
* if any interrupts are already enabled for the primary * if any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled * core (e.g. timer irq), then they will not have been enabled
...@@ -50,7 +55,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) ...@@ -50,7 +55,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* let the primary processor know we're out of the * let the primary processor know we're out of the
* pen, then head off into the C entry point * pen, then head off into the C entry point
*/ */
pen_release = -1; write_pen_release(-1);
/* /*
* Synchronise with the boot thread. * Synchronise with the boot thread.
...@@ -74,11 +79,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -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 * the holding pen - release it, then wait for it to flag
* that it has been released by resetting pen_release. * that it has been released by resetting pen_release.
*/ */
pen_release = cpu; write_pen_release(cpu);
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
outer_clean_range(__pa(&pen_release), __pa(&pen_release) + 1);
smp_cross_call(cpumask_of(cpu)); smp_cross_call(cpumask_of(cpu), 1);
timeout = jiffies + (1 * HZ); timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) { while (time_before(jiffies, timeout)) {
...@@ -97,9 +100,6 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -97,9 +100,6 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
static void __init wakeup_secondary(void) 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 * write the address of secondary startup into the backup ram register
* at offset 0x1FF4, then write the magic number 0xA1FEED01 to the * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the
...@@ -126,40 +126,26 @@ static void __init wakeup_secondary(void) ...@@ -126,40 +126,26 @@ static void __init wakeup_secondary(void)
*/ */
void __init smp_init_cpus(void) void __init smp_init_cpus(void)
{ {
unsigned int i, ncores = get_core_count(); unsigned int i, ncores;
for (i = 0; i < ncores; i++) ncores = scu_get_core_count(__io_address(UX500_SCU_BASE));
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;
/* sanity check */ /* sanity check */
if (ncores == 0) { if (ncores > NR_CPUS) {
printk(KERN_ERR
"U8500: strange CM count of 0? Default to 1\n");
ncores = 1;
}
if (ncores > num_possible_cpus()) {
printk(KERN_WARNING printk(KERN_WARNING
"U8500: no. of cores (%d) greater than configured " "U8500: no. of cores (%d) greater than configured "
"maximum of %d - clipping\n", "maximum of %d - clipping\n",
ncores, num_possible_cpus()); ncores, NR_CPUS);
ncores = num_possible_cpus(); ncores = NR_CPUS;
} }
smp_store_cpu_info(cpu); for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);
}
/* void __init platform_smp_prepare_cpus(unsigned int max_cpus)
* are we trying to boot more cores than exist? {
*/ int i;
if (max_cpus > ncores)
max_cpus = ncores;
/* /*
* Initialise the present map, which describes the set of CPUs * Initialise the present map, which describes the set of CPUs
...@@ -168,13 +154,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -168,13 +154,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
for (i = 0; i < max_cpus; i++) for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true); 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)); scu_enable(__io_address(UX500_SCU_BASE));
wakeup_secondary(); wakeup_secondary();
}
} }
...@@ -4,6 +4,7 @@ menu "Versatile platform type" ...@@ -4,6 +4,7 @@ menu "Versatile platform type"
config ARCH_VERSATILE_PB config ARCH_VERSATILE_PB
bool "Support Versatile/PB platform" bool "Support Versatile/PB platform"
select CPU_ARM926T select CPU_ARM926T
select MIGHT_HAVE_PCI
default y default y
help help
Include support for the ARM(R) Versatile/PB platform. Include support for the ARM(R) Versatile/PB platform.
......
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
#include <linux/amba/pl022.h> #include <linux/amba/pl022.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/leds.h> #include <asm/leds.h>
...@@ -46,7 +46,6 @@ ...@@ -46,7 +46,6 @@
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <asm/mach/time.h> #include <asm/mach/time.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <mach/clkdev.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/platform.h> #include <mach/platform.h>
#include <asm/hardware/timer-sp.h> #include <asm/hardware/timer-sp.h>
......
...@@ -5,4 +5,5 @@ ...@@ -5,4 +5,5 @@
obj-y := v2m.o obj-y := v2m.o
obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/amba/bus.h> #include <linux/amba/bus.h>
#include <linux/amba/clcd.h> #include <linux/amba/clcd.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/hardware/arm_timer.h> #include <asm/hardware/arm_timer.h>
#include <asm/hardware/cache-l2x0.h> #include <asm/hardware/cache-l2x0.h>
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <asm/pmu.h> #include <asm/pmu.h>
#include <asm/smp_twd.h> #include <asm/smp_twd.h>
#include <mach/clkdev.h>
#include <mach/ct-ca9x4.h> #include <mach/ct-ca9x4.h>
#include <asm/hardware/timer-sp.h> #include <asm/hardware/timer-sp.h>
......
/*
* 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;
}
...@@ -2,13 +2,12 @@ ...@@ -2,13 +2,12 @@
#define __MACH_SMP_H #define __MACH_SMP_H
#include <asm/hardware/gic.h> #include <asm/hardware/gic.h>
#include <asm/smp_mpidr.h>
/* /*
* We use IRQ1 as the IPI * 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 #endif
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/localtimer.h>
#include <asm/smp_scu.h> #include <asm/smp_scu.h>
#include <asm/unified.h> #include <asm/unified.h>
...@@ -35,6 +34,19 @@ extern void vexpress_secondary_startup(void); ...@@ -35,6 +34,19 @@ extern void vexpress_secondary_startup(void);
*/ */
volatile int __cpuinitdata pen_release = -1; 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) static void __iomem *scu_base_addr(void)
{ {
return MMIO_P2V(A9_MPCORE_SCU); return MMIO_P2V(A9_MPCORE_SCU);
...@@ -44,8 +56,6 @@ static DEFINE_SPINLOCK(boot_lock); ...@@ -44,8 +56,6 @@ static DEFINE_SPINLOCK(boot_lock);
void __cpuinit platform_secondary_init(unsigned int cpu) void __cpuinit platform_secondary_init(unsigned int cpu)
{ {
trace_hardirqs_off();
/* /*
* if any interrupts are already enabled for the primary * if any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled * core (e.g. timer irq), then they will not have been enabled
...@@ -57,8 +67,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) ...@@ -57,8 +67,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* let the primary processor know we're out of the * let the primary processor know we're out of the
* pen, then head off into the C entry point * pen, then head off into the C entry point
*/ */
pen_release = -1; write_pen_release(-1);
smp_wmb();
/* /*
* Synchronise with the boot thread. * Synchronise with the boot thread.
...@@ -83,16 +92,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -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 * since we haven't sent them a soft interrupt, they shouldn't
* be there. * be there.
*/ */
pen_release = cpu; write_pen_release(cpu);
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
/* /*
* Send the secondary CPU a soft interrupt, thereby causing * Send the secondary CPU a soft interrupt, thereby causing
* the boot monitor to read the system wide flags register, * the boot monitor to read the system wide flags register,
* and branch to the address found there. * and branch to the address found there.
*/ */
smp_cross_call(cpumask_of(cpu)); smp_cross_call(cpumask_of(cpu), 1);
timeout = jiffies + (1 * HZ); timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) { while (time_before(jiffies, timeout)) {
...@@ -124,13 +131,6 @@ void __init smp_init_cpus(void) ...@@ -124,13 +131,6 @@ void __init smp_init_cpus(void)
ncores = scu_base ? scu_get_core_count(scu_base) : 1; ncores = scu_base ? scu_get_core_count(scu_base) : 1;
/* sanity check */ /* sanity check */
if (ncores == 0) {
printk(KERN_ERR
"vexpress: strange CM count of 0? Default to 1\n");
ncores = 1;
}
if (ncores > NR_CPUS) { if (ncores > NR_CPUS) {
printk(KERN_WARNING printk(KERN_WARNING
"vexpress: no. of cores (%d) greater than configured " "vexpress: no. of cores (%d) greater than configured "
...@@ -143,20 +143,10 @@ void __init smp_init_cpus(void) ...@@ -143,20 +143,10 @@ void __init smp_init_cpus(void)
set_cpu_possible(i, true); 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; 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 * Initialise the present map, which describes the set of CPUs
* actually populated at the present time. * actually populated at the present time.
...@@ -164,17 +154,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -164,17 +154,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
for (i = 0; i < max_cpus; i++) for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true); set_cpu_present(i, true);
/*
* Initialise the SCU if there are more than one CPU and let
* them know where to start.
*/
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()); scu_enable(scu_base_addr());
/* /*
...@@ -186,5 +165,4 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -186,5 +165,4 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR)); writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR));
writel(BSYM(virt_to_phys(vexpress_secondary_startup)), writel(BSYM(virt_to_phys(vexpress_secondary_startup)),
MMIO_P2V(V2M_SYS_FLAGSSET)); MMIO_P2V(V2M_SYS_FLAGSSET));
}
} }
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/sysdev.h> #include <linux/sysdev.h>
#include <linux/usb/isp1760.h> #include <linux/usb/isp1760.h>
#include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <asm/sizes.h> #include <asm/sizes.h>
#include <asm/mach/flash.h> #include <asm/mach/flash.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include <asm/hardware/arm_timer.h> #include <asm/hardware/arm_timer.h>
#include <asm/hardware/timer-sp.h> #include <asm/hardware/timer-sp.h>
#include <mach/clkdev.h>
#include <mach/motherboard.h> #include <mach/motherboard.h>
#include <plat/sched_clock.h> #include <plat/sched_clock.h>
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* the Free Software Foundation; either version 2 of the License. * 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_clk_enable(struct clk *clk, int enable);
void nuc900_subclk_enable(struct clk *clk, int enable); void nuc900_subclk_enable(struct clk *clk, int enable);
......
...@@ -599,6 +599,14 @@ config CPU_CP15_MPU ...@@ -599,6 +599,14 @@ config CPU_CP15_MPU
help help
Processor has the CP15 register, which has MPU related registers. 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 # CPU supports 36-bit I/O
# #
...@@ -628,6 +636,33 @@ config ARM_THUMBEE ...@@ -628,6 +636,33 @@ config ARM_THUMBEE
Say Y here if you have a CPU with the ThumbEE extension and code to 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. 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 config CPU_BIG_ENDIAN
bool "Build big-endian kernel" bool "Build big-endian kernel"
depends on ARCH_SUPPORTS_BIG_ENDIAN depends on ARCH_SUPPORTS_BIG_ENDIAN
......
...@@ -312,7 +312,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, ...@@ -312,7 +312,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
addr = page_address(page); addr = page_address(page);
if (addr) if (addr)
*handle = page_to_dma(dev, page); *handle = pfn_to_dma(dev, page_to_pfn(page));
return addr; return addr;
} }
...@@ -407,7 +407,7 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr ...@@ -407,7 +407,7 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
if (!arch_is_coherent()) if (!arch_is_coherent())
__dma_free_remap(cpu_addr, size); __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); EXPORT_SYMBOL(dma_free_coherent);
...@@ -555,17 +555,20 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, ...@@ -555,17 +555,20 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
struct scatterlist *s; struct scatterlist *s;
int i, j; int i, j;
BUG_ON(!valid_dma_direction(dir));
for_each_sg(sg, s, nents, i) { 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); s->length, dir);
if (dma_mapping_error(dev, s->dma_address)) if (dma_mapping_error(dev, s->dma_address))
goto bad_mapping; goto bad_mapping;
} }
debug_dma_map_sg(dev, sg, nents, nents, dir);
return nents; return nents;
bad_mapping: bad_mapping:
for_each_sg(sg, s, i, j) 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; return 0;
} }
EXPORT_SYMBOL(dma_map_sg); EXPORT_SYMBOL(dma_map_sg);
...@@ -586,8 +589,10 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, ...@@ -586,8 +589,10 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
struct scatterlist *s; struct scatterlist *s;
int i; int i;
debug_dma_unmap_sg(dev, sg, nents, dir);
for_each_sg(sg, s, nents, i) 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); EXPORT_SYMBOL(dma_unmap_sg);
...@@ -612,6 +617,8 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *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, __dma_page_dev_to_cpu(sg_page(s), s->offset,
s->length, dir); s->length, dir);
} }
debug_dma_sync_sg_for_cpu(dev, sg, nents, dir);
} }
EXPORT_SYMBOL(dma_sync_sg_for_cpu); EXPORT_SYMBOL(dma_sync_sg_for_cpu);
...@@ -636,5 +643,16 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, ...@@ -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, __dma_page_cpu_to_dev(sg_page(s), s->offset,
s->length, dir); s->length, dir);
} }
debug_dma_sync_sg_for_device(dev, sg, nents, dir);
} }
EXPORT_SYMBOL(dma_sync_sg_for_device); 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);
...@@ -204,12 +204,8 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, ...@@ -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+ * Don't allow RAM to be mapped - this causes problems with ARMv6+
*/ */
if (pfn_valid(pfn)) { if (WARN_ON(pfn_valid(pfn)))
printk(KERN_WARNING "BUG: Your driver calls ioremap() on system memory. This leads\n" return NULL;
"to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n"
"will fail in the next kernel release. Please fix your driver.\n");
WARN_ON(1);
}
type = get_mem_type(mtype); type = get_mem_type(mtype);
if (!type) if (!type)
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <asm/smp_plat.h> #include <asm/smp_plat.h>
#include <asm/tlb.h> #include <asm/tlb.h>
#include <asm/highmem.h> #include <asm/highmem.h>
#include <asm/traps.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
...@@ -914,12 +915,11 @@ static void __init devicemaps_init(struct machine_desc *mdesc) ...@@ -914,12 +915,11 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
{ {
struct map_desc map; struct map_desc map;
unsigned long addr; unsigned long addr;
void *vectors;
/* /*
* Allocate the vector page early. * Allocate the vector page early.
*/ */
vectors = early_alloc(PAGE_SIZE); vectors_page = early_alloc(PAGE_SIZE);
for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE) for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
pmd_clear(pmd_off_k(addr)); pmd_clear(pmd_off_k(addr));
...@@ -959,7 +959,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) ...@@ -959,7 +959,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
* location (0xffff0000). If we aren't using high-vectors, also * location (0xffff0000). If we aren't using high-vectors, also
* create a mapping at the low-vectors virtual address. * 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.virtual = 0xffff0000;
map.length = PAGE_SIZE; map.length = PAGE_SIZE;
map.type = MT_HIGH_VECTORS; map.type = MT_HIGH_VECTORS;
......
...@@ -109,6 +109,10 @@ ...@@ -109,6 +109,10 @@
* 110x 0 1 0 r/w r/o * 110x 0 1 0 r/w r/o
* 11x0 0 1 0 r/w r/o * 11x0 0 1 0 r/w r/o
* 1111 0 1 1 r/w r/w * 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 .macro armv6_mt_table pfx
\pfx\()_mt_table: \pfx\()_mt_table:
...@@ -148,8 +152,11 @@ ...@@ -148,8 +152,11 @@
tst r1, #L_PTE_USER tst r1, #L_PTE_USER
orrne r3, r3, #PTE_EXT_AP1 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 tstne r3, #PTE_EXT_APX
bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
#endif
tst r1, #L_PTE_EXEC tst r1, #L_PTE_EXEC
orreq r3, r3, #PTE_EXT_XN orreq r3, r3, #PTE_EXT_XN
......
...@@ -148,8 +148,11 @@ ENTRY(cpu_v7_set_pte_ext) ...@@ -148,8 +148,11 @@ ENTRY(cpu_v7_set_pte_ext)
tst r1, #L_PTE_USER tst r1, #L_PTE_USER
orrne r3, r3, #PTE_EXT_AP1 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 tstne r3, #PTE_EXT_APX
bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
#endif
tst r1, #L_PTE_EXEC tst r1, #L_PTE_EXEC
orreq r3, r3, #PTE_EXT_XN orreq r3, r3, #PTE_EXT_XN
...@@ -273,8 +276,6 @@ __v7_setup: ...@@ -273,8 +276,6 @@ __v7_setup:
ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP) ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP)
ALT_UP(orr r4, r4, #TTB_FLAGS_UP) ALT_UP(orr r4, r4, #TTB_FLAGS_UP)
mcr p15, 0, r4, c2, c0, 1 @ load TTB1 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 * Memory region attributes with SCTLR.TRE=1
* *
...@@ -312,6 +313,10 @@ __v7_setup: ...@@ -312,6 +313,10 @@ __v7_setup:
ldmia r5, {r5, r6} ldmia r5, {r5, r6}
#ifdef CONFIG_CPU_ENDIAN_BE8 #ifdef CONFIG_CPU_ENDIAN_BE8
orr r6, r6, #1 << 25 @ big-endian page tables 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 #endif
mrc p15, 0, r0, c1, c0, 0 @ read control register mrc p15, 0, r0, c1, c0, 0 @ read control register
bic r0, r0, r5 @ clear bits them bic r0, r0, r5 @ clear bits them
......
...@@ -11,13 +11,13 @@ choice ...@@ -11,13 +11,13 @@ choice
config ARCH_OMAP1 config ARCH_OMAP1
bool "TI OMAP1" bool "TI OMAP1"
select COMMON_CLKDEV select CLKDEV_LOOKUP
help help
"Systems based on omap7xx, omap15xx or omap16xx" "Systems based on omap7xx, omap15xx or omap16xx"
config ARCH_OMAP2PLUS config ARCH_OMAP2PLUS
bool "TI OMAP2/3/4" bool "TI OMAP2/3/4"
select COMMON_CLKDEV select CLKDEV_LOOKUP
help help
"Systems based on OMAP2, OMAP3 or OMAP4" "Systems based on OMAP2, OMAP3 or OMAP4"
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H
#define __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 { struct omap_clk {
u16 cpu; u16 cpu;
......
...@@ -61,17 +61,17 @@ ...@@ -61,17 +61,17 @@
#define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET) #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 is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))
#define __arch_page_to_dma(dev, page) \ #define __arch_pfn_to_dma(dev, pfn) \
({ dma_addr_t __dma = page_to_phys(page); \ ({ dma_addr_t __dma = __pfn_to_phys(pfn); \
if (is_lbus_device(dev)) \ if (is_lbus_device(dev)) \
__dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \ __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \
__dma; }) __dma; })
#define __arch_dma_to_page(dev, addr) \ #define __arch_dma_to_pfn(dev, addr) \
({ dma_addr_t __dma = addr; \ ({ dma_addr_t __dma = addr; \
if (is_lbus_device(dev)) \ if (is_lbus_device(dev)) \
__dma += PHYS_OFFSET - OMAP1510_LB_OFFSET; \ __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) ? \ #define __arch_dma_to_virt(dev, addr) ({ (void *) (is_lbus_device(dev) ? \
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#define OMAP_ARCH_SMP_H #define OMAP_ARCH_SMP_H
#include <asm/hardware/gic.h> #include <asm/hardware/gic.h>
#include <asm/smp_mpidr.h>
/* Needed for secondary core boot */ /* Needed for secondary core boot */
extern void omap_secondary_startup(void); extern void omap_secondary_startup(void);
...@@ -29,9 +28,9 @@ extern u32 omap_read_auxcoreboot0(void); ...@@ -29,9 +28,9 @@ extern u32 omap_read_auxcoreboot0(void);
/* /*
* We use Soft IRQ1 as the IPI * 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 #endif
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#define __PLAT_CLOCK_H #define __PLAT_CLOCK_H
#include <linux/list.h> #include <linux/list.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <linux/types.h> #include <linux/types.h>
/* clk structure flags */ /* clk structure flags */
......
...@@ -25,9 +25,9 @@ ...@@ -25,9 +25,9 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clkdev.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/clkdev.h>
#include <mach/platform.h> #include <mach/platform.h>
#include <mach/regs-clkctrl.h> #include <mach/regs-clkctrl.h>
......
...@@ -10,9 +10,12 @@ ...@@ -10,9 +10,12 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/cpu.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/smp.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/cputype.h> #include <asm/cputype.h>
...@@ -484,7 +487,24 @@ void vfp_flush_hwstate(struct thread_info *thread) ...@@ -484,7 +487,24 @@ void vfp_flush_hwstate(struct thread_info *thread)
put_cpu(); 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. * VFP support code initialisation.
...@@ -514,6 +534,8 @@ static int __init vfp_init(void) ...@@ -514,6 +534,8 @@ static int __init vfp_init(void)
else if (vfpsid & FPSID_NODOUBLE) { else if (vfpsid & FPSID_NODOUBLE) {
printk("no double precision support\n"); printk("no double precision support\n");
} else { } else {
hotcpu_notifier(vfp_hotplug, 0);
smp_call_function(vfp_enable, NULL, 1); smp_call_function(vfp_enable, NULL, 1);
VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */
......
config SUPERH config SUPERH
def_bool y def_bool y
select EMBEDDED select EMBEDDED
select HAVE_CLK select CLKDEV_LOOKUP
select HAVE_IDE if HAS_IOPORT select HAVE_IDE if HAS_IOPORT
select HAVE_MEMBLOCK select HAVE_MEMBLOCK
select HAVE_OPROFILE select HAVE_OPROFILE
......
...@@ -24,10 +24,10 @@ ...@@ -24,10 +24,10 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/usb/r8a66597.h> #include <linux/usb/r8a66597.h>
#include <linux/usb/m66592.h> #include <linux/usb/m66592.h>
#include <linux/clkdev.h>
#include <net/ax88796.h> #include <net/ax88796.h>
#include <asm/machvec.h> #include <asm/machvec.h>
#include <mach/highlander.h> #include <mach/highlander.h>
#include <asm/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/heartbeat.h> #include <asm/heartbeat.h>
#include <asm/io.h> #include <asm/io.h>
......
/* /*
* arch/sh/include/asm/clkdev.h * Copyright (C) 2010 Paul Mundt <lethal@linux-sh.org>
*
* Cloned from arch/arm/include/asm/clkdev.h:
*
* Copyright (C) 2008 Russell King.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -11,25 +7,25 @@ ...@@ -11,25 +7,25 @@
* *
* Helper for the clk API to assist looking up a struct clk. * 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 { #include <linux/bootmem.h>
struct list_head node; #include <linux/mm.h>
const char *dev_id; #include <linux/slab.h>
const char *con_id;
struct clk *clk;
};
struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, #include <asm/clock.h>
const char *dev_fmt, ...);
void clkdev_add(struct clk_lookup *cl); static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
void clkdev_drop(struct clk_lookup *cl); {
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); #define __clk_put(clk)
int clk_add_alias(const char *, const char *, char *, struct device *); #define __clk_get(clk) ({ 1; })
#endif #endif /* __CLKDEV_H__ */
...@@ -11,7 +11,7 @@ endif ...@@ -11,7 +11,7 @@ endif
CFLAGS_REMOVE_return_address.o = -pg 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 \ idle.o io.o irq.o irq_$(BITS).o kdebugfs.o \
machvec.o nmi_debug.o process.o \ machvec.o nmi_debug.o process.o \
process_$(BITS).o ptrace.o ptrace_$(BITS).o \ process_$(BITS).o ptrace.o ptrace_$(BITS).o \
......
/*
* 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);
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
static struct clk master_clk = { static struct clk master_clk = {
......
...@@ -48,20 +48,4 @@ int __init clk_init(void) ...@@ -48,20 +48,4 @@ int __init clk_init(void)
return ret; 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);
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/freq.h> #include <asm/freq.h>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
/* SH7343 registers */ /* SH7343 registers */
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
/* SH7366 registers */ /* SH7366 registers */
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/hwblk.h> #include <asm/hwblk.h>
#include <cpu/sh7722.h> #include <cpu/sh7722.h>
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/hwblk.h> #include <asm/hwblk.h>
#include <cpu/sh7723.h> #include <cpu/sh7723.h>
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/hwblk.h> #include <asm/hwblk.h>
#include <cpu/sh7724.h> #include <cpu/sh7724.h>
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/freq.h> #include <asm/freq.h>
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/freq.h> #include <asm/freq.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/freq.h> #include <asm/freq.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/freq.h> #include <asm/freq.h>
#include <cpu/sh7785.h> #include <cpu/sh7785.h>
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/freq.h> #include <asm/freq.h>
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <asm/clkdev.h> #include <linux/clkdev.h>
#include <asm/clock.h> #include <asm/clock.h>
#include <asm/freq.h> #include <asm/freq.h>
......
...@@ -111,4 +111,6 @@ source "drivers/xen/Kconfig" ...@@ -111,4 +111,6 @@ source "drivers/xen/Kconfig"
source "drivers/staging/Kconfig" source "drivers/staging/Kconfig"
source "drivers/platform/Kconfig" source "drivers/platform/Kconfig"
source "drivers/clk/Kconfig"
endmenu endmenu
...@@ -115,3 +115,5 @@ obj-$(CONFIG_VLYNQ) += vlynq/ ...@@ -115,3 +115,5 @@ obj-$(CONFIG_VLYNQ) += vlynq/
obj-$(CONFIG_STAGING) += staging/ obj-$(CONFIG_STAGING) += staging/
obj-y += platform/ obj-y += platform/
obj-y += ieee802154/ obj-y += ieee802154/
#common clk code
obj-y += clk/
...@@ -147,6 +147,39 @@ static void amba_put_disable_pclk(struct amba_device *pcdev) ...@@ -147,6 +147,39 @@ static void amba_put_disable_pclk(struct amba_device *pcdev)
clk_put(pclk); 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 * These are the device model conversion veneers; they convert the
* device model structures to our more specific structures. * device model structures to our more specific structures.
...@@ -159,6 +192,10 @@ static int amba_probe(struct device *dev) ...@@ -159,6 +192,10 @@ static int amba_probe(struct device *dev)
int ret; int ret;
do { do {
ret = amba_get_enable_vcore(pcdev);
if (ret)
break;
ret = amba_get_enable_pclk(pcdev); ret = amba_get_enable_pclk(pcdev);
if (ret) if (ret)
break; break;
...@@ -168,6 +205,7 @@ static int amba_probe(struct device *dev) ...@@ -168,6 +205,7 @@ static int amba_probe(struct device *dev)
break; break;
amba_put_disable_pclk(pcdev); amba_put_disable_pclk(pcdev);
amba_put_disable_vcore(pcdev);
} while (0); } while (0);
return ret; return ret;
...@@ -180,6 +218,7 @@ static int amba_remove(struct device *dev) ...@@ -180,6 +218,7 @@ static int amba_remove(struct device *dev)
int ret = drv->remove(pcdev); int ret = drv->remove(pcdev);
amba_put_disable_pclk(pcdev); amba_put_disable_pclk(pcdev);
amba_put_disable_vcore(pcdev);
return ret; return ret;
} }
......
config CLKDEV_LOOKUP
bool
select HAVE_CLK
obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o
/* /*
* arch/arm/common/clkdev.c * drivers/clk/clkdev.c
* *
* Copyright (C) 2008 Russell King. * Copyright (C) 2008 Russell King.
* *
...@@ -18,10 +18,7 @@ ...@@ -18,10 +18,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/slab.h> #include <linux/clkdev.h>
#include <asm/clkdev.h>
#include <mach/clkdev.h>
static LIST_HEAD(clocks); static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex); static DEFINE_MUTEX(clocks_mutex);
...@@ -120,12 +117,12 @@ struct clk_lookup_alloc { ...@@ -120,12 +117,12 @@ struct clk_lookup_alloc {
char con_id[MAX_CON_ID]; char con_id[MAX_CON_ID];
}; };
struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, struct clk_lookup * __init_refok
const char *dev_fmt, ...) clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
{ {
struct clk_lookup_alloc *cla; struct clk_lookup_alloc *cla;
cla = kzalloc(sizeof(*cla), GFP_KERNEL); cla = __clkdev_alloc(sizeof(*cla));
if (!cla) if (!cla)
return NULL; return NULL;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/resource.h> #include <linux/resource.h>
#include <linux/regulator/consumer.h>
#define AMBA_NR_IRQS 2 #define AMBA_NR_IRQS 2
#define AMBA_CID 0xb105f00d #define AMBA_CID 0xb105f00d
...@@ -28,6 +29,7 @@ struct amba_device { ...@@ -28,6 +29,7 @@ struct amba_device {
struct device dev; struct device dev;
struct resource res; struct resource res;
struct clk *pclk; struct clk *pclk;
struct regulator *vcore;
u64 dma_mask; u64 dma_mask;
unsigned int periphid; unsigned int periphid;
unsigned int irq[AMBA_NR_IRQS]; unsigned int irq[AMBA_NR_IRQS];
...@@ -71,6 +73,12 @@ void amba_release_regions(struct amba_device *); ...@@ -71,6 +73,12 @@ void amba_release_regions(struct amba_device *);
#define amba_pclk_disable(d) \ #define amba_pclk_disable(d) \
do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0) 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 */ /* Some drivers don't use the struct amba_device */
#define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff) #define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff)
#define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f) #define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f)
......
/*
* 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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册