diff options
author | Linus Torvalds | 2017-05-09 12:10:15 -0500 |
---|---|---|
committer | Linus Torvalds | 2017-05-09 12:10:15 -0500 |
commit | 4a1e31c68e9f40be32838944931178b0d9ed9162 (patch) | |
tree | 98b2cd1280ec759543a07a9517db04706ebf5de5 /arch | |
parent | c6778ff813d2ca3e3c8733c87dc8b6831a64578b (diff) | |
parent | cf4100d1cddcd243f80ac2af2e4c4273919ff225 (diff) | |
download | kernel-4a1e31c68e9f40be32838944931178b0d9ed9162.tar.gz kernel-4a1e31c68e9f40be32838944931178b0d9ed9162.tar.xz kernel-4a1e31c68e9f40be32838944931178b0d9ed9162.zip |
Pull ARC updates from Vineet Gupta:
- AXS10x platform clk updates for I2S, PGU
- add region based cache flush operation for ARCv2 cores
- enforce PAE40 dependency on HIGHMEM
- ptrace support for additional regs in ARCv2 cores
- fix build failure in linux-next dut to a header include ordering
change
* tag 'arc-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc:
Revert "ARCv2: Allow enabling PAE40 w/o HIGHMEM"
ARC: mm: fix build failure in linux-next for UP builds
ARCv2: ptrace: provide regset for accumulator/r30 regs
elf: Add ARCv2 specific core note section
ARCv2: mm: micro-optimize region flush generated code
ARCv2: mm: Merge 2 updates to DC_CTRL for region flush
ARCv2: mm: Implement cache region flush operations
ARC: mm: Move full_page computation into cache version agnostic wrapper
arc: axs10x: Fix ARC PGU default clock frequency
arc: axs10x: Add DT bindings for I2S audio playback
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arc/Kconfig | 1 | ||||
-rw-r--r-- | arch/arc/boot/dts/axs10x_mb.dtsi | 24 | ||||
-rw-r--r-- | arch/arc/include/asm/cache.h | 6 | ||||
-rw-r--r-- | arch/arc/include/asm/mmu.h | 4 | ||||
-rw-r--r-- | arch/arc/include/asm/pgtable.h | 6 | ||||
-rw-r--r-- | arch/arc/include/uapi/asm/elf.h | 1 | ||||
-rw-r--r-- | arch/arc/include/uapi/asm/ptrace.h | 5 | ||||
-rw-r--r-- | arch/arc/kernel/ptrace.c | 62 | ||||
-rw-r--r-- | arch/arc/mm/cache.c | 111 |
9 files changed, 196 insertions, 24 deletions
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 5d7fb3e7cb97..a5459698f0ee 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig | |||
@@ -444,6 +444,7 @@ config ARC_HAS_PAE40 | |||
444 | bool "Support for the 40-bit Physical Address Extension" | 444 | bool "Support for the 40-bit Physical Address Extension" |
445 | default n | 445 | default n |
446 | depends on ISA_ARCV2 | 446 | depends on ISA_ARCV2 |
447 | select HIGHMEM | ||
447 | help | 448 | help |
448 | Enable access to physical memory beyond 4G, only supported on | 449 | Enable access to physical memory beyond 4G, only supported on |
449 | ARC cores with 40 bit Physical Addressing support | 450 | ARC cores with 40 bit Physical Addressing support |
diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi index d6c1bbc98ac3..41cfb29b62c1 100644 --- a/arch/arc/boot/dts/axs10x_mb.dtsi +++ b/arch/arc/boot/dts/axs10x_mb.dtsi | |||
@@ -51,7 +51,7 @@ | |||
51 | pguclk: pguclk { | 51 | pguclk: pguclk { |
52 | #clock-cells = <0>; | 52 | #clock-cells = <0>; |
53 | compatible = "fixed-clock"; | 53 | compatible = "fixed-clock"; |
54 | clock-frequency = <74440000>; | 54 | clock-frequency = <74250000>; |
55 | }; | 55 | }; |
56 | }; | 56 | }; |
57 | 57 | ||
@@ -149,12 +149,13 @@ | |||
149 | interrupts = <14>; | 149 | interrupts = <14>; |
150 | }; | 150 | }; |
151 | 151 | ||
152 | i2c@0x1e000 { | 152 | i2s: i2s@1e000 { |
153 | compatible = "snps,designware-i2c"; | 153 | compatible = "snps,designware-i2s"; |
154 | reg = <0x1e000 0x100>; | 154 | reg = <0x1e000 0x100>; |
155 | clock-frequency = <400000>; | 155 | clocks = <&i2sclk 0>; |
156 | clocks = <&i2cclk>; | 156 | clock-names = "i2sclk"; |
157 | interrupts = <15>; | 157 | interrupts = <15>; |
158 | #sound-dai-cells = <0>; | ||
158 | }; | 159 | }; |
159 | 160 | ||
160 | i2c@0x1f000 { | 161 | i2c@0x1f000 { |
@@ -174,6 +175,7 @@ | |||
174 | adi,input-colorspace = "rgb"; | 175 | adi,input-colorspace = "rgb"; |
175 | adi,input-clock = "1x"; | 176 | adi,input-clock = "1x"; |
176 | adi,clock-delay = <0x03>; | 177 | adi,clock-delay = <0x03>; |
178 | #sound-dai-cells = <0>; | ||
177 | 179 | ||
178 | ports { | 180 | ports { |
179 | #address-cells = <1>; | 181 | #address-cells = <1>; |
@@ -295,5 +297,17 @@ | |||
295 | }; | 297 | }; |
296 | }; | 298 | }; |
297 | }; | 299 | }; |
300 | |||
301 | sound_playback { | ||
302 | compatible = "simple-audio-card"; | ||
303 | simple-audio-card,name = "AXS10x HDMI Audio"; | ||
304 | simple-audio-card,format = "i2s"; | ||
305 | simple-audio-card,cpu { | ||
306 | sound-dai = <&i2s>; | ||
307 | }; | ||
308 | simple-audio-card,codec { | ||
309 | sound-dai = <&adv7511>; | ||
310 | }; | ||
311 | }; | ||
298 | }; | 312 | }; |
299 | }; | 313 | }; |
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 5008021fba98..19ebddffb279 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h | |||
@@ -62,6 +62,8 @@ extern unsigned long perip_base, perip_end; | |||
62 | #define ARC_REG_IC_BCR 0x77 /* Build Config reg */ | 62 | #define ARC_REG_IC_BCR 0x77 /* Build Config reg */ |
63 | #define ARC_REG_IC_IVIC 0x10 | 63 | #define ARC_REG_IC_IVIC 0x10 |
64 | #define ARC_REG_IC_CTRL 0x11 | 64 | #define ARC_REG_IC_CTRL 0x11 |
65 | #define ARC_REG_IC_IVIR 0x16 | ||
66 | #define ARC_REG_IC_ENDR 0x17 | ||
65 | #define ARC_REG_IC_IVIL 0x19 | 67 | #define ARC_REG_IC_IVIL 0x19 |
66 | #define ARC_REG_IC_PTAG 0x1E | 68 | #define ARC_REG_IC_PTAG 0x1E |
67 | #define ARC_REG_IC_PTAG_HI 0x1F | 69 | #define ARC_REG_IC_PTAG_HI 0x1F |
@@ -76,6 +78,8 @@ extern unsigned long perip_base, perip_end; | |||
76 | #define ARC_REG_DC_IVDL 0x4A | 78 | #define ARC_REG_DC_IVDL 0x4A |
77 | #define ARC_REG_DC_FLSH 0x4B | 79 | #define ARC_REG_DC_FLSH 0x4B |
78 | #define ARC_REG_DC_FLDL 0x4C | 80 | #define ARC_REG_DC_FLDL 0x4C |
81 | #define ARC_REG_DC_STARTR 0x4D | ||
82 | #define ARC_REG_DC_ENDR 0x4E | ||
79 | #define ARC_REG_DC_PTAG 0x5C | 83 | #define ARC_REG_DC_PTAG 0x5C |
80 | #define ARC_REG_DC_PTAG_HI 0x5F | 84 | #define ARC_REG_DC_PTAG_HI 0x5F |
81 | 85 | ||
@@ -83,6 +87,8 @@ extern unsigned long perip_base, perip_end; | |||
83 | #define DC_CTRL_DIS 0x001 | 87 | #define DC_CTRL_DIS 0x001 |
84 | #define DC_CTRL_INV_MODE_FLUSH 0x040 | 88 | #define DC_CTRL_INV_MODE_FLUSH 0x040 |
85 | #define DC_CTRL_FLUSH_STATUS 0x100 | 89 | #define DC_CTRL_FLUSH_STATUS 0x100 |
90 | #define DC_CTRL_RGN_OP_INV 0x200 | ||
91 | #define DC_CTRL_RGN_OP_MSK 0x200 | ||
86 | 92 | ||
87 | /*System-level cache (L2 cache) related Auxiliary registers */ | 93 | /*System-level cache (L2 cache) related Auxiliary registers */ |
88 | #define ARC_REG_SLC_CFG 0x901 | 94 | #define ARC_REG_SLC_CFG 0x901 |
diff --git a/arch/arc/include/asm/mmu.h b/arch/arc/include/asm/mmu.h index b144d7ca7d20..db7319e9b506 100644 --- a/arch/arc/include/asm/mmu.h +++ b/arch/arc/include/asm/mmu.h | |||
@@ -9,6 +9,10 @@ | |||
9 | #ifndef _ASM_ARC_MMU_H | 9 | #ifndef _ASM_ARC_MMU_H |
10 | #define _ASM_ARC_MMU_H | 10 | #define _ASM_ARC_MMU_H |
11 | 11 | ||
12 | #ifndef __ASSEMBLY__ | ||
13 | #include <linux/threads.h> /* NR_CPUS */ | ||
14 | #endif | ||
15 | |||
12 | #if defined(CONFIG_ARC_MMU_V1) | 16 | #if defined(CONFIG_ARC_MMU_V1) |
13 | #define CONFIG_ARC_MMU_VER 1 | 17 | #define CONFIG_ARC_MMU_VER 1 |
14 | #elif defined(CONFIG_ARC_MMU_V2) | 18 | #elif defined(CONFIG_ARC_MMU_V2) |
diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h index ee22d40afef4..08fe33830d4b 100644 --- a/arch/arc/include/asm/pgtable.h +++ b/arch/arc/include/asm/pgtable.h | |||
@@ -35,11 +35,11 @@ | |||
35 | #ifndef _ASM_ARC_PGTABLE_H | 35 | #ifndef _ASM_ARC_PGTABLE_H |
36 | #define _ASM_ARC_PGTABLE_H | 36 | #define _ASM_ARC_PGTABLE_H |
37 | 37 | ||
38 | #include <asm/page.h> | 38 | #include <linux/const.h> |
39 | #include <asm/mmu.h> | ||
40 | #define __ARCH_USE_5LEVEL_HACK | 39 | #define __ARCH_USE_5LEVEL_HACK |
41 | #include <asm-generic/pgtable-nopmd.h> | 40 | #include <asm-generic/pgtable-nopmd.h> |
42 | #include <linux/const.h> | 41 | #include <asm/page.h> |
42 | #include <asm/mmu.h> /* to propagate CONFIG_ARC_MMU_VER <n> */ | ||
43 | 43 | ||
44 | /************************************************************************** | 44 | /************************************************************************** |
45 | * Page Table Flags | 45 | * Page Table Flags |
diff --git a/arch/arc/include/uapi/asm/elf.h b/arch/arc/include/uapi/asm/elf.h index 0037a587320d..06d95e611616 100644 --- a/arch/arc/include/uapi/asm/elf.h +++ b/arch/arc/include/uapi/asm/elf.h | |||
@@ -27,6 +27,7 @@ typedef unsigned long elf_greg_t; | |||
27 | typedef unsigned long elf_fpregset_t; | 27 | typedef unsigned long elf_fpregset_t; |
28 | 28 | ||
29 | #define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) | 29 | #define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) |
30 | #define ELF_ARCV2REG (sizeof(struct user_regs_arcv2) / sizeof(elf_greg_t)) | ||
30 | 31 | ||
31 | typedef elf_greg_t elf_gregset_t[ELF_NGREG]; | 32 | typedef elf_greg_t elf_gregset_t[ELF_NGREG]; |
32 | 33 | ||
diff --git a/arch/arc/include/uapi/asm/ptrace.h b/arch/arc/include/uapi/asm/ptrace.h index 0b3ef63d4a03..dd206e6b482c 100644 --- a/arch/arc/include/uapi/asm/ptrace.h +++ b/arch/arc/include/uapi/asm/ptrace.h | |||
@@ -47,6 +47,11 @@ struct user_regs_struct { | |||
47 | unsigned long efa; /* break pt addr, for break points in delay slots */ | 47 | unsigned long efa; /* break pt addr, for break points in delay slots */ |
48 | unsigned long stop_pc; /* give dbg stop_pc after ensuring brkpt trap */ | 48 | unsigned long stop_pc; /* give dbg stop_pc after ensuring brkpt trap */ |
49 | }; | 49 | }; |
50 | |||
51 | struct user_regs_arcv2 { | ||
52 | unsigned long r30, r58, r59; | ||
53 | }; | ||
54 | |||
50 | #endif /* !__ASSEMBLY__ */ | 55 | #endif /* !__ASSEMBLY__ */ |
51 | 56 | ||
52 | #endif /* _UAPI__ASM_ARC_PTRACE_H */ | 57 | #endif /* _UAPI__ASM_ARC_PTRACE_H */ |
diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c index 31150060d38b..5ee4676f135d 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c | |||
@@ -184,19 +184,75 @@ static int genregs_set(struct task_struct *target, | |||
184 | return ret; | 184 | return ret; |
185 | } | 185 | } |
186 | 186 | ||
187 | #ifdef CONFIG_ISA_ARCV2 | ||
188 | static int arcv2regs_get(struct task_struct *target, | ||
189 | const struct user_regset *regset, | ||
190 | unsigned int pos, unsigned int count, | ||
191 | void *kbuf, void __user *ubuf) | ||
192 | { | ||
193 | const struct pt_regs *regs = task_pt_regs(target); | ||
194 | int ret, copy_sz; | ||
195 | |||
196 | if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS)) | ||
197 | copy_sz = sizeof(struct user_regs_arcv2); | ||
198 | else | ||
199 | copy_sz = 4; /* r30 only */ | ||
200 | |||
201 | /* | ||
202 | * itemized copy not needed like above as layout of regs (r30,r58,r59) | ||
203 | * is exactly same in kernel (pt_regs) and userspace (user_regs_arcv2) | ||
204 | */ | ||
205 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, ®s->r30, | ||
206 | 0, copy_sz); | ||
207 | |||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | static int arcv2regs_set(struct task_struct *target, | ||
212 | const struct user_regset *regset, | ||
213 | unsigned int pos, unsigned int count, | ||
214 | const void *kbuf, const void __user *ubuf) | ||
215 | { | ||
216 | const struct pt_regs *regs = task_pt_regs(target); | ||
217 | int ret, copy_sz; | ||
218 | |||
219 | if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS)) | ||
220 | copy_sz = sizeof(struct user_regs_arcv2); | ||
221 | else | ||
222 | copy_sz = 4; /* r30 only */ | ||
223 | |||
224 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, (void *)®s->r30, | ||
225 | 0, copy_sz); | ||
226 | |||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | #endif | ||
231 | |||
187 | enum arc_getset { | 232 | enum arc_getset { |
188 | REGSET_GENERAL, | 233 | REGSET_CMN, |
234 | REGSET_ARCV2, | ||
189 | }; | 235 | }; |
190 | 236 | ||
191 | static const struct user_regset arc_regsets[] = { | 237 | static const struct user_regset arc_regsets[] = { |
192 | [REGSET_GENERAL] = { | 238 | [REGSET_CMN] = { |
193 | .core_note_type = NT_PRSTATUS, | 239 | .core_note_type = NT_PRSTATUS, |
194 | .n = ELF_NGREG, | 240 | .n = ELF_NGREG, |
195 | .size = sizeof(unsigned long), | 241 | .size = sizeof(unsigned long), |
196 | .align = sizeof(unsigned long), | 242 | .align = sizeof(unsigned long), |
197 | .get = genregs_get, | 243 | .get = genregs_get, |
198 | .set = genregs_set, | 244 | .set = genregs_set, |
199 | } | 245 | }, |
246 | #ifdef CONFIG_ISA_ARCV2 | ||
247 | [REGSET_ARCV2] = { | ||
248 | .core_note_type = NT_ARC_V2, | ||
249 | .n = ELF_ARCV2REG, | ||
250 | .size = sizeof(unsigned long), | ||
251 | .align = sizeof(unsigned long), | ||
252 | .get = arcv2regs_get, | ||
253 | .set = arcv2regs_set, | ||
254 | }, | ||
255 | #endif | ||
200 | }; | 256 | }; |
201 | 257 | ||
202 | static const struct user_regset_view user_arc_view = { | 258 | static const struct user_regset_view user_arc_view = { |
diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c index 928562967f3c..a867575a758b 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c | |||
@@ -21,6 +21,10 @@ | |||
21 | #include <asm/cachectl.h> | 21 | #include <asm/cachectl.h> |
22 | #include <asm/setup.h> | 22 | #include <asm/setup.h> |
23 | 23 | ||
24 | #ifdef CONFIG_ISA_ARCV2 | ||
25 | #define USE_RGN_FLSH 1 | ||
26 | #endif | ||
27 | |||
24 | static int l2_line_sz; | 28 | static int l2_line_sz; |
25 | static int ioc_exists; | 29 | static int ioc_exists; |
26 | int slc_enable = 1, ioc_enable = 1; | 30 | int slc_enable = 1, ioc_enable = 1; |
@@ -28,7 +32,7 @@ unsigned long perip_base = ARC_UNCACHED_ADDR_SPACE; /* legacy value for boot */ | |||
28 | unsigned long perip_end = 0xFFFFFFFF; /* legacy value */ | 32 | unsigned long perip_end = 0xFFFFFFFF; /* legacy value */ |
29 | 33 | ||
30 | void (*_cache_line_loop_ic_fn)(phys_addr_t paddr, unsigned long vaddr, | 34 | void (*_cache_line_loop_ic_fn)(phys_addr_t paddr, unsigned long vaddr, |
31 | unsigned long sz, const int cacheop); | 35 | unsigned long sz, const int op, const int full_page); |
32 | 36 | ||
33 | void (*__dma_cache_wback_inv)(phys_addr_t start, unsigned long sz); | 37 | void (*__dma_cache_wback_inv)(phys_addr_t start, unsigned long sz); |
34 | void (*__dma_cache_inv)(phys_addr_t start, unsigned long sz); | 38 | void (*__dma_cache_inv)(phys_addr_t start, unsigned long sz); |
@@ -233,11 +237,10 @@ slc_chk: | |||
233 | 237 | ||
234 | static inline | 238 | static inline |
235 | void __cache_line_loop_v2(phys_addr_t paddr, unsigned long vaddr, | 239 | void __cache_line_loop_v2(phys_addr_t paddr, unsigned long vaddr, |
236 | unsigned long sz, const int op) | 240 | unsigned long sz, const int op, const int full_page) |
237 | { | 241 | { |
238 | unsigned int aux_cmd; | 242 | unsigned int aux_cmd; |
239 | int num_lines; | 243 | int num_lines; |
240 | const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE; | ||
241 | 244 | ||
242 | if (op == OP_INV_IC) { | 245 | if (op == OP_INV_IC) { |
243 | aux_cmd = ARC_REG_IC_IVIL; | 246 | aux_cmd = ARC_REG_IC_IVIL; |
@@ -279,11 +282,10 @@ void __cache_line_loop_v2(phys_addr_t paddr, unsigned long vaddr, | |||
279 | */ | 282 | */ |
280 | static inline | 283 | static inline |
281 | void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr, | 284 | void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr, |
282 | unsigned long sz, const int op) | 285 | unsigned long sz, const int op, const int full_page) |
283 | { | 286 | { |
284 | unsigned int aux_cmd, aux_tag; | 287 | unsigned int aux_cmd, aux_tag; |
285 | int num_lines; | 288 | int num_lines; |
286 | const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE; | ||
287 | 289 | ||
288 | if (op == OP_INV_IC) { | 290 | if (op == OP_INV_IC) { |
289 | aux_cmd = ARC_REG_IC_IVIL; | 291 | aux_cmd = ARC_REG_IC_IVIL; |
@@ -334,6 +336,8 @@ void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr, | |||
334 | } | 336 | } |
335 | } | 337 | } |
336 | 338 | ||
339 | #ifndef USE_RGN_FLSH | ||
340 | |||
337 | /* | 341 | /* |
338 | * In HS38x (MMU v4), I-cache is VIPT (can alias), D-cache is PIPT | 342 | * In HS38x (MMU v4), I-cache is VIPT (can alias), D-cache is PIPT |
339 | * Here's how cache ops are implemented | 343 | * Here's how cache ops are implemented |
@@ -349,17 +353,16 @@ void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr, | |||
349 | */ | 353 | */ |
350 | static inline | 354 | static inline |
351 | void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, | 355 | void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, |
352 | unsigned long sz, const int cacheop) | 356 | unsigned long sz, const int op, const int full_page) |
353 | { | 357 | { |
354 | unsigned int aux_cmd; | 358 | unsigned int aux_cmd; |
355 | int num_lines; | 359 | int num_lines; |
356 | const int full_page_op = __builtin_constant_p(sz) && sz == PAGE_SIZE; | ||
357 | 360 | ||
358 | if (cacheop == OP_INV_IC) { | 361 | if (op == OP_INV_IC) { |
359 | aux_cmd = ARC_REG_IC_IVIL; | 362 | aux_cmd = ARC_REG_IC_IVIL; |
360 | } else { | 363 | } else { |
361 | /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ | 364 | /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ |
362 | aux_cmd = cacheop & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL; | 365 | aux_cmd = op & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL; |
363 | } | 366 | } |
364 | 367 | ||
365 | /* Ensure we properly floor/ceil the non-line aligned/sized requests | 368 | /* Ensure we properly floor/ceil the non-line aligned/sized requests |
@@ -368,7 +371,7 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, | |||
368 | * -@paddr will be cache-line aligned already (being page aligned) | 371 | * -@paddr will be cache-line aligned already (being page aligned) |
369 | * -@sz will be integral multiple of line size (being page sized). | 372 | * -@sz will be integral multiple of line size (being page sized). |
370 | */ | 373 | */ |
371 | if (!full_page_op) { | 374 | if (!full_page) { |
372 | sz += paddr & ~CACHE_LINE_MASK; | 375 | sz += paddr & ~CACHE_LINE_MASK; |
373 | paddr &= CACHE_LINE_MASK; | 376 | paddr &= CACHE_LINE_MASK; |
374 | } | 377 | } |
@@ -381,7 +384,7 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, | |||
381 | * - (and needs to be written before the lower 32 bits) | 384 | * - (and needs to be written before the lower 32 bits) |
382 | */ | 385 | */ |
383 | if (is_pae40_enabled()) { | 386 | if (is_pae40_enabled()) { |
384 | if (cacheop == OP_INV_IC) | 387 | if (op == OP_INV_IC) |
385 | /* | 388 | /* |
386 | * Non aliasing I-cache in HS38, | 389 | * Non aliasing I-cache in HS38, |
387 | * aliasing I-cache handled in __cache_line_loop_v3() | 390 | * aliasing I-cache handled in __cache_line_loop_v3() |
@@ -397,6 +400,55 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, | |||
397 | } | 400 | } |
398 | } | 401 | } |
399 | 402 | ||
403 | #else | ||
404 | |||
405 | /* | ||
406 | * optimized flush operation which takes a region as opposed to iterating per line | ||
407 | */ | ||
408 | static inline | ||
409 | void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, | ||
410 | unsigned long sz, const int op, const int full_page) | ||
411 | { | ||
412 | unsigned int s, e; | ||
413 | |||
414 | /* Only for Non aliasing I-cache in HS38 */ | ||
415 | if (op == OP_INV_IC) { | ||
416 | s = ARC_REG_IC_IVIR; | ||
417 | e = ARC_REG_IC_ENDR; | ||
418 | } else { | ||
419 | s = ARC_REG_DC_STARTR; | ||
420 | e = ARC_REG_DC_ENDR; | ||
421 | } | ||
422 | |||
423 | if (!full_page) { | ||
424 | /* for any leading gap between @paddr and start of cache line */ | ||
425 | sz += paddr & ~CACHE_LINE_MASK; | ||
426 | paddr &= CACHE_LINE_MASK; | ||
427 | |||
428 | /* | ||
429 | * account for any trailing gap to end of cache line | ||
430 | * this is equivalent to DIV_ROUND_UP() in line ops above | ||
431 | */ | ||
432 | sz += L1_CACHE_BYTES - 1; | ||
433 | } | ||
434 | |||
435 | if (is_pae40_enabled()) { | ||
436 | /* TBD: check if crossing 4TB boundary */ | ||
437 | if (op == OP_INV_IC) | ||
438 | write_aux_reg(ARC_REG_IC_PTAG_HI, (u64)paddr >> 32); | ||
439 | else | ||
440 | write_aux_reg(ARC_REG_DC_PTAG_HI, (u64)paddr >> 32); | ||
441 | } | ||
442 | |||
443 | /* ENDR needs to be set ahead of START */ | ||
444 | write_aux_reg(e, paddr + sz); /* ENDR is exclusive */ | ||
445 | write_aux_reg(s, paddr); | ||
446 | |||
447 | /* caller waits on DC_CTRL.FS */ | ||
448 | } | ||
449 | |||
450 | #endif | ||
451 | |||
400 | #if (CONFIG_ARC_MMU_VER < 3) | 452 | #if (CONFIG_ARC_MMU_VER < 3) |
401 | #define __cache_line_loop __cache_line_loop_v2 | 453 | #define __cache_line_loop __cache_line_loop_v2 |
402 | #elif (CONFIG_ARC_MMU_VER == 3) | 454 | #elif (CONFIG_ARC_MMU_VER == 3) |
@@ -411,6 +463,11 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr, | |||
411 | * Machine specific helpers for Entire D-Cache or Per Line ops | 463 | * Machine specific helpers for Entire D-Cache or Per Line ops |
412 | */ | 464 | */ |
413 | 465 | ||
466 | #ifndef USE_RGN_FLSH | ||
467 | /* | ||
468 | * this version avoids extra read/write of DC_CTRL for flush or invalid ops | ||
469 | * in the non region flush regime (such as for ARCompact) | ||
470 | */ | ||
414 | static inline void __before_dc_op(const int op) | 471 | static inline void __before_dc_op(const int op) |
415 | { | 472 | { |
416 | if (op == OP_FLUSH_N_INV) { | 473 | if (op == OP_FLUSH_N_INV) { |
@@ -424,6 +481,32 @@ static inline void __before_dc_op(const int op) | |||
424 | } | 481 | } |
425 | } | 482 | } |
426 | 483 | ||
484 | #else | ||
485 | |||
486 | static inline void __before_dc_op(const int op) | ||
487 | { | ||
488 | const unsigned int ctl = ARC_REG_DC_CTRL; | ||
489 | unsigned int val = read_aux_reg(ctl); | ||
490 | |||
491 | if (op == OP_FLUSH_N_INV) { | ||
492 | val |= DC_CTRL_INV_MODE_FLUSH; | ||
493 | } | ||
494 | |||
495 | if (op != OP_INV_IC) { | ||
496 | /* | ||
497 | * Flush / Invalidate is provided by DC_CTRL.RNG_OP 0 or 1 | ||
498 | * combined Flush-n-invalidate uses DC_CTRL.IM = 1 set above | ||
499 | */ | ||
500 | val &= ~DC_CTRL_RGN_OP_MSK; | ||
501 | if (op & OP_INV) | ||
502 | val |= DC_CTRL_RGN_OP_INV; | ||
503 | } | ||
504 | write_aux_reg(ctl, val); | ||
505 | } | ||
506 | |||
507 | #endif | ||
508 | |||
509 | |||
427 | static inline void __after_dc_op(const int op) | 510 | static inline void __after_dc_op(const int op) |
428 | { | 511 | { |
429 | if (op & OP_FLUSH) { | 512 | if (op & OP_FLUSH) { |
@@ -486,13 +569,14 @@ static void __dc_enable(void) | |||
486 | static inline void __dc_line_op(phys_addr_t paddr, unsigned long vaddr, | 569 | static inline void __dc_line_op(phys_addr_t paddr, unsigned long vaddr, |
487 | unsigned long sz, const int op) | 570 | unsigned long sz, const int op) |
488 | { | 571 | { |
572 | const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE; | ||
489 | unsigned long flags; | 573 | unsigned long flags; |
490 | 574 | ||
491 | local_irq_save(flags); | 575 | local_irq_save(flags); |
492 | 576 | ||
493 | __before_dc_op(op); | 577 | __before_dc_op(op); |
494 | 578 | ||
495 | __cache_line_loop(paddr, vaddr, sz, op); | 579 | __cache_line_loop(paddr, vaddr, sz, op, full_page); |
496 | 580 | ||
497 | __after_dc_op(op); | 581 | __after_dc_op(op); |
498 | 582 | ||
@@ -521,10 +605,11 @@ static inline void | |||
521 | __ic_line_inv_vaddr_local(phys_addr_t paddr, unsigned long vaddr, | 605 | __ic_line_inv_vaddr_local(phys_addr_t paddr, unsigned long vaddr, |
522 | unsigned long sz) | 606 | unsigned long sz) |
523 | { | 607 | { |
608 | const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE; | ||
524 | unsigned long flags; | 609 | unsigned long flags; |
525 | 610 | ||
526 | local_irq_save(flags); | 611 | local_irq_save(flags); |
527 | (*_cache_line_loop_ic_fn)(paddr, vaddr, sz, OP_INV_IC); | 612 | (*_cache_line_loop_ic_fn)(paddr, vaddr, sz, OP_INV_IC, full_page); |
528 | local_irq_restore(flags); | 613 | local_irq_restore(flags); |
529 | } | 614 | } |
530 | 615 | ||