diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-02 12:50:51 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-02 12:50:51 -0500 |
commit | 367b0df173b0ebea5d18b6971c244e260b5feb17 (patch) | |
tree | 24d92e06f6982e6858612e377d8256897bd15801 | |
parent | 44644391ff1817fa01b1ae4a7e52af8a23e0baa2 (diff) | |
parent | 3a175cdf439275c3da347b6b42c4e9b652a12904 (diff) |
Merge branch 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm
Pull ARM updates from Russell King:
- StrongARM SA1111 updates to modernise and remove cruft
- Add StrongARM gpio drivers for board GPIOs
- Verify size of zImage is what we expect to avoid issues with
appended DTB
- nommu updates from Vladimir Murzin
- page table read-write-execute checking from Jinbum Park
- Broadcom Brahma-B15 cache updates from Florian Fainelli
- Avoid failure with kprobes test caused by inappropriately
placed kprobes
- Remove __memzero optimisation (which was incorrectly being
used directly by some drivers)
* 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm: (32 commits)
ARM: 8745/1: get rid of __memzero()
ARM: 8744/1: don't discard memblock for kexec
ARM: 8743/1: bL_switcher: add MODULE_LICENSE tag
ARM: 8742/1: Always use REFCOUNT_FULL
ARM: 8741/1: B15: fix unused label warnings
ARM: 8740/1: NOMMU: Make sure we do not hold stale data in mem[] array
ARM: 8739/1: NOMMU: Setup VBAR/Hivecs for secondaries cores
ARM: 8738/1: Disable CONFIG_DEBUG_VIRTUAL for NOMMU
ARM: 8737/1: mm: dump: add checking for writable and executable
ARM: 8736/1: mm: dump: make the page table dumping seq_file
ARM: 8735/1: mm: dump: make page table dumping reusable
ARM: sa1100/neponset: add GPIO drivers for control and modem registers
ARM: sa1100/assabet: add BCR/BSR GPIO driver
ARM: 8734/1: mm: idmap: Mark variables as ro_after_init
ARM: 8733/1: hw_breakpoint: Mark variables as __ro_after_init
ARM: 8732/1: NOMMU: Allow userspace to access background MPU region
ARM: 8727/1: MAINTAINERS: Update brcmstb entries to cover B15 code
ARM: 8728/1: B15: Register reboot notifier for KEXEC
ARM: 8730/1: B15: Add suspend/resume hooks
ARM: 8726/1: B15: Add CPU hotplug awareness
...
48 files changed, 1033 insertions, 625 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 4c104dbc746d..f981c5678eeb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -2855,6 +2855,8 @@ S: Maintained | |||
2855 | F: arch/arm/mach-bcm/*brcmstb* | 2855 | F: arch/arm/mach-bcm/*brcmstb* |
2856 | F: arch/arm/boot/dts/bcm7*.dts* | 2856 | F: arch/arm/boot/dts/bcm7*.dts* |
2857 | F: drivers/bus/brcmstb_gisb.c | 2857 | F: drivers/bus/brcmstb_gisb.c |
2858 | F: arch/arm/mm/cache-b15-rac.c | ||
2859 | F: arch/arm/include/asm/hardware/cache-b15-rac.h | ||
2858 | N: brcmstb | 2860 | N: brcmstb |
2859 | 2861 | ||
2860 | BROADCOM BMIPS CPUFREQ DRIVER | 2862 | BROADCOM BMIPS CPUFREQ DRIVER |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 11647091fa6d..4daddc53e7bc 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -3,8 +3,8 @@ config ARM | |||
3 | bool | 3 | bool |
4 | default y | 4 | default y |
5 | select ARCH_CLOCKSOURCE_DATA | 5 | select ARCH_CLOCKSOURCE_DATA |
6 | select ARCH_DISCARD_MEMBLOCK if !HAVE_ARCH_PFN_VALID | 6 | select ARCH_DISCARD_MEMBLOCK if !HAVE_ARCH_PFN_VALID && !KEXEC |
7 | select ARCH_HAS_DEBUG_VIRTUAL | 7 | select ARCH_HAS_DEBUG_VIRTUAL if MMU |
8 | select ARCH_HAS_DEVMEM_IS_ALLOWED | 8 | select ARCH_HAS_DEVMEM_IS_ALLOWED |
9 | select ARCH_HAS_ELF_RANDOMIZE | 9 | select ARCH_HAS_ELF_RANDOMIZE |
10 | select ARCH_HAS_SET_MEMORY | 10 | select ARCH_HAS_SET_MEMORY |
@@ -100,6 +100,7 @@ config ARM | |||
100 | select OLD_SIGACTION | 100 | select OLD_SIGACTION |
101 | select OLD_SIGSUSPEND3 | 101 | select OLD_SIGSUSPEND3 |
102 | select PERF_USE_VMALLOC | 102 | select PERF_USE_VMALLOC |
103 | select REFCOUNT_FULL | ||
103 | select RTC_LIB | 104 | select RTC_LIB |
104 | select SYS_SUPPORTS_APM_EMULATION | 105 | select SYS_SUPPORTS_APM_EMULATION |
105 | # Above selects are sorted alphabetically; please add new ones | 106 | # Above selects are sorted alphabetically; please add new ones |
@@ -1526,12 +1527,10 @@ config THUMB2_KERNEL | |||
1526 | bool "Compile the kernel in Thumb-2 mode" if !CPU_THUMBONLY | 1527 | bool "Compile the kernel in Thumb-2 mode" if !CPU_THUMBONLY |
1527 | depends on (CPU_V7 || CPU_V7M) && !CPU_V6 && !CPU_V6K | 1528 | depends on (CPU_V7 || CPU_V7M) && !CPU_V6 && !CPU_V6K |
1528 | default y if CPU_THUMBONLY | 1529 | default y if CPU_THUMBONLY |
1529 | select ARM_ASM_UNIFIED | ||
1530 | select ARM_UNWIND | 1530 | select ARM_UNWIND |
1531 | help | 1531 | help |
1532 | By enabling this option, the kernel will be compiled in | 1532 | By enabling this option, the kernel will be compiled in |
1533 | Thumb-2 mode. A compiler/assembler that understand the unified | 1533 | Thumb-2 mode. |
1534 | ARM-Thumb syntax is needed. | ||
1535 | 1534 | ||
1536 | If unsure, say N. | 1535 | If unsure, say N. |
1537 | 1536 | ||
@@ -1566,9 +1565,6 @@ config THUMB2_AVOID_R_ARM_THM_JUMP11 | |||
1566 | 1565 | ||
1567 | Unless you are sure your tools don't have this problem, say Y. | 1566 | Unless you are sure your tools don't have this problem, say Y. |
1568 | 1567 | ||
1569 | config ARM_ASM_UNIFIED | ||
1570 | bool | ||
1571 | |||
1572 | config ARM_PATCH_IDIV | 1568 | config ARM_PATCH_IDIV |
1573 | bool "Runtime patch udiv/sdiv instructions into __aeabi_{u}idiv()" | 1569 | bool "Runtime patch udiv/sdiv instructions into __aeabi_{u}idiv()" |
1574 | depends on CPU_32v7 && !XIP_KERNEL | 1570 | depends on CPU_32v7 && !XIP_KERNEL |
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 17685e19aed8..78a647080ebc 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug | |||
@@ -3,10 +3,14 @@ menu "Kernel hacking" | |||
3 | 3 | ||
4 | source "lib/Kconfig.debug" | 4 | source "lib/Kconfig.debug" |
5 | 5 | ||
6 | config ARM_PTDUMP | 6 | config ARM_PTDUMP_CORE |
7 | def_bool n | ||
8 | |||
9 | config ARM_PTDUMP_DEBUGFS | ||
7 | bool "Export kernel pagetable layout to userspace via debugfs" | 10 | bool "Export kernel pagetable layout to userspace via debugfs" |
8 | depends on DEBUG_KERNEL | 11 | depends on DEBUG_KERNEL |
9 | depends on MMU | 12 | depends on MMU |
13 | select ARM_PTDUMP_CORE | ||
10 | select DEBUG_FS | 14 | select DEBUG_FS |
11 | ---help--- | 15 | ---help--- |
12 | Say Y here if you want to show the kernel pagetable layout in a | 16 | Say Y here if you want to show the kernel pagetable layout in a |
@@ -16,6 +20,33 @@ config ARM_PTDUMP | |||
16 | kernel. | 20 | kernel. |
17 | If in doubt, say "N" | 21 | If in doubt, say "N" |
18 | 22 | ||
23 | config DEBUG_WX | ||
24 | bool "Warn on W+X mappings at boot" | ||
25 | select ARM_PTDUMP_CORE | ||
26 | ---help--- | ||
27 | Generate a warning if any W+X mappings are found at boot. | ||
28 | |||
29 | This is useful for discovering cases where the kernel is leaving | ||
30 | W+X mappings after applying NX, as such mappings are a security risk. | ||
31 | |||
32 | Look for a message in dmesg output like this: | ||
33 | |||
34 | arm/mm: Checked W+X mappings: passed, no W+X pages found. | ||
35 | |||
36 | or like this, if the check failed: | ||
37 | |||
38 | arm/mm: Checked W+X mappings: FAILED, <N> W+X pages found. | ||
39 | |||
40 | Note that even if the check fails, your kernel is possibly | ||
41 | still fine, as W+X mappings are not a security hole in | ||
42 | themselves, what they do is that they make the exploitation | ||
43 | of other unfixed kernel bugs easier. | ||
44 | |||
45 | There is no runtime or memory usage effect of this option | ||
46 | once the kernel has booted up - it's a one time check. | ||
47 | |||
48 | If in doubt, say "Y". | ||
49 | |||
19 | # RMK wants arm kernels compiled with frame pointers or stack unwinding. | 50 | # RMK wants arm kernels compiled with frame pointers or stack unwinding. |
20 | # If you know what you are doing and are willing to live without stack | 51 | # If you know what you are doing and are willing to live without stack |
21 | # traces, you can get a slightly smaller kernel by setting this option to | 52 | # traces, you can get a slightly smaller kernel by setting this option to |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 80351e505fd5..e83f5161fdd8 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -115,9 +115,11 @@ ifeq ($(CONFIG_ARM_UNWIND),y) | |||
115 | CFLAGS_ABI +=-funwind-tables | 115 | CFLAGS_ABI +=-funwind-tables |
116 | endif | 116 | endif |
117 | 117 | ||
118 | # Accept old syntax despite ".syntax unified" | ||
119 | AFLAGS_NOWARN :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W) | ||
120 | |||
118 | ifeq ($(CONFIG_THUMB2_KERNEL),y) | 121 | ifeq ($(CONFIG_THUMB2_KERNEL),y) |
119 | AFLAGS_AUTOIT :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mauto-it) | 122 | AFLAGS_AUTOIT :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mauto-it) |
120 | AFLAGS_NOWARN :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W) | ||
121 | CFLAGS_ISA :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN) | 123 | CFLAGS_ISA :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN) |
122 | AFLAGS_ISA :=$(CFLAGS_ISA) -Wa$(comma)-mthumb | 124 | AFLAGS_ISA :=$(CFLAGS_ISA) -Wa$(comma)-mthumb |
123 | # Work around buggy relocation from gas if requested: | 125 | # Work around buggy relocation from gas if requested: |
@@ -125,7 +127,7 @@ ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y) | |||
125 | KBUILD_CFLAGS_MODULE +=-fno-optimize-sibling-calls | 127 | KBUILD_CFLAGS_MODULE +=-fno-optimize-sibling-calls |
126 | endif | 128 | endif |
127 | else | 129 | else |
128 | CFLAGS_ISA :=$(call cc-option,-marm,) | 130 | CFLAGS_ISA :=$(call cc-option,-marm,) $(AFLAGS_NOWARN) |
129 | AFLAGS_ISA :=$(CFLAGS_ISA) | 131 | AFLAGS_ISA :=$(CFLAGS_ISA) |
130 | endif | 132 | endif |
131 | 133 | ||
diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c index 309e1bbad75d..13c90abc68d6 100644 --- a/arch/arm/boot/compressed/string.c +++ b/arch/arm/boot/compressed/string.c | |||
@@ -130,8 +130,3 @@ void *memset(void *s, int c, size_t count) | |||
130 | *xs++ = c; | 130 | *xs++ = c; |
131 | return s; | 131 | return s; |
132 | } | 132 | } |
133 | |||
134 | void __memzero(void *s, size_t count) | ||
135 | { | ||
136 | memset(s, 0, count); | ||
137 | } | ||
diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S index e6bf6774c4bb..2b963d8e76dd 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.S +++ b/arch/arm/boot/compressed/vmlinux.lds.S | |||
@@ -56,6 +56,7 @@ SECTIONS | |||
56 | .rodata : { | 56 | .rodata : { |
57 | *(.rodata) | 57 | *(.rodata) |
58 | *(.rodata.*) | 58 | *(.rodata.*) |
59 | *(.data.rel.ro) | ||
59 | } | 60 | } |
60 | .piggydata : { | 61 | .piggydata : { |
61 | *(.piggydata) | 62 | *(.piggydata) |
@@ -101,6 +102,12 @@ SECTIONS | |||
101 | * this symbol allows further debug in the near future. | 102 | * this symbol allows further debug in the near future. |
102 | */ | 103 | */ |
103 | .image_end (NOLOAD) : { | 104 | .image_end (NOLOAD) : { |
105 | /* | ||
106 | * EFI requires that the image is aligned to 512 bytes, and appended | ||
107 | * DTB requires that we know where the end of the image is. Ensure | ||
108 | * that both are satisfied by ensuring that there are no additional | ||
109 | * sections emitted into the decompressor image. | ||
110 | */ | ||
104 | _edata_real = .; | 111 | _edata_real = .; |
105 | } | 112 | } |
106 | 113 | ||
@@ -128,3 +135,4 @@ SECTIONS | |||
128 | .stab.indexstr 0 : { *(.stab.indexstr) } | 135 | .stab.indexstr 0 : { *(.stab.indexstr) } |
129 | .comment 0 : { *(.comment) } | 136 | .comment 0 : { *(.comment) } |
130 | } | 137 | } |
138 | ASSERT(_edata_real == _edata, "error: zImage file size is incorrect"); | ||
diff --git a/arch/arm/common/bL_switcher_dummy_if.c b/arch/arm/common/bL_switcher_dummy_if.c index 4c10c6452678..f4dc1714a79e 100644 --- a/arch/arm/common/bL_switcher_dummy_if.c +++ b/arch/arm/common/bL_switcher_dummy_if.c | |||
@@ -57,3 +57,7 @@ static struct miscdevice bL_switcher_device = { | |||
57 | &bL_switcher_fops | 57 | &bL_switcher_fops |
58 | }; | 58 | }; |
59 | module_misc_device(bL_switcher_device); | 59 | module_misc_device(bL_switcher_device); |
60 | |||
61 | MODULE_AUTHOR("Nicolas Pitre <nico@linaro.org>"); | ||
62 | MODULE_LICENSE("GPL v2"); | ||
63 | MODULE_DESCRIPTION("big.LITTLE switcher dummy user interface"); | ||
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 4ecd5120fce7..a2c878769eaf 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c | |||
@@ -108,6 +108,7 @@ struct sa1111 { | |||
108 | spinlock_t lock; | 108 | spinlock_t lock; |
109 | void __iomem *base; | 109 | void __iomem *base; |
110 | struct sa1111_platform_data *pdata; | 110 | struct sa1111_platform_data *pdata; |
111 | struct irq_domain *irqdomain; | ||
111 | struct gpio_chip gc; | 112 | struct gpio_chip gc; |
112 | #ifdef CONFIG_PM | 113 | #ifdef CONFIG_PM |
113 | void *saved_state; | 114 | void *saved_state; |
@@ -125,7 +126,7 @@ struct sa1111_dev_info { | |||
125 | unsigned long skpcr_mask; | 126 | unsigned long skpcr_mask; |
126 | bool dma; | 127 | bool dma; |
127 | unsigned int devid; | 128 | unsigned int devid; |
128 | unsigned int irq[6]; | 129 | unsigned int hwirq[6]; |
129 | }; | 130 | }; |
130 | 131 | ||
131 | static struct sa1111_dev_info sa1111_devices[] = { | 132 | static struct sa1111_dev_info sa1111_devices[] = { |
@@ -134,7 +135,7 @@ static struct sa1111_dev_info sa1111_devices[] = { | |||
134 | .skpcr_mask = SKPCR_UCLKEN, | 135 | .skpcr_mask = SKPCR_UCLKEN, |
135 | .dma = true, | 136 | .dma = true, |
136 | .devid = SA1111_DEVID_USB, | 137 | .devid = SA1111_DEVID_USB, |
137 | .irq = { | 138 | .hwirq = { |
138 | IRQ_USBPWR, | 139 | IRQ_USBPWR, |
139 | IRQ_HCIM, | 140 | IRQ_HCIM, |
140 | IRQ_HCIBUFFACC, | 141 | IRQ_HCIBUFFACC, |
@@ -148,7 +149,7 @@ static struct sa1111_dev_info sa1111_devices[] = { | |||
148 | .skpcr_mask = SKPCR_I2SCLKEN | SKPCR_L3CLKEN, | 149 | .skpcr_mask = SKPCR_I2SCLKEN | SKPCR_L3CLKEN, |
149 | .dma = true, | 150 | .dma = true, |
150 | .devid = SA1111_DEVID_SAC, | 151 | .devid = SA1111_DEVID_SAC, |
151 | .irq = { | 152 | .hwirq = { |
152 | AUDXMTDMADONEA, | 153 | AUDXMTDMADONEA, |
153 | AUDXMTDMADONEB, | 154 | AUDXMTDMADONEB, |
154 | AUDRCVDMADONEA, | 155 | AUDRCVDMADONEA, |
@@ -164,7 +165,7 @@ static struct sa1111_dev_info sa1111_devices[] = { | |||
164 | .offset = SA1111_KBD, | 165 | .offset = SA1111_KBD, |
165 | .skpcr_mask = SKPCR_PTCLKEN, | 166 | .skpcr_mask = SKPCR_PTCLKEN, |
166 | .devid = SA1111_DEVID_PS2_KBD, | 167 | .devid = SA1111_DEVID_PS2_KBD, |
167 | .irq = { | 168 | .hwirq = { |
168 | IRQ_TPRXINT, | 169 | IRQ_TPRXINT, |
169 | IRQ_TPTXINT | 170 | IRQ_TPTXINT |
170 | }, | 171 | }, |
@@ -173,7 +174,7 @@ static struct sa1111_dev_info sa1111_devices[] = { | |||
173 | .offset = SA1111_MSE, | 174 | .offset = SA1111_MSE, |
174 | .skpcr_mask = SKPCR_PMCLKEN, | 175 | .skpcr_mask = SKPCR_PMCLKEN, |
175 | .devid = SA1111_DEVID_PS2_MSE, | 176 | .devid = SA1111_DEVID_PS2_MSE, |
176 | .irq = { | 177 | .hwirq = { |
177 | IRQ_MSRXINT, | 178 | IRQ_MSRXINT, |
178 | IRQ_MSTXINT | 179 | IRQ_MSTXINT |
179 | }, | 180 | }, |
@@ -182,7 +183,7 @@ static struct sa1111_dev_info sa1111_devices[] = { | |||
182 | .offset = 0x1800, | 183 | .offset = 0x1800, |
183 | .skpcr_mask = 0, | 184 | .skpcr_mask = 0, |
184 | .devid = SA1111_DEVID_PCMCIA, | 185 | .devid = SA1111_DEVID_PCMCIA, |
185 | .irq = { | 186 | .hwirq = { |
186 | IRQ_S0_READY_NINT, | 187 | IRQ_S0_READY_NINT, |
187 | IRQ_S0_CD_VALID, | 188 | IRQ_S0_CD_VALID, |
188 | IRQ_S0_BVD1_STSCHG, | 189 | IRQ_S0_BVD1_STSCHG, |
@@ -193,6 +194,19 @@ static struct sa1111_dev_info sa1111_devices[] = { | |||
193 | }, | 194 | }, |
194 | }; | 195 | }; |
195 | 196 | ||
197 | static int sa1111_map_irq(struct sa1111 *sachip, irq_hw_number_t hwirq) | ||
198 | { | ||
199 | return irq_create_mapping(sachip->irqdomain, hwirq); | ||
200 | } | ||
201 | |||
202 | static void sa1111_handle_irqdomain(struct irq_domain *irqdomain, int irq) | ||
203 | { | ||
204 | struct irq_desc *d = irq_to_desc(irq_linear_revmap(irqdomain, irq)); | ||
205 | |||
206 | if (d) | ||
207 | generic_handle_irq_desc(d); | ||
208 | } | ||
209 | |||
196 | /* | 210 | /* |
197 | * SA1111 interrupt support. Since clearing an IRQ while there are | 211 | * SA1111 interrupt support. Since clearing an IRQ while there are |
198 | * active IRQs causes the interrupt output to pulse, the upper levels | 212 | * active IRQs causes the interrupt output to pulse, the upper levels |
@@ -202,49 +216,45 @@ static void sa1111_irq_handler(struct irq_desc *desc) | |||
202 | { | 216 | { |
203 | unsigned int stat0, stat1, i; | 217 | unsigned int stat0, stat1, i; |
204 | struct sa1111 *sachip = irq_desc_get_handler_data(desc); | 218 | struct sa1111 *sachip = irq_desc_get_handler_data(desc); |
219 | struct irq_domain *irqdomain; | ||
205 | void __iomem *mapbase = sachip->base + SA1111_INTC; | 220 | void __iomem *mapbase = sachip->base + SA1111_INTC; |
206 | 221 | ||
207 | stat0 = sa1111_readl(mapbase + SA1111_INTSTATCLR0); | 222 | stat0 = readl_relaxed(mapbase + SA1111_INTSTATCLR0); |
208 | stat1 = sa1111_readl(mapbase + SA1111_INTSTATCLR1); | 223 | stat1 = readl_relaxed(mapbase + SA1111_INTSTATCLR1); |
209 | 224 | ||
210 | sa1111_writel(stat0, mapbase + SA1111_INTSTATCLR0); | 225 | writel_relaxed(stat0, mapbase + SA1111_INTSTATCLR0); |
211 | 226 | ||
212 | desc->irq_data.chip->irq_ack(&desc->irq_data); | 227 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
213 | 228 | ||
214 | sa1111_writel(stat1, mapbase + SA1111_INTSTATCLR1); | 229 | writel_relaxed(stat1, mapbase + SA1111_INTSTATCLR1); |
215 | 230 | ||
216 | if (stat0 == 0 && stat1 == 0) { | 231 | if (stat0 == 0 && stat1 == 0) { |
217 | do_bad_IRQ(desc); | 232 | do_bad_IRQ(desc); |
218 | return; | 233 | return; |
219 | } | 234 | } |
220 | 235 | ||
236 | irqdomain = sachip->irqdomain; | ||
237 | |||
221 | for (i = 0; stat0; i++, stat0 >>= 1) | 238 | for (i = 0; stat0; i++, stat0 >>= 1) |
222 | if (stat0 & 1) | 239 | if (stat0 & 1) |
223 | generic_handle_irq(i + sachip->irq_base); | 240 | sa1111_handle_irqdomain(irqdomain, i); |
224 | 241 | ||
225 | for (i = 32; stat1; i++, stat1 >>= 1) | 242 | for (i = 32; stat1; i++, stat1 >>= 1) |
226 | if (stat1 & 1) | 243 | if (stat1 & 1) |
227 | generic_handle_irq(i + sachip->irq_base); | 244 | sa1111_handle_irqdomain(irqdomain, i); |
228 | 245 | ||
229 | /* For level-based interrupts */ | 246 | /* For level-based interrupts */ |
230 | desc->irq_data.chip->irq_unmask(&desc->irq_data); | 247 | desc->irq_data.chip->irq_unmask(&desc->irq_data); |
231 | } | 248 | } |
232 | 249 | ||
233 | #define SA1111_IRQMASK_LO(x) (1 << (x - sachip->irq_base)) | ||
234 | #define SA1111_IRQMASK_HI(x) (1 << (x - sachip->irq_base - 32)) | ||
235 | |||
236 | static u32 sa1111_irqmask(struct irq_data *d) | 250 | static u32 sa1111_irqmask(struct irq_data *d) |
237 | { | 251 | { |
238 | struct sa1111 *sachip = irq_data_get_irq_chip_data(d); | 252 | return BIT(irqd_to_hwirq(d) & 31); |
239 | |||
240 | return BIT((d->irq - sachip->irq_base) & 31); | ||
241 | } | 253 | } |
242 | 254 | ||
243 | static int sa1111_irqbank(struct irq_data *d) | 255 | static int sa1111_irqbank(struct irq_data *d) |
244 | { | 256 | { |
245 | struct sa1111 *sachip = irq_data_get_irq_chip_data(d); | 257 | return (irqd_to_hwirq(d) / 32) * 4; |
246 | |||
247 | return ((d->irq - sachip->irq_base) / 32) * 4; | ||
248 | } | 258 | } |
249 | 259 | ||
250 | static void sa1111_ack_irq(struct irq_data *d) | 260 | static void sa1111_ack_irq(struct irq_data *d) |
@@ -257,9 +267,9 @@ static void sa1111_mask_irq(struct irq_data *d) | |||
257 | void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d); | 267 | void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d); |
258 | u32 ie; | 268 | u32 ie; |
259 | 269 | ||
260 | ie = sa1111_readl(mapbase + SA1111_INTEN0); | 270 | ie = readl_relaxed(mapbase + SA1111_INTEN0); |
261 | ie &= ~sa1111_irqmask(d); | 271 | ie &= ~sa1111_irqmask(d); |
262 | sa1111_writel(ie, mapbase + SA1111_INTEN0); | 272 | writel(ie, mapbase + SA1111_INTEN0); |
263 | } | 273 | } |
264 | 274 | ||
265 | static void sa1111_unmask_irq(struct irq_data *d) | 275 | static void sa1111_unmask_irq(struct irq_data *d) |
@@ -268,9 +278,9 @@ static void sa1111_unmask_irq(struct irq_data *d) | |||
268 | void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d); | 278 | void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d); |
269 | u32 ie; | 279 | u32 ie; |
270 | 280 | ||
271 | ie = sa1111_readl(mapbase + SA1111_INTEN0); | 281 | ie = readl_relaxed(mapbase + SA1111_INTEN0); |
272 | ie |= sa1111_irqmask(d); | 282 | ie |= sa1111_irqmask(d); |
273 | sa1111_writel(ie, mapbase + SA1111_INTEN0); | 283 | writel_relaxed(ie, mapbase + SA1111_INTEN0); |
274 | } | 284 | } |
275 | 285 | ||
276 | /* | 286 | /* |
@@ -287,11 +297,11 @@ static int sa1111_retrigger_irq(struct irq_data *d) | |||
287 | u32 ip, mask = sa1111_irqmask(d); | 297 | u32 ip, mask = sa1111_irqmask(d); |
288 | int i; | 298 | int i; |
289 | 299 | ||
290 | ip = sa1111_readl(mapbase + SA1111_INTPOL0); | 300 | ip = readl_relaxed(mapbase + SA1111_INTPOL0); |
291 | for (i = 0; i < 8; i++) { | 301 | for (i = 0; i < 8; i++) { |
292 | sa1111_writel(ip ^ mask, mapbase + SA1111_INTPOL0); | 302 | writel_relaxed(ip ^ mask, mapbase + SA1111_INTPOL0); |
293 | sa1111_writel(ip, mapbase + SA1111_INTPOL0); | 303 | writel_relaxed(ip, mapbase + SA1111_INTPOL0); |
294 | if (sa1111_readl(mapbase + SA1111_INTSTATCLR0) & mask) | 304 | if (readl_relaxed(mapbase + SA1111_INTSTATCLR0) & mask) |
295 | break; | 305 | break; |
296 | } | 306 | } |
297 | 307 | ||
@@ -313,13 +323,13 @@ static int sa1111_type_irq(struct irq_data *d, unsigned int flags) | |||
313 | if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0) | 323 | if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0) |
314 | return -EINVAL; | 324 | return -EINVAL; |
315 | 325 | ||
316 | ip = sa1111_readl(mapbase + SA1111_INTPOL0); | 326 | ip = readl_relaxed(mapbase + SA1111_INTPOL0); |
317 | if (flags & IRQ_TYPE_EDGE_RISING) | 327 | if (flags & IRQ_TYPE_EDGE_RISING) |
318 | ip &= ~mask; | 328 | ip &= ~mask; |
319 | else | 329 | else |
320 | ip |= mask; | 330 | ip |= mask; |
321 | sa1111_writel(ip, mapbase + SA1111_INTPOL0); | 331 | writel_relaxed(ip, mapbase + SA1111_INTPOL0); |
322 | sa1111_writel(ip, mapbase + SA1111_WAKEPOL0); | 332 | writel_relaxed(ip, mapbase + SA1111_WAKEPOL0); |
323 | 333 | ||
324 | return 0; | 334 | return 0; |
325 | } | 335 | } |
@@ -330,12 +340,12 @@ static int sa1111_wake_irq(struct irq_data *d, unsigned int on) | |||
330 | void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d); | 340 | void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d); |
331 | u32 we, mask = sa1111_irqmask(d); | 341 | u32 we, mask = sa1111_irqmask(d); |
332 | 342 | ||
333 | we = sa1111_readl(mapbase + SA1111_WAKEEN0); | 343 | we = readl_relaxed(mapbase + SA1111_WAKEEN0); |
334 | if (on) | 344 | if (on) |
335 | we |= mask; | 345 | we |= mask; |
336 | else | 346 | else |
337 | we &= ~mask; | 347 | we &= ~mask; |
338 | sa1111_writel(we, mapbase + SA1111_WAKEEN0); | 348 | writel_relaxed(we, mapbase + SA1111_WAKEEN0); |
339 | 349 | ||
340 | return 0; | 350 | return 0; |
341 | } | 351 | } |
@@ -350,10 +360,30 @@ static struct irq_chip sa1111_irq_chip = { | |||
350 | .irq_set_wake = sa1111_wake_irq, | 360 | .irq_set_wake = sa1111_wake_irq, |
351 | }; | 361 | }; |
352 | 362 | ||
363 | static int sa1111_irqdomain_map(struct irq_domain *d, unsigned int irq, | ||
364 | irq_hw_number_t hwirq) | ||
365 | { | ||
366 | struct sa1111 *sachip = d->host_data; | ||
367 | |||
368 | /* Disallow unavailable interrupts */ | ||
369 | if (hwirq > SSPROR && hwirq < AUDXMTDMADONEA) | ||
370 | return -EINVAL; | ||
371 | |||
372 | irq_set_chip_data(irq, sachip); | ||
373 | irq_set_chip_and_handler(irq, &sa1111_irq_chip, handle_edge_irq); | ||
374 | irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); | ||
375 | |||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static const struct irq_domain_ops sa1111_irqdomain_ops = { | ||
380 | .map = sa1111_irqdomain_map, | ||
381 | .xlate = irq_domain_xlate_twocell, | ||
382 | }; | ||
383 | |||
353 | static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base) | 384 | static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base) |
354 | { | 385 | { |
355 | void __iomem *irqbase = sachip->base + SA1111_INTC; | 386 | void __iomem *irqbase = sachip->base + SA1111_INTC; |
356 | unsigned i, irq; | ||
357 | int ret; | 387 | int ret; |
358 | 388 | ||
359 | /* | 389 | /* |
@@ -373,38 +403,40 @@ static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base) | |||
373 | sachip->irq_base = ret; | 403 | sachip->irq_base = ret; |
374 | 404 | ||
375 | /* disable all IRQs */ | 405 | /* disable all IRQs */ |
376 | sa1111_writel(0, irqbase + SA1111_INTEN0); | 406 | writel_relaxed(0, irqbase + SA1111_INTEN0); |
377 | sa1111_writel(0, irqbase + SA1111_INTEN1); | 407 | writel_relaxed(0, irqbase + SA1111_INTEN1); |
378 | sa1111_writel(0, irqbase + SA1111_WAKEEN0); | 408 | writel_relaxed(0, irqbase + SA1111_WAKEEN0); |
379 | sa1111_writel(0, irqbase + SA1111_WAKEEN1); | 409 | writel_relaxed(0, irqbase + SA1111_WAKEEN1); |
380 | 410 | ||
381 | /* | 411 | /* |
382 | * detect on rising edge. Note: Feb 2001 Errata for SA1111 | 412 | * detect on rising edge. Note: Feb 2001 Errata for SA1111 |
383 | * specifies that S0ReadyInt and S1ReadyInt should be '1'. | 413 | * specifies that S0ReadyInt and S1ReadyInt should be '1'. |
384 | */ | 414 | */ |
385 | sa1111_writel(0, irqbase + SA1111_INTPOL0); | 415 | writel_relaxed(0, irqbase + SA1111_INTPOL0); |
386 | sa1111_writel(BIT(IRQ_S0_READY_NINT & 31) | | 416 | writel_relaxed(BIT(IRQ_S0_READY_NINT & 31) | |
387 | BIT(IRQ_S1_READY_NINT & 31), | 417 | BIT(IRQ_S1_READY_NINT & 31), |
388 | irqbase + SA1111_INTPOL1); | 418 | irqbase + SA1111_INTPOL1); |
389 | 419 | ||
390 | /* clear all IRQs */ | 420 | /* clear all IRQs */ |
391 | sa1111_writel(~0, irqbase + SA1111_INTSTATCLR0); | 421 | writel_relaxed(~0, irqbase + SA1111_INTSTATCLR0); |
392 | sa1111_writel(~0, irqbase + SA1111_INTSTATCLR1); | 422 | writel_relaxed(~0, irqbase + SA1111_INTSTATCLR1); |
393 | |||
394 | for (i = IRQ_GPAIN0; i <= SSPROR; i++) { | ||
395 | irq = sachip->irq_base + i; | ||
396 | irq_set_chip_and_handler(irq, &sa1111_irq_chip, handle_edge_irq); | ||
397 | irq_set_chip_data(irq, sachip); | ||
398 | irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); | ||
399 | } | ||
400 | 423 | ||
401 | for (i = AUDXMTDMADONEA; i <= IRQ_S1_BVD1_STSCHG; i++) { | 424 | sachip->irqdomain = irq_domain_add_linear(NULL, SA1111_IRQ_NR, |
402 | irq = sachip->irq_base + i; | 425 | &sa1111_irqdomain_ops, |
403 | irq_set_chip_and_handler(irq, &sa1111_irq_chip, handle_edge_irq); | 426 | sachip); |
404 | irq_set_chip_data(irq, sachip); | 427 | if (!sachip->irqdomain) { |
405 | irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); | 428 | irq_free_descs(sachip->irq_base, SA1111_IRQ_NR); |
429 | return -ENOMEM; | ||
406 | } | 430 | } |
407 | 431 | ||
432 | irq_domain_associate_many(sachip->irqdomain, | ||
433 | sachip->irq_base + IRQ_GPAIN0, | ||
434 | IRQ_GPAIN0, SSPROR + 1 - IRQ_GPAIN0); | ||
435 | irq_domain_associate_many(sachip->irqdomain, | ||
436 | sachip->irq_base + AUDXMTDMADONEA, | ||
437 | AUDXMTDMADONEA, | ||
438 | IRQ_S1_BVD1_STSCHG + 1 - AUDXMTDMADONEA); | ||
439 | |||
408 | /* | 440 | /* |
409 | * Register SA1111 interrupt | 441 | * Register SA1111 interrupt |
410 | */ | 442 | */ |
@@ -420,20 +452,22 @@ static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base) | |||
420 | 452 | ||
421 | static void sa1111_remove_irq(struct sa1111 *sachip) | 453 | static void sa1111_remove_irq(struct sa1111 *sachip) |
422 | { | 454 | { |
455 | struct irq_domain *domain = sachip->irqdomain; | ||
423 | void __iomem *irqbase = sachip->base + SA1111_INTC; | 456 | void __iomem *irqbase = sachip->base + SA1111_INTC; |
457 | int i; | ||
424 | 458 | ||
425 | /* disable all IRQs */ | 459 | /* disable all IRQs */ |
426 | sa1111_writel(0, irqbase + SA1111_INTEN0); | 460 | writel_relaxed(0, irqbase + SA1111_INTEN0); |
427 | sa1111_writel(0, irqbase + SA1111_INTEN1); | 461 | writel_relaxed(0, irqbase + SA1111_INTEN1); |
428 | sa1111_writel(0, irqbase + SA1111_WAKEEN0); | 462 | writel_relaxed(0, irqbase + SA1111_WAKEEN0); |
429 | sa1111_writel(0, irqbase + SA1111_WAKEEN1); | 463 | writel_relaxed(0, irqbase + SA1111_WAKEEN1); |
430 | 464 | ||
431 | if (sachip->irq != NO_IRQ) { | 465 | irq_set_chained_handler_and_data(sachip->irq, NULL, NULL); |
432 | irq_set_chained_handler_and_data(sachip->irq, NULL, NULL); | 466 | for (i = 0; i < SA1111_IRQ_NR; i++) |
433 | irq_free_descs(sachip->irq_base, SA1111_IRQ_NR); | 467 | irq_dispose_mapping(irq_find_mapping(domain, i)); |
468 | irq_domain_remove(domain); | ||
434 | 469 | ||
435 | release_mem_region(sachip->phys + SA1111_INTC, 512); | 470 | release_mem_region(sachip->phys + SA1111_INTC, 512); |
436 | } | ||
437 | } | 471 | } |
438 | 472 | ||
439 | enum { | 473 | enum { |
@@ -572,7 +606,7 @@ static int sa1111_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | |||
572 | { | 606 | { |
573 | struct sa1111 *sachip = gc_to_sa1111(gc); | 607 | struct sa1111 *sachip = gc_to_sa1111(gc); |
574 | 608 | ||
575 | return sachip->irq_base + offset; | 609 | return sa1111_map_irq(sachip, offset); |
576 | } | 610 | } |
577 | 611 | ||
578 | static int sa1111_setup_gpios(struct sa1111 *sachip) | 612 | static int sa1111_setup_gpios(struct sa1111 *sachip) |
@@ -618,11 +652,11 @@ static void sa1111_wake(struct sa1111 *sachip) | |||
618 | /* | 652 | /* |
619 | * Turn VCO on, and disable PLL Bypass. | 653 | * Turn VCO on, and disable PLL Bypass. |
620 | */ | 654 | */ |
621 | r = sa1111_readl(sachip->base + SA1111_SKCR); | 655 | r = readl_relaxed(sachip->base + SA1111_SKCR); |
622 | r &= ~SKCR_VCO_OFF; | 656 | r &= ~SKCR_VCO_OFF; |
623 | sa1111_writel(r, sachip->base + SA1111_SKCR); | 657 | writel_relaxed(r, sachip->base + SA1111_SKCR); |
624 | r |= SKCR_PLL_BYPASS | SKCR_OE_EN; | 658 | r |= SKCR_PLL_BYPASS | SKCR_OE_EN; |
625 | sa1111_writel(r, sachip->base + SA1111_SKCR); | 659 | writel_relaxed(r, sachip->base + SA1111_SKCR); |
626 | 660 | ||
627 | /* | 661 | /* |
628 | * Wait lock time. SA1111 manual _doesn't_ | 662 | * Wait lock time. SA1111 manual _doesn't_ |
@@ -634,7 +668,7 @@ static void sa1111_wake(struct sa1111 *sachip) | |||
634 | * Enable RCLK. We also ensure that RDYEN is set. | 668 | * Enable RCLK. We also ensure that RDYEN is set. |
635 | */ | 669 | */ |
636 | r |= SKCR_RCLKEN | SKCR_RDYEN; | 670 | r |= SKCR_RCLKEN | SKCR_RDYEN; |
637 | sa1111_writel(r, sachip->base + SA1111_SKCR); | 671 | writel_relaxed(r, sachip->base + SA1111_SKCR); |
638 | 672 | ||
639 | /* | 673 | /* |
640 | * Wait 14 RCLK cycles for the chip to finish coming out | 674 | * Wait 14 RCLK cycles for the chip to finish coming out |
@@ -645,7 +679,7 @@ static void sa1111_wake(struct sa1111 *sachip) | |||
645 | /* | 679 | /* |
646 | * Ensure all clocks are initially off. | 680 | * Ensure all clocks are initially off. |
647 | */ | 681 | */ |
648 | sa1111_writel(0, sachip->base + SA1111_SKPCR); | 682 | writel_relaxed(0, sachip->base + SA1111_SKPCR); |
649 | 683 | ||
650 | spin_unlock_irqrestore(&sachip->lock, flags); | 684 | spin_unlock_irqrestore(&sachip->lock, flags); |
651 | } | 685 | } |
@@ -675,7 +709,7 @@ sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac, | |||
675 | if (cas_latency == 3) | 709 | if (cas_latency == 3) |
676 | smcr |= SMCR_CLAT; | 710 | smcr |= SMCR_CLAT; |
677 | 711 | ||
678 | sa1111_writel(smcr, sachip->base + SA1111_SMCR); | 712 | writel_relaxed(smcr, sachip->base + SA1111_SMCR); |
679 | 713 | ||
680 | /* | 714 | /* |
681 | * Now clear the bits in the DMA mask to work around the SA1111 | 715 | * Now clear the bits in the DMA mask to work around the SA1111 |
@@ -723,8 +757,8 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent, | |||
723 | dev->mapbase = sachip->base + info->offset; | 757 | dev->mapbase = sachip->base + info->offset; |
724 | dev->skpcr_mask = info->skpcr_mask; | 758 | dev->skpcr_mask = info->skpcr_mask; |
725 | 759 | ||
726 | for (i = 0; i < ARRAY_SIZE(info->irq); i++) | 760 | for (i = 0; i < ARRAY_SIZE(info->hwirq); i++) |
727 | dev->irq[i] = sachip->irq_base + info->irq[i]; | 761 | dev->hwirq[i] = info->hwirq[i]; |
728 | 762 | ||
729 | /* | 763 | /* |
730 | * If the parent device has a DMA mask associated with it, and | 764 | * If the parent device has a DMA mask associated with it, and |
@@ -814,7 +848,7 @@ static int __sa1111_probe(struct device *me, struct resource *mem, int irq) | |||
814 | /* | 848 | /* |
815 | * Probe for the chip. Only touch the SBI registers. | 849 | * Probe for the chip. Only touch the SBI registers. |
816 | */ | 850 | */ |
817 | id = sa1111_readl(sachip->base + SA1111_SKID); | 851 | id = readl_relaxed(sachip->base + SA1111_SKID); |
818 | if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { | 852 | if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { |
819 | printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id); | 853 | printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id); |
820 | ret = -ENODEV; | 854 | ret = -ENODEV; |
@@ -833,11 +867,9 @@ static int __sa1111_probe(struct device *me, struct resource *mem, int irq) | |||
833 | * The interrupt controller must be initialised before any | 867 | * The interrupt controller must be initialised before any |
834 | * other device to ensure that the interrupts are available. | 868 | * other device to ensure that the interrupts are available. |
835 | */ | 869 | */ |
836 | if (sachip->irq != NO_IRQ) { | 870 | ret = sa1111_setup_irq(sachip, pd->irq_base); |
837 | ret = sa1111_setup_irq(sachip, pd->irq_base); | 871 | if (ret) |
838 | if (ret) | 872 | goto err_clk; |
839 | goto err_clk; | ||
840 | } | ||
841 | 873 | ||
842 | /* Setup the GPIOs - should really be done after the IRQ setup */ | 874 | /* Setup the GPIOs - should really be done after the IRQ setup */ |
843 | ret = sa1111_setup_gpios(sachip); | 875 | ret = sa1111_setup_gpios(sachip); |
@@ -864,8 +896,8 @@ static int __sa1111_probe(struct device *me, struct resource *mem, int irq) | |||
864 | * DMA. It can otherwise be held firmly in the off position. | 896 | * DMA. It can otherwise be held firmly in the off position. |
865 | * (currently, we always enable it.) | 897 | * (currently, we always enable it.) |
866 | */ | 898 | */ |
867 | val = sa1111_readl(sachip->base + SA1111_SKPCR); | 899 | val = readl_relaxed(sachip->base + SA1111_SKPCR); |
868 | sa1111_writel(val | SKPCR_DCLKEN, sachip->base + SA1111_SKPCR); | 900 | writel_relaxed(val | SKPCR_DCLKEN, sachip->base + SA1111_SKPCR); |
869 | 901 | ||
870 | /* | 902 | /* |
871 | * Enable the SA1110 memory bus request and grant signals. | 903 | * Enable the SA1110 memory bus request and grant signals. |
@@ -962,31 +994,31 @@ static int sa1111_suspend_noirq(struct device *dev) | |||
962 | * Save state. | 994 | * Save state. |
963 | */ | 995 | */ |
964 | base = sachip->base; | 996 | base = sachip->base; |
965 | save->skcr = sa1111_readl(base + SA1111_SKCR); | 997 | save->skcr = readl_relaxed(base + SA1111_SKCR); |
966 | save->skpcr = sa1111_readl(base + SA1111_SKPCR); | 998 | save->skpcr = readl_relaxed(base + SA1111_SKPCR); |
967 | save->skcdr = sa1111_readl(base + SA1111_SKCDR); | 999 | save->skcdr = readl_relaxed(base + SA1111_SKCDR); |
968 | save->skaud = sa1111_readl(base + SA1111_SKAUD); | 1000 | save->skaud = readl_relaxed(base + SA1111_SKAUD); |
969 | save->skpwm0 = sa1111_readl(base + SA1111_SKPWM0); | 1001 | save->skpwm0 = readl_relaxed(base + SA1111_SKPWM0); |
970 | save->skpwm1 = sa1111_readl(base + SA1111_SKPWM1); | 1002 | save->skpwm1 = readl_relaxed(base + SA1111_SKPWM1); |
971 | 1003 | ||
972 | sa1111_writel(0, sachip->base + SA1111_SKPWM0); | 1004 | writel_relaxed(0, sachip->base + SA1111_SKPWM0); |
973 | sa1111_writel(0, sachip->base + SA1111_SKPWM1); | 1005 | writel_relaxed(0, sachip->base + SA1111_SKPWM1); |
974 | 1006 | ||
975 | base = sachip->base + SA1111_INTC; | 1007 | base = sachip->base + SA1111_INTC; |
976 | save->intpol0 = sa1111_readl(base + SA1111_INTPOL0); | 1008 | save->intpol0 = readl_relaxed(base + SA1111_INTPOL0); |
977 | save->intpol1 = sa1111_readl(base + SA1111_INTPOL1); | 1009 | save->intpol1 = readl_relaxed(base + SA1111_INTPOL1); |
978 | save->inten0 = sa1111_readl(base + SA1111_INTEN0); | 1010 | save->inten0 = readl_relaxed(base + SA1111_INTEN0); |
979 | save->inten1 = sa1111_readl(base + SA1111_INTEN1); | 1011 | save->inten1 = readl_relaxed(base + SA1111_INTEN1); |
980 | save->wakepol0 = sa1111_readl(base + SA1111_WAKEPOL0); | 1012 | save->wakepol0 = readl_relaxed(base + SA1111_WAKEPOL0); |
981 | save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1); | 1013 | save->wakepol1 = readl_relaxed(base + SA1111_WAKEPOL1); |
982 | save->wakeen0 = sa1111_readl(base + SA1111_WAKEEN0); | 1014 | save->wakeen0 = readl_relaxed(base + SA1111_WAKEEN0); |
983 | save->wakeen1 = sa1111_readl(base + SA1111_WAKEEN1); | 1015 | save->wakeen1 = readl_relaxed(base + SA1111_WAKEEN1); |
984 | 1016 | ||
985 | /* | 1017 | /* |
986 | * Disable. | 1018 | * Disable. |
987 | */ | 1019 | */ |
988 | val = sa1111_readl(sachip->base + SA1111_SKCR); | 1020 | val = readl_relaxed(sachip->base + SA1111_SKCR); |
989 | sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR); | 1021 | writel_relaxed(val | SKCR_SLEEP, sachip->base + SA1111_SKCR); |
990 | 1022 | ||
991 | clk_disable(sachip->clk); | 1023 | clk_disable(sachip->clk); |
992 | 1024 | ||
@@ -1023,7 +1055,7 @@ static int sa1111_resume_noirq(struct device *dev) | |||
1023 | * Ensure that the SA1111 is still here. | 1055 | * Ensure that the SA1111 is still here. |
1024 | * FIXME: shouldn't do this here. | 1056 | * FIXME: shouldn't do this here. |
1025 | */ | 1057 | */ |
1026 | id = sa1111_readl(sachip->base + SA1111_SKID); | 1058 | id = readl_relaxed(sachip->base + SA1111_SKID); |
1027 | if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { | 1059 | if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { |
1028 | __sa1111_remove(sachip); | 1060 | __sa1111_remove(sachip); |
1029 | dev_set_drvdata(dev, NULL); | 1061 | dev_set_drvdata(dev, NULL); |
@@ -1047,26 +1079,26 @@ static int sa1111_resume_noirq(struct device *dev) | |||
1047 | */ | 1079 | */ |
1048 | spin_lock_irqsave(&sachip->lock, flags); | 1080 | spin_lock_irqsave(&sachip->lock, flags); |
1049 | 1081 | ||
1050 | sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0); | 1082 | writel_relaxed(0, sachip->base + SA1111_INTC + SA1111_INTEN0); |
1051 | sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1); | 1083 | writel_relaxed(0, sachip->base + SA1111_INTC + SA1111_INTEN1); |
1052 | 1084 | ||
1053 | base = sachip->base; | 1085 | base = sachip->base; |
1054 | sa1111_writel(save->skcr, base + SA1111_SKCR); | 1086 | writel_relaxed(save->skcr, base + SA1111_SKCR); |
1055 | sa1111_writel(save->skpcr, base + SA1111_SKPCR); | 1087 | writel_relaxed(save->skpcr, base + SA1111_SKPCR); |
1056 | sa1111_writel(save->skcdr, base + SA1111_SKCDR); | 1088 | writel_relaxed(save->skcdr, base + SA1111_SKCDR); |
1057 | sa1111_writel(save->skaud, base + SA1111_SKAUD); | 1089 | writel_relaxed(save->skaud, base + SA1111_SKAUD); |
1058 | sa1111_writel(save->skpwm0, base + SA1111_SKPWM0); | 1090 | writel_relaxed(save->skpwm0, base + SA1111_SKPWM0); |
1059 | sa1111_writel(save->skpwm1, base + SA1111_SKPWM1); | 1091 | writel_relaxed(save->skpwm1, base + SA1111_SKPWM1); |
1060 | 1092 | ||
1061 | base = sachip->base + SA1111_INTC; | 1093 | base = sachip->base + SA1111_INTC; |
1062 | sa1111_writel(save->intpol0, base + SA1111_INTPOL0); | 1094 | writel_relaxed(save->intpol0, base + SA1111_INTPOL0); |
1063 | sa1111_writel(save->intpol1, base + SA1111_INTPOL1); | 1095 | writel_relaxed(save->intpol1, base + SA1111_INTPOL1); |
1064 | sa1111_writel(save->inten0, base + SA1111_INTEN0); | 1096 | writel_relaxed(save->inten0, base + SA1111_INTEN0); |
1065 | sa1111_writel(save->inten1, base + SA1111_INTEN1); | 1097 | writel_relaxed(save->inten1, base + SA1111_INTEN1); |
1066 | sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0); | 1098 | writel_relaxed(save->wakepol0, base + SA1111_WAKEPOL0); |
1067 | sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1); | 1099 | writel_relaxed(save->wakepol1, base + SA1111_WAKEPOL1); |
1068 | sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0); | 1100 | writel_relaxed(save->wakeen0, base + SA1111_WAKEEN0); |
1069 | sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1); | 1101 | writel_relaxed(save->wakeen1, base + SA1111_WAKEEN1); |
1070 | 1102 | ||
1071 | spin_unlock_irqrestore(&sachip->lock, flags); | 1103 | spin_unlock_irqrestore(&sachip->lock, flags); |
1072 | 1104 | ||
@@ -1153,7 +1185,7 @@ static unsigned int __sa1111_pll_clock(struct sa1111 *sachip) | |||
1153 | { | 1185 | { |
1154 | unsigned int skcdr, fbdiv, ipdiv, opdiv; | 1186 | unsigned int skcdr, fbdiv, ipdiv, opdiv; |
1155 | 1187 | ||
1156 | skcdr = sa1111_readl(sachip->base + SA1111_SKCDR); | 1188 | skcdr = readl_relaxed(sachip->base + SA1111_SKCDR); |
1157 | 1189 | ||
1158 | fbdiv = (skcdr & 0x007f) + 2; | 1190 | fbdiv = (skcdr & 0x007f) + 2; |
1159 | ipdiv = ((skcdr & 0x0f80) >> 7) + 2; | 1191 | ipdiv = ((skcdr & 0x0f80) >> 7) + 2; |
@@ -1195,13 +1227,13 @@ void sa1111_select_audio_mode(struct sa1111_dev *sadev, int mode) | |||
1195 | 1227 | ||
1196 | spin_lock_irqsave(&sachip->lock, flags); | 1228 | spin_lock_irqsave(&sachip->lock, flags); |
1197 | 1229 | ||
1198 | val = sa1111_readl(sachip->base + SA1111_SKCR); | 1230 | val = readl_relaxed(sachip->base + SA1111_SKCR); |
1199 | if (mode == SA1111_AUDIO_I2S) { | 1231 | if (mode == SA1111_AUDIO_I2S) { |
1200 | val &= ~SKCR_SELAC; | 1232 | val &= ~SKCR_SELAC; |
1201 | } else { | 1233 | } else { |
1202 | val |= SKCR_SELAC; | 1234 | val |= SKCR_SELAC; |
1203 | } | 1235 | } |
1204 | sa1111_writel(val, sachip->base + SA1111_SKCR); | 1236 | writel_relaxed(val, sachip->base + SA1111_SKCR); |
1205 | 1237 | ||
1206 | spin_unlock_irqrestore(&sachip->lock, flags); | 1238 | spin_unlock_irqrestore(&sachip->lock, flags); |
1207 | } | 1239 | } |
@@ -1226,7 +1258,7 @@ int sa1111_set_audio_rate(struct sa1111_dev *sadev, int rate) | |||
1226 | if (div > 128) | 1258 | if (div > 128) |
1227 | div = 128; | 1259 | div = 128; |
1228 | 1260 | ||
1229 | sa1111_writel(div - 1, sachip->base + SA1111_SKAUD); | 1261 | writel_relaxed(div - 1, sachip->base + SA1111_SKAUD); |
1230 | 1262 | ||
1231 | return 0; | 1263 | return 0; |
1232 | } | 1264 | } |
@@ -1244,7 +1276,7 @@ int sa1111_get_audio_rate(struct sa1111_dev *sadev) | |||
1244 | if (sadev->devid != SA1111_DEVID_SAC) | 1276 | if (sadev->devid != SA1111_DEVID_SAC) |
1245 | return -EINVAL; | 1277 | return -EINVAL; |
1246 | 1278 | ||
1247 | div = sa1111_readl(sachip->base + SA1111_SKAUD) + 1; | 1279 | div = readl_relaxed(sachip->base + SA1111_SKAUD) + 1; |
1248 | 1280 | ||
1249 | return __sa1111_pll_clock(sachip) / (256 * div); | 1281 | return __sa1111_pll_clock(sachip) / (256 * div); |
1250 | } | 1282 | } |
@@ -1261,10 +1293,10 @@ void sa1111_set_io_dir(struct sa1111_dev *sadev, | |||
1261 | 1293 | ||
1262 | #define MODIFY_BITS(port, mask, dir) \ | 1294 | #define MODIFY_BITS(port, mask, dir) \ |
1263 | if (mask) { \ | 1295 | if (mask) { \ |
1264 | val = sa1111_readl(port); \ | 1296 | val = readl_relaxed(port); \ |
1265 | val &= ~(mask); \ | 1297 | val &= ~(mask); \ |
1266 | val |= (dir) & (mask); \ | 1298 | val |= (dir) & (mask); \ |
1267 | sa1111_writel(val, port); \ | 1299 | writel_relaxed(val, port); \ |
1268 | } | 1300 | } |
1269 | 1301 | ||
1270 | spin_lock_irqsave(&sachip->lock, flags); | 1302 | spin_lock_irqsave(&sachip->lock, flags); |
@@ -1329,8 +1361,8 @@ int sa1111_enable_device(struct sa1111_dev *sadev) | |||
1329 | 1361 | ||
1330 | if (ret == 0) { | 1362 | if (ret == 0) { |
1331 | spin_lock_irqsave(&sachip->lock, flags); | 1363 | spin_lock_irqsave(&sachip->lock, flags); |
1332 | val = sa1111_readl(sachip->base + SA1111_SKPCR); | 1364 | val = readl_relaxed(sachip->base + SA1111_SKPCR); |
1333 | sa1111_writel(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR); | 1365 | writel_relaxed(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR); |
1334 | spin_unlock_irqrestore(&sachip->lock, flags); | 1366 | spin_unlock_irqrestore(&sachip->lock, flags); |
1335 | } | 1367 | } |
1336 | return ret; | 1368 | return ret; |
@@ -1348,8 +1380,8 @@ void sa1111_disable_device(struct sa1111_dev *sadev) | |||
1348 | unsigned int val; | 1380 | unsigned int val; |
1349 | 1381 | ||
1350 | spin_lock_irqsave(&sachip->lock, flags); | 1382 | spin_lock_irqsave(&sachip->lock, flags); |
1351 | val = sa1111_readl(sachip->base + SA1111_SKPCR); | 1383 | val = readl_relaxed(sachip->base + SA1111_SKPCR); |
1352 | sa1111_writel(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR); | 1384 | writel_relaxed(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR); |
1353 | spin_unlock_irqrestore(&sachip->lock, flags); | 1385 | spin_unlock_irqrestore(&sachip->lock, flags); |
1354 | 1386 | ||
1355 | if (sachip->pdata && sachip->pdata->disable) | 1387 | if (sachip->pdata && sachip->pdata->disable) |
@@ -1359,9 +1391,10 @@ EXPORT_SYMBOL(sa1111_disable_device); | |||
1359 | 1391 | ||
1360 | int sa1111_get_irq(struct sa1111_dev *sadev, unsigned num) | 1392 | int sa1111_get_irq(struct sa1111_dev *sadev, unsigned num) |
1361 | { | 1393 | { |
1362 | if (num >= ARRAY_SIZE(sadev->irq)) | 1394 | struct sa1111 *sachip = sa1111_chip_driver(sadev); |
1395 | if (num >= ARRAY_SIZE(sadev->hwirq)) | ||
1363 | return -EINVAL; | 1396 | return -EINVAL; |
1364 | return sadev->irq[num]; | 1397 | return sa1111_map_irq(sachip, sadev->hwirq[num]); |
1365 | } | 1398 | } |
1366 | EXPORT_SYMBOL_GPL(sa1111_get_irq); | 1399 | EXPORT_SYMBOL_GPL(sa1111_get_irq); |
1367 | 1400 | ||
@@ -1379,36 +1412,6 @@ static int sa1111_match(struct device *_dev, struct device_driver *_drv) | |||
1379 | return !!(dev->devid & drv->devid); | 1412 | return !!(dev->devid & drv->devid); |
1380 | } | 1413 | } |
1381 | 1414 | ||
1382 | static int sa1111_bus_suspend(struct device *dev, pm_message_t state) | ||
1383 | { | ||
1384 | struct sa1111_dev *sadev = to_sa1111_device(dev); | ||
1385 | struct sa1111_driver *drv = SA1111_DRV(dev->driver); | ||
1386 | int ret = 0; | ||
1387 | |||
1388 | if (drv && drv->suspend) | ||
1389 | ret = drv->suspend(sadev, state); | ||
1390 | return ret; | ||
1391 | } | ||
1392 | |||
1393 | static int sa1111_bus_resume(struct device *dev) | ||
1394 | { | ||
1395 | struct sa1111_dev *sadev = to_sa1111_device(dev); | ||
1396 | struct sa1111_driver *drv = SA1111_DRV(dev->driver); | ||
1397 | int ret = 0; | ||
1398 | |||
1399 | if (drv && drv->resume) | ||
1400 | ret = drv->resume(sadev); | ||
1401 | return ret; | ||
1402 | } | ||
1403 | |||
1404 | static void sa1111_bus_shutdown(struct device *dev) | ||
1405 | { | ||
1406 | struct sa1111_driver *drv = SA1111_DRV(dev->driver); | ||
1407 | |||
1408 | if (drv && drv->shutdown) | ||
1409 | drv->shutdown(to_sa1111_device(dev)); | ||
1410 | } | ||
1411 | |||
1412 | static int sa1111_bus_probe(struct device *dev) | 1415 | static int sa1111_bus_probe(struct device *dev) |
1413 | { | 1416 | { |
1414 | struct sa1111_dev *sadev = to_sa1111_device(dev); | 1417 | struct sa1111_dev *sadev = to_sa1111_device(dev); |
@@ -1436,9 +1439,6 @@ struct bus_type sa1111_bus_type = { | |||
1436 | .match = sa1111_match, | 1439 | .match = sa1111_match, |
1437 | .probe = sa1111_bus_probe, | 1440 | .probe = sa1111_bus_probe, |
1438 | .remove = sa1111_bus_remove, | 1441 | .remove = sa1111_bus_remove, |
1439 | .suspend = sa1111_bus_suspend, | ||
1440 | .resume = sa1111_bus_resume, | ||
1441 | .shutdown = sa1111_bus_shutdown, | ||
1442 | }; | 1442 | }; |
1443 | EXPORT_SYMBOL(sa1111_bus_type); | 1443 | EXPORT_SYMBOL(sa1111_bus_type); |
1444 | 1444 | ||
diff --git a/arch/arm/include/asm/exception.h b/arch/arm/include/asm/exception.h index a7273ad9587a..58e039a851af 100644 --- a/arch/arm/include/asm/exception.h +++ b/arch/arm/include/asm/exception.h | |||
@@ -10,11 +10,10 @@ | |||
10 | 10 | ||
11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
12 | 12 | ||
13 | #define __exception __attribute__((section(".exception.text"))) | ||
14 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 13 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
15 | #define __exception_irq_entry __irq_entry | 14 | #define __exception_irq_entry __irq_entry |
16 | #else | 15 | #else |
17 | #define __exception_irq_entry __exception | 16 | #define __exception_irq_entry |
18 | #endif | 17 | #endif |
19 | 18 | ||
20 | #endif /* __ASM_ARM_EXCEPTION_H */ | 19 | #endif /* __ASM_ARM_EXCEPTION_H */ |
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h index 01c3d92624e5..8d1f498e5dd8 100644 --- a/arch/arm/include/asm/glue-cache.h +++ b/arch/arm/include/asm/glue-cache.h | |||
@@ -117,6 +117,10 @@ | |||
117 | # endif | 117 | # endif |
118 | #endif | 118 | #endif |
119 | 119 | ||
120 | #if defined(CONFIG_CACHE_B15_RAC) | ||
121 | # define MULTI_CACHE 1 | ||
122 | #endif | ||
123 | |||
120 | #if defined(CONFIG_CPU_V7M) | 124 | #if defined(CONFIG_CPU_V7M) |
121 | # define MULTI_CACHE 1 | 125 | # define MULTI_CACHE 1 |
122 | #endif | 126 | #endif |
diff --git a/arch/arm/include/asm/hardware/cache-b15-rac.h b/arch/arm/include/asm/hardware/cache-b15-rac.h new file mode 100644 index 000000000000..3d43ec06fd35 --- /dev/null +++ b/arch/arm/include/asm/hardware/cache-b15-rac.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef __ASM_ARM_HARDWARE_CACHE_B15_RAC_H | ||
2 | #define __ASM_ARM_HARDWARE_CACHE_B15_RAC_H | ||
3 | |||
4 | #ifndef __ASSEMBLY__ | ||
5 | |||
6 | void b15_flush_kern_cache_all(void); | ||
7 | |||
8 | #endif | ||
9 | |||
10 | #endif | ||
diff --git a/arch/arm/include/asm/hardware/sa1111.h b/arch/arm/include/asm/hardware/sa1111.h index 0bbf163d1ed3..798e520e8a49 100644 --- a/arch/arm/include/asm/hardware/sa1111.h +++ b/arch/arm/include/asm/hardware/sa1111.h | |||
@@ -16,33 +16,6 @@ | |||
16 | #include <mach/bitfield.h> | 16 | #include <mach/bitfield.h> |
17 | 17 | ||
18 | /* | 18 | /* |
19 | * The SA1111 is always located at virtual 0xf4000000, and is always | ||
20 | * "native" endian. | ||
21 | */ | ||
22 | |||
23 | #define SA1111_VBASE 0xf4000000 | ||
24 | |||
25 | /* Don't use these! */ | ||
26 | #define SA1111_p2v( x ) ((x) - SA1111_BASE + SA1111_VBASE) | ||
27 | #define SA1111_v2p( x ) ((x) - SA1111_VBASE + SA1111_BASE) | ||
28 | |||
29 | #ifndef __ASSEMBLY__ | ||
30 | #define _SA1111(x) ((x) + sa1111->resource.start) | ||
31 | #endif | ||
32 | |||
33 | #define sa1111_writel(val,addr) __raw_writel(val, addr) | ||
34 | #define sa1111_readl(addr) __raw_readl(addr) | ||
35 | |||
36 | /* | ||
37 | * 26 bits of the SA-1110 address bus are available to the SA-1111. | ||
38 | * Use these when feeding target addresses to the DMA engines. | ||
39 | */ | ||
40 | |||
41 | #define SA1111_ADDR_WIDTH (26) | ||
42 | #define SA1111_ADDR_MASK ((1<<SA1111_ADDR_WIDTH)-1) | ||
43 | #define SA1111_DMA_ADDR(x) ((x)&SA1111_ADDR_MASK) | ||
44 | |||
45 | /* | ||
46 | * Don't ask the (SAC) DMA engines to move less than this amount. | 19 | * Don't ask the (SAC) DMA engines to move less than this amount. |
47 | */ | 20 | */ |
48 | 21 | ||
@@ -417,7 +390,7 @@ struct sa1111_dev { | |||
417 | struct resource res; | 390 | struct resource res; |
418 | void __iomem *mapbase; | 391 | void __iomem *mapbase; |
419 | unsigned int skpcr_mask; | 392 | unsigned int skpcr_mask; |
420 | unsigned int irq[6]; | 393 | unsigned int hwirq[6]; |
421 | u64 dma_mask; | 394 | u64 dma_mask; |
422 | }; | 395 | }; |
423 | 396 | ||
@@ -431,9 +404,6 @@ struct sa1111_driver { | |||
431 | unsigned int devid; | 404 | unsigned int devid; |
432 | int (*probe)(struct sa1111_dev *); | 405 | int (*probe)(struct sa1111_dev *); |
433 | int (*remove)(struct sa1111_dev *); | 406 | int (*remove)(struct sa1111_dev *); |
434 | int (*suspend)(struct sa1111_dev *, pm_message_t); | ||
435 | int (*resume)(struct sa1111_dev *); | ||
436 | void (*shutdown)(struct sa1111_dev *); | ||
437 | }; | 407 | }; |
438 | 408 | ||
439 | #define SA1111_DRV(_d) container_of((_d), struct sa1111_driver, drv) | 409 | #define SA1111_DRV(_d) container_of((_d), struct sa1111_driver, drv) |
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 1f54e4e98c1e..496667703693 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h | |||
@@ -88,6 +88,7 @@ | |||
88 | #else /* CONFIG_MMU */ | 88 | #else /* CONFIG_MMU */ |
89 | 89 | ||
90 | #ifndef __ASSEMBLY__ | 90 | #ifndef __ASSEMBLY__ |
91 | extern unsigned long setup_vectors_base(void); | ||
91 | extern unsigned long vectors_base; | 92 | extern unsigned long vectors_base; |
92 | #define VECTORS_BASE vectors_base | 93 | #define VECTORS_BASE vectors_base |
93 | #endif | 94 | #endif |
diff --git a/arch/arm/include/asm/ptdump.h b/arch/arm/include/asm/ptdump.h new file mode 100644 index 000000000000..3ebf9718288d --- /dev/null +++ b/arch/arm/include/asm/ptdump.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* Copyright (C) 2014 ARM Ltd. */ | ||
3 | #ifndef __ASM_PTDUMP_H | ||
4 | #define __ASM_PTDUMP_H | ||
5 | |||
6 | #ifdef CONFIG_ARM_PTDUMP_CORE | ||
7 | |||
8 | #include <linux/mm_types.h> | ||
9 | #include <linux/seq_file.h> | ||
10 | |||
11 | struct addr_marker { | ||
12 | unsigned long start_address; | ||
13 | char *name; | ||
14 | }; | ||
15 | |||
16 | struct ptdump_info { | ||
17 | struct mm_struct *mm; | ||
18 | const struct addr_marker *markers; | ||
19 | unsigned long base_addr; | ||
20 | }; | ||
21 | |||
22 | void ptdump_walk_pgd(struct seq_file *s, struct ptdump_info *info); | ||
23 | #ifdef CONFIG_ARM_PTDUMP_DEBUGFS | ||
24 | int ptdump_debugfs_register(struct ptdump_info *info, const char *name); | ||
25 | #else | ||
26 | static inline int ptdump_debugfs_register(struct ptdump_info *info, | ||
27 | const char *name) | ||
28 | { | ||
29 | return 0; | ||
30 | } | ||
31 | #endif /* CONFIG_ARM_PTDUMP_DEBUGFS */ | ||
32 | |||
33 | void ptdump_check_wx(void); | ||
34 | |||
35 | #endif /* CONFIG_ARM_PTDUMP_CORE */ | ||
36 | |||
37 | #ifdef CONFIG_DEBUG_WX | ||
38 | #define debug_checkwx() ptdump_check_wx() | ||
39 | #else | ||
40 | #define debug_checkwx() do { } while (0) | ||
41 | #endif | ||
42 | |||
43 | #endif /* __ASM_PTDUMP_H */ | ||
diff --git a/arch/arm/include/asm/sections.h b/arch/arm/include/asm/sections.h index 63dfe1f10335..4ceb4f757d4d 100644 --- a/arch/arm/include/asm/sections.h +++ b/arch/arm/include/asm/sections.h | |||
@@ -6,4 +6,25 @@ | |||
6 | 6 | ||
7 | extern char _exiprom[]; | 7 | extern char _exiprom[]; |
8 | 8 | ||
9 | extern char __idmap_text_start[]; | ||
10 | extern char __idmap_text_end[]; | ||
11 | extern char __entry_text_start[]; | ||
12 | extern char __entry_text_end[]; | ||
13 | extern char __hyp_idmap_text_start[]; | ||
14 | extern char __hyp_idmap_text_end[]; | ||
15 | |||
16 | static inline bool in_entry_text(unsigned long addr) | ||
17 | { | ||
18 | return memory_contains(__entry_text_start, __entry_text_end, | ||
19 | (void *)addr, 1); | ||
20 | } | ||
21 | |||
22 | static inline bool in_idmap_text(unsigned long addr) | ||
23 | { | ||
24 | void *a = (void *)addr; | ||
25 | return memory_contains(__idmap_text_start, __idmap_text_end, a, 1) || | ||
26 | memory_contains(__hyp_idmap_text_start, __hyp_idmap_text_end, | ||
27 | a, 1); | ||
28 | } | ||
29 | |||
9 | #endif /* _ASM_ARM_SECTIONS_H */ | 30 | #endif /* _ASM_ARM_SECTIONS_H */ |
diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h index f54a3136aac6..111a1d8a41dd 100644 --- a/arch/arm/include/asm/string.h +++ b/arch/arm/include/asm/string.h | |||
@@ -39,18 +39,4 @@ static inline void *memset64(uint64_t *p, uint64_t v, __kernel_size_t n) | |||
39 | return __memset64(p, v, n * 8, v >> 32); | 39 | return __memset64(p, v, n * 8, v >> 32); |
40 | } | 40 | } |
41 | 41 | ||
42 | extern void __memzero(void *ptr, __kernel_size_t n); | ||
43 | |||
44 | #define memset(p,v,n) \ | ||
45 | ({ \ | ||
46 | void *__p = (p); size_t __n = n; \ | ||
47 | if ((__n) != 0) { \ | ||
48 | if (__builtin_constant_p((v)) && (v) == 0) \ | ||
49 | __memzero((__p),(__n)); \ | ||
50 | else \ | ||
51 | memset((__p),(v),(__n)); \ | ||
52 | } \ | ||
53 | (__p); \ | ||
54 | }) | ||
55 | |||
56 | #endif | 42 | #endif |
diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h index f9a6c5fc3fd1..a00288d75ee6 100644 --- a/arch/arm/include/asm/traps.h +++ b/arch/arm/include/asm/traps.h | |||
@@ -28,18 +28,6 @@ static inline int __in_irqentry_text(unsigned long ptr) | |||
28 | ptr < (unsigned long)&__irqentry_text_end; | 28 | ptr < (unsigned long)&__irqentry_text_end; |
29 | } | 29 | } |
30 | 30 | ||
31 | static inline int in_exception_text(unsigned long ptr) | ||
32 | { | ||
33 | extern char __exception_text_start[]; | ||
34 | extern char __exception_text_end[]; | ||
35 | int in; | ||
36 | |||
37 | in = ptr >= (unsigned long)&__exception_text_start && | ||
38 | ptr < (unsigned long)&__exception_text_end; | ||
39 | |||
40 | return in ? : __in_irqentry_text(ptr); | ||
41 | } | ||
42 | |||
43 | extern void __init early_trap_init(void *); | 31 | extern void __init early_trap_init(void *); |
44 | extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); | 32 | extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); |
45 | extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs); | 33 | extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs); |
diff --git a/arch/arm/include/asm/unified.h b/arch/arm/include/asm/unified.h index a91ae499614c..2c3b952be63e 100644 --- a/arch/arm/include/asm/unified.h +++ b/arch/arm/include/asm/unified.h | |||
@@ -20,8 +20,10 @@ | |||
20 | #ifndef __ASM_UNIFIED_H | 20 | #ifndef __ASM_UNIFIED_H |
21 | #define __ASM_UNIFIED_H | 21 | #define __ASM_UNIFIED_H |
22 | 22 | ||
23 | #if defined(__ASSEMBLY__) && defined(CONFIG_ARM_ASM_UNIFIED) | 23 | #if defined(__ASSEMBLY__) |
24 | .syntax unified | 24 | .syntax unified |
25 | #else | ||
26 | __asm__(".syntax unified"); | ||
25 | #endif | 27 | #endif |
26 | 28 | ||
27 | #ifdef CONFIG_CPU_V7M | 29 | #ifdef CONFIG_CPU_V7M |
@@ -64,77 +66,4 @@ | |||
64 | 66 | ||
65 | #endif /* CONFIG_THUMB2_KERNEL */ | 67 | #endif /* CONFIG_THUMB2_KERNEL */ |
66 | 68 | ||
67 | #ifndef CONFIG_ARM_ASM_UNIFIED | ||
68 | |||
69 | /* | ||
70 | * If the unified assembly syntax isn't used (in ARM mode), these | ||
71 | * macros expand to an empty string | ||
72 | */ | ||
73 | #ifdef __ASSEMBLY__ | ||
74 | .macro it, cond | ||
75 | .endm | ||
76 | .macro itt, cond | ||
77 | .endm | ||
78 | .macro ite, cond | ||
79 | .endm | ||
80 | .macro ittt, cond | ||
81 | .endm | ||
82 | .macro itte, cond | ||
83 | .endm | ||
84 | .macro itet, cond | ||
85 | .endm | ||
86 | .macro itee, cond | ||
87 | .endm | ||
88 | .macro itttt, cond | ||
89 | .endm | ||
90 | .macro ittte, cond | ||
91 | .endm | ||
92 | .macro ittet, cond | ||
93 | .endm | ||
94 | .macro ittee, cond | ||
95 | .endm | ||
96 | .macro itett, cond | ||
97 | .endm | ||
98 | .macro itete, cond | ||
99 | .endm | ||
100 | .macro iteet, cond | ||
101 | .endm | ||
102 | .macro iteee, cond | ||
103 | .endm | ||
104 | #else /* !__ASSEMBLY__ */ | ||
105 | __asm__( | ||
106 | " .macro it, cond\n" | ||
107 | " .endm\n" | ||
108 | " .macro itt, cond\n" | ||
109 | " .endm\n" | ||
110 | " .macro ite, cond\n" | ||
111 | " .endm\n" | ||
112 | " .macro ittt, cond\n" | ||
113 | " .endm\n" | ||
114 | " .macro itte, cond\n" | ||
115 | " .endm\n" | ||
116 | " .macro itet, cond\n" | ||
117 | " .endm\n" | ||
118 | " .macro itee, cond\n" | ||
119 | " .endm\n" | ||
120 | " .macro itttt, cond\n" | ||
121 | " .endm\n" | ||
122 | " .macro ittte, cond\n" | ||
123 | " .endm\n" | ||
124 | " .macro ittet, cond\n" | ||
125 | " .endm\n" | ||
126 | " .macro ittee, cond\n" | ||
127 | " .endm\n" | ||
128 | " .macro itett, cond\n" | ||
129 | " .endm\n" | ||
130 | " .macro itete, cond\n" | ||
131 | " .endm\n" | ||
132 | " .macro iteet, cond\n" | ||
133 | " .endm\n" | ||
134 | " .macro iteee, cond\n" | ||
135 | " .endm\n"); | ||
136 | #endif /* __ASSEMBLY__ */ | ||
137 | |||
138 | #endif /* CONFIG_ARM_ASM_UNIFIED */ | ||
139 | |||
140 | #endif /* !__ASM_UNIFIED_H */ | 69 | #endif /* !__ASM_UNIFIED_H */ |
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 5266fd9ad6b4..783fbb4de5f9 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c | |||
@@ -92,7 +92,6 @@ EXPORT_SYMBOL(__memset64); | |||
92 | EXPORT_SYMBOL(memcpy); | 92 | EXPORT_SYMBOL(memcpy); |
93 | EXPORT_SYMBOL(memmove); | 93 | EXPORT_SYMBOL(memmove); |
94 | EXPORT_SYMBOL(memchr); | 94 | EXPORT_SYMBOL(memchr); |
95 | EXPORT_SYMBOL(__memzero); | ||
96 | 95 | ||
97 | EXPORT_SYMBOL(mmioset); | 96 | EXPORT_SYMBOL(mmioset); |
98 | EXPORT_SYMBOL(mmiocpy); | 97 | EXPORT_SYMBOL(mmiocpy); |
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index fbc707626b3e..1752033b0070 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -82,11 +82,7 @@ | |||
82 | #endif | 82 | #endif |
83 | .endm | 83 | .endm |
84 | 84 | ||
85 | #ifdef CONFIG_KPROBES | 85 | .section .entry.text,"ax",%progbits |
86 | .section .kprobes.text,"ax",%progbits | ||
87 | #else | ||
88 | .text | ||
89 | #endif | ||
90 | 86 | ||
91 | /* | 87 | /* |
92 | * Invalid mode handlers | 88 | * Invalid mode handlers |
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index e655dcd0a933..3c4f88701f22 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -37,6 +37,7 @@ saved_pc .req lr | |||
37 | #define TRACE(x...) | 37 | #define TRACE(x...) |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | .section .entry.text,"ax",%progbits | ||
40 | .align 5 | 41 | .align 5 |
41 | #if !(IS_ENABLED(CONFIG_TRACE_IRQFLAGS) || IS_ENABLED(CONFIG_CONTEXT_TRACKING)) | 42 | #if !(IS_ENABLED(CONFIG_TRACE_IRQFLAGS) || IS_ENABLED(CONFIG_CONTEXT_TRACKING)) |
42 | /* | 43 | /* |
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index 21dde771a7dd..6e0375e7db05 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S | |||
@@ -105,8 +105,9 @@ __mmap_switched: | |||
105 | ARM( ldmia r4!, {r0, r1, sp} ) | 105 | ARM( ldmia r4!, {r0, r1, sp} ) |
106 | THUMB( ldmia r4!, {r0, r1, r3} ) | 106 | THUMB( ldmia r4!, {r0, r1, r3} ) |
107 | THUMB( mov sp, r3 ) | 107 | THUMB( mov sp, r3 ) |
108 | sub r1, r1, r0 | 108 | sub r2, r1, r0 |
109 | bl __memzero @ clear .bss | 109 | mov r1, #0 |
110 | bl memset @ clear .bss | ||
110 | 111 | ||
111 | ldmia r4, {r0, r1, r2, r3} | 112 | ldmia r4, {r0, r1, r2, r3} |
112 | str r9, [r0] @ Save processor ID | 113 | str r9, [r0] @ Save processor ID |
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index af2a7f1e3103..629e25152c0d 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c | |||
@@ -44,17 +44,17 @@ static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]); | |||
44 | static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]); | 44 | static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]); |
45 | 45 | ||
46 | /* Number of BRP/WRP registers on this CPU. */ | 46 | /* Number of BRP/WRP registers on this CPU. */ |
47 | static int core_num_brps; | 47 | static int core_num_brps __ro_after_init; |
48 | static int core_num_wrps; | 48 | static int core_num_wrps __ro_after_init; |
49 | 49 | ||
50 | /* Debug architecture version. */ | 50 | /* Debug architecture version. */ |
51 | static u8 debug_arch; | 51 | static u8 debug_arch __ro_after_init; |
52 | 52 | ||
53 | /* Does debug architecture support OS Save and Restore? */ | 53 | /* Does debug architecture support OS Save and Restore? */ |
54 | static bool has_ossr; | 54 | static bool has_ossr __ro_after_init; |
55 | 55 | ||
56 | /* Maximum supported watchpoint length. */ | 56 | /* Maximum supported watchpoint length. */ |
57 | static u8 max_watchpoint_len; | 57 | static u8 max_watchpoint_len __ro_after_init; |
58 | 58 | ||
59 | #define READ_WB_REG_CASE(OP2, M, VAL) \ | 59 | #define READ_WB_REG_CASE(OP2, M, VAL) \ |
60 | case ((OP2 << 4) + M): \ | 60 | case ((OP2 << 4) + M): \ |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index b4fbf00ee4ad..2da087926ebe 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -379,6 +379,9 @@ asmlinkage void secondary_start_kernel(void) | |||
379 | 379 | ||
380 | cpu_init(); | 380 | cpu_init(); |
381 | 381 | ||
382 | #ifndef CONFIG_MMU | ||
383 | setup_vectors_base(); | ||
384 | #endif | ||
382 | pr_debug("CPU%u: Booted secondary processor\n", cpu); | 385 | pr_debug("CPU%u: Booted secondary processor\n", cpu); |
383 | 386 | ||
384 | preempt_disable(); | 387 | preempt_disable(); |
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index 65228bf4c6df..a56e7c856ab5 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <linux/sched/debug.h> | 3 | #include <linux/sched/debug.h> |
4 | #include <linux/stacktrace.h> | 4 | #include <linux/stacktrace.h> |
5 | 5 | ||
6 | #include <asm/sections.h> | ||
6 | #include <asm/stacktrace.h> | 7 | #include <asm/stacktrace.h> |
7 | #include <asm/traps.h> | 8 | #include <asm/traps.h> |
8 | 9 | ||
@@ -63,7 +64,6 @@ EXPORT_SYMBOL(walk_stackframe); | |||
63 | #ifdef CONFIG_STACKTRACE | 64 | #ifdef CONFIG_STACKTRACE |
64 | struct stack_trace_data { | 65 | struct stack_trace_data { |
65 | struct stack_trace *trace; | 66 | struct stack_trace *trace; |
66 | unsigned long last_pc; | ||
67 | unsigned int no_sched_functions; | 67 | unsigned int no_sched_functions; |
68 | unsigned int skip; | 68 | unsigned int skip; |
69 | }; | 69 | }; |
@@ -87,16 +87,7 @@ static int save_trace(struct stackframe *frame, void *d) | |||
87 | if (trace->nr_entries >= trace->max_entries) | 87 | if (trace->nr_entries >= trace->max_entries) |
88 | return 1; | 88 | return 1; |
89 | 89 | ||
90 | /* | 90 | if (!in_entry_text(frame->pc)) |
91 | * in_exception_text() is designed to test if the PC is one of | ||
92 | * the functions which has an exception stack above it, but | ||
93 | * unfortunately what is in frame->pc is the return LR value, | ||
94 | * not the saved PC value. So, we need to track the previous | ||
95 | * frame PC value when doing this. | ||
96 | */ | ||
97 | addr = data->last_pc; | ||
98 | data->last_pc = frame->pc; | ||
99 | if (!in_exception_text(addr)) | ||
100 | return 0; | 91 | return 0; |
101 | 92 | ||
102 | regs = (struct pt_regs *)frame->sp; | 93 | regs = (struct pt_regs *)frame->sp; |
@@ -114,7 +105,6 @@ static noinline void __save_stack_trace(struct task_struct *tsk, | |||
114 | struct stackframe frame; | 105 | struct stackframe frame; |
115 | 106 | ||
116 | data.trace = trace; | 107 | data.trace = trace; |
117 | data.last_pc = ULONG_MAX; | ||
118 | data.skip = trace->skip; | 108 | data.skip = trace->skip; |
119 | data.no_sched_functions = nosched; | 109 | data.no_sched_functions = nosched; |
120 | 110 | ||
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 3e26c6f7a191..5e3633c24e63 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -72,7 +72,7 @@ void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long | |||
72 | printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); | 72 | printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); |
73 | #endif | 73 | #endif |
74 | 74 | ||
75 | if (in_exception_text(where)) | 75 | if (in_entry_text(from)) |
76 | dump_mem("", "Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs)); | 76 | dump_mem("", "Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs)); |
77 | } | 77 | } |
78 | 78 | ||
@@ -433,7 +433,7 @@ static int call_undef_hook(struct pt_regs *regs, unsigned int instr) | |||
433 | return fn ? fn(regs, instr) : 1; | 433 | return fn ? fn(regs, instr) : 1; |
434 | } | 434 | } |
435 | 435 | ||
436 | asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | 436 | asmlinkage void do_undefinstr(struct pt_regs *regs) |
437 | { | 437 | { |
438 | unsigned int instr; | 438 | unsigned int instr; |
439 | siginfo_t info; | 439 | siginfo_t info; |
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S index ec4b3f94ad80..12b87591eb7c 100644 --- a/arch/arm/kernel/vmlinux-xip.lds.S +++ b/arch/arm/kernel/vmlinux-xip.lds.S | |||
@@ -96,9 +96,9 @@ SECTIONS | |||
96 | .text : { /* Real text segment */ | 96 | .text : { /* Real text segment */ |
97 | _stext = .; /* Text and read-only data */ | 97 | _stext = .; /* Text and read-only data */ |
98 | IDMAP_TEXT | 98 | IDMAP_TEXT |
99 | __exception_text_start = .; | 99 | __entry_text_start = .; |
100 | *(.exception.text) | 100 | *(.entry.text) |
101 | __exception_text_end = .; | 101 | __entry_text_end = .; |
102 | IRQENTRY_TEXT | 102 | IRQENTRY_TEXT |
103 | TEXT_TEXT | 103 | TEXT_TEXT |
104 | SCHED_TEXT | 104 | SCHED_TEXT |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index ee53f6518872..84a1ae3ce46e 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -105,9 +105,9 @@ SECTIONS | |||
105 | .text : { /* Real text segment */ | 105 | .text : { /* Real text segment */ |
106 | _stext = .; /* Text and read-only data */ | 106 | _stext = .; /* Text and read-only data */ |
107 | IDMAP_TEXT | 107 | IDMAP_TEXT |
108 | __exception_text_start = .; | 108 | __entry_text_start = .; |
109 | *(.exception.text) | 109 | *(.entry.text) |
110 | __exception_text_end = .; | 110 | __entry_text_end = .; |
111 | IRQENTRY_TEXT | 111 | IRQENTRY_TEXT |
112 | SOFTIRQENTRY_TEXT | 112 | SOFTIRQENTRY_TEXT |
113 | TEXT_TEXT | 113 | TEXT_TEXT |
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 4cb0b9624d8f..ad25fd1872c7 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile | |||
@@ -8,7 +8,7 @@ | |||
8 | lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \ | 8 | lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \ |
9 | csumpartialcopy.o csumpartialcopyuser.o clearbit.o \ | 9 | csumpartialcopy.o csumpartialcopyuser.o clearbit.o \ |
10 | delay.o delay-loop.o findbit.o memchr.o memcpy.o \ | 10 | delay.o delay-loop.o findbit.o memchr.o memcpy.o \ |
11 | memmove.o memset.o memzero.o setbit.o \ | 11 | memmove.o memset.o setbit.o \ |
12 | strchr.o strrchr.o \ | 12 | strchr.o strrchr.o \ |
13 | testchangebit.o testclearbit.o testsetbit.o \ | 13 | testchangebit.o testclearbit.o testsetbit.o \ |
14 | ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ | 14 | ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ |
diff --git a/arch/arm/lib/memzero.S b/arch/arm/lib/memzero.S deleted file mode 100644 index 0eded952e089..000000000000 --- a/arch/arm/lib/memzero.S +++ /dev/null | |||
@@ -1,137 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/lib/memzero.S | ||
3 | * | ||
4 | * Copyright (C) 1995-2000 Russell King | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/linkage.h> | ||
11 | #include <asm/assembler.h> | ||
12 | #include <asm/unwind.h> | ||
13 | |||
14 | .text | ||
15 | .align 5 | ||
16 | .word 0 | ||
17 | /* | ||
18 | * Align the pointer in r0. r3 contains the number of bytes that we are | ||
19 | * mis-aligned by, and r1 is the number of bytes. If r1 < 4, then we | ||
20 | * don't bother; we use byte stores instead. | ||
21 | */ | ||
22 | UNWIND( .fnstart ) | ||
23 | 1: subs r1, r1, #4 @ 1 do we have enough | ||
24 | blt 5f @ 1 bytes to align with? | ||
25 | cmp r3, #2 @ 1 | ||
26 | strltb r2, [r0], #1 @ 1 | ||
27 | strleb r2, [r0], #1 @ 1 | ||
28 | strb r2, [r0], #1 @ 1 | ||
29 | add r1, r1, r3 @ 1 (r1 = r1 - (4 - r3)) | ||
30 | /* | ||
31 | * The pointer is now aligned and the length is adjusted. Try doing the | ||
32 | * memzero again. | ||
33 | */ | ||
34 | |||
35 | ENTRY(__memzero) | ||
36 | mov r2, #0 @ 1 | ||
37 | ands r3, r0, #3 @ 1 unaligned? | ||
38 | bne 1b @ 1 | ||
39 | /* | ||
40 | * r3 = 0, and we know that the pointer in r0 is aligned to a word boundary. | ||
41 | */ | ||
42 | cmp r1, #16 @ 1 we can skip this chunk if we | ||
43 | blt 4f @ 1 have < 16 bytes | ||
44 | |||
45 | #if ! CALGN(1)+0 | ||
46 | |||
47 | /* | ||
48 | * We need an extra register for this loop - save the return address and | ||
49 | * use the LR | ||
50 | */ | ||
51 | str lr, [sp, #-4]! @ 1 | ||
52 | UNWIND( .fnend ) | ||
53 | UNWIND( .fnstart ) | ||
54 | UNWIND( .save {lr} ) | ||
55 | mov ip, r2 @ 1 | ||
56 | mov lr, r2 @ 1 | ||
57 | |||
58 | 3: subs r1, r1, #64 @ 1 write 32 bytes out per loop | ||
59 | stmgeia r0!, {r2, r3, ip, lr} @ 4 | ||
60 | stmgeia r0!, {r2, r3, ip, lr} @ 4 | ||
61 | stmgeia r0!, {r2, r3, ip, lr} @ 4 | ||
62 | stmgeia r0!, {r2, r3, ip, lr} @ 4 | ||
63 | bgt 3b @ 1 | ||
64 | ldmeqfd sp!, {pc} @ 1/2 quick exit | ||
65 | /* | ||
66 | * No need to correct the count; we're only testing bits from now on | ||
67 | */ | ||
68 | tst r1, #32 @ 1 | ||
69 | stmneia r0!, {r2, r3, ip, lr} @ 4 | ||
70 | stmneia r0!, {r2, r3, ip, lr} @ 4 | ||
71 | tst r1, #16 @ 1 16 bytes or more? | ||
72 | stmneia r0!, {r2, r3, ip, lr} @ 4 | ||
73 | ldr lr, [sp], #4 @ 1 | ||
74 | UNWIND( .fnend ) | ||
75 | |||
76 | #else | ||
77 | |||
78 | /* | ||
79 | * This version aligns the destination pointer in order to write | ||
80 | * whole cache lines at once. | ||
81 | */ | ||
82 | |||
83 | stmfd sp!, {r4-r7, lr} | ||
84 | UNWIND( .fnend ) | ||
85 | UNWIND( .fnstart ) | ||
86 | UNWIND( .save {r4-r7, lr} ) | ||
87 | mov r4, r2 | ||
88 | mov r5, r2 | ||
89 | mov r6, r2 | ||
90 | mov r7, r2 | ||
91 | mov ip, r2 | ||
92 | mov lr, r2 | ||
93 | |||
94 | cmp r1, #96 | ||
95 | andgts ip, r0, #31 | ||
96 | ble 3f | ||
97 | |||
98 | rsb ip, ip, #32 | ||
99 | sub r1, r1, ip | ||
100 | movs ip, ip, lsl #(32 - 4) | ||
101 | stmcsia r0!, {r4, r5, r6, r7} | ||
102 | stmmiia r0!, {r4, r5} | ||
103 | movs ip, ip, lsl #2 | ||
104 | strcs r2, [r0], #4 | ||
105 | |||
106 | 3: subs r1, r1, #64 | ||
107 | stmgeia r0!, {r2-r7, ip, lr} | ||
108 | stmgeia r0!, {r2-r7, ip, lr} | ||
109 | bgt 3b | ||
110 | ldmeqfd sp!, {r4-r7, pc} | ||
111 | |||
112 | tst r1, #32 | ||
113 | stmneia r0!, {r2-r7, ip, lr} | ||
114 | tst r1, #16 | ||
115 | stmneia r0!, {r4-r7} | ||
116 | ldmfd sp!, {r4-r7, lr} | ||
117 | UNWIND( .fnend ) | ||
118 | |||
119 | #endif | ||
120 | |||
121 | UNWIND( .fnstart ) | ||
122 | 4: tst r1, #8 @ 1 8 bytes or more? | ||
123 | stmneia r0!, {r2, r3} @ 2 | ||
124 | tst r1, #4 @ 1 4 bytes or more? | ||
125 | strne r2, [r0], #4 @ 1 | ||
126 | /* | ||
127 | * When we get here, we've got less than 4 bytes to zero. We | ||
128 | * may have an unaligned pointer as well. | ||
129 | */ | ||
130 | 5: tst r1, #2 @ 1 2 bytes or more? | ||
131 | strneb r2, [r0], #1 @ 1 | ||
132 | strneb r2, [r0], #1 @ 1 | ||
133 | tst r1, #1 @ 1 a byte left over | ||
134 | strneb r2, [r0], #1 @ 1 | ||
135 | ret lr @ 1 | ||
136 | UNWIND( .fnend ) | ||
137 | ENDPROC(__memzero) | ||
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig index 36e3c79f4973..07df3a59b13f 100644 --- a/arch/arm/mach-sa1100/Kconfig +++ b/arch/arm/mach-sa1100/Kconfig | |||
@@ -5,6 +5,7 @@ menu "SA11x0 Implementations" | |||
5 | config SA1100_ASSABET | 5 | config SA1100_ASSABET |
6 | bool "Assabet" | 6 | bool "Assabet" |
7 | select ARM_SA1110_CPUFREQ | 7 | select ARM_SA1110_CPUFREQ |
8 | select GPIO_REG | ||
8 | help | 9 | help |
9 | Say Y here if you are using the Intel(R) StrongARM(R) SA-1110 | 10 | Say Y here if you are using the Intel(R) StrongARM(R) SA-1110 |
10 | Microprocessor Development Board (also known as the Assabet). | 11 | Microprocessor Development Board (also known as the Assabet). |
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index d28ecb9ef172..f68241d995f2 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
16 | #include <linux/gpio/gpio-reg.h> | ||
16 | #include <linux/ioport.h> | 17 | #include <linux/ioport.h> |
17 | #include <linux/platform_data/sa11x0-serial.h> | 18 | #include <linux/platform_data/sa11x0-serial.h> |
18 | #include <linux/serial_core.h> | 19 | #include <linux/serial_core.h> |
@@ -61,20 +62,45 @@ | |||
61 | unsigned long SCR_value = ASSABET_SCR_INIT; | 62 | unsigned long SCR_value = ASSABET_SCR_INIT; |
62 | EXPORT_SYMBOL(SCR_value); | 63 | EXPORT_SYMBOL(SCR_value); |
63 | 64 | ||
64 | static unsigned long BCR_value = ASSABET_BCR_DB1110; | 65 | static struct gpio_chip *assabet_bcr_gc; |
66 | |||
67 | static const char *assabet_names[] = { | ||
68 | "cf_pwr", "cf_gfx_reset", "nsoft_reset", "irda_fsel", | ||
69 | "irda_md0", "irda_md1", "stereo_loopback", "ncf_bus_on", | ||
70 | "audio_pwr_on", "light_pwr_on", "lcd16data", "lcd_pwr_on", | ||
71 | "rs232_on", "nred_led", "ngreen_led", "vib_on", | ||
72 | "com_dtr", "com_rts", "radio_wake_mod", "i2c_enab", | ||
73 | "tvir_enab", "qmute", "radio_pwr_on", "spkr_off", | ||
74 | "rs232_valid", "com_dcd", "com_cts", "com_dsr", | ||
75 | "radio_cts", "radio_dsr", "radio_dcd", "radio_ri", | ||
76 | }; | ||
65 | 77 | ||
78 | /* The old deprecated interface */ | ||
66 | void ASSABET_BCR_frob(unsigned int mask, unsigned int val) | 79 | void ASSABET_BCR_frob(unsigned int mask, unsigned int val) |
67 | { | 80 | { |
68 | unsigned long flags; | 81 | unsigned long m = mask, v = val; |
69 | 82 | ||
70 | local_irq_save(flags); | 83 | assabet_bcr_gc->set_multiple(assabet_bcr_gc, &m, &v); |
71 | BCR_value = (BCR_value & ~mask) | val; | ||
72 | ASSABET_BCR = BCR_value; | ||
73 | local_irq_restore(flags); | ||
74 | } | 84 | } |
75 | |||
76 | EXPORT_SYMBOL(ASSABET_BCR_frob); | 85 | EXPORT_SYMBOL(ASSABET_BCR_frob); |
77 | 86 | ||
87 | static int __init assabet_init_gpio(void __iomem *reg, u32 def_val) | ||
88 | { | ||
89 | struct gpio_chip *gc; | ||
90 | |||
91 | writel_relaxed(def_val, reg); | ||
92 | |||
93 | gc = gpio_reg_init(NULL, reg, -1, 32, "assabet", 0xff000000, def_val, | ||
94 | assabet_names, NULL, NULL); | ||
95 | |||
96 | if (IS_ERR(gc)) | ||
97 | return PTR_ERR(gc); | ||
98 | |||
99 | assabet_bcr_gc = gc; | ||
100 | |||
101 | return gc->base; | ||
102 | } | ||
103 | |||
78 | /* | 104 | /* |
79 | * The codec reset goes to three devices, so we need to release | 105 | * The codec reset goes to three devices, so we need to release |
80 | * the rest when any one of these requests it. However, that | 106 | * the rest when any one of these requests it. However, that |
@@ -146,7 +172,7 @@ static void adv7171_write(unsigned reg, unsigned val) | |||
146 | unsigned gpdr = GPDR; | 172 | unsigned gpdr = GPDR; |
147 | unsigned gplr = GPLR; | 173 | unsigned gplr = GPLR; |
148 | 174 | ||
149 | ASSABET_BCR = BCR_value | ASSABET_BCR_AUDIO_ON; | 175 | ASSABET_BCR_frob(ASSABET_BCR_AUDIO_ON, ASSABET_BCR_AUDIO_ON); |
150 | udelay(100); | 176 | udelay(100); |
151 | 177 | ||
152 | GPCR = SDA | SCK | MOD; /* clear L3 mode to ensure UDA1341 doesn't respond */ | 178 | GPCR = SDA | SCK | MOD; /* clear L3 mode to ensure UDA1341 doesn't respond */ |
@@ -457,14 +483,6 @@ static void __init assabet_init(void) | |||
457 | sa11x0_ppc_configure_mcp(); | 483 | sa11x0_ppc_configure_mcp(); |
458 | 484 | ||
459 | if (machine_has_neponset()) { | 485 | if (machine_has_neponset()) { |
460 | /* | ||
461 | * Angel sets this, but other bootloaders may not. | ||
462 | * | ||
463 | * This must precede any driver calls to BCR_set() | ||
464 | * or BCR_clear(). | ||
465 | */ | ||
466 | ASSABET_BCR = BCR_value = ASSABET_BCR_DB1111; | ||
467 | |||
468 | #ifndef CONFIG_ASSABET_NEPONSET | 486 | #ifndef CONFIG_ASSABET_NEPONSET |
469 | printk( "Warning: Neponset detected but full support " | 487 | printk( "Warning: Neponset detected but full support " |
470 | "hasn't been configured in the kernel\n" ); | 488 | "hasn't been configured in the kernel\n" ); |
@@ -748,12 +766,31 @@ static int __init assabet_leds_init(void) | |||
748 | fs_initcall(assabet_leds_init); | 766 | fs_initcall(assabet_leds_init); |
749 | #endif | 767 | #endif |
750 | 768 | ||
769 | void __init assabet_init_irq(void) | ||
770 | { | ||
771 | u32 def_val; | ||
772 | |||
773 | sa1100_init_irq(); | ||
774 | |||
775 | if (machine_has_neponset()) | ||
776 | def_val = ASSABET_BCR_DB1111; | ||
777 | else | ||
778 | def_val = ASSABET_BCR_DB1110; | ||
779 | |||
780 | /* | ||
781 | * Angel sets this, but other bootloaders may not. | ||
782 | * | ||
783 | * This must precede any driver calls to BCR_set() or BCR_clear(). | ||
784 | */ | ||
785 | assabet_init_gpio((void *)&ASSABET_BCR, def_val); | ||
786 | } | ||
787 | |||
751 | MACHINE_START(ASSABET, "Intel-Assabet") | 788 | MACHINE_START(ASSABET, "Intel-Assabet") |
752 | .atag_offset = 0x100, | 789 | .atag_offset = 0x100, |
753 | .fixup = fixup_assabet, | 790 | .fixup = fixup_assabet, |
754 | .map_io = assabet_map_io, | 791 | .map_io = assabet_map_io, |
755 | .nr_irqs = SA1100_NR_IRQS, | 792 | .nr_irqs = SA1100_NR_IRQS, |
756 | .init_irq = sa1100_init_irq, | 793 | .init_irq = assabet_init_irq, |
757 | .init_time = sa1100_timer_init, | 794 | .init_time = sa1100_timer_init, |
758 | .init_machine = assabet_init, | 795 | .init_machine = assabet_init, |
759 | .init_late = sa11x0_init_late, | 796 | .init_late = sa11x0_init_late, |
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c index a61a2432766b..b1823f445358 100644 --- a/arch/arm/mach-sa1100/neponset.c +++ b/arch/arm/mach-sa1100/neponset.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * linux/arch/arm/mach-sa1100/neponset.c | 3 | * linux/arch/arm/mach-sa1100/neponset.c |
4 | */ | 4 | */ |
5 | #include <linux/err.h> | 5 | #include <linux/err.h> |
6 | #include <linux/gpio/driver.h> | ||
7 | #include <linux/gpio/gpio-reg.h> | ||
6 | #include <linux/init.h> | 8 | #include <linux/init.h> |
7 | #include <linux/ioport.h> | 9 | #include <linux/ioport.h> |
8 | #include <linux/irq.h> | 10 | #include <linux/irq.h> |
@@ -45,10 +47,13 @@ | |||
45 | #define IRR_USAR (1 << 1) | 47 | #define IRR_USAR (1 << 1) |
46 | #define IRR_SA1111 (1 << 2) | 48 | #define IRR_SA1111 (1 << 2) |
47 | 49 | ||
50 | #define NCR_NGPIO 7 | ||
51 | |||
48 | #define MDM_CTL0_RTS1 (1 << 0) | 52 | #define MDM_CTL0_RTS1 (1 << 0) |
49 | #define MDM_CTL0_DTR1 (1 << 1) | 53 | #define MDM_CTL0_DTR1 (1 << 1) |
50 | #define MDM_CTL0_RTS2 (1 << 2) | 54 | #define MDM_CTL0_RTS2 (1 << 2) |
51 | #define MDM_CTL0_DTR2 (1 << 3) | 55 | #define MDM_CTL0_DTR2 (1 << 3) |
56 | #define MDM_CTL0_NGPIO 4 | ||
52 | 57 | ||
53 | #define MDM_CTL1_CTS1 (1 << 0) | 58 | #define MDM_CTL1_CTS1 (1 << 0) |
54 | #define MDM_CTL1_DSR1 (1 << 1) | 59 | #define MDM_CTL1_DSR1 (1 << 1) |
@@ -56,80 +61,87 @@ | |||
56 | #define MDM_CTL1_CTS2 (1 << 3) | 61 | #define MDM_CTL1_CTS2 (1 << 3) |
57 | #define MDM_CTL1_DSR2 (1 << 4) | 62 | #define MDM_CTL1_DSR2 (1 << 4) |
58 | #define MDM_CTL1_DCD2 (1 << 5) | 63 | #define MDM_CTL1_DCD2 (1 << 5) |
64 | #define MDM_CTL1_NGPIO 6 | ||
59 | 65 | ||
60 | #define AUD_SEL_1341 (1 << 0) | 66 | #define AUD_SEL_1341 (1 << 0) |
61 | #define AUD_MUTE_1341 (1 << 1) | 67 | #define AUD_MUTE_1341 (1 << 1) |
68 | #define AUD_NGPIO 2 | ||
62 | 69 | ||
63 | extern void sa1110_mb_disable(void); | 70 | extern void sa1110_mb_disable(void); |
64 | 71 | ||
72 | #define to_neponset_gpio_chip(x) container_of(x, struct neponset_gpio_chip, gc) | ||
73 | |||
74 | static const char *neponset_ncr_names[] = { | ||
75 | "gp01_off", "tp_power", "ms_power", "enet_osc", | ||
76 | "spi_kb_wk_up", "a0vpp", "a1vpp" | ||
77 | }; | ||
78 | |||
79 | static const char *neponset_mdmctl0_names[] = { | ||
80 | "rts3", "dtr3", "rts1", "dtr1", | ||
81 | }; | ||
82 | |||
83 | static const char *neponset_mdmctl1_names[] = { | ||
84 | "cts3", "dsr3", "dcd3", "cts1", "dsr1", "dcd1" | ||
85 | }; | ||
86 | |||
87 | static const char *neponset_aud_names[] = { | ||
88 | "sel_1341", "mute_1341", | ||
89 | }; | ||
90 | |||
65 | struct neponset_drvdata { | 91 | struct neponset_drvdata { |
66 | void __iomem *base; | 92 | void __iomem *base; |
67 | struct platform_device *sa1111; | 93 | struct platform_device *sa1111; |
68 | struct platform_device *smc91x; | 94 | struct platform_device *smc91x; |
69 | unsigned irq_base; | 95 | unsigned irq_base; |
70 | #ifdef CONFIG_PM_SLEEP | 96 | struct gpio_chip *gpio[4]; |
71 | u32 ncr0; | ||
72 | u32 mdm_ctl_0; | ||
73 | #endif | ||
74 | }; | 97 | }; |
75 | 98 | ||
76 | static void __iomem *nep_base; | 99 | static struct neponset_drvdata *nep; |
77 | 100 | ||
78 | void neponset_ncr_frob(unsigned int mask, unsigned int val) | 101 | void neponset_ncr_frob(unsigned int mask, unsigned int val) |
79 | { | 102 | { |
80 | void __iomem *base = nep_base; | 103 | struct neponset_drvdata *n = nep; |
81 | 104 | unsigned long m = mask, v = val; | |
82 | if (base) { | 105 | |
83 | unsigned long flags; | 106 | if (nep) |
84 | unsigned v; | 107 | n->gpio[0]->set_multiple(n->gpio[0], &m, &v); |
85 | 108 | else | |
86 | local_irq_save(flags); | 109 | WARN(1, "nep unset\n"); |
87 | v = readb_relaxed(base + NCR_0); | ||
88 | writeb_relaxed((v & ~mask) | val, base + NCR_0); | ||
89 | local_irq_restore(flags); | ||
90 | } else { | ||
91 | WARN(1, "nep_base unset\n"); | ||
92 | } | ||
93 | } | 110 | } |
94 | EXPORT_SYMBOL(neponset_ncr_frob); | 111 | EXPORT_SYMBOL(neponset_ncr_frob); |
95 | 112 | ||
96 | static void neponset_set_mctrl(struct uart_port *port, u_int mctrl) | 113 | static void neponset_set_mctrl(struct uart_port *port, u_int mctrl) |
97 | { | 114 | { |
98 | void __iomem *base = nep_base; | 115 | struct neponset_drvdata *n = nep; |
99 | u_int mdm_ctl0; | 116 | unsigned long mask, val = 0; |
100 | 117 | ||
101 | if (!base) | 118 | if (!n) |
102 | return; | 119 | return; |
103 | 120 | ||
104 | mdm_ctl0 = readb_relaxed(base + MDM_CTL_0); | ||
105 | if (port->mapbase == _Ser1UTCR0) { | 121 | if (port->mapbase == _Ser1UTCR0) { |
106 | if (mctrl & TIOCM_RTS) | 122 | mask = MDM_CTL0_RTS2 | MDM_CTL0_DTR2; |
107 | mdm_ctl0 &= ~MDM_CTL0_RTS2; | 123 | |
108 | else | 124 | if (!(mctrl & TIOCM_RTS)) |
109 | mdm_ctl0 |= MDM_CTL0_RTS2; | 125 | val |= MDM_CTL0_RTS2; |
110 | 126 | ||
111 | if (mctrl & TIOCM_DTR) | 127 | if (!(mctrl & TIOCM_DTR)) |
112 | mdm_ctl0 &= ~MDM_CTL0_DTR2; | 128 | val |= MDM_CTL0_DTR2; |
113 | else | ||
114 | mdm_ctl0 |= MDM_CTL0_DTR2; | ||
115 | } else if (port->mapbase == _Ser3UTCR0) { | 129 | } else if (port->mapbase == _Ser3UTCR0) { |
116 | if (mctrl & TIOCM_RTS) | 130 | mask = MDM_CTL0_RTS1 | MDM_CTL0_DTR1; |
117 | mdm_ctl0 &= ~MDM_CTL0_RTS1; | 131 | |
118 | else | 132 | if (!(mctrl & TIOCM_RTS)) |
119 | mdm_ctl0 |= MDM_CTL0_RTS1; | 133 | val |= MDM_CTL0_RTS1; |
120 | 134 | ||
121 | if (mctrl & TIOCM_DTR) | 135 | if (!(mctrl & TIOCM_DTR)) |
122 | mdm_ctl0 &= ~MDM_CTL0_DTR1; | 136 | val |= MDM_CTL0_DTR1; |
123 | else | ||
124 | mdm_ctl0 |= MDM_CTL0_DTR1; | ||
125 | } | 137 | } |
126 | 138 | ||
127 | writeb_relaxed(mdm_ctl0, base + MDM_CTL_0); | 139 | n->gpio[1]->set_multiple(n->gpio[1], &mask, &val); |
128 | } | 140 | } |
129 | 141 | ||
130 | static u_int neponset_get_mctrl(struct uart_port *port) | 142 | static u_int neponset_get_mctrl(struct uart_port *port) |
131 | { | 143 | { |
132 | void __iomem *base = nep_base; | 144 | void __iomem *base = nep->base; |
133 | u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR; | 145 | u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR; |
134 | u_int mdm_ctl1; | 146 | u_int mdm_ctl1; |
135 | 147 | ||
@@ -231,6 +243,22 @@ static struct irq_chip nochip = { | |||
231 | .irq_unmask = nochip_noop, | 243 | .irq_unmask = nochip_noop, |
232 | }; | 244 | }; |
233 | 245 | ||
246 | static int neponset_init_gpio(struct gpio_chip **gcp, | ||
247 | struct device *dev, const char *label, void __iomem *reg, | ||
248 | unsigned num, bool in, const char *const * names) | ||
249 | { | ||
250 | struct gpio_chip *gc; | ||
251 | |||
252 | gc = gpio_reg_init(dev, reg, -1, num, label, in ? 0xffffffff : 0, | ||
253 | readl_relaxed(reg), names, NULL, NULL); | ||
254 | if (IS_ERR(gc)) | ||
255 | return PTR_ERR(gc); | ||
256 | |||
257 | *gcp = gc; | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
234 | static struct sa1111_platform_data sa1111_info = { | 262 | static struct sa1111_platform_data sa1111_info = { |
235 | .disable_devs = SA1111_DEVID_PS2_MSE, | 263 | .disable_devs = SA1111_DEVID_PS2_MSE, |
236 | }; | 264 | }; |
@@ -274,7 +302,7 @@ static int neponset_probe(struct platform_device *dev) | |||
274 | }; | 302 | }; |
275 | int ret, irq; | 303 | int ret, irq; |
276 | 304 | ||
277 | if (nep_base) | 305 | if (nep) |
278 | return -EBUSY; | 306 | return -EBUSY; |
279 | 307 | ||
280 | irq = ret = platform_get_irq(dev, 0); | 308 | irq = ret = platform_get_irq(dev, 0); |
@@ -330,6 +358,22 @@ static int neponset_probe(struct platform_device *dev) | |||
330 | irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING); | 358 | irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING); |
331 | irq_set_chained_handler_and_data(irq, neponset_irq_handler, d); | 359 | irq_set_chained_handler_and_data(irq, neponset_irq_handler, d); |
332 | 360 | ||
361 | /* Disable GPIO 0/1 drivers so the buttons work on the Assabet */ | ||
362 | writeb_relaxed(NCR_GP01_OFF, d->base + NCR_0); | ||
363 | |||
364 | neponset_init_gpio(&d->gpio[0], &dev->dev, "neponset-ncr", | ||
365 | d->base + NCR_0, NCR_NGPIO, false, | ||
366 | neponset_ncr_names); | ||
367 | neponset_init_gpio(&d->gpio[1], &dev->dev, "neponset-mdm-ctl0", | ||
368 | d->base + MDM_CTL_0, MDM_CTL0_NGPIO, false, | ||
369 | neponset_mdmctl0_names); | ||
370 | neponset_init_gpio(&d->gpio[2], &dev->dev, "neponset-mdm-ctl1", | ||
371 | d->base + MDM_CTL_1, MDM_CTL1_NGPIO, true, | ||
372 | neponset_mdmctl1_names); | ||
373 | neponset_init_gpio(&d->gpio[3], &dev->dev, "neponset-aud-ctl", | ||
374 | d->base + AUD_CTL, AUD_NGPIO, false, | ||
375 | neponset_aud_names); | ||
376 | |||
333 | /* | 377 | /* |
334 | * We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately | 378 | * We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately |
335 | * something on the Neponset activates this IRQ on sleep (eth?) | 379 | * something on the Neponset activates this IRQ on sleep (eth?) |
@@ -340,16 +384,13 @@ static int neponset_probe(struct platform_device *dev) | |||
340 | 384 | ||
341 | dev_info(&dev->dev, "Neponset daughter board, providing IRQ%u-%u\n", | 385 | dev_info(&dev->dev, "Neponset daughter board, providing IRQ%u-%u\n", |
342 | d->irq_base, d->irq_base + NEP_IRQ_NR - 1); | 386 | d->irq_base, d->irq_base + NEP_IRQ_NR - 1); |
343 | nep_base = d->base; | 387 | nep = d; |
344 | 388 | ||
345 | sa1100_register_uart_fns(&neponset_port_fns); | 389 | sa1100_register_uart_fns(&neponset_port_fns); |
346 | 390 | ||
347 | /* Ensure that the memory bus request/grant signals are setup */ | 391 | /* Ensure that the memory bus request/grant signals are setup */ |
348 | sa1110_mb_disable(); | 392 | sa1110_mb_disable(); |
349 | 393 | ||
350 | /* Disable GPIO 0/1 drivers so the buttons work on the Assabet */ | ||
351 | writeb_relaxed(NCR_GP01_OFF, d->base + NCR_0); | ||
352 | |||
353 | sa1111_resources[0].parent = sa1111_res; | 394 | sa1111_resources[0].parent = sa1111_res; |
354 | sa1111_resources[1].start = d->irq_base + NEP_IRQ_SA1111; | 395 | sa1111_resources[1].start = d->irq_base + NEP_IRQ_SA1111; |
355 | sa1111_resources[1].end = d->irq_base + NEP_IRQ_SA1111; | 396 | sa1111_resources[1].end = d->irq_base + NEP_IRQ_SA1111; |
@@ -385,7 +426,7 @@ static int neponset_remove(struct platform_device *dev) | |||
385 | platform_device_unregister(d->smc91x); | 426 | platform_device_unregister(d->smc91x); |
386 | irq_set_chained_handler(irq, NULL); | 427 | irq_set_chained_handler(irq, NULL); |
387 | irq_free_descs(d->irq_base, NEP_IRQ_NR); | 428 | irq_free_descs(d->irq_base, NEP_IRQ_NR); |
388 | nep_base = NULL; | 429 | nep = NULL; |
389 | iounmap(d->base); | 430 | iounmap(d->base); |
390 | kfree(d); | 431 | kfree(d); |
391 | 432 | ||
@@ -393,30 +434,22 @@ static int neponset_remove(struct platform_device *dev) | |||
393 | } | 434 | } |
394 | 435 | ||
395 | #ifdef CONFIG_PM_SLEEP | 436 | #ifdef CONFIG_PM_SLEEP |
396 | static int neponset_suspend(struct device *dev) | ||
397 | { | ||
398 | struct neponset_drvdata *d = dev_get_drvdata(dev); | ||
399 | |||
400 | d->ncr0 = readb_relaxed(d->base + NCR_0); | ||
401 | d->mdm_ctl_0 = readb_relaxed(d->base + MDM_CTL_0); | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static int neponset_resume(struct device *dev) | 437 | static int neponset_resume(struct device *dev) |
407 | { | 438 | { |
408 | struct neponset_drvdata *d = dev_get_drvdata(dev); | 439 | struct neponset_drvdata *d = dev_get_drvdata(dev); |
440 | int i, ret = 0; | ||
409 | 441 | ||
410 | writeb_relaxed(d->ncr0, d->base + NCR_0); | 442 | for (i = 0; i < ARRAY_SIZE(d->gpio); i++) { |
411 | writeb_relaxed(d->mdm_ctl_0, d->base + MDM_CTL_0); | 443 | ret = gpio_reg_resume(d->gpio[i]); |
444 | if (ret) | ||
445 | break; | ||
446 | } | ||
412 | 447 | ||
413 | return 0; | 448 | return ret; |
414 | } | 449 | } |
415 | 450 | ||
416 | static const struct dev_pm_ops neponset_pm_ops = { | 451 | static const struct dev_pm_ops neponset_pm_ops = { |
417 | .suspend_noirq = neponset_suspend, | ||
418 | .resume_noirq = neponset_resume, | 452 | .resume_noirq = neponset_resume, |
419 | .freeze_noirq = neponset_suspend, | ||
420 | .restore_noirq = neponset_resume, | 453 | .restore_noirq = neponset_resume, |
421 | }; | 454 | }; |
422 | #define PM_OPS &neponset_pm_ops | 455 | #define PM_OPS &neponset_pm_ops |
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index fd9077a74fce..7f14acf67caf 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -909,6 +909,14 @@ config OUTER_CACHE_SYNC | |||
909 | The outer cache has a outer_cache_fns.sync function pointer | 909 | The outer cache has a outer_cache_fns.sync function pointer |
910 | that can be used to drain the write buffer of the outer cache. | 910 | that can be used to drain the write buffer of the outer cache. |
911 | 911 | ||
912 | config CACHE_B15_RAC | ||
913 | bool "Enable the Broadcom Brahma-B15 read-ahead cache controller" | ||
914 | depends on ARCH_BRCMSTB | ||
915 | default y | ||
916 | help | ||
917 | This option enables the Broadcom Brahma-B15 read-ahead cache | ||
918 | controller. If disabled, the read-ahead cache remains off. | ||
919 | |||
912 | config CACHE_FEROCEON_L2 | 920 | config CACHE_FEROCEON_L2 |
913 | bool "Enable the Feroceon L2 cache controller" | 921 | bool "Enable the Feroceon L2 cache controller" |
914 | depends on ARCH_MV78XX0 || ARCH_MVEBU | 922 | depends on ARCH_MV78XX0 || ARCH_MVEBU |
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 01bcc33f59e3..9dbb84923e12 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile | |||
@@ -13,7 +13,8 @@ obj-y += nommu.o | |||
13 | obj-$(CONFIG_ARM_MPU) += pmsa-v7.o | 13 | obj-$(CONFIG_ARM_MPU) += pmsa-v7.o |
14 | endif | 14 | endif |
15 | 15 | ||
16 | obj-$(CONFIG_ARM_PTDUMP) += dump.o | 16 | obj-$(CONFIG_ARM_PTDUMP_CORE) += dump.o |
17 | obj-$(CONFIG_ARM_PTDUMP_DEBUGFS) += ptdump_debugfs.o | ||
17 | obj-$(CONFIG_MODULES) += proc-syms.o | 18 | obj-$(CONFIG_MODULES) += proc-syms.o |
18 | obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o | 19 | obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o |
19 | 20 | ||
@@ -103,6 +104,7 @@ AFLAGS_proc-v6.o :=-Wa,-march=armv6 | |||
103 | AFLAGS_proc-v7.o :=-Wa,-march=armv7-a | 104 | AFLAGS_proc-v7.o :=-Wa,-march=armv7-a |
104 | 105 | ||
105 | obj-$(CONFIG_OUTER_CACHE) += l2c-common.o | 106 | obj-$(CONFIG_OUTER_CACHE) += l2c-common.o |
107 | obj-$(CONFIG_CACHE_B15_RAC) += cache-b15-rac.o | ||
106 | obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o | 108 | obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o |
107 | obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o l2c-l2x0-resume.o | 109 | obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o l2c-l2x0-resume.o |
108 | obj-$(CONFIG_CACHE_L2X0_PMU) += cache-l2x0-pmu.o | 110 | obj-$(CONFIG_CACHE_L2X0_PMU) += cache-l2x0-pmu.o |
diff --git a/arch/arm/mm/cache-b15-rac.c b/arch/arm/mm/cache-b15-rac.c new file mode 100644 index 000000000000..d9586ba2e63c --- /dev/null +++ b/arch/arm/mm/cache-b15-rac.c | |||
@@ -0,0 +1,356 @@ | |||
1 | /* | ||
2 | * Broadcom Brahma-B15 CPU read-ahead cache management functions | ||
3 | * | ||
4 | * Copyright (C) 2015-2016 Broadcom | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/err.h> | ||
12 | #include <linux/spinlock.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/bitops.h> | ||
15 | #include <linux/of_address.h> | ||
16 | #include <linux/notifier.h> | ||
17 | #include <linux/cpu.h> | ||
18 | #include <linux/syscore_ops.h> | ||
19 | #include <linux/reboot.h> | ||
20 | |||
21 | #include <asm/cacheflush.h> | ||
22 | #include <asm/hardware/cache-b15-rac.h> | ||
23 | |||
24 | extern void v7_flush_kern_cache_all(void); | ||
25 | |||
26 | /* RAC register offsets, relative to the HIF_CPU_BIUCTRL register base */ | ||
27 | #define RAC_CONFIG0_REG (0x78) | ||
28 | #define RACENPREF_MASK (0x3) | ||
29 | #define RACPREFINST_SHIFT (0) | ||
30 | #define RACENINST_SHIFT (2) | ||
31 | #define RACPREFDATA_SHIFT (4) | ||
32 | #define RACENDATA_SHIFT (6) | ||
33 | #define RAC_CPU_SHIFT (8) | ||
34 | #define RACCFG_MASK (0xff) | ||
35 | #define RAC_CONFIG1_REG (0x7c) | ||
36 | #define RAC_FLUSH_REG (0x80) | ||
37 | #define FLUSH_RAC (1 << 0) | ||
38 | |||
39 | /* Bitmask to enable instruction and data prefetching with a 256-bytes stride */ | ||
40 | #define RAC_DATA_INST_EN_MASK (1 << RACPREFINST_SHIFT | \ | ||
41 | RACENPREF_MASK << RACENINST_SHIFT | \ | ||
42 | 1 << RACPREFDATA_SHIFT | \ | ||
43 | RACENPREF_MASK << RACENDATA_SHIFT) | ||
44 | |||
45 | #define RAC_ENABLED 0 | ||
46 | /* Special state where we want to bypass the spinlock and call directly | ||
47 | * into the v7 cache maintenance operations during suspend/resume | ||
48 | */ | ||
49 | #define RAC_SUSPENDED 1 | ||
50 | |||
51 | static void __iomem *b15_rac_base; | ||
52 | static DEFINE_SPINLOCK(rac_lock); | ||
53 | |||
54 | static u32 rac_config0_reg; | ||
55 | |||
56 | /* Initialization flag to avoid checking for b15_rac_base, and to prevent | ||
57 | * multi-platform kernels from crashing here as well. | ||
58 | */ | ||
59 | static unsigned long b15_rac_flags; | ||
60 | |||
61 | static inline u32 __b15_rac_disable(void) | ||
62 | { | ||
63 | u32 val = __raw_readl(b15_rac_base + RAC_CONFIG0_REG); | ||
64 | __raw_writel(0, b15_rac_base + RAC_CONFIG0_REG); | ||
65 | dmb(); | ||
66 | return val; | ||
67 | } | ||
68 | |||
69 | static inline void __b15_rac_flush(void) | ||
70 | { | ||
71 | u32 reg; | ||
72 | |||
73 | __raw_writel(FLUSH_RAC, b15_rac_base + RAC_FLUSH_REG); | ||
74 | do { | ||
75 | /* This dmb() is required to force the Bus Interface Unit | ||
76 | * to clean oustanding writes, and forces an idle cycle | ||
77 | * to be inserted. | ||
78 | */ | ||
79 | dmb(); | ||
80 | reg = __raw_readl(b15_rac_base + RAC_FLUSH_REG); | ||
81 | } while (reg & FLUSH_RAC); | ||
82 | } | ||
83 | |||
84 | static inline u32 b15_rac_disable_and_flush(void) | ||
85 | { | ||
86 | u32 reg; | ||
87 | |||
88 | reg = __b15_rac_disable(); | ||
89 | __b15_rac_flush(); | ||
90 | return reg; | ||
91 | } | ||
92 | |||
93 | static inline void __b15_rac_enable(u32 val) | ||
94 | { | ||
95 | __raw_writel(val, b15_rac_base + RAC_CONFIG0_REG); | ||
96 | /* dsb() is required here to be consistent with __flush_icache_all() */ | ||
97 | dsb(); | ||
98 | } | ||
99 | |||
100 | #define BUILD_RAC_CACHE_OP(name, bar) \ | ||
101 | void b15_flush_##name(void) \ | ||
102 | { \ | ||
103 | unsigned int do_flush; \ | ||
104 | u32 val = 0; \ | ||
105 | \ | ||
106 | if (test_bit(RAC_SUSPENDED, &b15_rac_flags)) { \ | ||
107 | v7_flush_##name(); \ | ||
108 | bar; \ | ||
109 | return; \ | ||
110 | } \ | ||
111 | \ | ||
112 | spin_lock(&rac_lock); \ | ||
113 | do_flush = test_bit(RAC_ENABLED, &b15_rac_flags); \ | ||
114 | if (do_flush) \ | ||
115 | val = b15_rac_disable_and_flush(); \ | ||
116 | v7_flush_##name(); \ | ||
117 | if (!do_flush) \ | ||
118 | bar; \ | ||
119 | else \ | ||
120 | __b15_rac_enable(val); \ | ||
121 | spin_unlock(&rac_lock); \ | ||
122 | } | ||
123 | |||
124 | #define nobarrier | ||
125 | |||
126 | /* The readahead cache present in the Brahma-B15 CPU is a special piece of | ||
127 | * hardware after the integrated L2 cache of the B15 CPU complex whose purpose | ||
128 | * is to prefetch instruction and/or data with a line size of either 64 bytes | ||
129 | * or 256 bytes. The rationale is that the data-bus of the CPU interface is | ||
130 | * optimized for 256-bytes transactions, and enabling the readahead cache | ||
131 | * provides a significant performance boost we want it enabled (typically | ||
132 | * twice the performance for a memcpy benchmark application). | ||
133 | * | ||
134 | * The readahead cache is transparent for Modified Virtual Addresses | ||
135 | * cache maintenance operations: ICIMVAU, DCIMVAC, DCCMVAC, DCCMVAU and | ||
136 | * DCCIMVAC. | ||
137 | * | ||
138 | * It is however not transparent for the following cache maintenance | ||
139 | * operations: DCISW, DCCSW, DCCISW, ICIALLUIS and ICIALLU which is precisely | ||
140 | * what we are patching here with our BUILD_RAC_CACHE_OP here. | ||
141 | */ | ||
142 | BUILD_RAC_CACHE_OP(kern_cache_all, nobarrier); | ||
143 | |||
144 | static void b15_rac_enable(void) | ||
145 | { | ||
146 | unsigned int cpu; | ||
147 | u32 enable = 0; | ||
148 | |||
149 | for_each_possible_cpu(cpu) | ||
150 | enable |= (RAC_DATA_INST_EN_MASK << (cpu * RAC_CPU_SHIFT)); | ||
151 | |||
152 | b15_rac_disable_and_flush(); | ||
153 | __b15_rac_enable(enable); | ||
154 | } | ||
155 | |||
156 | static int b15_rac_reboot_notifier(struct notifier_block *nb, | ||
157 | unsigned long action, | ||
158 | void *data) | ||
159 | { | ||
160 | /* During kexec, we are not yet migrated on the boot CPU, so we need to | ||
161 | * make sure we are SMP safe here. Once the RAC is disabled, flag it as | ||
162 | * suspended such that the hotplug notifier returns early. | ||
163 | */ | ||
164 | if (action == SYS_RESTART) { | ||
165 | spin_lock(&rac_lock); | ||
166 | b15_rac_disable_and_flush(); | ||
167 | clear_bit(RAC_ENABLED, &b15_rac_flags); | ||
168 | set_bit(RAC_SUSPENDED, &b15_rac_flags); | ||
169 | spin_unlock(&rac_lock); | ||
170 | } | ||
171 | |||
172 | return NOTIFY_DONE; | ||
173 | } | ||
174 | |||
175 | static struct notifier_block b15_rac_reboot_nb = { | ||
176 | .notifier_call = b15_rac_reboot_notifier, | ||
177 | }; | ||
178 | |||
179 | /* The CPU hotplug case is the most interesting one, we basically need to make | ||
180 | * sure that the RAC is disabled for the entire system prior to having a CPU | ||
181 | * die, in particular prior to this dying CPU having exited the coherency | ||
182 | * domain. | ||
183 | * | ||
184 | * Once this CPU is marked dead, we can safely re-enable the RAC for the | ||
185 | * remaining CPUs in the system which are still online. | ||
186 | * | ||
187 | * Offlining a CPU is the problematic case, onlining a CPU is not much of an | ||
188 | * issue since the CPU and its cache-level hierarchy will start filling with | ||
189 | * the RAC disabled, so L1 and L2 only. | ||
190 | * | ||
191 | * In this function, we should NOT have to verify any unsafe setting/condition | ||
192 | * b15_rac_base: | ||
193 | * | ||
194 | * It is protected by the RAC_ENABLED flag which is cleared by default, and | ||
195 | * being cleared when initial procedure is done. b15_rac_base had been set at | ||
196 | * that time. | ||
197 | * | ||
198 | * RAC_ENABLED: | ||
199 | * There is a small timing windows, in b15_rac_init(), between | ||
200 | * cpuhp_setup_state_*() | ||
201 | * ... | ||
202 | * set RAC_ENABLED | ||
203 | * However, there is no hotplug activity based on the Linux booting procedure. | ||
204 | * | ||
205 | * Since we have to disable RAC for all cores, we keep RAC on as long as as | ||
206 | * possible (disable it as late as possible) to gain the cache benefit. | ||
207 | * | ||
208 | * Thus, dying/dead states are chosen here | ||
209 | * | ||
210 | * We are choosing not do disable the RAC on a per-CPU basis, here, if we did | ||
211 | * we would want to consider disabling it as early as possible to benefit the | ||
212 | * other active CPUs. | ||
213 | */ | ||
214 | |||
215 | /* Running on the dying CPU */ | ||
216 | static int b15_rac_dying_cpu(unsigned int cpu) | ||
217 | { | ||
218 | /* During kexec/reboot, the RAC is disabled via the reboot notifier | ||
219 | * return early here. | ||
220 | */ | ||
221 | if (test_bit(RAC_SUSPENDED, &b15_rac_flags)) | ||
222 | return 0; | ||
223 | |||
224 | spin_lock(&rac_lock); | ||
225 | |||
226 | /* Indicate that we are starting a hotplug procedure */ | ||
227 | __clear_bit(RAC_ENABLED, &b15_rac_flags); | ||
228 | |||
229 | /* Disable the readahead cache and save its value to a global */ | ||
230 | rac_config0_reg = b15_rac_disable_and_flush(); | ||
231 | |||
232 | spin_unlock(&rac_lock); | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | /* Running on a non-dying CPU */ | ||
238 | static int b15_rac_dead_cpu(unsigned int cpu) | ||
239 | { | ||
240 | /* During kexec/reboot, the RAC is disabled via the reboot notifier | ||
241 | * return early here. | ||
242 | */ | ||
243 | if (test_bit(RAC_SUSPENDED, &b15_rac_flags)) | ||
244 | return 0; | ||
245 | |||
246 | spin_lock(&rac_lock); | ||
247 | |||
248 | /* And enable it */ | ||
249 | __b15_rac_enable(rac_config0_reg); | ||
250 | __set_bit(RAC_ENABLED, &b15_rac_flags); | ||
251 | |||
252 | spin_unlock(&rac_lock); | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static int b15_rac_suspend(void) | ||
258 | { | ||
259 | /* Suspend the read-ahead cache oeprations, forcing our cache | ||
260 | * implementation to fallback to the regular ARMv7 calls. | ||
261 | * | ||
262 | * We are guaranteed to be running on the boot CPU at this point and | ||
263 | * with every other CPU quiesced, so setting RAC_SUSPENDED is not racy | ||
264 | * here. | ||
265 | */ | ||
266 | rac_config0_reg = b15_rac_disable_and_flush(); | ||
267 | set_bit(RAC_SUSPENDED, &b15_rac_flags); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static void b15_rac_resume(void) | ||
273 | { | ||
274 | /* Coming out of a S3 suspend/resume cycle, the read-ahead cache | ||
275 | * register RAC_CONFIG0_REG will be restored to its default value, make | ||
276 | * sure we re-enable it and set the enable flag, we are also guaranteed | ||
277 | * to run on the boot CPU, so not racy again. | ||
278 | */ | ||
279 | __b15_rac_enable(rac_config0_reg); | ||
280 | clear_bit(RAC_SUSPENDED, &b15_rac_flags); | ||
281 | } | ||
282 | |||
283 | static struct syscore_ops b15_rac_syscore_ops = { | ||
284 | .suspend = b15_rac_suspend, | ||
285 | .resume = b15_rac_resume, | ||
286 | }; | ||
287 | |||
288 | static int __init b15_rac_init(void) | ||
289 | { | ||
290 | struct device_node *dn; | ||
291 | int ret = 0, cpu; | ||
292 | u32 reg, en_mask = 0; | ||
293 | |||
294 | dn = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl"); | ||
295 | if (!dn) | ||
296 | return -ENODEV; | ||
297 | |||
298 | if (WARN(num_possible_cpus() > 4, "RAC only supports 4 CPUs\n")) | ||
299 | goto out; | ||
300 | |||
301 | b15_rac_base = of_iomap(dn, 0); | ||
302 | if (!b15_rac_base) { | ||
303 | pr_err("failed to remap BIU control base\n"); | ||
304 | ret = -ENOMEM; | ||
305 | goto out; | ||
306 | } | ||
307 | |||
308 | ret = register_reboot_notifier(&b15_rac_reboot_nb); | ||
309 | if (ret) { | ||
310 | pr_err("failed to register reboot notifier\n"); | ||
311 | iounmap(b15_rac_base); | ||
312 | goto out; | ||
313 | } | ||
314 | |||
315 | if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) { | ||
316 | ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CACHE_B15_RAC_DEAD, | ||
317 | "arm/cache-b15-rac:dead", | ||
318 | NULL, b15_rac_dead_cpu); | ||
319 | if (ret) | ||
320 | goto out_unmap; | ||
321 | |||
322 | ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CACHE_B15_RAC_DYING, | ||
323 | "arm/cache-b15-rac:dying", | ||
324 | NULL, b15_rac_dying_cpu); | ||
325 | if (ret) | ||
326 | goto out_cpu_dead; | ||
327 | } | ||
328 | |||
329 | if (IS_ENABLED(CONFIG_PM_SLEEP)) | ||
330 | register_syscore_ops(&b15_rac_syscore_ops); | ||
331 | |||
332 | spin_lock(&rac_lock); | ||
333 | reg = __raw_readl(b15_rac_base + RAC_CONFIG0_REG); | ||
334 | for_each_possible_cpu(cpu) | ||
335 | en_mask |= ((1 << RACPREFDATA_SHIFT) << (cpu * RAC_CPU_SHIFT)); | ||
336 | WARN(reg & en_mask, "Read-ahead cache not previously disabled\n"); | ||
337 | |||
338 | b15_rac_enable(); | ||
339 | set_bit(RAC_ENABLED, &b15_rac_flags); | ||
340 | spin_unlock(&rac_lock); | ||
341 | |||
342 | pr_info("Broadcom Brahma-B15 readahead cache at: 0x%p\n", | ||
343 | b15_rac_base + RAC_CONFIG0_REG); | ||
344 | |||
345 | goto out; | ||
346 | |||
347 | out_cpu_dead: | ||
348 | cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CACHE_B15_RAC_DYING); | ||
349 | out_unmap: | ||
350 | unregister_reboot_notifier(&b15_rac_reboot_nb); | ||
351 | iounmap(b15_rac_base); | ||
352 | out: | ||
353 | of_node_put(dn); | ||
354 | return ret; | ||
355 | } | ||
356 | arch_initcall(b15_rac_init); | ||
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index de78109d002d..215df435bfb9 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <asm/assembler.h> | 15 | #include <asm/assembler.h> |
16 | #include <asm/errno.h> | 16 | #include <asm/errno.h> |
17 | #include <asm/unwind.h> | 17 | #include <asm/unwind.h> |
18 | #include <asm/hardware/cache-b15-rac.h> | ||
18 | 19 | ||
19 | #include "proc-macros.S" | 20 | #include "proc-macros.S" |
20 | 21 | ||
@@ -446,3 +447,23 @@ ENDPROC(v7_dma_unmap_area) | |||
446 | 447 | ||
447 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) | 448 | @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S) |
448 | define_cache_functions v7 | 449 | define_cache_functions v7 |
450 | |||
451 | /* The Broadcom Brahma-B15 read-ahead cache requires some modifications | ||
452 | * to the v7_cache_fns, we only override the ones we need | ||
453 | */ | ||
454 | #ifndef CONFIG_CACHE_B15_RAC | ||
455 | globl_equ b15_flush_kern_cache_all, v7_flush_kern_cache_all | ||
456 | #endif | ||
457 | globl_equ b15_flush_icache_all, v7_flush_icache_all | ||
458 | globl_equ b15_flush_kern_cache_louis, v7_flush_kern_cache_louis | ||
459 | globl_equ b15_flush_user_cache_all, v7_flush_user_cache_all | ||
460 | globl_equ b15_flush_user_cache_range, v7_flush_user_cache_range | ||
461 | globl_equ b15_coherent_kern_range, v7_coherent_kern_range | ||
462 | globl_equ b15_coherent_user_range, v7_coherent_user_range | ||
463 | globl_equ b15_flush_kern_dcache_area, v7_flush_kern_dcache_area | ||
464 | |||
465 | globl_equ b15_dma_map_area, v7_dma_map_area | ||
466 | globl_equ b15_dma_unmap_area, v7_dma_unmap_area | ||
467 | globl_equ b15_dma_flush_range, v7_dma_flush_range | ||
468 | |||
469 | define_cache_functions b15 | ||
diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c index fc3b44028cfb..084779c5c893 100644 --- a/arch/arm/mm/dump.c +++ b/arch/arm/mm/dump.c | |||
@@ -21,11 +21,7 @@ | |||
21 | #include <asm/fixmap.h> | 21 | #include <asm/fixmap.h> |
22 | #include <asm/memory.h> | 22 | #include <asm/memory.h> |
23 | #include <asm/pgtable.h> | 23 | #include <asm/pgtable.h> |
24 | 24 | #include <asm/ptdump.h> | |
25 | struct addr_marker { | ||
26 | unsigned long start_address; | ||
27 | const char *name; | ||
28 | }; | ||
29 | 25 | ||
30 | static struct addr_marker address_markers[] = { | 26 | static struct addr_marker address_markers[] = { |
31 | { MODULES_VADDR, "Modules" }, | 27 | { MODULES_VADDR, "Modules" }, |
@@ -38,12 +34,26 @@ static struct addr_marker address_markers[] = { | |||
38 | { -1, NULL }, | 34 | { -1, NULL }, |
39 | }; | 35 | }; |
40 | 36 | ||
37 | #define pt_dump_seq_printf(m, fmt, args...) \ | ||
38 | ({ \ | ||
39 | if (m) \ | ||
40 | seq_printf(m, fmt, ##args); \ | ||
41 | }) | ||
42 | |||
43 | #define pt_dump_seq_puts(m, fmt) \ | ||
44 | ({ \ | ||
45 | if (m) \ | ||
46 | seq_printf(m, fmt); \ | ||
47 | }) | ||
48 | |||
41 | struct pg_state { | 49 | struct pg_state { |
42 | struct seq_file *seq; | 50 | struct seq_file *seq; |
43 | const struct addr_marker *marker; | 51 | const struct addr_marker *marker; |
44 | unsigned long start_address; | 52 | unsigned long start_address; |
45 | unsigned level; | 53 | unsigned level; |
46 | u64 current_prot; | 54 | u64 current_prot; |
55 | bool check_wx; | ||
56 | unsigned long wx_pages; | ||
47 | const char *current_domain; | 57 | const char *current_domain; |
48 | }; | 58 | }; |
49 | 59 | ||
@@ -52,6 +62,8 @@ struct prot_bits { | |||
52 | u64 val; | 62 | u64 val; |
53 | const char *set; | 63 | const char *set; |
54 | const char *clear; | 64 | const char *clear; |
65 | bool ro_bit; | ||
66 | bool nx_bit; | ||
55 | }; | 67 | }; |
56 | 68 | ||
57 | static const struct prot_bits pte_bits[] = { | 69 | static const struct prot_bits pte_bits[] = { |
@@ -65,11 +77,13 @@ static const struct prot_bits pte_bits[] = { | |||
65 | .val = L_PTE_RDONLY, | 77 | .val = L_PTE_RDONLY, |
66 | .set = "ro", | 78 | .set = "ro", |
67 | .clear = "RW", | 79 | .clear = "RW", |
80 | .ro_bit = true, | ||
68 | }, { | 81 | }, { |
69 | .mask = L_PTE_XN, | 82 | .mask = L_PTE_XN, |
70 | .val = L_PTE_XN, | 83 | .val = L_PTE_XN, |
71 | .set = "NX", | 84 | .set = "NX", |
72 | .clear = "x ", | 85 | .clear = "x ", |
86 | .nx_bit = true, | ||
73 | }, { | 87 | }, { |
74 | .mask = L_PTE_SHARED, | 88 | .mask = L_PTE_SHARED, |
75 | .val = L_PTE_SHARED, | 89 | .val = L_PTE_SHARED, |
@@ -133,11 +147,13 @@ static const struct prot_bits section_bits[] = { | |||
133 | .val = L_PMD_SECT_RDONLY | PMD_SECT_AP2, | 147 | .val = L_PMD_SECT_RDONLY | PMD_SECT_AP2, |
134 | .set = "ro", | 148 | .set = "ro", |
135 | .clear = "RW", | 149 | .clear = "RW", |
150 | .ro_bit = true, | ||
136 | #elif __LINUX_ARM_ARCH__ >= 6 | 151 | #elif __LINUX_ARM_ARCH__ >= 6 |
137 | { | 152 | { |
138 | .mask = PMD_SECT_APX | PMD_SECT_AP_READ | PMD_SECT_AP_WRITE, | 153 | .mask = PMD_SECT_APX | PMD_SECT_AP_READ | PMD_SECT_AP_WRITE, |
139 | .val = PMD_SECT_APX | PMD_SECT_AP_WRITE, | 154 | .val = PMD_SECT_APX | PMD_SECT_AP_WRITE, |
140 | .set = " ro", | 155 | .set = " ro", |
156 | .ro_bit = true, | ||
141 | }, { | 157 | }, { |
142 | .mask = PMD_SECT_APX | PMD_SECT_AP_READ | PMD_SECT_AP_WRITE, | 158 | .mask = PMD_SECT_APX | PMD_SECT_AP_READ | PMD_SECT_AP_WRITE, |
143 | .val = PMD_SECT_AP_WRITE, | 159 | .val = PMD_SECT_AP_WRITE, |
@@ -156,6 +172,7 @@ static const struct prot_bits section_bits[] = { | |||
156 | .mask = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE, | 172 | .mask = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE, |
157 | .val = 0, | 173 | .val = 0, |
158 | .set = " ro", | 174 | .set = " ro", |
175 | .ro_bit = true, | ||
159 | }, { | 176 | }, { |
160 | .mask = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE, | 177 | .mask = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE, |
161 | .val = PMD_SECT_AP_WRITE, | 178 | .val = PMD_SECT_AP_WRITE, |
@@ -174,6 +191,7 @@ static const struct prot_bits section_bits[] = { | |||
174 | .val = PMD_SECT_XN, | 191 | .val = PMD_SECT_XN, |
175 | .set = "NX", | 192 | .set = "NX", |
176 | .clear = "x ", | 193 | .clear = "x ", |
194 | .nx_bit = true, | ||
177 | }, { | 195 | }, { |
178 | .mask = PMD_SECT_S, | 196 | .mask = PMD_SECT_S, |
179 | .val = PMD_SECT_S, | 197 | .val = PMD_SECT_S, |
@@ -186,6 +204,8 @@ struct pg_level { | |||
186 | const struct prot_bits *bits; | 204 | const struct prot_bits *bits; |
187 | size_t num; | 205 | size_t num; |
188 | u64 mask; | 206 | u64 mask; |
207 | const struct prot_bits *ro_bit; | ||
208 | const struct prot_bits *nx_bit; | ||
189 | }; | 209 | }; |
190 | 210 | ||
191 | static struct pg_level pg_level[] = { | 211 | static struct pg_level pg_level[] = { |
@@ -214,10 +234,27 @@ static void dump_prot(struct pg_state *st, const struct prot_bits *bits, size_t | |||
214 | s = bits->clear; | 234 | s = bits->clear; |
215 | 235 | ||
216 | if (s) | 236 | if (s) |
217 | seq_printf(st->seq, " %s", s); | 237 | pt_dump_seq_printf(st->seq, " %s", s); |
218 | } | 238 | } |
219 | } | 239 | } |
220 | 240 | ||
241 | static void note_prot_wx(struct pg_state *st, unsigned long addr) | ||
242 | { | ||
243 | if (!st->check_wx) | ||
244 | return; | ||
245 | if ((st->current_prot & pg_level[st->level].ro_bit->mask) == | ||
246 | pg_level[st->level].ro_bit->val) | ||
247 | return; | ||
248 | if ((st->current_prot & pg_level[st->level].nx_bit->mask) == | ||
249 | pg_level[st->level].nx_bit->val) | ||
250 | return; | ||
251 | |||
252 | WARN_ONCE(1, "arm/mm: Found insecure W+X mapping at address %pS\n", | ||
253 | (void *)st->start_address); | ||
254 | |||
255 | st->wx_pages += (addr - st->start_address) / PAGE_SIZE; | ||
256 | } | ||
257 | |||
221 | static void note_page(struct pg_state *st, unsigned long addr, | 258 | static void note_page(struct pg_state *st, unsigned long addr, |
222 | unsigned int level, u64 val, const char *domain) | 259 | unsigned int level, u64 val, const char *domain) |
223 | { | 260 | { |
@@ -228,7 +265,7 @@ static void note_page(struct pg_state *st, unsigned long addr, | |||
228 | st->level = level; | 265 | st->level = level; |
229 | st->current_prot = prot; | 266 | st->current_prot = prot; |
230 | st->current_domain = domain; | 267 | st->current_domain = domain; |
231 | seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); | 268 | pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); |
232 | } else if (prot != st->current_prot || level != st->level || | 269 | } else if (prot != st->current_prot || level != st->level || |
233 | domain != st->current_domain || | 270 | domain != st->current_domain || |
234 | addr >= st->marker[1].start_address) { | 271 | addr >= st->marker[1].start_address) { |
@@ -236,7 +273,8 @@ static void note_page(struct pg_state *st, unsigned long addr, | |||
236 | unsigned long delta; | 273 | unsigned long delta; |
237 | 274 | ||
238 | if (st->current_prot) { | 275 | if (st->current_prot) { |
239 | seq_printf(st->seq, "0x%08lx-0x%08lx ", | 276 | note_prot_wx(st, addr); |
277 | pt_dump_seq_printf(st->seq, "0x%08lx-0x%08lx ", | ||
240 | st->start_address, addr); | 278 | st->start_address, addr); |
241 | 279 | ||
242 | delta = (addr - st->start_address) >> 10; | 280 | delta = (addr - st->start_address) >> 10; |
@@ -244,17 +282,19 @@ static void note_page(struct pg_state *st, unsigned long addr, | |||
244 | delta >>= 10; | 282 | delta >>= 10; |
245 | unit++; | 283 | unit++; |
246 | } | 284 | } |
247 | seq_printf(st->seq, "%9lu%c", delta, *unit); | 285 | pt_dump_seq_printf(st->seq, "%9lu%c", delta, *unit); |
248 | if (st->current_domain) | 286 | if (st->current_domain) |
249 | seq_printf(st->seq, " %s", st->current_domain); | 287 | pt_dump_seq_printf(st->seq, " %s", |
288 | st->current_domain); | ||
250 | if (pg_level[st->level].bits) | 289 | if (pg_level[st->level].bits) |
251 | dump_prot(st, pg_level[st->level].bits, pg_level[st->level].num); | 290 | dump_prot(st, pg_level[st->level].bits, pg_level[st->level].num); |
252 | seq_printf(st->seq, "\n"); | 291 | pt_dump_seq_printf(st->seq, "\n"); |
253 | } | 292 | } |
254 | 293 | ||
255 | if (addr >= st->marker[1].start_address) { | 294 | if (addr >= st->marker[1].start_address) { |
256 | st->marker++; | 295 | st->marker++; |
257 | seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); | 296 | pt_dump_seq_printf(st->seq, "---[ %s ]---\n", |
297 | st->marker->name); | ||
258 | } | 298 | } |
259 | st->start_address = addr; | 299 | st->start_address = addr; |
260 | st->current_prot = prot; | 300 | st->current_prot = prot; |
@@ -335,61 +375,82 @@ static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start) | |||
335 | } | 375 | } |
336 | } | 376 | } |
337 | 377 | ||
338 | static void walk_pgd(struct seq_file *m) | 378 | static void walk_pgd(struct pg_state *st, struct mm_struct *mm, |
379 | unsigned long start) | ||
339 | { | 380 | { |
340 | pgd_t *pgd = swapper_pg_dir; | 381 | pgd_t *pgd = pgd_offset(mm, 0UL); |
341 | struct pg_state st; | ||
342 | unsigned long addr; | ||
343 | unsigned i; | 382 | unsigned i; |
344 | 383 | unsigned long addr; | |
345 | memset(&st, 0, sizeof(st)); | ||
346 | st.seq = m; | ||
347 | st.marker = address_markers; | ||
348 | 384 | ||
349 | for (i = 0; i < PTRS_PER_PGD; i++, pgd++) { | 385 | for (i = 0; i < PTRS_PER_PGD; i++, pgd++) { |
350 | addr = i * PGDIR_SIZE; | 386 | addr = start + i * PGDIR_SIZE; |
351 | if (!pgd_none(*pgd)) { | 387 | if (!pgd_none(*pgd)) { |
352 | walk_pud(&st, pgd, addr); | 388 | walk_pud(st, pgd, addr); |
353 | } else { | 389 | } else { |
354 | note_page(&st, addr, 1, pgd_val(*pgd), NULL); | 390 | note_page(st, addr, 1, pgd_val(*pgd), NULL); |
355 | } | 391 | } |
356 | } | 392 | } |
357 | |||
358 | note_page(&st, 0, 0, 0, NULL); | ||
359 | } | 393 | } |
360 | 394 | ||
361 | static int ptdump_show(struct seq_file *m, void *v) | 395 | void ptdump_walk_pgd(struct seq_file *m, struct ptdump_info *info) |
362 | { | 396 | { |
363 | walk_pgd(m); | 397 | struct pg_state st = { |
364 | return 0; | 398 | .seq = m, |
365 | } | 399 | .marker = info->markers, |
400 | .check_wx = false, | ||
401 | }; | ||
366 | 402 | ||
367 | static int ptdump_open(struct inode *inode, struct file *file) | 403 | walk_pgd(&st, info->mm, info->base_addr); |
368 | { | 404 | note_page(&st, 0, 0, 0, NULL); |
369 | return single_open(file, ptdump_show, NULL); | ||
370 | } | 405 | } |
371 | 406 | ||
372 | static const struct file_operations ptdump_fops = { | 407 | static void ptdump_initialize(void) |
373 | .open = ptdump_open, | ||
374 | .read = seq_read, | ||
375 | .llseek = seq_lseek, | ||
376 | .release = single_release, | ||
377 | }; | ||
378 | |||
379 | static int ptdump_init(void) | ||
380 | { | 408 | { |
381 | struct dentry *pe; | ||
382 | unsigned i, j; | 409 | unsigned i, j; |
383 | 410 | ||
384 | for (i = 0; i < ARRAY_SIZE(pg_level); i++) | 411 | for (i = 0; i < ARRAY_SIZE(pg_level); i++) |
385 | if (pg_level[i].bits) | 412 | if (pg_level[i].bits) |
386 | for (j = 0; j < pg_level[i].num; j++) | 413 | for (j = 0; j < pg_level[i].num; j++) { |
387 | pg_level[i].mask |= pg_level[i].bits[j].mask; | 414 | pg_level[i].mask |= pg_level[i].bits[j].mask; |
415 | if (pg_level[i].bits[j].ro_bit) | ||
416 | pg_level[i].ro_bit = &pg_level[i].bits[j]; | ||
417 | if (pg_level[i].bits[j].nx_bit) | ||
418 | pg_level[i].nx_bit = &pg_level[i].bits[j]; | ||
419 | } | ||
388 | 420 | ||
389 | address_markers[2].start_address = VMALLOC_START; | 421 | address_markers[2].start_address = VMALLOC_START; |
422 | } | ||
423 | |||
424 | static struct ptdump_info kernel_ptdump_info = { | ||
425 | .mm = &init_mm, | ||
426 | .markers = address_markers, | ||
427 | .base_addr = 0, | ||
428 | }; | ||
390 | 429 | ||
391 | pe = debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, | 430 | void ptdump_check_wx(void) |
392 | &ptdump_fops); | 431 | { |
393 | return pe ? 0 : -ENOMEM; | 432 | struct pg_state st = { |
433 | .seq = NULL, | ||
434 | .marker = (struct addr_marker[]) { | ||
435 | { 0, NULL}, | ||
436 | { -1, NULL}, | ||
437 | }, | ||
438 | .check_wx = true, | ||
439 | }; | ||
440 | |||
441 | walk_pgd(&st, &init_mm, 0); | ||
442 | note_page(&st, 0, 0, 0, NULL); | ||
443 | if (st.wx_pages) | ||
444 | pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found\n", | ||
445 | st.wx_pages); | ||
446 | else | ||
447 | pr_info("Checked W+X mappings: passed, no W+X pages found\n"); | ||
448 | } | ||
449 | |||
450 | static int ptdump_init(void) | ||
451 | { | ||
452 | ptdump_initialize(); | ||
453 | return ptdump_debugfs_register(&kernel_ptdump_info, | ||
454 | "kernel_page_tables"); | ||
394 | } | 455 | } |
395 | __initcall(ptdump_init); | 456 | __initcall(ptdump_init); |
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 42f585379e19..b75eada23d0a 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/highmem.h> | 21 | #include <linux/highmem.h> |
22 | #include <linux/perf_event.h> | 22 | #include <linux/perf_event.h> |
23 | 23 | ||
24 | #include <asm/exception.h> | ||
25 | #include <asm/pgtable.h> | 24 | #include <asm/pgtable.h> |
26 | #include <asm/system_misc.h> | 25 | #include <asm/system_misc.h> |
27 | #include <asm/system_info.h> | 26 | #include <asm/system_info.h> |
@@ -545,7 +544,7 @@ hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *) | |||
545 | /* | 544 | /* |
546 | * Dispatch a data abort to the relevant handler. | 545 | * Dispatch a data abort to the relevant handler. |
547 | */ | 546 | */ |
548 | asmlinkage void __exception | 547 | asmlinkage void |
549 | do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | 548 | do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) |
550 | { | 549 | { |
551 | const struct fsr_info *inf = fsr_info + fsr_fs(fsr); | 550 | const struct fsr_info *inf = fsr_info + fsr_fs(fsr); |
@@ -578,7 +577,7 @@ hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs * | |||
578 | ifsr_info[nr].name = name; | 577 | ifsr_info[nr].name = name; |
579 | } | 578 | } |
580 | 579 | ||
581 | asmlinkage void __exception | 580 | asmlinkage void |
582 | do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) | 581 | do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs) |
583 | { | 582 | { |
584 | const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr); | 583 | const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr); |
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 10bfba85eb96..1d1edd064199 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c | |||
@@ -16,8 +16,8 @@ | |||
16 | * are not supported on any CPU using the idmap tables as its current | 16 | * are not supported on any CPU using the idmap tables as its current |
17 | * page tables. | 17 | * page tables. |
18 | */ | 18 | */ |
19 | pgd_t *idmap_pgd; | 19 | pgd_t *idmap_pgd __ro_after_init; |
20 | long long arch_phys_to_idmap_offset; | 20 | long long arch_phys_to_idmap_offset __ro_after_init; |
21 | 21 | ||
22 | #ifdef CONFIG_ARM_LPAE | 22 | #ifdef CONFIG_ARM_LPAE |
23 | static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, | 23 | static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, |
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index a1f11a7ee81b..bd6f4513539a 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <asm/system_info.h> | 36 | #include <asm/system_info.h> |
37 | #include <asm/tlb.h> | 37 | #include <asm/tlb.h> |
38 | #include <asm/fixmap.h> | 38 | #include <asm/fixmap.h> |
39 | #include <asm/ptdump.h> | ||
39 | 40 | ||
40 | #include <asm/mach/arch.h> | 41 | #include <asm/mach/arch.h> |
41 | #include <asm/mach/map.h> | 42 | #include <asm/mach/map.h> |
@@ -738,6 +739,7 @@ static int __mark_rodata_ro(void *unused) | |||
738 | void mark_rodata_ro(void) | 739 | void mark_rodata_ro(void) |
739 | { | 740 | { |
740 | stop_machine(__mark_rodata_ro, NULL, NULL); | 741 | stop_machine(__mark_rodata_ro, NULL, NULL); |
742 | debug_checkwx(); | ||
741 | } | 743 | } |
742 | 744 | ||
743 | void set_kernel_text_rw(void) | 745 | void set_kernel_text_rw(void) |
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index e4370810f4f1..7c087961b7ce 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c | |||
@@ -31,7 +31,7 @@ struct mpu_rgn_info mpu_rgn_info; | |||
31 | 31 | ||
32 | #ifdef CONFIG_CPU_CP15 | 32 | #ifdef CONFIG_CPU_CP15 |
33 | #ifdef CONFIG_CPU_HIGH_VECTOR | 33 | #ifdef CONFIG_CPU_HIGH_VECTOR |
34 | static unsigned long __init setup_vectors_base(void) | 34 | unsigned long setup_vectors_base(void) |
35 | { | 35 | { |
36 | unsigned long reg = get_cr(); | 36 | unsigned long reg = get_cr(); |
37 | 37 | ||
@@ -57,7 +57,7 @@ static inline bool security_extensions_enabled(void) | |||
57 | return 0; | 57 | return 0; |
58 | } | 58 | } |
59 | 59 | ||
60 | static unsigned long __init setup_vectors_base(void) | 60 | unsigned long setup_vectors_base(void) |
61 | { | 61 | { |
62 | unsigned long base = 0, reg = get_cr(); | 62 | unsigned long base = 0, reg = get_cr(); |
63 | 63 | ||
diff --git a/arch/arm/mm/pmsa-v7.c b/arch/arm/mm/pmsa-v7.c index 976df60ac426..e2853bfff74e 100644 --- a/arch/arm/mm/pmsa-v7.c +++ b/arch/arm/mm/pmsa-v7.c | |||
@@ -6,6 +6,7 @@ | |||
6 | 6 | ||
7 | #include <linux/bitops.h> | 7 | #include <linux/bitops.h> |
8 | #include <linux/memblock.h> | 8 | #include <linux/memblock.h> |
9 | #include <linux/string.h> | ||
9 | 10 | ||
10 | #include <asm/cacheflush.h> | 11 | #include <asm/cacheflush.h> |
11 | #include <asm/cp15.h> | 12 | #include <asm/cp15.h> |
@@ -296,6 +297,7 @@ void __init adjust_lowmem_bounds_mpu(void) | |||
296 | } | 297 | } |
297 | } | 298 | } |
298 | 299 | ||
300 | memset(mem, 0, sizeof(mem)); | ||
299 | num = allocate_region(mem_start, specified_mem_size, mem_max_regions, mem); | 301 | num = allocate_region(mem_start, specified_mem_size, mem_max_regions, mem); |
300 | 302 | ||
301 | for (i = 0; i < num; i++) { | 303 | for (i = 0; i < num; i++) { |
@@ -433,7 +435,7 @@ void __init mpu_setup(void) | |||
433 | 435 | ||
434 | /* Background */ | 436 | /* Background */ |
435 | err |= mpu_setup_region(region++, 0, 32, | 437 | err |= mpu_setup_region(region++, 0, 32, |
436 | MPU_ACR_XN | MPU_RGN_STRONGLY_ORDERED | MPU_AP_PL1RW_PL0NA, | 438 | MPU_ACR_XN | MPU_RGN_STRONGLY_ORDERED | MPU_AP_PL1RW_PL0RW, |
437 | 0, false); | 439 | 0, false); |
438 | 440 | ||
439 | #ifdef CONFIG_XIP_KERNEL | 441 | #ifdef CONFIG_XIP_KERNEL |
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 01d64c0b2563..d55d493f9a1e 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
@@ -567,7 +567,7 @@ __v7_setup_stack: | |||
567 | /* | 567 | /* |
568 | * Standard v7 proc info content | 568 | * Standard v7 proc info content |
569 | */ | 569 | */ |
570 | .macro __v7_proc name, initfunc, mm_mmuflags = 0, io_mmuflags = 0, hwcaps = 0, proc_fns = v7_processor_functions | 570 | .macro __v7_proc name, initfunc, mm_mmuflags = 0, io_mmuflags = 0, hwcaps = 0, proc_fns = v7_processor_functions, cache_fns = v7_cache_fns |
571 | ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \ | 571 | ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \ |
572 | PMD_SECT_AF | PMD_FLAGS_SMP | \mm_mmuflags) | 572 | PMD_SECT_AF | PMD_FLAGS_SMP | \mm_mmuflags) |
573 | ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \ | 573 | ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \ |
@@ -583,7 +583,7 @@ __v7_setup_stack: | |||
583 | .long \proc_fns | 583 | .long \proc_fns |
584 | .long v7wbi_tlb_fns | 584 | .long v7wbi_tlb_fns |
585 | .long v6_user_fns | 585 | .long v6_user_fns |
586 | .long v7_cache_fns | 586 | .long \cache_fns |
587 | .endm | 587 | .endm |
588 | 588 | ||
589 | #ifndef CONFIG_ARM_LPAE | 589 | #ifndef CONFIG_ARM_LPAE |
@@ -678,7 +678,7 @@ __v7_ca15mp_proc_info: | |||
678 | __v7_b15mp_proc_info: | 678 | __v7_b15mp_proc_info: |
679 | .long 0x420f00f0 | 679 | .long 0x420f00f0 |
680 | .long 0xff0ffff0 | 680 | .long 0xff0ffff0 |
681 | __v7_proc __v7_b15mp_proc_info, __v7_b15mp_setup | 681 | __v7_proc __v7_b15mp_proc_info, __v7_b15mp_setup, cache_fns = b15_cache_fns |
682 | .size __v7_b15mp_proc_info, . - __v7_b15mp_proc_info | 682 | .size __v7_b15mp_proc_info, . - __v7_b15mp_proc_info |
683 | 683 | ||
684 | /* | 684 | /* |
diff --git a/arch/arm/mm/ptdump_debugfs.c b/arch/arm/mm/ptdump_debugfs.c new file mode 100644 index 000000000000..be8d87be4b93 --- /dev/null +++ b/arch/arm/mm/ptdump_debugfs.c | |||
@@ -0,0 +1,34 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | #include <linux/debugfs.h> | ||
3 | #include <linux/seq_file.h> | ||
4 | |||
5 | #include <asm/ptdump.h> | ||
6 | |||
7 | static int ptdump_show(struct seq_file *m, void *v) | ||
8 | { | ||
9 | struct ptdump_info *info = m->private; | ||
10 | |||
11 | ptdump_walk_pgd(m, info); | ||
12 | return 0; | ||
13 | } | ||
14 | |||
15 | static int ptdump_open(struct inode *inode, struct file *file) | ||
16 | { | ||
17 | return single_open(file, ptdump_show, inode->i_private); | ||
18 | } | ||
19 | |||
20 | static const struct file_operations ptdump_fops = { | ||
21 | .open = ptdump_open, | ||
22 | .read = seq_read, | ||
23 | .llseek = seq_lseek, | ||
24 | .release = single_release, | ||
25 | }; | ||
26 | |||
27 | int ptdump_debugfs_register(struct ptdump_info *info, const char *name) | ||
28 | { | ||
29 | struct dentry *pe; | ||
30 | |||
31 | pe = debugfs_create_file(name, 0400, NULL, info, &ptdump_fops); | ||
32 | return pe ? 0 : -ENOMEM; | ||
33 | |||
34 | } | ||
diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c index 52d1cd14fda4..e90cc8a08186 100644 --- a/arch/arm/probes/kprobes/core.c +++ b/arch/arm/probes/kprobes/core.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/percpu.h> | 32 | #include <linux/percpu.h> |
33 | #include <linux/bug.h> | 33 | #include <linux/bug.h> |
34 | #include <asm/patch.h> | 34 | #include <asm/patch.h> |
35 | #include <asm/sections.h> | ||
35 | 36 | ||
36 | #include "../decode-arm.h" | 37 | #include "../decode-arm.h" |
37 | #include "../decode-thumb.h" | 38 | #include "../decode-thumb.h" |
@@ -64,9 +65,6 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
64 | int is; | 65 | int is; |
65 | const struct decode_checker **checkers; | 66 | const struct decode_checker **checkers; |
66 | 67 | ||
67 | if (in_exception_text(addr)) | ||
68 | return -EINVAL; | ||
69 | |||
70 | #ifdef CONFIG_THUMB2_KERNEL | 68 | #ifdef CONFIG_THUMB2_KERNEL |
71 | thumb = true; | 69 | thumb = true; |
72 | addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */ | 70 | addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */ |
@@ -680,3 +678,13 @@ int __init arch_init_kprobes() | |||
680 | #endif | 678 | #endif |
681 | return 0; | 679 | return 0; |
682 | } | 680 | } |
681 | |||
682 | bool arch_within_kprobe_blacklist(unsigned long addr) | ||
683 | { | ||
684 | void *a = (void *)addr; | ||
685 | |||
686 | return __in_irqentry_text(addr) || | ||
687 | in_entry_text(addr) || | ||
688 | in_idmap_text(addr) || | ||
689 | memory_contains(__kprobes_text_start, __kprobes_text_end, a, 1); | ||
690 | } | ||
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 331f863c605e..715b39ae5a46 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c | |||
@@ -765,7 +765,7 @@ static int imxdma_alloc_chan_resources(struct dma_chan *chan) | |||
765 | desc = kzalloc(sizeof(*desc), GFP_KERNEL); | 765 | desc = kzalloc(sizeof(*desc), GFP_KERNEL); |
766 | if (!desc) | 766 | if (!desc) |
767 | break; | 767 | break; |
768 | __memzero(&desc->desc, sizeof(struct dma_async_tx_descriptor)); | 768 | memset(&desc->desc, 0, sizeof(struct dma_async_tx_descriptor)); |
769 | dma_async_tx_descriptor_init(&desc->desc, chan); | 769 | dma_async_tx_descriptor_init(&desc->desc, chan); |
770 | desc->desc.tx_submit = imxdma_tx_submit; | 770 | desc->desc.tx_submit = imxdma_tx_submit; |
771 | /* txd.flags will be overwritten in prep funcs */ | 771 | /* txd.flags will be overwritten in prep funcs */ |
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 2c787c5cad3d..5172ad0daa7c 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h | |||
@@ -59,6 +59,7 @@ enum cpuhp_state { | |||
59 | CPUHP_PCI_XGENE_DEAD, | 59 | CPUHP_PCI_XGENE_DEAD, |
60 | CPUHP_IOMMU_INTEL_DEAD, | 60 | CPUHP_IOMMU_INTEL_DEAD, |
61 | CPUHP_LUSTRE_CFS_DEAD, | 61 | CPUHP_LUSTRE_CFS_DEAD, |
62 | CPUHP_AP_ARM_CACHE_B15_RAC_DEAD, | ||
62 | CPUHP_WORKQUEUE_PREP, | 63 | CPUHP_WORKQUEUE_PREP, |
63 | CPUHP_POWER_NUMA_PREPARE, | 64 | CPUHP_POWER_NUMA_PREPARE, |
64 | CPUHP_HRTIMERS_PREPARE, | 65 | CPUHP_HRTIMERS_PREPARE, |
@@ -138,6 +139,7 @@ enum cpuhp_state { | |||
138 | CPUHP_AP_ARM64_ISNDEP_STARTING, | 139 | CPUHP_AP_ARM64_ISNDEP_STARTING, |
139 | CPUHP_AP_SMPCFD_DYING, | 140 | CPUHP_AP_SMPCFD_DYING, |
140 | CPUHP_AP_X86_TBOOT_DYING, | 141 | CPUHP_AP_X86_TBOOT_DYING, |
142 | CPUHP_AP_ARM_CACHE_B15_RAC_DYING, | ||
141 | CPUHP_AP_ONLINE, | 143 | CPUHP_AP_ONLINE, |
142 | CPUHP_TEARDOWN_CPU, | 144 | CPUHP_TEARDOWN_CPU, |
143 | CPUHP_AP_ONLINE_IDLE, | 145 | CPUHP_AP_ONLINE_IDLE, |