mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 06:31:52 +00:00
Merge branch 'misc' into devel
Conflicts: arch/arm/Kconfig arch/arm/common/Makefile arch/arm/kernel/Makefile arch/arm/kernel/smp.c
This commit is contained in:
commit
4073723acb
@ -34,3 +34,5 @@ memory.txt
|
||||
- description of the virtual memory layout
|
||||
nwfpe/
|
||||
- NWFPE floating point emulator documentation
|
||||
swp_emulation
|
||||
- SWP/SWPB emulation handler/logging description
|
||||
|
27
Documentation/arm/swp_emulation
Normal file
27
Documentation/arm/swp_emulation
Normal file
@ -0,0 +1,27 @@
|
||||
Software emulation of deprecated SWP instruction (CONFIG_SWP_EMULATE)
|
||||
---------------------------------------------------------------------
|
||||
|
||||
ARMv6 architecture deprecates use of the SWP/SWPB instructions, and recommeds
|
||||
moving to the load-locked/store-conditional instructions LDREX and STREX.
|
||||
|
||||
ARMv7 multiprocessing extensions introduce the ability to disable these
|
||||
instructions, triggering an undefined instruction exception when executed.
|
||||
Trapped instructions are emulated using an LDREX/STREX or LDREXB/STREXB
|
||||
sequence. If a memory access fault (an abort) occurs, a segmentation fault is
|
||||
signalled to the triggering process.
|
||||
|
||||
/proc/cpu/swp_emulation holds some statistics/information, including the PID of
|
||||
the last process to trigger the emulation to be invocated. For example:
|
||||
---
|
||||
Emulated SWP: 12
|
||||
Emulated SWPB: 0
|
||||
Aborted SWP{B}: 1
|
||||
Last process: 314
|
||||
---
|
||||
|
||||
NOTE: when accessing uncached shared regions, LDREX/STREX rely on an external
|
||||
transaction monitoring block called a global monitor to maintain update
|
||||
atomicity. If your system does not implement a global monitor, this option can
|
||||
cause programs that perform SWP operations to uncached memory to deadlock, as
|
||||
the STREX operation will always fail.
|
||||
|
@ -2,6 +2,7 @@ config ARM
|
||||
bool
|
||||
default y
|
||||
select HAVE_AOUT
|
||||
select HAVE_DMA_API_DEBUG
|
||||
select HAVE_IDE
|
||||
select HAVE_MEMBLOCK
|
||||
select RTC_LIB
|
||||
@ -36,6 +37,9 @@ config ARM
|
||||
config HAVE_PWM
|
||||
bool
|
||||
|
||||
config MIGHT_HAVE_PCI
|
||||
bool
|
||||
|
||||
config SYS_SUPPORTS_APM_EMULATION
|
||||
bool
|
||||
|
||||
@ -226,7 +230,7 @@ config ARCH_INTEGRATOR
|
||||
bool "ARM Ltd. Integrator family"
|
||||
select ARM_AMBA
|
||||
select ARCH_HAS_CPUFREQ
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select ICST
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select PLAT_VERSATILE
|
||||
@ -236,7 +240,7 @@ config ARCH_INTEGRATOR
|
||||
config ARCH_REALVIEW
|
||||
bool "ARM Ltd. RealView family"
|
||||
select ARM_AMBA
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select HAVE_SCHED_CLOCK
|
||||
select ICST
|
||||
select GENERIC_CLOCKEVENTS
|
||||
@ -251,7 +255,7 @@ config ARCH_VERSATILE
|
||||
bool "ARM Ltd. Versatile family"
|
||||
select ARM_AMBA
|
||||
select ARM_VIC
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select HAVE_SCHED_CLOCK
|
||||
select ICST
|
||||
select GENERIC_CLOCKEVENTS
|
||||
@ -266,7 +270,7 @@ config ARCH_VEXPRESS
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
select ARM_AMBA
|
||||
select ARM_TIMER_SP804
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select HAVE_CLK
|
||||
select HAVE_SCHED_CLOCK
|
||||
@ -288,7 +292,7 @@ config ARCH_BCMRING
|
||||
depends on MMU
|
||||
select CPU_V6
|
||||
select ARM_AMBA
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
help
|
||||
@ -306,6 +310,7 @@ config ARCH_CNS3XXX
|
||||
select CPU_V6
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select ARM_GIC
|
||||
select MIGHT_HAVE_PCI
|
||||
select PCI_DOMAINS if PCI
|
||||
help
|
||||
Support for Cavium Networks CNS3XXX platform.
|
||||
@ -335,7 +340,7 @@ config ARCH_EP93XX
|
||||
select CPU_ARM920T
|
||||
select ARM_AMBA
|
||||
select ARM_VIC
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARCH_HAS_HOLES_MEMORYMODEL
|
||||
select ARCH_USES_GETTIMEOFFSET
|
||||
@ -355,14 +360,14 @@ config ARCH_MXC
|
||||
bool "Freescale MXC/iMX-based"
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
help
|
||||
Support for Freescale MXC/iMX-based family of processors
|
||||
|
||||
config ARCH_STMP3XXX
|
||||
bool "Freescale STMP3xxx"
|
||||
select CPU_ARM926T
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select USB_ARCH_HAS_EHCI
|
||||
@ -442,6 +447,7 @@ config ARCH_IXP4XX
|
||||
select GENERIC_GPIO
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select HAVE_SCHED_CLOCK
|
||||
select MIGHT_HAVE_PCI
|
||||
select DMABOUNCE if PCI
|
||||
help
|
||||
Support for Intel's IXP4XX (XScale) family of processors.
|
||||
@ -481,7 +487,7 @@ config ARCH_LPC32XX
|
||||
select HAVE_IDE
|
||||
select ARM_AMBA
|
||||
select USB_ARCH_HAS_OHCI
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select GENERIC_TIME
|
||||
select GENERIC_CLOCKEVENTS
|
||||
help
|
||||
@ -515,7 +521,7 @@ config ARCH_MMP
|
||||
bool "Marvell PXA168/910/MMP2"
|
||||
depends on MMU
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select HAVE_SCHED_CLOCK
|
||||
select TICK_ONESHOT
|
||||
@ -549,7 +555,7 @@ config ARCH_W90X900
|
||||
bool "Nuvoton W90X900 CPU"
|
||||
select CPU_ARM926T
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select GENERIC_CLOCKEVENTS
|
||||
help
|
||||
Support for Nuvoton (Winbond logic dept.) ARM9 processor,
|
||||
@ -563,19 +569,19 @@ config ARCH_W90X900
|
||||
config ARCH_NUC93X
|
||||
bool "Nuvoton NUC93X CPU"
|
||||
select CPU_ARM926T
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
help
|
||||
Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a
|
||||
low-power and high performance MPEG-4/JPEG multimedia controller chip.
|
||||
|
||||
config ARCH_TEGRA
|
||||
bool "NVIDIA Tegra"
|
||||
select CLKDEV_LOOKUP
|
||||
select GENERIC_TIME
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select GENERIC_GPIO
|
||||
select HAVE_CLK
|
||||
select HAVE_SCHED_CLOCK
|
||||
select COMMON_CLKDEV
|
||||
select ARCH_HAS_BARRIERS if CACHE_L2X0
|
||||
select ARCH_HAS_CPUFREQ
|
||||
help
|
||||
@ -585,7 +591,7 @@ config ARCH_TEGRA
|
||||
config ARCH_PNX4008
|
||||
bool "Philips Nexperia PNX4008 Mobile"
|
||||
select CPU_ARM926T
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select ARCH_USES_GETTIMEOFFSET
|
||||
help
|
||||
This enables support for Philips PNX4008 mobile platform.
|
||||
@ -595,7 +601,7 @@ config ARCH_PXA
|
||||
depends on MMU
|
||||
select ARCH_MTD_XIP
|
||||
select ARCH_HAS_CPUFREQ
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select HAVE_SCHED_CLOCK
|
||||
@ -774,7 +780,7 @@ config ARCH_TCC_926
|
||||
bool "Telechips TCC ARM926-based systems"
|
||||
select CPU_ARM926T
|
||||
select HAVE_CLK
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select GENERIC_CLOCKEVENTS
|
||||
help
|
||||
Support for Telechips TCC ARM926-based systems.
|
||||
@ -799,7 +805,7 @@ config ARCH_U300
|
||||
select ARM_AMBA
|
||||
select ARM_VIC
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select GENERIC_GPIO
|
||||
help
|
||||
Support for ST-Ericsson U300 series mobile platforms.
|
||||
@ -809,7 +815,7 @@ config ARCH_U8500
|
||||
select CPU_V7
|
||||
select ARM_AMBA
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
help
|
||||
Support for ST-Ericsson's Ux500 architecture
|
||||
@ -819,7 +825,7 @@ config ARCH_NOMADIK
|
||||
select ARM_AMBA
|
||||
select ARM_VIC
|
||||
select CPU_ARM926T
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
help
|
||||
@ -831,7 +837,7 @@ config ARCH_DAVINCI
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ZONE_DMA
|
||||
select HAVE_IDE
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select GENERIC_ALLOCATOR
|
||||
select ARCH_HAS_HOLES_MEMORYMODEL
|
||||
help
|
||||
@ -852,7 +858,7 @@ config PLAT_SPEAR
|
||||
bool "ST SPEAr"
|
||||
select ARM_AMBA
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select HAVE_CLK
|
||||
help
|
||||
@ -1034,6 +1040,11 @@ config CPU_HAS_PMU
|
||||
default y
|
||||
bool
|
||||
|
||||
config MULTI_IRQ_HANDLER
|
||||
bool
|
||||
help
|
||||
Allow each machine to specify it's own IRQ handler at run time.
|
||||
|
||||
if !MMU
|
||||
source "arch/arm/Kconfig-nommu"
|
||||
endif
|
||||
@ -1181,7 +1192,7 @@ config ISA_DMA_API
|
||||
bool
|
||||
|
||||
config PCI
|
||||
bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX || SA1100_NANOENGINE
|
||||
bool "PCI support" if MIGHT_HAVE_PCI
|
||||
help
|
||||
Find out whether you have a PCI motherboard. PCI is the name of a
|
||||
bus system, i.e. the way the CPU talks to the other stuff inside
|
||||
@ -1253,7 +1264,7 @@ config SMP
|
||||
config SMP_ON_UP
|
||||
bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
depends on SMP && !XIP && !THUMB2_KERNEL
|
||||
depends on SMP && !XIP
|
||||
default y
|
||||
help
|
||||
SMP kernels contain instructions which fail on non-SMP processors.
|
||||
@ -1272,6 +1283,7 @@ config HAVE_ARM_SCU
|
||||
config HAVE_ARM_TWD
|
||||
bool
|
||||
depends on SMP
|
||||
select TICK_ONESHOT
|
||||
help
|
||||
This options enables support for the ARM timer and watchdog unit
|
||||
|
||||
@ -1335,7 +1347,7 @@ config HZ
|
||||
default 100
|
||||
|
||||
config THUMB2_KERNEL
|
||||
bool "Compile the kernel in Thumb-2 mode"
|
||||
bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)"
|
||||
depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL
|
||||
select AEABI
|
||||
select ARM_ASM_UNIFIED
|
||||
@ -1549,6 +1561,7 @@ config SECCOMP
|
||||
|
||||
config CC_STACKPROTECTOR
|
||||
bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
This option turns on the -fstack-protector GCC feature. This
|
||||
feature puts, at the beginning of functions, a canary value on
|
||||
@ -1745,7 +1758,7 @@ config CPU_FREQ_S3C
|
||||
Internal configuration node for common cpufreq on Samsung SoC
|
||||
|
||||
config CPU_FREQ_S3C24XX
|
||||
bool "CPUfreq driver for Samsung S3C24XX series CPUs"
|
||||
bool "CPUfreq driver for Samsung S3C24XX series CPUs (EXPERIMENTAL)"
|
||||
depends on ARCH_S3C2410 && CPU_FREQ && EXPERIMENTAL
|
||||
select CPU_FREQ_S3C
|
||||
help
|
||||
@ -1757,7 +1770,7 @@ config CPU_FREQ_S3C24XX
|
||||
If in doubt, say N.
|
||||
|
||||
config CPU_FREQ_S3C24XX_PLL
|
||||
bool "Support CPUfreq changing of PLL frequency"
|
||||
bool "Support CPUfreq changing of PLL frequency (EXPERIMENTAL)"
|
||||
depends on CPU_FREQ_S3C24XX && EXPERIMENTAL
|
||||
help
|
||||
Compile in support for changing the PLL frequency from the
|
||||
|
@ -31,7 +31,7 @@ config FRAME_POINTER
|
||||
reported is severely limited.
|
||||
|
||||
config ARM_UNWIND
|
||||
bool "Enable stack unwinding support"
|
||||
bool "Enable stack unwinding support (EXPERIMENTAL)"
|
||||
depends on AEABI && EXPERIMENTAL
|
||||
default y
|
||||
help
|
||||
|
@ -37,7 +37,3 @@ config SHARP_PARAM
|
||||
|
||||
config SHARP_SCOOP
|
||||
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,
|
||||
* substitute the safe buffer for the unsafe one.
|
||||
* (basically move the buffer from an unsafe area to a safe one)
|
||||
*/
|
||||
dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
|
||||
dma_addr_t __dma_map_single(struct device *dev, void *ptr, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
|
||||
@ -338,7 +338,7 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
|
||||
|
||||
return map_single(dev, ptr, size, dir);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_map_single);
|
||||
EXPORT_SYMBOL(__dma_map_single);
|
||||
|
||||
/*
|
||||
* see if a mapped address was really a "safe" buffer and if so, copy
|
||||
@ -346,7 +346,7 @@ EXPORT_SYMBOL(dma_map_single);
|
||||
* the safe buffer. (basically return things back to the way they
|
||||
* should be)
|
||||
*/
|
||||
void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
|
||||
void __dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
|
||||
@ -354,9 +354,9 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
|
||||
|
||||
unmap_single(dev, dma_addr, size, dir);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_unmap_single);
|
||||
EXPORT_SYMBOL(__dma_unmap_single);
|
||||
|
||||
dma_addr_t dma_map_page(struct device *dev, struct page *page,
|
||||
dma_addr_t __dma_map_page(struct device *dev, struct page *page,
|
||||
unsigned long offset, size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n",
|
||||
@ -372,7 +372,7 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page,
|
||||
|
||||
return map_single(dev, page_address(page) + offset, size, dir);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_map_page);
|
||||
EXPORT_SYMBOL(__dma_map_page);
|
||||
|
||||
/*
|
||||
* see if a mapped address was really a "safe" buffer and if so, copy
|
||||
@ -380,7 +380,7 @@ EXPORT_SYMBOL(dma_map_page);
|
||||
* the safe buffer. (basically return things back to the way they
|
||||
* should be)
|
||||
*/
|
||||
void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
|
||||
void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
|
||||
@ -388,7 +388,7 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
|
||||
|
||||
unmap_single(dev, dma_addr, size, dir);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_unmap_page);
|
||||
EXPORT_SYMBOL(__dma_unmap_page);
|
||||
|
||||
int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
|
||||
unsigned long off, size_t sz, enum dma_data_direction dir)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#endif
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/domain.h>
|
||||
|
||||
/*
|
||||
* Endian independent macros for shifting bytes within registers.
|
||||
@ -157,16 +158,24 @@
|
||||
#ifdef CONFIG_SMP
|
||||
#define ALT_SMP(instr...) \
|
||||
9998: instr
|
||||
/*
|
||||
* Note: if you get assembler errors from ALT_UP() when building with
|
||||
* CONFIG_THUMB2_KERNEL, you almost certainly need to use
|
||||
* ALT_SMP( W(instr) ... )
|
||||
*/
|
||||
#define ALT_UP(instr...) \
|
||||
.pushsection ".alt.smp.init", "a" ;\
|
||||
.long 9998b ;\
|
||||
instr ;\
|
||||
9997: instr ;\
|
||||
.if . - 9997b != 4 ;\
|
||||
.error "ALT_UP() content must assemble to exactly 4 bytes";\
|
||||
.endif ;\
|
||||
.popsection
|
||||
#define ALT_UP_B(label) \
|
||||
.equ up_b_offset, label - 9998b ;\
|
||||
.pushsection ".alt.smp.init", "a" ;\
|
||||
.long 9998b ;\
|
||||
b . + up_b_offset ;\
|
||||
W(b) . + up_b_offset ;\
|
||||
.popsection
|
||||
#else
|
||||
#define ALT_SMP(instr...)
|
||||
@ -177,16 +186,24 @@
|
||||
/*
|
||||
* SMP data memory barrier
|
||||
*/
|
||||
.macro smp_dmb
|
||||
.macro smp_dmb mode
|
||||
#ifdef CONFIG_SMP
|
||||
#if __LINUX_ARM_ARCH__ >= 7
|
||||
.ifeqs "\mode","arm"
|
||||
ALT_SMP(dmb)
|
||||
.else
|
||||
ALT_SMP(W(dmb))
|
||||
.endif
|
||||
#elif __LINUX_ARM_ARCH__ == 6
|
||||
ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb
|
||||
#else
|
||||
#error Incompatible SMP platform
|
||||
#endif
|
||||
.ifeqs "\mode","arm"
|
||||
ALT_UP(nop)
|
||||
.else
|
||||
ALT_UP(W(nop))
|
||||
.endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
@ -206,12 +223,12 @@
|
||||
*/
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
|
||||
.macro usraccoff, instr, reg, ptr, inc, off, cond, abort
|
||||
.macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T()
|
||||
9999:
|
||||
.if \inc == 1
|
||||
\instr\cond\()bt \reg, [\ptr, #\off]
|
||||
\instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
|
||||
.elseif \inc == 4
|
||||
\instr\cond\()t \reg, [\ptr, #\off]
|
||||
\instr\cond\()\t\().w \reg, [\ptr, #\off]
|
||||
.else
|
||||
.error "Unsupported inc macro argument"
|
||||
.endif
|
||||
@ -246,13 +263,13 @@
|
||||
|
||||
#else /* !CONFIG_THUMB2_KERNEL */
|
||||
|
||||
.macro usracc, instr, reg, ptr, inc, cond, rept, abort
|
||||
.macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=T()
|
||||
.rept \rept
|
||||
9999:
|
||||
.if \inc == 1
|
||||
\instr\cond\()bt \reg, [\ptr], #\inc
|
||||
\instr\cond\()b\()\t \reg, [\ptr], #\inc
|
||||
.elseif \inc == 4
|
||||
\instr\cond\()t \reg, [\ptr], #\inc
|
||||
\instr\cond\()\t \reg, [\ptr], #\inc
|
||||
.else
|
||||
.error "Unsupported inc macro argument"
|
||||
.endif
|
||||
|
@ -23,4 +23,6 @@
|
||||
#define ARCH_SLAB_MINALIGN 8
|
||||
#endif
|
||||
|
||||
#define __read_mostly __attribute__((__section__(".data..read_mostly")))
|
||||
|
||||
#endif
|
||||
|
@ -12,23 +12,13 @@
|
||||
#ifndef __ASM_CLKDEV_H
|
||||
#define __ASM_CLKDEV_H
|
||||
|
||||
struct clk;
|
||||
struct device;
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct clk_lookup {
|
||||
struct list_head node;
|
||||
const char *dev_id;
|
||||
const char *con_id;
|
||||
struct clk *clk;
|
||||
};
|
||||
#include <mach/clkdev.h>
|
||||
|
||||
struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
|
||||
const char *dev_fmt, ...);
|
||||
|
||||
void clkdev_add(struct clk_lookup *cl);
|
||||
void clkdev_drop(struct clk_lookup *cl);
|
||||
|
||||
void clkdev_add_table(struct clk_lookup *, size_t);
|
||||
int clk_add_alias(const char *, const char *, char *, struct device *);
|
||||
static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
|
||||
{
|
||||
return kzalloc(size, GFP_KERNEL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -5,24 +5,29 @@
|
||||
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/dma-debug.h>
|
||||
|
||||
#include <asm-generic/dma-coherent.h>
|
||||
#include <asm/memory.h>
|
||||
|
||||
#ifdef __arch_page_to_dma
|
||||
#error Please update to __arch_pfn_to_dma
|
||||
#endif
|
||||
|
||||
/*
|
||||
* page_to_dma/dma_to_virt/virt_to_dma are architecture private functions
|
||||
* used internally by the DMA-mapping API to provide DMA addresses. They
|
||||
* must not be used by drivers.
|
||||
* dma_to_pfn/pfn_to_dma/dma_to_virt/virt_to_dma are architecture private
|
||||
* functions used internally by the DMA-mapping API to provide DMA
|
||||
* addresses. They must not be used by drivers.
|
||||
*/
|
||||
#ifndef __arch_page_to_dma
|
||||
static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
|
||||
#ifndef __arch_pfn_to_dma
|
||||
static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
|
||||
{
|
||||
return (dma_addr_t)__pfn_to_bus(page_to_pfn(page));
|
||||
return (dma_addr_t)__pfn_to_bus(pfn);
|
||||
}
|
||||
|
||||
static inline struct page *dma_to_page(struct device *dev, dma_addr_t addr)
|
||||
static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
|
||||
{
|
||||
return pfn_to_page(__bus_to_pfn(addr));
|
||||
return __bus_to_pfn(addr);
|
||||
}
|
||||
|
||||
static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
|
||||
@ -35,14 +40,14 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
|
||||
return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
|
||||
}
|
||||
#else
|
||||
static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
|
||||
static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
|
||||
{
|
||||
return __arch_page_to_dma(dev, page);
|
||||
return __arch_pfn_to_dma(dev, pfn);
|
||||
}
|
||||
|
||||
static inline struct page *dma_to_page(struct device *dev, dma_addr_t addr)
|
||||
static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
|
||||
{
|
||||
return __arch_dma_to_page(dev, addr);
|
||||
return __arch_dma_to_pfn(dev, addr);
|
||||
}
|
||||
|
||||
static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
|
||||
@ -293,13 +298,13 @@ extern int dma_needs_bounce(struct device*, dma_addr_t, size_t);
|
||||
/*
|
||||
* The DMA API, implemented by dmabounce.c. See below for descriptions.
|
||||
*/
|
||||
extern dma_addr_t dma_map_single(struct device *, void *, size_t,
|
||||
extern dma_addr_t __dma_map_single(struct device *, void *, size_t,
|
||||
enum dma_data_direction);
|
||||
extern void dma_unmap_single(struct device *, dma_addr_t, size_t,
|
||||
extern void __dma_unmap_single(struct device *, dma_addr_t, size_t,
|
||||
enum dma_data_direction);
|
||||
extern dma_addr_t dma_map_page(struct device *, struct page *,
|
||||
extern dma_addr_t __dma_map_page(struct device *, struct page *,
|
||||
unsigned long, size_t, enum dma_data_direction);
|
||||
extern void dma_unmap_page(struct device *, dma_addr_t, size_t,
|
||||
extern void __dma_unmap_page(struct device *, dma_addr_t, size_t,
|
||||
enum dma_data_direction);
|
||||
|
||||
/*
|
||||
@ -323,6 +328,34 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
|
||||
}
|
||||
|
||||
|
||||
static inline dma_addr_t __dma_map_single(struct device *dev, void *cpu_addr,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
__dma_single_cpu_to_dev(cpu_addr, size, dir);
|
||||
return virt_to_dma(dev, cpu_addr);
|
||||
}
|
||||
|
||||
static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
|
||||
unsigned long offset, size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
__dma_page_cpu_to_dev(page, offset, size, dir);
|
||||
return pfn_to_dma(dev, page_to_pfn(page)) + offset;
|
||||
}
|
||||
|
||||
static inline void __dma_unmap_single(struct device *dev, dma_addr_t handle,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
__dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
|
||||
}
|
||||
|
||||
static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
__dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
|
||||
handle & ~PAGE_MASK, size, dir);
|
||||
}
|
||||
#endif /* CONFIG_DMABOUNCE */
|
||||
|
||||
/**
|
||||
* dma_map_single - map a single buffer for streaming DMA
|
||||
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
|
||||
@ -340,11 +373,16 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
|
||||
static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
dma_addr_t addr;
|
||||
|
||||
BUG_ON(!valid_dma_direction(dir));
|
||||
|
||||
__dma_single_cpu_to_dev(cpu_addr, size, dir);
|
||||
addr = __dma_map_single(dev, cpu_addr, size, dir);
|
||||
debug_dma_map_page(dev, virt_to_page(cpu_addr),
|
||||
(unsigned long)cpu_addr & ~PAGE_MASK, size,
|
||||
dir, addr, true);
|
||||
|
||||
return virt_to_dma(dev, cpu_addr);
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -364,11 +402,14 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
|
||||
static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
|
||||
unsigned long offset, size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
dma_addr_t addr;
|
||||
|
||||
BUG_ON(!valid_dma_direction(dir));
|
||||
|
||||
__dma_page_cpu_to_dev(page, offset, size, dir);
|
||||
addr = __dma_map_page(dev, page, offset, size, dir);
|
||||
debug_dma_map_page(dev, page, offset, size, dir, addr, false);
|
||||
|
||||
return page_to_dma(dev, page) + offset;
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -388,7 +429,8 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
|
||||
static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
__dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
|
||||
debug_dma_unmap_page(dev, handle, size, dir, true);
|
||||
__dma_unmap_single(dev, handle, size, dir);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -408,10 +450,9 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
|
||||
static inline void dma_unmap_page(struct device *dev, dma_addr_t handle,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
__dma_page_dev_to_cpu(dma_to_page(dev, handle), handle & ~PAGE_MASK,
|
||||
size, dir);
|
||||
debug_dma_unmap_page(dev, handle, size, dir, false);
|
||||
__dma_unmap_page(dev, handle, size, dir);
|
||||
}
|
||||
#endif /* CONFIG_DMABOUNCE */
|
||||
|
||||
/**
|
||||
* dma_sync_single_range_for_cpu
|
||||
@ -437,6 +478,8 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev,
|
||||
{
|
||||
BUG_ON(!valid_dma_direction(dir));
|
||||
|
||||
debug_dma_sync_single_for_cpu(dev, handle + offset, size, dir);
|
||||
|
||||
if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir))
|
||||
return;
|
||||
|
||||
@ -449,6 +492,8 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
|
||||
{
|
||||
BUG_ON(!valid_dma_direction(dir));
|
||||
|
||||
debug_dma_sync_single_for_device(dev, handle + offset, size, dir);
|
||||
|
||||
if (!dmabounce_sync_for_device(dev, handle, offset, size, dir))
|
||||
return;
|
||||
|
||||
|
@ -45,13 +45,17 @@
|
||||
*/
|
||||
#define DOMAIN_NOACCESS 0
|
||||
#define DOMAIN_CLIENT 1
|
||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
||||
#define DOMAIN_MANAGER 3
|
||||
#else
|
||||
#define DOMAIN_MANAGER 1
|
||||
#endif
|
||||
|
||||
#define domain_val(dom,type) ((type) << (2*(dom)))
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
||||
#define set_domain(x) \
|
||||
do { \
|
||||
__asm__ __volatile__( \
|
||||
@ -74,5 +78,28 @@
|
||||
#define modify_domain(dom,type) do { } while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Generate the T (user) versions of the LDR/STR and related
|
||||
* instructions (inline assembly)
|
||||
*/
|
||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
||||
#define T(instr) #instr "t"
|
||||
#else
|
||||
#define T(instr) #instr
|
||||
#endif
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
* Generate the T (user) versions of the LDR/STR and related
|
||||
* instructions
|
||||
*/
|
||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
||||
#define T(instr) instr ## t
|
||||
#else
|
||||
#define T(instr) instr
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* !__ASM_PROC_DOMAIN_H */
|
||||
|
44
arch/arm/include/asm/entry-macro-multi.S
Normal file
44
arch/arm/include/asm/entry-macro-multi.S
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Interrupt handling. Preserves r7, r8, r9
|
||||
*/
|
||||
.macro arch_irq_handler_default
|
||||
get_irqnr_preamble r5, lr
|
||||
1: get_irqnr_and_base r0, r6, r5, lr
|
||||
movne r1, sp
|
||||
@
|
||||
@ routine called with r0 = irq number, r1 = struct pt_regs *
|
||||
@
|
||||
adrne lr, BSYM(1b)
|
||||
bne asm_do_IRQ
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* XXX
|
||||
*
|
||||
* this macro assumes that irqstat (r6) and base (r5) are
|
||||
* preserved from get_irqnr_and_base above
|
||||
*/
|
||||
ALT_SMP(test_for_ipi r0, r6, r5, lr)
|
||||
ALT_UP_B(9997f)
|
||||
movne r1, sp
|
||||
adrne lr, BSYM(1b)
|
||||
bne do_IPI
|
||||
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
test_for_ltirq r0, r6, r5, lr
|
||||
movne r0, sp
|
||||
adrne lr, BSYM(1b)
|
||||
bne do_local_timer
|
||||
#endif
|
||||
#endif
|
||||
9997:
|
||||
.endm
|
||||
|
||||
.macro arch_irq_handler, symbol_name
|
||||
.align 5
|
||||
.global \symbol_name
|
||||
\symbol_name:
|
||||
mov r4, lr
|
||||
arch_irq_handler_default
|
||||
mov pc, r4
|
||||
.endm
|
@ -13,12 +13,13 @@
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/domain.h>
|
||||
|
||||
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
|
||||
__asm__ __volatile__( \
|
||||
"1: ldrt %1, [%2]\n" \
|
||||
"1: " T(ldr) " %1, [%2]\n" \
|
||||
" " insn "\n" \
|
||||
"2: strt %0, [%2]\n" \
|
||||
"2: " T(str) " %0, [%2]\n" \
|
||||
" mov %0, #0\n" \
|
||||
"3:\n" \
|
||||
" .pushsection __ex_table,\"a\"\n" \
|
||||
@ -97,10 +98,10 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
|
||||
pagefault_disable(); /* implies preempt_disable() */
|
||||
|
||||
__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
|
||||
"1: ldrt %0, [%3]\n"
|
||||
"1: " T(ldr) " %0, [%3]\n"
|
||||
" teq %0, %1\n"
|
||||
" it eq @ explicit IT needed for the 2b label\n"
|
||||
"2: streqt %2, [%3]\n"
|
||||
"2: " T(streq) " %2, [%3]\n"
|
||||
"3:\n"
|
||||
" .pushsection __ex_table,\"a\"\n"
|
||||
" .align 3\n"
|
||||
|
@ -5,13 +5,31 @@
|
||||
#include <linux/threads.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#define NR_IPI 5
|
||||
|
||||
typedef struct {
|
||||
unsigned int __softirq_pending;
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
unsigned int local_timer_irqs;
|
||||
#endif
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned int ipi_irqs[NR_IPI];
|
||||
#endif
|
||||
} ____cacheline_aligned irq_cpustat_t;
|
||||
|
||||
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
|
||||
|
||||
#define __inc_irq_stat(cpu, member) __IRQ_STAT(cpu, member)++
|
||||
#define __get_irq_stat(cpu, member) __IRQ_STAT(cpu, member)
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
u64 smp_irq_stat_cpu(unsigned int cpu);
|
||||
#else
|
||||
#define smp_irq_stat_cpu(cpu) 0
|
||||
#endif
|
||||
|
||||
#define arch_irq_stat_cpu smp_irq_stat_cpu
|
||||
|
||||
#if NR_IRQS > 512
|
||||
#define HARDIRQ_BITS 10
|
||||
#elif NR_IRQS > 256
|
||||
|
@ -30,7 +30,6 @@ asmlinkage void do_local_timer(struct pt_regs *);
|
||||
#include "smp_twd.h"
|
||||
|
||||
#define local_timer_ack() twd_timer_ack()
|
||||
#define local_timer_stop() twd_timer_stop()
|
||||
|
||||
#else
|
||||
|
||||
@ -40,11 +39,6 @@ asmlinkage void do_local_timer(struct pt_regs *);
|
||||
*/
|
||||
int local_timer_ack(void);
|
||||
|
||||
/*
|
||||
* Stop a local timer interrupt.
|
||||
*/
|
||||
void local_timer_stop(void);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -52,12 +46,6 @@ void local_timer_stop(void);
|
||||
*/
|
||||
void local_timer_setup(struct clock_event_device *);
|
||||
|
||||
#else
|
||||
|
||||
static inline void local_timer_stop(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -37,11 +37,20 @@ struct machine_desc {
|
||||
struct meminfo *);
|
||||
void (*reserve)(void);/* reserve mem blocks */
|
||||
void (*map_io)(void);/* IO mapping function */
|
||||
void (*init_early)(void);
|
||||
void (*init_irq)(void);
|
||||
struct sys_timer *timer; /* system tick timer */
|
||||
void (*init_machine)(void);
|
||||
#ifdef CONFIG_MULTI_IRQ_HANDLER
|
||||
void (*handle_irq)(struct pt_regs *);
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Current machine - only accessible during boot.
|
||||
*/
|
||||
extern struct machine_desc *machine_desc;
|
||||
|
||||
/*
|
||||
* Set of macros to define architecture features. This is built into
|
||||
* a table by the linker.
|
||||
|
@ -17,10 +17,12 @@ struct seq_file;
|
||||
/*
|
||||
* This is internal. Do not use it.
|
||||
*/
|
||||
extern unsigned int arch_nr_irqs;
|
||||
extern void (*init_arch_irq)(void);
|
||||
extern void init_FIQ(void);
|
||||
extern int show_fiq_list(struct seq_file *, void *);
|
||||
extern int show_fiq_list(struct seq_file *, int);
|
||||
|
||||
#ifdef CONFIG_MULTI_IRQ_HANDLER
|
||||
extern void (*handle_arch_irq)(struct pt_regs *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is for easy migration, but should be changed in the source
|
||||
|
@ -43,7 +43,6 @@ struct sys_timer {
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct sys_timer *system_timer;
|
||||
extern void timer_tick(void);
|
||||
|
||||
#endif
|
||||
|
@ -33,27 +33,23 @@ struct seq_file;
|
||||
/*
|
||||
* generate IPI list text
|
||||
*/
|
||||
extern void show_ipi_list(struct seq_file *p);
|
||||
extern void show_ipi_list(struct seq_file *, int);
|
||||
|
||||
/*
|
||||
* Called from assembly code, this handles an IPI.
|
||||
*/
|
||||
asmlinkage void do_IPI(struct pt_regs *regs);
|
||||
asmlinkage void do_IPI(int ipinr, struct pt_regs *regs);
|
||||
|
||||
/*
|
||||
* Setup the set of possible CPUs (via set_cpu_possible)
|
||||
*/
|
||||
extern void smp_init_cpus(void);
|
||||
|
||||
/*
|
||||
* Move global data into per-processor storage.
|
||||
*/
|
||||
extern void smp_store_cpu_info(unsigned int cpuid);
|
||||
|
||||
/*
|
||||
* Raise an IPI cross call on CPUs in callmap.
|
||||
*/
|
||||
extern void smp_cross_call(const struct cpumask *mask);
|
||||
extern void smp_cross_call(const struct cpumask *mask, int ipi);
|
||||
|
||||
/*
|
||||
* Boot a secondary CPU, and assign it the specified idle task.
|
||||
@ -72,6 +68,11 @@ asmlinkage void secondary_start_kernel(void);
|
||||
*/
|
||||
extern void platform_secondary_init(unsigned int cpu);
|
||||
|
||||
/*
|
||||
* Initialize cpu_possible map, and enable coherency
|
||||
*/
|
||||
extern void platform_smp_prepare_cpus(unsigned int);
|
||||
|
||||
/*
|
||||
* Initial data for bringing up a secondary CPU.
|
||||
*/
|
||||
@ -97,6 +98,6 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
|
||||
/*
|
||||
* show local interrupt info
|
||||
*/
|
||||
extern void show_local_irqs(struct seq_file *);
|
||||
extern void show_local_irqs(struct seq_file *, int);
|
||||
|
||||
#endif /* ifndef __ASM_ARM_SMP_H */
|
||||
|
@ -1,17 +0,0 @@
|
||||
#ifndef ASMARM_SMP_MIDR_H
|
||||
#define ASMARM_SMP_MIDR_H
|
||||
|
||||
#define hard_smp_processor_id() \
|
||||
({ \
|
||||
unsigned int cpunum; \
|
||||
__asm__("\n" \
|
||||
"1: mrc p15, 0, %0, c0, c0, 5\n" \
|
||||
" .pushsection \".alt.smp.init\", \"a\"\n"\
|
||||
" .long 1b\n" \
|
||||
" mov %0, #0\n" \
|
||||
" .popsection" \
|
||||
: "=r" (cpunum)); \
|
||||
cpunum &= 0x0F; \
|
||||
})
|
||||
|
||||
#endif
|
@ -22,7 +22,6 @@ struct clock_event_device;
|
||||
|
||||
extern void __iomem *twd_base;
|
||||
|
||||
void twd_timer_stop(void);
|
||||
int twd_timer_ack(void);
|
||||
void twd_timer_setup(struct clock_event_device *);
|
||||
|
||||
|
@ -124,6 +124,13 @@ extern unsigned int user_debug;
|
||||
#define vectors_high() (0)
|
||||
#endif
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 7 || \
|
||||
(__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K))
|
||||
#define sev() __asm__ __volatile__ ("sev" : : : "memory")
|
||||
#define wfe() __asm__ __volatile__ ("wfe" : : : "memory")
|
||||
#define wfi() __asm__ __volatile__ ("wfi" : : : "memory")
|
||||
#endif
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 7
|
||||
#define isb() __asm__ __volatile__ ("isb" : : : "memory")
|
||||
#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
|
||||
|
@ -46,4 +46,6 @@ static inline int in_exception_text(unsigned long ptr)
|
||||
extern void __init early_trap_init(void);
|
||||
extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
|
||||
|
||||
extern void *vectors_page;
|
||||
|
||||
#endif
|
||||
|
@ -227,7 +227,7 @@ do { \
|
||||
|
||||
#define __get_user_asm_byte(x,addr,err) \
|
||||
__asm__ __volatile__( \
|
||||
"1: ldrbt %1,[%2]\n" \
|
||||
"1: " T(ldrb) " %1,[%2],#0\n" \
|
||||
"2:\n" \
|
||||
" .pushsection .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
@ -263,7 +263,7 @@ do { \
|
||||
|
||||
#define __get_user_asm_word(x,addr,err) \
|
||||
__asm__ __volatile__( \
|
||||
"1: ldrt %1,[%2]\n" \
|
||||
"1: " T(ldr) " %1,[%2],#0\n" \
|
||||
"2:\n" \
|
||||
" .pushsection .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
@ -308,7 +308,7 @@ do { \
|
||||
|
||||
#define __put_user_asm_byte(x,__pu_addr,err) \
|
||||
__asm__ __volatile__( \
|
||||
"1: strbt %1,[%2]\n" \
|
||||
"1: " T(strb) " %1,[%2],#0\n" \
|
||||
"2:\n" \
|
||||
" .pushsection .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
@ -341,7 +341,7 @@ do { \
|
||||
|
||||
#define __put_user_asm_word(x,__pu_addr,err) \
|
||||
__asm__ __volatile__( \
|
||||
"1: strt %1,[%2]\n" \
|
||||
"1: " T(str) " %1,[%2],#0\n" \
|
||||
"2:\n" \
|
||||
" .pushsection .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
@ -366,10 +366,10 @@ do { \
|
||||
|
||||
#define __put_user_asm_dword(x,__pu_addr,err) \
|
||||
__asm__ __volatile__( \
|
||||
ARM( "1: strt " __reg_oper1 ", [%1], #4\n" ) \
|
||||
ARM( "2: strt " __reg_oper0 ", [%1]\n" ) \
|
||||
THUMB( "1: strt " __reg_oper1 ", [%1]\n" ) \
|
||||
THUMB( "2: strt " __reg_oper0 ", [%1, #4]\n" ) \
|
||||
ARM( "1: " T(str) " " __reg_oper1 ", [%1], #4\n" ) \
|
||||
ARM( "2: " T(str) " " __reg_oper0 ", [%1]\n" ) \
|
||||
THUMB( "1: " T(str) " " __reg_oper1 ", [%1]\n" ) \
|
||||
THUMB( "2: " T(str) " " __reg_oper0 ", [%1, #4]\n" ) \
|
||||
"3:\n" \
|
||||
" .pushsection .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
|
@ -30,7 +30,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o
|
||||
obj-$(CONFIG_ISA_DMA) += dma-isa.o
|
||||
obj-$(CONFIG_PCI) += bios32.o isa.o
|
||||
obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_SMP) += smp.o smp_tlb.o
|
||||
obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o
|
||||
obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
|
||||
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
||||
@ -44,6 +44,8 @@ obj-$(CONFIG_KGDB) += kgdb.o
|
||||
obj-$(CONFIG_ARM_UNWIND) += unwind.o
|
||||
obj-$(CONFIG_HAVE_TCM) += tcm.o
|
||||
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
|
||||
obj-$(CONFIG_SWP_EMULATE) += swp_emulate.o
|
||||
CFLAGS_swp_emulate.o := -Wa,-march=armv7-a
|
||||
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
|
||||
|
||||
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
|
||||
|
@ -25,42 +25,22 @@
|
||||
#include <asm/tls.h>
|
||||
|
||||
#include "entry-header.S"
|
||||
#include <asm/entry-macro-multi.S>
|
||||
|
||||
/*
|
||||
* Interrupt handling. Preserves r7, r8, r9
|
||||
*/
|
||||
.macro irq_handler
|
||||
get_irqnr_preamble r5, lr
|
||||
1: get_irqnr_and_base r0, r6, r5, lr
|
||||
movne r1, sp
|
||||
@
|
||||
@ routine called with r0 = irq number, r1 = struct pt_regs *
|
||||
@
|
||||
adrne lr, BSYM(1b)
|
||||
bne asm_do_IRQ
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* XXX
|
||||
*
|
||||
* this macro assumes that irqstat (r6) and base (r5) are
|
||||
* preserved from get_irqnr_and_base above
|
||||
*/
|
||||
ALT_SMP(test_for_ipi r0, r6, r5, lr)
|
||||
ALT_UP_B(9997f)
|
||||
movne r0, sp
|
||||
adrne lr, BSYM(1b)
|
||||
bne do_IPI
|
||||
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
test_for_ltirq r0, r6, r5, lr
|
||||
movne r0, sp
|
||||
adrne lr, BSYM(1b)
|
||||
bne do_local_timer
|
||||
#ifdef CONFIG_MULTI_IRQ_HANDLER
|
||||
ldr r5, =handle_arch_irq
|
||||
mov r0, sp
|
||||
ldr r5, [r5]
|
||||
adr lr, BSYM(9997f)
|
||||
teq r5, #0
|
||||
movne pc, r5
|
||||
#endif
|
||||
arch_irq_handler_default
|
||||
9997:
|
||||
#endif
|
||||
|
||||
.endm
|
||||
|
||||
#ifdef CONFIG_KPROBES
|
||||
@ -735,7 +715,7 @@ ENTRY(__switch_to)
|
||||
THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack
|
||||
THUMB( str sp, [ip], #4 )
|
||||
THUMB( str lr, [ip], #4 )
|
||||
#ifdef CONFIG_MMU
|
||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
||||
ldr r6, [r2, #TI_CPU_DOMAIN]
|
||||
#endif
|
||||
set_tls r3, r4, r5
|
||||
@ -744,7 +724,7 @@ ENTRY(__switch_to)
|
||||
ldr r8, =__stack_chk_guard
|
||||
ldr r7, [r7, #TSK_STACK_CANARY]
|
||||
#endif
|
||||
#ifdef CONFIG_MMU
|
||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
||||
mcr p15, 0, r6, c3, c0, 0 @ Set domain register
|
||||
#endif
|
||||
mov r5, r0
|
||||
@ -842,7 +822,7 @@ __kuser_helper_start:
|
||||
*/
|
||||
|
||||
__kuser_memory_barrier: @ 0xffff0fa0
|
||||
smp_dmb
|
||||
smp_dmb arm
|
||||
usr_ret lr
|
||||
|
||||
.align 5
|
||||
@ -959,7 +939,7 @@ kuser_cmpxchg_fixup:
|
||||
|
||||
#else
|
||||
|
||||
smp_dmb
|
||||
smp_dmb arm
|
||||
1: ldrex r3, [r2]
|
||||
subs r3, r3, r0
|
||||
strexeq r3, r1, [r2]
|
||||
@ -1245,3 +1225,9 @@ cr_alignment:
|
||||
.space 4
|
||||
cr_no_alignment:
|
||||
.space 4
|
||||
|
||||
#ifdef CONFIG_MULTI_IRQ_HANDLER
|
||||
.globl handle_arch_irq
|
||||
handle_arch_irq:
|
||||
.space 4
|
||||
#endif
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <asm/fiq.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
static unsigned long no_fiq_insn;
|
||||
|
||||
@ -67,17 +68,22 @@ static struct fiq_handler default_owner = {
|
||||
|
||||
static struct fiq_handler *current_fiq = &default_owner;
|
||||
|
||||
int show_fiq_list(struct seq_file *p, void *v)
|
||||
int show_fiq_list(struct seq_file *p, int prec)
|
||||
{
|
||||
if (current_fiq != &default_owner)
|
||||
seq_printf(p, "FIQ: %s\n", current_fiq->name);
|
||||
seq_printf(p, "%*s: %s\n", prec, "FIQ",
|
||||
current_fiq->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_fiq_handler(void *start, unsigned int length)
|
||||
{
|
||||
#if defined(CONFIG_CPU_USE_DOMAINS)
|
||||
memcpy((void *)0xffff001c, start, length);
|
||||
#else
|
||||
memcpy(vectors_page + 0x1c, start, length);
|
||||
#endif
|
||||
flush_icache_range(0xffff001c, 0xffff001c + length);
|
||||
if (!vectors_high())
|
||||
flush_icache_range(0x1c, 0x1c + length);
|
||||
|
@ -91,6 +91,11 @@ ENTRY(stext)
|
||||
movs r8, r5 @ invalid machine (r5=0)?
|
||||
THUMB( it eq ) @ force fixup-able long branch encoding
|
||||
beq __error_a @ yes, error 'a'
|
||||
|
||||
/*
|
||||
* r1 = machine no, r2 = atags,
|
||||
* r8 = machinfo, r9 = cpuid, r10 = procinfo
|
||||
*/
|
||||
bl __vet_atags
|
||||
#ifdef CONFIG_SMP_ON_UP
|
||||
bl __fixup_smp
|
||||
@ -387,19 +392,19 @@ ENDPROC(__turn_mmu_on)
|
||||
|
||||
#ifdef CONFIG_SMP_ON_UP
|
||||
__fixup_smp:
|
||||
mov r7, #0x00070000
|
||||
orr r6, r7, #0xff000000 @ mask 0xff070000
|
||||
orr r7, r7, #0x41000000 @ val 0x41070000
|
||||
and r0, r9, r6
|
||||
teq r0, r7 @ ARM CPU and ARMv6/v7?
|
||||
mov r4, #0x00070000
|
||||
orr r3, r4, #0xff000000 @ mask 0xff070000
|
||||
orr r4, r4, #0x41000000 @ val 0x41070000
|
||||
and r0, r9, r3
|
||||
teq r0, r4 @ ARM CPU and ARMv6/v7?
|
||||
bne __fixup_smp_on_up @ no, assume UP
|
||||
|
||||
orr r6, r6, #0x0000ff00
|
||||
orr r6, r6, #0x000000f0 @ mask 0xff07fff0
|
||||
orr r7, r7, #0x0000b000
|
||||
orr r7, r7, #0x00000020 @ val 0x4107b020
|
||||
and r0, r9, r6
|
||||
teq r0, r7 @ ARM 11MPCore?
|
||||
orr r3, r3, #0x0000ff00
|
||||
orr r3, r3, #0x000000f0 @ mask 0xff07fff0
|
||||
orr r4, r4, #0x0000b000
|
||||
orr r4, r4, #0x00000020 @ val 0x4107b020
|
||||
and r0, r9, r3
|
||||
teq r0, r4 @ ARM 11MPCore?
|
||||
moveq pc, lr @ yes, assume SMP
|
||||
|
||||
mrc p15, 0, r0, c0, c0, 5 @ read MPIDR
|
||||
@ -408,15 +413,22 @@ __fixup_smp:
|
||||
|
||||
__fixup_smp_on_up:
|
||||
adr r0, 1f
|
||||
ldmia r0, {r3, r6, r7}
|
||||
ldmia r0, {r3 - r5}
|
||||
sub r3, r0, r3
|
||||
add r6, r6, r3
|
||||
add r7, r7, r3
|
||||
2: cmp r6, r7
|
||||
ldmia r6!, {r0, r4}
|
||||
strlo r4, [r0, r3]
|
||||
blo 2b
|
||||
mov pc, lr
|
||||
add r4, r4, r3
|
||||
add r5, r5, r3
|
||||
2: cmp r4, r5
|
||||
movhs pc, lr
|
||||
ldmia r4!, {r0, r6}
|
||||
ARM( str r6, [r0, r3] )
|
||||
THUMB( add r0, r0, r3 )
|
||||
#ifdef __ARMEB__
|
||||
THUMB( mov r6, r6, ror #16 ) @ Convert word order for big-endian.
|
||||
#endif
|
||||
THUMB( strh r6, [r0], #2 ) @ For Thumb-2, store as two halfwords
|
||||
THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r3.
|
||||
THUMB( strh r6, [r0] )
|
||||
b 2b
|
||||
ENDPROC(__fixup_smp)
|
||||
|
||||
.align
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <linux/ftrace.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
@ -48,8 +49,6 @@
|
||||
#define irq_finish(irq) do { } while (0)
|
||||
#endif
|
||||
|
||||
unsigned int arch_nr_irqs;
|
||||
void (*init_arch_irq)(void) __initdata = NULL;
|
||||
unsigned long irq_err_count;
|
||||
|
||||
int show_interrupts(struct seq_file *p, void *v)
|
||||
@ -58,11 +57,20 @@ int show_interrupts(struct seq_file *p, void *v)
|
||||
struct irq_desc *desc;
|
||||
struct irqaction * action;
|
||||
unsigned long flags;
|
||||
int prec, n;
|
||||
|
||||
for (prec = 3, n = 1000; prec < 10 && n <= nr_irqs; prec++)
|
||||
n *= 10;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
if (prec < 4)
|
||||
prec = 4;
|
||||
#endif
|
||||
|
||||
if (i == 0) {
|
||||
char cpuname[12];
|
||||
|
||||
seq_printf(p, " ");
|
||||
seq_printf(p, "%*s ", prec, "");
|
||||
for_each_present_cpu(cpu) {
|
||||
sprintf(cpuname, "CPU%d", cpu);
|
||||
seq_printf(p, " %10s", cpuname);
|
||||
@ -77,7 +85,7 @@ int show_interrupts(struct seq_file *p, void *v)
|
||||
if (!action)
|
||||
goto unlock;
|
||||
|
||||
seq_printf(p, "%3d: ", i);
|
||||
seq_printf(p, "%*d: ", prec, i);
|
||||
for_each_present_cpu(cpu)
|
||||
seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
|
||||
seq_printf(p, " %10s", desc->chip->name ? : "-");
|
||||
@ -90,13 +98,15 @@ unlock:
|
||||
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
||||
} else if (i == nr_irqs) {
|
||||
#ifdef CONFIG_FIQ
|
||||
show_fiq_list(p, v);
|
||||
show_fiq_list(p, prec);
|
||||
#endif
|
||||
#ifdef CONFIG_SMP
|
||||
show_ipi_list(p);
|
||||
show_local_irqs(p);
|
||||
show_ipi_list(p, prec);
|
||||
#endif
|
||||
seq_printf(p, "Err: %10lu\n", irq_err_count);
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
show_local_irqs(p, prec);
|
||||
#endif
|
||||
seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -156,13 +166,13 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
|
||||
|
||||
void __init init_IRQ(void)
|
||||
{
|
||||
init_arch_irq();
|
||||
machine_desc->init_irq();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPARSE_IRQ
|
||||
int __init arch_probe_nr_irqs(void)
|
||||
{
|
||||
nr_irqs = arch_nr_irqs ? arch_nr_irqs : NR_IRQS;
|
||||
nr_irqs = machine_desc->nr_irqs ? machine_desc->nr_irqs : NR_IRQS;
|
||||
return nr_irqs;
|
||||
}
|
||||
#endif
|
||||
|
@ -75,9 +75,9 @@ extern void reboot_setup(char *str);
|
||||
|
||||
unsigned int processor_id;
|
||||
EXPORT_SYMBOL(processor_id);
|
||||
unsigned int __machine_arch_type;
|
||||
unsigned int __machine_arch_type __read_mostly;
|
||||
EXPORT_SYMBOL(__machine_arch_type);
|
||||
unsigned int cacheid;
|
||||
unsigned int cacheid __read_mostly;
|
||||
EXPORT_SYMBOL(cacheid);
|
||||
|
||||
unsigned int __atags_pointer __initdata;
|
||||
@ -91,24 +91,24 @@ EXPORT_SYMBOL(system_serial_low);
|
||||
unsigned int system_serial_high;
|
||||
EXPORT_SYMBOL(system_serial_high);
|
||||
|
||||
unsigned int elf_hwcap;
|
||||
unsigned int elf_hwcap __read_mostly;
|
||||
EXPORT_SYMBOL(elf_hwcap);
|
||||
|
||||
|
||||
#ifdef MULTI_CPU
|
||||
struct processor processor;
|
||||
struct processor processor __read_mostly;
|
||||
#endif
|
||||
#ifdef MULTI_TLB
|
||||
struct cpu_tlb_fns cpu_tlb;
|
||||
struct cpu_tlb_fns cpu_tlb __read_mostly;
|
||||
#endif
|
||||
#ifdef MULTI_USER
|
||||
struct cpu_user_fns cpu_user;
|
||||
struct cpu_user_fns cpu_user __read_mostly;
|
||||
#endif
|
||||
#ifdef MULTI_CACHE
|
||||
struct cpu_cache_fns cpu_cache;
|
||||
struct cpu_cache_fns cpu_cache __read_mostly;
|
||||
#endif
|
||||
#ifdef CONFIG_OUTER_CACHE
|
||||
struct outer_cache_fns outer_cache;
|
||||
struct outer_cache_fns outer_cache __read_mostly;
|
||||
EXPORT_SYMBOL(outer_cache);
|
||||
#endif
|
||||
|
||||
@ -126,6 +126,7 @@ EXPORT_SYMBOL(elf_platform);
|
||||
static const char *cpu_name;
|
||||
static const char *machine_name;
|
||||
static char __initdata cmd_line[COMMAND_LINE_SIZE];
|
||||
struct machine_desc *machine_desc __initdata;
|
||||
|
||||
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
|
||||
static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
|
||||
@ -708,13 +709,11 @@ static struct init_tags {
|
||||
{ 0, ATAG_NONE }
|
||||
};
|
||||
|
||||
static void (*init_machine)(void) __initdata;
|
||||
|
||||
static int __init customize_machine(void)
|
||||
{
|
||||
/* customizes platform devices, or adds new ones */
|
||||
if (init_machine)
|
||||
init_machine();
|
||||
if (machine_desc->init_machine)
|
||||
machine_desc->init_machine();
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(customize_machine);
|
||||
@ -809,6 +808,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
|
||||
setup_processor();
|
||||
mdesc = setup_machine(machine_arch_type);
|
||||
machine_desc = mdesc;
|
||||
machine_name = mdesc->name;
|
||||
|
||||
if (mdesc->soft_reboot)
|
||||
@ -868,13 +868,9 @@ void __init setup_arch(char **cmdline_p)
|
||||
cpu_init();
|
||||
tcm_init();
|
||||
|
||||
/*
|
||||
* Set up various architecture-specific pointers
|
||||
*/
|
||||
arch_nr_irqs = mdesc->nr_irqs;
|
||||
init_arch_irq = mdesc->init_irq;
|
||||
system_timer = mdesc->timer;
|
||||
init_machine = mdesc->init_machine;
|
||||
#ifdef CONFIG_MULTI_IRQ_HANDLER
|
||||
handle_arch_irq = mdesc->handle_irq;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VT
|
||||
#if defined(CONFIG_VGA_CONSOLE)
|
||||
@ -884,6 +880,9 @@ void __init setup_arch(char **cmdline_p)
|
||||
#endif
|
||||
#endif
|
||||
early_trap_init();
|
||||
|
||||
if (mdesc->init_early)
|
||||
mdesc->init_early();
|
||||
}
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/cacheflush.h>
|
||||
@ -38,7 +39,6 @@
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
/*
|
||||
* as from 2.5, kernels no longer have an init_tasks structure
|
||||
@ -47,22 +47,8 @@
|
||||
*/
|
||||
struct secondary_data secondary_data;
|
||||
|
||||
/*
|
||||
* structures for inter-processor calls
|
||||
* - A collection of single bit ipi messages.
|
||||
*/
|
||||
struct ipi_data {
|
||||
spinlock_t lock;
|
||||
unsigned long ipi_count;
|
||||
unsigned long bits;
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct ipi_data, ipi_data) = {
|
||||
.lock = SPIN_LOCK_UNLOCKED,
|
||||
};
|
||||
|
||||
enum ipi_msg_type {
|
||||
IPI_TIMER,
|
||||
IPI_TIMER = 2,
|
||||
IPI_RESCHEDULE,
|
||||
IPI_CALL_FUNC,
|
||||
IPI_CALL_FUNC_SINGLE,
|
||||
@ -178,8 +164,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
||||
barrier();
|
||||
}
|
||||
|
||||
if (!cpu_online(cpu))
|
||||
if (!cpu_online(cpu)) {
|
||||
pr_crit("CPU%u: failed to come online\n", cpu);
|
||||
ret = -EIO;
|
||||
}
|
||||
} else {
|
||||
pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
|
||||
}
|
||||
|
||||
secondary_data.stack = NULL;
|
||||
@ -195,18 +185,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
||||
|
||||
pgd_free(&init_mm, pgd);
|
||||
|
||||
if (ret) {
|
||||
printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
|
||||
|
||||
/*
|
||||
* FIXME: We need to clean up the new idle thread. --rmk
|
||||
*/
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static void percpu_timer_stop(void);
|
||||
|
||||
/*
|
||||
* __cpu_disable runs on the processor to be shutdown.
|
||||
*/
|
||||
@ -234,7 +218,7 @@ int __cpu_disable(void)
|
||||
/*
|
||||
* Stop the local timer for this CPU.
|
||||
*/
|
||||
local_timer_stop();
|
||||
percpu_timer_stop();
|
||||
|
||||
/*
|
||||
* Flush user cache and TLB mappings, and then remove this CPU
|
||||
@ -253,12 +237,20 @@ int __cpu_disable(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DECLARE_COMPLETION(cpu_died);
|
||||
|
||||
/*
|
||||
* called on the thread which is asking for a CPU to be shutdown -
|
||||
* waits until shutdown has completed, or it is timed out.
|
||||
*/
|
||||
void __cpu_die(unsigned int cpu)
|
||||
{
|
||||
if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) {
|
||||
pr_err("CPU%u: cpu didn't die\n", cpu);
|
||||
return;
|
||||
}
|
||||
printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
|
||||
|
||||
if (!platform_cpu_kill(cpu))
|
||||
printk("CPU%u: unable to kill\n", cpu);
|
||||
}
|
||||
@ -275,12 +267,17 @@ void __ref cpu_die(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
local_irq_disable();
|
||||
idle_task_exit();
|
||||
|
||||
local_irq_disable();
|
||||
mb();
|
||||
|
||||
/* Tell __cpu_die() that this CPU is now safe to dispose of */
|
||||
complete(&cpu_died);
|
||||
|
||||
/*
|
||||
* actual CPU shutdown procedure is at least platform (if not
|
||||
* CPU) specific
|
||||
* CPU) specific.
|
||||
*/
|
||||
platform_cpu_die(cpu);
|
||||
|
||||
@ -290,12 +287,24 @@ void __ref cpu_die(void)
|
||||
* to be repeated to undo the effects of taking the CPU offline.
|
||||
*/
|
||||
__asm__("mov sp, %0\n"
|
||||
" mov fp, #0\n"
|
||||
" b secondary_start_kernel"
|
||||
:
|
||||
: "r" (task_stack_page(current) + THREAD_SIZE - 8));
|
||||
}
|
||||
#endif /* CONFIG_HOTPLUG_CPU */
|
||||
|
||||
/*
|
||||
* Called by both boot and secondaries to move global data into
|
||||
* per-processor storage.
|
||||
*/
|
||||
static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
|
||||
{
|
||||
struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
|
||||
|
||||
cpu_info->loops_per_jiffy = loops_per_jiffy;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the secondary CPU boot entry. We're using this CPUs
|
||||
* idle thread stack, but a set of temporary page tables.
|
||||
@ -320,6 +329,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
|
||||
|
||||
cpu_init();
|
||||
preempt_disable();
|
||||
trace_hardirqs_off();
|
||||
|
||||
/*
|
||||
* Give the platform a chance to do its own initialisation.
|
||||
@ -353,17 +363,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
|
||||
cpu_idle();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by both boot and secondaries to move global data into
|
||||
* per-processor storage.
|
||||
*/
|
||||
void __cpuinit smp_store_cpu_info(unsigned int cpuid)
|
||||
{
|
||||
struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
|
||||
|
||||
cpu_info->loops_per_jiffy = loops_per_jiffy;
|
||||
}
|
||||
|
||||
void __init smp_cpus_done(unsigned int max_cpus)
|
||||
{
|
||||
int cpu;
|
||||
@ -386,61 +385,80 @@ void __init smp_prepare_boot_cpu(void)
|
||||
per_cpu(cpu_data, cpu).idle = current;
|
||||
}
|
||||
|
||||
static void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg)
|
||||
void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int cpu;
|
||||
unsigned int ncores = num_possible_cpus();
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
for_each_cpu(cpu, mask) {
|
||||
struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
|
||||
|
||||
spin_lock(&ipi->lock);
|
||||
ipi->bits |= 1 << msg;
|
||||
spin_unlock(&ipi->lock);
|
||||
}
|
||||
smp_store_cpu_info(smp_processor_id());
|
||||
|
||||
/*
|
||||
* Call the platform specific cross-CPU call function.
|
||||
* are we trying to boot more cores than exist?
|
||||
*/
|
||||
smp_cross_call(mask);
|
||||
if (max_cpus > ncores)
|
||||
max_cpus = ncores;
|
||||
|
||||
local_irq_restore(flags);
|
||||
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 if there are more than one CPU
|
||||
* and let them know where to start.
|
||||
*/
|
||||
platform_smp_prepare_cpus(max_cpus);
|
||||
}
|
||||
}
|
||||
|
||||
void arch_send_call_function_ipi_mask(const struct cpumask *mask)
|
||||
{
|
||||
send_ipi_message(mask, IPI_CALL_FUNC);
|
||||
smp_cross_call(mask, IPI_CALL_FUNC);
|
||||
}
|
||||
|
||||
void arch_send_call_function_single_ipi(int cpu)
|
||||
{
|
||||
send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
|
||||
smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
|
||||
}
|
||||
|
||||
void show_ipi_list(struct seq_file *p)
|
||||
static const char *ipi_types[NR_IPI] = {
|
||||
#define S(x,s) [x - IPI_TIMER] = s
|
||||
S(IPI_TIMER, "Timer broadcast interrupts"),
|
||||
S(IPI_RESCHEDULE, "Rescheduling interrupts"),
|
||||
S(IPI_CALL_FUNC, "Function call interrupts"),
|
||||
S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
|
||||
S(IPI_CPU_STOP, "CPU stop interrupts"),
|
||||
};
|
||||
|
||||
void show_ipi_list(struct seq_file *p, int prec)
|
||||
{
|
||||
unsigned int cpu;
|
||||
unsigned int cpu, i;
|
||||
|
||||
seq_puts(p, "IPI:");
|
||||
for (i = 0; i < NR_IPI; i++) {
|
||||
seq_printf(p, "%*s%u: ", prec - 1, "IPI", i);
|
||||
|
||||
for_each_present_cpu(cpu)
|
||||
seq_printf(p, " %10lu", per_cpu(ipi_data, cpu).ipi_count);
|
||||
for_each_present_cpu(cpu)
|
||||
seq_printf(p, "%10u ",
|
||||
__get_irq_stat(cpu, ipi_irqs[i]));
|
||||
|
||||
seq_putc(p, '\n');
|
||||
seq_printf(p, " %s\n", ipi_types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void show_local_irqs(struct seq_file *p)
|
||||
u64 smp_irq_stat_cpu(unsigned int cpu)
|
||||
{
|
||||
unsigned int cpu;
|
||||
u64 sum = 0;
|
||||
int i;
|
||||
|
||||
seq_printf(p, "LOC: ");
|
||||
for (i = 0; i < NR_IPI; i++)
|
||||
sum += __get_irq_stat(cpu, ipi_irqs[i]);
|
||||
|
||||
for_each_present_cpu(cpu)
|
||||
seq_printf(p, "%10u ", irq_stat[cpu].local_timer_irqs);
|
||||
#ifdef CONFIG_LOCAL_TIMERS
|
||||
sum += __get_irq_stat(cpu, local_timer_irqs);
|
||||
#endif
|
||||
|
||||
seq_putc(p, '\n');
|
||||
return sum;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -463,18 +481,30 @@ asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
if (local_timer_ack()) {
|
||||
irq_stat[cpu].local_timer_irqs++;
|
||||
__inc_irq_stat(cpu, local_timer_irqs);
|
||||
ipi_timer();
|
||||
}
|
||||
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
void show_local_irqs(struct seq_file *p, int prec)
|
||||
{
|
||||
unsigned int cpu;
|
||||
|
||||
seq_printf(p, "%*s: ", prec, "LOC");
|
||||
|
||||
for_each_present_cpu(cpu)
|
||||
seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs));
|
||||
|
||||
seq_printf(p, " Local timer interrupts\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
|
||||
static void smp_timer_broadcast(const struct cpumask *mask)
|
||||
{
|
||||
send_ipi_message(mask, IPI_TIMER);
|
||||
smp_cross_call(mask, IPI_TIMER);
|
||||
}
|
||||
#else
|
||||
#define smp_timer_broadcast NULL
|
||||
@ -511,6 +541,21 @@ void __cpuinit percpu_timer_setup(void)
|
||||
local_timer_setup(evt);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
/*
|
||||
* The generic clock events code purposely does not stop the local timer
|
||||
* on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it
|
||||
* manually here.
|
||||
*/
|
||||
static void percpu_timer_stop(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
|
||||
|
||||
evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
|
||||
}
|
||||
#endif
|
||||
|
||||
static DEFINE_SPINLOCK(stop_lock);
|
||||
|
||||
/*
|
||||
@ -537,85 +582,70 @@ static void ipi_cpu_stop(unsigned int cpu)
|
||||
|
||||
/*
|
||||
* Main handler for inter-processor interrupts
|
||||
*
|
||||
* For ARM, the ipimask now only identifies a single
|
||||
* category of IPI (Bit 1 IPIs have been replaced by a
|
||||
* different mechanism):
|
||||
*
|
||||
* Bit 0 - Inter-processor function call
|
||||
*/
|
||||
asmlinkage void __exception_irq_entry do_IPI(struct pt_regs *regs)
|
||||
asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
|
||||
ipi->ipi_count++;
|
||||
if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI)
|
||||
__inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]);
|
||||
|
||||
for (;;) {
|
||||
unsigned long msgs;
|
||||
switch (ipinr) {
|
||||
case IPI_TIMER:
|
||||
ipi_timer();
|
||||
break;
|
||||
|
||||
spin_lock(&ipi->lock);
|
||||
msgs = ipi->bits;
|
||||
ipi->bits = 0;
|
||||
spin_unlock(&ipi->lock);
|
||||
case IPI_RESCHEDULE:
|
||||
/*
|
||||
* nothing more to do - eveything is
|
||||
* done on the interrupt return path
|
||||
*/
|
||||
break;
|
||||
|
||||
if (!msgs)
|
||||
break;
|
||||
case IPI_CALL_FUNC:
|
||||
generic_smp_call_function_interrupt();
|
||||
break;
|
||||
|
||||
do {
|
||||
unsigned nextmsg;
|
||||
case IPI_CALL_FUNC_SINGLE:
|
||||
generic_smp_call_function_single_interrupt();
|
||||
break;
|
||||
|
||||
nextmsg = msgs & -msgs;
|
||||
msgs &= ~nextmsg;
|
||||
nextmsg = ffz(~nextmsg);
|
||||
case IPI_CPU_STOP:
|
||||
ipi_cpu_stop(cpu);
|
||||
break;
|
||||
|
||||
switch (nextmsg) {
|
||||
case IPI_TIMER:
|
||||
ipi_timer();
|
||||
break;
|
||||
|
||||
case IPI_RESCHEDULE:
|
||||
/*
|
||||
* nothing more to do - eveything is
|
||||
* done on the interrupt return path
|
||||
*/
|
||||
break;
|
||||
|
||||
case IPI_CALL_FUNC:
|
||||
generic_smp_call_function_interrupt();
|
||||
break;
|
||||
|
||||
case IPI_CALL_FUNC_SINGLE:
|
||||
generic_smp_call_function_single_interrupt();
|
||||
break;
|
||||
|
||||
case IPI_CPU_STOP:
|
||||
ipi_cpu_stop(cpu);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
|
||||
cpu, nextmsg);
|
||||
break;
|
||||
}
|
||||
} while (msgs);
|
||||
default:
|
||||
printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
|
||||
cpu, ipinr);
|
||||
break;
|
||||
}
|
||||
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
|
||||
void smp_send_reschedule(int cpu)
|
||||
{
|
||||
send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE);
|
||||
smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
|
||||
}
|
||||
|
||||
void smp_send_stop(void)
|
||||
{
|
||||
cpumask_t mask = cpu_online_map;
|
||||
cpu_clear(smp_processor_id(), mask);
|
||||
if (!cpus_empty(mask))
|
||||
send_ipi_message(&mask, IPI_CPU_STOP);
|
||||
unsigned long timeout;
|
||||
|
||||
if (num_online_cpus() > 1) {
|
||||
cpumask_t mask = cpu_online_map;
|
||||
cpu_clear(smp_processor_id(), mask);
|
||||
|
||||
smp_cross_call(&mask, IPI_CPU_STOP);
|
||||
}
|
||||
|
||||
/* Wait up to one second for other CPUs to stop */
|
||||
timeout = USEC_PER_SEC;
|
||||
while (num_online_cpus() > 1 && timeout--)
|
||||
udelay(1);
|
||||
|
||||
if (num_online_cpus() > 1)
|
||||
pr_warning("SMP: failed to stop secondary CPUs\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -625,128 +655,3 @@ 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);
|
||||
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);
|
||||
}
|
||||
|
139
arch/arm/kernel/smp_tlb.c
Normal file
139
arch/arm/kernel/smp_tlb.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* linux/arch/arm/kernel/smp_tlb.c
|
||||
*
|
||||
* Copyright (C) 2002 ARM Limited, All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
#include <asm/smp_plat.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
static void on_each_cpu_mask(void (*func)(void *), void *info, int wait,
|
||||
const struct cpumask *mask)
|
||||
{
|
||||
preempt_disable();
|
||||
|
||||
smp_call_function_many(mask, func, info, wait);
|
||||
if (cpumask_test_cpu(smp_processor_id(), mask))
|
||||
func(info);
|
||||
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* TLB operations
|
||||
*/
|
||||
struct tlb_args {
|
||||
struct vm_area_struct *ta_vma;
|
||||
unsigned long ta_start;
|
||||
unsigned long ta_end;
|
||||
};
|
||||
|
||||
static inline void ipi_flush_tlb_all(void *ignored)
|
||||
{
|
||||
local_flush_tlb_all();
|
||||
}
|
||||
|
||||
static inline void ipi_flush_tlb_mm(void *arg)
|
||||
{
|
||||
struct mm_struct *mm = (struct mm_struct *)arg;
|
||||
|
||||
local_flush_tlb_mm(mm);
|
||||
}
|
||||
|
||||
static inline void ipi_flush_tlb_page(void *arg)
|
||||
{
|
||||
struct tlb_args *ta = (struct tlb_args *)arg;
|
||||
|
||||
local_flush_tlb_page(ta->ta_vma, ta->ta_start);
|
||||
}
|
||||
|
||||
static inline void ipi_flush_tlb_kernel_page(void *arg)
|
||||
{
|
||||
struct tlb_args *ta = (struct tlb_args *)arg;
|
||||
|
||||
local_flush_tlb_kernel_page(ta->ta_start);
|
||||
}
|
||||
|
||||
static inline void ipi_flush_tlb_range(void *arg)
|
||||
{
|
||||
struct tlb_args *ta = (struct tlb_args *)arg;
|
||||
|
||||
local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
|
||||
}
|
||||
|
||||
static inline void ipi_flush_tlb_kernel_range(void *arg)
|
||||
{
|
||||
struct tlb_args *ta = (struct tlb_args *)arg;
|
||||
|
||||
local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
|
||||
}
|
||||
|
||||
void flush_tlb_all(void)
|
||||
{
|
||||
if (tlb_ops_need_broadcast())
|
||||
on_each_cpu(ipi_flush_tlb_all, NULL, 1);
|
||||
else
|
||||
local_flush_tlb_all();
|
||||
}
|
||||
|
||||
void flush_tlb_mm(struct mm_struct *mm)
|
||||
{
|
||||
if (tlb_ops_need_broadcast())
|
||||
on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm));
|
||||
else
|
||||
local_flush_tlb_mm(mm);
|
||||
}
|
||||
|
||||
void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
|
||||
{
|
||||
if (tlb_ops_need_broadcast()) {
|
||||
struct tlb_args ta;
|
||||
ta.ta_vma = vma;
|
||||
ta.ta_start = uaddr;
|
||||
on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm));
|
||||
} else
|
||||
local_flush_tlb_page(vma, uaddr);
|
||||
}
|
||||
|
||||
void flush_tlb_kernel_page(unsigned long kaddr)
|
||||
{
|
||||
if (tlb_ops_need_broadcast()) {
|
||||
struct tlb_args ta;
|
||||
ta.ta_start = kaddr;
|
||||
on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
|
||||
} else
|
||||
local_flush_tlb_kernel_page(kaddr);
|
||||
}
|
||||
|
||||
void flush_tlb_range(struct vm_area_struct *vma,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
if (tlb_ops_need_broadcast()) {
|
||||
struct tlb_args ta;
|
||||
ta.ta_vma = vma;
|
||||
ta.ta_start = start;
|
||||
ta.ta_end = end;
|
||||
on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm));
|
||||
} else
|
||||
local_flush_tlb_range(vma, start, end);
|
||||
}
|
||||
|
||||
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
if (tlb_ops_need_broadcast()) {
|
||||
struct tlb_args ta;
|
||||
ta.ta_start = start;
|
||||
ta.ta_end = end;
|
||||
on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
|
||||
} else
|
||||
local_flush_tlb_kernel_range(start, end);
|
||||
}
|
||||
|
@ -145,13 +145,3 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
|
||||
|
||||
clockevents_register_device(clk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
/*
|
||||
* take a local timer down
|
||||
*/
|
||||
void twd_timer_stop(void)
|
||||
{
|
||||
__raw_writel(0, twd_base + TWD_TIMER_CONTROL);
|
||||
}
|
||||
#endif
|
||||
|
267
arch/arm/kernel/swp_emulate.c
Normal file
267
arch/arm/kernel/swp_emulate.c
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* linux/arch/arm/kernel/swp_emulate.c
|
||||
*
|
||||
* Copyright (C) 2009 ARM Limited
|
||||
* __user_* functions adapted from include/asm/uaccess.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Implements emulation of the SWP/SWPB instructions using load-exclusive and
|
||||
* store-exclusive for processors that have them disabled (or future ones that
|
||||
* might not implement them).
|
||||
*
|
||||
* Syntax of SWP{B} instruction: SWP{B}<c> <Rt>, <Rt2>, [<Rn>]
|
||||
* Where: Rt = destination
|
||||
* Rt2 = source
|
||||
* Rn = address
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
#include <asm/traps.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
/*
|
||||
* Error-checking SWP macros implemented using ldrex{b}/strex{b}
|
||||
*/
|
||||
#define __user_swpX_asm(data, addr, res, temp, B) \
|
||||
__asm__ __volatile__( \
|
||||
" mov %2, %1\n" \
|
||||
"0: ldrex"B" %1, [%3]\n" \
|
||||
"1: strex"B" %0, %2, [%3]\n" \
|
||||
" cmp %0, #0\n" \
|
||||
" movne %0, %4\n" \
|
||||
"2:\n" \
|
||||
" .section .fixup,\"ax\"\n" \
|
||||
" .align 2\n" \
|
||||
"3: mov %0, %5\n" \
|
||||
" b 2b\n" \
|
||||
" .previous\n" \
|
||||
" .section __ex_table,\"a\"\n" \
|
||||
" .align 3\n" \
|
||||
" .long 0b, 3b\n" \
|
||||
" .long 1b, 3b\n" \
|
||||
" .previous" \
|
||||
: "=&r" (res), "+r" (data), "=&r" (temp) \
|
||||
: "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \
|
||||
: "cc", "memory")
|
||||
|
||||
#define __user_swp_asm(data, addr, res, temp) \
|
||||
__user_swpX_asm(data, addr, res, temp, "")
|
||||
#define __user_swpb_asm(data, addr, res, temp) \
|
||||
__user_swpX_asm(data, addr, res, temp, "b")
|
||||
|
||||
/*
|
||||
* Macros/defines for extracting register numbers from instruction.
|
||||
*/
|
||||
#define EXTRACT_REG_NUM(instruction, offset) \
|
||||
(((instruction) & (0xf << (offset))) >> (offset))
|
||||
#define RN_OFFSET 16
|
||||
#define RT_OFFSET 12
|
||||
#define RT2_OFFSET 0
|
||||
/*
|
||||
* Bit 22 of the instruction encoding distinguishes between
|
||||
* the SWP and SWPB variants (bit set means SWPB).
|
||||
*/
|
||||
#define TYPE_SWPB (1 << 22)
|
||||
|
||||
static unsigned long swpcounter;
|
||||
static unsigned long swpbcounter;
|
||||
static unsigned long abtcounter;
|
||||
static pid_t previous_pid;
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int proc_read_status(char *page, char **start, off_t off, int count,
|
||||
int *eof, void *data)
|
||||
{
|
||||
char *p = page;
|
||||
int len;
|
||||
|
||||
p += sprintf(p, "Emulated SWP:\t\t%lu\n", swpcounter);
|
||||
p += sprintf(p, "Emulated SWPB:\t\t%lu\n", swpbcounter);
|
||||
p += sprintf(p, "Aborted SWP{B}:\t\t%lu\n", abtcounter);
|
||||
if (previous_pid != 0)
|
||||
p += sprintf(p, "Last process:\t\t%d\n", previous_pid);
|
||||
|
||||
len = (p - page) - off;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
|
||||
*eof = (len <= count) ? 1 : 0;
|
||||
*start = page + off;
|
||||
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set up process info to signal segmentation fault - called on access error.
|
||||
*/
|
||||
static void set_segfault(struct pt_regs *regs, unsigned long addr)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if (find_vma(current->mm, addr) == NULL)
|
||||
info.si_code = SEGV_MAPERR;
|
||||
else
|
||||
info.si_code = SEGV_ACCERR;
|
||||
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_addr = (void *) instruction_pointer(regs);
|
||||
|
||||
pr_debug("SWP{B} emulation: access caused memory abort!\n");
|
||||
arm_notify_die("Illegal memory access", regs, &info, 0, 0);
|
||||
|
||||
abtcounter++;
|
||||
}
|
||||
|
||||
static int emulate_swpX(unsigned int address, unsigned int *data,
|
||||
unsigned int type)
|
||||
{
|
||||
unsigned int res = 0;
|
||||
|
||||
if ((type != TYPE_SWPB) && (address & 0x3)) {
|
||||
/* SWP to unaligned address not permitted */
|
||||
pr_debug("SWP instruction on unaligned pointer!\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
unsigned long temp;
|
||||
|
||||
/*
|
||||
* Barrier required between accessing protected resource and
|
||||
* releasing a lock for it. Legacy code might not have done
|
||||
* this, and we cannot determine that this is not the case
|
||||
* being emulated, so insert always.
|
||||
*/
|
||||
smp_mb();
|
||||
|
||||
if (type == TYPE_SWPB)
|
||||
__user_swpb_asm(*data, address, res, temp);
|
||||
else
|
||||
__user_swp_asm(*data, address, res, temp);
|
||||
|
||||
if (likely(res != -EAGAIN) || signal_pending(current))
|
||||
break;
|
||||
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
if (res == 0) {
|
||||
/*
|
||||
* Barrier also required between aquiring a lock for a
|
||||
* protected resource and accessing the resource. Inserted for
|
||||
* same reason as above.
|
||||
*/
|
||||
smp_mb();
|
||||
|
||||
if (type == TYPE_SWPB)
|
||||
swpbcounter++;
|
||||
else
|
||||
swpcounter++;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* swp_handler logs the id of calling process, dissects the instruction, sanity
|
||||
* checks the memory location, calls emulate_swpX for the actual operation and
|
||||
* deals with fixup/error handling before returning
|
||||
*/
|
||||
static int swp_handler(struct pt_regs *regs, unsigned int instr)
|
||||
{
|
||||
unsigned int address, destreg, data, type;
|
||||
unsigned int res = 0;
|
||||
|
||||
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, regs->ARM_pc);
|
||||
|
||||
if (current->pid != previous_pid) {
|
||||
pr_debug("\"%s\" (%ld) uses deprecated SWP{B} instruction\n",
|
||||
current->comm, (unsigned long)current->pid);
|
||||
previous_pid = current->pid;
|
||||
}
|
||||
|
||||
address = regs->uregs[EXTRACT_REG_NUM(instr, RN_OFFSET)];
|
||||
data = regs->uregs[EXTRACT_REG_NUM(instr, RT2_OFFSET)];
|
||||
destreg = EXTRACT_REG_NUM(instr, RT_OFFSET);
|
||||
|
||||
type = instr & TYPE_SWPB;
|
||||
|
||||
pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n",
|
||||
EXTRACT_REG_NUM(instr, RN_OFFSET), address,
|
||||
destreg, EXTRACT_REG_NUM(instr, RT2_OFFSET), data);
|
||||
|
||||
/* Check access in reasonable access range for both SWP and SWPB */
|
||||
if (!access_ok(VERIFY_WRITE, (address & ~3), 4)) {
|
||||
pr_debug("SWP{B} emulation: access to %p not allowed!\n",
|
||||
(void *)address);
|
||||
res = -EFAULT;
|
||||
} else {
|
||||
res = emulate_swpX(address, &data, type);
|
||||
}
|
||||
|
||||
if (res == 0) {
|
||||
/*
|
||||
* On successful emulation, revert the adjustment to the PC
|
||||
* made in kernel/traps.c in order to resume execution at the
|
||||
* instruction following the SWP{B}.
|
||||
*/
|
||||
regs->ARM_pc += 4;
|
||||
regs->uregs[destreg] = data;
|
||||
} else if (res == -EFAULT) {
|
||||
/*
|
||||
* Memory errors do not mean emulation failed.
|
||||
* Set up signal info to return SEGV, then return OK
|
||||
*/
|
||||
set_segfault(regs, address);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only emulate SWP/SWPB executed in ARM state/User mode.
|
||||
* The kernel must be SWP free and SWP{B} does not exist in Thumb/ThumbEE.
|
||||
*/
|
||||
static struct undef_hook swp_hook = {
|
||||
.instr_mask = 0x0fb00ff0,
|
||||
.instr_val = 0x01000090,
|
||||
.cpsr_mask = MODE_MASK | PSR_T_BIT | PSR_J_BIT,
|
||||
.cpsr_val = USR_MODE,
|
||||
.fn = swp_handler
|
||||
};
|
||||
|
||||
/*
|
||||
* Register handler and create status file in /proc/cpu
|
||||
* Invoked as late_initcall, since not needed before init spawned.
|
||||
*/
|
||||
static int __init swp_emulation_init(void)
|
||||
{
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry *res;
|
||||
|
||||
res = create_proc_entry("cpu/swp_emulation", S_IRUGO, NULL);
|
||||
|
||||
if (!res)
|
||||
return -ENOMEM;
|
||||
|
||||
res->read_proc = proc_read_status;
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
printk(KERN_NOTICE "Registering SWP/SWPB emulation handler\n");
|
||||
register_undef_hook(&swp_hook);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
late_initcall(swp_emulation_init);
|
@ -30,12 +30,13 @@
|
||||
#include <asm/leds.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/stacktrace.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
/*
|
||||
* Our system timer.
|
||||
*/
|
||||
struct sys_timer *system_timer;
|
||||
static struct sys_timer *system_timer;
|
||||
|
||||
#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
|
||||
/* this needs a better home */
|
||||
@ -160,6 +161,7 @@ device_initcall(timer_init_sysfs);
|
||||
|
||||
void __init time_init(void)
|
||||
{
|
||||
system_timer = machine_desc->timer;
|
||||
system_timer->init();
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,8 @@
|
||||
|
||||
static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
|
||||
|
||||
void *vectors_page;
|
||||
|
||||
#ifdef CONFIG_DEBUG_USER
|
||||
unsigned int user_debug;
|
||||
|
||||
@ -756,7 +758,11 @@ static void __init kuser_get_tls_init(unsigned long vectors)
|
||||
|
||||
void __init early_trap_init(void)
|
||||
{
|
||||
#if defined(CONFIG_CPU_USE_DOMAINS)
|
||||
unsigned long vectors = CONFIG_VECTORS_BASE;
|
||||
#else
|
||||
unsigned long vectors = (unsigned long)vectors_page;
|
||||
#endif
|
||||
extern char __stubs_start[], __stubs_end[];
|
||||
extern char __vectors_start[], __vectors_end[];
|
||||
extern char __kuser_helper_start[], __kuser_helper_end[];
|
||||
@ -780,10 +786,10 @@ void __init early_trap_init(void)
|
||||
* Copy signal return handlers into the vector page, and
|
||||
* set sigreturn to be a pointer to these.
|
||||
*/
|
||||
memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
|
||||
sizeof(sigreturn_codes));
|
||||
memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
|
||||
sizeof(syscall_restart_code));
|
||||
memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
|
||||
sigreturn_codes, sizeof(sigreturn_codes));
|
||||
memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
|
||||
syscall_restart_code, sizeof(syscall_restart_code));
|
||||
|
||||
flush_icache_range(vectors, vectors + PAGE_SIZE);
|
||||
modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
|
||||
|
@ -168,6 +168,7 @@ SECTIONS
|
||||
|
||||
NOSAVE_DATA
|
||||
CACHELINE_ALIGNED_DATA(32)
|
||||
READ_MOSTLY_DATA(32)
|
||||
|
||||
/*
|
||||
* The exception fixup table (might need resorting at runtime)
|
||||
|
@ -28,20 +28,21 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/domain.h>
|
||||
|
||||
ENTRY(__get_user_1)
|
||||
1: ldrbt r2, [r0]
|
||||
1: T(ldrb) r2, [r0]
|
||||
mov r0, #0
|
||||
mov pc, lr
|
||||
ENDPROC(__get_user_1)
|
||||
|
||||
ENTRY(__get_user_2)
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
2: ldrbt r2, [r0]
|
||||
3: ldrbt r3, [r0, #1]
|
||||
2: T(ldrb) r2, [r0]
|
||||
3: T(ldrb) r3, [r0, #1]
|
||||
#else
|
||||
2: ldrbt r2, [r0], #1
|
||||
3: ldrbt r3, [r0]
|
||||
2: T(ldrb) r2, [r0], #1
|
||||
3: T(ldrb) r3, [r0]
|
||||
#endif
|
||||
#ifndef __ARMEB__
|
||||
orr r2, r2, r3, lsl #8
|
||||
@ -53,7 +54,7 @@ ENTRY(__get_user_2)
|
||||
ENDPROC(__get_user_2)
|
||||
|
||||
ENTRY(__get_user_4)
|
||||
4: ldrt r2, [r0]
|
||||
4: T(ldr) r2, [r0]
|
||||
mov r0, #0
|
||||
mov pc, lr
|
||||
ENDPROC(__get_user_4)
|
||||
|
@ -28,9 +28,10 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/domain.h>
|
||||
|
||||
ENTRY(__put_user_1)
|
||||
1: strbt r2, [r0]
|
||||
1: T(strb) r2, [r0]
|
||||
mov r0, #0
|
||||
mov pc, lr
|
||||
ENDPROC(__put_user_1)
|
||||
@ -39,19 +40,19 @@ ENTRY(__put_user_2)
|
||||
mov ip, r2, lsr #8
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
#ifndef __ARMEB__
|
||||
2: strbt r2, [r0]
|
||||
3: strbt ip, [r0, #1]
|
||||
2: T(strb) r2, [r0]
|
||||
3: T(strb) ip, [r0, #1]
|
||||
#else
|
||||
2: strbt ip, [r0]
|
||||
3: strbt r2, [r0, #1]
|
||||
2: T(strb) ip, [r0]
|
||||
3: T(strb) r2, [r0, #1]
|
||||
#endif
|
||||
#else /* !CONFIG_THUMB2_KERNEL */
|
||||
#ifndef __ARMEB__
|
||||
2: strbt r2, [r0], #1
|
||||
3: strbt ip, [r0]
|
||||
2: T(strb) r2, [r0], #1
|
||||
3: T(strb) ip, [r0]
|
||||
#else
|
||||
2: strbt ip, [r0], #1
|
||||
3: strbt r2, [r0]
|
||||
2: T(strb) ip, [r0], #1
|
||||
3: T(strb) r2, [r0]
|
||||
#endif
|
||||
#endif /* CONFIG_THUMB2_KERNEL */
|
||||
mov r0, #0
|
||||
@ -59,18 +60,18 @@ ENTRY(__put_user_2)
|
||||
ENDPROC(__put_user_2)
|
||||
|
||||
ENTRY(__put_user_4)
|
||||
4: strt r2, [r0]
|
||||
4: T(str) r2, [r0]
|
||||
mov r0, #0
|
||||
mov pc, lr
|
||||
ENDPROC(__put_user_4)
|
||||
|
||||
ENTRY(__put_user_8)
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
5: strt r2, [r0]
|
||||
6: strt r3, [r0, #4]
|
||||
5: T(str) r2, [r0]
|
||||
6: T(str) r3, [r0, #4]
|
||||
#else
|
||||
5: strt r2, [r0], #4
|
||||
6: strt r3, [r0]
|
||||
5: T(str) r2, [r0], #4
|
||||
6: T(str) r3, [r0]
|
||||
#endif
|
||||
mov r0, #0
|
||||
mov pc, lr
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/domain.h>
|
||||
|
||||
.text
|
||||
|
||||
@ -31,11 +32,11 @@
|
||||
rsb ip, ip, #4
|
||||
cmp ip, #2
|
||||
ldrb r3, [r1], #1
|
||||
USER( strbt r3, [r0], #1) @ May fault
|
||||
USER( T(strb) r3, [r0], #1) @ May fault
|
||||
ldrgeb r3, [r1], #1
|
||||
USER( strgebt r3, [r0], #1) @ May fault
|
||||
USER( T(strgeb) r3, [r0], #1) @ May fault
|
||||
ldrgtb r3, [r1], #1
|
||||
USER( strgtbt r3, [r0], #1) @ May fault
|
||||
USER( T(strgtb) r3, [r0], #1) @ May fault
|
||||
sub r2, r2, ip
|
||||
b .Lc2u_dest_aligned
|
||||
|
||||
@ -58,7 +59,7 @@ ENTRY(__copy_to_user)
|
||||
addmi ip, r2, #4
|
||||
bmi .Lc2u_0nowords
|
||||
ldr r3, [r1], #4
|
||||
USER( strt r3, [r0], #4) @ May fault
|
||||
USER( T(str) r3, [r0], #4) @ May fault
|
||||
mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
|
||||
rsb ip, ip, #0
|
||||
movs ip, ip, lsr #32 - PAGE_SHIFT
|
||||
@ -87,18 +88,18 @@ USER( strt r3, [r0], #4) @ May fault
|
||||
stmneia r0!, {r3 - r4} @ Shouldnt fault
|
||||
tst ip, #4
|
||||
ldrne r3, [r1], #4
|
||||
strnet r3, [r0], #4 @ Shouldnt fault
|
||||
T(strne) r3, [r0], #4 @ Shouldnt fault
|
||||
ands ip, ip, #3
|
||||
beq .Lc2u_0fupi
|
||||
.Lc2u_0nowords: teq ip, #0
|
||||
beq .Lc2u_finished
|
||||
.Lc2u_nowords: cmp ip, #2
|
||||
ldrb r3, [r1], #1
|
||||
USER( strbt r3, [r0], #1) @ May fault
|
||||
USER( T(strb) r3, [r0], #1) @ May fault
|
||||
ldrgeb r3, [r1], #1
|
||||
USER( strgebt r3, [r0], #1) @ May fault
|
||||
USER( T(strgeb) r3, [r0], #1) @ May fault
|
||||
ldrgtb r3, [r1], #1
|
||||
USER( strgtbt r3, [r0], #1) @ May fault
|
||||
USER( T(strgtb) r3, [r0], #1) @ May fault
|
||||
b .Lc2u_finished
|
||||
|
||||
.Lc2u_not_enough:
|
||||
@ -119,7 +120,7 @@ USER( strgtbt r3, [r0], #1) @ May fault
|
||||
mov r3, r7, pull #8
|
||||
ldr r7, [r1], #4
|
||||
orr r3, r3, r7, push #24
|
||||
USER( strt r3, [r0], #4) @ May fault
|
||||
USER( T(str) r3, [r0], #4) @ May fault
|
||||
mov ip, r0, lsl #32 - PAGE_SHIFT
|
||||
rsb ip, ip, #0
|
||||
movs ip, ip, lsr #32 - PAGE_SHIFT
|
||||
@ -154,18 +155,18 @@ USER( strt r3, [r0], #4) @ May fault
|
||||
movne r3, r7, pull #8
|
||||
ldrne r7, [r1], #4
|
||||
orrne r3, r3, r7, push #24
|
||||
strnet r3, [r0], #4 @ Shouldnt fault
|
||||
T(strne) r3, [r0], #4 @ Shouldnt fault
|
||||
ands ip, ip, #3
|
||||
beq .Lc2u_1fupi
|
||||
.Lc2u_1nowords: mov r3, r7, get_byte_1
|
||||
teq ip, #0
|
||||
beq .Lc2u_finished
|
||||
cmp ip, #2
|
||||
USER( strbt r3, [r0], #1) @ May fault
|
||||
USER( T(strb) r3, [r0], #1) @ May fault
|
||||
movge r3, r7, get_byte_2
|
||||
USER( strgebt r3, [r0], #1) @ May fault
|
||||
USER( T(strgeb) r3, [r0], #1) @ May fault
|
||||
movgt r3, r7, get_byte_3
|
||||
USER( strgtbt r3, [r0], #1) @ May fault
|
||||
USER( T(strgtb) r3, [r0], #1) @ May fault
|
||||
b .Lc2u_finished
|
||||
|
||||
.Lc2u_2fupi: subs r2, r2, #4
|
||||
@ -174,7 +175,7 @@ USER( strgtbt r3, [r0], #1) @ May fault
|
||||
mov r3, r7, pull #16
|
||||
ldr r7, [r1], #4
|
||||
orr r3, r3, r7, push #16
|
||||
USER( strt r3, [r0], #4) @ May fault
|
||||
USER( T(str) r3, [r0], #4) @ May fault
|
||||
mov ip, r0, lsl #32 - PAGE_SHIFT
|
||||
rsb ip, ip, #0
|
||||
movs ip, ip, lsr #32 - PAGE_SHIFT
|
||||
@ -209,18 +210,18 @@ USER( strt r3, [r0], #4) @ May fault
|
||||
movne r3, r7, pull #16
|
||||
ldrne r7, [r1], #4
|
||||
orrne r3, r3, r7, push #16
|
||||
strnet r3, [r0], #4 @ Shouldnt fault
|
||||
T(strne) r3, [r0], #4 @ Shouldnt fault
|
||||
ands ip, ip, #3
|
||||
beq .Lc2u_2fupi
|
||||
.Lc2u_2nowords: mov r3, r7, get_byte_2
|
||||
teq ip, #0
|
||||
beq .Lc2u_finished
|
||||
cmp ip, #2
|
||||
USER( strbt r3, [r0], #1) @ May fault
|
||||
USER( T(strb) r3, [r0], #1) @ May fault
|
||||
movge r3, r7, get_byte_3
|
||||
USER( strgebt r3, [r0], #1) @ May fault
|
||||
USER( T(strgeb) r3, [r0], #1) @ May fault
|
||||
ldrgtb r3, [r1], #0
|
||||
USER( strgtbt r3, [r0], #1) @ May fault
|
||||
USER( T(strgtb) r3, [r0], #1) @ May fault
|
||||
b .Lc2u_finished
|
||||
|
||||
.Lc2u_3fupi: subs r2, r2, #4
|
||||
@ -229,7 +230,7 @@ USER( strgtbt r3, [r0], #1) @ May fault
|
||||
mov r3, r7, pull #24
|
||||
ldr r7, [r1], #4
|
||||
orr r3, r3, r7, push #8
|
||||
USER( strt r3, [r0], #4) @ May fault
|
||||
USER( T(str) r3, [r0], #4) @ May fault
|
||||
mov ip, r0, lsl #32 - PAGE_SHIFT
|
||||
rsb ip, ip, #0
|
||||
movs ip, ip, lsr #32 - PAGE_SHIFT
|
||||
@ -264,18 +265,18 @@ USER( strt r3, [r0], #4) @ May fault
|
||||
movne r3, r7, pull #24
|
||||
ldrne r7, [r1], #4
|
||||
orrne r3, r3, r7, push #8
|
||||
strnet r3, [r0], #4 @ Shouldnt fault
|
||||
T(strne) r3, [r0], #4 @ Shouldnt fault
|
||||
ands ip, ip, #3
|
||||
beq .Lc2u_3fupi
|
||||
.Lc2u_3nowords: mov r3, r7, get_byte_3
|
||||
teq ip, #0
|
||||
beq .Lc2u_finished
|
||||
cmp ip, #2
|
||||
USER( strbt r3, [r0], #1) @ May fault
|
||||
USER( T(strb) r3, [r0], #1) @ May fault
|
||||
ldrgeb r3, [r1], #1
|
||||
USER( strgebt r3, [r0], #1) @ May fault
|
||||
USER( T(strgeb) r3, [r0], #1) @ May fault
|
||||
ldrgtb r3, [r1], #0
|
||||
USER( strgtbt r3, [r0], #1) @ May fault
|
||||
USER( T(strgtb) r3, [r0], #1) @ May fault
|
||||
b .Lc2u_finished
|
||||
ENDPROC(__copy_to_user)
|
||||
|
||||
@ -294,11 +295,11 @@ ENDPROC(__copy_to_user)
|
||||
.Lcfu_dest_not_aligned:
|
||||
rsb ip, ip, #4
|
||||
cmp ip, #2
|
||||
USER( ldrbt r3, [r1], #1) @ May fault
|
||||
USER( T(ldrb) r3, [r1], #1) @ May fault
|
||||
strb r3, [r0], #1
|
||||
USER( ldrgebt r3, [r1], #1) @ May fault
|
||||
USER( T(ldrgeb) r3, [r1], #1) @ May fault
|
||||
strgeb r3, [r0], #1
|
||||
USER( ldrgtbt r3, [r1], #1) @ May fault
|
||||
USER( T(ldrgtb) r3, [r1], #1) @ May fault
|
||||
strgtb r3, [r0], #1
|
||||
sub r2, r2, ip
|
||||
b .Lcfu_dest_aligned
|
||||
@ -321,7 +322,7 @@ ENTRY(__copy_from_user)
|
||||
.Lcfu_0fupi: subs r2, r2, #4
|
||||
addmi ip, r2, #4
|
||||
bmi .Lcfu_0nowords
|
||||
USER( ldrt r3, [r1], #4)
|
||||
USER( T(ldr) r3, [r1], #4)
|
||||
str r3, [r0], #4
|
||||
mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
|
||||
rsb ip, ip, #0
|
||||
@ -350,18 +351,18 @@ USER( ldrt r3, [r1], #4)
|
||||
ldmneia r1!, {r3 - r4} @ Shouldnt fault
|
||||
stmneia r0!, {r3 - r4}
|
||||
tst ip, #4
|
||||
ldrnet r3, [r1], #4 @ Shouldnt fault
|
||||
T(ldrne) r3, [r1], #4 @ Shouldnt fault
|
||||
strne r3, [r0], #4
|
||||
ands ip, ip, #3
|
||||
beq .Lcfu_0fupi
|
||||
.Lcfu_0nowords: teq ip, #0
|
||||
beq .Lcfu_finished
|
||||
.Lcfu_nowords: cmp ip, #2
|
||||
USER( ldrbt r3, [r1], #1) @ May fault
|
||||
USER( T(ldrb) r3, [r1], #1) @ May fault
|
||||
strb r3, [r0], #1
|
||||
USER( ldrgebt r3, [r1], #1) @ May fault
|
||||
USER( T(ldrgeb) r3, [r1], #1) @ May fault
|
||||
strgeb r3, [r0], #1
|
||||
USER( ldrgtbt r3, [r1], #1) @ May fault
|
||||
USER( T(ldrgtb) r3, [r1], #1) @ May fault
|
||||
strgtb r3, [r0], #1
|
||||
b .Lcfu_finished
|
||||
|
||||
@ -374,7 +375,7 @@ USER( ldrgtbt r3, [r1], #1) @ May fault
|
||||
|
||||
.Lcfu_src_not_aligned:
|
||||
bic r1, r1, #3
|
||||
USER( ldrt r7, [r1], #4) @ May fault
|
||||
USER( T(ldr) r7, [r1], #4) @ May fault
|
||||
cmp ip, #2
|
||||
bgt .Lcfu_3fupi
|
||||
beq .Lcfu_2fupi
|
||||
@ -382,7 +383,7 @@ USER( ldrt r7, [r1], #4) @ May fault
|
||||
addmi ip, r2, #4
|
||||
bmi .Lcfu_1nowords
|
||||
mov r3, r7, pull #8
|
||||
USER( ldrt r7, [r1], #4) @ May fault
|
||||
USER( T(ldr) r7, [r1], #4) @ May fault
|
||||
orr r3, r3, r7, push #24
|
||||
str r3, [r0], #4
|
||||
mov ip, r1, lsl #32 - PAGE_SHIFT
|
||||
@ -417,7 +418,7 @@ USER( ldrt r7, [r1], #4) @ May fault
|
||||
stmneia r0!, {r3 - r4}
|
||||
tst ip, #4
|
||||
movne r3, r7, pull #8
|
||||
USER( ldrnet r7, [r1], #4) @ May fault
|
||||
USER( T(ldrne) r7, [r1], #4) @ May fault
|
||||
orrne r3, r3, r7, push #24
|
||||
strne r3, [r0], #4
|
||||
ands ip, ip, #3
|
||||
@ -437,7 +438,7 @@ USER( ldrnet r7, [r1], #4) @ May fault
|
||||
addmi ip, r2, #4
|
||||
bmi .Lcfu_2nowords
|
||||
mov r3, r7, pull #16
|
||||
USER( ldrt r7, [r1], #4) @ May fault
|
||||
USER( T(ldr) r7, [r1], #4) @ May fault
|
||||
orr r3, r3, r7, push #16
|
||||
str r3, [r0], #4
|
||||
mov ip, r1, lsl #32 - PAGE_SHIFT
|
||||
@ -473,7 +474,7 @@ USER( ldrt r7, [r1], #4) @ May fault
|
||||
stmneia r0!, {r3 - r4}
|
||||
tst ip, #4
|
||||
movne r3, r7, pull #16
|
||||
USER( ldrnet r7, [r1], #4) @ May fault
|
||||
USER( T(ldrne) r7, [r1], #4) @ May fault
|
||||
orrne r3, r3, r7, push #16
|
||||
strne r3, [r0], #4
|
||||
ands ip, ip, #3
|
||||
@ -485,7 +486,7 @@ USER( ldrnet r7, [r1], #4) @ May fault
|
||||
strb r3, [r0], #1
|
||||
movge r3, r7, get_byte_3
|
||||
strgeb r3, [r0], #1
|
||||
USER( ldrgtbt r3, [r1], #0) @ May fault
|
||||
USER( T(ldrgtb) r3, [r1], #0) @ May fault
|
||||
strgtb r3, [r0], #1
|
||||
b .Lcfu_finished
|
||||
|
||||
@ -493,7 +494,7 @@ USER( ldrgtbt r3, [r1], #0) @ May fault
|
||||
addmi ip, r2, #4
|
||||
bmi .Lcfu_3nowords
|
||||
mov r3, r7, pull #24
|
||||
USER( ldrt r7, [r1], #4) @ May fault
|
||||
USER( T(ldr) r7, [r1], #4) @ May fault
|
||||
orr r3, r3, r7, push #8
|
||||
str r3, [r0], #4
|
||||
mov ip, r1, lsl #32 - PAGE_SHIFT
|
||||
@ -528,7 +529,7 @@ USER( ldrt r7, [r1], #4) @ May fault
|
||||
stmneia r0!, {r3 - r4}
|
||||
tst ip, #4
|
||||
movne r3, r7, pull #24
|
||||
USER( ldrnet r7, [r1], #4) @ May fault
|
||||
USER( T(ldrne) r7, [r1], #4) @ May fault
|
||||
orrne r3, r3, r7, push #8
|
||||
strne r3, [r0], #4
|
||||
ands ip, ip, #3
|
||||
@ -538,9 +539,9 @@ USER( ldrnet r7, [r1], #4) @ May fault
|
||||
beq .Lcfu_finished
|
||||
cmp ip, #2
|
||||
strb r3, [r0], #1
|
||||
USER( ldrgebt r3, [r1], #1) @ May fault
|
||||
USER( T(ldrgeb) r3, [r1], #1) @ May fault
|
||||
strgeb r3, [r0], #1
|
||||
USER( ldrgtbt r3, [r1], #1) @ May fault
|
||||
USER( T(ldrgtb) r3, [r1], #1) @ May fault
|
||||
strgtb r3, [r0], #1
|
||||
b .Lcfu_finished
|
||||
ENDPROC(__copy_from_user)
|
||||
|
@ -21,13 +21,12 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <mach/csp/hw_cfg.h>
|
||||
#include <mach/csp/chipcHw_def.h>
|
||||
#include <mach/csp/chipcHw_reg.h>
|
||||
#include <mach/csp/chipcHw_inline.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
|
||||
#include "clock.h"
|
||||
|
||||
#define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY)
|
||||
|
@ -30,10 +30,10 @@
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <mach/csp/mm_addr.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/hardware/arm_timer.h>
|
||||
|
@ -3,6 +3,7 @@ menu "CNS3XXX platform type"
|
||||
|
||||
config MACH_CNS3420VB
|
||||
bool "Support for CNS3420 Validation Board"
|
||||
select MIGHT_HAVE_PCI
|
||||
help
|
||||
Include support for the Cavium Networks CNS3420 MPCore Platform
|
||||
Baseboard.
|
||||
|
@ -68,7 +68,7 @@
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#define PLLSTAT_GOSTAT BIT(0)
|
||||
#define PLLCMD_GOSET BIT(0)
|
||||
|
@ -19,10 +19,10 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
|
||||
|
@ -22,8 +22,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <mach/clock.h>
|
||||
#include <mach/hardware.h>
|
||||
|
@ -21,11 +21,11 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <mach/clock.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/common.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#define IO_ADDR_CCM(off) (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off)))
|
||||
|
@ -21,8 +21,8 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include <mach/clock.h>
|
||||
|
@ -4,6 +4,7 @@ menu "Integrator Options"
|
||||
|
||||
config ARCH_INTEGRATOR_AP
|
||||
bool "Support Integrator/AP and Integrator/PP2 platforms"
|
||||
select MIGHT_HAVE_PCI
|
||||
help
|
||||
Include support for the ARM(R) Integrator/AP and
|
||||
Integrator/PP2 platforms.
|
||||
|
@ -21,9 +21,8 @@
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/serial.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <mach/clkdev.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/platform.h>
|
||||
#include <asm/irq.h>
|
||||
|
@ -22,9 +22,8 @@
|
||||
#include <linux/amba/clcd.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <mach/clkdev.h>
|
||||
#include <asm/hardware/icst.h>
|
||||
#include <mach/lm.h>
|
||||
#include <mach/impd1.h>
|
||||
|
@ -21,9 +21,8 @@
|
||||
#include <linux/amba/mmci.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <mach/clkdev.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/platform.h>
|
||||
#include <asm/irq.h>
|
||||
|
@ -58,13 +58,13 @@ static inline unsigned long __lbus_to_virt(dma_addr_t x)
|
||||
__dma; \
|
||||
})
|
||||
|
||||
#define __arch_page_to_dma(dev, page) \
|
||||
#define __arch_pfn_to_dma(dev, pfn) \
|
||||
({ \
|
||||
/* __is_lbus_virt() can never be true for RAM pages */ \
|
||||
(dma_addr_t)page_to_phys(page); \
|
||||
(dma_addr_t)__pfn_to_phys(pfn); \
|
||||
})
|
||||
|
||||
#define __arch_dma_to_page(dev, addr) phys_to_page(addr)
|
||||
#define __arch_dma_to_pfn(dev, addr) __phys_to_pfn(addr)
|
||||
|
||||
#endif /* CONFIG_ARCH_IOP13XX */
|
||||
#endif /* !ASSEMBLY */
|
||||
|
@ -4,6 +4,7 @@ menu "Kendin/Micrel KS8695 Implementations"
|
||||
|
||||
config MACH_KS8695
|
||||
bool "KS8695 development board"
|
||||
select MIGHT_HAVE_PCI
|
||||
help
|
||||
Say 'Y' here if you want your kernel to run on the original
|
||||
Kendin-Micrel KS8695 development board.
|
||||
|
@ -35,17 +35,17 @@ extern struct bus_type platform_bus_type;
|
||||
__phys_to_virt(x) : __bus_to_virt(x)); })
|
||||
#define __arch_virt_to_dma(dev, x) ({ is_lbus_device(dev) ? \
|
||||
(dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); })
|
||||
#define __arch_page_to_dma(dev, x) \
|
||||
({ dma_addr_t __dma = page_to_phys(page); \
|
||||
#define __arch_pfn_to_dma(dev, pfn) \
|
||||
({ dma_addr_t __dma = __pfn_to_phys(pfn); \
|
||||
if (!is_lbus_device(dev)) \
|
||||
__dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \
|
||||
__dma; })
|
||||
|
||||
#define __arch_dma_to_page(dev, x) \
|
||||
#define __arch_dma_to_pfn(dev, x) \
|
||||
({ dma_addr_t __dma = x; \
|
||||
if (!is_lbus_device(dev)) \
|
||||
__dma += PHYS_OFFSET - KS8695_PCIMEM_PA; \
|
||||
phys_to_page(__dma); \
|
||||
__phys_to_pfn(__dma); \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
@ -90,10 +90,9 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/clcd.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <mach/clkdev.h>
|
||||
#include <mach/platform.h>
|
||||
#include "clock.h"
|
||||
#include "common.h"
|
||||
|
@ -6,7 +6,7 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
struct clkops {
|
||||
void (*enable)(struct clk *);
|
||||
|
@ -31,9 +31,9 @@
|
||||
|
||||
#include <asm/hardware/gic.h>
|
||||
|
||||
static inline void smp_cross_call(const struct cpumask *mask)
|
||||
static inline void smp_cross_call(const struct cpumask *mask, int ipi)
|
||||
{
|
||||
gic_raise_softirq(mask, 1);
|
||||
gic_raise_softirq(mask, ipi);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -21,8 +21,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <mach/clock.h>
|
||||
#include <mach/hardware.h>
|
||||
|
@ -23,8 +23,8 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include <mach/clock.h>
|
||||
|
@ -21,8 +21,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <mach/clock.h>
|
||||
#include <mach/hardware.h>
|
||||
|
@ -14,8 +14,8 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
|
@ -2,12 +2,12 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <mach/clock.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/common.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/bug.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/clk.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include "clock.h"
|
||||
|
||||
/*
|
||||
|
@ -10,7 +10,7 @@
|
||||
* the Free Software Foundation; either version 2 of the License.
|
||||
*/
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
void nuc93x_clk_enable(struct clk *clk, int enable);
|
||||
void clks_register(struct clk_lookup *clks, size_t num);
|
||||
|
@ -17,9 +17,9 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/clkdev.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/usb.h>
|
||||
|
@ -26,10 +26,10 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/clock.h>
|
||||
#include <asm/clkdev.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "prm.h"
|
||||
|
@ -17,16 +17,13 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <mach/omap4-common.h>
|
||||
|
||||
static DECLARE_COMPLETION(cpu_killed);
|
||||
|
||||
int platform_cpu_kill(unsigned int cpu)
|
||||
{
|
||||
return wait_for_completion_timeout(&cpu_killed, 5000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -35,15 +32,6 @@ int platform_cpu_kill(unsigned int cpu)
|
||||
*/
|
||||
void platform_cpu_die(unsigned int cpu)
|
||||
{
|
||||
unsigned int this_cpu = hard_smp_processor_id();
|
||||
|
||||
if (cpu != this_cpu) {
|
||||
pr_crit("platform_cpu_die running on %u, should be %u\n",
|
||||
this_cpu, cpu);
|
||||
BUG();
|
||||
}
|
||||
pr_notice("CPU%u: shutdown\n", cpu);
|
||||
complete(&cpu_killed);
|
||||
flush_cache_all();
|
||||
dsb();
|
||||
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/omap4-common.h>
|
||||
@ -29,22 +28,10 @@
|
||||
/* SCU base address */
|
||||
static void __iomem *scu_base;
|
||||
|
||||
/*
|
||||
* Use SCU config register to count number of cores
|
||||
*/
|
||||
static inline unsigned int get_core_count(void)
|
||||
{
|
||||
if (scu_base)
|
||||
return scu_get_core_count(scu_base);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(boot_lock);
|
||||
|
||||
void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
{
|
||||
trace_hardirqs_off();
|
||||
|
||||
/*
|
||||
* If any interrupts are already enabled for the primary
|
||||
* core (e.g. timer irq), then they will not have been enabled
|
||||
@ -76,7 +63,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
omap_modify_auxcoreboot0(0x200, 0xfffffdff);
|
||||
flush_cache_all();
|
||||
smp_wmb();
|
||||
smp_cross_call(cpumask_of(cpu));
|
||||
smp_cross_call(cpumask_of(cpu), 1);
|
||||
|
||||
/*
|
||||
* Now the secondary core is starting up let it run its
|
||||
@ -118,25 +105,9 @@ void __init smp_init_cpus(void)
|
||||
scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256);
|
||||
BUG_ON(!scu_base);
|
||||
|
||||
ncores = get_core_count();
|
||||
|
||||
for (i = 0; i < ncores; i++)
|
||||
set_cpu_possible(i, true);
|
||||
}
|
||||
|
||||
void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
unsigned int ncores = get_core_count();
|
||||
unsigned int cpu = smp_processor_id();
|
||||
int i;
|
||||
ncores = scu_get_core_count(scu_base);
|
||||
|
||||
/* sanity check */
|
||||
if (ncores == 0) {
|
||||
printk(KERN_ERR
|
||||
"OMAP4: strange core count of 0? Default to 1\n");
|
||||
ncores = 1;
|
||||
}
|
||||
|
||||
if (ncores > NR_CPUS) {
|
||||
printk(KERN_WARNING
|
||||
"OMAP4: no. of cores (%d) greater than configured "
|
||||
@ -144,13 +115,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
ncores, NR_CPUS);
|
||||
ncores = NR_CPUS;
|
||||
}
|
||||
smp_store_cpu_info(cpu);
|
||||
|
||||
/*
|
||||
* are we trying to boot more cores than exist?
|
||||
*/
|
||||
if (max_cpus > ncores)
|
||||
max_cpus = ncores;
|
||||
for (i = 0; i < ncores; i++)
|
||||
set_cpu_possible(i, true);
|
||||
}
|
||||
|
||||
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Initialise the present map, which describes the set of CPUs
|
||||
@ -159,18 +131,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
for (i = 0; i < max_cpus; i++)
|
||||
set_cpu_present(i, true);
|
||||
|
||||
if (max_cpus > 1) {
|
||||
/*
|
||||
* Enable the local timer or broadcast device for the
|
||||
* boot CPU, but only if we have more than one CPU.
|
||||
*/
|
||||
percpu_timer_setup();
|
||||
|
||||
/*
|
||||
* Initialise the SCU and wake up the secondary core using
|
||||
* wakeup_secondary().
|
||||
*/
|
||||
scu_enable(scu_base);
|
||||
wakeup_secondary();
|
||||
}
|
||||
/*
|
||||
* Initialise the SCU and wake up the secondary core using
|
||||
* wakeup_secondary().
|
||||
*/
|
||||
scu_enable(scu_base);
|
||||
wakeup_secondary();
|
||||
}
|
||||
|
@ -21,8 +21,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/clock.h>
|
||||
|
@ -94,6 +94,7 @@ config MACH_ARMCORE
|
||||
select PXA27x
|
||||
select IWMMXT
|
||||
select PXA25x
|
||||
select MIGHT_HAVE_PCI
|
||||
|
||||
config MACH_EM_X270
|
||||
bool "CompuLab EM-x270 platform"
|
||||
|
@ -11,8 +11,8 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <mach/pxa2xx-regs.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
struct clkops {
|
||||
void (*enable)(struct clk *);
|
||||
|
@ -30,8 +30,8 @@
|
||||
#include <linux/ata_platform.h>
|
||||
#include <linux/amba/mmci.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/system.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
@ -47,7 +47,6 @@
|
||||
|
||||
#include <asm/hardware/gic.h>
|
||||
|
||||
#include <mach/clkdev.h>
|
||||
#include <mach/platform.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <asm/hardware/timer-sp.h>
|
||||
|
@ -11,14 +11,11 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
extern volatile int pen_release;
|
||||
|
||||
static DECLARE_COMPLETION(cpu_killed);
|
||||
|
||||
static inline void cpu_enter_lowpower(void)
|
||||
{
|
||||
unsigned int v;
|
||||
@ -34,10 +31,10 @@ static inline void cpu_enter_lowpower(void)
|
||||
" bic %0, %0, #0x20\n"
|
||||
" mcr p15, 0, %0, c1, c0, 1\n"
|
||||
" mrc p15, 0, %0, c1, c0, 0\n"
|
||||
" bic %0, %0, #0x04\n"
|
||||
" bic %0, %0, %2\n"
|
||||
" mcr p15, 0, %0, c1, c0, 0\n"
|
||||
: "=&r" (v)
|
||||
: "r" (0)
|
||||
: "r" (0), "Ir" (CR_C)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
@ -46,17 +43,17 @@ static inline void cpu_leave_lowpower(void)
|
||||
unsigned int v;
|
||||
|
||||
asm volatile( "mrc p15, 0, %0, c1, c0, 0\n"
|
||||
" orr %0, %0, #0x04\n"
|
||||
" orr %0, %0, %1\n"
|
||||
" mcr p15, 0, %0, c1, c0, 0\n"
|
||||
" mrc p15, 0, %0, c1, c0, 1\n"
|
||||
" orr %0, %0, #0x20\n"
|
||||
" mcr p15, 0, %0, c1, c0, 1\n"
|
||||
: "=&r" (v)
|
||||
:
|
||||
: "Ir" (CR_C)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
static inline void platform_do_lowpower(unsigned int cpu)
|
||||
static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
|
||||
{
|
||||
/*
|
||||
* there is no power-control hardware on this platform, so all
|
||||
@ -80,22 +77,19 @@ static inline void platform_do_lowpower(unsigned int cpu)
|
||||
}
|
||||
|
||||
/*
|
||||
* getting here, means that we have come out of WFI without
|
||||
* Getting here, means that we have come out of WFI without
|
||||
* having been woken up - this shouldn't happen
|
||||
*
|
||||
* The trouble is, letting people know about this is not really
|
||||
* possible, since we are currently running incoherently, and
|
||||
* therefore cannot safely call printk() or anything else
|
||||
* Just note it happening - when we're woken, we can report
|
||||
* its occurrence.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
printk("CPU%u: spurious wakeup call\n", cpu);
|
||||
#endif
|
||||
(*spurious)++;
|
||||
}
|
||||
}
|
||||
|
||||
int platform_cpu_kill(unsigned int cpu)
|
||||
{
|
||||
return wait_for_completion_timeout(&cpu_killed, 5000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -105,30 +99,22 @@ int platform_cpu_kill(unsigned int cpu)
|
||||
*/
|
||||
void platform_cpu_die(unsigned int cpu)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
unsigned int this_cpu = hard_smp_processor_id();
|
||||
|
||||
if (cpu != this_cpu) {
|
||||
printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
|
||||
this_cpu, cpu);
|
||||
BUG();
|
||||
}
|
||||
#endif
|
||||
|
||||
printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
|
||||
complete(&cpu_killed);
|
||||
int spurious = 0;
|
||||
|
||||
/*
|
||||
* we're ready for shutdown now, so do it
|
||||
*/
|
||||
cpu_enter_lowpower();
|
||||
platform_do_lowpower(cpu);
|
||||
platform_do_lowpower(cpu, &spurious);
|
||||
|
||||
/*
|
||||
* bring this CPU back into the world of cache
|
||||
* coherency, and then restore interrupts
|
||||
*/
|
||||
cpu_leave_lowpower();
|
||||
|
||||
if (spurious)
|
||||
pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
|
||||
}
|
||||
|
||||
int platform_cpu_disable(unsigned int cpu)
|
||||
|
@ -2,14 +2,13 @@
|
||||
#define ASMARM_ARCH_SMP_H
|
||||
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/smp_mpidr.h>
|
||||
|
||||
/*
|
||||
* We use IRQ1 as the IPI
|
||||
*/
|
||||
static inline void smp_cross_call(const struct cpumask *mask)
|
||||
static inline void smp_cross_call(const struct cpumask *mask, int ipi)
|
||||
{
|
||||
gic_raise_softirq(mask, 1);
|
||||
gic_raise_softirq(mask, ipi);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <asm/cacheflush.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/unified.h>
|
||||
|
||||
#include <mach/board-eb.h>
|
||||
@ -37,6 +36,19 @@ extern void realview_secondary_startup(void);
|
||||
*/
|
||||
volatile int __cpuinitdata pen_release = -1;
|
||||
|
||||
/*
|
||||
* Write pen_release in a way that is guaranteed to be visible to all
|
||||
* observers, irrespective of whether they're taking part in coherency
|
||||
* or not. This is necessary for the hotplug code to work reliably.
|
||||
*/
|
||||
static void write_pen_release(int val)
|
||||
{
|
||||
pen_release = val;
|
||||
smp_wmb();
|
||||
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
|
||||
outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
|
||||
}
|
||||
|
||||
static void __iomem *scu_base_addr(void)
|
||||
{
|
||||
if (machine_is_realview_eb_mp())
|
||||
@ -50,20 +62,10 @@ static void __iomem *scu_base_addr(void)
|
||||
return (void __iomem *)0;
|
||||
}
|
||||
|
||||
static inline unsigned int get_core_count(void)
|
||||
{
|
||||
void __iomem *scu_base = scu_base_addr();
|
||||
if (scu_base)
|
||||
return scu_get_core_count(scu_base);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(boot_lock);
|
||||
|
||||
void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
{
|
||||
trace_hardirqs_off();
|
||||
|
||||
/*
|
||||
* if any interrupts are already enabled for the primary
|
||||
* core (e.g. timer irq), then they will not have been enabled
|
||||
@ -75,8 +77,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
* let the primary processor know we're out of the
|
||||
* pen, then head off into the C entry point
|
||||
*/
|
||||
pen_release = -1;
|
||||
smp_wmb();
|
||||
write_pen_release(-1);
|
||||
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
@ -103,20 +104,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
* Note that "pen_release" is the hardware CPU ID, whereas
|
||||
* "cpu" is Linux's internal ID.
|
||||
*/
|
||||
pen_release = cpu;
|
||||
flush_cache_all();
|
||||
write_pen_release(cpu);
|
||||
|
||||
/*
|
||||
* XXX
|
||||
*
|
||||
* This is a later addition to the booting protocol: the
|
||||
* bootMonitor now puts secondary cores into WFI, so
|
||||
* poke_milo() no longer gets the cores moving; we need
|
||||
* to send a soft interrupt to wake the secondary core.
|
||||
* Use smp_cross_call() for this, since there's little
|
||||
* point duplicating the code here
|
||||
* Send the secondary CPU a soft interrupt, thereby causing
|
||||
* the boot monitor to read the system wide flags register,
|
||||
* and branch to the address found there.
|
||||
*/
|
||||
smp_cross_call(cpumask_of(cpu));
|
||||
smp_cross_call(cpumask_of(cpu), 1);
|
||||
|
||||
timeout = jiffies + (1 * HZ);
|
||||
while (time_before(jiffies, timeout)) {
|
||||
@ -136,48 +131,18 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
return pen_release != -1 ? -ENOSYS : 0;
|
||||
}
|
||||
|
||||
static void __init poke_milo(void)
|
||||
{
|
||||
/* nobody is to be released from the pen yet */
|
||||
pen_release = -1;
|
||||
|
||||
/*
|
||||
* Write the address of secondary startup into the system-wide flags
|
||||
* register. The BootMonitor waits for this register to become
|
||||
* non-zero.
|
||||
*/
|
||||
__raw_writel(BSYM(virt_to_phys(realview_secondary_startup)),
|
||||
__io_address(REALVIEW_SYS_FLAGSSET));
|
||||
|
||||
mb();
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the CPU possible map early - this describes the CPUs
|
||||
* which may be present or become present in the system.
|
||||
*/
|
||||
void __init smp_init_cpus(void)
|
||||
{
|
||||
unsigned int i, ncores = get_core_count();
|
||||
void __iomem *scu_base = scu_base_addr();
|
||||
unsigned int i, ncores;
|
||||
|
||||
for (i = 0; i < ncores; i++)
|
||||
set_cpu_possible(i, true);
|
||||
}
|
||||
|
||||
void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
unsigned int ncores = get_core_count();
|
||||
unsigned int cpu = smp_processor_id();
|
||||
int i;
|
||||
ncores = scu_base ? scu_get_core_count(scu_base) : 1;
|
||||
|
||||
/* sanity check */
|
||||
if (ncores == 0) {
|
||||
printk(KERN_ERR
|
||||
"Realview: strange CM count of 0? Default to 1\n");
|
||||
|
||||
ncores = 1;
|
||||
}
|
||||
|
||||
if (ncores > NR_CPUS) {
|
||||
printk(KERN_WARNING
|
||||
"Realview: no. of cores (%d) greater than configured "
|
||||
@ -186,13 +151,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
ncores = NR_CPUS;
|
||||
}
|
||||
|
||||
smp_store_cpu_info(cpu);
|
||||
for (i = 0; i < ncores; i++)
|
||||
set_cpu_possible(i, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* are we trying to boot more cores than exist?
|
||||
*/
|
||||
if (max_cpus > ncores)
|
||||
max_cpus = ncores;
|
||||
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Initialise the present map, which describes the set of CPUs
|
||||
@ -201,21 +166,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
for (i = 0; i < max_cpus; i++)
|
||||
set_cpu_present(i, true);
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
/*
|
||||
* 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());
|
||||
poke_milo();
|
||||
}
|
||||
/*
|
||||
* Write the address of secondary startup into the
|
||||
* system-wide flags register. The BootMonitor waits
|
||||
* until it receives a soft interrupt, and then the
|
||||
* secondary CPU branches to this address.
|
||||
*/
|
||||
__raw_writel(BSYM(virt_to_phys(realview_secondary_startup)),
|
||||
__io_address(REALVIEW_SYS_FLAGSSET));
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ config MACH_JIVE
|
||||
Say Y here if you are using the Logitech Jive.
|
||||
|
||||
config MACH_JIVE_SHOW_BOOTLOADER
|
||||
bool "Allow access to bootloader partitions in MTD"
|
||||
bool "Allow access to bootloader partitions in MTD (EXPERIMENTAL)"
|
||||
depends on MACH_JIVE && EXPERIMENTAL
|
||||
|
||||
config MACH_SMDK2413
|
||||
|
@ -13,14 +13,11 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
extern volatile int pen_release;
|
||||
|
||||
static DECLARE_COMPLETION(cpu_killed);
|
||||
|
||||
static inline void cpu_enter_lowpower(void)
|
||||
{
|
||||
unsigned int v;
|
||||
@ -33,13 +30,13 @@ static inline void cpu_enter_lowpower(void)
|
||||
* Turn off coherency
|
||||
*/
|
||||
" mrc p15, 0, %0, c1, c0, 1\n"
|
||||
" bic %0, %0, #0x20\n"
|
||||
" bic %0, %0, %2\n"
|
||||
" mcr p15, 0, %0, c1, c0, 1\n"
|
||||
" mrc p15, 0, %0, c1, c0, 0\n"
|
||||
" bic %0, %0, #0x04\n"
|
||||
" mcr p15, 0, %0, c1, c0, 0\n"
|
||||
: "=&r" (v)
|
||||
: "r" (0)
|
||||
: "r" (0), "Ir" (CR_C)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
@ -49,17 +46,17 @@ static inline void cpu_leave_lowpower(void)
|
||||
|
||||
asm volatile(
|
||||
"mrc p15, 0, %0, c1, c0, 0\n"
|
||||
" orr %0, %0, #0x04\n"
|
||||
" orr %0, %0, %1\n"
|
||||
" mcr p15, 0, %0, c1, c0, 0\n"
|
||||
" mrc p15, 0, %0, c1, c0, 1\n"
|
||||
" orr %0, %0, #0x20\n"
|
||||
" mcr p15, 0, %0, c1, c0, 1\n"
|
||||
: "=&r" (v)
|
||||
:
|
||||
: "Ir" (CR_C)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
static inline void platform_do_lowpower(unsigned int cpu)
|
||||
static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
|
||||
{
|
||||
/*
|
||||
* there is no power-control hardware on this platform, so all
|
||||
@ -83,22 +80,19 @@ static inline void platform_do_lowpower(unsigned int cpu)
|
||||
}
|
||||
|
||||
/*
|
||||
* getting here, means that we have come out of WFI without
|
||||
* Getting here, means that we have come out of WFI without
|
||||
* having been woken up - this shouldn't happen
|
||||
*
|
||||
* The trouble is, letting people know about this is not really
|
||||
* possible, since we are currently running incoherently, and
|
||||
* therefore cannot safely call printk() or anything else
|
||||
* Just note it happening - when we're woken, we can report
|
||||
* its occurrence.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
|
||||
#endif
|
||||
(*spurious)++;
|
||||
}
|
||||
}
|
||||
|
||||
int platform_cpu_kill(unsigned int cpu)
|
||||
{
|
||||
return wait_for_completion_timeout(&cpu_killed, 5000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -108,30 +102,22 @@ int platform_cpu_kill(unsigned int cpu)
|
||||
*/
|
||||
void platform_cpu_die(unsigned int cpu)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
unsigned int this_cpu = hard_smp_processor_id();
|
||||
|
||||
if (cpu != this_cpu) {
|
||||
printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
|
||||
this_cpu, cpu);
|
||||
BUG();
|
||||
}
|
||||
#endif
|
||||
|
||||
printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
|
||||
complete(&cpu_killed);
|
||||
int spurious = 0;
|
||||
|
||||
/*
|
||||
* we're ready for shutdown now, so do it
|
||||
*/
|
||||
cpu_enter_lowpower();
|
||||
platform_do_lowpower(cpu);
|
||||
platform_do_lowpower(cpu, &spurious);
|
||||
|
||||
/*
|
||||
* bring this CPU back into the world of cache
|
||||
* coherency, and then restore interrupts
|
||||
*/
|
||||
cpu_leave_lowpower();
|
||||
|
||||
if (spurious)
|
||||
pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
|
||||
}
|
||||
|
||||
int platform_cpu_disable(unsigned int cpu)
|
||||
|
@ -7,14 +7,13 @@
|
||||
#define ASM_ARCH_SMP_H __FILE__
|
||||
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/smp_mpidr.h>
|
||||
|
||||
/*
|
||||
* We use IRQ1 as the IPI
|
||||
*/
|
||||
static inline void smp_cross_call(const struct cpumask *mask)
|
||||
static inline void smp_cross_call(const struct cpumask *mask, int ipi)
|
||||
{
|
||||
gic_raise_softirq(mask, 1);
|
||||
gic_raise_softirq(mask, ipi);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <asm/unified.h>
|
||||
|
||||
@ -38,6 +37,19 @@ extern void s5pv310_secondary_startup(void);
|
||||
|
||||
volatile int __cpuinitdata pen_release = -1;
|
||||
|
||||
/*
|
||||
* Write pen_release in a way that is guaranteed to be visible to all
|
||||
* observers, irrespective of whether they're taking part in coherency
|
||||
* or not. This is necessary for the hotplug code to work reliably.
|
||||
*/
|
||||
static void write_pen_release(int val)
|
||||
{
|
||||
pen_release = val;
|
||||
smp_wmb();
|
||||
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
|
||||
outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
|
||||
}
|
||||
|
||||
static void __iomem *scu_base_addr(void)
|
||||
{
|
||||
return (void __iomem *)(S5P_VA_SCU);
|
||||
@ -47,8 +59,6 @@ static DEFINE_SPINLOCK(boot_lock);
|
||||
|
||||
void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
{
|
||||
trace_hardirqs_off();
|
||||
|
||||
/*
|
||||
* if any interrupts are already enabled for the primary
|
||||
* core (e.g. timer irq), then they will not have been enabled
|
||||
@ -60,8 +70,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
* let the primary processor know we're out of the
|
||||
* pen, then head off into the C entry point
|
||||
*/
|
||||
pen_release = -1;
|
||||
smp_wmb();
|
||||
write_pen_release(-1);
|
||||
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
@ -88,16 +97,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
* Note that "pen_release" is the hardware CPU ID, whereas
|
||||
* "cpu" is Linux's internal ID.
|
||||
*/
|
||||
pen_release = cpu;
|
||||
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
|
||||
outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
|
||||
write_pen_release(cpu);
|
||||
|
||||
/*
|
||||
* Send the secondary CPU a soft interrupt, thereby causing
|
||||
* the boot monitor to read the system wide flags register,
|
||||
* and branch to the address found there.
|
||||
*/
|
||||
smp_cross_call(cpumask_of(cpu));
|
||||
smp_cross_call(cpumask_of(cpu), 1);
|
||||
|
||||
timeout = jiffies + (1 * HZ);
|
||||
while (time_before(jiffies, timeout)) {
|
||||
@ -130,13 +137,6 @@ void __init smp_init_cpus(void)
|
||||
ncores = scu_base ? scu_get_core_count(scu_base) : 1;
|
||||
|
||||
/* sanity check */
|
||||
if (ncores == 0) {
|
||||
printk(KERN_ERR
|
||||
"S5PV310: strange CM count of 0? Default to 1\n");
|
||||
|
||||
ncores = 1;
|
||||
}
|
||||
|
||||
if (ncores > NR_CPUS) {
|
||||
printk(KERN_WARNING
|
||||
"S5PV310: no. of cores (%d) greater than configured "
|
||||
@ -149,18 +149,10 @@ void __init smp_init_cpus(void)
|
||||
set_cpu_possible(i, true);
|
||||
}
|
||||
|
||||
void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
unsigned int ncores = num_possible_cpus();
|
||||
unsigned int cpu = smp_processor_id();
|
||||
int i;
|
||||
|
||||
smp_store_cpu_info(cpu);
|
||||
|
||||
/* are we trying to boot more cores than exist? */
|
||||
if (max_cpus > ncores)
|
||||
max_cpus = ncores;
|
||||
|
||||
/*
|
||||
* Initialise the present map, which describes the set of CPUs
|
||||
* actually populated at the present time.
|
||||
@ -168,25 +160,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
for (i = 0; i < max_cpus; i++)
|
||||
set_cpu_present(i, true);
|
||||
|
||||
scu_enable(scu_base_addr());
|
||||
|
||||
/*
|
||||
* Initialise the SCU if there are more than one CPU and let
|
||||
* them know where to start.
|
||||
* Write the address of secondary startup into the
|
||||
* system-wide flags register. The boot monitor waits
|
||||
* until it receives a soft interrupt, and then the
|
||||
* secondary CPU branches to this address.
|
||||
*/
|
||||
if (max_cpus > 1) {
|
||||
/*
|
||||
* Enable the local timer or broadcast device for the
|
||||
* boot CPU, but only if we have more than one CPU.
|
||||
*/
|
||||
percpu_timer_setup();
|
||||
|
||||
scu_enable(scu_base_addr());
|
||||
|
||||
/*
|
||||
* Write the address of secondary startup into the
|
||||
* system-wide flags register. The boot monitor waits
|
||||
* until it receives a soft interrupt, and then the
|
||||
* secondary CPU branches to this address.
|
||||
*/
|
||||
__raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_VA_SYSRAM);
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ config ARCH_SH7367
|
||||
bool "SH-Mobile G3 (SH7367)"
|
||||
select CPU_V6
|
||||
select HAVE_CLK
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select SH_CLK_CPG
|
||||
select GENERIC_CLOCKEVENTS
|
||||
|
||||
@ -14,7 +14,7 @@ config ARCH_SH7377
|
||||
bool "SH-Mobile G4 (SH7377)"
|
||||
select CPU_V7
|
||||
select HAVE_CLK
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select SH_CLK_CPG
|
||||
select GENERIC_CLOCKEVENTS
|
||||
|
||||
@ -22,7 +22,7 @@ config ARCH_SH7372
|
||||
bool "SH-Mobile AP4 (SH7372)"
|
||||
select CPU_V7
|
||||
select HAVE_CLK
|
||||
select COMMON_CLKDEV
|
||||
select CLKDEV_LOOKUP
|
||||
select SH_CLK_CPG
|
||||
select GENERIC_CLOCKEVENTS
|
||||
|
||||
|
@ -20,8 +20,8 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sh_clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <mach/common.h>
|
||||
#include <asm/clkdev.h>
|
||||
|
||||
/* SH7367 registers */
|
||||
#define RTFRQCR 0xe6150000
|
||||
|
@ -20,8 +20,8 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sh_clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <mach/common.h>
|
||||
#include <asm/clkdev.h>
|
||||
|
||||
/* SH7372 registers */
|
||||
#define FRQCRA 0xe6150000
|
||||
|
@ -20,8 +20,8 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sh_clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <mach/common.h>
|
||||
#include <asm/clkdev.h>
|
||||
|
||||
/* SH7377 registers */
|
||||
#define RTFRQCR 0xe6150000
|
||||
|
@ -12,8 +12,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <mach/clock.h>
|
||||
#include <mach/irqs.h>
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "board.h"
|
||||
|
@ -21,7 +21,7 @@
|
||||
#define __MACH_TEGRA_CLOCK_H
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#define DIV_BUS (1 << 0)
|
||||
#define DIV_U71 (1 << 1)
|
||||
|
@ -11,12 +11,9 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
static DECLARE_COMPLETION(cpu_killed);
|
||||
|
||||
static inline void cpu_enter_lowpower(void)
|
||||
{
|
||||
unsigned int v;
|
||||
@ -29,13 +26,13 @@ static inline void cpu_enter_lowpower(void)
|
||||
* Turn off coherency
|
||||
*/
|
||||
" mrc p15, 0, %0, c1, c0, 1\n"
|
||||
" bic %0, %0, #0x20\n"
|
||||
" bic %0, %0, %2\n"
|
||||
" mcr p15, 0, %0, c1, c0, 1\n"
|
||||
" mrc p15, 0, %0, c1, c0, 0\n"
|
||||
" bic %0, %0, #0x04\n"
|
||||
" mcr p15, 0, %0, c1, c0, 0\n"
|
||||
: "=&r" (v)
|
||||
: "r" (0)
|
||||
: "r" (0), "Ir" (CR_C)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
@ -45,17 +42,17 @@ static inline void cpu_leave_lowpower(void)
|
||||
|
||||
asm volatile(
|
||||
"mrc p15, 0, %0, c1, c0, 0\n"
|
||||
" orr %0, %0, #0x04\n"
|
||||
" orr %0, %0, %1\n"
|
||||
" mcr p15, 0, %0, c1, c0, 0\n"
|
||||
" mrc p15, 0, %0, c1, c0, 1\n"
|
||||
" orr %0, %0, #0x20\n"
|
||||
" mcr p15, 0, %0, c1, c0, 1\n"
|
||||
: "=&r" (v)
|
||||
:
|
||||
: "Ir" (CR_C)
|
||||
: "cc");
|
||||
}
|
||||
|
||||
static inline void platform_do_lowpower(unsigned int cpu)
|
||||
static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
|
||||
{
|
||||
/*
|
||||
* there is no power-control hardware on this platform, so all
|
||||
@ -79,22 +76,19 @@ static inline void platform_do_lowpower(unsigned int cpu)
|
||||
/*}*/
|
||||
|
||||
/*
|
||||
* getting here, means that we have come out of WFI without
|
||||
* Getting here, means that we have come out of WFI without
|
||||
* having been woken up - this shouldn't happen
|
||||
*
|
||||
* The trouble is, letting people know about this is not really
|
||||
* possible, since we are currently running incoherently, and
|
||||
* therefore cannot safely call printk() or anything else
|
||||
* Just note it happening - when we're woken, we can report
|
||||
* its occurrence.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
|
||||
#endif
|
||||
(*spurious)++;
|
||||
}
|
||||
}
|
||||
|
||||
int platform_cpu_kill(unsigned int cpu)
|
||||
{
|
||||
return wait_for_completion_timeout(&cpu_killed, 5000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -104,30 +98,22 @@ int platform_cpu_kill(unsigned int cpu)
|
||||
*/
|
||||
void platform_cpu_die(unsigned int cpu)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
unsigned int this_cpu = hard_smp_processor_id();
|
||||
|
||||
if (cpu != this_cpu) {
|
||||
printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
|
||||
this_cpu, cpu);
|
||||
BUG();
|
||||
}
|
||||
#endif
|
||||
|
||||
printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
|
||||
complete(&cpu_killed);
|
||||
int spurious = 0;
|
||||
|
||||
/*
|
||||
* we're ready for shutdown now, so do it
|
||||
*/
|
||||
cpu_enter_lowpower();
|
||||
platform_do_lowpower(cpu);
|
||||
platform_do_lowpower(cpu, &spurious);
|
||||
|
||||
/*
|
||||
* bring this CPU back into the world of cache
|
||||
* coherency, and then restore interrupts
|
||||
*/
|
||||
cpu_leave_lowpower();
|
||||
|
||||
if (spurious)
|
||||
pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
|
||||
}
|
||||
|
||||
int platform_cpu_disable(unsigned int cpu)
|
||||
|
@ -2,21 +2,13 @@
|
||||
#define ASMARM_ARCH_SMP_H
|
||||
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/smp_mpidr.h>
|
||||
|
||||
/*
|
||||
* We use IRQ1 as the IPI
|
||||
*/
|
||||
static inline void smp_cross_call(const struct cpumask *mask)
|
||||
{
|
||||
gic_raise_softirq(mask, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do nothing on MPcore.
|
||||
*/
|
||||
static inline void smp_cross_call_done(cpumask_t callmap)
|
||||
static inline void smp_cross_call(const struct cpumask *mask, int ipi)
|
||||
{
|
||||
gic_raise_softirq(mask, ipi);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include <asm/cacheflush.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/smp_scu.h>
|
||||
|
||||
#include <mach/iomap.h>
|
||||
@ -41,8 +40,6 @@ static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
|
||||
|
||||
void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
{
|
||||
trace_hardirqs_off();
|
||||
|
||||
/*
|
||||
* if any interrupts are already enabled for the primary
|
||||
* core (e.g. timer irq), then they will not have been enabled
|
||||
@ -117,24 +114,20 @@ void __init smp_init_cpus(void)
|
||||
{
|
||||
unsigned int i, ncores = scu_get_core_count(scu_base);
|
||||
|
||||
if (ncores > NR_CPUS) {
|
||||
printk(KERN_ERR "Tegra: no. of cores (%u) greater than configured (%u), clipping\n",
|
||||
ncores, NR_CPUS);
|
||||
ncores = NR_CPUS;
|
||||
}
|
||||
|
||||
for (i = 0; i < ncores; i++)
|
||||
cpu_set(i, cpu_possible_map);
|
||||
}
|
||||
|
||||
void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
unsigned int ncores = scu_get_core_count(scu_base);
|
||||
unsigned int cpu = smp_processor_id();
|
||||
int i;
|
||||
|
||||
smp_store_cpu_info(cpu);
|
||||
|
||||
/*
|
||||
* are we trying to boot more cores than exist?
|
||||
*/
|
||||
if (max_cpus > ncores)
|
||||
max_cpus = ncores;
|
||||
|
||||
/*
|
||||
* Initialise the present map, which describes the set of CPUs
|
||||
* actually populated at the present time.
|
||||
@ -142,15 +135,5 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
for (i = 0; i < max_cpus; i++)
|
||||
set_cpu_present(i, true);
|
||||
|
||||
/*
|
||||
* Initialise the SCU if there are more than one CPU and let
|
||||
* them know where to start. Note that, on modern versions of
|
||||
* MILO, the "poke" doesn't actually do anything until each
|
||||
* individual core is sent a soft interrupt to get it out of
|
||||
* WFI
|
||||
*/
|
||||
if (max_cpus > 1) {
|
||||
percpu_timer_setup();
|
||||
scu_enable(scu_base);
|
||||
}
|
||||
scu_enable(scu_base);
|
||||
}
|
||||
|
@ -24,8 +24,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/hrtimer.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <mach/iomap.h>
|
||||
|
||||
|
@ -25,8 +25,8 @@
|
||||
#include <linux/timer.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/syscon.h>
|
||||
|
||||
|
@ -13,8 +13,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <plat/mtu.h>
|
||||
#include <mach/hardware.h>
|
||||
|
@ -23,7 +23,6 @@ ENTRY(u8500_secondary_startup)
|
||||
ldmia r4, {r5, r6}
|
||||
sub r4, r4, r5
|
||||
add r6, r6, r4
|
||||
dsb
|
||||
pen: ldr r7, [r6]
|
||||
cmp r7, r0
|
||||
bne pen
|
||||
|
@ -11,14 +11,11 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
extern volatile int pen_release;
|
||||
|
||||
static DECLARE_COMPLETION(cpu_killed);
|
||||
|
||||
static inline void platform_do_lowpower(unsigned int cpu)
|
||||
{
|
||||
flush_cache_all();
|
||||
@ -38,7 +35,7 @@ static inline void platform_do_lowpower(unsigned int cpu)
|
||||
|
||||
int platform_cpu_kill(unsigned int cpu)
|
||||
{
|
||||
return wait_for_completion_timeout(&cpu_killed, 5000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -48,19 +45,6 @@ int platform_cpu_kill(unsigned int cpu)
|
||||
*/
|
||||
void platform_cpu_die(unsigned int cpu)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
unsigned int this_cpu = hard_smp_processor_id();
|
||||
|
||||
if (cpu != this_cpu) {
|
||||
printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
|
||||
this_cpu, cpu);
|
||||
BUG();
|
||||
}
|
||||
#endif
|
||||
|
||||
printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
|
||||
complete(&cpu_killed);
|
||||
|
||||
/* directly enter low power state, skipping secure registers */
|
||||
platform_do_lowpower(cpu);
|
||||
}
|
||||
|
@ -10,7 +10,6 @@
|
||||
#define ASMARM_ARCH_SMP_H
|
||||
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/smp_mpidr.h>
|
||||
|
||||
/* This is required to wakeup the secondary core */
|
||||
extern void u8500_secondary_startup(void);
|
||||
@ -18,8 +17,8 @@ extern void u8500_secondary_startup(void);
|
||||
/*
|
||||
* We use IRQ1 as the IPI
|
||||
*/
|
||||
static inline void smp_cross_call(const struct cpumask *mask)
|
||||
static inline void smp_cross_call(const struct cpumask *mask, int ipi)
|
||||
{
|
||||
gic_raise_softirq(mask, 1);
|
||||
gic_raise_softirq(mask, ipi);
|
||||
}
|
||||
#endif
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/localtimer.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
@ -28,17 +27,23 @@
|
||||
*/
|
||||
volatile int __cpuinitdata pen_release = -1;
|
||||
|
||||
static unsigned int __init get_core_count(void)
|
||||
/*
|
||||
* Write pen_release in a way that is guaranteed to be visible to all
|
||||
* observers, irrespective of whether they're taking part in coherency
|
||||
* or not. This is necessary for the hotplug code to work reliably.
|
||||
*/
|
||||
static void write_pen_release(int val)
|
||||
{
|
||||
return scu_get_core_count(__io_address(UX500_SCU_BASE));
|
||||
pen_release = val;
|
||||
smp_wmb();
|
||||
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
|
||||
outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(boot_lock);
|
||||
|
||||
void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
{
|
||||
trace_hardirqs_off();
|
||||
|
||||
/*
|
||||
* if any interrupts are already enabled for the primary
|
||||
* core (e.g. timer irq), then they will not have been enabled
|
||||
@ -50,7 +55,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
|
||||
* let the primary processor know we're out of the
|
||||
* pen, then head off into the C entry point
|
||||
*/
|
||||
pen_release = -1;
|
||||
write_pen_release(-1);
|
||||
|
||||
/*
|
||||
* Synchronise with the boot thread.
|
||||
@ -74,11 +79,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
* the holding pen - release it, then wait for it to flag
|
||||
* that it has been released by resetting pen_release.
|
||||
*/
|
||||
pen_release = cpu;
|
||||
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
|
||||
outer_clean_range(__pa(&pen_release), __pa(&pen_release) + 1);
|
||||
write_pen_release(cpu);
|
||||
|
||||
smp_cross_call(cpumask_of(cpu));
|
||||
smp_cross_call(cpumask_of(cpu), 1);
|
||||
|
||||
timeout = jiffies + (1 * HZ);
|
||||
while (time_before(jiffies, timeout)) {
|
||||
@ -97,9 +100,6 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
|
||||
static void __init wakeup_secondary(void)
|
||||
{
|
||||
/* nobody is to be released from the pen yet */
|
||||
pen_release = -1;
|
||||
|
||||
/*
|
||||
* write the address of secondary startup into the backup ram register
|
||||
* at offset 0x1FF4, then write the magic number 0xA1FEED01 to the
|
||||
@ -126,41 +126,27 @@ static void __init wakeup_secondary(void)
|
||||
*/
|
||||
void __init smp_init_cpus(void)
|
||||
{
|
||||
unsigned int i, ncores = get_core_count();
|
||||
unsigned int i, ncores;
|
||||
|
||||
ncores = scu_get_core_count(__io_address(UX500_SCU_BASE));
|
||||
|
||||
/* sanity check */
|
||||
if (ncores > NR_CPUS) {
|
||||
printk(KERN_WARNING
|
||||
"U8500: no. of cores (%d) greater than configured "
|
||||
"maximum of %d - clipping\n",
|
||||
ncores, NR_CPUS);
|
||||
ncores = NR_CPUS;
|
||||
}
|
||||
|
||||
for (i = 0; i < ncores; i++)
|
||||
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 = get_core_count();
|
||||
unsigned int cpu = smp_processor_id();
|
||||
int i;
|
||||
|
||||
/* sanity check */
|
||||
if (ncores == 0) {
|
||||
printk(KERN_ERR
|
||||
"U8500: strange CM count of 0? Default to 1\n");
|
||||
ncores = 1;
|
||||
}
|
||||
|
||||
if (ncores > num_possible_cpus()) {
|
||||
printk(KERN_WARNING
|
||||
"U8500: no. of cores (%d) greater than configured "
|
||||
"maximum of %d - clipping\n",
|
||||
ncores, num_possible_cpus());
|
||||
ncores = num_possible_cpus();
|
||||
}
|
||||
|
||||
smp_store_cpu_info(cpu);
|
||||
|
||||
/*
|
||||
* are we trying to boot more cores than exist?
|
||||
*/
|
||||
if (max_cpus > ncores)
|
||||
max_cpus = ncores;
|
||||
|
||||
/*
|
||||
* Initialise the present map, which describes the set of CPUs
|
||||
* actually populated at the present time.
|
||||
@ -168,13 +154,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
for (i = 0; i < max_cpus; i++)
|
||||
set_cpu_present(i, true);
|
||||
|
||||
if (max_cpus > 1) {
|
||||
/*
|
||||
* Enable the local timer or broadcast device for the
|
||||
* boot CPU, but only if we have more than one CPU.
|
||||
*/
|
||||
percpu_timer_setup();
|
||||
scu_enable(__io_address(UX500_SCU_BASE));
|
||||
wakeup_secondary();
|
||||
}
|
||||
scu_enable(__io_address(UX500_SCU_BASE));
|
||||
wakeup_secondary();
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ menu "Versatile platform type"
|
||||
config ARCH_VERSATILE_PB
|
||||
bool "Support Versatile/PB platform"
|
||||
select CPU_ARM926T
|
||||
select MIGHT_HAVE_PCI
|
||||
default y
|
||||
help
|
||||
Include support for the ARM(R) Versatile/PB platform.
|
||||
|
@ -31,8 +31,8 @@
|
||||
#include <linux/amba/pl022.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/clkdev.h>
|
||||
|
||||
#include <asm/clkdev.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/leds.h>
|
||||
@ -46,7 +46,6 @@
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <mach/clkdev.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/platform.h>
|
||||
#include <asm/hardware/timer-sp.h>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user