From 16c79a3776c17965dedab4732d925f6098df91c1 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Fri, 28 Mar 2014 12:21:16 +0100 Subject: ARM: 8013/1: PJ4B: Add cpu_suspend/cpu_resume hooks for PJ4B PJ4B needs extra instructions for suspend and resume, so instead of using the armv7 version, this commit introduces specific versions for PJ4B. Signed-off-by: Gregory CLEMENT Signed-off-by: Russell King --- arch/arm/mm/proc-v7.S | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 195731d3813b..b74ea60891d5 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -169,9 +169,31 @@ ENDPROC(cpu_pj4b_do_idle) globl_equ cpu_pj4b_do_idle, cpu_v7_do_idle #endif globl_equ cpu_pj4b_dcache_clean_area, cpu_v7_dcache_clean_area - globl_equ cpu_pj4b_do_suspend, cpu_v7_do_suspend - globl_equ cpu_pj4b_do_resume, cpu_v7_do_resume - globl_equ cpu_pj4b_suspend_size, cpu_v7_suspend_size +#ifdef CONFIG_ARM_CPU_SUSPEND +ENTRY(cpu_pj4b_do_suspend) + stmfd sp!, {r6 - r10} + mrc p15, 1, r6, c15, c1, 0 @ save CP15 - extra features + mrc p15, 1, r7, c15, c2, 0 @ save CP15 - Aux Func Modes Ctrl 0 + mrc p15, 1, r8, c15, c1, 2 @ save CP15 - Aux Debug Modes Ctrl 2 + mrc p15, 1, r9, c15, c1, 1 @ save CP15 - Aux Debug Modes Ctrl 1 + mrc p15, 0, r10, c9, c14, 0 @ save CP15 - PMC + stmia r0!, {r6 - r10} + ldmfd sp!, {r6 - r10} + b cpu_v7_do_suspend +ENDPROC(cpu_pj4b_do_suspend) + +ENTRY(cpu_pj4b_do_resume) + ldmia r0!, {r6 - r10} + mcr p15, 1, r6, c15, c1, 0 @ save CP15 - extra features + mcr p15, 1, r7, c15, c2, 0 @ save CP15 - Aux Func Modes Ctrl 0 + mcr p15, 1, r8, c15, c1, 2 @ save CP15 - Aux Debug Modes Ctrl 2 + mcr p15, 1, r9, c15, c1, 1 @ save CP15 - Aux Debug Modes Ctrl 1 + mcr p15, 0, r10, c9, c14, 0 @ save CP15 - PMC + b cpu_v7_do_resume +ENDPROC(cpu_pj4b_do_resume) +#endif +.globl cpu_pj4b_suspend_size +.equ cpu_pj4b_suspend_size, 4 * 14 #endif -- cgit v1.2.3 From 4221e2e6b3160e4b558df14fa79f025c0e277935 Mon Sep 17 00:00:00 2001 From: Liu Hua Date: Fri, 18 Apr 2014 09:27:01 +0100 Subject: ARM: 8031/1: fixmap: remove FIX_KMAP_BEGIN and FIX_KMAP_END It seems that these two macros are not used by non architecture specific code. And on ARM FIX_KMAP_BEGIN equals zero. This patch removes these two macros. Instead, using FIX_KMAP_NR_PTES to tell the pte number belonged to fixmap mapping region. The code will become clearer when I introduce a bugfix on fixmap mapping region. Reviewed-by: Nicolas Pitre Signed-off-by: Liu Hua Signed-off-by: Russell King --- arch/arm/include/asm/fixmap.h | 5 ++--- arch/arm/mm/highmem.c | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h index bbae919bceb4..be55ebc08ed4 100644 --- a/arch/arm/include/asm/fixmap.h +++ b/arch/arm/include/asm/fixmap.h @@ -17,8 +17,7 @@ #define FIXADDR_TOP 0xfffe0000UL #define FIXADDR_SIZE (FIXADDR_TOP - FIXADDR_START) -#define FIX_KMAP_BEGIN 0 -#define FIX_KMAP_END (FIXADDR_SIZE >> PAGE_SHIFT) +#define FIX_KMAP_NR_PTES (FIXADDR_SIZE >> PAGE_SHIFT) #define __fix_to_virt(x) (FIXADDR_START + ((x) << PAGE_SHIFT)) #define __virt_to_fix(x) (((x) - FIXADDR_START) >> PAGE_SHIFT) @@ -27,7 +26,7 @@ extern void __this_fixmap_does_not_exist(void); static inline unsigned long fix_to_virt(const unsigned int idx) { - if (idx >= FIX_KMAP_END) + if (idx >= FIX_KMAP_NR_PTES) __this_fixmap_does_not_exist(); return __fix_to_virt(idx); } diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c index 21b9e1bf9b77..e05e8ad26ba5 100644 --- a/arch/arm/mm/highmem.c +++ b/arch/arm/mm/highmem.c @@ -63,7 +63,7 @@ void *kmap_atomic(struct page *page) type = kmap_atomic_idx_push(); idx = type + KM_TYPE_NR * smp_processor_id(); - vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); + vaddr = __fix_to_virt(idx); #ifdef CONFIG_DEBUG_HIGHMEM /* * With debugging enabled, kunmap_atomic forces that entry to 0. @@ -94,7 +94,7 @@ void __kunmap_atomic(void *kvaddr) if (cache_is_vivt()) __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); #ifdef CONFIG_DEBUG_HIGHMEM - BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); + BUG_ON(vaddr != __fix_to_virt(idx)); set_top_pte(vaddr, __pte(0)); #else (void) idx; /* to kill a warning */ @@ -117,7 +117,7 @@ void *kmap_atomic_pfn(unsigned long pfn) type = kmap_atomic_idx_push(); idx = type + KM_TYPE_NR * smp_processor_id(); - vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); + vaddr = __fix_to_virt(idx); #ifdef CONFIG_DEBUG_HIGHMEM BUG_ON(!pte_none(get_top_pte(vaddr))); #endif -- cgit v1.2.3 From a05e54c103b0b8e1dab5d04b411f1d48387c4903 Mon Sep 17 00:00:00 2001 From: Liu Hua Date: Fri, 18 Apr 2014 09:43:32 +0100 Subject: ARM: 8031/2: change fixmap mapping region to support 32 CPUs In 32-bit ARM systems, the fixmap mapping region can support no more than 14 CPUs(total: 896k; one CPU: 64K). And we can configure NR_CPUS up to 32. So there is a mismatch. This patch moves fixmapping region downwards to region 0xffc00000- 0xffe00000. Then the fixmap mapping region can support up to 32 CPUs. Reviewed-by: Nicolas Pitre Signed-off-by: Liu Hua Signed-off-by: Russell King --- Documentation/arm/memory.txt | 2 +- arch/arm/include/asm/fixmap.h | 16 ++-------------- arch/arm/include/asm/highmem.h | 1 + arch/arm/mm/highmem.c | 27 +++++++++++++++++++++------ arch/arm/mm/mmu.c | 4 ++++ 5 files changed, 29 insertions(+), 21 deletions(-) (limited to 'arch/arm/mm') diff --git a/Documentation/arm/memory.txt b/Documentation/arm/memory.txt index d74e8a5901fc..256c5e067fb1 100644 --- a/Documentation/arm/memory.txt +++ b/Documentation/arm/memory.txt @@ -41,7 +41,7 @@ fffe8000 fffeffff DTCM mapping area for platforms with fffe0000 fffe7fff ITCM mapping area for platforms with ITCM mounted inside the CPU. -fff00000 fffdffff Fixmap mapping region. Addresses provided +fffc0000 ffdfffff Fixmap mapping region. Addresses provided by fix_to_virt() will be located here. fee00000 feffffff Mapping of PCI I/O space. This is a static diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h index be55ebc08ed4..74124b0d0d79 100644 --- a/arch/arm/include/asm/fixmap.h +++ b/arch/arm/include/asm/fixmap.h @@ -1,20 +1,8 @@ #ifndef _ASM_FIXMAP_H #define _ASM_FIXMAP_H -/* - * Nothing too fancy for now. - * - * On ARM we already have well known fixed virtual addresses imposed by - * the architecture such as the vector page which is located at 0xffff0000, - * therefore a second level page table is already allocated covering - * 0xfff00000 upwards. - * - * The cache flushing code in proc-xscale.S uses the virtual area between - * 0xfffe0000 and 0xfffeffff. - */ - -#define FIXADDR_START 0xfff00000UL -#define FIXADDR_TOP 0xfffe0000UL +#define FIXADDR_START 0xffc00000UL +#define FIXADDR_TOP 0xffe00000UL #define FIXADDR_SIZE (FIXADDR_TOP - FIXADDR_START) #define FIX_KMAP_NR_PTES (FIXADDR_SIZE >> PAGE_SHIFT) diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h index 91b99abe7a95..535579511ed0 100644 --- a/arch/arm/include/asm/highmem.h +++ b/arch/arm/include/asm/highmem.h @@ -18,6 +18,7 @@ } while (0) extern pte_t *pkmap_page_table; +extern pte_t *fixmap_page_table; extern void *kmap_high(struct page *page); extern void kunmap_high(struct page *page); diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c index e05e8ad26ba5..45aeaaca9052 100644 --- a/arch/arm/mm/highmem.c +++ b/arch/arm/mm/highmem.c @@ -18,6 +18,21 @@ #include #include "mm.h" +pte_t *fixmap_page_table; + +static inline void set_fixmap_pte(int idx, pte_t pte) +{ + unsigned long vaddr = __fix_to_virt(idx); + set_pte_ext(fixmap_page_table + idx, pte, 0); + local_flush_tlb_kernel_page(vaddr); +} + +static inline pte_t get_fixmap_pte(unsigned long vaddr) +{ + unsigned long idx = __virt_to_fix(vaddr); + return *(fixmap_page_table + idx); +} + void *kmap(struct page *page) { might_sleep(); @@ -69,14 +84,14 @@ void *kmap_atomic(struct page *page) * With debugging enabled, kunmap_atomic forces that entry to 0. * Make sure it was indeed properly unmapped. */ - BUG_ON(!pte_none(get_top_pte(vaddr))); + BUG_ON(!pte_none(*(fixmap_page_table + idx))); #endif /* * When debugging is off, kunmap_atomic leaves the previous mapping * in place, so the contained TLB flush ensures the TLB is updated * with the new mapping. */ - set_top_pte(vaddr, mk_pte(page, kmap_prot)); + set_fixmap_pte(idx, mk_pte(page, kmap_prot)); return (void *)vaddr; } @@ -95,7 +110,7 @@ void __kunmap_atomic(void *kvaddr) __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); #ifdef CONFIG_DEBUG_HIGHMEM BUG_ON(vaddr != __fix_to_virt(idx)); - set_top_pte(vaddr, __pte(0)); + set_fixmap_pte(idx, __pte(0)); #else (void) idx; /* to kill a warning */ #endif @@ -119,9 +134,9 @@ void *kmap_atomic_pfn(unsigned long pfn) idx = type + KM_TYPE_NR * smp_processor_id(); vaddr = __fix_to_virt(idx); #ifdef CONFIG_DEBUG_HIGHMEM - BUG_ON(!pte_none(get_top_pte(vaddr))); + BUG_ON(!pte_none(*(fixmap_page_table + idx))); #endif - set_top_pte(vaddr, pfn_pte(pfn, kmap_prot)); + set_fixmap_pte(idx, pfn_pte(pfn, kmap_prot)); return (void *)vaddr; } @@ -133,5 +148,5 @@ struct page *kmap_atomic_to_page(const void *ptr) if (vaddr < FIXADDR_START) return virt_to_page(ptr); - return pte_page(get_top_pte(vaddr)); + return pte_page(get_fixmap_pte(vaddr)); } diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index b68c6b22e1c8..09c0a16165dc 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "mm.h" #include "tcm.h" @@ -1359,6 +1360,9 @@ static void __init kmap_init(void) #ifdef CONFIG_HIGHMEM pkmap_page_table = early_pte_alloc(pmd_off_k(PKMAP_BASE), PKMAP_BASE, _PAGE_KERNEL_TABLE); + + fixmap_page_table = early_pte_alloc(pmd_off_k(FIXADDR_START), + FIXADDR_START, _PAGE_KERNEL_TABLE); #endif } -- cgit v1.2.3 From 86f40622af7329375e38f282f6c0aab95f3e5f72 Mon Sep 17 00:00:00 2001 From: Jianguo Wu Date: Thu, 24 Apr 2014 03:45:56 +0100 Subject: ARM: 8037/1: mm: support big-endian page tables When enable LPAE and big-endian in a hisilicon board, while specify mem=384M mem=512M@7680M, will get bad page state: Freeing unused kernel memory: 180K (c0466000 - c0493000) BUG: Bad page state in process init pfn:fa442 page:c7749840 count:0 mapcount:-1 mapping: (null) index:0x0 page flags: 0x40000400(reserved) Modules linked in: CPU: 0 PID: 1 Comm: init Not tainted 3.10.27+ #66 [] (unwind_backtrace+0x0/0x11c) from [] (show_stack+0x10/0x14) [] (show_stack+0x10/0x14) from [] (bad_page+0xd4/0x104) [] (bad_page+0xd4/0x104) from [] (free_pages_prepare+0xa8/0x14c) [] (free_pages_prepare+0xa8/0x14c) from [] (free_hot_cold_page+0x18/0xf0) [] (free_hot_cold_page+0x18/0xf0) from [] (handle_pte_fault+0xcf4/0xdc8) [] (handle_pte_fault+0xcf4/0xdc8) from [] (handle_mm_fault+0xf4/0x120) [] (handle_mm_fault+0xf4/0x120) from [] (do_page_fault+0xfc/0x354) [] (do_page_fault+0xfc/0x354) from [] (do_DataAbort+0x2c/0x90) [] (do_DataAbort+0x2c/0x90) from [] (__dabt_usr+0x34/0x40) The bad pfn:fa442 is not system memory(mem=384M mem=512M@7680M), after debugging, I find in page fault handler, will get wrong pfn from pte just after set pte, as follow: do_anonymous_page() { ... set_pte_at(mm, address, page_table, entry); //debug code pfn = pte_pfn(entry); pr_info("pfn:0x%lx, pte:0x%llxn", pfn, pte_val(entry)); //read out the pte just set new_pte = pte_offset_map(pmd, address); new_pfn = pte_pfn(*new_pte); pr_info("new pfn:0x%lx, new pte:0x%llxn", pfn, pte_val(entry)); ... } pfn: 0x1fa4f5, pte:0xc00001fa4f575f new_pfn:0xfa4f5, new_pte:0xc00000fa4f5f5f //new pfn/pte is wrong. The bug is happened in cpu_v7_set_pte_ext(ptep, pte): An LPAE PTE is a 64bit quantity, passed to cpu_v7_set_pte_ext in the r2 and r3 registers. On an LE kernel, r2 contains the LSB of the PTE, and r3 the MSB. On a BE kernel, the assignment is reversed. Unfortunately, the current code always assumes the LE case, leading to corruption of the PTE when clearing/setting bits. This patch fixes this issue much like it has been done already in the cpu_v7_switch_mm case. CC stable Signed-off-by: Jianguo Wu Acked-by: Marc Zyngier Acked-by: Will Deacon Signed-off-by: Russell King --- arch/arm/mm/proc-v7-3level.S | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S index 01a719e18bb0..22e3ad63500c 100644 --- a/arch/arm/mm/proc-v7-3level.S +++ b/arch/arm/mm/proc-v7-3level.S @@ -64,6 +64,14 @@ ENTRY(cpu_v7_switch_mm) mov pc, lr ENDPROC(cpu_v7_switch_mm) +#ifdef __ARMEB__ +#define rl r3 +#define rh r2 +#else +#define rl r2 +#define rh r3 +#endif + /* * cpu_v7_set_pte_ext(ptep, pte) * @@ -73,13 +81,13 @@ ENDPROC(cpu_v7_switch_mm) */ ENTRY(cpu_v7_set_pte_ext) #ifdef CONFIG_MMU - tst r2, #L_PTE_VALID + tst rl, #L_PTE_VALID beq 1f - tst r3, #1 << (57 - 32) @ L_PTE_NONE - bicne r2, #L_PTE_VALID + tst rh, #1 << (57 - 32) @ L_PTE_NONE + bicne rl, #L_PTE_VALID bne 1f - tst r3, #1 << (55 - 32) @ L_PTE_DIRTY - orreq r2, #L_PTE_RDONLY + tst rh, #1 << (55 - 32) @ L_PTE_DIRTY + orreq rl, #L_PTE_RDONLY 1: strd r2, r3, [r0] ALT_SMP(W(nop)) ALT_UP (mcr p15, 0, r0, c7, c10, 1) @ flush_pte -- cgit v1.2.3 From 2161c2485d03520060f6094359b22f33913eefa2 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 24 Apr 2014 11:30:07 -0400 Subject: ARM: dma: use phys_addr_t in __dma_page_[cpu_to_dev/dev_to_cpu] On a 32 bit ARM architecture with LPAE extension physical addresses cannot fit into unsigned long variable. So fix it by using phys_addr_t instead of unsigned long. Cc: Nicolas Pitre Cc: Russell King - ARM Linux Cc: Catalin Marinas Acked-by: Will Deacon Signed-off-by: Santosh Shilimkar --- arch/arm/mm/dma-mapping.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index f62aa0677e5c..5260f43c3d03 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -885,7 +885,7 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset, static void __dma_page_cpu_to_dev(struct page *page, unsigned long off, size_t size, enum dma_data_direction dir) { - unsigned long paddr; + phys_addr_t paddr; dma_cache_maint_page(page, off, size, dir, dmac_map_area); @@ -901,7 +901,7 @@ static void __dma_page_cpu_to_dev(struct page *page, unsigned long off, static void __dma_page_dev_to_cpu(struct page *page, unsigned long off, size_t size, enum dma_data_direction dir) { - unsigned long paddr = page_to_phys(page) + off; + phys_addr_t paddr = page_to_phys(page) + off; /* FIXME: non-speculating: not required */ /* don't bother invalidating if DMA to device */ -- cgit v1.2.3 From 265c271c822bd57677e3b286389487fd45e6960d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:44 +0000 Subject: ARM: l2c: remove outer_inv_all() method No one ever calls this function anywhere in the kernel, so let's completely remove it from the outer cache API and turn it into an internal-only thing. Signed-off-by: Russell King --- arch/arm/include/asm/outercache.h | 8 -------- arch/arm/mm/cache-feroceon-l2.c | 1 - arch/arm/mm/cache-l2x0.c | 5 ----- 3 files changed, 14 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index f94784f0e3a6..0e4420858990 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h @@ -28,7 +28,6 @@ struct outer_cache_fns { void (*clean_range)(unsigned long, unsigned long); void (*flush_range)(unsigned long, unsigned long); void (*flush_all)(void); - void (*inv_all)(void); void (*disable)(void); #ifdef CONFIG_OUTER_CACHE_SYNC void (*sync)(void); @@ -63,12 +62,6 @@ static inline void outer_flush_all(void) outer_cache.flush_all(); } -static inline void outer_inv_all(void) -{ - if (outer_cache.inv_all) - outer_cache.inv_all(); -} - static inline void outer_disable(void) { if (outer_cache.disable) @@ -90,7 +83,6 @@ static inline void outer_clean_range(phys_addr_t start, phys_addr_t end) static inline void outer_flush_range(phys_addr_t start, phys_addr_t end) { } static inline void outer_flush_all(void) { } -static inline void outer_inv_all(void) { } static inline void outer_disable(void) { } static inline void outer_resume(void) { } diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c index dc814a548056..e028a7f2ebcc 100644 --- a/arch/arm/mm/cache-feroceon-l2.c +++ b/arch/arm/mm/cache-feroceon-l2.c @@ -350,7 +350,6 @@ void __init feroceon_l2_init(int __l2_wt_override) outer_cache.inv_range = feroceon_l2_inv_range; outer_cache.clean_range = feroceon_l2_clean_range; outer_cache.flush_range = feroceon_l2_flush_range; - outer_cache.inv_all = l2_inv_all; enable_l2(); diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 7abde2ce8973..f9985e5a208c 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -414,7 +414,6 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) outer_cache.flush_range = l2x0_flush_range; outer_cache.sync = l2x0_cache_sync; outer_cache.flush_all = l2x0_flush_all; - outer_cache.inv_all = l2x0_inv_all; outer_cache.disable = l2x0_disable; } @@ -884,7 +883,6 @@ static const struct l2x0_of_data pl310_data = { .flush_range = l2x0_flush_range, .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, - .inv_all = l2x0_inv_all, .disable = l2x0_disable, }, }; @@ -899,7 +897,6 @@ static const struct l2x0_of_data l2x0_data = { .flush_range = l2x0_flush_range, .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, - .inv_all = l2x0_inv_all, .disable = l2x0_disable, }, }; @@ -914,7 +911,6 @@ static const struct l2x0_of_data aurora_with_outer_data = { .flush_range = aurora_flush_range, .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, - .inv_all = l2x0_inv_all, .disable = l2x0_disable, }, }; @@ -946,7 +942,6 @@ static const struct l2x0_of_data bcm_l2x0_data = { .flush_range = bcm_flush_range, .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, - .inv_all = l2x0_inv_all, .disable = l2x0_disable, }, }; -- cgit v1.2.3 From 4585eaff634b1bbb09686895221b3645f53f7a60 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 13 Apr 2014 18:47:34 +0100 Subject: ARM: use get_cr() rather than cr_alignment Rather than reading the cr_alignment variable, use get_cr() to read directly from the hardware instead. We have two places where this occurs, neither of them are performance critical. Signed-off-by: Russell King --- arch/arm/include/asm/cp15.h | 7 ++++++- arch/arm/kernel/setup.c | 2 +- arch/arm/mm/alignment.c | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h index d5bf322a0630..63427266015d 100644 --- a/arch/arm/include/asm/cp15.h +++ b/arch/arm/include/asm/cp15.h @@ -42,7 +42,7 @@ #ifndef __ASSEMBLY__ #if __LINUX_ARM_ARCH__ >= 4 -#define vectors_high() (cr_alignment & CR_V) +#define vectors_high() (get_cr() & CR_V) #else #define vectors_high() (0) #endif @@ -113,6 +113,11 @@ static inline void set_copro_access(unsigned int val) #define cr_no_alignment UL(0) #define cr_alignment UL(0) +static inline unsigned long get_cr(void) +{ + return 0; +} + #endif /* ifdef CONFIG_CPU_CP15 / else */ #endif /* ifndef __ASSEMBLY__ */ diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 50e198c1e9c8..df21f9f98945 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -590,7 +590,7 @@ static void __init setup_processor(void) pr_info("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n", cpu_name, read_cpuid_id(), read_cpuid_id() & 15, - proc_arch[cpu_architecture()], cr_alignment); + proc_arch[cpu_architecture()], get_cr()); snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c", list->arch_name, ENDIANNESS); diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 924036473b16..1ab611ce5009 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -91,7 +91,7 @@ core_param(alignment, ai_usermode, int, 0600); /* Return true if and only if the ARMv6 unaligned access model is in use. */ static bool cpu_is_v6_unaligned(void) { - return cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U); + return cpu_architecture() >= CPU_ARCH_ARMv6 && get_cr() & CR_U; } static int safe_usermode(int new_usermode, bool warn) -- cgit v1.2.3 From deace4a6b440f2e05f3e073338b28901d02a15c9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 3 May 2014 11:06:55 +0100 Subject: ARM: dma-mapping: avoid calling dma_cache_maint_page() on dev=>cpu Avoid calling dma_cache_maint_page() when unmapping a DMA_TO_DEVICE buffer. The L1 cache ops never do anything in this circumstance, nor do they ever need to - all that matters for this case is that the data written is visible to the device before DMA starts. What happens during the transfer (provided the buffer is not written to) is of no real consequence. We already do this optimisation for the L2 cache. Signed-off-by: Russell King --- arch/arm/mm/dma-mapping.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index f62aa0677e5c..137463bcbeac 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -904,11 +904,12 @@ static void __dma_page_dev_to_cpu(struct page *page, unsigned long off, unsigned long paddr = page_to_phys(page) + off; /* FIXME: non-speculating: not required */ - /* don't bother invalidating if DMA to device */ - if (dir != DMA_TO_DEVICE) + /* in any case, don't bother invalidating if DMA to device */ + if (dir != DMA_TO_DEVICE) { outer_inv_range(paddr, paddr + size); - dma_cache_maint_page(page, off, size, dir, dmac_unmap_area); + dma_cache_maint_page(page, off, size, dir, dmac_unmap_area); + } /* * Mark the D-cache clean for these pages to avoid extra flushing. -- cgit v1.2.3 From cd000cf650cd43dc0dc37032cb4016985c9dda6c Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 2 May 2014 17:06:02 +0100 Subject: ARM: 8046/1: proc: add support for the Cortex-A17 processor Cortex-A17 has identical initialisation requirements to Cortex-A12, so hook it up in proc-v7.S in the same way. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/cputype.h | 1 + arch/arm/mm/proc-v7.S | 11 +++++++++++ 2 files changed, 12 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index c651e3b26ec7..550bf7110fef 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h @@ -72,6 +72,7 @@ #define ARM_CPU_PART_CORTEX_A15 0xC0F0 #define ARM_CPU_PART_CORTEX_A7 0xC070 #define ARM_CPU_PART_CORTEX_A12 0xC0D0 +#define ARM_CPU_PART_CORTEX_A17 0xC0E0 #define ARM_CPU_XSCALE_ARCH_MASK 0xe000 #define ARM_CPU_XSCALE_ARCH_V1 0x2000 diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index b74ea60891d5..3db2c2f04a30 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -216,6 +216,7 @@ __v7_cr7mp_setup: __v7_ca7mp_setup: __v7_ca12mp_setup: __v7_ca15mp_setup: +__v7_ca17mp_setup: mov r10, #0 1: #ifdef CONFIG_SMP @@ -526,6 +527,16 @@ __v7_ca15mp_proc_info: __v7_proc __v7_ca15mp_setup .size __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info + /* + * ARM Ltd. Cortex A17 processor. + */ + .type __v7_ca17mp_proc_info, #object +__v7_ca17mp_proc_info: + .long 0x410fc0e0 + .long 0xff0ffff0 + __v7_proc __v7_ca17mp_setup + .size __v7_ca17mp_proc_info, . - __v7_ca17mp_proc_info + /* * Qualcomm Inc. Krait processors. */ -- cgit v1.2.3 From 9581960a40ab0e281b695bf03744c8924ec3b5d0 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 9 May 2014 18:36:27 +0100 Subject: ARM: 8055/1: cacheflush: use -st dsb option for ensuring completion dsb st can be used to ensure completion of pending cache maintenance operations, so use it for the v7 cache maintenance operations. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/include/asm/cacheflush.h | 2 +- arch/arm/mm/cache-v7.S | 12 ++++++------ arch/arm/mm/mmu.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 8b8b61685a34..00af9fe435e6 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -212,7 +212,7 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *, static inline void __flush_icache_all(void) { __flush_icache_preferred(); - dsb(); + dsb(ishst); } /* diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 778bcf88ee79..615c99e38ba1 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -59,7 +59,7 @@ ENTRY(v7_invalidate_l1) bgt 2b cmp r2, #0 bgt 1b - dsb + dsb st isb mov pc, lr ENDPROC(v7_invalidate_l1) @@ -166,7 +166,7 @@ skip: finished: mov r10, #0 @ swith back to cache level 0 mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr - dsb + dsb st isb mov pc, lr ENDPROC(v7_flush_dcache_all) @@ -335,7 +335,7 @@ ENTRY(v7_flush_kern_dcache_area) add r0, r0, r2 cmp r0, r1 blo 1b - dsb + dsb st mov pc, lr ENDPROC(v7_flush_kern_dcache_area) @@ -368,7 +368,7 @@ v7_dma_inv_range: add r0, r0, r2 cmp r0, r1 blo 1b - dsb + dsb st mov pc, lr ENDPROC(v7_dma_inv_range) @@ -390,7 +390,7 @@ v7_dma_clean_range: add r0, r0, r2 cmp r0, r1 blo 1b - dsb + dsb st mov pc, lr ENDPROC(v7_dma_clean_range) @@ -412,7 +412,7 @@ ENTRY(v7_dma_flush_range) add r0, r0, r2 cmp r0, r1 blo 1b - dsb + dsb st mov pc, lr ENDPROC(v7_dma_flush_range) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 09c0a16165dc..a991ce2f18d4 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1465,7 +1465,7 @@ void __init early_paging_init(const struct machine_desc *mdesc, * just complicate the code. */ flush_cache_louis(); - dsb(); + dsb(ishst); isb(); /* remap level 1 table */ -- cgit v1.2.3 From 72e6ae285a1dbff553734985bedadf409d99c02d Mon Sep 17 00:00:00 2001 From: Victor Kamensky Date: Tue, 29 Apr 2014 04:20:52 +0100 Subject: ARM: 8043/1: uprobes need icache flush after xol write After instruction write into xol area, on ARM V7 architecture code need to flush dcache and icache to sync them up for given set of addresses. Having just 'flush_dcache_page(page)' call is not enough - it is possible to have stale instruction sitting in icache for given xol area slot address. Introduce arch_uprobe_ixol_copy weak function that by default calls uprobes copy_to_page function and than flush_dcache_page function and on ARM define new one that handles xol slot copy in ARM specific way flush_uprobe_xol_access function shares/reuses implementation with/of flush_ptrace_access function and takes care of writing instruction to user land address space on given variety of different cache types on ARM CPUs. Because flush_uprobe_xol_access does not have vma around flush_ptrace_access was split into two parts. First that retrieves set of condition from vma and common that receives those conditions as flags. Note ARM cache flush function need kernel address through which instruction write happened, so instead of using uprobes copy_to_page function changed code to explicitly map page and do memcpy. Note arch_uprobe_copy_ixol function, in similar way as copy_to_user_page function, has preempt_disable/preempt_enable. Signed-off-by: Victor Kamensky Acked-by: Oleg Nesterov Reviewed-by: David A. Long Signed-off-by: Russell King --- arch/arm/include/asm/cacheflush.h | 2 ++ arch/arm/kernel/uprobes.c | 20 ++++++++++++++++++++ arch/arm/mm/flush.c | 33 ++++++++++++++++++++++++++++----- include/linux/uprobes.h | 3 +++ kernel/events/uprobes.c | 25 +++++++++++++++++-------- 5 files changed, 70 insertions(+), 13 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 00af9fe435e6..fd43f7f55b70 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -487,4 +487,6 @@ int set_memory_rw(unsigned long addr, int numpages); int set_memory_x(unsigned long addr, int numpages); int set_memory_nx(unsigned long addr, int numpages); +void flush_uprobe_xol_access(struct page *page, unsigned long uaddr, + void *kaddr, unsigned long len); #endif diff --git a/arch/arm/kernel/uprobes.c b/arch/arm/kernel/uprobes.c index f9bacee973bf..56adf9c1fde0 100644 --- a/arch/arm/kernel/uprobes.c +++ b/arch/arm/kernel/uprobes.c @@ -113,6 +113,26 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, return 0; } +void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, + void *src, unsigned long len) +{ + void *xol_page_kaddr = kmap_atomic(page); + void *dst = xol_page_kaddr + (vaddr & ~PAGE_MASK); + + preempt_disable(); + + /* Initialize the slot */ + memcpy(dst, src, len); + + /* flush caches (dcache/icache) */ + flush_uprobe_xol_access(page, vaddr, dst, len); + + preempt_enable(); + + kunmap_atomic(xol_page_kaddr); +} + + int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) { struct uprobe_task *utask = current->utask; diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 3387e60e4ea3..43d54f5b26b9 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -104,17 +104,20 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig #define flush_icache_alias(pfn,vaddr,len) do { } while (0) #endif +#define FLAG_PA_IS_EXEC 1 +#define FLAG_PA_CORE_IN_MM 2 + static void flush_ptrace_access_other(void *args) { __flush_icache_all(); } -static -void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, - unsigned long uaddr, void *kaddr, unsigned long len) +static inline +void __flush_ptrace_access(struct page *page, unsigned long uaddr, void *kaddr, + unsigned long len, unsigned int flags) { if (cache_is_vivt()) { - if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) { + if (flags & FLAG_PA_CORE_IN_MM) { unsigned long addr = (unsigned long)kaddr; __cpuc_coherent_kern_range(addr, addr + len); } @@ -128,7 +131,7 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, } /* VIPT non-aliasing D-cache */ - if (vma->vm_flags & VM_EXEC) { + if (flags & FLAG_PA_IS_EXEC) { unsigned long addr = (unsigned long)kaddr; if (icache_is_vipt_aliasing()) flush_icache_alias(page_to_pfn(page), uaddr, len); @@ -140,6 +143,26 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, } } +static +void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, + unsigned long uaddr, void *kaddr, unsigned long len) +{ + unsigned int flags = 0; + if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) + flags |= FLAG_PA_CORE_IN_MM; + if (vma->vm_flags & VM_EXEC) + flags |= FLAG_PA_IS_EXEC; + __flush_ptrace_access(page, uaddr, kaddr, len, flags); +} + +void flush_uprobe_xol_access(struct page *page, unsigned long uaddr, + void *kaddr, unsigned long len) +{ + unsigned int flags = FLAG_PA_CORE_IN_MM|FLAG_PA_IS_EXEC; + + __flush_ptrace_access(page, uaddr, kaddr, len, flags); +} + /* * Copy user data from/to a page which is mapped into a different * processes address space. Really, we want to allow our "user diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h index edff2b97b864..c52f827ba6ce 100644 --- a/include/linux/uprobes.h +++ b/include/linux/uprobes.h @@ -32,6 +32,7 @@ struct vm_area_struct; struct mm_struct; struct inode; struct notifier_block; +struct page; #define UPROBE_HANDLER_REMOVE 1 #define UPROBE_HANDLER_MASK 1 @@ -127,6 +128,8 @@ extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned l extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs); extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs); extern bool __weak arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *regs); +extern void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, + void *src, unsigned long len); #else /* !CONFIG_UPROBES */ struct uprobes_state { }; diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 04709b66369d..4968213c63fa 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -1296,14 +1296,8 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe) if (unlikely(!xol_vaddr)) return 0; - /* Initialize the slot */ - copy_to_page(area->page, xol_vaddr, - &uprobe->arch.ixol, sizeof(uprobe->arch.ixol)); - /* - * We probably need flush_icache_user_range() but it needs vma. - * This should work on supported architectures too. - */ - flush_dcache_page(area->page); + arch_uprobe_copy_ixol(area->page, xol_vaddr, + &uprobe->arch.ixol, sizeof(uprobe->arch.ixol)); return xol_vaddr; } @@ -1346,6 +1340,21 @@ static void xol_free_insn_slot(struct task_struct *tsk) } } +void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, + void *src, unsigned long len) +{ + /* Initialize the slot */ + copy_to_page(page, vaddr, src, len); + + /* + * We probably need flush_icache_user_range() but it needs vma. + * This should work on most of architectures by default. If + * architecture needs to do something different it can define + * its own version of the function. + */ + flush_dcache_page(page); +} + /** * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs * @regs: Reflects the saved state of the task after it has hit a breakpoint -- cgit v1.2.3 From 1f1d5b745a4617a2cb2ffd8f4a9bc3be664cfc98 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 13:14:38 +0000 Subject: ARM: outer cache: add WARN_ON() to outer_disable() Add WARN_ON() conditions to outer_disable() to ensure that its requirements aren't violated. Signed-off-by: Russell King --- arch/arm/include/asm/outercache.h | 6 +----- arch/arm/mm/Makefile | 1 + arch/arm/mm/l2c-common.c | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 arch/arm/mm/l2c-common.c (limited to 'arch/arm/mm') diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index 2615b3d9e807..e96f194bf3d4 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h @@ -96,11 +96,7 @@ static inline void outer_flush_all(void) * cache is pushed out to lower levels of system memory. The note and * conditions above concerning outer_flush_all() applies here. */ -static inline void outer_disable(void) -{ - if (outer_cache.disable) - outer_cache.disable(); -} +extern void outer_disable(void); /** * outer_resume - restore the cache configuration and re-enable outer cache diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 7f39ce2f841f..de5a6a27081b 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -95,6 +95,7 @@ obj-$(CONFIG_CPU_V7M) += proc-v7m.o AFLAGS_proc-v6.o :=-Wa,-march=armv6 AFLAGS_proc-v7.o :=-Wa,-march=armv7-a +obj-$(CONFIG_OUTER_CACHE) += l2c-common.o obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o diff --git a/arch/arm/mm/l2c-common.c b/arch/arm/mm/l2c-common.c new file mode 100644 index 000000000000..10a3cf28c362 --- /dev/null +++ b/arch/arm/mm/l2c-common.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2010 ARM Ltd. + * Written by Catalin Marinas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +void outer_disable(void) +{ + WARN_ON(!irqs_disabled()); + WARN_ON(num_online_cpus() > 1); + + if (outer_cache.disable) + outer_cache.disable(); +} -- cgit v1.2.3 From a65bb925601cf35ef5db54c8a9ad9e6575c6fe8c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:01 +0000 Subject: ARM: l2c: add helper for L2 cache controller DT IDs Make it easier to declare L2 cache controller DT IDs by using a macro. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index f9985e5a208c..ac410b21edfb 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -946,20 +946,17 @@ static const struct l2x0_of_data bcm_l2x0_data = { }, }; +#define L2C_ID(name, fns) { .compatible = name, .data = (void *)&fns } static const struct of_device_id l2x0_ids[] __initconst = { - { .compatible = "arm,l210-cache", .data = (void *)&l2x0_data }, - { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data }, - { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data }, - { .compatible = "bcm,bcm11351-a2-pl310-cache", /* deprecated name */ - .data = (void *)&bcm_l2x0_data}, - { .compatible = "brcm,bcm11351-a2-pl310-cache", - .data = (void *)&bcm_l2x0_data}, - { .compatible = "marvell,aurora-outer-cache", - .data = (void *)&aurora_with_outer_data}, - { .compatible = "marvell,aurora-system-cache", - .data = (void *)&aurora_no_outer_data}, - { .compatible = "marvell,tauros3-cache", - .data = (void *)&tauros3_data }, + L2C_ID("arm,l210-cache", l2x0_data), + L2C_ID("arm,l220-cache", l2x0_data), + L2C_ID("arm,pl310-cache", pl310_data), + L2C_ID("brcm,bcm11351-a2-pl310-cache", bcm_l2x0_data), + L2C_ID("marvell,aurora-outer-cache", aurora_with_outer_data), + L2C_ID("marvell,aurora-system-cache", aurora_no_outer_data), + L2C_ID("marvell,tauros3-cache", tauros3_data), + /* Deprecated IDs */ + L2C_ID("bcm,bcm11351-a2-pl310-cache", bcm_l2x0_data), {} }; -- cgit v1.2.3 From ce84130384badcad2cdbc1e825657d622165f0e6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:03 +0000 Subject: ARM: l2c: tidy up l2x0_of_data declarations Remove NULL initialisers, make these all __initconst structures, and order their members in the same order as the structure declaration. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index ac410b21edfb..063e1787e8c3 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -873,49 +873,48 @@ static void __init aurora_of_setup(const struct device_node *np, *aux_mask &= ~mask; } -static const struct l2x0_of_data pl310_data = { +static const struct l2x0_of_data pl310_data __initconst = { .setup = pl310_of_setup, .save = pl310_save, .outer_cache = { - .resume = pl310_resume, .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range, .flush_range = l2x0_flush_range, - .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = pl310_resume, }, }; -static const struct l2x0_of_data l2x0_data = { +static const struct l2x0_of_data l2x0_data __initconst = { .setup = l2x0_of_setup, - .save = NULL, .outer_cache = { - .resume = l2x0_resume, .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range, .flush_range = l2x0_flush_range, - .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = l2x0_resume, }, }; -static const struct l2x0_of_data aurora_with_outer_data = { +static const struct l2x0_of_data aurora_with_outer_data __initconst = { .setup = aurora_of_setup, .save = aurora_save, .outer_cache = { - .resume = aurora_resume, .inv_range = aurora_inv_range, .clean_range = aurora_clean_range, .flush_range = aurora_flush_range, - .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = aurora_resume, }, }; -static const struct l2x0_of_data aurora_no_outer_data = { +static const struct l2x0_of_data aurora_no_outer_data __initconst = { .setup = aurora_of_setup, .save = aurora_save, .outer_cache = { @@ -923,8 +922,7 @@ static const struct l2x0_of_data aurora_no_outer_data = { }, }; -static const struct l2x0_of_data tauros3_data = { - .setup = NULL, +static const struct l2x0_of_data tauros3_data __initconst = { .save = tauros3_save, /* Tauros3 broadcasts L1 cache operations to L2 */ .outer_cache = { @@ -932,17 +930,17 @@ static const struct l2x0_of_data tauros3_data = { }, }; -static const struct l2x0_of_data bcm_l2x0_data = { +static const struct l2x0_of_data bcm_l2x0_data __initconst = { .setup = pl310_of_setup, .save = pl310_save, .outer_cache = { - .resume = pl310_resume, .inv_range = bcm_inv_range, .clean_range = bcm_clean_range, .flush_range = bcm_flush_range, - .sync = l2x0_cache_sync, .flush_all = l2x0_flush_all, .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = pl310_resume, }, }; -- cgit v1.2.3 From c02642bc1010b7ef8a4b87763ab28f5e4ab1d823 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:54 +0000 Subject: ARM: l2c: rename OF specific things, making l2x0_of_data available to all Rename a few things to help distinguish their function(s): l2x0_of_data -> l2c_init_data setup -> of_parse add of_ prefix to OF specific data Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 64 ++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 063e1787e8c3..d659c4ca46bb 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -28,6 +28,12 @@ #include "cache-tauros3.h" #include "cache-aurora-l2.h" +struct l2c_init_data { + void (*of_parse)(const struct device_node *, u32 *, u32 *); + void (*save)(void); + struct outer_cache_fns outer_cache; +}; + #define CACHE_LINE_SIZE 32 static void __iomem *l2x0_base; @@ -42,12 +48,6 @@ static u32 cache_id_part_number_from_dt; struct l2x0_regs l2x0_saved_regs; -struct l2x0_of_data { - void (*setup)(const struct device_node *, u32 *, u32 *); - void (*save)(void); - struct outer_cache_fns outer_cache; -}; - static bool of_init = false; static inline void cache_wait_way(void __iomem *reg, unsigned long mask) @@ -664,7 +664,7 @@ static void bcm_flush_range(unsigned long start, unsigned long end) new_end); } -static void __init l2x0_of_setup(const struct device_node *np, +static void __init l2x0_of_parse(const struct device_node *np, u32 *aux_val, u32 *aux_mask) { u32 data[2] = { 0, 0 }; @@ -698,7 +698,7 @@ static void __init l2x0_of_setup(const struct device_node *np, *aux_mask &= ~mask; } -static void __init pl310_of_setup(const struct device_node *np, +static void __init pl310_of_parse(const struct device_node *np, u32 *aux_val, u32 *aux_mask) { u32 data[3] = { 0, 0, 0 }; @@ -851,7 +851,7 @@ static void __init aurora_broadcast_l2_commands(void) isb(); } -static void __init aurora_of_setup(const struct device_node *np, +static void __init aurora_of_parse(const struct device_node *np, u32 *aux_val, u32 *aux_mask) { u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU; @@ -873,8 +873,8 @@ static void __init aurora_of_setup(const struct device_node *np, *aux_mask &= ~mask; } -static const struct l2x0_of_data pl310_data __initconst = { - .setup = pl310_of_setup, +static const struct l2c_init_data of_pl310_data __initconst = { + .of_parse = pl310_of_parse, .save = pl310_save, .outer_cache = { .inv_range = l2x0_inv_range, @@ -887,8 +887,8 @@ static const struct l2x0_of_data pl310_data __initconst = { }, }; -static const struct l2x0_of_data l2x0_data __initconst = { - .setup = l2x0_of_setup, +static const struct l2c_init_data of_l2x0_data __initconst = { + .of_parse = l2x0_of_parse, .outer_cache = { .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range, @@ -900,8 +900,8 @@ static const struct l2x0_of_data l2x0_data __initconst = { }, }; -static const struct l2x0_of_data aurora_with_outer_data __initconst = { - .setup = aurora_of_setup, +static const struct l2c_init_data of_aurora_with_outer_data __initconst = { + .of_parse = aurora_of_parse, .save = aurora_save, .outer_cache = { .inv_range = aurora_inv_range, @@ -914,15 +914,15 @@ static const struct l2x0_of_data aurora_with_outer_data __initconst = { }, }; -static const struct l2x0_of_data aurora_no_outer_data __initconst = { - .setup = aurora_of_setup, +static const struct l2c_init_data of_aurora_no_outer_data __initconst = { + .of_parse = aurora_of_parse, .save = aurora_save, .outer_cache = { .resume = aurora_resume, }, }; -static const struct l2x0_of_data tauros3_data __initconst = { +static const struct l2c_init_data of_tauros3_data __initconst = { .save = tauros3_save, /* Tauros3 broadcasts L1 cache operations to L2 */ .outer_cache = { @@ -930,8 +930,8 @@ static const struct l2x0_of_data tauros3_data __initconst = { }, }; -static const struct l2x0_of_data bcm_l2x0_data __initconst = { - .setup = pl310_of_setup, +static const struct l2c_init_data of_bcm_l2x0_data __initconst = { + .of_parse = pl310_of_parse, .save = pl310_save, .outer_cache = { .inv_range = bcm_inv_range, @@ -946,22 +946,22 @@ static const struct l2x0_of_data bcm_l2x0_data __initconst = { #define L2C_ID(name, fns) { .compatible = name, .data = (void *)&fns } static const struct of_device_id l2x0_ids[] __initconst = { - L2C_ID("arm,l210-cache", l2x0_data), - L2C_ID("arm,l220-cache", l2x0_data), - L2C_ID("arm,pl310-cache", pl310_data), - L2C_ID("brcm,bcm11351-a2-pl310-cache", bcm_l2x0_data), - L2C_ID("marvell,aurora-outer-cache", aurora_with_outer_data), - L2C_ID("marvell,aurora-system-cache", aurora_no_outer_data), - L2C_ID("marvell,tauros3-cache", tauros3_data), + L2C_ID("arm,l210-cache", of_l2x0_data), + L2C_ID("arm,l220-cache", of_l2x0_data), + L2C_ID("arm,pl310-cache", of_pl310_data), + L2C_ID("brcm,bcm11351-a2-pl310-cache", of_bcm_l2x0_data), + L2C_ID("marvell,aurora-outer-cache", of_aurora_with_outer_data), + L2C_ID("marvell,aurora-system-cache", of_aurora_no_outer_data), + L2C_ID("marvell,tauros3-cache", of_tauros3_data), /* Deprecated IDs */ - L2C_ID("bcm,bcm11351-a2-pl310-cache", bcm_l2x0_data), + L2C_ID("bcm,bcm11351-a2-pl310-cache", of_bcm_l2x0_data), {} }; int __init l2x0_of_init(u32 aux_val, u32 aux_mask) { + const struct l2c_init_data *data; struct device_node *np; - const struct l2x0_of_data *data; struct resource res; np = of_find_matching_node(NULL, l2x0_ids); @@ -981,12 +981,12 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) /* L2 configuration can only be changed if the cache is disabled */ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { - if (data->setup) - data->setup(np, &aux_val, &aux_mask); + if (data->of_parse) + data->of_parse(np, &aux_val, &aux_mask); /* For aurora cache in no outer mode select the * correct mode using the coprocessor*/ - if (data == &aurora_no_outer_data) + if (data == &of_aurora_no_outer_data) aurora_broadcast_l2_commands(); } -- cgit v1.2.3 From 2b2a87a12d2e0aede29e45911aeb0c520066b0c0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 17:19:21 +0000 Subject: ARM: l2c: provide generic function for calling set_debug method Provide a generic function which always calls the set_debug method. This will be used later in the series as some work-arounds require that the debug register be written. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index d659c4ca46bb..595c50519e41 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -57,6 +57,16 @@ static inline void cache_wait_way(void __iomem *reg, unsigned long mask) cpu_relax(); } +/* + * This should only be called when we have a requirement that the + * register be written due to a work-around, as platforms running + * in non-secure mode may not be able to access this register. + */ +static inline void l2c_set_debug(void __iomem *base, unsigned long val) +{ + outer_cache.set_debug(val); +} + #ifdef CONFIG_CACHE_PL310 static inline void cache_wait(void __iomem *reg, unsigned long mask) { @@ -92,7 +102,7 @@ static inline void l2x0_inv_line(unsigned long addr) static inline void debug_writel(unsigned long val) { if (outer_cache.set_debug) - outer_cache.set_debug(val); + l2c_set_debug(l2x0_base, val); } static void pl310_set_debug(unsigned long val) -- cgit v1.2.3 From 37abcdb9194001a0c6ccc5508cd84ea8bd92c29c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:50 +0000 Subject: ARM: l2c: split out cache unlock code Split the cache unlock code out of l2x0_unlock(). We want to be able to re-use this functionality later. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 595c50519e41..a1313d20f205 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -50,6 +50,9 @@ struct l2x0_regs l2x0_saved_regs; static bool of_init = false; +/* + * Common code for all cache controllers. + */ static inline void cache_wait_way(void __iomem *reg, unsigned long mask) { /* wait for cache operation by line or way to complete */ @@ -67,6 +70,18 @@ static inline void l2c_set_debug(void __iomem *base, unsigned long val) outer_cache.set_debug(val); } +static inline void l2c_unlock(void __iomem *base, unsigned num) +{ + unsigned i; + + for (i = 0; i < num; i++) { + writel_relaxed(0, base + L2X0_LOCKDOWN_WAY_D_BASE + + i * L2X0_LOCKDOWN_STRIDE); + writel_relaxed(0, base + L2X0_LOCKDOWN_WAY_I_BASE + + i * L2X0_LOCKDOWN_STRIDE); + } +} + #ifdef CONFIG_CACHE_PL310 static inline void cache_wait(void __iomem *reg, unsigned long mask) { @@ -308,7 +323,6 @@ static void l2x0_disable(void) static void l2x0_unlock(u32 cache_id) { int lockregs; - int i; switch (cache_id & L2X0_CACHE_ID_PART_MASK) { case L2X0_CACHE_ID_PART_L310: @@ -323,12 +337,7 @@ static void l2x0_unlock(u32 cache_id) break; } - for (i = 0; i < lockregs; i++) { - writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE + - i * L2X0_LOCKDOWN_STRIDE); - writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE + - i * L2X0_LOCKDOWN_STRIDE); - } + l2c_unlock(l2x0_base, lockregs); } void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) -- cgit v1.2.3 From df5dd4c6e27081bce2c68cdc2e57a93ea998b63e Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:56 +0000 Subject: ARM: l2c: provide generic helper for way-based operations Provide a generic helper function for way based operations. These are always background operations, and thus have to be waited for before a new operation is commenced. This helper extracts that requirement from several locations in the code. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index a1313d20f205..1c3a23318f53 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -70,6 +70,12 @@ static inline void l2c_set_debug(void __iomem *base, unsigned long val) outer_cache.set_debug(val); } +static void __l2c_op_way(void __iomem *reg) +{ + writel_relaxed(l2x0_way_mask, reg); + cache_wait_way(reg, l2x0_way_mask); +} + static inline void l2c_unlock(void __iomem *base, unsigned num) { unsigned i; @@ -166,8 +172,7 @@ static void l2x0_cache_sync(void) static void __l2x0_flush_all(void) { debug_writel(0x03); - writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY); - cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask); + __l2c_op_way(l2x0_base + L2X0_CLEAN_INV_WAY); cache_sync(); debug_writel(0x00); } @@ -188,8 +193,7 @@ static void l2x0_clean_all(void) /* clean all ways */ raw_spin_lock_irqsave(&l2x0_lock, flags); - writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_WAY); - cache_wait_way(l2x0_base + L2X0_CLEAN_WAY, l2x0_way_mask); + __l2c_op_way(l2x0_base + L2X0_CLEAN_WAY); cache_sync(); raw_spin_unlock_irqrestore(&l2x0_lock, flags); } @@ -202,8 +206,7 @@ static void l2x0_inv_all(void) raw_spin_lock_irqsave(&l2x0_lock, flags); /* Invalidating when L2 is enabled is a nono */ BUG_ON(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN); - writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); - cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); + __l2c_op_way(l2x0_base + L2X0_INV_WAY); cache_sync(); raw_spin_unlock_irqrestore(&l2x0_lock, flags); } -- cgit v1.2.3 From 83841fe1fb0c4316af89ab85d3528702724a33f4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:14 +0000 Subject: ARM: l2c: rename cache_wait_way() cache_wait_way() is actually used to wait for a particular mask to report clear; it's not really got much to do with cache ways at all. Indeed, it gets used to wait for the C bit to clear on older caches. Rename this with a more generic function name which better reflects its purpose: l2c_wait_mask(). Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 1c3a23318f53..29ee7f692801 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -53,7 +53,7 @@ static bool of_init = false; /* * Common code for all cache controllers. */ -static inline void cache_wait_way(void __iomem *reg, unsigned long mask) +static inline void l2c_wait_mask(void __iomem *reg, unsigned long mask) { /* wait for cache operation by line or way to complete */ while (readl_relaxed(reg) & mask) @@ -73,7 +73,7 @@ static inline void l2c_set_debug(void __iomem *base, unsigned long val) static void __l2c_op_way(void __iomem *reg) { writel_relaxed(l2x0_way_mask, reg); - cache_wait_way(reg, l2x0_way_mask); + l2c_wait_mask(reg, l2x0_way_mask); } static inline void l2c_unlock(void __iomem *base, unsigned num) @@ -94,7 +94,7 @@ static inline void cache_wait(void __iomem *reg, unsigned long mask) /* cache operations by line are atomic on PL310 */ } #else -#define cache_wait cache_wait_way +#define cache_wait l2c_wait_mask #endif static inline void cache_sync(void) -- cgit v1.2.3 From 14b882cfa3f9db3430037dca6038e161eda953a1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:49 +0000 Subject: ARM: l2c: add and use L2C revision constants The revision namespace is specific to the L2 cache part, so don't name these with generic identifiers, use a part specific identifier. Signed-off-by: Russell King --- arch/arm/include/asm/hardware/cache-l2x0.h | 22 ++++++++++++++++------ arch/arm/mm/cache-l2x0.c | 10 +++++----- 2 files changed, 21 insertions(+), 11 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h index 6795ff743b3d..3af45734b514 100644 --- a/arch/arm/include/asm/hardware/cache-l2x0.h +++ b/arch/arm/include/asm/hardware/cache-l2x0.h @@ -68,14 +68,24 @@ /* Registers shifts and masks */ #define L2X0_CACHE_ID_PART_MASK (0xf << 6) #define L2X0_CACHE_ID_PART_L210 (1 << 6) +#define L2X0_CACHE_ID_PART_L220 (2 << 6) #define L2X0_CACHE_ID_PART_L310 (3 << 6) #define L2X0_CACHE_ID_RTL_MASK 0x3f -#define L2X0_CACHE_ID_RTL_R0P0 0x0 -#define L2X0_CACHE_ID_RTL_R1P0 0x2 -#define L2X0_CACHE_ID_RTL_R2P0 0x4 -#define L2X0_CACHE_ID_RTL_R3P0 0x5 -#define L2X0_CACHE_ID_RTL_R3P1 0x6 -#define L2X0_CACHE_ID_RTL_R3P2 0x8 +#define L210_CACHE_ID_RTL_R0P2_02 0x00 +#define L210_CACHE_ID_RTL_R0P1 0x01 +#define L210_CACHE_ID_RTL_R0P2_01 0x02 +#define L210_CACHE_ID_RTL_R0P3 0x03 +#define L210_CACHE_ID_RTL_R0P4 0x0b +#define L210_CACHE_ID_RTL_R0P5 0x0f +#define L220_CACHE_ID_RTL_R1P7_01REL0 0x06 +#define L310_CACHE_ID_RTL_R0P0 0x00 +#define L310_CACHE_ID_RTL_R1P0 0x02 +#define L310_CACHE_ID_RTL_R2P0 0x04 +#define L310_CACHE_ID_RTL_R3P0 0x05 +#define L310_CACHE_ID_RTL_R3P1 0x06 +#define L310_CACHE_ID_RTL_R3P1_50REL0 0x07 +#define L310_CACHE_ID_RTL_R3P2 0x08 +#define L310_CACHE_ID_RTL_R3P3 0x09 #define L2X0_AUX_CTRL_MASK 0xc0000fff #define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT 0 diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 29ee7f692801..c39602ef2cdd 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -374,7 +374,7 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) /* Unmapped register. */ sync_reg_offset = L2X0_DUMMY_REG; #endif - if ((cache_id & L2X0_CACHE_ID_RTL_MASK) <= L2X0_CACHE_ID_RTL_R3P0) + if ((cache_id & L2X0_CACHE_ID_RTL_MASK) <= L310_CACHE_ID_RTL_R3P0) outer_cache.set_debug = pl310_set_debug; break; case L2X0_CACHE_ID_PART_L210: @@ -768,7 +768,7 @@ static void __init pl310_save(void) l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base + L2X0_ADDR_FILTER_START); - if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) { + if (l2x0_revision >= L310_CACHE_ID_RTL_R2P0) { /* * From r2p0, there is Prefetch offset/control register */ @@ -777,7 +777,7 @@ static void __init pl310_save(void) /* * From r3p0, there is Power control register */ - if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0) + if (l2x0_revision >= L310_CACHE_ID_RTL_R3P0) l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base + L2X0_POWER_CTRL); } @@ -830,10 +830,10 @@ static void pl310_resume(void) l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) & L2X0_CACHE_ID_RTL_MASK; - if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) { + if (l2x0_revision >= L310_CACHE_ID_RTL_R2P0) { writel_relaxed(l2x0_saved_regs.prefetch_ctrl, l2x0_base + L2X0_PREFETCH_CTRL); - if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0) + if (l2x0_revision >= L310_CACHE_ID_RTL_R3P0) writel_relaxed(l2x0_saved_regs.pwr_ctrl, l2x0_base + L2X0_POWER_CTRL); } -- cgit v1.2.3 From 96054b0a99f4b7104c02e5521ee5c0d7b1fb09bc Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:52 +0000 Subject: ARM: l2c: clean up OF initialisation a bit Rather than having a boolean and other tricks to disable some bits of l2x0_init(), split this function into two parts: a common part shared between OF and non-OF, and the non-OF part. The common part can take a block of function pointers, and the cache ID (to cope with Aurora's DT specified ID.) Eliminate the redundant setting of l2x0_base in the OF case, moving it to the non-OF init function. This allows us to localise the OF-specific initialisation handling from the non-OF handling. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 66 +++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 26 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index c39602ef2cdd..0d83b24b7971 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -42,14 +42,8 @@ static u32 l2x0_way_mask; /* Bitmask of active ways */ static u32 l2x0_size; static unsigned long sync_reg_offset = L2X0_CACHE_SYNC; -/* Aurora don't have the cache ID register available, so we have to - * pass it though the device tree */ -static u32 cache_id_part_number_from_dt; - struct l2x0_regs l2x0_saved_regs; -static bool of_init = false; - /* * Common code for all cache controllers. */ @@ -343,20 +337,26 @@ static void l2x0_unlock(u32 cache_id) l2c_unlock(l2x0_base, lockregs); } -void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) +static const struct l2c_init_data l2x0_init_fns __initconst = { + .outer_cache = { + .inv_range = l2x0_inv_range, + .clean_range = l2x0_clean_range, + .flush_range = l2x0_flush_range, + .flush_all = l2x0_flush_all, + .disable = l2x0_disable, + .sync = l2x0_cache_sync, + }, +}; + +static void __init __l2c_init(const struct l2c_init_data *data, + u32 aux_val, u32 aux_mask, u32 cache_id) { u32 aux; - u32 cache_id; u32 way_size = 0; int ways; int way_size_shift = L2X0_WAY_SIZE_SHIFT; const char *type; - l2x0_base = base; - if (cache_id_part_number_from_dt) - cache_id = cache_id_part_number_from_dt; - else - cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID); aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); aux &= aux_mask; @@ -374,8 +374,6 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) /* Unmapped register. */ sync_reg_offset = L2X0_DUMMY_REG; #endif - if ((cache_id & L2X0_CACHE_ID_RTL_MASK) <= L310_CACHE_ID_RTL_R3P0) - outer_cache.set_debug = pl310_set_debug; break; case L2X0_CACHE_ID_PART_L210: ways = (aux >> 13) & 0xf; @@ -430,23 +428,35 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) /* Save the value for resuming. */ l2x0_saved_regs.aux_ctrl = aux; - if (!of_init) { - outer_cache.inv_range = l2x0_inv_range; - outer_cache.clean_range = l2x0_clean_range; - outer_cache.flush_range = l2x0_flush_range; - outer_cache.sync = l2x0_cache_sync; - outer_cache.flush_all = l2x0_flush_all; - outer_cache.disable = l2x0_disable; - } + outer_cache = data->outer_cache; + + if ((cache_id & L2X0_CACHE_ID_PART_MASK) == L2X0_CACHE_ID_PART_L310 && + (cache_id & L2X0_CACHE_ID_RTL_MASK) <= L310_CACHE_ID_RTL_R3P0) + outer_cache.set_debug = pl310_set_debug; pr_info("%s cache controller enabled\n", type); pr_info("l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d kB\n", ways, cache_id, aux, l2x0_size >> 10); } +void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) +{ + u32 cache_id; + + l2x0_base = base; + + cache_id = readl_relaxed(base + L2X0_CACHE_ID); + + __l2c_init(&l2x0_init_fns, aux_val, aux_mask, cache_id); +} + #ifdef CONFIG_OF static int l2_wt_override; +/* Aurora don't have the cache ID register available, so we have to + * pass it though the device tree */ +static u32 cache_id_part_number_from_dt; + /* * Note that the end addresses passed to Linux primitives are * noninclusive, while the hardware cache range operations use @@ -985,6 +995,7 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) const struct l2c_init_data *data; struct device_node *np; struct resource res; + u32 cache_id; np = of_find_matching_node(NULL, l2x0_ids); if (!np) @@ -1015,9 +1026,12 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) if (data->save) data->save(); - of_init = true; - memcpy(&outer_cache, &data->outer_cache, sizeof(outer_cache)); - l2x0_init(l2x0_base, aux_val, aux_mask); + if (cache_id_part_number_from_dt) + cache_id = cache_id_part_number_from_dt; + else + cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID); + + __l2c_init(data, aux_val, aux_mask, cache_id); return 0; } -- cgit v1.2.3 From 9846dfc98f0e3482e3d0df91bea67ead728301ac Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:55 +0000 Subject: ARM: l2c: pass iomem address into data->save function Pass the iomem address into this function so we don't have to keep accessing it from a global. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 0d83b24b7971..08f9cade028a 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -30,7 +30,7 @@ struct l2c_init_data { void (*of_parse)(const struct device_node *, u32 *, u32 *); - void (*save)(void); + void (*save)(void __iomem *); struct outer_cache_fns outer_cache; }; @@ -764,47 +764,47 @@ static void __init pl310_of_parse(const struct device_node *np, } } -static void __init pl310_save(void) +static void __init pl310_save(void __iomem *base) { - u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) & + u32 l2x0_revision = readl_relaxed(base + L2X0_CACHE_ID) & L2X0_CACHE_ID_RTL_MASK; - l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base + + l2x0_saved_regs.tag_latency = readl_relaxed(base + L2X0_TAG_LATENCY_CTRL); - l2x0_saved_regs.data_latency = readl_relaxed(l2x0_base + + l2x0_saved_regs.data_latency = readl_relaxed(base + L2X0_DATA_LATENCY_CTRL); - l2x0_saved_regs.filter_end = readl_relaxed(l2x0_base + + l2x0_saved_regs.filter_end = readl_relaxed(base + L2X0_ADDR_FILTER_END); - l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base + + l2x0_saved_regs.filter_start = readl_relaxed(base + L2X0_ADDR_FILTER_START); if (l2x0_revision >= L310_CACHE_ID_RTL_R2P0) { /* * From r2p0, there is Prefetch offset/control register */ - l2x0_saved_regs.prefetch_ctrl = readl_relaxed(l2x0_base + + l2x0_saved_regs.prefetch_ctrl = readl_relaxed(base + L2X0_PREFETCH_CTRL); /* * From r3p0, there is Power control register */ if (l2x0_revision >= L310_CACHE_ID_RTL_R3P0) - l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base + + l2x0_saved_regs.pwr_ctrl = readl_relaxed(base + L2X0_POWER_CTRL); } } -static void aurora_save(void) +static void aurora_save(void __iomem *base) { - l2x0_saved_regs.ctrl = readl_relaxed(l2x0_base + L2X0_CTRL); - l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); + l2x0_saved_regs.ctrl = readl_relaxed(base + L2X0_CTRL); + l2x0_saved_regs.aux_ctrl = readl_relaxed(base + L2X0_AUX_CTRL); } -static void __init tauros3_save(void) +static void __init tauros3_save(void __iomem *base) { l2x0_saved_regs.aux2_ctrl = - readl_relaxed(l2x0_base + TAUROS3_AUX2_CTRL); + readl_relaxed(base + TAUROS3_AUX2_CTRL); l2x0_saved_regs.prefetch_ctrl = - readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL); + readl_relaxed(base + L2X0_PREFETCH_CTRL); } static void l2x0_resume(void) @@ -1024,7 +1024,7 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) } if (data->save) - data->save(); + data->save(l2x0_base); if (cache_id_part_number_from_dt) cache_id = cache_id_part_number_from_dt; -- cgit v1.2.3 From c40e7eb6c0b08fbc905ac1bec516e6f59ffd4d02 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:04 +0000 Subject: ARM: l2c: move l2c save function to __l2c_init() There's no reason this functionality should be specific to DT, so move it into the common initialisation function. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 08f9cade028a..3b6213838054 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -357,6 +357,13 @@ static void __init __l2c_init(const struct l2c_init_data *data, int way_size_shift = L2X0_WAY_SIZE_SHIFT; const char *type; + /* + * It is strange to save the register state before initialisation, + * but hey, this is what the DT implementations decided to do. + */ + if (data->save) + data->save(l2x0_base); + aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); aux &= aux_mask; @@ -1023,9 +1030,6 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) aurora_broadcast_l2_commands(); } - if (data->save) - data->save(l2x0_base); - if (cache_id_part_number_from_dt) cache_id = cache_id_part_number_from_dt; else -- cgit v1.2.3 From da3627fbda8983e96fb087c358fab4d7661fd97d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:06 +0000 Subject: ARM: l2c: group implementation specific code together Back in the mists of time, someone decided that it would be a good idea to group like functions together - so all the save functions in one place, all the resume functions in another, all the OF parsing functions some place else. This makes it difficult to get an overview on what a particular implementation is doing - grouping an implementations specific functions together makes more sense, because you can see what it's doing without the clutter of other implementations. Organise it according to implementation. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 502 +++++++++++++++++++++++------------------------ 1 file changed, 251 insertions(+), 251 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 3b6213838054..09fe0f5eada5 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -464,6 +464,175 @@ static int l2_wt_override; * pass it though the device tree */ static u32 cache_id_part_number_from_dt; +static void __init l2x0_of_parse(const struct device_node *np, + u32 *aux_val, u32 *aux_mask) +{ + u32 data[2] = { 0, 0 }; + u32 tag = 0; + u32 dirty = 0; + u32 val = 0, mask = 0; + + of_property_read_u32(np, "arm,tag-latency", &tag); + if (tag) { + mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK; + val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT; + } + + of_property_read_u32_array(np, "arm,data-latency", + data, ARRAY_SIZE(data)); + if (data[0] && data[1]) { + mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK | + L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK; + val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) | + ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT); + } + + of_property_read_u32(np, "arm,dirty-latency", &dirty); + if (dirty) { + mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK; + val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT; + } + + *aux_val &= ~mask; + *aux_val |= val; + *aux_mask &= ~mask; +} + +static void l2x0_resume(void) +{ + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { + /* restore aux ctrl and enable l2 */ + l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID)); + + writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base + + L2X0_AUX_CTRL); + + l2x0_inv_all(); + + writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL); + } +} + +static const struct l2c_init_data of_l2x0_data __initconst = { + .of_parse = l2x0_of_parse, + .outer_cache = { + .inv_range = l2x0_inv_range, + .clean_range = l2x0_clean_range, + .flush_range = l2x0_flush_range, + .flush_all = l2x0_flush_all, + .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = l2x0_resume, + }, +}; + +static void __init pl310_of_parse(const struct device_node *np, + u32 *aux_val, u32 *aux_mask) +{ + u32 data[3] = { 0, 0, 0 }; + u32 tag[3] = { 0, 0, 0 }; + u32 filter[2] = { 0, 0 }; + + of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag)); + if (tag[0] && tag[1] && tag[2]) + writel_relaxed( + ((tag[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) | + ((tag[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) | + ((tag[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT), + l2x0_base + L2X0_TAG_LATENCY_CTRL); + + of_property_read_u32_array(np, "arm,data-latency", + data, ARRAY_SIZE(data)); + if (data[0] && data[1] && data[2]) + writel_relaxed( + ((data[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) | + ((data[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) | + ((data[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT), + l2x0_base + L2X0_DATA_LATENCY_CTRL); + + of_property_read_u32_array(np, "arm,filter-ranges", + filter, ARRAY_SIZE(filter)); + if (filter[1]) { + writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M), + l2x0_base + L2X0_ADDR_FILTER_END); + writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN, + l2x0_base + L2X0_ADDR_FILTER_START); + } +} + +static void __init pl310_save(void __iomem *base) +{ + u32 l2x0_revision = readl_relaxed(base + L2X0_CACHE_ID) & + L2X0_CACHE_ID_RTL_MASK; + + l2x0_saved_regs.tag_latency = readl_relaxed(base + + L2X0_TAG_LATENCY_CTRL); + l2x0_saved_regs.data_latency = readl_relaxed(base + + L2X0_DATA_LATENCY_CTRL); + l2x0_saved_regs.filter_end = readl_relaxed(base + + L2X0_ADDR_FILTER_END); + l2x0_saved_regs.filter_start = readl_relaxed(base + + L2X0_ADDR_FILTER_START); + + if (l2x0_revision >= L310_CACHE_ID_RTL_R2P0) { + /* + * From r2p0, there is Prefetch offset/control register + */ + l2x0_saved_regs.prefetch_ctrl = readl_relaxed(base + + L2X0_PREFETCH_CTRL); + /* + * From r3p0, there is Power control register + */ + if (l2x0_revision >= L310_CACHE_ID_RTL_R3P0) + l2x0_saved_regs.pwr_ctrl = readl_relaxed(base + + L2X0_POWER_CTRL); + } +} + +static void pl310_resume(void) +{ + u32 l2x0_revision; + + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { + /* restore pl310 setup */ + writel_relaxed(l2x0_saved_regs.tag_latency, + l2x0_base + L2X0_TAG_LATENCY_CTRL); + writel_relaxed(l2x0_saved_regs.data_latency, + l2x0_base + L2X0_DATA_LATENCY_CTRL); + writel_relaxed(l2x0_saved_regs.filter_end, + l2x0_base + L2X0_ADDR_FILTER_END); + writel_relaxed(l2x0_saved_regs.filter_start, + l2x0_base + L2X0_ADDR_FILTER_START); + + l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) & + L2X0_CACHE_ID_RTL_MASK; + + if (l2x0_revision >= L310_CACHE_ID_RTL_R2P0) { + writel_relaxed(l2x0_saved_regs.prefetch_ctrl, + l2x0_base + L2X0_PREFETCH_CTRL); + if (l2x0_revision >= L310_CACHE_ID_RTL_R3P0) + writel_relaxed(l2x0_saved_regs.pwr_ctrl, + l2x0_base + L2X0_POWER_CTRL); + } + } + + l2x0_resume(); +} + +static const struct l2c_init_data of_pl310_data __initconst = { + .of_parse = pl310_of_parse, + .save = pl310_save, + .outer_cache = { + .inv_range = l2x0_inv_range, + .clean_range = l2x0_clean_range, + .flush_range = l2x0_flush_range, + .flush_all = l2x0_flush_all, + .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = pl310_resume, + }, +}; + /* * Note that the end addresses passed to Linux primitives are * noninclusive, while the hardware cache range operations use @@ -562,6 +731,75 @@ static void aurora_flush_range(unsigned long start, unsigned long end) } } +static void aurora_save(void __iomem *base) +{ + l2x0_saved_regs.ctrl = readl_relaxed(base + L2X0_CTRL); + l2x0_saved_regs.aux_ctrl = readl_relaxed(base + L2X0_AUX_CTRL); +} + +static void aurora_resume(void) +{ + if (!(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { + writel_relaxed(l2x0_saved_regs.aux_ctrl, + l2x0_base + L2X0_AUX_CTRL); + writel_relaxed(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL); + } +} + +static void __init aurora_broadcast_l2_commands(void) +{ + __u32 u; + /* Enable Broadcasting of cache commands to L2*/ + __asm__ __volatile__("mrc p15, 1, %0, c15, c2, 0" : "=r"(u)); + u |= AURORA_CTRL_FW; /* Set the FW bit */ + __asm__ __volatile__("mcr p15, 1, %0, c15, c2, 0\n" : : "r"(u)); + isb(); +} + +static void __init aurora_of_parse(const struct device_node *np, + u32 *aux_val, u32 *aux_mask) +{ + u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU; + u32 mask = AURORA_ACR_REPLACEMENT_MASK; + + of_property_read_u32(np, "cache-id-part", + &cache_id_part_number_from_dt); + + /* Determine and save the write policy */ + l2_wt_override = of_property_read_bool(np, "wt-override"); + + if (l2_wt_override) { + val |= AURORA_ACR_FORCE_WRITE_THRO_POLICY; + mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK; + } + + *aux_val &= ~mask; + *aux_val |= val; + *aux_mask &= ~mask; +} + +static const struct l2c_init_data of_aurora_with_outer_data __initconst = { + .of_parse = aurora_of_parse, + .save = aurora_save, + .outer_cache = { + .inv_range = aurora_inv_range, + .clean_range = aurora_clean_range, + .flush_range = aurora_flush_range, + .flush_all = l2x0_flush_all, + .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = aurora_resume, + }, +}; + +static const struct l2c_init_data of_aurora_no_outer_data __initconst = { + .of_parse = aurora_of_parse, + .save = aurora_save, + .outer_cache = { + .resume = aurora_resume, + }, +}; + /* * For certain Broadcom SoCs, depending on the address range, different offsets * need to be added to the address before passing it to L2 for @@ -703,108 +941,19 @@ static void bcm_flush_range(unsigned long start, unsigned long end) new_end); } -static void __init l2x0_of_parse(const struct device_node *np, - u32 *aux_val, u32 *aux_mask) -{ - u32 data[2] = { 0, 0 }; - u32 tag = 0; - u32 dirty = 0; - u32 val = 0, mask = 0; - - of_property_read_u32(np, "arm,tag-latency", &tag); - if (tag) { - mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK; - val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT; - } - - of_property_read_u32_array(np, "arm,data-latency", - data, ARRAY_SIZE(data)); - if (data[0] && data[1]) { - mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK | - L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK; - val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) | - ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT); - } - - of_property_read_u32(np, "arm,dirty-latency", &dirty); - if (dirty) { - mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK; - val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT; - } - - *aux_val &= ~mask; - *aux_val |= val; - *aux_mask &= ~mask; -} - -static void __init pl310_of_parse(const struct device_node *np, - u32 *aux_val, u32 *aux_mask) -{ - u32 data[3] = { 0, 0, 0 }; - u32 tag[3] = { 0, 0, 0 }; - u32 filter[2] = { 0, 0 }; - - of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag)); - if (tag[0] && tag[1] && tag[2]) - writel_relaxed( - ((tag[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) | - ((tag[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) | - ((tag[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT), - l2x0_base + L2X0_TAG_LATENCY_CTRL); - - of_property_read_u32_array(np, "arm,data-latency", - data, ARRAY_SIZE(data)); - if (data[0] && data[1] && data[2]) - writel_relaxed( - ((data[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) | - ((data[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) | - ((data[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT), - l2x0_base + L2X0_DATA_LATENCY_CTRL); - - of_property_read_u32_array(np, "arm,filter-ranges", - filter, ARRAY_SIZE(filter)); - if (filter[1]) { - writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M), - l2x0_base + L2X0_ADDR_FILTER_END); - writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN, - l2x0_base + L2X0_ADDR_FILTER_START); - } -} - -static void __init pl310_save(void __iomem *base) -{ - u32 l2x0_revision = readl_relaxed(base + L2X0_CACHE_ID) & - L2X0_CACHE_ID_RTL_MASK; - - l2x0_saved_regs.tag_latency = readl_relaxed(base + - L2X0_TAG_LATENCY_CTRL); - l2x0_saved_regs.data_latency = readl_relaxed(base + - L2X0_DATA_LATENCY_CTRL); - l2x0_saved_regs.filter_end = readl_relaxed(base + - L2X0_ADDR_FILTER_END); - l2x0_saved_regs.filter_start = readl_relaxed(base + - L2X0_ADDR_FILTER_START); - - if (l2x0_revision >= L310_CACHE_ID_RTL_R2P0) { - /* - * From r2p0, there is Prefetch offset/control register - */ - l2x0_saved_regs.prefetch_ctrl = readl_relaxed(base + - L2X0_PREFETCH_CTRL); - /* - * From r3p0, there is Power control register - */ - if (l2x0_revision >= L310_CACHE_ID_RTL_R3P0) - l2x0_saved_regs.pwr_ctrl = readl_relaxed(base + - L2X0_POWER_CTRL); - } -} - -static void aurora_save(void __iomem *base) -{ - l2x0_saved_regs.ctrl = readl_relaxed(base + L2X0_CTRL); - l2x0_saved_regs.aux_ctrl = readl_relaxed(base + L2X0_AUX_CTRL); -} +static const struct l2c_init_data of_bcm_l2x0_data __initconst = { + .of_parse = pl310_of_parse, + .save = pl310_save, + .outer_cache = { + .inv_range = bcm_inv_range, + .clean_range = bcm_clean_range, + .flush_range = bcm_flush_range, + .flush_all = l2x0_flush_all, + .disable = l2x0_disable, + .sync = l2x0_cache_sync, + .resume = pl310_resume, + }, +}; static void __init tauros3_save(void __iomem *base) { @@ -814,60 +963,6 @@ static void __init tauros3_save(void __iomem *base) readl_relaxed(base + L2X0_PREFETCH_CTRL); } -static void l2x0_resume(void) -{ - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { - /* restore aux ctrl and enable l2 */ - l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID)); - - writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base + - L2X0_AUX_CTRL); - - l2x0_inv_all(); - - writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL); - } -} - -static void pl310_resume(void) -{ - u32 l2x0_revision; - - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { - /* restore pl310 setup */ - writel_relaxed(l2x0_saved_regs.tag_latency, - l2x0_base + L2X0_TAG_LATENCY_CTRL); - writel_relaxed(l2x0_saved_regs.data_latency, - l2x0_base + L2X0_DATA_LATENCY_CTRL); - writel_relaxed(l2x0_saved_regs.filter_end, - l2x0_base + L2X0_ADDR_FILTER_END); - writel_relaxed(l2x0_saved_regs.filter_start, - l2x0_base + L2X0_ADDR_FILTER_START); - - l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) & - L2X0_CACHE_ID_RTL_MASK; - - if (l2x0_revision >= L310_CACHE_ID_RTL_R2P0) { - writel_relaxed(l2x0_saved_regs.prefetch_ctrl, - l2x0_base + L2X0_PREFETCH_CTRL); - if (l2x0_revision >= L310_CACHE_ID_RTL_R3P0) - writel_relaxed(l2x0_saved_regs.pwr_ctrl, - l2x0_base + L2X0_POWER_CTRL); - } - } - - l2x0_resume(); -} - -static void aurora_resume(void) -{ - if (!(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { - writel_relaxed(l2x0_saved_regs.aux_ctrl, - l2x0_base + L2X0_AUX_CTRL); - writel_relaxed(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL); - } -} - static void tauros3_resume(void) { if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { @@ -880,87 +975,6 @@ static void tauros3_resume(void) l2x0_resume(); } -static void __init aurora_broadcast_l2_commands(void) -{ - __u32 u; - /* Enable Broadcasting of cache commands to L2*/ - __asm__ __volatile__("mrc p15, 1, %0, c15, c2, 0" : "=r"(u)); - u |= AURORA_CTRL_FW; /* Set the FW bit */ - __asm__ __volatile__("mcr p15, 1, %0, c15, c2, 0\n" : : "r"(u)); - isb(); -} - -static void __init aurora_of_parse(const struct device_node *np, - u32 *aux_val, u32 *aux_mask) -{ - u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU; - u32 mask = AURORA_ACR_REPLACEMENT_MASK; - - of_property_read_u32(np, "cache-id-part", - &cache_id_part_number_from_dt); - - /* Determine and save the write policy */ - l2_wt_override = of_property_read_bool(np, "wt-override"); - - if (l2_wt_override) { - val |= AURORA_ACR_FORCE_WRITE_THRO_POLICY; - mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK; - } - - *aux_val &= ~mask; - *aux_val |= val; - *aux_mask &= ~mask; -} - -static const struct l2c_init_data of_pl310_data __initconst = { - .of_parse = pl310_of_parse, - .save = pl310_save, - .outer_cache = { - .inv_range = l2x0_inv_range, - .clean_range = l2x0_clean_range, - .flush_range = l2x0_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, - .resume = pl310_resume, - }, -}; - -static const struct l2c_init_data of_l2x0_data __initconst = { - .of_parse = l2x0_of_parse, - .outer_cache = { - .inv_range = l2x0_inv_range, - .clean_range = l2x0_clean_range, - .flush_range = l2x0_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, - .resume = l2x0_resume, - }, -}; - -static const struct l2c_init_data of_aurora_with_outer_data __initconst = { - .of_parse = aurora_of_parse, - .save = aurora_save, - .outer_cache = { - .inv_range = aurora_inv_range, - .clean_range = aurora_clean_range, - .flush_range = aurora_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, - .resume = aurora_resume, - }, -}; - -static const struct l2c_init_data of_aurora_no_outer_data __initconst = { - .of_parse = aurora_of_parse, - .save = aurora_save, - .outer_cache = { - .resume = aurora_resume, - }, -}; - static const struct l2c_init_data of_tauros3_data __initconst = { .save = tauros3_save, /* Tauros3 broadcasts L1 cache operations to L2 */ @@ -969,20 +983,6 @@ static const struct l2c_init_data of_tauros3_data __initconst = { }, }; -static const struct l2c_init_data of_bcm_l2x0_data __initconst = { - .of_parse = pl310_of_parse, - .save = pl310_save, - .outer_cache = { - .inv_range = bcm_inv_range, - .clean_range = bcm_clean_range, - .flush_range = bcm_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, - .resume = pl310_resume, - }, -}; - #define L2C_ID(name, fns) { .compatible = name, .data = (void *)&fns } static const struct of_device_id l2x0_ids[] __initconst = { L2C_ID("arm,l210-cache", of_l2x0_data), -- cgit v1.2.3 From 3b8bad5758113df34076dd868b6cab502bd4ee9a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:57 +0000 Subject: ARM: l2c: provide enable method Providing an enable method gives L2 cache controllers a chance to do special handling at enable time. This allows us to remove a hack in l2x0_unlock() for Marvell Aurora L2 caches. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 80 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 18 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 09fe0f5eada5..2adb82e7f4b3 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -29,7 +29,9 @@ #include "cache-aurora-l2.h" struct l2c_init_data { + unsigned num_lock; void (*of_parse)(const struct device_node *, u32 *, u32 *); + void (*enable)(void __iomem *, u32, unsigned); void (*save)(void __iomem *); struct outer_cache_fns outer_cache; }; @@ -82,6 +84,36 @@ static inline void l2c_unlock(void __iomem *base, unsigned num) } } +/* + * Enable the L2 cache controller. This function must only be + * called when the cache controller is known to be disabled. + */ +static void l2c_enable(void __iomem *base, u32 aux, unsigned num_lock) +{ + unsigned long flags; + + l2c_unlock(base, num_lock); + + writel_relaxed(aux, base + L2X0_AUX_CTRL); + + local_irq_save(flags); + __l2c_op_way(base + L2X0_INV_WAY); + writel_relaxed(0, base + sync_reg_offset); + l2c_wait_mask(base + sync_reg_offset, 1); + local_irq_restore(flags); + + writel_relaxed(L2X0_CTRL_EN, base + L2X0_CTRL); +} + +static void l2c_disable(void) +{ + void __iomem *base = l2x0_base; + + outer_cache.flush_all(); + writel_relaxed(0, base + L2X0_CTRL); + dsb(st); +} + #ifdef CONFIG_CACHE_PL310 static inline void cache_wait(void __iomem *reg, unsigned long mask) { @@ -325,9 +357,6 @@ static void l2x0_unlock(u32 cache_id) case L2X0_CACHE_ID_PART_L310: lockregs = 8; break; - case AURORA_CACHE_ID: - lockregs = 4; - break; default: /* L210 and unknown types */ lockregs = 1; @@ -337,7 +366,22 @@ static void l2x0_unlock(u32 cache_id) l2c_unlock(l2x0_base, lockregs); } +static void l2x0_enable(void __iomem *base, u32 aux, unsigned num_lock) +{ + /* Make sure that I&D is not locked down when starting */ + l2x0_unlock(readl_relaxed(base + L2X0_CACHE_ID)); + + /* l2x0 controller is disabled */ + writel_relaxed(aux, base + L2X0_AUX_CTRL); + + l2x0_inv_all(); + + /* enable L2X0 */ + writel_relaxed(L2X0_CTRL_EN, base + L2X0_CTRL); +} + static const struct l2c_init_data l2x0_init_fns __initconst = { + .enable = l2x0_enable, .outer_cache = { .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range, @@ -412,22 +456,11 @@ static void __init __l2c_init(const struct l2c_init_data *data, l2x0_size = ways * way_size * SZ_1K; /* - * Check if l2x0 controller is already enabled. - * If you are booting from non-secure mode - * accessing the below registers will fault. + * Check if l2x0 controller is already enabled. If we are booting + * in non-secure mode accessing the below registers will fault. */ - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { - /* Make sure that I&D is not locked down when starting */ - l2x0_unlock(cache_id); - - /* l2x0 controller is disabled */ - writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL); - - l2x0_inv_all(); - - /* enable L2X0 */ - writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL); - } + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) + data->enable(l2x0_base, aux, data->num_lock); /* Re-read it in case some bits are reserved. */ aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); @@ -515,6 +548,7 @@ static void l2x0_resume(void) static const struct l2c_init_data of_l2x0_data __initconst = { .of_parse = l2x0_of_parse, + .enable = l2x0_enable, .outer_cache = { .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range, @@ -620,7 +654,9 @@ static void pl310_resume(void) } static const struct l2c_init_data of_pl310_data __initconst = { + .num_lock = 8, .of_parse = pl310_of_parse, + .enable = l2c_enable, .save = pl310_save, .outer_cache = { .inv_range = l2x0_inv_range, @@ -779,7 +815,9 @@ static void __init aurora_of_parse(const struct device_node *np, } static const struct l2c_init_data of_aurora_with_outer_data __initconst = { + .num_lock = 4, .of_parse = aurora_of_parse, + .enable = l2c_enable, .save = aurora_save, .outer_cache = { .inv_range = aurora_inv_range, @@ -793,7 +831,9 @@ static const struct l2c_init_data of_aurora_with_outer_data __initconst = { }; static const struct l2c_init_data of_aurora_no_outer_data __initconst = { + .num_lock = 4, .of_parse = aurora_of_parse, + .enable = l2c_enable, .save = aurora_save, .outer_cache = { .resume = aurora_resume, @@ -942,7 +982,9 @@ static void bcm_flush_range(unsigned long start, unsigned long end) } static const struct l2c_init_data of_bcm_l2x0_data __initconst = { + .num_lock = 8, .of_parse = pl310_of_parse, + .enable = l2c_enable, .save = pl310_save, .outer_cache = { .inv_range = bcm_inv_range, @@ -976,6 +1018,8 @@ static void tauros3_resume(void) } static const struct l2c_init_data of_tauros3_data __initconst = { + .num_lock = 8, + .enable = l2c_enable, .save = tauros3_save, /* Tauros3 broadcasts L1 cache operations to L2 */ .outer_cache = { -- cgit v1.2.3 From 17f3f99fab43ad17ae1adfc724e5ebaca9635902 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 17 Mar 2014 17:15:02 +0000 Subject: ARM: l2c: write auxctrl register before unlocking We should write the auxillary control register before unlocking: the write may be necessary to enable non-secure access to the lock registers. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 2adb82e7f4b3..fc609550b7fa 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -92,10 +92,10 @@ static void l2c_enable(void __iomem *base, u32 aux, unsigned num_lock) { unsigned long flags; - l2c_unlock(base, num_lock); - writel_relaxed(aux, base + L2X0_AUX_CTRL); + l2c_unlock(base, num_lock); + local_irq_save(flags); __l2c_op_way(base + L2X0_INV_WAY); writel_relaxed(0, base + sync_reg_offset); @@ -368,12 +368,12 @@ static void l2x0_unlock(u32 cache_id) static void l2x0_enable(void __iomem *base, u32 aux, unsigned num_lock) { - /* Make sure that I&D is not locked down when starting */ - l2x0_unlock(readl_relaxed(base + L2X0_CACHE_ID)); - /* l2x0 controller is disabled */ writel_relaxed(aux, base + L2X0_AUX_CTRL); + /* Make sure that I&D is not locked down when starting */ + l2x0_unlock(readl_relaxed(base + L2X0_CACHE_ID)); + l2x0_inv_all(); /* enable L2X0 */ -- cgit v1.2.3 From 9a07f27bc5ff2e36400e605d99cc1e129582a0ca Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 17 Mar 2014 20:10:31 +0000 Subject: ARM: l2c: only write the auxiliary control register if required Avoid unnecessary writes to the auxiliary control register if the register already contains the required value. This allows us to avoid invoking the platforms secure monitor code unnecessarily. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index fc609550b7fa..1c947b4c7f05 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -92,7 +92,9 @@ static void l2c_enable(void __iomem *base, u32 aux, unsigned num_lock) { unsigned long flags; - writel_relaxed(aux, base + L2X0_AUX_CTRL); + /* Only write the aux register if it needs changing */ + if (readl_relaxed(base + L2X0_AUX_CTRL) != aux) + writel_relaxed(aux, base + L2X0_AUX_CTRL); l2c_unlock(base, num_lock); -- cgit v1.2.3 From 40266d6f410a272b76ad861ba0b5ce91d598f606 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:59 +0000 Subject: ARM: l2c: move aurora broadcast setup to enable function Rather than having this hacked into the OF initialiation function, we can handle this via the enable function instead. While here, clean up that code and comments a little. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 1c947b4c7f05..5f381af1a7a4 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -784,14 +784,22 @@ static void aurora_resume(void) } } -static void __init aurora_broadcast_l2_commands(void) +/* + * For Aurora cache in no outer mode, enable via the CP15 coprocessor + * broadcasting of cache commands to L2. + */ +static void __init aurora_enable_no_outer(void __iomem *base, u32 aux, + unsigned num_lock) { - __u32 u; - /* Enable Broadcasting of cache commands to L2*/ - __asm__ __volatile__("mrc p15, 1, %0, c15, c2, 0" : "=r"(u)); + u32 u; + + asm volatile("mrc p15, 1, %0, c15, c2, 0" : "=r" (u)); u |= AURORA_CTRL_FW; /* Set the FW bit */ - __asm__ __volatile__("mcr p15, 1, %0, c15, c2, 0\n" : : "r"(u)); + asm volatile("mcr p15, 1, %0, c15, c2, 0" : : "r" (u)); + isb(); + + l2c_enable(base, aux, num_lock); } static void __init aurora_of_parse(const struct device_node *np, @@ -835,7 +843,7 @@ static const struct l2c_init_data of_aurora_with_outer_data __initconst = { static const struct l2c_init_data of_aurora_no_outer_data __initconst = { .num_lock = 4, .of_parse = aurora_of_parse, - .enable = l2c_enable, + .enable = aurora_enable_no_outer, .save = aurora_save, .outer_cache = { .resume = aurora_resume, @@ -1066,16 +1074,10 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) data = of_match_node(l2x0_ids, np)->data; /* L2 configuration can only be changed if the cache is disabled */ - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) if (data->of_parse) data->of_parse(np, &aux_val, &aux_mask); - /* For aurora cache in no outer mode select the - * correct mode using the coprocessor*/ - if (data == &of_aurora_no_outer_data) - aurora_broadcast_l2_commands(); - } - if (cache_id_part_number_from_dt) cache_id = cache_id_part_number_from_dt; else -- cgit v1.2.3 From 75461f5c8483bee543df30b288787fd3369312b8 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:07 +0000 Subject: ARM: l2c: implement fixups for L2 cache controller quirks/errata Rather than putting quirk handling in __l2c_init(), move it out to a separate function which individual implementations can specify. This helps to localise the quirks to those implementations which require them. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 112 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 101 insertions(+), 11 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 5f381af1a7a4..a544f19c448f 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -32,6 +32,7 @@ struct l2c_init_data { unsigned num_lock; void (*of_parse)(const struct device_node *, u32 *, u32 *); void (*enable)(void __iomem *, u32, unsigned); + void (*fixup)(void __iomem *, u32, struct outer_cache_fns *); void (*save)(void __iomem *); struct outer_cache_fns outer_cache; }; @@ -394,9 +395,80 @@ static const struct l2c_init_data l2x0_init_fns __initconst = { }, }; +/* + * L2C-310 specific code. + * + * Errata: + * 588369: PL310 R0P0->R1P0, fixed R2P0. + * Affects: all clean+invalidate operations + * clean and invalidate skips the invalidate step, so we need to issue + * separate operations. We also require the above debug workaround + * enclosing this code fragment on affected parts. On unaffected parts, + * we must not use this workaround without the debug register writes + * to avoid exposing a problem similar to 727915. + * + * 727915: PL310 R2P0->R3P0, fixed R3P1. + * Affects: clean+invalidate by way + * clean and invalidate by way runs in the background, and a store can + * hit the line between the clean operation and invalidate operation, + * resulting in the store being lost. + * + * 753970: PL310 R3P0, fixed R3P1. + * Affects: sync + * prevents merging writes after the sync operation, until another L2C + * operation is performed (or a number of other conditions.) + * + * 769419: PL310 R0P0->R3P1, fixed R3P2. + * Affects: store buffer + * store buffer is not automatically drained. + */ +static void __init l2c310_fixup(void __iomem *base, u32 cache_id, + struct outer_cache_fns *fns) +{ + unsigned revision = cache_id & L2X0_CACHE_ID_RTL_MASK; + const char *errata[4]; + unsigned n = 0; + + if (revision <= L310_CACHE_ID_RTL_R3P0) + fns->set_debug = pl310_set_debug; + + if (IS_ENABLED(CONFIG_PL310_ERRATA_753970) && + revision == L310_CACHE_ID_RTL_R3P0) { + sync_reg_offset = L2X0_DUMMY_REG; + errata[n++] = "753970"; + } + + if (IS_ENABLED(CONFIG_PL310_ERRATA_769419)) + errata[n++] = "769419"; + + if (n) { + unsigned i; + + pr_info("L2C-310 errat%s", n > 1 ? "a" : "um"); + for (i = 0; i < n; i++) + pr_cont(" %s", errata[i]); + pr_cont(" enabled\n"); + } +} + +static const struct l2c_init_data l2c310_init_fns __initconst = { + .num_lock = 8, + .enable = l2c_enable, + .fixup = l2c310_fixup, + .outer_cache = { + .inv_range = l2x0_inv_range, + .clean_range = l2x0_clean_range, + .flush_range = l2x0_flush_range, + .flush_all = l2x0_flush_all, + .disable = l2x0_disable, + .sync = l2x0_cache_sync, + }, +}; + static void __init __l2c_init(const struct l2c_init_data *data, u32 aux_val, u32 aux_mask, u32 cache_id) { + struct outer_cache_fns fns; u32 aux; u32 way_size = 0; int ways; @@ -423,23 +495,20 @@ static void __init __l2c_init(const struct l2c_init_data *data, else ways = 8; type = "L310"; -#ifdef CONFIG_PL310_ERRATA_753970 - /* Unmapped register. */ - sync_reg_offset = L2X0_DUMMY_REG; -#endif break; + case L2X0_CACHE_ID_PART_L210: ways = (aux >> 13) & 0xf; type = "L210"; break; case AURORA_CACHE_ID: - sync_reg_offset = AURORA_SYNC_REG; ways = (aux >> 13) & 0xf; ways = 2 << ((ways + 1) >> 2); way_size_shift = AURORA_WAY_SIZE_SHIFT; type = "Aurora"; break; + default: /* Assume unknown chips have 8 ways */ ways = 8; @@ -457,6 +526,10 @@ static void __init __l2c_init(const struct l2c_init_data *data, l2x0_size = ways * way_size * SZ_1K; + fns = data->outer_cache; + if (data->fixup) + data->fixup(l2x0_base, cache_id, &fns); + /* * Check if l2x0 controller is already enabled. If we are booting * in non-secure mode accessing the below registers will fault. @@ -470,11 +543,7 @@ static void __init __l2c_init(const struct l2c_init_data *data, /* Save the value for resuming. */ l2x0_saved_regs.aux_ctrl = aux; - outer_cache = data->outer_cache; - - if ((cache_id & L2X0_CACHE_ID_PART_MASK) == L2X0_CACHE_ID_PART_L310 && - (cache_id & L2X0_CACHE_ID_RTL_MASK) <= L310_CACHE_ID_RTL_R3P0) - outer_cache.set_debug = pl310_set_debug; + outer_cache = fns; pr_info("%s cache controller enabled\n", type); pr_info("l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d kB\n", @@ -483,13 +552,24 @@ static void __init __l2c_init(const struct l2c_init_data *data, void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) { + const struct l2c_init_data *data; u32 cache_id; l2x0_base = base; cache_id = readl_relaxed(base + L2X0_CACHE_ID); - __l2c_init(&l2x0_init_fns, aux_val, aux_mask, cache_id); + switch (cache_id & L2X0_CACHE_ID_PART_MASK) { + default: + data = &l2x0_init_fns; + break; + + case L2X0_CACHE_ID_PART_L310: + data = &l2c310_init_fns; + break; + } + + __l2c_init(data, aux_val, aux_mask, cache_id); } #ifdef CONFIG_OF @@ -659,6 +739,7 @@ static const struct l2c_init_data of_pl310_data __initconst = { .num_lock = 8, .of_parse = pl310_of_parse, .enable = l2c_enable, + .fixup = l2c310_fixup, .save = pl310_save, .outer_cache = { .inv_range = l2x0_inv_range, @@ -802,6 +883,12 @@ static void __init aurora_enable_no_outer(void __iomem *base, u32 aux, l2c_enable(base, aux, num_lock); } +static void __init aurora_fixup(void __iomem *base, u32 cache_id, + struct outer_cache_fns *fns) +{ + sync_reg_offset = AURORA_SYNC_REG; +} + static void __init aurora_of_parse(const struct device_node *np, u32 *aux_val, u32 *aux_mask) { @@ -828,6 +915,7 @@ static const struct l2c_init_data of_aurora_with_outer_data __initconst = { .num_lock = 4, .of_parse = aurora_of_parse, .enable = l2c_enable, + .fixup = aurora_fixup, .save = aurora_save, .outer_cache = { .inv_range = aurora_inv_range, @@ -844,6 +932,7 @@ static const struct l2c_init_data of_aurora_no_outer_data __initconst = { .num_lock = 4, .of_parse = aurora_of_parse, .enable = aurora_enable_no_outer, + .fixup = aurora_fixup, .save = aurora_save, .outer_cache = { .resume = aurora_resume, @@ -995,6 +1084,7 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .num_lock = 8, .of_parse = pl310_of_parse, .enable = l2c_enable, + .fixup = l2c310_fixup, .save = pl310_save, .outer_cache = { .inv_range = bcm_inv_range, -- cgit v1.2.3 From cdef8689ef640d5f83e1ac95c6a190f4859c9bf3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:08 +0000 Subject: ARM: l2c: clean up L2 cache initialisation messages Make one of them purely "English", and the other purely technical. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index a544f19c448f..713cdcef25d1 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -545,9 +545,10 @@ static void __init __l2c_init(const struct l2c_init_data *data, outer_cache = fns; - pr_info("%s cache controller enabled\n", type); - pr_info("l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d kB\n", - ways, cache_id, aux, l2x0_size >> 10); + pr_info("%s cache controller enabled, %d ways, %d kB\n", + type, ways, l2x0_size >> 10); + pr_info("%s: CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n", + type, cache_id, aux); } void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) -- cgit v1.2.3 From b98556f26dca7f7a7401cdb67b77848f1176a379 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:11 +0000 Subject: ARM: l2c: move and add ARM L2C-2x0/L2C-310 save/resume code to non-OF Add the save/resume code hooks to the non-OF implementations as well. There's no reason for the non-OF implementations to be any different from the OF implementations. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 151 ++++++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 74 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 713cdcef25d1..4d985c17291c 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -383,6 +383,21 @@ static void l2x0_enable(void __iomem *base, u32 aux, unsigned num_lock) writel_relaxed(L2X0_CTRL_EN, base + L2X0_CTRL); } +static void l2x0_resume(void) +{ + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { + /* restore aux ctrl and enable l2 */ + l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID)); + + writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base + + L2X0_AUX_CTRL); + + l2x0_inv_all(); + + writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL); + } +} + static const struct l2c_init_data l2x0_init_fns __initconst = { .enable = l2x0_enable, .outer_cache = { @@ -392,6 +407,7 @@ static const struct l2c_init_data l2x0_init_fns __initconst = { .flush_all = l2x0_flush_all, .disable = l2x0_disable, .sync = l2x0_cache_sync, + .resume = l2x0_resume, }, }; @@ -422,6 +438,65 @@ static const struct l2c_init_data l2x0_init_fns __initconst = { * Affects: store buffer * store buffer is not automatically drained. */ +static void __init pl310_save(void __iomem *base) +{ + u32 l2x0_revision = readl_relaxed(base + L2X0_CACHE_ID) & + L2X0_CACHE_ID_RTL_MASK; + + l2x0_saved_regs.tag_latency = readl_relaxed(base + + L2X0_TAG_LATENCY_CTRL); + l2x0_saved_regs.data_latency = readl_relaxed(base + + L2X0_DATA_LATENCY_CTRL); + l2x0_saved_regs.filter_end = readl_relaxed(base + + L2X0_ADDR_FILTER_END); + l2x0_saved_regs.filter_start = readl_relaxed(base + + L2X0_ADDR_FILTER_START); + + if (l2x0_revision >= L310_CACHE_ID_RTL_R2P0) { + /* + * From r2p0, there is Prefetch offset/control register + */ + l2x0_saved_regs.prefetch_ctrl = readl_relaxed(base + + L2X0_PREFETCH_CTRL); + /* + * From r3p0, there is Power control register + */ + if (l2x0_revision >= L310_CACHE_ID_RTL_R3P0) + l2x0_saved_regs.pwr_ctrl = readl_relaxed(base + + L2X0_POWER_CTRL); + } +} + +static void pl310_resume(void) +{ + u32 l2x0_revision; + + if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { + /* restore pl310 setup */ + writel_relaxed(l2x0_saved_regs.tag_latency, + l2x0_base + L2X0_TAG_LATENCY_CTRL); + writel_relaxed(l2x0_saved_regs.data_latency, + l2x0_base + L2X0_DATA_LATENCY_CTRL); + writel_relaxed(l2x0_saved_regs.filter_end, + l2x0_base + L2X0_ADDR_FILTER_END); + writel_relaxed(l2x0_saved_regs.filter_start, + l2x0_base + L2X0_ADDR_FILTER_START); + + l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) & + L2X0_CACHE_ID_RTL_MASK; + + if (l2x0_revision >= L310_CACHE_ID_RTL_R2P0) { + writel_relaxed(l2x0_saved_regs.prefetch_ctrl, + l2x0_base + L2X0_PREFETCH_CTRL); + if (l2x0_revision >= L310_CACHE_ID_RTL_R3P0) + writel_relaxed(l2x0_saved_regs.pwr_ctrl, + l2x0_base + L2X0_POWER_CTRL); + } + } + + l2x0_resume(); +} + static void __init l2c310_fixup(void __iomem *base, u32 cache_id, struct outer_cache_fns *fns) { @@ -455,6 +530,7 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .num_lock = 8, .enable = l2c_enable, .fixup = l2c310_fixup, + .save = pl310_save, .outer_cache = { .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range, @@ -462,6 +538,7 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .flush_all = l2x0_flush_all, .disable = l2x0_disable, .sync = l2x0_cache_sync, + .resume = pl310_resume, }, }; @@ -614,21 +691,6 @@ static void __init l2x0_of_parse(const struct device_node *np, *aux_mask &= ~mask; } -static void l2x0_resume(void) -{ - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { - /* restore aux ctrl and enable l2 */ - l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID)); - - writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base + - L2X0_AUX_CTRL); - - l2x0_inv_all(); - - writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL); - } -} - static const struct l2c_init_data of_l2x0_data __initconst = { .of_parse = l2x0_of_parse, .enable = l2x0_enable, @@ -677,65 +739,6 @@ static void __init pl310_of_parse(const struct device_node *np, } } -static void __init pl310_save(void __iomem *base) -{ - u32 l2x0_revision = readl_relaxed(base + L2X0_CACHE_ID) & - L2X0_CACHE_ID_RTL_MASK; - - l2x0_saved_regs.tag_latency = readl_relaxed(base + - L2X0_TAG_LATENCY_CTRL); - l2x0_saved_regs.data_latency = readl_relaxed(base + - L2X0_DATA_LATENCY_CTRL); - l2x0_saved_regs.filter_end = readl_relaxed(base + - L2X0_ADDR_FILTER_END); - l2x0_saved_regs.filter_start = readl_relaxed(base + - L2X0_ADDR_FILTER_START); - - if (l2x0_revision >= L310_CACHE_ID_RTL_R2P0) { - /* - * From r2p0, there is Prefetch offset/control register - */ - l2x0_saved_regs.prefetch_ctrl = readl_relaxed(base + - L2X0_PREFETCH_CTRL); - /* - * From r3p0, there is Power control register - */ - if (l2x0_revision >= L310_CACHE_ID_RTL_R3P0) - l2x0_saved_regs.pwr_ctrl = readl_relaxed(base + - L2X0_POWER_CTRL); - } -} - -static void pl310_resume(void) -{ - u32 l2x0_revision; - - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { - /* restore pl310 setup */ - writel_relaxed(l2x0_saved_regs.tag_latency, - l2x0_base + L2X0_TAG_LATENCY_CTRL); - writel_relaxed(l2x0_saved_regs.data_latency, - l2x0_base + L2X0_DATA_LATENCY_CTRL); - writel_relaxed(l2x0_saved_regs.filter_end, - l2x0_base + L2X0_ADDR_FILTER_END); - writel_relaxed(l2x0_saved_regs.filter_start, - l2x0_base + L2X0_ADDR_FILTER_START); - - l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) & - L2X0_CACHE_ID_RTL_MASK; - - if (l2x0_revision >= L310_CACHE_ID_RTL_R2P0) { - writel_relaxed(l2x0_saved_regs.prefetch_ctrl, - l2x0_base + L2X0_PREFETCH_CTRL); - if (l2x0_revision >= L310_CACHE_ID_RTL_R3P0) - writel_relaxed(l2x0_saved_regs.pwr_ctrl, - l2x0_base + L2X0_POWER_CTRL); - } - } - - l2x0_resume(); -} - static const struct l2c_init_data of_pl310_data __initconst = { .num_lock = 8, .of_parse = pl310_of_parse, -- cgit v1.2.3 From 09a5d180ed9d5aeb9bd6b0ba2c63ad4be05cb9b9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:13 +0000 Subject: ARM: l2c: clean up save/resume functions Rename the pl310 save/resume functions to have a l2c310 prefix - this is it's official name. Use a local cached copy of the l2x0_base virtual address, and also realise that many of the resume function tails are the same as the enable functions, so make a call to the enable function instead of duplicating that code. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 109 ++++++++++++++++++++++------------------------- 1 file changed, 52 insertions(+), 57 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 4d985c17291c..e3f4fcbcc88b 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -385,17 +385,10 @@ static void l2x0_enable(void __iomem *base, u32 aux, unsigned num_lock) static void l2x0_resume(void) { - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { - /* restore aux ctrl and enable l2 */ - l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID)); - - writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base + - L2X0_AUX_CTRL); - - l2x0_inv_all(); + void __iomem *base = l2x0_base; - writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL); - } + if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) + l2x0_enable(base, l2x0_saved_regs.aux_ctrl, 0); } static const struct l2c_init_data l2x0_init_fns __initconst = { @@ -438,10 +431,9 @@ static const struct l2c_init_data l2x0_init_fns __initconst = { * Affects: store buffer * store buffer is not automatically drained. */ -static void __init pl310_save(void __iomem *base) +static void __init l2c310_save(void __iomem *base) { - u32 l2x0_revision = readl_relaxed(base + L2X0_CACHE_ID) & - L2X0_CACHE_ID_RTL_MASK; + unsigned revision; l2x0_saved_regs.tag_latency = readl_relaxed(base + L2X0_TAG_LATENCY_CTRL); @@ -452,49 +444,49 @@ static void __init pl310_save(void __iomem *base) l2x0_saved_regs.filter_start = readl_relaxed(base + L2X0_ADDR_FILTER_START); - if (l2x0_revision >= L310_CACHE_ID_RTL_R2P0) { - /* - * From r2p0, there is Prefetch offset/control register - */ + revision = readl_relaxed(base + L2X0_CACHE_ID) & + L2X0_CACHE_ID_RTL_MASK; + + /* From r2p0, there is Prefetch offset/control register */ + if (revision >= L310_CACHE_ID_RTL_R2P0) l2x0_saved_regs.prefetch_ctrl = readl_relaxed(base + - L2X0_PREFETCH_CTRL); - /* - * From r3p0, there is Power control register - */ - if (l2x0_revision >= L310_CACHE_ID_RTL_R3P0) - l2x0_saved_regs.pwr_ctrl = readl_relaxed(base + - L2X0_POWER_CTRL); - } + L2X0_PREFETCH_CTRL); + + /* From r3p0, there is Power control register */ + if (revision >= L310_CACHE_ID_RTL_R3P0) + l2x0_saved_regs.pwr_ctrl = readl_relaxed(base + + L2X0_POWER_CTRL); } -static void pl310_resume(void) +static void l2c310_resume(void) { - u32 l2x0_revision; + void __iomem *base = l2x0_base; + + if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) { + unsigned revision; - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { /* restore pl310 setup */ writel_relaxed(l2x0_saved_regs.tag_latency, - l2x0_base + L2X0_TAG_LATENCY_CTRL); + base + L2X0_TAG_LATENCY_CTRL); writel_relaxed(l2x0_saved_regs.data_latency, - l2x0_base + L2X0_DATA_LATENCY_CTRL); + base + L2X0_DATA_LATENCY_CTRL); writel_relaxed(l2x0_saved_regs.filter_end, - l2x0_base + L2X0_ADDR_FILTER_END); + base + L2X0_ADDR_FILTER_END); writel_relaxed(l2x0_saved_regs.filter_start, - l2x0_base + L2X0_ADDR_FILTER_START); + base + L2X0_ADDR_FILTER_START); - l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) & - L2X0_CACHE_ID_RTL_MASK; + revision = readl_relaxed(base + L2X0_CACHE_ID) & + L2X0_CACHE_ID_RTL_MASK; - if (l2x0_revision >= L310_CACHE_ID_RTL_R2P0) { + if (revision >= L310_CACHE_ID_RTL_R2P0) writel_relaxed(l2x0_saved_regs.prefetch_ctrl, - l2x0_base + L2X0_PREFETCH_CTRL); - if (l2x0_revision >= L310_CACHE_ID_RTL_R3P0) - writel_relaxed(l2x0_saved_regs.pwr_ctrl, - l2x0_base + L2X0_POWER_CTRL); - } - } + base + L2X0_PREFETCH_CTRL); + if (revision >= L310_CACHE_ID_RTL_R3P0) + writel_relaxed(l2x0_saved_regs.pwr_ctrl, + base + L2X0_POWER_CTRL); - l2x0_resume(); + l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8); + } } static void __init l2c310_fixup(void __iomem *base, u32 cache_id, @@ -530,7 +522,7 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .num_lock = 8, .enable = l2c_enable, .fixup = l2c310_fixup, - .save = pl310_save, + .save = l2c310_save, .outer_cache = { .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range, @@ -538,7 +530,7 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .flush_all = l2x0_flush_all, .disable = l2x0_disable, .sync = l2x0_cache_sync, - .resume = pl310_resume, + .resume = l2c310_resume, }, }; @@ -744,7 +736,7 @@ static const struct l2c_init_data of_pl310_data __initconst = { .of_parse = pl310_of_parse, .enable = l2c_enable, .fixup = l2c310_fixup, - .save = pl310_save, + .save = l2c310_save, .outer_cache = { .inv_range = l2x0_inv_range, .clean_range = l2x0_clean_range, @@ -752,7 +744,7 @@ static const struct l2c_init_data of_pl310_data __initconst = { .flush_all = l2x0_flush_all, .disable = l2x0_disable, .sync = l2x0_cache_sync, - .resume = pl310_resume, + .resume = l2c310_resume, }, }; @@ -862,10 +854,11 @@ static void aurora_save(void __iomem *base) static void aurora_resume(void) { - if (!(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { - writel_relaxed(l2x0_saved_regs.aux_ctrl, - l2x0_base + L2X0_AUX_CTRL); - writel_relaxed(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL); + void __iomem *base = l2x0_base; + + if (!(readl(base + L2X0_CTRL) & L2X0_CTRL_EN)) { + writel_relaxed(l2x0_saved_regs.aux_ctrl, base + L2X0_AUX_CTRL); + writel_relaxed(l2x0_saved_regs.ctrl, base + L2X0_CTRL); } } @@ -1089,7 +1082,7 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .of_parse = pl310_of_parse, .enable = l2c_enable, .fixup = l2c310_fixup, - .save = pl310_save, + .save = l2c310_save, .outer_cache = { .inv_range = bcm_inv_range, .clean_range = bcm_clean_range, @@ -1097,7 +1090,7 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .flush_all = l2x0_flush_all, .disable = l2x0_disable, .sync = l2x0_cache_sync, - .resume = pl310_resume, + .resume = l2c310_resume, }, }; @@ -1111,14 +1104,16 @@ static void __init tauros3_save(void __iomem *base) static void tauros3_resume(void) { - if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { + void __iomem *base = l2x0_base; + + if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) { writel_relaxed(l2x0_saved_regs.aux2_ctrl, - l2x0_base + TAUROS3_AUX2_CTRL); + base + TAUROS3_AUX2_CTRL); writel_relaxed(l2x0_saved_regs.prefetch_ctrl, - l2x0_base + L2X0_PREFETCH_CTRL); - } + base + L2X0_PREFETCH_CTRL); - l2x0_resume(); + l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8); + } } static const struct l2c_init_data of_tauros3_data __initconst = { -- cgit v1.2.3 From faf9b2e7018b0afede92329c5b35e5d113a07f1c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 22:49:59 +0000 Subject: ARM: l2c: simplify l2x0 unlocking code The l2x0 unlocking code is only called from l2x0_enable() now, so move the logic entirely into that function and simplify it. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index e3f4fcbcc88b..157fd7ae331a 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -352,30 +352,21 @@ static void l2x0_disable(void) raw_spin_unlock_irqrestore(&l2x0_lock, flags); } -static void l2x0_unlock(u32 cache_id) +static void l2x0_enable(void __iomem *base, u32 aux, unsigned num_lock) { - int lockregs; + unsigned id; - switch (cache_id & L2X0_CACHE_ID_PART_MASK) { - case L2X0_CACHE_ID_PART_L310: - lockregs = 8; - break; - default: - /* L210 and unknown types */ - lockregs = 1; - break; - } - - l2c_unlock(l2x0_base, lockregs); -} + id = readl_relaxed(base + L2X0_CACHE_ID) & L2X0_CACHE_ID_PART_MASK; + if (id == L2X0_CACHE_ID_PART_L310) + num_lock = 8; + else + num_lock = 1; -static void l2x0_enable(void __iomem *base, u32 aux, unsigned num_lock) -{ /* l2x0 controller is disabled */ writel_relaxed(aux, base + L2X0_AUX_CTRL); /* Make sure that I&D is not locked down when starting */ - l2x0_unlock(readl_relaxed(base + L2X0_CACHE_ID)); + l2c_unlock(base, num_lock); l2x0_inv_all(); -- cgit v1.2.3 From bda0b74e6a5a4ce25198f55889bb321532c63d92 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:16 +0000 Subject: ARM: l2c: move pl310_set_debug() into l2c-310 code Move the pl310_set_debug() into the l2c-310 code area, and don't hide it with ifdefs. Rename it to l2c310_set_debug(). Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 157fd7ae331a..9586be73ca4f 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -154,18 +154,11 @@ static inline void debug_writel(unsigned long val) if (outer_cache.set_debug) l2c_set_debug(l2x0_base, val); } - -static void pl310_set_debug(unsigned long val) -{ - writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL); -} #else /* Optimised out for non-errata case */ static inline void debug_writel(unsigned long val) { } - -#define pl310_set_debug NULL #endif #ifdef CONFIG_PL310_ERRATA_588369 @@ -422,6 +415,11 @@ static const struct l2c_init_data l2x0_init_fns __initconst = { * Affects: store buffer * store buffer is not automatically drained. */ +static void l2c310_set_debug(unsigned long val) +{ + writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL); +} + static void __init l2c310_save(void __iomem *base) { unsigned revision; @@ -488,7 +486,7 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, unsigned n = 0; if (revision <= L310_CACHE_ID_RTL_R3P0) - fns->set_debug = pl310_set_debug; + fns->set_debug = l2c310_set_debug; if (IS_ENABLED(CONFIG_PL310_ERRATA_753970) && revision == L310_CACHE_ID_RTL_R3P0) { -- cgit v1.2.3 From 6a28cf59ff1144398d9d32d409ed8cbf1215922d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 18:55:53 +0000 Subject: ARM: l2c: add L2C-210 specific handlers Add L2C-210 specific cache operation handlers. These are tailored to the requirements of the L2C-210 cache controller, which doesn't require any workarounds. We avoid using the way operations during normal operation, which means we can avoid locking: the only time we use the way operations are during initialisation, and when disabling the cache. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 9586be73ca4f..d07fa4fc95a3 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -388,6 +388,108 @@ static const struct l2c_init_data l2x0_init_fns __initconst = { }, }; +/* + * L2C-210 specific code. + * + * The L2C-2x0 PA, set/way and sync operations are atomic, but we must + * ensure that no background operation is running. The way operations + * are all background tasks. + * + * While a background operation is in progress, any new operation is + * ignored (unspecified whether this causes an error.) Thankfully, not + * used on SMP. + * + * Never has a different sync register other than L2X0_CACHE_SYNC, but + * we use sync_reg_offset here so we can share some of this with L2C-310. + */ +static void __l2c210_cache_sync(void __iomem *base) +{ + writel_relaxed(0, base + sync_reg_offset); +} + +static void __l2c210_op_pa_range(void __iomem *reg, unsigned long start, + unsigned long end) +{ + while (start < end) { + writel_relaxed(start, reg); + start += CACHE_LINE_SIZE; + } +} + +static void l2c210_inv_range(unsigned long start, unsigned long end) +{ + void __iomem *base = l2x0_base; + + if (start & (CACHE_LINE_SIZE - 1)) { + start &= ~(CACHE_LINE_SIZE - 1); + writel_relaxed(start, base + L2X0_CLEAN_INV_LINE_PA); + start += CACHE_LINE_SIZE; + } + + if (end & (CACHE_LINE_SIZE - 1)) { + end &= ~(CACHE_LINE_SIZE - 1); + writel_relaxed(end, base + L2X0_CLEAN_INV_LINE_PA); + } + + __l2c210_op_pa_range(base + L2X0_INV_LINE_PA, start, end); + __l2c210_cache_sync(base); +} + +static void l2c210_clean_range(unsigned long start, unsigned long end) +{ + void __iomem *base = l2x0_base; + + start &= ~(CACHE_LINE_SIZE - 1); + __l2c210_op_pa_range(base + L2X0_CLEAN_LINE_PA, start, end); + __l2c210_cache_sync(base); +} + +static void l2c210_flush_range(unsigned long start, unsigned long end) +{ + void __iomem *base = l2x0_base; + + start &= ~(CACHE_LINE_SIZE - 1); + __l2c210_op_pa_range(base + L2X0_CLEAN_INV_LINE_PA, start, end); + __l2c210_cache_sync(base); +} + +static void l2c210_flush_all(void) +{ + void __iomem *base = l2x0_base; + + BUG_ON(!irqs_disabled()); + + __l2c_op_way(base + L2X0_CLEAN_INV_WAY); + __l2c210_cache_sync(base); +} + +static void l2c210_sync(void) +{ + __l2c210_cache_sync(l2x0_base); +} + +static void l2c210_resume(void) +{ + void __iomem *base = l2x0_base; + + if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) + l2c_enable(base, l2x0_saved_regs.aux_ctrl, 1); +} + +static const struct l2c_init_data l2c210_data __initconst = { + .num_lock = 1, + .enable = l2c_enable, + .outer_cache = { + .inv_range = l2c210_inv_range, + .clean_range = l2c210_clean_range, + .flush_range = l2c210_flush_range, + .flush_all = l2c210_flush_all, + .disable = l2c_disable, + .sync = l2c210_sync, + .resume = l2c210_resume, + }, +}; + /* * L2C-310 specific code. * @@ -623,6 +725,10 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) data = &l2x0_init_fns; break; + case L2X0_CACHE_ID_PART_L210: + data = &l2c210_data; + break; + case L2X0_CACHE_ID_PART_L310: data = &l2c310_init_fns; break; @@ -672,6 +778,21 @@ static void __init l2x0_of_parse(const struct device_node *np, *aux_mask &= ~mask; } +static const struct l2c_init_data of_l2c210_data __initconst = { + .num_lock = 1, + .of_parse = l2x0_of_parse, + .enable = l2c_enable, + .outer_cache = { + .inv_range = l2c210_inv_range, + .clean_range = l2c210_clean_range, + .flush_range = l2c210_flush_range, + .flush_all = l2c210_flush_all, + .disable = l2c_disable, + .sync = l2c210_sync, + .resume = l2c210_resume, + }, +}; + static const struct l2c_init_data of_l2x0_data __initconst = { .of_parse = l2x0_of_parse, .enable = l2x0_enable, @@ -1117,7 +1238,7 @@ static const struct l2c_init_data of_tauros3_data __initconst = { #define L2C_ID(name, fns) { .compatible = name, .data = (void *)&fns } static const struct of_device_id l2x0_ids[] __initconst = { - L2C_ID("arm,l210-cache", of_l2x0_data), + L2C_ID("arm,l210-cache", of_l2c210_data), L2C_ID("arm,l220-cache", of_l2x0_data), L2C_ID("arm,pl310-cache", of_pl310_data), L2C_ID("brcm,bcm11351-a2-pl310-cache", of_bcm_l2x0_data), -- cgit v1.2.3 From 99ca1772e52d8825172100a24e461a0ffe11e125 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:18 +0000 Subject: ARM: l2c: implement L2C-310 erratum 727915 as a method override Implement L2C-310 erratum 727915 by overriding the flush_all method in the outer_cache operations structure. This allows us to sensibly contain the erratum code in one place without affecting other locations or implementations. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index d07fa4fc95a3..6161232c8a85 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -522,6 +522,19 @@ static void l2c310_set_debug(unsigned long val) writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL); } +static void l2c310_flush_all_erratum(void) +{ + void __iomem *base = l2x0_base; + unsigned long flags; + + raw_spin_lock_irqsave(&l2x0_lock, flags); + l2c_set_debug(base, 0x03); + __l2c_op_way(base + L2X0_CLEAN_INV_WAY); + l2c_set_debug(base, 0x00); + __l2c210_cache_sync(base); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); +} + static void __init l2c310_save(void __iomem *base) { unsigned revision; @@ -590,6 +603,13 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, if (revision <= L310_CACHE_ID_RTL_R3P0) fns->set_debug = l2c310_set_debug; + if (IS_ENABLED(CONFIG_PL310_ERRATA_727915) && + revision >= L310_CACHE_ID_RTL_R2P0 && + revision < L310_CACHE_ID_RTL_R3P1) { + fns->flush_all = l2c310_flush_all_erratum; + errata[n++] = "727915"; + } + if (IS_ENABLED(CONFIG_PL310_ERRATA_753970) && revision == L310_CACHE_ID_RTL_R3P0) { sync_reg_offset = L2X0_DUMMY_REG; -- cgit v1.2.3 From ebd4219f10fbe3938cd36443e240eb6076b811ab Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 19:08:11 +0000 Subject: ARM: l2c: implement L2C-310 erratum 588369 as a method override Implement L2C-310 erratum 588369 by overriding the invalidate range and flush range methods in the outer_cache operations structure. This allows us to sensibly contain the erratum code in one place without affecting other locations/implemetations. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 6161232c8a85..79ff08db204d 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -522,6 +522,65 @@ static void l2c310_set_debug(unsigned long val) writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL); } +static void l2c310_inv_range_erratum(unsigned long start, unsigned long end) +{ + void __iomem *base = l2x0_base; + + if ((start | end) & (CACHE_LINE_SIZE - 1)) { + unsigned long flags; + + /* Erratum 588369 for both clean+invalidate operations */ + raw_spin_lock_irqsave(&l2x0_lock, flags); + l2c_set_debug(base, 0x03); + + if (start & (CACHE_LINE_SIZE - 1)) { + start &= ~(CACHE_LINE_SIZE - 1); + writel_relaxed(start, base + L2X0_CLEAN_LINE_PA); + writel_relaxed(start, base + L2X0_INV_LINE_PA); + start += CACHE_LINE_SIZE; + } + + if (end & (CACHE_LINE_SIZE - 1)) { + end &= ~(CACHE_LINE_SIZE - 1); + writel_relaxed(end, base + L2X0_CLEAN_LINE_PA); + writel_relaxed(end, base + L2X0_INV_LINE_PA); + } + + l2c_set_debug(base, 0x00); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); + } + + __l2c210_op_pa_range(base + L2X0_INV_LINE_PA, start, end); + __l2c210_cache_sync(base); +} + +static void l2c310_flush_range_erratum(unsigned long start, unsigned long end) +{ + raw_spinlock_t *lock = &l2x0_lock; + unsigned long flags; + void __iomem *base = l2x0_base; + + raw_spin_lock_irqsave(lock, flags); + while (start < end) { + unsigned long blk_end = start + min(end - start, 4096UL); + + l2c_set_debug(base, 0x03); + while (start < blk_end) { + writel_relaxed(start, base + L2X0_CLEAN_LINE_PA); + writel_relaxed(start, base + L2X0_INV_LINE_PA); + start += CACHE_LINE_SIZE; + } + l2c_set_debug(base, 0x00); + + if (blk_end < end) { + raw_spin_unlock_irqrestore(lock, flags); + raw_spin_lock_irqsave(lock, flags); + } + } + raw_spin_unlock_irqrestore(lock, flags); + __l2c210_cache_sync(base); +} + static void l2c310_flush_all_erratum(void) { void __iomem *base = l2x0_base; @@ -600,9 +659,19 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, const char *errata[4]; unsigned n = 0; + /* For compatibility */ if (revision <= L310_CACHE_ID_RTL_R3P0) fns->set_debug = l2c310_set_debug; + if (IS_ENABLED(CONFIG_PL310_ERRATA_588369) && + revision < L310_CACHE_ID_RTL_R2P0 && + /* For bcm compatibility */ + fns->inv_range == l2x0_inv_range) { + fns->inv_range = l2c310_inv_range_erratum; + fns->flush_range = l2c310_flush_range_erratum; + errata[n++] = "588369"; + } + if (IS_ENABLED(CONFIG_PL310_ERRATA_727915) && revision >= L310_CACHE_ID_RTL_R2P0 && revision < L310_CACHE_ID_RTL_R3P1) { -- cgit v1.2.3 From f777332ba7ae42c396b7aabc20bdbeeebb3a63c0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 20:51:47 +0000 Subject: ARM: l2c: use L2C-210 handlers for L2C-310 errata-less implementations Where no errata affect the L2C-310 handlers, they are functionally equivalent to L2C-210. Re-use the L2C-210 handlers for the L2C-310 part. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 58 ++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 22 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 79ff08db204d..49ddff972cb3 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -493,6 +493,18 @@ static const struct l2c_init_data l2c210_data __initconst = { /* * L2C-310 specific code. * + * Very similar to L2C-210, the PA, set/way and sync operations are atomic, + * and the way operations are all background tasks. However, issuing an + * operation while a background operation is in progress results in a + * SLVERR response. We can reuse: + * + * __l2c210_cache_sync (using sync_reg_offset) + * l2c210_sync + * l2c210_inv_range (if 588369 is not applicable) + * l2c210_clean_range + * l2c210_flush_range (if 588369 is not applicable) + * l2c210_flush_all (if 727915 is not applicable) + * * Errata: * 588369: PL310 R0P0->R1P0, fixed R2P0. * Affects: all clean+invalidate operations @@ -666,7 +678,7 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, if (IS_ENABLED(CONFIG_PL310_ERRATA_588369) && revision < L310_CACHE_ID_RTL_R2P0 && /* For bcm compatibility */ - fns->inv_range == l2x0_inv_range) { + fns->inv_range == l2c210_inv_range) { fns->inv_range = l2c310_inv_range_erratum; fns->flush_range = l2c310_flush_range_erratum; errata[n++] = "588369"; @@ -704,12 +716,13 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .fixup = l2c310_fixup, .save = l2c310_save, .outer_cache = { - .inv_range = l2x0_inv_range, - .clean_range = l2x0_clean_range, - .flush_range = l2x0_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, + .inv_range = l2c210_inv_range, + .clean_range = l2c210_clean_range, + .flush_range = l2c210_flush_range, + .flush_all = l2c210_flush_all, + .disable = l2c_disable, + .sync = l2c210_sync, + .set_debug = l2c310_set_debug, .resume = l2c310_resume, }, }; @@ -896,8 +909,8 @@ static const struct l2c_init_data of_l2x0_data __initconst = { }, }; -static void __init pl310_of_parse(const struct device_node *np, - u32 *aux_val, u32 *aux_mask) +static void __init l2c310_of_parse(const struct device_node *np, + u32 *aux_val, u32 *aux_mask) { u32 data[3] = { 0, 0, 0 }; u32 tag[3] = { 0, 0, 0 }; @@ -930,19 +943,20 @@ static void __init pl310_of_parse(const struct device_node *np, } } -static const struct l2c_init_data of_pl310_data __initconst = { +static const struct l2c_init_data of_l2c310_data __initconst = { .num_lock = 8, - .of_parse = pl310_of_parse, + .of_parse = l2c310_of_parse, .enable = l2c_enable, .fixup = l2c310_fixup, .save = l2c310_save, .outer_cache = { - .inv_range = l2x0_inv_range, - .clean_range = l2x0_clean_range, - .flush_range = l2x0_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, + .inv_range = l2c210_inv_range, + .clean_range = l2c210_clean_range, + .flush_range = l2c210_flush_range, + .flush_all = l2c210_flush_all, + .disable = l2c_disable, + .sync = l2c210_sync, + .set_debug = l2c310_set_debug, .resume = l2c310_resume, }, }; @@ -1278,7 +1292,7 @@ static void bcm_flush_range(unsigned long start, unsigned long end) static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .num_lock = 8, - .of_parse = pl310_of_parse, + .of_parse = l2c310_of_parse, .enable = l2c_enable, .fixup = l2c310_fixup, .save = l2c310_save, @@ -1286,9 +1300,9 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .inv_range = bcm_inv_range, .clean_range = bcm_clean_range, .flush_range = bcm_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, + .flush_all = l2c210_flush_all, + .disable = l2c_disable, + .sync = l2c210_sync, .resume = l2c310_resume, }, }; @@ -1329,7 +1343,7 @@ static const struct l2c_init_data of_tauros3_data __initconst = { static const struct of_device_id l2x0_ids[] __initconst = { L2C_ID("arm,l210-cache", of_l2c210_data), L2C_ID("arm,l220-cache", of_l2x0_data), - L2C_ID("arm,pl310-cache", of_pl310_data), + L2C_ID("arm,pl310-cache", of_l2c310_data), L2C_ID("brcm,bcm11351-a2-pl310-cache", of_bcm_l2x0_data), L2C_ID("marvell,aurora-outer-cache", of_aurora_with_outer_data), L2C_ID("marvell,aurora-system-cache", of_aurora_no_outer_data), -- cgit v1.2.3 From 733c6bbafdfac62a307ed5ca925889343c5635ac Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 21:29:28 +0000 Subject: ARM: l2c: add L2C-220 specific handlers The L2C-220 is different from the L2C-210 and L2C-310 in that every operation is a background operation: this means we have to use spinlocks to protect all operations, and we have to wait for every operation to complete. Should a second operation be attempted while a previous operation is in progress, the response will be an imprecise abort. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 167 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 157 insertions(+), 10 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 49ddff972cb3..751c3d7a22b3 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -490,6 +490,148 @@ static const struct l2c_init_data l2c210_data __initconst = { }, }; +/* + * L2C-220 specific code. + * + * All operations are background operations: they have to be waited for. + * Conflicting requests generate a slave error (which will cause an + * imprecise abort.) Never uses sync_reg_offset, so we hard-code the + * sync register here. + * + * However, we can re-use the l2c210_resume call. + */ +static inline void __l2c220_cache_sync(void __iomem *base) +{ + writel_relaxed(0, base + L2X0_CACHE_SYNC); + l2c_wait_mask(base + L2X0_CACHE_SYNC, 1); +} + +static void l2c220_op_way(void __iomem *base, unsigned reg) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&l2x0_lock, flags); + __l2c_op_way(base + reg); + __l2c220_cache_sync(base); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); +} + +static unsigned long l2c220_op_pa_range(void __iomem *reg, unsigned long start, + unsigned long end, unsigned long flags) +{ + raw_spinlock_t *lock = &l2x0_lock; + + while (start < end) { + unsigned long blk_end = start + min(end - start, 4096UL); + + while (start < blk_end) { + l2c_wait_mask(reg, 1); + writel_relaxed(start, reg); + start += CACHE_LINE_SIZE; + } + + if (blk_end < end) { + raw_spin_unlock_irqrestore(lock, flags); + raw_spin_lock_irqsave(lock, flags); + } + } + + return flags; +} + +static void l2c220_inv_range(unsigned long start, unsigned long end) +{ + void __iomem *base = l2x0_base; + unsigned long flags; + + raw_spin_lock_irqsave(&l2x0_lock, flags); + if ((start | end) & (CACHE_LINE_SIZE - 1)) { + if (start & (CACHE_LINE_SIZE - 1)) { + start &= ~(CACHE_LINE_SIZE - 1); + writel_relaxed(start, base + L2X0_CLEAN_INV_LINE_PA); + start += CACHE_LINE_SIZE; + } + + if (end & (CACHE_LINE_SIZE - 1)) { + end &= ~(CACHE_LINE_SIZE - 1); + l2c_wait_mask(base + L2X0_CLEAN_INV_LINE_PA, 1); + writel_relaxed(end, base + L2X0_CLEAN_INV_LINE_PA); + } + } + + flags = l2c220_op_pa_range(base + L2X0_INV_LINE_PA, + start, end, flags); + l2c_wait_mask(base + L2X0_INV_LINE_PA, 1); + __l2c220_cache_sync(base); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); +} + +static void l2c220_clean_range(unsigned long start, unsigned long end) +{ + void __iomem *base = l2x0_base; + unsigned long flags; + + start &= ~(CACHE_LINE_SIZE - 1); + if ((end - start) >= l2x0_size) { + l2c220_op_way(base, L2X0_CLEAN_WAY); + return; + } + + raw_spin_lock_irqsave(&l2x0_lock, flags); + flags = l2c220_op_pa_range(base + L2X0_CLEAN_LINE_PA, + start, end, flags); + l2c_wait_mask(base + L2X0_CLEAN_INV_LINE_PA, 1); + __l2c220_cache_sync(base); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); +} + +static void l2c220_flush_range(unsigned long start, unsigned long end) +{ + void __iomem *base = l2x0_base; + unsigned long flags; + + start &= ~(CACHE_LINE_SIZE - 1); + if ((end - start) >= l2x0_size) { + l2c220_op_way(base, L2X0_CLEAN_INV_WAY); + return; + } + + raw_spin_lock_irqsave(&l2x0_lock, flags); + flags = l2c220_op_pa_range(base + L2X0_CLEAN_INV_LINE_PA, + start, end, flags); + l2c_wait_mask(base + L2X0_CLEAN_INV_LINE_PA, 1); + __l2c220_cache_sync(base); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); +} + +static void l2c220_flush_all(void) +{ + l2c220_op_way(l2x0_base, L2X0_CLEAN_INV_WAY); +} + +static void l2c220_sync(void) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&l2x0_lock, flags); + __l2c220_cache_sync(l2x0_base); + raw_spin_unlock_irqrestore(&l2x0_lock, flags); +} + +static const struct l2c_init_data l2c220_data = { + .num_lock = 1, + .enable = l2c_enable, + .outer_cache = { + .inv_range = l2c220_inv_range, + .clean_range = l2c220_clean_range, + .flush_range = l2c220_flush_range, + .flush_all = l2c220_flush_all, + .disable = l2c_disable, + .sync = l2c220_sync, + .resume = l2c210_resume, + }, +}; + /* * L2C-310 specific code. * @@ -831,6 +973,10 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) data = &l2c210_data; break; + case L2X0_CACHE_ID_PART_L220: + data = &l2c220_data; + break; + case L2X0_CACHE_ID_PART_L310: data = &l2c310_init_fns; break; @@ -895,17 +1041,18 @@ static const struct l2c_init_data of_l2c210_data __initconst = { }, }; -static const struct l2c_init_data of_l2x0_data __initconst = { +static const struct l2c_init_data of_l2c220_data __initconst = { + .num_lock = 1, .of_parse = l2x0_of_parse, - .enable = l2x0_enable, + .enable = l2c_enable, .outer_cache = { - .inv_range = l2x0_inv_range, - .clean_range = l2x0_clean_range, - .flush_range = l2x0_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, - .resume = l2x0_resume, + .inv_range = l2c220_inv_range, + .clean_range = l2c220_clean_range, + .flush_range = l2c220_flush_range, + .flush_all = l2c220_flush_all, + .disable = l2c_disable, + .sync = l2c220_sync, + .resume = l2c210_resume, }, }; @@ -1342,7 +1489,7 @@ static const struct l2c_init_data of_tauros3_data __initconst = { #define L2C_ID(name, fns) { .compatible = name, .data = (void *)&fns } static const struct of_device_id l2x0_ids[] __initconst = { L2C_ID("arm,l210-cache", of_l2c210_data), - L2C_ID("arm,l220-cache", of_l2x0_data), + L2C_ID("arm,l220-cache", of_l2c220_data), L2C_ID("arm,pl310-cache", of_l2c310_data), L2C_ID("brcm,bcm11351-a2-pl310-cache", of_bcm_l2x0_data), L2C_ID("marvell,aurora-outer-cache", of_aurora_with_outer_data), -- cgit v1.2.3 From 9081114837742cf7f152c9bccbeeb2a9273183f4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 19:14:13 +0000 Subject: ARM: l2c: convert Broadcom L2C-310 to new code The Broadcom L2C-310 devices use ARMs L2C-310 R2P3 or later. These require no errata workarounds, and so we can directly call the l2c210 functions from their methods. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 751c3d7a22b3..57680e03da84 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1360,16 +1360,16 @@ static void bcm_inv_range(unsigned long start, unsigned long end) /* normal case, no cross section between start and end */ if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) { - l2x0_inv_range(new_start, new_end); + l2c210_inv_range(new_start, new_end); return; } /* They cross sections, so it can only be a cross from section * 2 to section 3 */ - l2x0_inv_range(new_start, + l2c210_inv_range(new_start, bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1)); - l2x0_inv_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), + l2c210_inv_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), new_end); } @@ -1382,26 +1382,21 @@ static void bcm_clean_range(unsigned long start, unsigned long end) if (unlikely(end <= start)) return; - if ((end - start) >= l2x0_size) { - l2x0_clean_all(); - return; - } - new_start = bcm_l2_phys_addr(start); new_end = bcm_l2_phys_addr(end); /* normal case, no cross section between start and end */ if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) { - l2x0_clean_range(new_start, new_end); + l2c210_clean_range(new_start, new_end); return; } /* They cross sections, so it can only be a cross from section * 2 to section 3 */ - l2x0_clean_range(new_start, + l2c210_clean_range(new_start, bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1)); - l2x0_clean_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), + l2c210_clean_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), new_end); } @@ -1415,7 +1410,7 @@ static void bcm_flush_range(unsigned long start, unsigned long end) return; if ((end - start) >= l2x0_size) { - l2x0_flush_all(); + outer_cache.flush_all(); return; } @@ -1424,24 +1419,24 @@ static void bcm_flush_range(unsigned long start, unsigned long end) /* normal case, no cross section between start and end */ if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) { - l2x0_flush_range(new_start, new_end); + l2c210_flush_range(new_start, new_end); return; } /* They cross sections, so it can only be a cross from section * 2 to section 3 */ - l2x0_flush_range(new_start, + l2c210_flush_range(new_start, bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1)); - l2x0_flush_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), + l2c210_flush_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), new_end); } +/* Broadcom L2C-310 start from ARMs R3P2 or later, and require no fixups */ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .num_lock = 8, .of_parse = l2c310_of_parse, .enable = l2c_enable, - .fixup = l2c310_fixup, .save = l2c310_save, .outer_cache = { .inv_range = bcm_inv_range, -- cgit v1.2.3 From cf9ea8f130e29915cb441e315f03ab4f64e0d73c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 22:44:38 +0000 Subject: ARM: l2c: remove obsolete l2x0 ops for non-OF init non-OF initialisation has never been used with any cache controller which isn't an ARM cache controller, so we can safely get rid of the old (and buggy) l2x0_*-based operations structure. This is also the last reference to: - l2x0_clean_line() - l2x0_inv_line() - l2x0_flush_line() - l2x0_flush_all() - l2x0_clean_all() - l2x0_inv_all() - l2x0_inv_range() - l2x0_clean_range() - l2x0_flush_range() - l2x0_enable() - l2x0_resume() so kill those functions too. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 206 ----------------------------------------------- 1 file changed, 206 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 57680e03da84..c5d754912f96 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -134,20 +134,6 @@ static inline void cache_sync(void) cache_wait(base + L2X0_CACHE_SYNC, 1); } -static inline void l2x0_clean_line(unsigned long addr) -{ - void __iomem *base = l2x0_base; - cache_wait(base + L2X0_CLEAN_LINE_PA, 1); - writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA); -} - -static inline void l2x0_inv_line(unsigned long addr) -{ - void __iomem *base = l2x0_base; - cache_wait(base + L2X0_INV_LINE_PA, 1); - writel_relaxed(addr, base + L2X0_INV_LINE_PA); -} - #if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915) static inline void debug_writel(unsigned long val) { @@ -161,27 +147,6 @@ static inline void debug_writel(unsigned long val) } #endif -#ifdef CONFIG_PL310_ERRATA_588369 -static inline void l2x0_flush_line(unsigned long addr) -{ - void __iomem *base = l2x0_base; - - /* Clean by PA followed by Invalidate by PA */ - cache_wait(base + L2X0_CLEAN_LINE_PA, 1); - writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA); - cache_wait(base + L2X0_INV_LINE_PA, 1); - writel_relaxed(addr, base + L2X0_INV_LINE_PA); -} -#else - -static inline void l2x0_flush_line(unsigned long addr) -{ - void __iomem *base = l2x0_base; - cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); - writel_relaxed(addr, base + L2X0_CLEAN_INV_LINE_PA); -} -#endif - static void l2x0_cache_sync(void) { unsigned long flags; @@ -209,131 +174,6 @@ static void l2x0_flush_all(void) raw_spin_unlock_irqrestore(&l2x0_lock, flags); } -static void l2x0_clean_all(void) -{ - unsigned long flags; - - /* clean all ways */ - raw_spin_lock_irqsave(&l2x0_lock, flags); - __l2c_op_way(l2x0_base + L2X0_CLEAN_WAY); - cache_sync(); - raw_spin_unlock_irqrestore(&l2x0_lock, flags); -} - -static void l2x0_inv_all(void) -{ - unsigned long flags; - - /* invalidate all ways */ - raw_spin_lock_irqsave(&l2x0_lock, flags); - /* Invalidating when L2 is enabled is a nono */ - BUG_ON(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN); - __l2c_op_way(l2x0_base + L2X0_INV_WAY); - cache_sync(); - raw_spin_unlock_irqrestore(&l2x0_lock, flags); -} - -static void l2x0_inv_range(unsigned long start, unsigned long end) -{ - void __iomem *base = l2x0_base; - unsigned long flags; - - raw_spin_lock_irqsave(&l2x0_lock, flags); - if (start & (CACHE_LINE_SIZE - 1)) { - start &= ~(CACHE_LINE_SIZE - 1); - debug_writel(0x03); - l2x0_flush_line(start); - debug_writel(0x00); - start += CACHE_LINE_SIZE; - } - - if (end & (CACHE_LINE_SIZE - 1)) { - end &= ~(CACHE_LINE_SIZE - 1); - debug_writel(0x03); - l2x0_flush_line(end); - debug_writel(0x00); - } - - while (start < end) { - unsigned long blk_end = start + min(end - start, 4096UL); - - while (start < blk_end) { - l2x0_inv_line(start); - start += CACHE_LINE_SIZE; - } - - if (blk_end < end) { - raw_spin_unlock_irqrestore(&l2x0_lock, flags); - raw_spin_lock_irqsave(&l2x0_lock, flags); - } - } - cache_wait(base + L2X0_INV_LINE_PA, 1); - cache_sync(); - raw_spin_unlock_irqrestore(&l2x0_lock, flags); -} - -static void l2x0_clean_range(unsigned long start, unsigned long end) -{ - void __iomem *base = l2x0_base; - unsigned long flags; - - if ((end - start) >= l2x0_size) { - l2x0_clean_all(); - return; - } - - raw_spin_lock_irqsave(&l2x0_lock, flags); - start &= ~(CACHE_LINE_SIZE - 1); - while (start < end) { - unsigned long blk_end = start + min(end - start, 4096UL); - - while (start < blk_end) { - l2x0_clean_line(start); - start += CACHE_LINE_SIZE; - } - - if (blk_end < end) { - raw_spin_unlock_irqrestore(&l2x0_lock, flags); - raw_spin_lock_irqsave(&l2x0_lock, flags); - } - } - cache_wait(base + L2X0_CLEAN_LINE_PA, 1); - cache_sync(); - raw_spin_unlock_irqrestore(&l2x0_lock, flags); -} - -static void l2x0_flush_range(unsigned long start, unsigned long end) -{ - void __iomem *base = l2x0_base; - unsigned long flags; - - if ((end - start) >= l2x0_size) { - l2x0_flush_all(); - return; - } - - raw_spin_lock_irqsave(&l2x0_lock, flags); - start &= ~(CACHE_LINE_SIZE - 1); - while (start < end) { - unsigned long blk_end = start + min(end - start, 4096UL); - - debug_writel(0x03); - while (start < blk_end) { - l2x0_flush_line(start); - start += CACHE_LINE_SIZE; - } - debug_writel(0x00); - - if (blk_end < end) { - raw_spin_unlock_irqrestore(&l2x0_lock, flags); - raw_spin_lock_irqsave(&l2x0_lock, flags); - } - } - cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); - cache_sync(); - raw_spin_unlock_irqrestore(&l2x0_lock, flags); -} - static void l2x0_disable(void) { unsigned long flags; @@ -345,49 +185,6 @@ static void l2x0_disable(void) raw_spin_unlock_irqrestore(&l2x0_lock, flags); } -static void l2x0_enable(void __iomem *base, u32 aux, unsigned num_lock) -{ - unsigned id; - - id = readl_relaxed(base + L2X0_CACHE_ID) & L2X0_CACHE_ID_PART_MASK; - if (id == L2X0_CACHE_ID_PART_L310) - num_lock = 8; - else - num_lock = 1; - - /* l2x0 controller is disabled */ - writel_relaxed(aux, base + L2X0_AUX_CTRL); - - /* Make sure that I&D is not locked down when starting */ - l2c_unlock(base, num_lock); - - l2x0_inv_all(); - - /* enable L2X0 */ - writel_relaxed(L2X0_CTRL_EN, base + L2X0_CTRL); -} - -static void l2x0_resume(void) -{ - void __iomem *base = l2x0_base; - - if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) - l2x0_enable(base, l2x0_saved_regs.aux_ctrl, 0); -} - -static const struct l2c_init_data l2x0_init_fns __initconst = { - .enable = l2x0_enable, - .outer_cache = { - .inv_range = l2x0_inv_range, - .clean_range = l2x0_clean_range, - .flush_range = l2x0_flush_range, - .flush_all = l2x0_flush_all, - .disable = l2x0_disable, - .sync = l2x0_cache_sync, - .resume = l2x0_resume, - }, -}; - /* * L2C-210 specific code. * @@ -966,9 +763,6 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) switch (cache_id & L2X0_CACHE_ID_PART_MASK) { default: - data = &l2x0_init_fns; - break; - case L2X0_CACHE_ID_PART_L210: data = &l2c210_data; break; -- cgit v1.2.3 From 051334bdc5252362500a686100d9ec20cbfdcd8a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 23:04:10 +0000 Subject: ARM: l2c: move type string into l2c_init_data structure Rather than decoding this from the ID register, store it in the l2c_init_data structure. This simplifies things some more, and allows us to better provide further details as to how we're driving the cache. We print the cache ID value anyway should we need to precisely identify the cache hardware. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index c5d754912f96..b4dd2f4b491b 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -29,6 +29,7 @@ #include "cache-aurora-l2.h" struct l2c_init_data { + const char *type; unsigned num_lock; void (*of_parse)(const struct device_node *, u32 *, u32 *); void (*enable)(void __iomem *, u32, unsigned); @@ -274,6 +275,7 @@ static void l2c210_resume(void) } static const struct l2c_init_data l2c210_data __initconst = { + .type = "L2C-210", .num_lock = 1, .enable = l2c_enable, .outer_cache = { @@ -416,6 +418,7 @@ static void l2c220_sync(void) } static const struct l2c_init_data l2c220_data = { + .type = "L2C-220", .num_lock = 1, .enable = l2c_enable, .outer_cache = { @@ -650,6 +653,7 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, } static const struct l2c_init_data l2c310_init_fns __initconst = { + .type = "L2C-310", .num_lock = 8, .enable = l2c_enable, .fixup = l2c310_fixup, @@ -674,7 +678,6 @@ static void __init __l2c_init(const struct l2c_init_data *data, u32 way_size = 0; int ways; int way_size_shift = L2X0_WAY_SIZE_SHIFT; - const char *type; /* * It is strange to save the register state before initialisation, @@ -695,25 +698,21 @@ static void __init __l2c_init(const struct l2c_init_data *data, ways = 16; else ways = 8; - type = "L310"; break; case L2X0_CACHE_ID_PART_L210: ways = (aux >> 13) & 0xf; - type = "L210"; break; case AURORA_CACHE_ID: ways = (aux >> 13) & 0xf; ways = 2 << ((ways + 1) >> 2); way_size_shift = AURORA_WAY_SIZE_SHIFT; - type = "Aurora"; break; default: /* Assume unknown chips have 8 ways */ ways = 8; - type = "L2x0 series"; break; } @@ -747,9 +746,9 @@ static void __init __l2c_init(const struct l2c_init_data *data, outer_cache = fns; pr_info("%s cache controller enabled, %d ways, %d kB\n", - type, ways, l2x0_size >> 10); + data->type, ways, l2x0_size >> 10); pr_info("%s: CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n", - type, cache_id, aux); + data->type, cache_id, aux); } void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) @@ -821,6 +820,7 @@ static void __init l2x0_of_parse(const struct device_node *np, } static const struct l2c_init_data of_l2c210_data __initconst = { + .type = "L2C-210", .num_lock = 1, .of_parse = l2x0_of_parse, .enable = l2c_enable, @@ -836,6 +836,7 @@ static const struct l2c_init_data of_l2c210_data __initconst = { }; static const struct l2c_init_data of_l2c220_data __initconst = { + .type = "L2C-220", .num_lock = 1, .of_parse = l2x0_of_parse, .enable = l2c_enable, @@ -885,6 +886,7 @@ static void __init l2c310_of_parse(const struct device_node *np, } static const struct l2c_init_data of_l2c310_data __initconst = { + .type = "L2C-310", .num_lock = 8, .of_parse = l2c310_of_parse, .enable = l2c_enable, @@ -1063,6 +1065,7 @@ static void __init aurora_of_parse(const struct device_node *np, } static const struct l2c_init_data of_aurora_with_outer_data __initconst = { + .type = "Aurora", .num_lock = 4, .of_parse = aurora_of_parse, .enable = l2c_enable, @@ -1080,6 +1083,7 @@ static const struct l2c_init_data of_aurora_with_outer_data __initconst = { }; static const struct l2c_init_data of_aurora_no_outer_data __initconst = { + .type = "Aurora", .num_lock = 4, .of_parse = aurora_of_parse, .enable = aurora_enable_no_outer, @@ -1228,6 +1232,7 @@ static void bcm_flush_range(unsigned long start, unsigned long end) /* Broadcom L2C-310 start from ARMs R3P2 or later, and require no fixups */ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { + .type = "BCM-L2C-310", .num_lock = 8, .of_parse = l2c310_of_parse, .enable = l2c_enable, @@ -1266,6 +1271,7 @@ static void tauros3_resume(void) } static const struct l2c_init_data of_tauros3_data __initconst = { + .type = "Tauros3", .num_lock = 8, .enable = l2c_enable, .save = tauros3_save, -- cgit v1.2.3 From 5f47c38704e15f9db356dd799391bc9f9efc4e0c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 23:07:07 +0000 Subject: ARM: l2c: add decode for L2C-220 cache ways Rather than assuming these are always 8-way, it can be decoded from the auxillary register in the same manner as L2C-210. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index b4dd2f4b491b..69a18316b239 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -701,6 +701,7 @@ static void __init __l2c_init(const struct l2c_init_data *data, break; case L2X0_CACHE_ID_PART_L210: + case L2X0_CACHE_ID_PART_L220: ways = (aux >> 13) & 0xf; break; -- cgit v1.2.3 From 0493aef4da8231b4b2f2da8dc1784c265e610a7d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 23:26:24 +0000 Subject: ARM: l2c: move way size calculation data into l2c_init_data Move the way size calculation data (base of way size) out of the switch statement into the provided initialisation data. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 69a18316b239..b4d373ab1a5c 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -30,6 +30,7 @@ struct l2c_init_data { const char *type; + unsigned way_size_0; unsigned num_lock; void (*of_parse)(const struct device_node *, u32 *, u32 *); void (*enable)(void __iomem *, u32, unsigned); @@ -276,6 +277,7 @@ static void l2c210_resume(void) static const struct l2c_init_data l2c210_data __initconst = { .type = "L2C-210", + .way_size_0 = SZ_8K, .num_lock = 1, .enable = l2c_enable, .outer_cache = { @@ -419,6 +421,7 @@ static void l2c220_sync(void) static const struct l2c_init_data l2c220_data = { .type = "L2C-220", + .way_size_0 = SZ_8K, .num_lock = 1, .enable = l2c_enable, .outer_cache = { @@ -654,6 +657,7 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, static const struct l2c_init_data l2c310_init_fns __initconst = { .type = "L2C-310", + .way_size_0 = SZ_8K, .num_lock = 8, .enable = l2c_enable, .fixup = l2c310_fixup, @@ -674,10 +678,8 @@ static void __init __l2c_init(const struct l2c_init_data *data, u32 aux_val, u32 aux_mask, u32 cache_id) { struct outer_cache_fns fns; + unsigned way_size_bits, ways; u32 aux; - u32 way_size = 0; - int ways; - int way_size_shift = L2X0_WAY_SIZE_SHIFT; /* * It is strange to save the register state before initialisation, @@ -708,7 +710,6 @@ static void __init __l2c_init(const struct l2c_init_data *data, case AURORA_CACHE_ID: ways = (aux >> 13) & 0xf; ways = 2 << ((ways + 1) >> 2); - way_size_shift = AURORA_WAY_SIZE_SHIFT; break; default: @@ -720,12 +721,15 @@ static void __init __l2c_init(const struct l2c_init_data *data, l2x0_way_mask = (1 << ways) - 1; /* - * L2 cache Size = Way size * Number of ways + * way_size_0 is the size that a way_size value of zero would be + * given the calculation: way_size = way_size_0 << way_size_bits. + * So, if way_size_bits=0 is reserved, but way_size_bits=1 is 16k, + * then way_size_0 would be 8k. + * + * L2 cache size = number of ways * way size. */ - way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17; - way_size = 1 << (way_size + way_size_shift); - - l2x0_size = ways * way_size * SZ_1K; + way_size_bits = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17; + l2x0_size = ways * (data->way_size_0 << way_size_bits); fns = data->outer_cache; if (data->fixup) @@ -822,6 +826,7 @@ static void __init l2x0_of_parse(const struct device_node *np, static const struct l2c_init_data of_l2c210_data __initconst = { .type = "L2C-210", + .way_size_0 = SZ_8K, .num_lock = 1, .of_parse = l2x0_of_parse, .enable = l2c_enable, @@ -838,6 +843,7 @@ static const struct l2c_init_data of_l2c210_data __initconst = { static const struct l2c_init_data of_l2c220_data __initconst = { .type = "L2C-220", + .way_size_0 = SZ_8K, .num_lock = 1, .of_parse = l2x0_of_parse, .enable = l2c_enable, @@ -888,6 +894,7 @@ static void __init l2c310_of_parse(const struct device_node *np, static const struct l2c_init_data of_l2c310_data __initconst = { .type = "L2C-310", + .way_size_0 = SZ_8K, .num_lock = 8, .of_parse = l2c310_of_parse, .enable = l2c_enable, @@ -1067,6 +1074,7 @@ static void __init aurora_of_parse(const struct device_node *np, static const struct l2c_init_data of_aurora_with_outer_data __initconst = { .type = "Aurora", + .way_size_0 = SZ_4K, .num_lock = 4, .of_parse = aurora_of_parse, .enable = l2c_enable, @@ -1085,6 +1093,7 @@ static const struct l2c_init_data of_aurora_with_outer_data __initconst = { static const struct l2c_init_data of_aurora_no_outer_data __initconst = { .type = "Aurora", + .way_size_0 = SZ_4K, .num_lock = 4, .of_parse = aurora_of_parse, .enable = aurora_enable_no_outer, @@ -1234,6 +1243,7 @@ static void bcm_flush_range(unsigned long start, unsigned long end) /* Broadcom L2C-310 start from ARMs R3P2 or later, and require no fixups */ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .type = "BCM-L2C-310", + .way_size_0 = SZ_8K, .num_lock = 8, .of_parse = l2c310_of_parse, .enable = l2c_enable, @@ -1273,6 +1283,7 @@ static void tauros3_resume(void) static const struct l2c_init_data of_tauros3_data __initconst = { .type = "Tauros3", + .way_size_0 = SZ_8K, .num_lock = 8, .enable = l2c_enable, .save = tauros3_save, -- cgit v1.2.3 From c0fe18ba30a62854490b1ac0f7a02145d84153f5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 12:12:11 +0000 Subject: ARM: l2c: move errata configuration options to arch/arm/mm/Kconfig Move the L2C-310 errata configuration options to arch/arm/mm/Kconfig along side the option which enables support for this device. Signed-off-by: Russell King --- arch/arm/Kconfig | 51 --------------------------------------------------- arch/arm/mm/Kconfig | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 51 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index db3c5414223e..c9d7196fd0bd 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1230,19 +1230,6 @@ config ARM_ERRATA_742231 register of the Cortex-A9 which reduces the linefill issuing capabilities of the processor. -config PL310_ERRATA_588369 - bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines" - depends on CACHE_L2X0 - help - The PL310 L2 cache controller implements three types of Clean & - Invalidate maintenance operations: by Physical Address - (offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC). - They are architecturally defined to behave as the execution of a - clean operation followed immediately by an invalidate operation, - both performing to the same memory location. This functionality - is not correctly implemented in PL310 as clean lines are not - invalidated as a result of these operations. - config ARM_ERRATA_643719 bool "ARM errata: LoUIS bit field in CLIDR register is incorrect" depends on CPU_V7 && SMP @@ -1265,17 +1252,6 @@ config ARM_ERRATA_720789 tables. The workaround changes the TLB flushing routines to invalidate entries regardless of the ASID. -config PL310_ERRATA_727915 - bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption" - depends on CACHE_L2X0 - help - PL310 implements the Clean & Invalidate by Way L2 cache maintenance - operation (offset 0x7FC). This operation runs in background so that - PL310 can handle normal accesses while it is in progress. Under very - rare circumstances, due to this erratum, write data can be lost when - PL310 treats a cacheable write transaction during a Clean & - Invalidate by Way operation. - config ARM_ERRATA_743622 bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption" depends on CPU_V7 @@ -1301,21 +1277,6 @@ config ARM_ERRATA_751472 operation is received by a CPU before the ICIALLUIS has completed, potentially leading to corrupted entries in the cache or TLB. -config PL310_ERRATA_753970 - bool "PL310 errata: cache sync operation may be faulty" - depends on CACHE_PL310 - help - This option enables the workaround for the 753970 PL310 (r3p0) erratum. - - Under some condition the effect of cache sync operation on - the store buffer still remains when the operation completes. - This means that the store buffer is always asked to drain and - this prevents it from merging any further writes. The workaround - is to replace the normal offset of cache sync operation (0x730) - by another offset targeting an unmapped PL310 register 0x740. - This has the same effect as the cache sync operation: store buffer - drain and waiting for all buffers empty. - config ARM_ERRATA_754322 bool "ARM errata: possible faulty MMU translations following an ASID switch" depends on CPU_V7 @@ -1364,18 +1325,6 @@ config ARM_ERRATA_764369 relevant cache maintenance functions and sets a specific bit in the diagnostic control register of the SCU. -config PL310_ERRATA_769419 - bool "PL310 errata: no automatic Store Buffer drain" - depends on CACHE_L2X0 - help - On revisions of the PL310 prior to r3p2, the Store Buffer does - not automatically drain. This can cause normal, non-cacheable - writes to be retained when the memory system is idle, leading - to suboptimal I/O performance for drivers using coherent DMA. - This option adds a write barrier to the cpu_idle loop so that, - on systems with an outer cache, the store buffer is drained - explicitly. - config ARM_ERRATA_775420 bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock" depends on CPU_V7 diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 5bf7c3c3b301..eda0dd0ab97b 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -897,6 +897,57 @@ config CACHE_PL310 This option enables optimisations for the PL310 cache controller. +config PL310_ERRATA_588369 + bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines" + depends on CACHE_L2X0 + help + The PL310 L2 cache controller implements three types of Clean & + Invalidate maintenance operations: by Physical Address + (offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC). + They are architecturally defined to behave as the execution of a + clean operation followed immediately by an invalidate operation, + both performing to the same memory location. This functionality + is not correctly implemented in PL310 as clean lines are not + invalidated as a result of these operations. + +config PL310_ERRATA_727915 + bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption" + depends on CACHE_L2X0 + help + PL310 implements the Clean & Invalidate by Way L2 cache maintenance + operation (offset 0x7FC). This operation runs in background so that + PL310 can handle normal accesses while it is in progress. Under very + rare circumstances, due to this erratum, write data can be lost when + PL310 treats a cacheable write transaction during a Clean & + Invalidate by Way operation. + +config PL310_ERRATA_753970 + bool "PL310 errata: cache sync operation may be faulty" + depends on CACHE_PL310 + help + This option enables the workaround for the 753970 PL310 (r3p0) erratum. + + Under some condition the effect of cache sync operation on + the store buffer still remains when the operation completes. + This means that the store buffer is always asked to drain and + this prevents it from merging any further writes. The workaround + is to replace the normal offset of cache sync operation (0x730) + by another offset targeting an unmapped PL310 register 0x740. + This has the same effect as the cache sync operation: store buffer + drain and waiting for all buffers empty. + +config PL310_ERRATA_769419 + bool "PL310 errata: no automatic Store Buffer drain" + depends on CACHE_L2X0 + help + On revisions of the PL310 prior to r3p2, the Store Buffer does + not automatically drain. This can cause normal, non-cacheable + writes to be retained when the memory system is idle, leading + to suboptimal I/O performance for drivers using coherent DMA. + This option adds a write barrier to the cpu_idle loop so that, + on systems with an outer cache, the store buffer is drained + explicitly. + config CACHE_TAUROS2 bool "Enable the Tauros2 L2 cache controller" depends on (ARCH_DOVE || ARCH_MMP || CPU_PJ4) -- cgit v1.2.3 From 8abd259f657d5742f96ffd46ed65feb11c44b1fb Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 17:38:08 +0000 Subject: ARM: l2c: provide generic hook to intercept writes to secure registers When Linux is running in the non-secure world, any write to a secure L2C register will generate an abort. Platforms normally have to call firmware to work around this. Provide a hook for them to intercept any L2C secure register write. l2c_write_sec() avoids writes to secure registers which are already set to the appropriate value, thus avoiding the overhead of needlessly calling into the secure monitor. Signed-off-by: Russell King --- arch/arm/include/asm/outercache.h | 5 ++++- arch/arm/mm/cache-l2x0.c | 42 ++++++++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 13 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index e96f194bf3d4..864afe2114d3 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h @@ -32,8 +32,11 @@ struct outer_cache_fns { #ifdef CONFIG_OUTER_CACHE_SYNC void (*sync)(void); #endif - void (*set_debug)(unsigned long); void (*resume)(void); + + /* This is an ARM L2C thing */ + void (*set_debug)(unsigned long); + void (*write_sec)(unsigned long, unsigned); }; extern struct outer_cache_fns outer_cache; diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index b4d373ab1a5c..369a9d01d94f 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -59,6 +59,20 @@ static inline void l2c_wait_mask(void __iomem *reg, unsigned long mask) cpu_relax(); } +/* + * By default, we write directly to secure registers. Platforms must + * override this if they are running non-secure. + */ +static void l2c_write_sec(unsigned long val, void __iomem *base, unsigned reg) +{ + if (val == readl_relaxed(base + reg)) + return; + if (outer_cache.write_sec) + outer_cache.write_sec(val, reg); + else + writel_relaxed(val, base + reg); +} + /* * This should only be called when we have a requirement that the * register be written due to a work-around, as platforms running @@ -66,7 +80,10 @@ static inline void l2c_wait_mask(void __iomem *reg, unsigned long mask) */ static inline void l2c_set_debug(void __iomem *base, unsigned long val) { - outer_cache.set_debug(val); + if (outer_cache.set_debug) + outer_cache.set_debug(val); + else + l2c_write_sec(val, base, L2X0_DEBUG_CTRL); } static void __l2c_op_way(void __iomem *reg) @@ -95,9 +112,7 @@ static void l2c_enable(void __iomem *base, u32 aux, unsigned num_lock) { unsigned long flags; - /* Only write the aux register if it needs changing */ - if (readl_relaxed(base + L2X0_AUX_CTRL) != aux) - writel_relaxed(aux, base + L2X0_AUX_CTRL); + l2c_write_sec(aux, base, L2X0_AUX_CTRL); l2c_unlock(base, num_lock); @@ -107,7 +122,7 @@ static void l2c_enable(void __iomem *base, u32 aux, unsigned num_lock) l2c_wait_mask(base + sync_reg_offset, 1); local_irq_restore(flags); - writel_relaxed(L2X0_CTRL_EN, base + L2X0_CTRL); + l2c_write_sec(L2X0_CTRL_EN, base, L2X0_CTRL); } static void l2c_disable(void) @@ -115,7 +130,7 @@ static void l2c_disable(void) void __iomem *base = l2x0_base; outer_cache.flush_all(); - writel_relaxed(0, base + L2X0_CTRL); + l2c_write_sec(0, base, L2X0_CTRL); dsb(st); } @@ -139,7 +154,7 @@ static inline void cache_sync(void) #if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915) static inline void debug_writel(unsigned long val) { - if (outer_cache.set_debug) + if (outer_cache.set_debug || outer_cache.write_sec) l2c_set_debug(l2x0_base, val); } #else @@ -182,7 +197,7 @@ static void l2x0_disable(void) raw_spin_lock_irqsave(&l2x0_lock, flags); __l2x0_flush_all(); - writel_relaxed(0, l2x0_base + L2X0_CTRL); + l2c_write_sec(0, l2x0_base, L2X0_CTRL); dsb(st); raw_spin_unlock_irqrestore(&l2x0_lock, flags); } @@ -599,11 +614,11 @@ static void l2c310_resume(void) L2X0_CACHE_ID_RTL_MASK; if (revision >= L310_CACHE_ID_RTL_R2P0) - writel_relaxed(l2x0_saved_regs.prefetch_ctrl, - base + L2X0_PREFETCH_CTRL); + l2c_write_sec(l2x0_saved_regs.prefetch_ctrl, base, + L2X0_PREFETCH_CTRL); if (revision >= L310_CACHE_ID_RTL_R3P0) - writel_relaxed(l2x0_saved_regs.pwr_ctrl, - base + L2X0_POWER_CTRL); + l2c_write_sec(l2x0_saved_regs.pwr_ctrl, base, + L2X0_POWER_CTRL); l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8); } @@ -732,8 +747,11 @@ static void __init __l2c_init(const struct l2c_init_data *data, l2x0_size = ways * (data->way_size_0 << way_size_bits); fns = data->outer_cache; + fns.write_sec = outer_cache.write_sec; if (data->fixup) data->fixup(l2x0_base, cache_id, &fns); + if (fns.write_sec) + fns.set_debug = NULL; /* * Check if l2x0 controller is already enabled. If we are booting -- cgit v1.2.3 From a8875a092af5d9f88f6c335dd07d8988e80e1343 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 20:02:06 +0000 Subject: ARM: l2c: implement L2C-310 erratum 752271 in core L2C code Rather than having SoCs work around L2C erratum themselves, move them into core code. This erratum affects the double linefill feature which needs to be disabled for r3p0 to r3p1-50rel0. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 369a9d01d94f..84933f48edea 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -480,6 +480,11 @@ static const struct l2c_init_data l2c220_data = { * hit the line between the clean operation and invalidate operation, * resulting in the store being lost. * + * 752271: PL310 R3P0->R3P1-50REL0, fixed R3P2. + * Affects: 8x64-bit (double fill) line fetches + * double fill line fetches can fail to cause dirty data to be evicted + * from the cache before the new data overwrites the second line. + * * 753970: PL310 R3P0, fixed R3P1. * Affects: sync * prevents merging writes after the sync operation, until another L2C @@ -628,7 +633,7 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, struct outer_cache_fns *fns) { unsigned revision = cache_id & L2X0_CACHE_ID_RTL_MASK; - const char *errata[4]; + const char *errata[8]; unsigned n = 0; /* For compatibility */ @@ -651,6 +656,17 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, errata[n++] = "727915"; } + if (revision >= L310_CACHE_ID_RTL_R3P0 && + revision < L310_CACHE_ID_RTL_R3P2) { + u32 val = readl_relaxed(base + L2X0_PREFETCH_CTRL); + /* I don't think bit23 is required here... but iMX6 does so */ + if (val & (BIT(30) | BIT(23))) { + val &= ~(BIT(30) | BIT(23)); + l2c_write_sec(val, base, L2X0_PREFETCH_CTRL); + errata[n++] = "752271"; + } + } + if (IS_ENABLED(CONFIG_PL310_ERRATA_753970) && revision == L310_CACHE_ID_RTL_R3P0) { sync_reg_offset = L2X0_DUMMY_REG; -- cgit v1.2.3 From 1a5a954ce0dd8ba1fc8b5305bcdb6e4cf7d6939b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 20:52:25 +0000 Subject: ARM: l2c: fix register naming We have a mixture of different devices with different register layouts, but we group all the bits together in an opaque mess. Split them out into those which are L2C-310 specific and ones which refer to earlier devices. Provide full auxiliary control register definitions. Acked-by: Tony Lindgren Acked-by: Linus Walleij Acked-by: Shawn Guo Acked-by: Stephen Warren Signed-off-by: Russell King --- arch/arm/include/asm/hardware/cache-l2x0.h | 73 ++++++++++++++++++++---------- arch/arm/mach-cns3xxx/core.c | 8 ++-- arch/arm/mach-exynos/sleep.S | 8 ++-- arch/arm/mach-imx/system.c | 8 ++-- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 2 +- arch/arm/mach-omap2/omap4-common.c | 18 ++++---- arch/arm/mach-prima2/l2x0.c | 5 +- arch/arm/mach-realview/realview_pbx.c | 4 +- arch/arm/mach-spear/spear13xx.c | 6 +-- arch/arm/mach-sti/board-dt.c | 8 ++-- arch/arm/mach-tegra/sleep.h | 8 ++-- arch/arm/mach-ux500/cache-l2x0.c | 4 +- arch/arm/mach-vexpress/ct-ca9x4.c | 4 +- arch/arm/mm/cache-l2x0.c | 57 +++++++++++------------ 14 files changed, 118 insertions(+), 95 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h index 3af45734b514..b3ee122c6f24 100644 --- a/arch/arm/include/asm/hardware/cache-l2x0.h +++ b/arch/arm/include/asm/hardware/cache-l2x0.h @@ -26,8 +26,8 @@ #define L2X0_CACHE_TYPE 0x004 #define L2X0_CTRL 0x100 #define L2X0_AUX_CTRL 0x104 -#define L2X0_TAG_LATENCY_CTRL 0x108 -#define L2X0_DATA_LATENCY_CTRL 0x10C +#define L310_TAG_LATENCY_CTRL 0x108 +#define L310_DATA_LATENCY_CTRL 0x10C #define L2X0_EVENT_CNT_CTRL 0x200 #define L2X0_EVENT_CNT1_CFG 0x204 #define L2X0_EVENT_CNT0_CFG 0x208 @@ -54,16 +54,16 @@ #define L2X0_LOCKDOWN_WAY_D_BASE 0x900 #define L2X0_LOCKDOWN_WAY_I_BASE 0x904 #define L2X0_LOCKDOWN_STRIDE 0x08 -#define L2X0_ADDR_FILTER_START 0xC00 -#define L2X0_ADDR_FILTER_END 0xC04 +#define L310_ADDR_FILTER_START 0xC00 +#define L310_ADDR_FILTER_END 0xC04 #define L2X0_TEST_OPERATION 0xF00 #define L2X0_LINE_DATA 0xF10 #define L2X0_LINE_TAG 0xF30 #define L2X0_DEBUG_CTRL 0xF40 -#define L2X0_PREFETCH_CTRL 0xF60 -#define L2X0_POWER_CTRL 0xF80 -#define L2X0_DYNAMIC_CLK_GATING_EN (1 << 1) -#define L2X0_STNDBY_MODE_EN (1 << 0) +#define L310_PREFETCH_CTRL 0xF60 +#define L310_POWER_CTRL 0xF80 +#define L310_DYNAMIC_CLK_GATING_EN (1 << 1) +#define L310_STNDBY_MODE_EN (1 << 0) /* Registers shifts and masks */ #define L2X0_CACHE_ID_PART_MASK (0xf << 6) @@ -88,29 +88,52 @@ #define L310_CACHE_ID_RTL_R3P3 0x09 #define L2X0_AUX_CTRL_MASK 0xc0000fff +/* L2C auxiliary control register - bits common to L2C-210/220/310 */ +#define L2C_AUX_CTRL_WAY_SIZE_SHIFT 17 +#define L2C_AUX_CTRL_WAY_SIZE_MASK (7 << 17) +#define L2C_AUX_CTRL_WAY_SIZE(n) ((n) << 17) +#define L2C_AUX_CTRL_EVTMON_ENABLE BIT(20) +#define L2C_AUX_CTRL_PARITY_ENABLE BIT(21) +#define L2C_AUX_CTRL_SHARED_OVERRIDE BIT(22) +/* L2C-210/220 common bits */ #define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT 0 -#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK 0x7 +#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK (7 << 0) #define L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT 3 -#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK (0x7 << 3) +#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK (7 << 3) #define L2X0_AUX_CTRL_TAG_LATENCY_SHIFT 6 -#define L2X0_AUX_CTRL_TAG_LATENCY_MASK (0x7 << 6) +#define L2X0_AUX_CTRL_TAG_LATENCY_MASK (7 << 6) #define L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT 9 -#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK (0x7 << 9) -#define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT 16 -#define L2X0_AUX_CTRL_WAY_SIZE_SHIFT 17 -#define L2X0_AUX_CTRL_WAY_SIZE_MASK (0x7 << 17) -#define L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT 22 -#define L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT 26 -#define L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT 27 -#define L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT 28 -#define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29 -#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30 +#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK (7 << 9) +#define L2X0_AUX_CTRL_ASSOC_SHIFT 13 +#define L2X0_AUX_CTRL_ASSOC_MASK (15 << 13) +/* L2C-210 specific bits */ +#define L210_AUX_CTRL_WRAP_DISABLE BIT(12) +#define L210_AUX_CTRL_WA_OVERRIDE BIT(23) +#define L210_AUX_CTRL_EXCLUSIVE_ABORT BIT(24) +/* L2C-220 specific bits */ +#define L220_AUX_CTRL_EXCLUSIVE_CACHE BIT(12) +#define L220_AUX_CTRL_FWA_SHIFT 23 +#define L220_AUX_CTRL_FWA_MASK (3 << 23) +#define L220_AUX_CTRL_NS_LOCKDOWN BIT(26) +#define L220_AUX_CTRL_NS_INT_CTRL BIT(27) +/* L2C-310 specific bits */ +#define L310_AUX_CTRL_FULL_LINE_ZERO BIT(0) /* R2P0+ */ +#define L310_AUX_CTRL_HIGHPRIO_SO_DEV BIT(10) /* R2P0+ */ +#define L310_AUX_CTRL_STORE_LIMITATION BIT(11) /* R2P0+ */ +#define L310_AUX_CTRL_EXCLUSIVE_CACHE BIT(12) +#define L310_AUX_CTRL_ASSOCIATIVITY_16 BIT(16) +#define L310_AUX_CTRL_CACHE_REPLACE_RR BIT(25) /* R2P0+ */ +#define L310_AUX_CTRL_NS_LOCKDOWN BIT(26) +#define L310_AUX_CTRL_NS_INT_CTRL BIT(27) +#define L310_AUX_CTRL_DATA_PREFETCH BIT(28) +#define L310_AUX_CTRL_INSTR_PREFETCH BIT(29) +#define L310_AUX_CTRL_EARLY_BRESP BIT(30) /* R2P0+ */ -#define L2X0_LATENCY_CTRL_SETUP_SHIFT 0 -#define L2X0_LATENCY_CTRL_RD_SHIFT 4 -#define L2X0_LATENCY_CTRL_WR_SHIFT 8 +#define L310_LATENCY_CTRL_SETUP(n) ((n) << 0) +#define L310_LATENCY_CTRL_RD(n) ((n) << 4) +#define L310_LATENCY_CTRL_WR(n) ((n) << 8) -#define L2X0_ADDR_FILTER_EN 1 +#define L310_ADDR_FILTER_EN 1 #define L2X0_CTRL_EN 1 diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c index 2ae28a69e3e5..5c31b2638c01 100644 --- a/arch/arm/mach-cns3xxx/core.c +++ b/arch/arm/mach-cns3xxx/core.c @@ -272,9 +272,9 @@ void __init cns3xxx_l2x0_init(void) * * 1 cycle of latency for setup, read and write accesses */ - val = readl(base + L2X0_TAG_LATENCY_CTRL); + val = readl(base + L310_TAG_LATENCY_CTRL); val &= 0xfffff888; - writel(val, base + L2X0_TAG_LATENCY_CTRL); + writel(val, base + L310_TAG_LATENCY_CTRL); /* * Data RAM Control register @@ -285,9 +285,9 @@ void __init cns3xxx_l2x0_init(void) * * 1 cycle of latency for setup, read and write accesses */ - val = readl(base + L2X0_DATA_LATENCY_CTRL); + val = readl(base + L310_DATA_LATENCY_CTRL); val &= 0xfffff888; - writel(val, base + L2X0_DATA_LATENCY_CTRL); + writel(val, base + L310_DATA_LATENCY_CTRL); /* 32 KiB, 8-way, parity disable */ l2x0_init(base, 0x00540000, 0xfe000fff); diff --git a/arch/arm/mach-exynos/sleep.S b/arch/arm/mach-exynos/sleep.S index a2613e944e10..7e0af530511e 100644 --- a/arch/arm/mach-exynos/sleep.S +++ b/arch/arm/mach-exynos/sleep.S @@ -65,13 +65,13 @@ ENTRY(exynos_cpu_resume) ldr r2, [r0, #L2X0_R_AUX_CTRL] str r2, [r1, #L2X0_AUX_CTRL] ldr r2, [r0, #L2X0_R_TAG_LATENCY] - str r2, [r1, #L2X0_TAG_LATENCY_CTRL] + str r2, [r1, #L310_TAG_LATENCY_CTRL] ldr r2, [r0, #L2X0_R_DATA_LATENCY] - str r2, [r1, #L2X0_DATA_LATENCY_CTRL] + str r2, [r1, #L310_DATA_LATENCY_CTRL] ldr r2, [r0, #L2X0_R_PREFETCH_CTRL] - str r2, [r1, #L2X0_PREFETCH_CTRL] + str r2, [r1, #L310_PREFETCH_CTRL] ldr r2, [r0, #L2X0_R_PWR_CTRL] - str r2, [r1, #L2X0_POWER_CTRL] + str r2, [r1, #L310_POWER_CTRL] mov r2, #1 str r2, [r1, #L2X0_CTRL] skip_l2_resume: diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c index c6571f1de9fd..59013a81107b 100644 --- a/arch/arm/mach-imx/system.c +++ b/arch/arm/mach-imx/system.c @@ -124,7 +124,7 @@ void __init imx_init_l2cache(void) } /* Configure the L2 PREFETCH and POWER registers */ - val = readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL); + val = readl_relaxed(l2x0_base + L310_PREFETCH_CTRL); val |= 0x70800000; /* * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0 @@ -137,9 +137,9 @@ void __init imx_init_l2cache(void) */ if (cpu_is_imx6q()) val &= ~(1 << 30 | 1 << 23); - writel_relaxed(val, l2x0_base + L2X0_PREFETCH_CTRL); - val = L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN; - writel_relaxed(val, l2x0_base + L2X0_POWER_CTRL); + writel_relaxed(val, l2x0_base + L310_PREFETCH_CTRL); + val = L310_DYNAMIC_CLK_GATING_EN | L310_STNDBY_MODE_EN; + writel_relaxed(val, l2x0_base + L310_POWER_CTRL); iounmap(l2x0_base); of_node_put(np); diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 667915d236f3..ba43f49fbb59 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -194,7 +194,7 @@ static void save_l2x0_context(void) if (l2x0_base) { val = __raw_readl(l2x0_base + L2X0_AUX_CTRL); __raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET); - val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL); + val = __raw_readl(l2x0_base + L310_PREFETCH_CTRL); __raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET); } } diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 48cf74d284ec..1dfb806da33e 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -197,15 +197,15 @@ static int __init omap_l2_cache_init(void) return -ENOMEM; /* 16-way associativity, parity disabled, way size - 64KB (es2.0 +) */ - aux_ctrl = (1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT) | - (0x1 << 25) | - (0x1 << L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT) | - (0x1 << L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT)) | - (0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | - (1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) | - (1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) | - (1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) | - (1 << L2X0_AUX_CTRL_EARLY_BRESP_SHIFT); + aux_ctrl = L310_AUX_CTRL_ASSOCIATIVITY_16 | + L310_AUX_CTRL_CACHE_REPLACE_RR | + L310_AUX_CTRL_NS_LOCKDOWN | + L310_AUX_CTRL_NS_INT_CTRL | + L2C_AUX_CTRL_WAY_SIZE(3) | + L2C_AUX_CTRL_SHARED_OVERRIDE | + L310_AUX_CTRL_DATA_PREFETCH | + L310_AUX_CTRL_INSTR_PREFETCH | + L310_AUX_CTRL_EARLY_BRESP; omap_smc1(0x109, aux_ctrl); diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c index c7102539c0b0..2db82742fb74 100644 --- a/arch/arm/mach-prima2/l2x0.c +++ b/arch/arm/mach-prima2/l2x0.c @@ -17,13 +17,12 @@ struct l2x0_aux { }; static const struct l2x0_aux prima2_l2x0_aux __initconst = { - .val = 2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT, + .val = L2C_AUX_CTRL_WAY_SIZE(2), .mask = 0, }; static const struct l2x0_aux marco_l2x0_aux __initconst = { - .val = (2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | - (1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT), + .val = L2C_AUX_CTRL_WAY_SIZE(2) | L310_AUX_CTRL_ASSOCIATIVITY_16, .mask = L2X0_AUX_CTRL_MASK, }; diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index 9d75493e3f0c..f0cfd7e7e569 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -370,8 +370,8 @@ static void __init realview_pbx_init(void) __io_address(REALVIEW_PBX_TILE_L220_BASE); /* set RAM latencies to 1 cycle for eASIC */ - writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL); - writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL); + writel(0, l2x0_base + L310_TAG_LATENCY_CTRL); + writel(0, l2x0_base + L310_DATA_LATENCY_CTRL); /* 16KB way size, 8-way associativity, parity disabled * Bits: .. 0 0 0 0 1 00 1 0 1 001 0 000 0 .... .... .... */ diff --git a/arch/arm/mach-spear/spear13xx.c b/arch/arm/mach-spear/spear13xx.c index 7aa6e8cf830f..92860fa01668 100644 --- a/arch/arm/mach-spear/spear13xx.c +++ b/arch/arm/mach-spear/spear13xx.c @@ -38,14 +38,14 @@ void __init spear13xx_l2x0_init(void) if (!IS_ENABLED(CONFIG_CACHE_L2X0)) return; - writel_relaxed(0x06, VA_L2CC_BASE + L2X0_PREFETCH_CTRL); + writel_relaxed(0x06, VA_L2CC_BASE + L310_PREFETCH_CTRL); /* * Program following latencies in order to make * SPEAr1340 work at 600 MHz */ - writel_relaxed(0x221, VA_L2CC_BASE + L2X0_TAG_LATENCY_CTRL); - writel_relaxed(0x441, VA_L2CC_BASE + L2X0_DATA_LATENCY_CTRL); + writel_relaxed(0x221, VA_L2CC_BASE + L310_TAG_LATENCY_CTRL); + writel_relaxed(0x441, VA_L2CC_BASE + L310_DATA_LATENCY_CTRL); l2x0_init(VA_L2CC_BASE, 0x70A60001, 0xfe00ffff); } diff --git a/arch/arm/mach-sti/board-dt.c b/arch/arm/mach-sti/board-dt.c index 1217fb598cfd..dc8669efc12d 100644 --- a/arch/arm/mach-sti/board-dt.c +++ b/arch/arm/mach-sti/board-dt.c @@ -19,10 +19,10 @@ void __init stih41x_l2x0_init(void) u32 way_size = 0x4; u32 aux_ctrl; /* may be this can be encoded in macros like BIT*() */ - aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) | - (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) | - (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) | - (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); + aux_ctrl = L2C_AUX_CTRL_SHARED_OVERRIDE | + L310_AUX_CTRL_DATA_PREFETCH | + L310_AUX_CTRL_INSTR_PREFETCH | + L2C_AUX_CTRL_WAY_SIZE(way_size); l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK); } diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h index a4edbb3abd3d..a032820d2fac 100644 --- a/arch/arm/mach-tegra/sleep.h +++ b/arch/arm/mach-tegra/sleep.h @@ -134,13 +134,13 @@ tst \tmp3, #L2X0_CTRL_EN bne exit_l2_resume ldr \tmp3, [\tmp1, #L2X0_R_TAG_LATENCY] - str \tmp3, [\tmp2, #L2X0_TAG_LATENCY_CTRL] + str \tmp3, [\tmp2, #L310_TAG_LATENCY_CTRL] ldr \tmp3, [\tmp1, #L2X0_R_DATA_LATENCY] - str \tmp3, [\tmp2, #L2X0_DATA_LATENCY_CTRL] + str \tmp3, [\tmp2, #L310_DATA_LATENCY_CTRL] ldr \tmp3, [\tmp1, #L2X0_R_PREFETCH_CTRL] - str \tmp3, [\tmp2, #L2X0_PREFETCH_CTRL] + str \tmp3, [\tmp2, #L310_PREFETCH_CTRL] ldr \tmp3, [\tmp1, #L2X0_R_PWR_CTRL] - str \tmp3, [\tmp2, #L2X0_POWER_CTRL] + str \tmp3, [\tmp2, #L310_POWER_CTRL] ldr \tmp3, [\tmp1, #L2X0_R_AUX_CTRL] str \tmp3, [\tmp2, #L2X0_AUX_CTRL] mov \tmp3, #L2X0_CTRL_EN diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c index 264f894c0e3d..132cd2b465e7 100644 --- a/arch/arm/mach-ux500/cache-l2x0.c +++ b/arch/arm/mach-ux500/cache-l2x0.c @@ -51,10 +51,10 @@ static int __init ux500_l2x0_init(void) /* DBx540's L2 has 128KB way size */ if (cpu_is_ux540_family()) /* 128KB way size */ - aux_val |= (0x4 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); + aux_val |= L2C_AUX_CTRL_WAY_SIZE(4); else /* 64KB way size */ - aux_val |= (0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); + aux_val |= L2C_AUX_CTRL_WAY_SIZE(3); /* 64KB way size, 8 way associativity, force WA */ if (of_have_populated_dt()) diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 6f34497a4245..6c4ffb6c5ad8 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -145,8 +145,8 @@ static void __init ct_ca9x4_init(void) void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K); /* set RAM latencies to 1 cycle for this core tile. */ - writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL); - writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL); + writel(0, l2x0_base + L310_TAG_LATENCY_CTRL); + writel(0, l2x0_base + L310_DATA_LATENCY_CTRL); l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff); #endif diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 84933f48edea..c5c8a4152825 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -576,13 +576,13 @@ static void __init l2c310_save(void __iomem *base) unsigned revision; l2x0_saved_regs.tag_latency = readl_relaxed(base + - L2X0_TAG_LATENCY_CTRL); + L310_TAG_LATENCY_CTRL); l2x0_saved_regs.data_latency = readl_relaxed(base + - L2X0_DATA_LATENCY_CTRL); + L310_DATA_LATENCY_CTRL); l2x0_saved_regs.filter_end = readl_relaxed(base + - L2X0_ADDR_FILTER_END); + L310_ADDR_FILTER_END); l2x0_saved_regs.filter_start = readl_relaxed(base + - L2X0_ADDR_FILTER_START); + L310_ADDR_FILTER_START); revision = readl_relaxed(base + L2X0_CACHE_ID) & L2X0_CACHE_ID_RTL_MASK; @@ -590,12 +590,12 @@ static void __init l2c310_save(void __iomem *base) /* From r2p0, there is Prefetch offset/control register */ if (revision >= L310_CACHE_ID_RTL_R2P0) l2x0_saved_regs.prefetch_ctrl = readl_relaxed(base + - L2X0_PREFETCH_CTRL); + L310_PREFETCH_CTRL); /* From r3p0, there is Power control register */ if (revision >= L310_CACHE_ID_RTL_R3P0) l2x0_saved_regs.pwr_ctrl = readl_relaxed(base + - L2X0_POWER_CTRL); + L310_POWER_CTRL); } static void l2c310_resume(void) @@ -607,23 +607,23 @@ static void l2c310_resume(void) /* restore pl310 setup */ writel_relaxed(l2x0_saved_regs.tag_latency, - base + L2X0_TAG_LATENCY_CTRL); + base + L310_TAG_LATENCY_CTRL); writel_relaxed(l2x0_saved_regs.data_latency, - base + L2X0_DATA_LATENCY_CTRL); + base + L310_DATA_LATENCY_CTRL); writel_relaxed(l2x0_saved_regs.filter_end, - base + L2X0_ADDR_FILTER_END); + base + L310_ADDR_FILTER_END); writel_relaxed(l2x0_saved_regs.filter_start, - base + L2X0_ADDR_FILTER_START); + base + L310_ADDR_FILTER_START); revision = readl_relaxed(base + L2X0_CACHE_ID) & L2X0_CACHE_ID_RTL_MASK; if (revision >= L310_CACHE_ID_RTL_R2P0) l2c_write_sec(l2x0_saved_regs.prefetch_ctrl, base, - L2X0_PREFETCH_CTRL); + L310_PREFETCH_CTRL); if (revision >= L310_CACHE_ID_RTL_R3P0) l2c_write_sec(l2x0_saved_regs.pwr_ctrl, base, - L2X0_POWER_CTRL); + L310_POWER_CTRL); l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8); } @@ -658,11 +658,11 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, if (revision >= L310_CACHE_ID_RTL_R3P0 && revision < L310_CACHE_ID_RTL_R3P2) { - u32 val = readl_relaxed(base + L2X0_PREFETCH_CTRL); + u32 val = readl_relaxed(base + L310_PREFETCH_CTRL); /* I don't think bit23 is required here... but iMX6 does so */ if (val & (BIT(30) | BIT(23))) { val &= ~(BIT(30) | BIT(23)); - l2c_write_sec(val, base, L2X0_PREFETCH_CTRL); + l2c_write_sec(val, base, L310_PREFETCH_CTRL); errata[n++] = "752271"; } } @@ -759,7 +759,8 @@ static void __init __l2c_init(const struct l2c_init_data *data, * * L2 cache size = number of ways * way size. */ - way_size_bits = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17; + way_size_bits = (aux & L2C_AUX_CTRL_WAY_SIZE_MASK) >> + L2C_AUX_CTRL_WAY_SIZE_SHIFT; l2x0_size = ways * (data->way_size_0 << way_size_bits); fns = data->outer_cache; @@ -902,27 +903,27 @@ static void __init l2c310_of_parse(const struct device_node *np, of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag)); if (tag[0] && tag[1] && tag[2]) writel_relaxed( - ((tag[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) | - ((tag[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) | - ((tag[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT), - l2x0_base + L2X0_TAG_LATENCY_CTRL); + L310_LATENCY_CTRL_RD(tag[0] - 1) | + L310_LATENCY_CTRL_WR(tag[1] - 1) | + L310_LATENCY_CTRL_SETUP(tag[2] - 1), + l2x0_base + L310_TAG_LATENCY_CTRL); of_property_read_u32_array(np, "arm,data-latency", data, ARRAY_SIZE(data)); if (data[0] && data[1] && data[2]) writel_relaxed( - ((data[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) | - ((data[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) | - ((data[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT), - l2x0_base + L2X0_DATA_LATENCY_CTRL); + L310_LATENCY_CTRL_RD(data[0] - 1) | + L310_LATENCY_CTRL_WR(data[1] - 1) | + L310_LATENCY_CTRL_SETUP(data[2] - 1), + l2x0_base + L310_DATA_LATENCY_CTRL); of_property_read_u32_array(np, "arm,filter-ranges", filter, ARRAY_SIZE(filter)); if (filter[1]) { writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M), - l2x0_base + L2X0_ADDR_FILTER_END); - writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN, - l2x0_base + L2X0_ADDR_FILTER_START); + l2x0_base + L310_ADDR_FILTER_END); + writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L310_ADDR_FILTER_EN, + l2x0_base + L310_ADDR_FILTER_START); } } @@ -1298,7 +1299,7 @@ static void __init tauros3_save(void __iomem *base) l2x0_saved_regs.aux2_ctrl = readl_relaxed(base + TAUROS3_AUX2_CTRL); l2x0_saved_regs.prefetch_ctrl = - readl_relaxed(base + L2X0_PREFETCH_CTRL); + readl_relaxed(base + L310_PREFETCH_CTRL); } static void tauros3_resume(void) @@ -1309,7 +1310,7 @@ static void tauros3_resume(void) writel_relaxed(l2x0_saved_regs.aux2_ctrl, base + TAUROS3_AUX2_CTRL); writel_relaxed(l2x0_saved_regs.prefetch_ctrl, - base + L2X0_PREFETCH_CTRL); + base + L310_PREFETCH_CTRL); l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8); } -- cgit v1.2.3 From d9d1f3e2d71144348d73210cf9f1fe0b32481c79 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 17 Mar 2014 12:59:08 +0000 Subject: ARM: l2c: check that DT files specify the required "cache-unified" property This is a required property, and should always be specified. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index c5c8a4152825..790343b2c13b 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1364,6 +1364,10 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) data = of_match_node(l2x0_ids, np)->data; + /* All L2 caches are unified, so this property should be specified */ + if (!of_property_read_bool(np, "cache-unified")) + pr_err("L2C: device tree omits to specify unified cache\n"); + /* L2 configuration can only be changed if the cache is disabled */ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) if (data->of_parse) -- cgit v1.2.3 From ddf7d79bc739c44f7e7cdffc9eb5d94aa213f53e Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 28 Mar 2014 14:18:35 +0000 Subject: ARM: l2c: move L2 cache register saving to a more sensible location Move the L2 cache register saving to a more sensible location - after the cache has been enabled, and fixups have been run. We move the saving of the auxiliary control register into the ->save function as well which makes everything operate in a sane and maintainable way. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 790343b2c13b..3a34db56827b 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -202,6 +202,11 @@ static void l2x0_disable(void) raw_spin_unlock_irqrestore(&l2x0_lock, flags); } +static void l2c_save(void __iomem *base) +{ + l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); +} + /* * L2C-210 specific code. * @@ -295,6 +300,7 @@ static const struct l2c_init_data l2c210_data __initconst = { .way_size_0 = SZ_8K, .num_lock = 1, .enable = l2c_enable, + .save = l2c_save, .outer_cache = { .inv_range = l2c210_inv_range, .clean_range = l2c210_clean_range, @@ -439,6 +445,7 @@ static const struct l2c_init_data l2c220_data = { .way_size_0 = SZ_8K, .num_lock = 1, .enable = l2c_enable, + .save = l2c_save, .outer_cache = { .inv_range = l2c220_inv_range, .clean_range = l2c220_clean_range, @@ -575,6 +582,8 @@ static void __init l2c310_save(void __iomem *base) { unsigned revision; + l2c_save(base); + l2x0_saved_regs.tag_latency = readl_relaxed(base + L310_TAG_LATENCY_CTRL); l2x0_saved_regs.data_latency = readl_relaxed(base + @@ -712,13 +721,6 @@ static void __init __l2c_init(const struct l2c_init_data *data, unsigned way_size_bits, ways; u32 aux; - /* - * It is strange to save the register state before initialisation, - * but hey, this is what the DT implementations decided to do. - */ - if (data->save) - data->save(l2x0_base); - aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); aux &= aux_mask; @@ -777,13 +779,17 @@ static void __init __l2c_init(const struct l2c_init_data *data, if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) data->enable(l2x0_base, aux, data->num_lock); - /* Re-read it in case some bits are reserved. */ - aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); + outer_cache = fns; - /* Save the value for resuming. */ - l2x0_saved_regs.aux_ctrl = aux; + /* + * It is strange to save the register state before initialisation, + * but hey, this is what the DT implementations decided to do. + */ + if (data->save) + data->save(l2x0_base); - outer_cache = fns; + /* Re-read it in case some bits are reserved. */ + aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); pr_info("%s cache controller enabled, %d ways, %d kB\n", data->type, ways, l2x0_size >> 10); @@ -865,6 +871,7 @@ static const struct l2c_init_data of_l2c210_data __initconst = { .num_lock = 1, .of_parse = l2x0_of_parse, .enable = l2c_enable, + .save = l2c_save, .outer_cache = { .inv_range = l2c210_inv_range, .clean_range = l2c210_clean_range, @@ -882,6 +889,7 @@ static const struct l2c_init_data of_l2c220_data __initconst = { .num_lock = 1, .of_parse = l2x0_of_parse, .enable = l2c_enable, + .save = l2c_save, .outer_cache = { .inv_range = l2c220_inv_range, .clean_range = l2c220_clean_range, @@ -1296,6 +1304,8 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { static void __init tauros3_save(void __iomem *base) { + l2c_save(base); + l2x0_saved_regs.aux2_ctrl = readl_relaxed(base + TAUROS3_AUX2_CTRL); l2x0_saved_regs.prefetch_ctrl = -- cgit v1.2.3 From 4374d64933b1d0f0ebbad064289ef44b869d77c1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 15:39:09 +0000 Subject: ARM: l2c: add automatic enable of early BRESP The AXI bus protocol requires that a write response should only be sent back to the master when the last write has been accepted. Early BRESP allows the L2C-310 to send the write response as soon as the store buffer accepts the write address. Cortex-A9 processors can signal to the L2C-310 that they wish to be notified early, and if this optimisation is enabled, the L2C-310 can signal an early write response. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 3a34db56827b..7e53214f7c36 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -24,6 +24,7 @@ #include #include +#include #include #include "cache-tauros3.h" #include "cache-aurora-l2.h" @@ -638,6 +639,24 @@ static void l2c310_resume(void) } } +static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock) +{ + unsigned rev = readl_relaxed(base + L2X0_CACHE_ID) & L2X0_CACHE_ID_PART_MASK; + bool cortex_a9 = read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9; + + if (rev >= L310_CACHE_ID_RTL_R2P0) { + if (cortex_a9) { + aux |= L310_AUX_CTRL_EARLY_BRESP; + pr_info("L2C-310 enabling early BRESP for Cortex-A9\n"); + } else if (aux & L310_AUX_CTRL_EARLY_BRESP) { + pr_warn("L2C-310 early BRESP only supported with Cortex-A9\n"); + aux &= ~L310_AUX_CTRL_EARLY_BRESP; + } + } + + l2c_enable(base, aux, num_lock); +} + static void __init l2c310_fixup(void __iomem *base, u32 cache_id, struct outer_cache_fns *fns) { @@ -699,7 +718,7 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .type = "L2C-310", .way_size_0 = SZ_8K, .num_lock = 8, - .enable = l2c_enable, + .enable = l2c310_enable, .fixup = l2c310_fixup, .save = l2c310_save, .outer_cache = { @@ -940,7 +959,7 @@ static const struct l2c_init_data of_l2c310_data __initconst = { .way_size_0 = SZ_8K, .num_lock = 8, .of_parse = l2c310_of_parse, - .enable = l2c_enable, + .enable = l2c310_enable, .fixup = l2c310_fixup, .save = l2c310_save, .outer_cache = { @@ -1289,7 +1308,7 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .way_size_0 = SZ_8K, .num_lock = 8, .of_parse = l2c310_of_parse, - .enable = l2c_enable, + .enable = l2c310_enable, .save = l2c310_save, .outer_cache = { .inv_range = bcm_inv_range, -- cgit v1.2.3 From 3a43b581dac1e5e70169dd6267bef4503ec3da21 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 28 Mar 2014 14:22:04 +0000 Subject: ARM: l2c: always enable low power modes Always enable the L2C low power modes on L2C-310 R3P0 and newer parts. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 7e53214f7c36..6d8a0575a684 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -654,6 +654,18 @@ static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock) } } + /* r3p0 or later has power control register */ + if (rev >= L310_CACHE_ID_RTL_R3P0) { + u32 power_ctrl; + + l2c_write_sec(L310_DYNAMIC_CLK_GATING_EN | L310_STNDBY_MODE_EN, + base, L310_POWER_CTRL); + power_ctrl = readl_relaxed(base + L310_POWER_CTRL); + pr_info("L2C-310 dynamic clock gating %sabled, standby mode %sabled\n", + power_ctrl & L310_DYNAMIC_CLK_GATING_EN ? "en" : "dis", + power_ctrl & L310_STNDBY_MODE_EN ? "en" : "dis"); + } + l2c_enable(base, aux, num_lock); } -- cgit v1.2.3 From a4b041a0e25c6e9ccd809b3cb68a98c816e0c967 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 11 Apr 2014 00:48:25 +0100 Subject: ARM: l2c: always enable non-secure access to lockdown registers Since we always write to these during the cache initialisation, it is a good idea to always have the non-secure access bit set. Set it in core code. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 6d8a0575a684..c4f3e8dc64ff 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -441,11 +441,23 @@ static void l2c220_sync(void) raw_spin_unlock_irqrestore(&l2x0_lock, flags); } +static void l2c220_enable(void __iomem *base, u32 aux, unsigned num_lock) +{ + /* + * Always enable non-secure access to the lockdown registers - + * we write to them as part of the L2C enable sequence so they + * need to be accessible. + */ + aux |= L220_AUX_CTRL_NS_LOCKDOWN; + + l2c_enable(base, aux, num_lock); +} + static const struct l2c_init_data l2c220_data = { .type = "L2C-220", .way_size_0 = SZ_8K, .num_lock = 1, - .enable = l2c_enable, + .enable = l2c220_enable, .save = l2c_save, .outer_cache = { .inv_range = l2c220_inv_range, @@ -666,6 +678,13 @@ static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock) power_ctrl & L310_STNDBY_MODE_EN ? "en" : "dis"); } + /* + * Always enable non-secure access to the lockdown registers - + * we write to them as part of the L2C enable sequence so they + * need to be accessible. + */ + aux |= L310_AUX_CTRL_NS_LOCKDOWN; + l2c_enable(base, aux, num_lock); } @@ -919,7 +938,7 @@ static const struct l2c_init_data of_l2c220_data __initconst = { .way_size_0 = SZ_8K, .num_lock = 1, .of_parse = l2x0_of_parse, - .enable = l2c_enable, + .enable = l2c220_enable, .save = l2c_save, .outer_cache = { .inv_range = l2c220_inv_range, -- cgit v1.2.3 From de7e75326c05c10ebd96aed9440c870f0ff1e34f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Apr 2014 11:39:57 +0100 Subject: ARM: l2c: provide common PL310 early resume code Provide a common assembly implementation for PL310 resume code. Certain platforms need to re-initialise the L2C cache early as it may preserve data across a S2RAM cycle, and therefore must be enabled along with the L1 cache and MMU. Signed-off-by: Russell King --- arch/arm/mm/Makefile | 2 +- arch/arm/mm/l2c-l2x0-resume.S | 58 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mm/l2c-l2x0-resume.S (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index de5a6a27081b..91da64de440f 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -97,6 +97,6 @@ AFLAGS_proc-v7.o :=-Wa,-march=armv7-a obj-$(CONFIG_OUTER_CACHE) += l2c-common.o obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o -obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o +obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o l2c-l2x0-resume.o obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o obj-$(CONFIG_CACHE_TAUROS2) += cache-tauros2.o diff --git a/arch/arm/mm/l2c-l2x0-resume.S b/arch/arm/mm/l2c-l2x0-resume.S new file mode 100644 index 000000000000..99b05f21a59a --- /dev/null +++ b/arch/arm/mm/l2c-l2x0-resume.S @@ -0,0 +1,58 @@ +/* + * L2C-310 early resume code. This can be used by platforms to restore + * the settings of their L2 cache controller before restoring the + * processor state. + * + * This code can only be used to if you are running in the secure world. + */ +#include +#include + + .text + +ENTRY(l2c310_early_resume) + adr r0, 1f + ldr r2, [r0] + add r0, r2, r0 + + ldmia r0, {r1, r2, r3, r4, r5, r6, r7, r8} + @ r1 = phys address of L2C-310 controller + @ r2 = aux_ctrl + @ r3 = tag_latency + @ r4 = data_latency + @ r5 = filter_start + @ r6 = filter_end + @ r7 = prefetch_ctrl + @ r8 = pwr_ctrl + + @ Check that the address has been initialised + teq r1, #0 + moveq pc, lr + + @ The prefetch and power control registers are revision dependent + @ and can be written whether or not the L2 cache is enabled + ldr r0, [r1, #L2X0_CACHE_ID] + and r0, r0, #L2X0_CACHE_ID_RTL_MASK + cmp r0, #L310_CACHE_ID_RTL_R2P0 + strcs r7, [r1, #L310_PREFETCH_CTRL] + cmp r0, #L310_CACHE_ID_RTL_R3P0 + strcs r8, [r1, #L310_POWER_CTRL] + + @ Don't setup the L2 cache if it is already enabled + ldr r0, [r1, #L2X0_CTRL] + tst r0, #L2X0_CTRL_EN + movne pc, lr + + str r3, [r1, #L310_TAG_LATENCY_CTRL] + str r4, [r1, #L310_DATA_LATENCY_CTRL] + str r6, [r1, #L310_ADDR_FILTER_END] + str r5, [r1, #L310_ADDR_FILTER_START] + + str r2, [r1, #L2X0_AUX_CTRL] + mov r9, #L2X0_CTRL_EN + str r9, [r1, #L2X0_CTRL] + mov pc, lr +ENDPROC(l2c310_early_resume) + + .align +1: .long l2x0_saved_regs - . -- cgit v1.2.3 From 678ea28b7c3cc9a7196192dc77dfc13513db3d5f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 19:38:25 +0000 Subject: ARM: l2c: remove old .set_debug method We no longer need or require the .set_debug method; we handle everything it used to do via the .write_sec method instead. Signed-off-by: Russell King --- arch/arm/include/asm/outercache.h | 1 - arch/arm/mm/cache-l2x0.c | 21 ++------------------- 2 files changed, 2 insertions(+), 20 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index 864afe2114d3..891a56b35bcf 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h @@ -35,7 +35,6 @@ struct outer_cache_fns { void (*resume)(void); /* This is an ARM L2C thing */ - void (*set_debug)(unsigned long); void (*write_sec)(unsigned long, unsigned); }; diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index c4f3e8dc64ff..ae6e71b3295c 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -81,10 +81,7 @@ static void l2c_write_sec(unsigned long val, void __iomem *base, unsigned reg) */ static inline void l2c_set_debug(void __iomem *base, unsigned long val) { - if (outer_cache.set_debug) - outer_cache.set_debug(val); - else - l2c_write_sec(val, base, L2X0_DEBUG_CTRL); + l2c_write_sec(val, base, L2X0_DEBUG_CTRL); } static void __l2c_op_way(void __iomem *reg) @@ -155,8 +152,7 @@ static inline void cache_sync(void) #if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915) static inline void debug_writel(unsigned long val) { - if (outer_cache.set_debug || outer_cache.write_sec) - l2c_set_debug(l2x0_base, val); + l2c_set_debug(l2x0_base, val); } #else /* Optimised out for non-errata case */ @@ -514,11 +510,6 @@ static const struct l2c_init_data l2c220_data = { * Affects: store buffer * store buffer is not automatically drained. */ -static void l2c310_set_debug(unsigned long val) -{ - writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL); -} - static void l2c310_inv_range_erratum(unsigned long start, unsigned long end) { void __iomem *base = l2x0_base; @@ -695,10 +686,6 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, const char *errata[8]; unsigned n = 0; - /* For compatibility */ - if (revision <= L310_CACHE_ID_RTL_R3P0) - fns->set_debug = l2c310_set_debug; - if (IS_ENABLED(CONFIG_PL310_ERRATA_588369) && revision < L310_CACHE_ID_RTL_R2P0 && /* For bcm compatibility */ @@ -759,7 +746,6 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .flush_all = l2c210_flush_all, .disable = l2c_disable, .sync = l2c210_sync, - .set_debug = l2c310_set_debug, .resume = l2c310_resume, }, }; @@ -819,8 +805,6 @@ static void __init __l2c_init(const struct l2c_init_data *data, fns.write_sec = outer_cache.write_sec; if (data->fixup) data->fixup(l2x0_base, cache_id, &fns); - if (fns.write_sec) - fns.set_debug = NULL; /* * Check if l2x0 controller is already enabled. If we are booting @@ -1000,7 +984,6 @@ static const struct l2c_init_data of_l2c310_data __initconst = { .flush_all = l2c210_flush_all, .disable = l2c_disable, .sync = l2c210_sync, - .set_debug = l2c310_set_debug, .resume = l2c310_resume, }, }; -- cgit v1.2.3 From 314e47b7b651db93bbdeb83f4244240ff5d33baa Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 14:07:12 +0000 Subject: ARM: l2c: print a warning with L2C-310 caches if the cache size is modified As we have now removed all instances of the L2C-310 having its cache size "modified" via platform/SoC code, discourage new cases showing up by printing a warning. Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index ae6e71b3295c..415efc3bee0d 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -765,6 +765,8 @@ static void __init __l2c_init(const struct l2c_init_data *data, /* Determine the number of ways */ switch (cache_id & L2X0_CACHE_ID_PART_MASK) { case L2X0_CACHE_ID_PART_L310: + if ((aux_val | ~aux_mask) & (L2C_AUX_CTRL_WAY_SIZE_MASK | L310_AUX_CTRL_ASSOCIATIVITY_16)) + pr_warn("L2C: DT/platform tries to modify or specify cache size\n"); if (aux & (1 << 16)) ways = 16; else -- cgit v1.2.3 From 560be6136b3605ebbb8bd04b49b175c809d4e953 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 17 Mar 2014 17:02:56 +0000 Subject: ARM: l2c: add warnings for stuff modifying aux_ctrl register values Signed-off-by: Russell King --- arch/arm/mm/cache-l2x0.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 415efc3bee0d..e99a0ffd22d1 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -755,13 +755,24 @@ static void __init __l2c_init(const struct l2c_init_data *data, { struct outer_cache_fns fns; unsigned way_size_bits, ways; - u32 aux; + u32 aux, old_aux; - aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); + /* + * Sanity check the aux values. aux_mask is the bits we preserve + * from reading the hardware register, and aux_val is the bits we + * set. + */ + if (aux_val & aux_mask) + pr_alert("L2C: platform provided aux values permit register corruption.\n"); + old_aux = aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); aux &= aux_mask; aux |= aux_val; + if (old_aux != aux) + pr_warn("L2C: DT/platform modifies aux control register: 0x%08x -> 0x%08x\n", + old_aux, aux); + /* Determine the number of ways */ switch (cache_id & L2X0_CACHE_ID_PART_MASK) { case L2X0_CACHE_ID_PART_L310: @@ -1392,7 +1403,7 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) const struct l2c_init_data *data; struct device_node *np; struct resource res; - u32 cache_id; + u32 cache_id, old_aux; np = of_find_matching_node(NULL, l2x0_ids); if (!np) @@ -1409,6 +1420,14 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) data = of_match_node(l2x0_ids, np)->data; + old_aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); + if (old_aux != ((old_aux & aux_mask) | aux_val)) { + pr_warn("L2C: platform modifies aux control register: 0x%08x -> 0x%08x\n", + old_aux, (old_aux & aux_mask) | aux_val); + } else if (aux_mask != ~0U && aux_val != 0) { + pr_alert("L2C: platform provided aux values match the hardware, so have no effect. Please remove them.\n"); + } + /* All L2 caches are unified, so this property should be specified */ if (!of_property_read_bool(np, "cache-unified")) pr_err("L2C: device tree omits to specify unified cache\n"); -- cgit v1.2.3 From 8ef418c7178fa611d84e187bacb967880f6f5b69 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Mar 2014 21:40:01 +0000 Subject: ARM: l2c: trial at enabling some Cortex-A9 optimisations Signed-off-by: Russell King --- arch/arm/include/asm/hardware/cache-l2x0.h | 8 ++++ arch/arm/mm/cache-l2x0.c | 73 ++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 3 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h index 84bbd31b8910..3a5ec1c25659 100644 --- a/arch/arm/include/asm/hardware/cache-l2x0.h +++ b/arch/arm/include/asm/hardware/cache-l2x0.h @@ -134,6 +134,14 @@ #define L310_ADDR_FILTER_EN 1 +#define L310_PREFETCH_CTRL_OFFSET_MASK 0x1f +#define L310_PREFETCH_CTRL_DBL_LINEFILL_INCR BIT(23) +#define L310_PREFETCH_CTRL_PREFETCH_DROP BIT(24) +#define L310_PREFETCH_CTRL_DBL_LINEFILL_WRAP BIT(27) +#define L310_PREFETCH_CTRL_DATA_PREFETCH BIT(28) +#define L310_PREFETCH_CTRL_INSTR_PREFETCH BIT(29) +#define L310_PREFETCH_CTRL_DBL_LINEFILL BIT(30) + #define L2X0_CTRL_EN 1 #define L2X0_WAY_SIZE_SHIFT 3 diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index e99a0ffd22d1..efc5cabf70e0 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -16,14 +16,17 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include +#include #include #include #include #include #include +#include #include #include #include "cache-tauros3.h" @@ -639,7 +642,24 @@ static void l2c310_resume(void) L310_POWER_CTRL); l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8); + + /* Re-enable full-line-of-zeros for Cortex-A9 */ + if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO) + set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1)); + } +} + +static int l2c310_cpu_enable_flz(struct notifier_block *nb, unsigned long act, void *data) +{ + switch (act & ~CPU_TASKS_FROZEN) { + case CPU_STARTING: + set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1)); + break; + case CPU_DYING: + set_auxcr(get_auxcr() & ~(BIT(3) | BIT(2) | BIT(1))); + break; } + return NOTIFY_OK; } static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock) @@ -657,6 +677,36 @@ static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock) } } + if (cortex_a9) { + u32 aux_cur = readl_relaxed(base + L2X0_AUX_CTRL); + u32 acr = get_auxcr(); + + pr_debug("Cortex-A9 ACR=0x%08x\n", acr); + + if (acr & BIT(3) && !(aux_cur & L310_AUX_CTRL_FULL_LINE_ZERO)) + pr_err("L2C-310: full line of zeros enabled in Cortex-A9 but not L2C-310 - invalid\n"); + + if (aux & L310_AUX_CTRL_FULL_LINE_ZERO && !(acr & BIT(3))) + pr_err("L2C-310: enabling full line of zeros but not enabled in Cortex-A9\n"); + + if (!(aux & L310_AUX_CTRL_FULL_LINE_ZERO) && !outer_cache.write_sec) { + aux |= L310_AUX_CTRL_FULL_LINE_ZERO; + pr_info("L2C-310 full line of zeros enabled for Cortex-A9\n"); + } + } else if (aux & (L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP)) { + pr_err("L2C-310: disabling Cortex-A9 specific feature bits\n"); + aux &= ~(L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP); + } + + if (aux & (L310_AUX_CTRL_DATA_PREFETCH | L310_AUX_CTRL_INSTR_PREFETCH)) { + u32 prefetch = readl_relaxed(base + L310_PREFETCH_CTRL); + + pr_info("L2C-310 %s%s prefetch enabled, offset %u lines\n", + aux & L310_AUX_CTRL_INSTR_PREFETCH ? "I" : "", + aux & L310_AUX_CTRL_DATA_PREFETCH ? "D" : "", + 1 + (prefetch & L310_PREFETCH_CTRL_OFFSET_MASK)); + } + /* r3p0 or later has power control register */ if (rev >= L310_CACHE_ID_RTL_R3P0) { u32 power_ctrl; @@ -677,6 +727,11 @@ static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock) aux |= L310_AUX_CTRL_NS_LOCKDOWN; l2c_enable(base, aux, num_lock); + + if (aux & L310_AUX_CTRL_FULL_LINE_ZERO) { + set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1)); + cpu_notifier(l2c310_cpu_enable_flz, 0); + } } static void __init l2c310_fixup(void __iomem *base, u32 cache_id, @@ -732,6 +787,18 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id, } } +static void l2c310_disable(void) +{ + /* + * If full-line-of-zeros is enabled, we must first disable it in the + * Cortex-A9 auxiliary control register before disabling the L2 cache. + */ + if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO) + set_auxcr(get_auxcr() & ~(BIT(3) | BIT(2) | BIT(1))); + + l2c_disable(); +} + static const struct l2c_init_data l2c310_init_fns __initconst = { .type = "L2C-310", .way_size_0 = SZ_8K, @@ -744,7 +811,7 @@ static const struct l2c_init_data l2c310_init_fns __initconst = { .clean_range = l2c210_clean_range, .flush_range = l2c210_flush_range, .flush_all = l2c210_flush_all, - .disable = l2c_disable, + .disable = l2c310_disable, .sync = l2c210_sync, .resume = l2c310_resume, }, @@ -995,7 +1062,7 @@ static const struct l2c_init_data of_l2c310_data __initconst = { .clean_range = l2c210_clean_range, .flush_range = l2c210_flush_range, .flush_all = l2c210_flush_all, - .disable = l2c_disable, + .disable = l2c310_disable, .sync = l2c210_sync, .resume = l2c310_resume, }, @@ -1342,7 +1409,7 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = { .clean_range = bcm_clean_range, .flush_range = bcm_flush_range, .flush_all = l2c210_flush_all, - .disable = l2c_disable, + .disable = l2c310_disable, .sync = l2c210_sync, .resume = l2c310_resume, }, -- cgit v1.2.3 From 1c8c3cf0b5239388e712508a85821f4718f4d889 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 19 May 2014 11:04:39 +0100 Subject: ARM: 8060/1: mm: allow sub-architectures to override PCI I/O memory type Due to a design incompatibility between the PCIe Marvell controller and the Cortex-A9, stressing PCIe devices with a lot of traffic quickly causes a deadlock. One part of the workaround for this is to have all PCIe regions mapped as strongly-ordered (MT_UNCACHED) instead of the default MT_DEVICE. While the arch_ioremap_caller() mechanism allows sub-architecture code to override ioremap(), used to map PCIe memory regions, there isn't such a mechanism to override the behavior of pci_ioremap_io(). This commit adds the arch_pci_ioremap_mem_type variable, initialized to MT_DEVICE by default, and that sub-architecture code can override. We have chosen to expose a single variable rather than offering the possibility of overriding the entire pci_ioremap_io(), because implementing pci_ioremap_io() requires calling functions (get_mem_type()) that are private to the arch/arm/mm/ code. Signed-off-by: Thomas Petazzoni Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/include/asm/io.h | 6 ++++++ arch/arm/mm/ioremap.c | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 8aa4cca74501..3d23418cbddd 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -179,6 +179,12 @@ static inline void __iomem *__typesafe_io(unsigned long addr) /* PCI fixed i/o mapping */ #define PCI_IO_VIRT_BASE 0xfee00000 +#if defined(CONFIG_PCI) +void pci_ioremap_set_mem_type(int mem_type); +#else +static inline void pci_ioremap_set_mem_type(int mem_type) {} +#endif + extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr); /* diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index f9c32ba73544..d1e5ad7ab3bc 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -438,6 +438,13 @@ void __arm_iounmap(volatile void __iomem *io_addr) EXPORT_SYMBOL(__arm_iounmap); #ifdef CONFIG_PCI +static int pci_ioremap_mem_type = MT_DEVICE; + +void pci_ioremap_set_mem_type(int mem_type) +{ + pci_ioremap_mem_type = mem_type; +} + int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr) { BUG_ON(offset + SZ_64K > IO_SPACE_LIMIT); @@ -445,7 +452,7 @@ int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr) return ioremap_page_range(PCI_IO_VIRT_BASE + offset, PCI_IO_VIRT_BASE + offset + SZ_64K, phys_addr, - __pgprot(get_mem_type(MT_DEVICE)->prot_pte)); + __pgprot(get_mem_type(pci_ioremap_mem_type)->prot_pte)); } EXPORT_SYMBOL_GPL(pci_ioremap_io); #endif -- cgit v1.2.3 From 1c2f87c22566cd057bc8cde10c37ae9da1a1bb76 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Sun, 13 Apr 2014 22:54:58 +0100 Subject: ARM: 8025/1: Get rid of meminfo memblock is now fully integrated into the kernel and is the prefered method for tracking memory. Rather than reinvent the wheel with meminfo, migrate to using memblock directly instead of meminfo as an intermediate. Acked-by: Jason Cooper Acked-by: Catalin Marinas Acked-by: Santosh Shilimkar Acked-by: Kukjin Kim Tested-by: Marek Szyprowski Tested-by: Leif Lindholm Signed-off-by: Laura Abbott Signed-off-by: Russell King --- arch/arm/Kconfig | 5 -- arch/arm/boot/compressed/atags_to_fdt.c | 2 + arch/arm/include/asm/mach/arch.h | 4 +- arch/arm/include/asm/memblock.h | 3 +- arch/arm/include/asm/setup.h | 28 -------- arch/arm/kernel/atags_parse.c | 5 +- arch/arm/kernel/devtree.c | 5 -- arch/arm/kernel/setup.c | 30 +++----- arch/arm/mach-clps711x/board-clep7312.c | 7 +- arch/arm/mach-clps711x/board-edb7211.c | 10 ++- arch/arm/mach-clps711x/board-p720t.c | 2 +- arch/arm/mach-footbridge/cats-hw.c | 2 +- arch/arm/mach-footbridge/netwinder-hw.c | 2 +- arch/arm/mach-msm/board-halibut.c | 6 -- arch/arm/mach-msm/board-mahimahi.c | 13 ++-- arch/arm/mach-msm/board-msm7x30.c | 3 +- arch/arm/mach-msm/board-sapphire.c | 13 ++-- arch/arm/mach-msm/board-trout.c | 8 +-- arch/arm/mach-orion5x/common.c | 3 +- arch/arm/mach-orion5x/common.h | 3 +- arch/arm/mach-pxa/cm-x300.c | 3 +- arch/arm/mach-pxa/corgi.c | 10 ++- arch/arm/mach-pxa/eseries.c | 9 ++- arch/arm/mach-pxa/poodle.c | 8 +-- arch/arm/mach-pxa/spitz.c | 8 +-- arch/arm/mach-pxa/tosa.c | 8 +-- arch/arm/mach-realview/core.c | 11 ++- arch/arm/mach-realview/core.h | 3 +- arch/arm/mach-realview/realview_pb1176.c | 8 +-- arch/arm/mach-realview/realview_pbx.c | 17 ++--- arch/arm/mach-s3c24xx/mach-smdk2413.c | 8 +-- arch/arm/mach-s3c24xx/mach-vstms.c | 8 +-- arch/arm/mach-sa1100/assabet.c | 2 +- arch/arm/mm/init.c | 72 ++++++++----------- arch/arm/mm/mmu.c | 117 +++++++++---------------------- arch/arm/mm/nommu.c | 66 +++++++++-------- 36 files changed, 179 insertions(+), 333 deletions(-) (limited to 'arch/arm/mm') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ce64b7f66328..03551fafb1fd 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1101,11 +1101,6 @@ source "arch/arm/firmware/Kconfig" source arch/arm/mm/Kconfig -config ARM_NR_BANKS - int - default 16 if ARCH_EP93XX - default 8 - config IWMMXT bool "Enable iWMMXt support" if !CPU_PJ4 depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4 diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c index d1153c8a765a..9448aa0c6686 100644 --- a/arch/arm/boot/compressed/atags_to_fdt.c +++ b/arch/arm/boot/compressed/atags_to_fdt.c @@ -7,6 +7,8 @@ #define do_extend_cmdline 0 #endif +#define NR_BANKS 16 + static int node_offset(void *fdt, const char *node_path) { int offset = fdt_path_offset(fdt, node_path); diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index 17a3fa2979e8..c43473afde8a 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h @@ -14,7 +14,6 @@ #include struct tag; -struct meminfo; struct pt_regs; struct smp_operations; #ifdef CONFIG_SMP @@ -47,8 +46,7 @@ struct machine_desc { enum reboot_mode reboot_mode; /* default restart mode */ struct smp_operations *smp; /* SMP operations */ bool (*smp_init)(void); - void (*fixup)(struct tag *, char **, - struct meminfo *); + void (*fixup)(struct tag *, char **); void (*init_meminfo)(void); void (*reserve)(void);/* reserve mem blocks */ void (*map_io)(void);/* IO mapping function */ diff --git a/arch/arm/include/asm/memblock.h b/arch/arm/include/asm/memblock.h index c2f5102ae659..bf47a6c110a2 100644 --- a/arch/arm/include/asm/memblock.h +++ b/arch/arm/include/asm/memblock.h @@ -1,10 +1,9 @@ #ifndef _ASM_ARM_MEMBLOCK_H #define _ASM_ARM_MEMBLOCK_H -struct meminfo; struct machine_desc; -void arm_memblock_init(struct meminfo *, const struct machine_desc *); +void arm_memblock_init(const struct machine_desc *); phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align); #endif diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index 8d6a089dfb76..e0adb9f1bf94 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h @@ -21,34 +21,6 @@ #define __tagtable(tag, fn) \ static const struct tagtable __tagtable_##fn __tag = { tag, fn } -/* - * Memory map description - */ -#define NR_BANKS CONFIG_ARM_NR_BANKS - -struct membank { - phys_addr_t start; - phys_addr_t size; - unsigned int highmem; -}; - -struct meminfo { - int nr_banks; - struct membank bank[NR_BANKS]; -}; - -extern struct meminfo meminfo; - -#define for_each_bank(iter,mi) \ - for (iter = 0; iter < (mi)->nr_banks; iter++) - -#define bank_pfn_start(bank) __phys_to_pfn((bank)->start) -#define bank_pfn_end(bank) __phys_to_pfn((bank)->start + (bank)->size) -#define bank_pfn_size(bank) ((bank)->size >> PAGE_SHIFT) -#define bank_phys_start(bank) (bank)->start -#define bank_phys_end(bank) ((bank)->start + (bank)->size) -#define bank_phys_size(bank) (bank)->size - extern int arm_add_memory(u64 start, u64 size); extern void early_print(const char *str, ...); extern void dump_machine_table(void); diff --git a/arch/arm/kernel/atags_parse.c b/arch/arm/kernel/atags_parse.c index 8c14de8180c0..7807ef58a2ab 100644 --- a/arch/arm/kernel/atags_parse.c +++ b/arch/arm/kernel/atags_parse.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -222,10 +223,10 @@ setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr) } if (mdesc->fixup) - mdesc->fixup(tags, &from, &meminfo); + mdesc->fixup(tags, &from); if (tags->hdr.tag == ATAG_CORE) { - if (meminfo.nr_banks != 0) + if (memblock_phys_mem_size()) squash_mem_tags(tags); save_atags(tags); parse_tags(tags); diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index c7419a585ddc..679a83d470cc 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -27,11 +27,6 @@ #include #include -void __init early_init_dt_add_memory_arch(u64 base, u64 size) -{ - arm_add_memory(base, size); -} - void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) { return memblock_virt_alloc(size, align); diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 50e198c1e9c8..6d78ba47ea5b 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -628,15 +628,8 @@ void __init dump_machine_table(void) int __init arm_add_memory(u64 start, u64 size) { - struct membank *bank = &meminfo.bank[meminfo.nr_banks]; u64 aligned_start; - if (meminfo.nr_banks >= NR_BANKS) { - pr_crit("NR_BANKS too low, ignoring memory at 0x%08llx\n", - (long long)start); - return -EINVAL; - } - /* * Ensure that start/size are aligned to a page boundary. * Size is appropriately rounded down, start is rounded up. @@ -677,17 +670,17 @@ int __init arm_add_memory(u64 start, u64 size) aligned_start = PHYS_OFFSET; } - bank->start = aligned_start; - bank->size = size & ~(phys_addr_t)(PAGE_SIZE - 1); + start = aligned_start; + size = size & ~(phys_addr_t)(PAGE_SIZE - 1); /* * Check whether this memory region has non-zero size or * invalid node number. */ - if (bank->size == 0) + if (size == 0) return -EINVAL; - meminfo.nr_banks++; + memblock_add(start, size); return 0; } @@ -695,6 +688,7 @@ int __init arm_add_memory(u64 start, u64 size) * Pick out the memory size. We look for mem=size@start, * where start and size are "size[KkMm]" */ + static int __init early_mem(char *p) { static int usermem __initdata = 0; @@ -709,7 +703,8 @@ static int __init early_mem(char *p) */ if (usermem == 0) { usermem = 1; - meminfo.nr_banks = 0; + memblock_remove(memblock_start_of_DRAM(), + memblock_end_of_DRAM() - memblock_start_of_DRAM()); } start = PHYS_OFFSET; @@ -854,13 +849,6 @@ static void __init reserve_crashkernel(void) static inline void reserve_crashkernel(void) {} #endif /* CONFIG_KEXEC */ -static int __init meminfo_cmp(const void *_a, const void *_b) -{ - const struct membank *a = _a, *b = _b; - long cmp = bank_pfn_start(a) - bank_pfn_start(b); - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; -} - void __init hyp_mode_check(void) { #ifdef CONFIG_ARM_VIRT_EXT @@ -903,12 +891,10 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); - sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL); - early_paging_init(mdesc, lookup_processor_type(read_cpuid_id())); setup_dma_zone(mdesc); sanity_check_meminfo(); - arm_memblock_init(&meminfo, mdesc); + arm_memblock_init(mdesc); paging_init(mdesc); request_standard_resources(mdesc); diff --git a/arch/arm/mach-clps711x/board-clep7312.c b/arch/arm/mach-clps711x/board-clep7312.c index 221b9de32dd6..94a7add88a3f 100644 --- a/arch/arm/mach-clps711x/board-clep7312.c +++ b/arch/arm/mach-clps711x/board-clep7312.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -26,11 +27,9 @@ #include "common.h" static void __init -fixup_clep7312(struct tag *tags, char **cmdline, struct meminfo *mi) +fixup_clep7312(struct tag *tags, char **cmdline) { - mi->nr_banks=1; - mi->bank[0].start = 0xc0000000; - mi->bank[0].size = 0x01000000; + memblock_add(0xc0000000, 0x01000000); } MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312") diff --git a/arch/arm/mach-clps711x/board-edb7211.c b/arch/arm/mach-clps711x/board-edb7211.c index 077609841f14..f9828f89972a 100644 --- a/arch/arm/mach-clps711x/board-edb7211.c +++ b/arch/arm/mach-clps711x/board-edb7211.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -133,7 +134,7 @@ static void __init edb7211_reserve(void) } static void __init -fixup_edb7211(struct tag *tags, char **cmdline, struct meminfo *mi) +fixup_edb7211(struct tag *tags, char **cmdline) { /* * Bank start addresses are not present in the information @@ -143,11 +144,8 @@ fixup_edb7211(struct tag *tags, char **cmdline, struct meminfo *mi) * Banks sizes _are_ present in the param block, but we're * not using that information yet. */ - mi->bank[0].start = 0xc0000000; - mi->bank[0].size = SZ_8M; - mi->bank[1].start = 0xc1000000; - mi->bank[1].size = SZ_8M; - mi->nr_banks = 2; + memblock_add(0xc0000000, SZ_8M); + memblock_add(0xc1000000, SZ_8M); } static void __init edb7211_init(void) diff --git a/arch/arm/mach-clps711x/board-p720t.c b/arch/arm/mach-clps711x/board-p720t.c index 67b733744ed7..0cf0e51e6546 100644 --- a/arch/arm/mach-clps711x/board-p720t.c +++ b/arch/arm/mach-clps711x/board-p720t.c @@ -295,7 +295,7 @@ static struct generic_bl_info p720t_lcd_backlight_pdata = { }; static void __init -fixup_p720t(struct tag *tag, char **cmdline, struct meminfo *mi) +fixup_p720t(struct tag *tag, char **cmdline) { /* * Our bootloader doesn't setup any tags (yet). diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c index da0415094856..8f05489671b7 100644 --- a/arch/arm/mach-footbridge/cats-hw.c +++ b/arch/arm/mach-footbridge/cats-hw.c @@ -76,7 +76,7 @@ __initcall(cats_hw_init); * hard reboots fail on early boards. */ static void __init -fixup_cats(struct tag *tags, char **cmdline, struct meminfo *mi) +fixup_cats(struct tag *tags, char **cmdline) { #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) screen_info.orig_video_lines = 25; diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c index eb1fa5c84723..cdee08c6d239 100644 --- a/arch/arm/mach-footbridge/netwinder-hw.c +++ b/arch/arm/mach-footbridge/netwinder-hw.c @@ -620,7 +620,7 @@ __initcall(nw_hw_init); * the parameter page. */ static void __init -fixup_netwinder(struct tag *tags, char **cmdline, struct meminfo *mi) +fixup_netwinder(struct tag *tags, char **cmdline) { #ifdef CONFIG_ISAPNP extern int isapnp_disable; diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c index a77529887cbc..61bfe584a9d7 100644 --- a/arch/arm/mach-msm/board-halibut.c +++ b/arch/arm/mach-msm/board-halibut.c @@ -83,11 +83,6 @@ static void __init halibut_init(void) platform_add_devices(devices, ARRAY_SIZE(devices)); } -static void __init halibut_fixup(struct tag *tags, char **cmdline, - struct meminfo *mi) -{ -} - static void __init halibut_map_io(void) { msm_map_common_io(); @@ -100,7 +95,6 @@ static void __init halibut_init_late(void) MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)") .atag_offset = 0x100, - .fixup = halibut_fixup, .map_io = halibut_map_io, .init_early = halibut_init_early, .init_irq = halibut_init_irq, diff --git a/arch/arm/mach-msm/board-mahimahi.c b/arch/arm/mach-msm/board-mahimahi.c index 7d9981cb400e..873c3ca3cd7e 100644 --- a/arch/arm/mach-msm/board-mahimahi.c +++ b/arch/arm/mach-msm/board-mahimahi.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -52,16 +53,10 @@ static void __init mahimahi_init(void) platform_add_devices(devices, ARRAY_SIZE(devices)); } -static void __init mahimahi_fixup(struct tag *tags, char **cmdline, - struct meminfo *mi) +static void __init mahimahi_fixup(struct tag *tags, char **cmdline) { - mi->nr_banks = 2; - mi->bank[0].start = PHYS_OFFSET; - mi->bank[0].node = PHYS_TO_NID(PHYS_OFFSET); - mi->bank[0].size = (219*1024*1024); - mi->bank[1].start = MSM_HIGHMEM_BASE; - mi->bank[1].node = PHYS_TO_NID(MSM_HIGHMEM_BASE); - mi->bank[1].size = MSM_HIGHMEM_SIZE; + memblock_add(PHYS_OFFSET, 219*SZ_1M); + memblock_add(MSM_HIGHMEM_BASE, MSM_HIGHMEM_SIZE); } static void __init mahimahi_map_io(void) diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c index 46de789ad3ae..b621b23a5ecc 100644 --- a/arch/arm/mach-msm/board-msm7x30.c +++ b/arch/arm/mach-msm/board-msm7x30.c @@ -40,8 +40,7 @@ #include "proc_comm.h" #include "common.h" -static void __init msm7x30_fixup(struct tag *tag, char **cmdline, - struct meminfo *mi) +static void __init msm7x30_fixup(struct tag *tag, char **cmdline) { for (; tag->hdr.size; tag = tag_next(tag)) if (tag->hdr.tag == ATAG_MEM && tag->u.mem.start == 0x200000) { diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c index 327605174d63..e50967926dcd 100644 --- a/arch/arm/mach-msm/board-sapphire.c +++ b/arch/arm/mach-msm/board-sapphire.c @@ -35,6 +35,7 @@ #include #include +#include #include "gpio_chip.h" #include "board-sapphire.h" @@ -74,22 +75,18 @@ static struct map_desc sapphire_io_desc[] __initdata = { } }; -static void __init sapphire_fixup(struct tag *tags, char **cmdline, - struct meminfo *mi) +static void __init sapphire_fixup(struct tag *tags, char **cmdline) { int smi_sz = parse_tag_smi((const struct tag *)tags); - mi->nr_banks = 1; - mi->bank[0].start = PHYS_OFFSET; - mi->bank[0].node = PHYS_TO_NID(PHYS_OFFSET); if (smi_sz == 32) { - mi->bank[0].size = (84*1024*1024); + memblock_add(PHYS_OFFSET, 84*SZ_1M); } else if (smi_sz == 64) { - mi->bank[0].size = (101*1024*1024); + memblock_add(PHYS_OFFSET, 101*SZ_1M); } else { + memblock_add(PHYS_OFFSET, 101*SZ_1M); /* Give a default value when not get smi size */ smi_sz = 64; - mi->bank[0].size = (101*1024*1024); } } diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c index 015d544aa017..58826cfab6b0 100644 --- a/arch/arm/mach-msm/board-trout.c +++ b/arch/arm/mach-msm/board-trout.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -55,12 +56,9 @@ static void __init trout_init_irq(void) msm_init_irq(); } -static void __init trout_fixup(struct tag *tags, char **cmdline, - struct meminfo *mi) +static void __init trout_fixup(struct tag *tags, char **cmdline) { - mi->nr_banks = 1; - mi->bank[0].start = PHYS_OFFSET; - mi->bank[0].size = (101*1024*1024); + memblock_add(PHYS_OFFSET, 101*SZ_1M); } static void __init trout_init(void) diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 3f1de1111e0f..6bbb7b55c6d1 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c @@ -365,8 +365,7 @@ void orion5x_restart(enum reboot_mode mode, const char *cmd) * Many orion-based systems have buggy bootloader implementations. * This is a common fixup for bogus memory tags. */ -void __init tag_fixup_mem32(struct tag *t, char **from, - struct meminfo *meminfo) +void __init tag_fixup_mem32(struct tag *t, char **from) { for (; t->hdr.size; t = tag_next(t)) if (t->hdr.tag == ATAG_MEM && diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h index f565f9944af2..175ec4ca8df6 100644 --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@ -71,9 +71,8 @@ void edmini_v2_init(void); static inline void edmini_v2_init(void) {}; #endif -struct meminfo; struct tag; -extern void __init tag_fixup_mem32(struct tag *, char **, struct meminfo *); +extern void __init tag_fixup_mem32(struct tag *, char **); /***************************************************************************** * Helpers to access Orion registers diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index 584439bfa59f..4d3588d26c2a 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -837,8 +837,7 @@ static void __init cm_x300_init(void) cm_x300_init_bl(); } -static void __init cm_x300_fixup(struct tag *tags, char **cmdline, - struct meminfo *mi) +static void __init cm_x300_fixup(struct tag *tags, char **cmdline) { /* Make sure that mi->bank[0].start = PHYS_ADDR */ for (; tags->hdr.size; tags = tag_next(tags)) diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 57d60542f982..91dd1c7cdbcd 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -34,6 +34,7 @@ #include #include #include +#include #include