From 44ae903b96b1e5f9ff3103cd86918619c188003f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 20 Mar 2014 15:16:54 +0100 Subject: [PATCH 001/142] ARM: 8008/1: topology: Coding style fixes Use kcalloc() and ULONG_MAX rather than open coding them. Signed-off-by: Mark Brown Signed-off-by: Russell King --- arch/arm/kernel/topology.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 0bc94b1fd1ae..0fa8825cea04 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -91,13 +91,13 @@ static void __init parse_dt_topology(void) { const struct cpu_efficiency *cpu_eff; struct device_node *cn = NULL; - unsigned long min_capacity = (unsigned long)(-1); + unsigned long min_capacity = ULONG_MAX; unsigned long max_capacity = 0; unsigned long capacity = 0; - int alloc_size, cpu = 0; + int cpu = 0; - alloc_size = nr_cpu_ids * sizeof(*__cpu_capacity); - __cpu_capacity = kzalloc(alloc_size, GFP_NOWAIT); + __cpu_capacity = kcalloc(nr_cpu_ids, sizeof(*__cpu_capacity), + GFP_NOWAIT); for_each_possible_cpu(cpu) { const u32 *rate; From 603fb42a66499ab353466c7afa3d38beea20a8a9 Mon Sep 17 00:00:00 2001 From: Sebastian Capella Date: Tue, 25 Mar 2014 01:20:29 +0100 Subject: [PATCH 002/142] ARM: 8011/1: ARM hibernation / suspend-to-disk Enable hibernation for ARM architectures and provide ARM architecture specific calls used during hibernation. The swsusp hibernation framework depends on the platform first having functional suspend/resume. Then, in order to enable hibernation on a given platform, a platform_hibernation_ops structure may need to be registered with the system in order to save/restore any SoC-specific / cpu specific state needing (re)init over a suspend-to-disk/resume-from-disk cycle. For example: - "secure" SoCs that have different sets of control registers and/or different CR reg access patterns. - SoCs with L2 caches as the activation sequence there is SoC-dependent; a full off-on cycle for L2 is not done by the hibernation support code. - SoCs requiring steps on wakeup _before_ the "generic" parts done by cpu_suspend / cpu_resume can work correctly. - SoCs having persistent state which is maintained during suspend and resume, but will be lost during the power off cycle after suspend-to-disk. This is a rebase/rework of Frank Hofmann's v5 hibernation patchset. Acked-by: Russ Dill Cc: "Rafael J. Wysocki" Signed-off-by: Sebastian Capella Acked-by: Pavel Machek Reviewed-by: Lorenzo Pieralisi [fixed duplicate virt_to_pfn() definition --rmk] Signed-off-by: Russell King --- arch/arm/Kconfig | 5 ++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/hibernate.c | 107 ++++++++++++++++++++++++++++++++++++ include/linux/suspend.h | 2 + 4 files changed, 115 insertions(+) create mode 100644 arch/arm/kernel/hibernate.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ab438cb5af55..58506175a3ea 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -2294,6 +2294,11 @@ config ARCH_SUSPEND_POSSIBLE config ARM_CPU_SUSPEND def_bool PM_SLEEP +config ARCH_HIBERNATION_POSSIBLE + bool + depends on MMU + default y if ARCH_SUSPEND_POSSIBLE + endmenu source "net/Kconfig" diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index a766bcbaf8ad..10f0464206a2 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_PCI) += bios32.o isa.o obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o +obj-$(CONFIG_HIBERNATION) += hibernate.o obj-$(CONFIG_SMP) += smp.o ifdef CONFIG_MMU obj-$(CONFIG_SMP) += smp_tlb.o diff --git a/arch/arm/kernel/hibernate.c b/arch/arm/kernel/hibernate.c new file mode 100644 index 000000000000..bb8b79648643 --- /dev/null +++ b/arch/arm/kernel/hibernate.c @@ -0,0 +1,107 @@ +/* + * Hibernation support specific for ARM + * + * Derived from work on ARM hibernation support by: + * + * Ubuntu project, hibernation support for mach-dove + * Copyright (C) 2010 Nokia Corporation (Hiroshi Doyu) + * Copyright (C) 2010 Texas Instruments, Inc. (Teerth Reddy et al.) + * https://lkml.org/lkml/2010/6/18/4 + * https://lists.linux-foundation.org/pipermail/linux-pm/2010-June/027422.html + * https://patchwork.kernel.org/patch/96442/ + * + * Copyright (C) 2006 Rafael J. Wysocki + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include +#include +#include + +extern const void __nosave_begin, __nosave_end; + +int pfn_is_nosave(unsigned long pfn) +{ + unsigned long nosave_begin_pfn = virt_to_pfn(&__nosave_begin); + unsigned long nosave_end_pfn = virt_to_pfn(&__nosave_end - 1); + + return (pfn >= nosave_begin_pfn) && (pfn <= nosave_end_pfn); +} + +void notrace save_processor_state(void) +{ + WARN_ON(num_online_cpus() != 1); + local_fiq_disable(); +} + +void notrace restore_processor_state(void) +{ + local_fiq_enable(); +} + +/* + * Snapshot kernel memory and reset the system. + * + * swsusp_save() is executed in the suspend finisher so that the CPU + * context pointer and memory are part of the saved image, which is + * required by the resume kernel image to restart execution from + * swsusp_arch_suspend(). + * + * soft_restart is not technically needed, but is used to get success + * returned from cpu_suspend. + * + * When soft reboot completes, the hibernation snapshot is written out. + */ +static int notrace arch_save_image(unsigned long unused) +{ + int ret; + + ret = swsusp_save(); + if (ret == 0) + soft_restart(virt_to_phys(cpu_resume)); + return ret; +} + +/* + * Save the current CPU state before suspend / poweroff. + */ +int notrace swsusp_arch_suspend(void) +{ + return cpu_suspend(0, arch_save_image); +} + +/* + * Restore page contents for physical pages that were in use during loading + * hibernation image. Switch to idmap_pgd so the physical page tables + * are overwritten with the same contents. + */ +static void notrace arch_restore_image(void *unused) +{ + struct pbe *pbe; + + cpu_switch_mm(idmap_pgd, &init_mm); + for (pbe = restore_pblist; pbe; pbe = pbe->next) + copy_page(pbe->orig_address, pbe->address); + + soft_restart(virt_to_phys(cpu_resume)); +} + +static u64 resume_stack[PAGE_SIZE/2/sizeof(u64)] __nosavedata; + +/* + * Resume from the hibernation image. + * Due to the kernel heap / data restore, stack contents change underneath + * and that would make function calls impossible; switch to a temporary + * stack within the nosave region to avoid that problem. + */ +int swsusp_arch_resume(void) +{ + extern void call_with_stack(void (*fn)(void *), void *arg, void *sp); + call_with_stack(arch_restore_image, 0, + resume_stack + ARRAY_SIZE(resume_stack)); + return 0; +} diff --git a/include/linux/suspend.h b/include/linux/suspend.h index f73cabf59012..38bbf95109da 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -320,6 +320,8 @@ extern unsigned long get_safe_page(gfp_t gfp_mask); extern void hibernation_set_ops(const struct platform_hibernation_ops *ops); extern int hibernate(void); extern bool system_entering_hibernation(void); +asmlinkage int swsusp_save(void); +extern struct pbe *restore_pblist; #else /* CONFIG_HIBERNATION */ static inline void register_nosave_region(unsigned long b, unsigned long e) {} static inline void register_nosave_region_late(unsigned long b, unsigned long e) {} From a672917ab8964228f83ac1f0728468b309d6ea19 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 3 Apr 2014 18:46:45 +0100 Subject: [PATCH 003/142] ARM: 8022/1: ftrace: work with CONFIG_DEBUG_SET_MODULE_RONX Make ftrace work with CONFIG_DEBUG_SET_MODULE_RONX by making module text writable around the place where ftrace does its work, like it is done on x86 in the patch which introduced CONFIG_DEBUG_SET_MODULE_RONX, 84e1c6bb38eb ("x86: Add RO/NX protection for loadable kernel modules"). Tested-by: Mitchel Humpherys Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/kernel/ftrace.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index c108ddcb9ba4..af9a8a927a4e 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -63,6 +64,18 @@ static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr) } #endif +int ftrace_arch_code_modify_prepare(void) +{ + set_all_modules_text_rw(); + return 0; +} + +int ftrace_arch_code_modify_post_process(void) +{ + set_all_modules_text_ro(); + return 0; +} + static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr) { return arm_gen_branch_link(pc, addr); From 64d3b6a3f480154b6727dd2187f5f2b58c15da77 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 9 Apr 2014 21:24:02 +0100 Subject: [PATCH 004/142] ARM: 8023/1: remove remnants of the static DMA mapping It looks like the static mapping area for DMA was replaced by dynamic allocation into the vmalloc area by commit e9da6e9905e6 but the information in Documentation/arm/memory.txt was not removed accordingly. CONSISTENT_END in arch/arm/include/asm/memory.h has no more users and can be removed as well. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- Documentation/arm/memory.txt | 7 ------- arch/arm/include/asm/memory.h | 2 -- 2 files changed, 9 deletions(-) diff --git a/Documentation/arm/memory.txt b/Documentation/arm/memory.txt index 4bfb9ffbdbc1..d74e8a5901fc 100644 --- a/Documentation/arm/memory.txt +++ b/Documentation/arm/memory.txt @@ -44,13 +44,6 @@ fffe0000 fffe7fff ITCM mapping area for platforms with fff00000 fffdffff Fixmap mapping region. Addresses provided by fix_to_virt() will be located here. -ffc00000 ffefffff DMA memory mapping region. Memory returned - by the dma_alloc_xxx functions will be - dynamically mapped here. - -ff000000 ffbfffff Reserved for future expansion of DMA - mapping region. - fee00000 feffffff Mapping of PCI I/O space. This is a static mapping within the vmalloc space. diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 02fa2558f662..2b751464d6ff 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -83,8 +83,6 @@ */ #define IOREMAP_MAX_ORDER 24 -#define CONSISTENT_END (0xffe00000UL) - #else /* CONFIG_MMU */ /* From 16c79a3776c17965dedab4732d925f6098df91c1 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Fri, 28 Mar 2014 12:21:16 +0100 Subject: [PATCH 005/142] 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(-) 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 From 4221e2e6b3160e4b558df14fa79f025c0e277935 Mon Sep 17 00:00:00 2001 From: Liu Hua Date: Fri, 18 Apr 2014 09:27:01 +0100 Subject: [PATCH 006/142] 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(-) 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 From a05e54c103b0b8e1dab5d04b411f1d48387c4903 Mon Sep 17 00:00:00 2001 From: Liu Hua Date: Fri, 18 Apr 2014 09:43:32 +0100 Subject: [PATCH 007/142] 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(-) 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 } From 431a84b1a4f7d1a0085d5b91330c5053cc8e8b12 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 22 Apr 2014 16:14:27 +0100 Subject: [PATCH 008/142] ARM: 8034/1: Disable preemption in iwmmxt_task_enable() This patch is in preparation for calling the iwmmxt_task_enable() function with interrupts enabled. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/kernel/iwmmxt.S | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S index a08783823b32..fcb33a70a35f 100644 --- a/arch/arm/kernel/iwmmxt.S +++ b/arch/arm/kernel/iwmmxt.S @@ -18,6 +18,7 @@ #include #include #include +#include #if defined(CONFIG_CPU_PJ4) #define PJ4(code...) code @@ -65,13 +66,14 @@ */ ENTRY(iwmmxt_task_enable) + inc_preempt_count r10, r3 XSC(mrc p15, 0, r2, c15, c1, 0) PJ4(mrc p15, 0, r2, c1, c0, 2) @ CP0 and CP1 accessible? XSC(tst r2, #0x3) PJ4(tst r2, #0xf) - movne pc, lr @ if so no business here + bne 4f @ if so no business here @ enable access to CP0 and CP1 XSC(orr r2, r2, #0x3) XSC(mcr p15, 0, r2, c15, c1, 0) @@ -132,7 +134,7 @@ concan_dump: wstrd wR15, [r1, #MMX_WR15] 2: teq r0, #0 @ anything to load? - moveq pc, lr + beq 3f concan_load: @@ -165,8 +167,14 @@ concan_load: @ clear CUP/MUP (only if r1 != 0) teq r1, #0 mov r2, #0 - moveq pc, lr + beq 3f tmcr wCon, r2 + +3: +#ifdef CONFIG_PREEMPT_COUNT + get_thread_info r10 +#endif +4: dec_preempt_count r10, r3 mov pc, lr /* From bc94081c6ac823c4723d8e36e9604c6cf3eba0ef Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 22 Apr 2014 16:14:28 +0100 Subject: [PATCH 009/142] ARM: 8035/1: Disable preemption in crunch_task_enable() This patch is in preparation for calling the crunch_task_enable() function with interrupts enabled. Signed-off-by: Catalin Marinas Cc: Hartley Sweeten Cc: Ryan Mallon Signed-off-by: Russell King --- arch/arm/mach-ep93xx/crunch-bits.S | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ep93xx/crunch-bits.S b/arch/arm/mach-ep93xx/crunch-bits.S index 0ec9bb48fab9..eaa5e34729d3 100644 --- a/arch/arm/mach-ep93xx/crunch-bits.S +++ b/arch/arm/mach-ep93xx/crunch-bits.S @@ -16,6 +16,7 @@ #include #include #include +#include #include /* @@ -65,11 +66,13 @@ * called from prefetch exception handler with interrupts disabled */ ENTRY(crunch_task_enable) + inc_preempt_count r10, r3 + ldr r8, =(EP93XX_APB_VIRT_BASE + 0x00130000) @ syscon addr ldr r1, [r8, #0x80] tst r1, #0x00800000 @ access to crunch enabled? - movne pc, lr @ if so no business here + bne 2f @ if so no business here mov r3, #0xaa @ unlock syscon swlock str r3, [r8, #0xc0] orr r1, r1, #0x00800000 @ enable access to crunch @@ -142,7 +145,7 @@ crunch_save: teq r0, #0 @ anything to load? cfldr64eq mvdx0, [r1, #CRUNCH_MVDX0] @ mvdx0 was clobbered - moveq pc, lr + beq 1f crunch_load: cfldr64 mvdx0, [r0, #CRUNCH_DSPSC] @ load status word @@ -190,6 +193,11 @@ crunch_load: cfldr64 mvdx14, [r0, #CRUNCH_MVDX14] cfldr64 mvdx15, [r0, #CRUNCH_MVDX15] +1: +#ifdef CONFIG_PREEMPT_COUNT + get_thread_info r10 +#endif +2: dec_preempt_count r10, r3 mov pc, lr /* From 1417a6b8dc4db73055be9a3aa288b050e9dc06ab Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 22 Apr 2014 16:14:29 +0100 Subject: [PATCH 010/142] ARM: 8036/1: Enable IRQs before attempting to read user space in __und_usr The Undef abort handler in the kernel reads the undefined instruction from user space. If the page table was modified from another CPU, the user access could fail and do_page_fault() will be executed with interrupts disabled. This can potentially deadlock on ARM11MPCore or on Cortex-A15 with erratum 798181 workaround enabled (both implying IPI for TLB maintenance with page table lock held). This patch enables the IRQs in __und_usr before attempting to read the instruction from user space. Signed-off-by: Catalin Marinas Tested-by: Arun KS Cc: Hartley Sweeten Cc: Ryan Mallon Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 11 +++++++---- arch/arm/kernel/iwmmxt.S | 2 +- arch/arm/mach-ep93xx/crunch-bits.S | 2 +- arch/arm/vfp/entry.S | 3 +-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 1879e8dd2acc..5fc897cf409b 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -413,6 +413,11 @@ __und_usr: @ adr r9, BSYM(ret_from_exception) + @ IRQs must be enabled before attempting to read the instruction from + @ user space since that could cause a page/translation fault if the + @ page table was modified by another CPU. + enable_irq + tst r3, #PSR_T_BIT @ Thumb mode? bne __und_usr_thumb sub r4, r2, #4 @ ARM instr at LR - 4 @@ -517,7 +522,7 @@ ENDPROC(__und_usr) * r9 = normal "successful" return address * r10 = this threads thread_info structure * lr = unrecognised instruction return address - * IRQs disabled, FIQs enabled. + * IRQs enabled, FIQs enabled. */ @ @ Fall-through from Thumb-2 __und_usr @@ -624,7 +629,6 @@ call_fpe: #endif do_fpe: - enable_irq ldr r4, .LCfp add r10, r10, #TI_FPSTATE @ r10 = workspace ldr pc, [r4] @ Call FP module USR entry point @@ -652,8 +656,7 @@ __und_usr_fault_32: b 1f __und_usr_fault_16: mov r1, #2 -1: enable_irq - mov r0, sp +1: mov r0, sp adr lr, BSYM(ret_from_exception) b __und_fault ENDPROC(__und_usr_fault_32) diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S index fcb33a70a35f..4bb029ea8917 100644 --- a/arch/arm/kernel/iwmmxt.S +++ b/arch/arm/kernel/iwmmxt.S @@ -62,7 +62,7 @@ * r9 = ret_from_exception * lr = undefined instr exit * - * called from prefetch exception handler with interrupts disabled + * called from prefetch exception handler with interrupts enabled */ ENTRY(iwmmxt_task_enable) diff --git a/arch/arm/mach-ep93xx/crunch-bits.S b/arch/arm/mach-ep93xx/crunch-bits.S index eaa5e34729d3..e96923a3017b 100644 --- a/arch/arm/mach-ep93xx/crunch-bits.S +++ b/arch/arm/mach-ep93xx/crunch-bits.S @@ -63,7 +63,7 @@ * r9 = ret_from_exception * lr = undefined instr exit * - * called from prefetch exception handler with interrupts disabled + * called from prefetch exception handler with interrupts enabled */ ENTRY(crunch_task_enable) inc_preempt_count r10, r3 diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S index f0759e70fb86..fe6ca574d093 100644 --- a/arch/arm/vfp/entry.S +++ b/arch/arm/vfp/entry.S @@ -22,11 +22,10 @@ @ r9 = normal "successful" return address @ r10 = this threads thread_info structure @ lr = unrecognised instruction return address -@ IRQs disabled. +@ IRQs enabled. @ ENTRY(do_vfp) inc_preempt_count r10, r4 - enable_irq ldr r4, .LCvfp ldr r11, [r10, #TI_CPU] @ CPU number add r10, r10, #TI_VFPSTATE @ r10 = workspace From 86f40622af7329375e38f282f6c0aab95f3e5f72 Mon Sep 17 00:00:00 2001 From: Jianguo Wu Date: Thu, 24 Apr 2014 03:45:56 +0100 Subject: [PATCH 011/142] 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(-) 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 From 8febcaa2aac184d7e729acb75e9c4b80b04ad1b9 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 24 Apr 2014 11:30:01 -0400 Subject: [PATCH 012/142] device: introduce per device dma_pfn_offset On few architectures, there are few restrictions on DMAble area of system RAM. That also means that devices needs to know about this restrictions so that the dma_masks can be updated accordingly and dma address translation helpers can add/subtract the dma offset. In most of cases DMA addresses can be performed using offset value of Bus address space relatively to physical address space as following: PFN->DMA: __pfn_to_phys(pfn + [-]dma_pfn_offset) DMA->PFN: __phys_to_pfn(dma_addr) + [-]dma_pfn_offset So we introduce per device dma_pfn_offset which can be popullated by architecture init code while creating the devices. Cc: Greg Kroah-Hartman Cc: Russell King Cc: Arnd Bergmann Cc: Olof Johansson Cc: Grant Likely Cc: Catalin Marinas Cc: Linus Walleij Reviewed-by: Rob Herring Signed-off-by: Grygorii Strashko Signed-off-by: Santosh Shilimkar --- include/linux/device.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/device.h b/include/linux/device.h index 233bbbeb768d..85a52d698f78 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -691,6 +691,7 @@ struct acpi_dev_node { * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all * hardware supports 64-bit addresses for consistent allocations * such descriptors. + * @dma_pfn_offset: offset of DMA memory range relatively of RAM * @dma_parms: A low level driver may set these to teach IOMMU code about * segment limitations. * @dma_pools: Dma pools (if dma'ble device). @@ -756,6 +757,7 @@ struct device { not all hardware supports 64 bit addresses for consistent allocations such descriptors. */ + unsigned long dma_pfn_offset; struct device_dma_parameters *dma_parms; From 18308c94723e162ed121942335bc186e66820a7a Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 24 Apr 2014 11:30:02 -0400 Subject: [PATCH 013/142] of: introduce of_dma_get_range() helper The of_dma_get_range() allows to find "dma-range" property for the specified device and parse it. dma-ranges format: DMA addr (dma_addr) : naddr cells CPU addr (phys_addr_t) : pna cells size : nsize cells Cc: Greg Kroah-Hartman Cc: Russell King Cc: Arnd Bergmann Cc: Olof Johansson Cc: Grant Likely Cc: Catalin Marinas Cc: Linus Walleij Reviewed-by: Rob Herring Signed-off-by: Grygorii Strashko Signed-off-by: Santosh Shilimkar --- drivers/of/address.c | 87 ++++++++++++++++++++++++++++++++++++++ include/linux/of_address.h | 8 ++++ 2 files changed, 95 insertions(+) diff --git a/drivers/of/address.c b/drivers/of/address.c index cb4242a69cd5..c54baee87d93 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -721,3 +721,90 @@ void __iomem *of_iomap(struct device_node *np, int index) return ioremap(res.start, resource_size(&res)); } EXPORT_SYMBOL(of_iomap); + +/** + * of_dma_get_range - Get DMA range info + * @np: device node to get DMA range info + * @dma_addr: pointer to store initial DMA address of DMA range + * @paddr: pointer to store initial CPU address of DMA range + * @size: pointer to store size of DMA range + * + * Look in bottom up direction for the first "dma-ranges" property + * and parse it. + * dma-ranges format: + * DMA addr (dma_addr) : naddr cells + * CPU addr (phys_addr_t) : pna cells + * size : nsize cells + * + * It returns -ENODEV if "dma-ranges" property was not found + * for this device in DT. + */ +int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *size) +{ + struct device_node *node = of_node_get(np); + const __be32 *ranges = NULL; + int len, naddr, nsize, pna; + int ret = 0; + u64 dmaaddr; + + if (!node) + return -EINVAL; + + while (1) { + naddr = of_n_addr_cells(node); + nsize = of_n_size_cells(node); + node = of_get_next_parent(node); + if (!node) + break; + + ranges = of_get_property(node, "dma-ranges", &len); + + /* Ignore empty ranges, they imply no translation required */ + if (ranges && len > 0) + break; + + /* + * At least empty ranges has to be defined for parent node if + * DMA is supported + */ + if (!ranges) + break; + } + + if (!ranges) { + pr_debug("%s: no dma-ranges found for node(%s)\n", + __func__, np->full_name); + ret = -ENODEV; + goto out; + } + + len /= sizeof(u32); + + pna = of_n_addr_cells(node); + + /* dma-ranges format: + * DMA addr : naddr cells + * CPU addr : pna cells + * size : nsize cells + */ + dmaaddr = of_read_number(ranges, naddr); + *paddr = of_translate_dma_address(np, ranges); + if (*paddr == OF_BAD_ADDR) { + pr_err("%s: translation of DMA address(%pad) to CPU address failed node(%s)\n", + __func__, dma_addr, np->full_name); + ret = -EINVAL; + goto out; + } + *dma_addr = dmaaddr; + + *size = of_read_number(ranges + naddr + pna, nsize); + + pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", + *dma_addr, *paddr, *size); + +out: + of_node_put(node); + + return ret; +} +EXPORT_SYMBOL_GPL(of_dma_get_range); diff --git a/include/linux/of_address.h b/include/linux/of_address.h index 5f6ed6b182b8..4d7b325af2ca 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -63,6 +63,8 @@ extern int of_pci_range_parser_init(struct of_pci_range_parser *parser, extern struct of_pci_range *of_pci_range_parser_one( struct of_pci_range_parser *parser, struct of_pci_range *range); +extern int of_dma_get_range(struct device_node *np, u64 *dma_addr, + u64 *paddr, u64 *size); #else /* CONFIG_OF_ADDRESS */ static inline struct device_node *of_find_matching_node_by_address( struct device_node *from, @@ -90,6 +92,12 @@ static inline struct of_pci_range *of_pci_range_parser_one( { return NULL; } + +static inline int of_dma_get_range(struct device_node *np, u64 *dma_addr, + u64 *paddr, u64 *size) +{ + return -ENODEV; +} #endif /* CONFIG_OF_ADDRESS */ #ifdef CONFIG_OF From 92ea637edea36e58236e3124f199161da6f5c5de Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 24 Apr 2014 11:30:03 -0400 Subject: [PATCH 014/142] of: introduce of_dma_is_coherent() helper The of_dma_is_coherent() helper parses the given DT device node to see if the "dma-coherent" property is supported and returns true or false accordingly. If the arch is always coherent or always noncoherent, then the default DMA ops has to be specified accordingly. Cc: Greg Kroah-Hartman Cc: Russell King Cc: Arnd Bergmann Cc: Olof Johansson Cc: Grant Likely Cc: Catalin Marinas Cc: Linus Walleij Reviewed-by: Rob Herring Signed-off-by: Santosh Shilimkar Signed-off-by: Grygorii Strashko --- drivers/of/address.c | 23 +++++++++++++++++++++++ include/linux/of_address.h | 6 ++++++ 2 files changed, 29 insertions(+) diff --git a/drivers/of/address.c b/drivers/of/address.c index c54baee87d93..d244b2859aac 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -808,3 +808,26 @@ out: return ret; } EXPORT_SYMBOL_GPL(of_dma_get_range); + +/** + * of_dma_is_coherent - Check if device is coherent + * @np: device node + * + * It returns true if "dma-coherent" property was found + * for this device in DT. + */ +bool of_dma_is_coherent(struct device_node *np) +{ + struct device_node *node = of_node_get(np); + + while (node) { + if (of_property_read_bool(node, "dma-coherent")) { + of_node_put(node); + return true; + } + node = of_get_next_parent(node); + } + of_node_put(node); + return false; +} +EXPORT_SYMBOL_GPL(of_dma_is_coherent); \ No newline at end of file diff --git a/include/linux/of_address.h b/include/linux/of_address.h index 4d7b325af2ca..839a3521b28e 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -65,6 +65,7 @@ extern struct of_pci_range *of_pci_range_parser_one( struct of_pci_range *range); extern int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *size); +extern bool of_dma_is_coherent(struct device_node *np); #else /* CONFIG_OF_ADDRESS */ static inline struct device_node *of_find_matching_node_by_address( struct device_node *from, @@ -98,6 +99,11 @@ static inline int of_dma_get_range(struct device_node *np, u64 *dma_addr, { return -ENODEV; } + +static inline bool of_dma_is_coherent(struct device_node *np) +{ + return false; +} #endif /* CONFIG_OF_ADDRESS */ #ifdef CONFIG_OF From 591c1ee465ce5372385dbc41e7d3e36cbb477bd8 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 24 Apr 2014 11:30:04 -0400 Subject: [PATCH 015/142] of: configure the platform device dma parameters Retrieve DMA configuration from DT and setup platform device's DMA parameters. The DMA configuration in DT has to be specified using "dma-ranges" and "dma-coherent" properties if supported. We setup dma_pfn_offset using "dma-ranges" and dma_coherent_ops using "dma-coherent" device tree properties. The set_arch_dma_coherent_ops macro has to be defined by arch if it supports coherent dma_ops. Otherwise, set_arch_dma_coherent_ops() is declared as nop. Cc: Greg Kroah-Hartman Cc: Russell King Cc: Arnd Bergmann Cc: Olof Johansson Cc: Grant Likely Cc: Catalin Marinas Cc: Linus Walleij Reviewed-by: Rob Herring Signed-off-by: Grygorii Strashko Signed-off-by: Santosh Shilimkar --- drivers/of/platform.c | 65 +++++++++++++++++++++++++++++++++---- include/linux/dma-mapping.h | 7 ++++ 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 404d1daebefa..91fa9838b56f 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -186,6 +186,64 @@ struct platform_device *of_device_alloc(struct device_node *np, } EXPORT_SYMBOL(of_device_alloc); +/** + * of_dma_configure - Setup DMA configuration + * @dev: Device to apply DMA configuration + * + * Try to get devices's DMA configuration from DT and update it + * accordingly. + * + * In case if platform code need to use own special DMA configuration,it + * can use Platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE event + * to fix up DMA configuration. + */ +static void of_dma_configure(struct platform_device *pdev) +{ + u64 dma_addr, paddr, size; + int ret; + struct device *dev = &pdev->dev; + +#if defined(CONFIG_MICROBLAZE) + pdev->archdata.dma_mask = 0xffffffffUL; +#endif + + /* + * Set default dma-mask to 32 bit. Drivers are expected to setup + * the correct supported dma_mask. + */ + dev->coherent_dma_mask = DMA_BIT_MASK(32); + + /* + * Set it to coherent_dma_mask by default if the architecture + * code has not set it. + */ + if (!dev->dma_mask) + dev->dma_mask = &dev->coherent_dma_mask; + + /* + * if dma-coherent property exist, call arch hook to setup + * dma coherent operations. + */ + if (of_dma_is_coherent(dev->of_node)) { + set_arch_dma_coherent_ops(dev); + dev_dbg(dev, "device is dma coherent\n"); + } + + /* + * if dma-ranges property doesn't exist - just return else + * setup the dma offset + */ + ret = of_dma_get_range(dev->of_node, &dma_addr, &paddr, &size); + if (ret < 0) { + dev_dbg(dev, "no dma range information to setup\n"); + return; + } + + /* DMA ranges found. Calculate and set dma_pfn_offset */ + dev->dma_pfn_offset = PFN_DOWN(paddr - dma_addr); + dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", dev->dma_pfn_offset); +} + /** * of_platform_device_create_pdata - Alloc, initialize and register an of_device * @np: pointer to node to create device for @@ -211,12 +269,7 @@ static struct platform_device *of_platform_device_create_pdata( if (!dev) return NULL; -#if defined(CONFIG_MICROBLAZE) - dev->archdata.dma_mask = 0xffffffffUL; -#endif - dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); - if (!dev->dev.dma_mask) - dev->dev.dma_mask = &dev->dev.coherent_dma_mask; + of_dma_configure(dev); dev->dev.bus = &platform_bus_type; dev->dev.platform_data = platform_data; diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index fd4aee29ad10..c7d9b1b14ce7 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -123,6 +123,13 @@ static inline int dma_coerce_mask_and_coherent(struct device *dev, u64 mask) extern u64 dma_get_required_mask(struct device *dev); +#ifndef set_arch_dma_coherent_ops +static inline int set_arch_dma_coherent_ops(struct device *dev) +{ + return 0; +} +#endif + static inline unsigned int dma_get_max_seg_size(struct device *dev) { return dev->dma_parms ? dev->dma_parms->max_segment_size : 65536; From 6ce0d20016925d031f1e24d64302e4c976d7cec6 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 24 Apr 2014 11:30:05 -0400 Subject: [PATCH 016/142] ARM: dma: Use dma_pfn_offset for dma address translation In most of cases DMA addresses can be performed using offset value of Bus address space relatively to physical address space as following: PFN->DMA: __pfn_to_phys(pfn + [-]dma_pfn_offset) DMA->PFN: __phys_to_pfn(dma_addr) + [-]dma_pfn_offset Thanks to Russell King for suggesting the optimised macro's for conversion. Cc: Greg Kroah-Hartman Cc: Russell King Cc: Arnd Bergmann Cc: Olof Johansson Cc: Grant Likely Cc: Catalin Marinas Cc: Linus Walleij Reviewed-by: Rob Herring Signed-off-by: Grygorii Strashko Signed-off-by: Santosh Shilimkar --- arch/arm/include/asm/dma-mapping.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index e701a4d9aa59..b0c79fdd9375 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -58,21 +58,37 @@ static inline int dma_set_mask(struct device *dev, u64 mask) #ifndef __arch_pfn_to_dma static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn) { + if (dev) + pfn -= dev->dma_pfn_offset; return (dma_addr_t)__pfn_to_bus(pfn); } static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr) { - return __bus_to_pfn(addr); + unsigned long pfn = __bus_to_pfn(addr); + + if (dev) + pfn += dev->dma_pfn_offset; + + return pfn; } static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) { + if (dev) { + unsigned long pfn = dma_to_pfn(dev, addr); + + return phys_to_virt(__pfn_to_phys(pfn)); + } + return (void *)__bus_to_virt((unsigned long)addr); } static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) { + if (dev) + return pfn_to_dma(dev, virt_to_pfn(addr)); + return (dma_addr_t)__virt_to_bus((unsigned long)(addr)); } From 812b99e4b024d6f83e9281ec1a0bd4bf63dad90f Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 24 Apr 2014 11:30:06 -0400 Subject: [PATCH 017/142] ARM: dma: implement set_arch_dma_coherent_ops() Implement the set_arch_dma_coherent_ops() for ARM architecture. Cc: Greg Kroah-Hartman Cc: Russell King Cc: Arnd Bergmann Cc: Olof Johansson Cc: Grant Likely Cc: Catalin Marinas Cc: Linus Walleij Reviewed-by: Rob Herring Signed-off-by: Grygorii Strashko Signed-off-by: Santosh Shilimkar --- arch/arm/include/asm/dma-mapping.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index b0c79fdd9375..c45b61a4b4a5 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -121,6 +121,13 @@ static inline unsigned long dma_max_pfn(struct device *dev) } #define dma_max_pfn(dev) dma_max_pfn(dev) +static inline int set_arch_dma_coherent_ops(struct device *dev) +{ + set_dma_ops(dev, &arm_coherent_dma_ops); + return 0; +} +#define set_arch_dma_coherent_ops(dev) set_arch_dma_coherent_ops(dev) + static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) { unsigned int offset = paddr & ~PAGE_MASK; From 2161c2485d03520060f6094359b22f33913eefa2 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 24 Apr 2014 11:30:07 -0400 Subject: [PATCH 018/142] 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(-) 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 */ From 265c271c822bd57677e3b286389487fd45e6960d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:44 +0000 Subject: [PATCH 019/142] 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(-) 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, }, }; From 7668fd577bae5bba50e97d257a4cf0c44ca002d3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 13 Apr 2014 20:09:55 +0100 Subject: [PATCH 020/142] ARM: make get_cr()/set_cr() use unsigned long values Signed-off-by: Russell King --- arch/arm/include/asm/cp15.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h index 6493802f880a..d5bf322a0630 100644 --- a/arch/arm/include/asm/cp15.h +++ b/arch/arm/include/asm/cp15.h @@ -52,14 +52,14 @@ extern unsigned long cr_no_alignment; /* defined in entry-armv.S */ extern unsigned long cr_alignment; /* defined in entry-armv.S */ -static inline unsigned int get_cr(void) +static inline unsigned long get_cr(void) { - unsigned int val; + unsigned long val; asm("mrc p15, 0, %0, c1, c0, 0 @ get CR" : "=r" (val) : : "cc"); return val; } -static inline void set_cr(unsigned int val) +static inline void set_cr(unsigned long val) { asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR" : : "r" (val) : "cc"); From 4585eaff634b1bbb09686895221b3645f53f7a60 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 13 Apr 2014 18:47:34 +0100 Subject: [PATCH 021/142] 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(-) 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) From deace4a6b440f2e05f3e073338b28901d02a15c9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 3 May 2014 11:06:55 +0100 Subject: [PATCH 022/142] 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(-) 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. From 3683f44c42e991d313dc301504ee0fca1aeb8580 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 3 May 2014 11:03:28 +0100 Subject: [PATCH 023/142] ARM: stacktrace: avoid listing stacktrace functions in stacktrace While debugging the FEC ethernet driver using stacktrace, it was noticed that the stacktraces always begin as follows: [] save_stack_trace_tsk+0x0/0x98 [] save_stack_trace+0x24/0x28 ... This is because the stack trace code includes the stack frames for itself. This is incorrect behaviour, and also leads to "skip" doing the wrong thing (which is the number of stack frames to avoid recording.) Perversely, it does the right thing when passed a non-current thread. Fix this by ensuring that we have a known constant number of frames above the main stack trace function, and always skip these. Cc: Signed-off-by: Russell King --- arch/arm/kernel/stacktrace.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index af4e8c8a5422..6582c4adc182 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -83,13 +83,16 @@ static int save_trace(struct stackframe *frame, void *d) return trace->nr_entries >= trace->max_entries; } -void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +/* This must be noinline to so that our skip calculation works correctly */ +static noinline void __save_stack_trace(struct task_struct *tsk, + struct stack_trace *trace, unsigned int nosched) { struct stack_trace_data data; struct stackframe frame; data.trace = trace; data.skip = trace->skip; + data.no_sched_functions = nosched; if (tsk != current) { #ifdef CONFIG_SMP @@ -102,7 +105,6 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) trace->entries[trace->nr_entries++] = ULONG_MAX; return; #else - data.no_sched_functions = 1; frame.fp = thread_saved_fp(tsk); frame.sp = thread_saved_sp(tsk); frame.lr = 0; /* recovered from the stack */ @@ -111,11 +113,12 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) } else { register unsigned long current_sp asm ("sp"); - data.no_sched_functions = 0; + /* We don't want this function nor the caller */ + data.skip += 2; frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_sp; frame.lr = (unsigned long)__builtin_return_address(0); - frame.pc = (unsigned long)save_stack_trace_tsk; + frame.pc = (unsigned long)__save_stack_trace; } walk_stackframe(&frame, save_trace, &data); @@ -123,9 +126,14 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) trace->entries[trace->nr_entries++] = ULONG_MAX; } +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +{ + __save_stack_trace(tsk, trace, 1); +} + void save_stack_trace(struct stack_trace *trace) { - save_stack_trace_tsk(current, trace); + __save_stack_trace(current, trace, 0); } EXPORT_SYMBOL_GPL(save_stack_trace); #endif From 07b403415884e961920f55e6db462dff15d9df5a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 3 May 2014 16:17:16 +0100 Subject: [PATCH 024/142] ARM: stacktrace: include exception PC value in stacktrace output When we unwind through an exception stack, include the saved PC value into the stack trace: this fills in an otherwise missed functions from the trace (as indicated below): [] fec_enet_interrupt+0xa0/0xe8 [] handle_irq_event_percpu+0x68/0x228 [] handle_irq_event+0x4c/0x6c [] handle_fasteoi_irq+0xac/0x198 [] generic_handle_irq+0x4c/0x60 [] handle_IRQ+0x40/0x98 [] gic_handle_irq+0x30/0x64 [] __irq_svc+0x40/0x50 [] __do_softirq+0xe0/0x2fc <==== [] irq_exit+0xb0/0x100 [] handle_IRQ+0x44/0x98 [] gic_handle_irq+0x30/0x64 [] __irq_svc+0x40/0x50 [] arch_cpu_idle+0x30/0x38 <==== [] cpu_startup_entry+0xac/0x214 [] rest_init+0x68/0x80 [] start_kernel+0x2fc/0x358 Signed-off-by: Russell King --- arch/arm/kernel/stacktrace.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index 6582c4adc182..5a80ddfe7031 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -3,6 +3,7 @@ #include #include +#include #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) /* @@ -61,6 +62,7 @@ EXPORT_SYMBOL(walk_stackframe); #ifdef CONFIG_STACKTRACE struct stack_trace_data { struct stack_trace *trace; + unsigned long last_pc; unsigned int no_sched_functions; unsigned int skip; }; @@ -69,6 +71,7 @@ static int save_trace(struct stackframe *frame, void *d) { struct stack_trace_data *data = d; struct stack_trace *trace = data->trace; + struct pt_regs *regs; unsigned long addr = frame->pc; if (data->no_sched_functions && in_sched_functions(addr)) @@ -80,6 +83,25 @@ static int save_trace(struct stackframe *frame, void *d) trace->entries[trace->nr_entries++] = addr; + if (trace->nr_entries >= trace->max_entries) + return 1; + + /* + * in_exception_text() is designed to test if the PC is one of + * the functions which has an exception stack above it, but + * unfortunately what is in frame->pc is the return LR value, + * not the saved PC value. So, we need to track the previous + * frame PC value when doing this. + */ + addr = data->last_pc; + data->last_pc = frame->pc; + if (!in_exception_text(addr)) + return 0; + + regs = (struct pt_regs *)frame->sp; + + trace->entries[trace->nr_entries++] = regs->ARM_pc; + return trace->nr_entries >= trace->max_entries; } @@ -91,6 +113,7 @@ static noinline void __save_stack_trace(struct task_struct *tsk, struct stackframe frame; data.trace = trace; + data.last_pc = ULONG_MAX; data.skip = trace->skip; data.no_sched_functions = nosched; From b13b9e98b80fa24460a011ba0378d3fe56137a31 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:45 +0000 Subject: [PATCH 025/142] ARM: l2c: remove unnecessary call to outer_flush_all() outer_disable() is defined to safely turn the L2 cache off without data loss: this means that outer_flush_all() should never be called unless you need to implement some special L2 cache disabling, and even then only from your replacement L2 cache disable function. Acked-by: Barry Song Signed-off-by: Russell King --- arch/arm/mach-prima2/pm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-prima2/pm.c b/arch/arm/mach-prima2/pm.c index c4525a88e5da..96e9bc102117 100644 --- a/arch/arm/mach-prima2/pm.c +++ b/arch/arm/mach-prima2/pm.c @@ -71,7 +71,6 @@ static int sirfsoc_pm_enter(suspend_state_t state) case PM_SUSPEND_MEM: sirfsoc_pre_suspend_power_off(); - outer_flush_all(); outer_disable(); /* go zzz */ cpu_suspend(0, sirfsoc_finish_suspend); From 03a166e22a49350010fc398a8cb9be3e93192fef Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:47 +0000 Subject: [PATCH 026/142] ARM: l2c: avoid calling outer_flush_all() unnecessarily (Spear) Spear calls outer_flush_all() from it's SMP bringup function. This is potentially dangerous as the L2C set/way operations which implement this don't take kindly to concurrent operations. Besides, there's better solutions to this, as implemented on other platforms. Signed-off-by: Russell King --- arch/arm/mach-spear/platsmp.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-spear/platsmp.c b/arch/arm/mach-spear/platsmp.c index c19751fff2c6..fd4297713d67 100644 --- a/arch/arm/mach-spear/platsmp.c +++ b/arch/arm/mach-spear/platsmp.c @@ -20,6 +20,18 @@ #include #include "generic.h" +/* + * Write pen_release in a way that is guaranteed to be visible to all + * observers, irrespective of whether they're taking part in coherency + * or not. This is necessary for the hotplug code to work reliably. + */ +static void write_pen_release(int val) +{ + pen_release = val; + smp_wmb(); + sync_cache_w(&pen_release); +} + static DEFINE_SPINLOCK(boot_lock); static void __iomem *scu_base = IOMEM(VA_SCU_BASE); @@ -30,8 +42,7 @@ static void spear13xx_secondary_init(unsigned int cpu) * let the primary processor know we're out of the * pen, then head off into the C entry point */ - pen_release = -1; - smp_wmb(); + write_pen_release(-1); /* * Synchronise with the boot thread. @@ -58,9 +69,7 @@ static int spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle) * Note that "pen_release" is the hardware CPU ID, whereas * "cpu" is Linux's internal ID. */ - pen_release = cpu; - flush_cache_all(); - outer_flush_all(); + write_pen_release(cpu); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { From cef3d92c5bd54b38ddca48c4394e0991be934385 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 13:38:10 +0000 Subject: [PATCH 027/142] ARM: l2c: omap2: remove ES1.0 support Santosh says: > But we should kill all of that since we long back decided to remove > ES1.0 related code. The mach-omap code alreasy has removed the ES1.0 > compatibility so feel free to remove any specific ES1.0 > related stuff. That silicon is long dead. Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/omap4-common.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 95e171a055f3..48cf74d284ec 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -182,7 +182,7 @@ static void omap4_l2x0_set_debug(unsigned long val) static int __init omap_l2_cache_init(void) { - u32 aux_ctrl = 0; + u32 aux_ctrl; /* * To avoid code running on other OMAPs in @@ -196,27 +196,18 @@ static int __init omap_l2_cache_init(void) if (WARN_ON(!l2cache_base)) return -ENOMEM; - /* - * 16-way associativity, parity disabled - * Way size - 32KB (es1.0) - * Way size - 64KB (es2.0 +) - */ - aux_ctrl = ((1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT) | + /* 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)); - - if (omap_rev() == OMAP4430_REV_ES1_0) { - aux_ctrl |= 0x2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT; - } else { - aux_ctrl |= ((0x3 << L2X0_AUX_CTRL_WAY_SIZE_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)); - } - if (omap_rev() != OMAP4430_REV_ES1_0) - omap_smc1(0x109, aux_ctrl); + (1 << L2X0_AUX_CTRL_EARLY_BRESP_SHIFT); + + omap_smc1(0x109, aux_ctrl); /* Enable PL310 L2 Cache controller */ omap_smc1(0x102, 0x1); From d453ef752cf01e96168ea012016baea0079f5377 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 12:50:53 +0000 Subject: [PATCH 028/142] ARM: l2c: remove unnecessary UL-suffix to mask values They're u32, they're not unsigned long. The UL suffix is not required here. Acked-by: Shawn Guo Signed-off-by: Russell King --- arch/arm/mach-bcm/bcm_5301x.c | 2 +- arch/arm/mach-highbank/highbank.c | 2 +- arch/arm/mach-imx/mach-vf610.c | 2 +- arch/arm/mach-imx/system.c | 2 +- arch/arm/mach-mvebu/board-v7.c | 2 +- arch/arm/mach-rockchip/rockchip.c | 2 +- arch/arm/mach-socfpga/socfpga.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-bcm/bcm_5301x.c b/arch/arm/mach-bcm/bcm_5301x.c index edff69761e04..6bc9c31b1b0b 100644 --- a/arch/arm/mach-bcm/bcm_5301x.c +++ b/arch/arm/mach-bcm/bcm_5301x.c @@ -45,7 +45,7 @@ static void __init bcm5301x_init_early(void) static void __init bcm5301x_dt_init(void) { - l2x0_of_init(0, ~0UL); + l2x0_of_init(0, ~0); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index c7de89b263dd..38e1dc3b4c6e 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -69,7 +69,7 @@ static void __init highbank_init_irq(void) if (IS_ENABLED(CONFIG_CACHE_L2X0) && of_find_compatible_node(NULL, NULL, "arm,pl310-cache")) { highbank_smc1(0x102, 0x1); - l2x0_of_init(0, ~0UL); + l2x0_of_init(0, ~0); outer_cache.disable = highbank_l2x0_disable; } } diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c index 2d8aef5a6efa..6288a9690e78 100644 --- a/arch/arm/mach-imx/mach-vf610.c +++ b/arch/arm/mach-imx/mach-vf610.c @@ -22,7 +22,7 @@ static void __init vf610_init_machine(void) static void __init vf610_init_irq(void) { - l2x0_of_init(0, ~0UL); + l2x0_of_init(0, ~0); irqchip_init(); } diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c index 5e3027d3692f..c6571f1de9fd 100644 --- a/arch/arm/mach-imx/system.c +++ b/arch/arm/mach-imx/system.c @@ -145,6 +145,6 @@ void __init imx_init_l2cache(void) of_node_put(np); out: - l2x0_of_init(0, ~0UL); + l2x0_of_init(0, ~0); } #endif diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c index 333fca8fdc41..c6bd79f64744 100644 --- a/arch/arm/mach-mvebu/board-v7.c +++ b/arch/arm/mach-mvebu/board-v7.c @@ -60,7 +60,7 @@ static void __init mvebu_timer_and_clk_init(void) coherency_init(); BUG_ON(mvebu_mbus_dt_init()); #ifdef CONFIG_CACHE_L2X0 - l2x0_of_init(0, ~0UL); + l2x0_of_init(0, ~0); #endif if (of_machine_is_compatible("marvell,armada375")) diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c index d211d6fa0d98..d252efe3747b 100644 --- a/arch/arm/mach-rockchip/rockchip.c +++ b/arch/arm/mach-rockchip/rockchip.c @@ -26,7 +26,7 @@ static void __init rockchip_dt_init(void) { - l2x0_of_init(0, ~0UL); + l2x0_of_init(0, ~0); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c index d86231e11b34..9bbb8177f247 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c @@ -100,7 +100,7 @@ static void socfpga_cyclone5_restart(enum reboot_mode mode, const char *cmd) static void __init socfpga_cyclone5_init(void) { - l2x0_of_init(0, ~0UL); + l2x0_of_init(0, ~0); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } From bc4f94d85cad6035d02d2bed1b27f9bea7e7b6e6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 10:52:55 +0000 Subject: [PATCH 029/142] ARM: outer cache: add documentation of outer cache functions Add some documentation to cover the outer cache functions so that their requirements can be better understood. Of particular note are the flush_all() and disable() methods which must not be called except in very specific circumstances. Signed-off-by: Russell King --- arch/arm/include/asm/outercache.h | 48 ++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index 0e4420858990..2615b3d9e807 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h @@ -39,35 +39,75 @@ struct outer_cache_fns { extern struct outer_cache_fns outer_cache; #ifdef CONFIG_OUTER_CACHE - +/** + * outer_inv_range - invalidate range of outer cache lines + * @start: starting physical address, inclusive + * @end: end physical address, exclusive + */ static inline void outer_inv_range(phys_addr_t start, phys_addr_t end) { if (outer_cache.inv_range) outer_cache.inv_range(start, end); } + +/** + * outer_clean_range - clean dirty outer cache lines + * @start: starting physical address, inclusive + * @end: end physical address, exclusive + */ static inline void outer_clean_range(phys_addr_t start, phys_addr_t end) { if (outer_cache.clean_range) outer_cache.clean_range(start, end); } + +/** + * outer_flush_range - clean and invalidate outer cache lines + * @start: starting physical address, inclusive + * @end: end physical address, exclusive + */ static inline void outer_flush_range(phys_addr_t start, phys_addr_t end) { if (outer_cache.flush_range) outer_cache.flush_range(start, end); } +/** + * outer_flush_all - clean and invalidate all cache lines in the outer cache + * + * Note: depending on implementation, this may not be atomic - it must + * only be called with interrupts disabled and no other active outer + * cache masters. + * + * It is intended that this function is only used by implementations + * needing to override the outer_cache.disable() method due to security. + * (Some implementations perform this as a clean followed by an invalidate.) + */ static inline void outer_flush_all(void) { if (outer_cache.flush_all) outer_cache.flush_all(); } +/** + * outer_disable - clean, invalidate and disable the outer cache + * + * Disable the outer cache, ensuring that any data contained in the outer + * 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(); } +/** + * outer_resume - restore the cache configuration and re-enable outer cache + * + * Restore any configuration that the cache had when previously enabled, + * and re-enable the outer cache. + */ static inline void outer_resume(void) { if (outer_cache.resume) @@ -89,6 +129,12 @@ static inline void outer_resume(void) { } #endif #ifdef CONFIG_OUTER_CACHE_SYNC +/** + * outer_sync - perform a sync point for outer cache + * + * Ensure that all outer cache operations are complete and any store + * buffers are drained. + */ static inline void outer_sync(void) { if (outer_cache.sync) From 1dc5455f6f0b2422b410cc913e8af32a617ba921 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 16 Apr 2014 15:38:26 +0100 Subject: [PATCH 030/142] ARM: 8028/1: move __fixup_smp out of init section With large kernel builds such as allyesconfig exceeding maximum relative branch offsets, the init section will be too far away to branch to directly. This causes veneers to be added by the linker, but veneers don't work before the MMU is enabled. Fix this by moving __fixup_smp to the .head.text section as it is not very big. Signed-off-by: Rob Herring Signed-off-by: Russell King --- arch/arm/kernel/head.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index f8c08839edf3..73dbee3097e4 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -475,7 +475,7 @@ ENDPROC(__turn_mmu_on) #ifdef CONFIG_SMP_ON_UP - __INIT + __HEAD __fixup_smp: and r3, r9, #0x000f0000 @ architecture version teq r3, #0x000f0000 @ CPU ID supported? From cd000cf650cd43dc0dc37032cb4016985c9dda6c Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 2 May 2014 17:06:02 +0100 Subject: [PATCH 031/142] 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(+) 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. */ From 9581960a40ab0e281b695bf03744c8924ec3b5d0 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 9 May 2014 18:36:27 +0100 Subject: [PATCH 032/142] 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(-) 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 */ From 166aaf396654b533f536f2cf84d7558eb42f1c9f Mon Sep 17 00:00:00 2001 From: Dave Martin Date: Thu, 17 Apr 2014 16:58:39 +0100 Subject: [PATCH 033/142] ARM: 8029/1: mcpm: Rename the power_down_finish() functions to be less confusing The name "power_down_finish" seems to be causing some confusion, because it suggests that this function is responsible for taking some action to cause the specified CPU to complete its power down. This patch renames the affected functions to "wait_for_powerdown" and similar, since this function's intended purpose is just to wait for the hardware to finish a powerdown initiated by a previous cpu_power_down. Signed-off-by: Dave Martin Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/common/mcpm_entry.c | 6 +++--- arch/arm/common/mcpm_platsmp.c | 2 +- arch/arm/include/asm/mcpm.h | 8 ++++---- arch/arm/mach-vexpress/tc2_pm.c | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/common/mcpm_entry.c b/arch/arm/common/mcpm_entry.c index 1e361abc29eb..7522c87e82fc 100644 --- a/arch/arm/common/mcpm_entry.c +++ b/arch/arm/common/mcpm_entry.c @@ -101,14 +101,14 @@ void mcpm_cpu_power_down(void) BUG(); } -int mcpm_cpu_power_down_finish(unsigned int cpu, unsigned int cluster) +int mcpm_wait_for_cpu_powerdown(unsigned int cpu, unsigned int cluster) { int ret; - if (WARN_ON_ONCE(!platform_ops || !platform_ops->power_down_finish)) + if (WARN_ON_ONCE(!platform_ops || !platform_ops->wait_for_powerdown)) return -EUNATCH; - ret = platform_ops->power_down_finish(cpu, cluster); + ret = platform_ops->wait_for_powerdown(cpu, cluster); if (ret) pr_warn("%s: cpu %u, cluster %u failed to power down (%d)\n", __func__, cpu, cluster, ret); diff --git a/arch/arm/common/mcpm_platsmp.c b/arch/arm/common/mcpm_platsmp.c index 177251a4dd9a..92e54d7c6f46 100644 --- a/arch/arm/common/mcpm_platsmp.c +++ b/arch/arm/common/mcpm_platsmp.c @@ -62,7 +62,7 @@ static int mcpm_cpu_kill(unsigned int cpu) cpu_to_pcpu(cpu, &pcpu, &pcluster); - return !mcpm_cpu_power_down_finish(pcpu, pcluster); + return !mcpm_wait_for_cpu_powerdown(pcpu, pcluster); } static int mcpm_cpu_disable(unsigned int cpu) diff --git a/arch/arm/include/asm/mcpm.h b/arch/arm/include/asm/mcpm.h index 608516ebabfe..90ed21942456 100644 --- a/arch/arm/include/asm/mcpm.h +++ b/arch/arm/include/asm/mcpm.h @@ -91,14 +91,14 @@ int mcpm_cpu_power_up(unsigned int cpu, unsigned int cluster); * previously in which case the caller should take appropriate action. * * On success, the CPU is not guaranteed to be truly halted until - * mcpm_cpu_power_down_finish() subsequently returns non-zero for the + * mcpm_wait_for_cpu_powerdown() subsequently returns non-zero for the * specified cpu. Until then, other CPUs should make sure they do not * trash memory the target CPU might be executing/accessing. */ void mcpm_cpu_power_down(void); /** - * mcpm_cpu_power_down_finish - wait for a specified CPU to halt, and + * mcpm_wait_for_cpu_powerdown - wait for a specified CPU to halt, and * make sure it is powered off * * @cpu: CPU number within given cluster @@ -120,7 +120,7 @@ void mcpm_cpu_power_down(void); * - zero if the CPU is in a safely parked state * - nonzero otherwise (e.g., timeout) */ -int mcpm_cpu_power_down_finish(unsigned int cpu, unsigned int cluster); +int mcpm_wait_for_cpu_powerdown(unsigned int cpu, unsigned int cluster); /** * mcpm_cpu_suspend - bring the calling CPU in a suspended state @@ -164,7 +164,7 @@ int mcpm_cpu_powered_up(void); struct mcpm_platform_ops { int (*power_up)(unsigned int cpu, unsigned int cluster); void (*power_down)(void); - int (*power_down_finish)(unsigned int cpu, unsigned int cluster); + int (*wait_for_powerdown)(unsigned int cpu, unsigned int cluster); void (*suspend)(u64); void (*powered_up)(void); }; diff --git a/arch/arm/mach-vexpress/tc2_pm.c b/arch/arm/mach-vexpress/tc2_pm.c index 29e7785a54bc..b743a0ae02ce 100644 --- a/arch/arm/mach-vexpress/tc2_pm.c +++ b/arch/arm/mach-vexpress/tc2_pm.c @@ -209,7 +209,7 @@ static int tc2_core_in_reset(unsigned int cpu, unsigned int cluster) #define POLL_MSEC 10 #define TIMEOUT_MSEC 1000 -static int tc2_pm_power_down_finish(unsigned int cpu, unsigned int cluster) +static int tc2_pm_wait_for_powerdown(unsigned int cpu, unsigned int cluster) { unsigned tries; @@ -290,7 +290,7 @@ static void tc2_pm_powered_up(void) static const struct mcpm_platform_ops tc2_pm_power_ops = { .power_up = tc2_pm_power_up, .power_down = tc2_pm_power_down, - .power_down_finish = tc2_pm_power_down_finish, + .wait_for_powerdown = tc2_pm_wait_for_powerdown, .suspend = tc2_pm_suspend, .powered_up = tc2_pm_powered_up, }; From 72e6ae285a1dbff553734985bedadf409d99c02d Mon Sep 17 00:00:00 2001 From: Victor Kamensky Date: Tue, 29 Apr 2014 04:20:52 +0100 Subject: [PATCH 034/142] 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(-) 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 From 0e0779da2233f2dfc85e9c3a6ea142476d326811 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Thu, 8 May 2014 17:31:40 +0100 Subject: [PATCH 035/142] ARM: 8053/1: kernel: sleep: restore HYP mode configuration in cpu_resume On CPUs with virtualization extensions the kernel installs HYP mode configuration on both primary and secondary cpus upon cold boot. On platforms where CPUs are shutdown in idle paths (ie CPU core gating), when a CPU resumes from low-power states it currently does not execute code that reinstalls the HYP configuration, which means that the kernel cannot run eg KVM properly on such machines. This patch, mirroring cold-boot behaviour, executes position independent code that reinstalls HYP configuration and drops to SVC mode safely on warmboot, so that deep idle states can be enabled in kernel running as hosts on platforms with power management HW. Cc: Christoffer Dall Cc: Dave Martin Cc: Marc Zyngier Cc: Nicolas Pitre Signed-off-by: Lorenzo Pieralisi Acked-by: Marc Zyngier Reviewed-by: Dave Martin Signed-off-by: Russell King --- arch/arm/include/asm/assembler.h | 2 +- arch/arm/kernel/sleep.S | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index b974184f9941..57f0584e8d97 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -312,7 +312,7 @@ * you cannot return to the original mode. */ .macro safe_svcmode_maskall reg:req -#if __LINUX_ARM_ARCH__ >= 6 +#if __LINUX_ARM_ARCH__ >= 6 && !defined(CONFIG_CPU_V7M) mrs \reg , cpsr eor \reg, \reg, #HYP_MODE tst \reg, #MODE_MASK diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S index b907d9b790ab..1b880db2a033 100644 --- a/arch/arm/kernel/sleep.S +++ b/arch/arm/kernel/sleep.S @@ -127,6 +127,10 @@ ENDPROC(cpu_resume_after_mmu) .align ENTRY(cpu_resume) ARM_BE8(setend be) @ ensure we are in BE mode +#ifdef CONFIG_ARM_VIRT_EXT + bl __hyp_stub_install_secondary +#endif + safe_svcmode_maskall r1 mov r1, #0 ALT_SMP(mrc p15, 0, r0, c0, c0, 5) ALT_UP_B(1f) @@ -144,7 +148,6 @@ ARM_BE8(setend be) @ ensure we are in BE mode ldr r0, [r0, #SLEEP_SAVE_SP_PHYS] ldr r0, [r0, r1, lsl #2] - setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set SVC, irqs off @ load phys pgd, stack, resume fn ARM( ldmia r0!, {r1, sp, pc} ) THUMB( ldmia r0!, {r1, r2, r3} ) From 03eff46ce31dbb186fea3eb2016e1c41f000db7e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 9 May 2014 18:34:19 +0100 Subject: [PATCH 036/142] ARM: 8054/1: perf: add support for the Cortex-A17 PMU The Cortex-A17 PMU is identical to that of the A12, so wire up a new compatible string to the existing event structures. Signed-off-by: Will Deacon Signed-off-by: Russell King --- Documentation/devicetree/bindings/arm/pmu.txt | 1 + arch/arm/kernel/perf_event_cpu.c | 1 + arch/arm/kernel/perf_event_v7.c | 12 ++++++++++++ 3 files changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/pmu.txt b/Documentation/devicetree/bindings/arm/pmu.txt index fe5cef8976cb..75ef91d08f3b 100644 --- a/Documentation/devicetree/bindings/arm/pmu.txt +++ b/Documentation/devicetree/bindings/arm/pmu.txt @@ -8,6 +8,7 @@ Required properties: - compatible : should be one of "arm,armv8-pmuv3" + "arm,cortex-a17-pmu" "arm,cortex-a15-pmu" "arm,cortex-a12-pmu" "arm,cortex-a9-pmu" diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c index 51798d7854ac..a71ae1523620 100644 --- a/arch/arm/kernel/perf_event_cpu.c +++ b/arch/arm/kernel/perf_event_cpu.c @@ -221,6 +221,7 @@ static struct notifier_block cpu_pmu_hotplug_notifier = { * PMU platform driver and devicetree bindings. */ static struct of_device_id cpu_pmu_of_device_ids[] = { + {.compatible = "arm,cortex-a17-pmu", .data = armv7_a17_pmu_init}, {.compatible = "arm,cortex-a15-pmu", .data = armv7_a15_pmu_init}, {.compatible = "arm,cortex-a12-pmu", .data = armv7_a12_pmu_init}, {.compatible = "arm,cortex-a9-pmu", .data = armv7_a9_pmu_init}, diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index f4ef3981ed02..2037f7205987 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -1599,6 +1599,13 @@ static int armv7_a12_pmu_init(struct arm_pmu *cpu_pmu) return 0; } +static int armv7_a17_pmu_init(struct arm_pmu *cpu_pmu) +{ + armv7_a12_pmu_init(cpu_pmu); + cpu_pmu->name = "ARMv7 Cortex-A17"; + return 0; +} + /* * Krait Performance Monitor Region Event Selection Register (PMRESRn) * @@ -2021,6 +2028,11 @@ static inline int armv7_a12_pmu_init(struct arm_pmu *cpu_pmu) return -ENODEV; } +static inline int armv7_a17_pmu_init(struct arm_pmu *cpu_pmu) +{ + return -ENODEV; +} + static inline int krait_pmu_init(struct arm_pmu *cpu_pmu) { return -ENODEV; From 1f1d5b745a4617a2cb2ffd8f4a9bc3be664cfc98 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 13:14:38 +0000 Subject: [PATCH 037/142] 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 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(); +} From a65bb925601cf35ef5db54c8a9ad9e6575c6fe8c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:01 +0000 Subject: [PATCH 038/142] 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(-) 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), {} }; From ce84130384badcad2cdbc1e825657d622165f0e6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:03 +0000 Subject: [PATCH 039/142] 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 | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) 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 = { + .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, - .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, }, }; -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, }, }; From c02642bc1010b7ef8a4b87763ab28f5e4ab1d823 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:54 +0000 Subject: [PATCH 040/142] 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(-) 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(); } From 2b2a87a12d2e0aede29e45911aeb0c520066b0c0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 17:19:21 +0000 Subject: [PATCH 041/142] 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(-) 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) From 37abcdb9194001a0c6ccc5508cd84ea8bd92c29c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:50 +0000 Subject: [PATCH 042/142] 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(-) 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) From df5dd4c6e27081bce2c68cdc2e57a93ea998b63e Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:56 +0000 Subject: [PATCH 043/142] 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(-) 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); } From 83841fe1fb0c4316af89ab85d3528702724a33f4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:14 +0000 Subject: [PATCH 044/142] 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(-) 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) From 14b882cfa3f9db3430037dca6038e161eda953a1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:49 +0000 Subject: [PATCH 045/142] 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(-) 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); } From 96054b0a99f4b7104c02e5521ee5c0d7b1fb09bc Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:52 +0000 Subject: [PATCH 046/142] 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(-) 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; } From 9846dfc98f0e3482e3d0df91bea67ead728301ac Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:55 +0000 Subject: [PATCH 047/142] 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(-) 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; From c40e7eb6c0b08fbc905ac1bec516e6f59ffd4d02 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:04 +0000 Subject: [PATCH 048/142] 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(-) 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 From da3627fbda8983e96fb087c358fab4d7661fd97d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:06 +0000 Subject: [PATCH 049/142] 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(-) 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), From 3b8bad5758113df34076dd868b6cab502bd4ee9a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:57 +0000 Subject: [PATCH 050/142] 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(-) 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 = { From 17f3f99fab43ad17ae1adfc724e5ebaca9635902 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 17 Mar 2014 17:15:02 +0000 Subject: [PATCH 051/142] 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(-) 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 */ From 9a07f27bc5ff2e36400e605d99cc1e129582a0ca Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 17 Mar 2014 20:10:31 +0000 Subject: [PATCH 052/142] 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(-) 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); From 40266d6f410a272b76ad861ba0b5ce91d598f606 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:47:59 +0000 Subject: [PATCH 053/142] 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(-) 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 From 75461f5c8483bee543df30b288787fd3369312b8 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:07 +0000 Subject: [PATCH 054/142] 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(-) 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, From cdef8689ef640d5f83e1ac95c6a190f4859c9bf3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:08 +0000 Subject: [PATCH 055/142] 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(-) 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) From b98556f26dca7f7a7401cdb67b77848f1176a379 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:11 +0000 Subject: [PATCH 056/142] 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(-) 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, From 09a5d180ed9d5aeb9bd6b0ba2c63ad4be05cb9b9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:13 +0000 Subject: [PATCH 057/142] 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 | 135 +++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 70 deletions(-) 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)); + void __iomem *base = l2x0_base; - writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base + - L2X0_AUX_CTRL); - - l2x0_inv_all(); - - 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 - */ - 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) & + revision = readl_relaxed(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); - } - } + /* 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); - l2x0_resume(); + /* 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 l2c310_resume(void) +{ + void __iomem *base = l2x0_base; + + if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) { + unsigned revision; + + /* restore pl310 setup */ + writel_relaxed(l2x0_saved_regs.tag_latency, + base + L2X0_TAG_LATENCY_CTRL); + writel_relaxed(l2x0_saved_regs.data_latency, + base + L2X0_DATA_LATENCY_CTRL); + writel_relaxed(l2x0_saved_regs.filter_end, + base + L2X0_ADDR_FILTER_END); + writel_relaxed(l2x0_saved_regs.filter_start, + base + L2X0_ADDR_FILTER_START); + + revision = readl_relaxed(base + L2X0_CACHE_ID) & + L2X0_CACHE_ID_RTL_MASK; + + if (revision >= L310_CACHE_ID_RTL_R2P0) + writel_relaxed(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_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)) { - writel_relaxed(l2x0_saved_regs.aux2_ctrl, - l2x0_base + TAUROS3_AUX2_CTRL); - writel_relaxed(l2x0_saved_regs.prefetch_ctrl, - l2x0_base + L2X0_PREFETCH_CTRL); - } + void __iomem *base = l2x0_base; - l2x0_resume(); + if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) { + writel_relaxed(l2x0_saved_regs.aux2_ctrl, + base + TAUROS3_AUX2_CTRL); + writel_relaxed(l2x0_saved_regs.prefetch_ctrl, + base + L2X0_PREFETCH_CTRL); + + l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8); + } } static const struct l2c_init_data of_tauros3_data __initconst = { From faf9b2e7018b0afede92329c5b35e5d113a07f1c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 22:49:59 +0000 Subject: [PATCH 058/142] 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 | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) 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) -{ - int lockregs; - - 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); -} - 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 */ - l2x0_unlock(readl_relaxed(base + L2X0_CACHE_ID)); + l2c_unlock(base, num_lock); l2x0_inv_all(); From bda0b74e6a5a4ce25198f55889bb321532c63d92 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:16 +0000 Subject: [PATCH 059/142] 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(-) 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) { From 6a28cf59ff1144398d9d32d409ed8cbf1215922d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 18:55:53 +0000 Subject: [PATCH 060/142] 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(-) 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), From 99ca1772e52d8825172100a24e461a0ffe11e125 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 16:48:18 +0000 Subject: [PATCH 061/142] 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(+) 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; From ebd4219f10fbe3938cd36443e240eb6076b811ab Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 19:08:11 +0000 Subject: [PATCH 062/142] 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(+) 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) { From f777332ba7ae42c396b7aabc20bdbeeebb3a63c0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 20:51:47 +0000 Subject: [PATCH 063/142] 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(-) 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), From 733c6bbafdfac62a307ed5ca925889343c5635ac Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 21:29:28 +0000 Subject: [PATCH 064/142] 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(-) 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), From 9081114837742cf7f152c9bccbeeb2a9273183f4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 19:14:13 +0000 Subject: [PATCH 065/142] 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(-) 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, From cf9ea8f130e29915cb441e315f03ab4f64e0d73c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 22:44:38 +0000 Subject: [PATCH 066/142] 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(-) 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; From 051334bdc5252362500a686100d9ec20cbfdcd8a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 23:04:10 +0000 Subject: [PATCH 067/142] 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(-) 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, From 5f47c38704e15f9db356dd799391bc9f9efc4e0c Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 23:07:07 +0000 Subject: [PATCH 068/142] 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(+) 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; From 0493aef4da8231b4b2f2da8dc1784c265e610a7d Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 Mar 2014 23:26:24 +0000 Subject: [PATCH 069/142] 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(-) 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, From c0fe18ba30a62854490b1ac0f7a02145d84153f5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 12:12:11 +0000 Subject: [PATCH 070/142] 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(-) 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) From 8abd259f657d5742f96ffd46ed65feb11c44b1fb Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 17:38:08 +0000 Subject: [PATCH 071/142] 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(-) 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 From a8875a092af5d9f88f6c335dd07d8988e80e1343 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 20:02:06 +0000 Subject: [PATCH 072/142] 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(-) 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; From 1a5a954ce0dd8ba1fc8b5305bcdb6e4cf7d6939b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 20:52:25 +0000 Subject: [PATCH 073/142] 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(-) 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); } From d9d1f3e2d71144348d73210cf9f1fe0b32481c79 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 17 Mar 2014 12:59:08 +0000 Subject: [PATCH 074/142] 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(+) 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) From ddf7d79bc739c44f7e7cdffc9eb5d94aa213f53e Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 28 Mar 2014 14:18:35 +0000 Subject: [PATCH 075/142] 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(-) 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,14 +779,18 @@ 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); + outer_cache = fns; + + /* + * 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); + /* Re-read it in case some bits are reserved. */ aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); - /* Save the value for resuming. */ - l2x0_saved_regs.aux_ctrl = aux; - - outer_cache = fns; - pr_info("%s cache controller enabled, %d ways, %d kB\n", data->type, ways, l2x0_size >> 10); pr_info("%s: CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n", @@ -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 = From 4374d64933b1d0f0ebbad064289ef44b869d77c1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 15:39:09 +0000 Subject: [PATCH 076/142] 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(-) 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, From 36bccb11a4ac7cc9d190c3062945f1c911a62801 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 12:44:41 +0000 Subject: [PATCH 077/142] ARM: l2c: remove platforms/SoCs setting early BRESP Since we now automatically enable early BRESP in core L2C-310 code when we detect a Cortex-A9, we don't need platforms/SoCs to set this bit explicitly. Instead, they should seek to preserve the value of bit 30 in the auxiliary control register. Acked-by: Tony Lindgren Acked-by: Stephen Warren Signed-off-by: Russell King --- arch/arm/mach-berlin/berlin.c | 2 +- arch/arm/mach-exynos/exynos.c | 4 ++-- arch/arm/mach-omap2/omap4-common.c | 3 +-- arch/arm/mach-shmobile/board-armadillo800eva-reference.c | 4 ++-- arch/arm/mach-shmobile/board-armadillo800eva.c | 4 ++-- arch/arm/mach-shmobile/board-kzm9g-reference.c | 4 ++-- arch/arm/mach-shmobile/board-kzm9g.c | 4 ++-- arch/arm/mach-shmobile/setup-r8a7778.c | 4 ++-- arch/arm/mach-shmobile/setup-r8a7779.c | 4 ++-- arch/arm/mach-spear/spear13xx.c | 2 +- arch/arm/mach-tegra/tegra.c | 4 ++-- 11 files changed, 19 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-berlin/berlin.c b/arch/arm/mach-berlin/berlin.c index 025bcb5473eb..6709d2a6bec8 100644 --- a/arch/arm/mach-berlin/berlin.c +++ b/arch/arm/mach-berlin/berlin.c @@ -24,7 +24,7 @@ static void __init berlin_init_machine(void) * with DT probing for L2CCs, berlin_init_machine can be removed. * Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc */ - l2x0_of_init(0x70c00000, 0xfeffffff); + l2x0_of_init(0x30c00000, 0xfeffffff); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index b32a907d021d..e6828fb46034 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -32,8 +32,8 @@ #include "mfc.h" #include "regs-pmu.h" -#define L2_AUX_VAL 0x7C470001 -#define L2_AUX_MASK 0xC200ffff +#define L2_AUX_VAL 0x3c470001 +#define L2_AUX_MASK 0xc200ffff static struct map_desc exynos4_iodesc[] __initdata = { { diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 1dfb806da33e..fb149b03d56d 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -204,8 +204,7 @@ static int __init omap_l2_cache_init(void) 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; + L310_AUX_CTRL_INSTR_PREFETCH; omap_smc1(0x109, aux_ctrl); diff --git a/arch/arm/mach-shmobile/board-armadillo800eva-reference.c b/arch/arm/mach-shmobile/board-armadillo800eva-reference.c index 57d1a78367b6..34e7f3c17dd2 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva-reference.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva-reference.c @@ -164,8 +164,8 @@ static void __init eva_init(void) r8a7740_meram_workaround(); #ifdef CONFIG_CACHE_L2X0 - /* Early BRESP enable, Shared attribute override enable, 32K*8way */ - l2x0_init(IOMEM(0xf0002000), 0x40440000, 0x82000fff); + /* Shared attribute override enable, 32K*8way */ + l2x0_init(IOMEM(0xf0002000), 0x00440000, 0xc2000fff); #endif r8a7740_add_standard_devices_dt(); diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 486063db2a2f..a01f867227ac 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -1271,8 +1271,8 @@ static void __init eva_init(void) #ifdef CONFIG_CACHE_L2X0 - /* Early BRESP enable, Shared attribute override enable, 32K*8way */ - l2x0_init(IOMEM(0xf0002000), 0x40440000, 0x82000fff); + /* Shared attribute override enable, 32K*8way */ + l2x0_init(IOMEM(0xf0002000), 0x00440000, 0xc2000fff); #endif i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); diff --git a/arch/arm/mach-shmobile/board-kzm9g-reference.c b/arch/arm/mach-shmobile/board-kzm9g-reference.c index 598e32488410..85873f186d77 100644 --- a/arch/arm/mach-shmobile/board-kzm9g-reference.c +++ b/arch/arm/mach-shmobile/board-kzm9g-reference.c @@ -36,8 +36,8 @@ static void __init kzm_init(void) sh73a0_add_standard_devices_dt(); #ifdef CONFIG_CACHE_L2X0 - /* Early BRESP enable, Shared attribute override enable, 64K*8way */ - l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff); + /* Shared attribute override enable, 64K*8way */ + l2x0_init(IOMEM(0xf0100000), 0x00460000, 0xc2000fff); #endif } diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index 03dc3ac84502..ea9bf39fdc10 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c @@ -876,8 +876,8 @@ static void __init kzm_init(void) gpio_request_one(223, GPIOF_IN, NULL); /* IRQ8 */ #ifdef CONFIG_CACHE_L2X0 - /* Early BRESP enable, Shared attribute override enable, 64K*8way */ - l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff); + /* Shared attribute override enable, 64K*8way */ + l2x0_init(IOMEM(0xf0100000), 0x00460000, 0xc2000fff); #endif i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c index 6d694526e4ca..3a8e5316671e 100644 --- a/arch/arm/mach-shmobile/setup-r8a7778.c +++ b/arch/arm/mach-shmobile/setup-r8a7778.c @@ -298,10 +298,10 @@ void __init r8a7778_add_dt_devices(void) void __iomem *base = ioremap_nocache(0xf0100000, 0x1000); if (base) { /* - * Early BRESP enable, Shared attribute override enable, 64K*16way + * Shared attribute override enable, 64K*16way * don't call iounmap(base) */ - l2x0_init(base, 0x40470000, 0x82000fff); + l2x0_init(base, 0x00470000, 0xc2000fff); } #endif diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index 8e860b36997a..91c90bf0ae83 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c @@ -700,8 +700,8 @@ static struct platform_device *r8a7779_standard_devices[] __initdata = { void __init r8a7779_add_standard_devices(void) { #ifdef CONFIG_CACHE_L2X0 - /* Early BRESP enable, Shared attribute override enable, 64K*16way */ - l2x0_init(IOMEM(0xf0100000), 0x40470000, 0x82000fff); + /* Shared attribute override enable, 64K*16way */ + l2x0_init(IOMEM(0xf0100000), 0x00470000, 0xc2000fff); #endif r8a7779_pm_init(); diff --git a/arch/arm/mach-spear/spear13xx.c b/arch/arm/mach-spear/spear13xx.c index 92860fa01668..dcb300443b66 100644 --- a/arch/arm/mach-spear/spear13xx.c +++ b/arch/arm/mach-spear/spear13xx.c @@ -46,7 +46,7 @@ void __init spear13xx_l2x0_init(void) */ 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); + l2x0_init(VA_L2CC_BASE, 0x30a60001, 0xfe00ffff); } /* diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index 6191603379e1..ecbb5411a104 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c @@ -89,9 +89,9 @@ static void __init tegra_init_cache(void) cache_type = readl(p + L2X0_CACHE_TYPE); aux_ctrl = (cache_type & 0x700) << (17-8); - aux_ctrl |= 0x7C400001; + aux_ctrl |= 0x3c400001; - ret = l2x0_of_init(aux_ctrl, 0x8200c3fe); + ret = l2x0_of_init(aux_ctrl, 0xc200c3fe); if (!ret) l2x0_saved_regs_addr = virt_to_phys(&l2x0_saved_regs); #endif From 3a43b581dac1e5e70169dd6267bef4503ec3da21 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 28 Mar 2014 14:22:04 +0000 Subject: [PATCH 078/142] 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(+) 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); } From a4b041a0e25c6e9ccd809b3cb68a98c816e0c967 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 11 Apr 2014 00:48:25 +0100 Subject: [PATCH 079/142] 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(-) 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, From 805604ef8596968e5f251c69fd92bd3b8f466317 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:24:10 +0100 Subject: [PATCH 080/142] ARM: l2c: add platform independent core L2 cache OF initialisation Add a hook into the core ARM code to perform L2 cache initialisation in a platform independent manner. Platforms still get to indicate their auxiliary control register values and mask, but the initialisation call will now be made from generic code. Signed-off-by: Russell King --- arch/arm/include/asm/mach/arch.h | 3 +++ arch/arm/kernel/irq.c | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index 17a3fa2979e8..5249cc3c52f4 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h @@ -45,6 +45,9 @@ struct machine_desc { unsigned char reserve_lp1 :1; /* never has lp1 */ unsigned char reserve_lp2 :1; /* never has lp2 */ enum reboot_mode reboot_mode; /* default restart mode */ + unsigned l2c_aux_val; /* L2 cache aux value */ + unsigned l2c_aux_mask; /* L2 cache aux mask */ + void (*l2c_write_sec)(unsigned long, unsigned); struct smp_operations *smp; /* SMP operations */ bool (*smp_init)(void); void (*fixup)(struct tag *, char **, diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 9723d17b8f38..2c4257604513 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -115,10 +116,21 @@ EXPORT_SYMBOL_GPL(set_irq_flags); void __init init_IRQ(void) { + int ret; + if (IS_ENABLED(CONFIG_OF) && !machine_desc->init_irq) irqchip_init(); else machine_desc->init_irq(); + + if (IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_CACHE_L2X0) && + (machine_desc->l2c_aux_mask || machine_desc->l2c_aux_val)) { + outer_cache.write_sec = machine_desc->l2c_write_sec; + ret = l2x0_of_init(machine_desc->l2c_aux_val, + machine_desc->l2c_aux_mask); + if (ret) + pr_err("L2C: failed to init: %d\n", ret); + } } #ifdef CONFIG_MULTI_IRQ_HANDLER From de7e75326c05c10ebd96aed9440c870f0ff1e34f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Apr 2014 11:39:57 +0100 Subject: [PATCH 081/142] 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 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 - . From d458773fb3c456d0e2e860fece8602b062e2f7a0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:27:59 +0100 Subject: [PATCH 082/142] ARM: l2c: bcm_5301x: convert to generic l2c OF initialisation Remove the explicit call to l2x0_of_init(), converting to the generic infrastructure instead. We can remove the explicit machine init too as this becomes identical to the generic version. Signed-off-by: Russell King --- arch/arm/mach-bcm/bcm_5301x.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-bcm/bcm_5301x.c b/arch/arm/mach-bcm/bcm_5301x.c index 6bc9c31b1b0b..e9bcbdbce555 100644 --- a/arch/arm/mach-bcm/bcm_5301x.c +++ b/arch/arm/mach-bcm/bcm_5301x.c @@ -43,19 +43,14 @@ static void __init bcm5301x_init_early(void) "imprecise external abort"); } -static void __init bcm5301x_dt_init(void) -{ - l2x0_of_init(0, ~0); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -} - static const char __initconst *bcm5301x_dt_compat[] = { "brcm,bcm4708", NULL, }; DT_MACHINE_START(BCM5301X, "BCM5301X") + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, .init_early = bcm5301x_init_early, - .init_machine = bcm5301x_dt_init, .dt_compat = bcm5301x_dt_compat, MACHINE_END From a048711c0b3701ee22efd74022cb1f548a52842c Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:57:21 +0100 Subject: [PATCH 083/142] ARM: l2c: berlin: convert to generic l2c OF initialisation Remove the explicit call to l2x0_of_init(), converting to the generic infrastructure instead. We can remove the explicit machine init too as this becomes identical to the generic version. Acked-by: Sebastian Hesselbarth Signed-off-by: Russell King --- arch/arm/mach-berlin/berlin.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-berlin/berlin.c b/arch/arm/mach-berlin/berlin.c index 6709d2a6bec8..ac181c6797ee 100644 --- a/arch/arm/mach-berlin/berlin.c +++ b/arch/arm/mach-berlin/berlin.c @@ -18,16 +18,6 @@ #include #include -static void __init berlin_init_machine(void) -{ - /* - * with DT probing for L2CCs, berlin_init_machine can be removed. - * Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc - */ - l2x0_of_init(0x30c00000, 0xfeffffff); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -} - static const char * const berlin_dt_compat[] = { "marvell,berlin", NULL, @@ -35,5 +25,10 @@ static const char * const berlin_dt_compat[] = { DT_MACHINE_START(BERLIN_DT, "Marvell Berlin") .dt_compat = berlin_dt_compat, - .init_machine = berlin_init_machine, + /* + * with DT probing for L2CCs, berlin_init_machine can be removed. + * Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc + */ + .l2c_aux_val = 0x30c00000, + .l2c_aux_mask = 0xfeffffff, MACHINE_END From 24cb65feab42ac0cc26464ac4b7a38c0ab7ce173 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 12:06:27 +0000 Subject: [PATCH 084/142] ARM: l2c: cns3xxx: remove cache size override The cache size should already be present in the L2 cache auxiliary control register: it is part of the integration process to configure the hardware IP. Most platforms get this right, yet still many cargo-cult program, and assume that they always need specifying to the L2 cache code. Remove them so we can find out which really need this. Signed-off-by: Russell King --- arch/arm/mach-cns3xxx/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c index 5c31b2638c01..f85449a6accd 100644 --- a/arch/arm/mach-cns3xxx/core.c +++ b/arch/arm/mach-cns3xxx/core.c @@ -290,7 +290,7 @@ void __init cns3xxx_l2x0_init(void) writel(val, base + L310_DATA_LATENCY_CTRL); /* 32 KiB, 8-way, parity disable */ - l2x0_init(base, 0x00540000, 0xfe000fff); + l2x0_init(base, 0x00500000, 0xfe0f0fff); } #endif /* CONFIG_CACHE_L2X0 */ From dfbdd3d55403ebd29a355e907e53576ce57c6d96 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 12:07:34 +0000 Subject: [PATCH 085/142] ARM: l2c: exynos: remove cache size override The cache size should already be present in the L2 cache auxiliary control register: it is part of the integration process to configure the hardware IP. Most platforms get this right, yet still many cargo-cult program, and assume that they always need specifying to the L2 cache code. Remove them so we can find out which really need this. Signed-off-by: Russell King --- arch/arm/mach-exynos/exynos.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index e6828fb46034..a51bf25e7523 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -32,9 +32,6 @@ #include "mfc.h" #include "regs-pmu.h" -#define L2_AUX_VAL 0x3c470001 -#define L2_AUX_MASK 0xc200ffff - static struct map_desc exynos4_iodesc[] __initdata = { { .virtual = (unsigned long)S3C_VA_SYS, @@ -323,7 +320,7 @@ static int __init exynos4_l2x0_cache_init(void) { int ret; - ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK); + ret = l2x0_of_init(0x3c400001, 0xc20fffff); if (ret) return ret; From 25a9ef63cd2beb248e51bd192df19fbe5cf20545 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Apr 2014 11:45:34 +0100 Subject: [PATCH 086/142] ARM: l2c: exynos: convert to common l2c310 early resume functionality Signed-off-by: Russell King --- arch/arm/mach-exynos/common.h | 1 - arch/arm/mach-exynos/exynos.c | 12 +----------- arch/arm/mach-exynos/sleep.S | 30 +----------------------------- arch/arm/plat-samsung/s5p-sleep.S | 1 - 4 files changed, 2 insertions(+), 42 deletions(-) diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 9ef3f83efaff..88c619d1e145 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -55,7 +55,6 @@ enum sys_powerdown { NUM_SYS_POWERDOWN, }; -extern unsigned long l2x0_regs_phys; struct exynos_pmu_conf { void __iomem *reg; unsigned int val[NUM_SYS_POWERDOWN]; diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index a51bf25e7523..fbfc29df3299 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -318,17 +318,7 @@ core_initcall(exynos_core_init); static int __init exynos4_l2x0_cache_init(void) { - int ret; - - ret = l2x0_of_init(0x3c400001, 0xc20fffff); - if (ret) - return ret; - - if (IS_ENABLED(CONFIG_S5P_SLEEP)) { - l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs); - clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long)); - } - return 0; + return l2x0_of_init(0x3c400001, 0xc20fffff); } early_initcall(exynos4_l2x0_cache_init); diff --git a/arch/arm/mach-exynos/sleep.S b/arch/arm/mach-exynos/sleep.S index 7e0af530511e..108a45f4bb62 100644 --- a/arch/arm/mach-exynos/sleep.S +++ b/arch/arm/mach-exynos/sleep.S @@ -16,8 +16,6 @@ */ #include -#include -#include #define CPU_MASK 0xff0ffff0 #define CPU_CORTEX_A9 0x410fc090 @@ -53,33 +51,7 @@ ENTRY(exynos_cpu_resume) and r0, r0, r1 ldr r1, =CPU_CORTEX_A9 cmp r0, r1 - bne skip_l2_resume - adr r0, l2x0_regs_phys - ldr r0, [r0] - cmp r0, #0 - beq skip_l2_resume - ldr r1, [r0, #L2X0_R_PHY_BASE] - ldr r2, [r1, #L2X0_CTRL] - tst r2, #0x1 - bne skip_l2_resume - ldr r2, [r0, #L2X0_R_AUX_CTRL] - str r2, [r1, #L2X0_AUX_CTRL] - ldr r2, [r0, #L2X0_R_TAG_LATENCY] - str r2, [r1, #L310_TAG_LATENCY_CTRL] - ldr r2, [r0, #L2X0_R_DATA_LATENCY] - str r2, [r1, #L310_DATA_LATENCY_CTRL] - ldr r2, [r0, #L2X0_R_PREFETCH_CTRL] - str r2, [r1, #L310_PREFETCH_CTRL] - ldr r2, [r0, #L2X0_R_PWR_CTRL] - str r2, [r1, #L310_POWER_CTRL] - mov r2, #1 - str r2, [r1, #L2X0_CTRL] -skip_l2_resume: + bleq l2c310_early_resume #endif b cpu_resume ENDPROC(exynos_cpu_resume) -#ifdef CONFIG_CACHE_L2X0 - .globl l2x0_regs_phys -l2x0_regs_phys: - .long 0 -#endif diff --git a/arch/arm/plat-samsung/s5p-sleep.S b/arch/arm/plat-samsung/s5p-sleep.S index c5001659bdf8..25c68ceb9e2b 100644 --- a/arch/arm/plat-samsung/s5p-sleep.S +++ b/arch/arm/plat-samsung/s5p-sleep.S @@ -22,7 +22,6 @@ */ #include -#include .data .align From 15b0bc4041baf0444e4ddd969849bb1d91703f59 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:54:08 +0100 Subject: [PATCH 087/142] ARM: l2c: exynos: convert to generic l2c OF initialisation (and thereby fix it) exynos was unconditionally calling the L2 cache initialisation from an early_initcall. This breaks multiplatform kernels. Thankfully, converting to generic l2c initialisation fixes this. Signed-off-by: Russell King --- arch/arm/mach-exynos/exynos.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index fbfc29df3299..a763c0862da9 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -316,12 +316,6 @@ static int __init exynos_core_init(void) } core_initcall(exynos_core_init); -static int __init exynos4_l2x0_cache_init(void) -{ - return l2x0_of_init(0x3c400001, 0xc20fffff); -} -early_initcall(exynos4_l2x0_cache_init); - static void __init exynos_dt_machine_init(void) { struct device_node *i2c_np; @@ -387,6 +381,8 @@ static void __init exynos_reserve(void) DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)") /* Maintainer: Thomas Abraham */ /* Maintainer: Kukjin Kim */ + .l2c_aux_val = 0x3c400001, + .l2c_aux_mask = 0xc20fffff, .smp = smp_ops(exynos_smp_ops), .map_io = exynos_init_io, .init_early = exynos_firmware_init, From 0074fb2c9e75acfdea391e6962c4be98444b4792 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 17:53:23 +0000 Subject: [PATCH 088/142] ARM: l2c: highbank: implement new write_sec method With the write_sec method, we no longer need to override the default L2C disable method. This can be handled via the write_sec method instead. Signed-off-by: Russell King --- arch/arm/mach-highbank/highbank.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index 38e1dc3b4c6e..4712aed3d9f6 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -51,11 +51,13 @@ static void __init highbank_scu_map_io(void) } -static void highbank_l2x0_disable(void) +static void highbank_l2c310_write_sec(unsigned long val, unsigned reg) { - outer_flush_all(); - /* Disable PL310 L2 Cache controller */ - highbank_smc1(0x102, 0x0); + if (reg == L2X0_CTRL) + highbank_smc1(0x102, val); + else + WARN_ONCE(1, "Highbank L2C310: ignoring write to reg 0x%x\n", + reg); } static void __init highbank_init_irq(void) @@ -69,8 +71,8 @@ static void __init highbank_init_irq(void) if (IS_ENABLED(CONFIG_CACHE_L2X0) && of_find_compatible_node(NULL, NULL, "arm,pl310-cache")) { highbank_smc1(0x102, 0x1); + outer_cache.write_sec = highbank_l2c310_write_sec; l2x0_of_init(0, ~0); - outer_cache.disable = highbank_l2x0_disable; } } From e761f6f332afe3356714a0d0eaf5ec1ebd8aab50 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 17 Mar 2014 22:42:48 +0000 Subject: [PATCH 089/142] ARM: l2c: highbank: remove explicit SMI call in L2 cache initialisation Now that highbank uses the write_sec method, we don't need to enable the L2 cache in SoC specific code; this can be done via the normal mechanisms in the L2C code. Checking with Rob Herring: > > Can we kill the "highbank_smc1(0x102, 0x1);" here? That means > > l2x0_of_init() will see the L2 cache disabled, and will try to enable > > it via the write_sec hook, so it should do the right thing. > > Yes, that should work. You should be able to just call l2x0_of_init > unconditionally. The condition was really to just avoid the smc on > Midway which does get handled on h/w, but not if running virtualized. So also drop the DT check too. I'm leaving the config check in place so that if L2 is disabled, the write_sec hook can be optimised away. Signed-off-by: Russell King --- arch/arm/mach-highbank/highbank.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index 4712aed3d9f6..245e588859ec 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -68,9 +68,7 @@ static void __init highbank_init_irq(void) highbank_scu_map_io(); /* Enable PL310 L2 Cache controller */ - if (IS_ENABLED(CONFIG_CACHE_L2X0) && - of_find_compatible_node(NULL, NULL, "arm,pl310-cache")) { - highbank_smc1(0x102, 0x1); + if (IS_ENABLED(CONFIG_CACHE_L2X0)) { outer_cache.write_sec = highbank_l2c310_write_sec; l2x0_of_init(0, ~0); } From 513b9a08f82c70228ace549e6f990012244b9f18 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:34:11 +0100 Subject: [PATCH 090/142] ARM: l2c: highbank: convert to generic l2c OF initialisation Remove the explicit call to l2x0_of_init(), converting to the generic infrastructure instead. Signed-off-by: Russell King --- arch/arm/mach-highbank/highbank.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index 245e588859ec..8c35ae4ff176 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c @@ -66,12 +66,6 @@ static void __init highbank_init_irq(void) if (of_find_compatible_node(NULL, NULL, "arm,cortex-a9")) highbank_scu_map_io(); - - /* Enable PL310 L2 Cache controller */ - if (IS_ENABLED(CONFIG_CACHE_L2X0)) { - outer_cache.write_sec = highbank_l2c310_write_sec; - l2x0_of_init(0, ~0); - } } static void highbank_power_off(void) @@ -185,6 +179,9 @@ DT_MACHINE_START(HIGHBANK, "Highbank") #if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE) .dma_zone_size = (4ULL * SZ_1G), #endif + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, + .l2c_write_sec = highbank_l2c310_write_sec, .init_irq = highbank_init_irq, .init_machine = highbank_init, .dt_compat = highbank_match, From 28ed53f2227a98fd5af78dfcea28170eadfc991f Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 28 Mar 2014 14:36:38 +0000 Subject: [PATCH 091/142] ARM: l2c: imx: remove direct write to power control register Now that we handle this in core code, we don't need platforms enabling the low power modes directly. Acked-by: Shawn Guo Signed-off-by: Russell King --- arch/arm/mach-imx/system.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c index 59013a81107b..3b0733edb68c 100644 --- a/arch/arm/mach-imx/system.c +++ b/arch/arm/mach-imx/system.c @@ -138,8 +138,6 @@ void __init imx_init_l2cache(void) if (cpu_is_imx6q()) val &= ~(1 << 30 | 1 << 23); 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); From f5a5f430d9ae1c118b16d0ae9c74109eb622f7df Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Apr 2014 11:55:03 +0100 Subject: [PATCH 092/142] ARM: l2c: imx: convert to common l2c310 early resume functionality Signed-off-by: Russell King --- arch/arm/mach-imx/suspend-imx6.S | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S index 20048ff05739..fe123b079c05 100644 --- a/arch/arm/mach-imx/suspend-imx6.S +++ b/arch/arm/mach-imx/suspend-imx6.S @@ -334,28 +334,10 @@ ENDPROC(imx6_suspend) * turned into relative ones. */ -#ifdef CONFIG_CACHE_L2X0 - .macro pl310_resume - adr r0, l2x0_saved_regs_offset - ldr r2, [r0] - add r2, r2, r0 - ldr r0, [r2, #L2X0_R_PHY_BASE] @ get physical base of l2x0 - ldr r1, [r2, #L2X0_R_AUX_CTRL] @ get aux_ctrl value - str r1, [r0, #L2X0_AUX_CTRL] @ restore aux_ctrl - mov r1, #0x1 - str r1, [r0, #L2X0_CTRL] @ re-enable L2 - .endm - -l2x0_saved_regs_offset: - .word l2x0_saved_regs - . - -#else - .macro pl310_resume - .endm -#endif - ENTRY(v7_cpu_resume) bl v7_invalidate_l1 - pl310_resume +#ifdef CONFIG_CACHE_L2X0 + bl l2c310_early_resume +#endif b cpu_resume ENDPROC(v7_cpu_resume) From b9f71aad7cdb826246d4d6e5bd7ff99ffc4f3278 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:48:14 +0100 Subject: [PATCH 093/142] ARM: l2c: imx vf610: convert to generic l2c OF initialisation Remove the explicit call to l2x0_of_init(), converting to the generic infrastructure instead. Since the .init_irq method only calls irqchip_init(), we can remove that too as the generic code will take care of that. Signed-off-by: Russell King --- arch/arm/mach-imx/mach-vf610.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c index 6288a9690e78..c44602758120 100644 --- a/arch/arm/mach-imx/mach-vf610.c +++ b/arch/arm/mach-imx/mach-vf610.c @@ -20,19 +20,14 @@ static void __init vf610_init_machine(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } -static void __init vf610_init_irq(void) -{ - l2x0_of_init(0, ~0); - irqchip_init(); -} - static const char *vf610_dt_compat[] __initconst = { "fsl,vf610", NULL, }; DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)") - .init_irq = vf610_init_irq, + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, .init_machine = vf610_init_machine, .dt_compat = vf610_dt_compat, .restart = mxc_restart, From 9847cf0403c7c8a054fd48f9833d408b468554b6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:44:47 +0100 Subject: [PATCH 094/142] ARM: l2c: mvebu: convert to generic l2c OF initialisation Remove the explicit call to l2x0_of_init(), converting to the generic infrastructure instead. Acked-by: Jason Cooper Signed-off-by: Russell King --- arch/arm/mach-mvebu/board-v7.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c index c6bd79f64744..48169caa56ea 100644 --- a/arch/arm/mach-mvebu/board-v7.c +++ b/arch/arm/mach-mvebu/board-v7.c @@ -59,9 +59,6 @@ static void __init mvebu_timer_and_clk_init(void) clocksource_of_init(); coherency_init(); BUG_ON(mvebu_mbus_dt_init()); -#ifdef CONFIG_CACHE_L2X0 - l2x0_of_init(0, ~0); -#endif if (of_machine_is_compatible("marvell,armada375")) hook_fault_code(16 + 6, armada_375_external_abort_wa, SIGBUS, 0, @@ -109,6 +106,8 @@ static const char * const armada_370_xp_dt_compat[] = { }; DT_MACHINE_START(ARMADA_370_XP_DT, "Marvell Armada 370/XP (Device Tree)") + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, .smp = smp_ops(armada_xp_smp_ops), .init_machine = mvebu_dt_init, .init_time = mvebu_timer_and_clk_init, @@ -122,6 +121,8 @@ static const char * const armada_375_dt_compat[] = { }; DT_MACHINE_START(ARMADA_375_DT, "Marvell Armada 375 (Device Tree)") + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, .init_time = mvebu_timer_and_clk_init, .restart = mvebu_restart, .dt_compat = armada_375_dt_compat, @@ -134,6 +135,8 @@ static const char * const armada_38x_dt_compat[] = { }; DT_MACHINE_START(ARMADA_38X_DT, "Marvell Armada 380/385 (Device Tree)") + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, .init_time = mvebu_timer_and_clk_init, .restart = mvebu_restart, .dt_compat = armada_38x_dt_compat, From 42708e37a3b68da1041ac79d106945c3c90e630a Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 12:10:16 +0000 Subject: [PATCH 095/142] ARM: l2c: nomadik: remove cache size override The cache size should already be present in the L2 cache auxiliary control register: it is part of the integration process to configure the hardware IP. Most platforms get this right, yet still many cargo-cult program, and assume that they always need specifying to the L2 cache code. Remove them so we can find out which really need this. Acked-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-nomadik/cpu-8815.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index 4a1065e41e9c..0f245bcc6b7e 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -147,7 +147,7 @@ static void __init cpu8815_init_of(void) { #ifdef CONFIG_CACHE_L2X0 /* At full speed latency must be >=2, so 0x249 in low bits */ - l2x0_of_init(0x00730249, 0xfe000fff); + l2x0_of_init(0x00700249, 0xfe0fefff); #endif of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } From 8523f615377f661dac7a784193fa842d45dd3fd9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:27:59 +0100 Subject: [PATCH 096/142] ARM: l2c: nomadik: convert to generic l2c OF initialisation Remove the explicit call to l2x0_of_init(), converting to the generic infrastructure instead. This also allows us to eliminate the .init_machine function as it is identical to the generic version. Acked-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-nomadik/cpu-8815.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index 0f245bcc6b7e..9116ca476d7c 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -143,23 +143,16 @@ static int __init cpu8815_mmcsd_init(void) } device_initcall(cpu8815_mmcsd_init); -static void __init cpu8815_init_of(void) -{ -#ifdef CONFIG_CACHE_L2X0 - /* At full speed latency must be >=2, so 0x249 in low bits */ - l2x0_of_init(0x00700249, 0xfe0fefff); -#endif - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -} - static const char * cpu8815_board_compat[] = { "calaosystems,usb-s8815", NULL, }; DT_MACHINE_START(NOMADIK_DT, "Nomadik STn8815") + /* At full speed latency must be >=2, so 0x249 in low bits */ + .l2c_aux_val = 0x00700249, + .l2c_aux_mask = 0xfe0fefff, .map_io = cpu8815_map_io, - .init_machine = cpu8815_init_of, .restart = cpu8815_restart, .dt_compat = cpu8815_board_compat, MACHINE_END From 36827edd2e3711749ff472949b9cf94f4cb700e9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 17:45:56 +0000 Subject: [PATCH 097/142] ARM: l2c: omap2: implement new write_sec method With the write_sec method, we no longer need to override the default L2C disable method, and we no longer need the L2C set_debug method. Both of these can be handled via the write_sec method. Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/omap4-common.c | 42 ++++++++++++++++++------------ 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index fb149b03d56d..44472b7469c5 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -167,17 +167,33 @@ void __iomem *omap4_get_l2cache_base(void) return l2cache_base; } -static void omap4_l2x0_disable(void) +static void omap4_l2c310_write_sec(unsigned long val, unsigned reg) { - outer_flush_all(); - /* Disable PL310 L2 Cache controller */ - omap_smc1(0x102, 0x0); -} + unsigned smc_op; -static void omap4_l2x0_set_debug(unsigned long val) -{ - /* Program PL310 L2 Cache controller debug register */ - omap_smc1(0x100, val); + switch (reg) { + case L2X0_CTRL: + smc_op = OMAP4_MON_L2X0_CTRL_INDEX; + break; + + case L2X0_AUX_CTRL: + smc_op = OMAP4_MON_L2X0_AUXCTRL_INDEX; + break; + + case L2X0_DEBUG_CTRL: + smc_op = OMAP4_MON_L2X0_DBG_CTRL_INDEX; + break; + + case L310_PREFETCH_CTRL: + smc_op = OMAP4_MON_L2X0_PREFETCH_INDEX; + break; + + default: + WARN_ONCE(1, "OMAP L2C310: ignoring write to reg 0x%x\n", reg); + return; + } + + omap_smc1(smc_op, val); } static int __init omap_l2_cache_init(void) @@ -211,18 +227,12 @@ static int __init omap_l2_cache_init(void) /* Enable PL310 L2 Cache controller */ omap_smc1(0x102, 0x1); + outer_cache.write_sec = omap4_l2c310_write_sec; if (of_have_populated_dt()) l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK); else l2x0_init(l2cache_base, aux_ctrl, L2X0_AUX_CTRL_MASK); - /* - * Override default outer_cache.disable with a OMAP4 - * specific one - */ - outer_cache.disable = omap4_l2x0_disable; - outer_cache.set_debug = omap4_l2x0_set_debug; - return 0; } omap_early_initcall(omap_l2_cache_init); From 7eab0039d3ef35bddaf02bb87c9009d484d90eea Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 17 Mar 2014 16:35:46 +0000 Subject: [PATCH 098/142] ARM: l2c: omap2: remove explicit SMI calls to enable L2 cache Now that OMAP2 uses the write_sec method, we don't need to enable the L2 cache in OMAP2 specific code; this can be done via the normal mechanisms in the L2C code. Remove the OMAP2 specific code. Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/omap4-common.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 44472b7469c5..9ce52548a484 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -222,11 +222,6 @@ static int __init omap_l2_cache_init(void) L310_AUX_CTRL_DATA_PREFETCH | L310_AUX_CTRL_INSTR_PREFETCH; - omap_smc1(0x109, aux_ctrl); - - /* Enable PL310 L2 Cache controller */ - omap_smc1(0x102, 0x1); - outer_cache.write_sec = omap4_l2c310_write_sec; if (of_have_populated_dt()) l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK); From deb125abad130fc1200782048a79079f5a41af05 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 17 Mar 2014 16:53:31 +0000 Subject: [PATCH 099/142] ARM: l2c: omap2: remove cache size override The cache size should already be present in the L2 cache auxiliary control register: it is part of the integration process to configure the hardware IP. Most platforms get this right, yet still many cargo-cult program, and assume that they always need specifying to the L2 cache code. Remove them so we can find out which really need this. Acked-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/omap4-common.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 9ce52548a484..06c6a181d6ad 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -213,20 +213,18 @@ static int __init omap_l2_cache_init(void) return -ENOMEM; /* 16-way associativity, parity disabled, way size - 64KB (es2.0 +) */ - aux_ctrl = L310_AUX_CTRL_ASSOCIATIVITY_16 | - L310_AUX_CTRL_CACHE_REPLACE_RR | + aux_ctrl = 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; outer_cache.write_sec = omap4_l2c310_write_sec; if (of_have_populated_dt()) - l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK); + l2x0_of_init(aux_ctrl, 0xc19fffff); else - l2x0_init(l2cache_base, aux_ctrl, L2X0_AUX_CTRL_MASK); + l2x0_init(l2cache_base, aux_ctrl, 0xc19fffff); return 0; } From 72ecbed1c5fe96ca5238c0c333fee3b5a858b6fb Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 11 Apr 2014 00:48:25 +0100 Subject: [PATCH 100/142] ARM: l2c: omap2: remove explicit non-secure access bits Since we now always enable NS access to the unlock registers, this can be removed from OMAP4. Remove the NS access bit for the interrupt registers from OMAP4 as well - nothing in the kernel accesses that yet, and we can add it in core code when we have the need. Signed-off-by: Russell King --- arch/arm/mach-omap2/omap4-common.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 06c6a181d6ad..df3f53195c57 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -214,17 +214,15 @@ static int __init omap_l2_cache_init(void) /* 16-way associativity, parity disabled, way size - 64KB (es2.0 +) */ aux_ctrl = L310_AUX_CTRL_CACHE_REPLACE_RR | - L310_AUX_CTRL_NS_LOCKDOWN | - L310_AUX_CTRL_NS_INT_CTRL | L2C_AUX_CTRL_SHARED_OVERRIDE | L310_AUX_CTRL_DATA_PREFETCH | L310_AUX_CTRL_INSTR_PREFETCH; outer_cache.write_sec = omap4_l2c310_write_sec; if (of_have_populated_dt()) - l2x0_of_init(aux_ctrl, 0xc19fffff); + l2x0_of_init(aux_ctrl, 0xcd9fffff); else - l2x0_init(l2cache_base, aux_ctrl, 0xc19fffff); + l2x0_init(l2cache_base, aux_ctrl, 0xcd9fffff); return 0; } From 7a09b28e8a48cfde98c25d91f64554ddf061a31b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Apr 2014 10:57:44 +0100 Subject: [PATCH 101/142] ARM: l2c: omap2: avoid reading directly from the L2 registers in platform code Avoid reading directly from the L2 registers in platform code. The L2 code will have already saved the register values itself into the l2x0_saved_regs structure, so platform code should just move these values to where they're required. This is safe because the L2x0 will have been initialised by an early initcall, whereas the OMAP4 PM code is initialised late. Signed-off-by: Russell King --- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index ba43f49fbb59..61cb77f8cf12 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -187,19 +187,15 @@ static void l2x0_pwrst_prepare(unsigned int cpu_id, unsigned int save_state) * in every restore MPUSS OFF path. */ #ifdef CONFIG_CACHE_L2X0 -static void save_l2x0_context(void) +static void __init save_l2x0_context(void) { - u32 val; - void __iomem *l2x0_base = omap4_get_l2cache_base(); - if (l2x0_base) { - val = __raw_readl(l2x0_base + L2X0_AUX_CTRL); - __raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET); - val = __raw_readl(l2x0_base + L310_PREFETCH_CTRL); - __raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET); - } + __raw_writel(l2x0_saved_regs.aux_ctrl, + sar_base + L2X0_AUXCTRL_OFFSET); + __raw_writel(l2x0_saved_regs.prefetch_ctrl, + sar_base + L2X0_PREFETCH_CTRL_OFFSET); } #else -static void save_l2x0_context(void) +static void __init save_l2x0_context(void) {} #endif From d196483dfce233da7d6094371e694eadd7e4cc1b Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Tue, 22 Apr 2014 13:58:02 +0530 Subject: [PATCH 102/142] ARM: l2c: omap2+: get rid of redundant cache replacement policy setting L2 cache initialization for OMAP4 redundantly sets the cache policy to Round-Robin. This is not needed since thats the PL310 default anyway. Removing this reduces the number of platform specific aux control settings. Signed-off-by: Sekhar Nori Acked-by: Santosh Shilimkar Signed-off-by: Russell King --- arch/arm/mach-omap2/omap4-common.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index df3f53195c57..6927d5b120fe 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -213,16 +213,15 @@ static int __init omap_l2_cache_init(void) return -ENOMEM; /* 16-way associativity, parity disabled, way size - 64KB (es2.0 +) */ - aux_ctrl = L310_AUX_CTRL_CACHE_REPLACE_RR | - L2C_AUX_CTRL_SHARED_OVERRIDE | + aux_ctrl = L2C_AUX_CTRL_SHARED_OVERRIDE | L310_AUX_CTRL_DATA_PREFETCH | L310_AUX_CTRL_INSTR_PREFETCH; outer_cache.write_sec = omap4_l2c310_write_sec; if (of_have_populated_dt()) - l2x0_of_init(aux_ctrl, 0xcd9fffff); + l2x0_of_init(aux_ctrl, 0xcf9fffff); else - l2x0_init(l2cache_base, aux_ctrl, 0xcd9fffff); + l2x0_init(l2cache_base, aux_ctrl, 0xcf9fffff); return 0; } From b39b14e62ac3d0a66d13123ef85aaa83fd7c90fc Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Tue, 22 Apr 2014 13:58:01 +0530 Subject: [PATCH 103/142] ARM: l2c: omap2+: get rid of init call Get rid of init call to initialize L2 cache. Instead use the init_early machine hook. This helps in using the initialization routine across SoCs without the need of ugly cpu_is_*() checks. Signed-off-by: Sekhar Nori Acked-by: Santosh Shilimkar Signed-off-by: Russell King --- arch/arm/mach-omap2/common.h | 1 + arch/arm/mach-omap2/io.c | 1 + arch/arm/mach-omap2/omap4-common.c | 10 +--------- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index d88aff7baff8..ff029737c8f0 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -91,6 +91,7 @@ extern void omap3_sync32k_timer_init(void); extern void omap3_secure_sync32k_timer_init(void); extern void omap3_gptimer_timer_init(void); extern void omap4_local_timer_init(void); +int omap_l2_cache_init(void); extern void omap5_realtime_timer_init(void); void omap2420_init_early(void); diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index f14f9ac2dca1..b28299b5afd5 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -640,6 +640,7 @@ void __init omap4430_init_early(void) omap44xx_clockdomains_init(); omap44xx_hwmod_init(); omap_hwmod_init_postsetup(); + omap_l2_cache_init(); omap_clk_soc_init = omap4xxx_dt_clk_init; } diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 6927d5b120fe..c41ff8b638e1 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -196,17 +196,10 @@ static void omap4_l2c310_write_sec(unsigned long val, unsigned reg) omap_smc1(smc_op, val); } -static int __init omap_l2_cache_init(void) +int __init omap_l2_cache_init(void) { u32 aux_ctrl; - /* - * To avoid code running on other OMAPs in - * multi-omap builds - */ - if (!cpu_is_omap44xx()) - return -ENODEV; - /* Static mapping, never released */ l2cache_base = ioremap(OMAP44XX_L2CACHE_BASE, SZ_4K); if (WARN_ON(!l2cache_base)) @@ -225,7 +218,6 @@ static int __init omap_l2_cache_init(void) return 0; } -omap_early_initcall(omap_l2_cache_init); #endif void __iomem *omap4_get_sar_ram_base(void) From d941f86fad41b8150f99f840250bafea7bd553c4 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Tue, 22 Apr 2014 13:58:03 +0530 Subject: [PATCH 104/142] ARM: l2c: AM43x: add L2 cache support Add support for L2 cache controller (PL310) on AM437x SoC. Signed-off-by: Sekhar Nori Acked-by: Santosh Shilimkar Signed-off-by: Russell King --- arch/arm/mach-omap2/Kconfig | 1 + arch/arm/mach-omap2/io.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index cb31d4390d52..0ba482638ebf 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -65,6 +65,7 @@ config SOC_AM43XX select ARCH_HAS_OPP select ARM_GIC select MACH_OMAP_GENERIC + select MIGHT_HAVE_CACHE_L2X0 config SOC_DRA7XX bool "TI DRA7XX" diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index b28299b5afd5..4e2df49991ad 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -609,6 +609,7 @@ void __init am43xx_init_early(void) am43xx_clockdomains_init(); am43xx_hwmod_init(); omap_hwmod_init_postsetup(); + omap_l2_cache_init(); omap_clk_soc_init = am43xx_dt_clk_init; } From c95680e6f56d6bc345a7907c4d4bd985e875f2a7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 12:14:18 +0000 Subject: [PATCH 105/142] ARM: l2c: prima2: remove cache size override The cache size should already be present in the L2 cache auxiliary control register: it is part of the integration process to configure the hardware IP. Most platforms get this right, yet still many cargo-cult program, and assume that they always need specifying to the L2 cache code. Remove them so we can find out which really need this. Signed-off-by: Russell King --- arch/arm/mach-prima2/l2x0.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c index 2db82742fb74..dbd837bdb7f7 100644 --- a/arch/arm/mach-prima2/l2x0.c +++ b/arch/arm/mach-prima2/l2x0.c @@ -11,21 +11,6 @@ #include #include -struct l2x0_aux { - u32 val; - u32 mask; -}; - -static const struct l2x0_aux prima2_l2x0_aux __initconst = { - .val = L2C_AUX_CTRL_WAY_SIZE(2), - .mask = 0, -}; - -static const struct l2x0_aux marco_l2x0_aux __initconst = { - .val = L2C_AUX_CTRL_WAY_SIZE(2) | L310_AUX_CTRL_ASSOCIATIVITY_16, - .mask = L2X0_AUX_CTRL_MASK, -}; - static const struct of_device_id sirf_l2x0_ids[] __initconst = { { .compatible = "sirf,prima2-pl310-cache", .data = &prima2_l2x0_aux, }, { .compatible = "sirf,marco-pl310-cache", .data = &marco_l2x0_aux, }, @@ -35,13 +20,10 @@ static const struct of_device_id sirf_l2x0_ids[] __initconst = { static int __init sirfsoc_l2x0_init(void) { struct device_node *np; - const struct l2x0_aux *aux; np = of_find_matching_node(NULL, sirf_l2x0_ids); - if (np) { - aux = of_match_node(sirf_l2x0_ids, np)->data; - return l2x0_of_init(aux->val, aux->mask); - } + if (np) + return l2x0_of_init(0, ~0); return 0; } From 918197be3992801054ff02fc8183bf9429bab98b Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:41:08 +0100 Subject: [PATCH 106/142] ARM: l2c: prima2: convert to generic l2c OF initialisation Remove the explicit call to l2x0_of_init(), converting to the generic infrastructure instead. Along with this change, we can delete l2x0.c from prima2. Signed-off-by: Russell King --- arch/arm/boot/dts/marco.dtsi | 2 +- arch/arm/boot/dts/prima2.dtsi | 2 +- arch/arm/mach-prima2/Makefile | 1 - arch/arm/mach-prima2/common.c | 6 ++++++ arch/arm/mach-prima2/l2x0.c | 30 ------------------------------ 5 files changed, 8 insertions(+), 33 deletions(-) delete mode 100644 arch/arm/mach-prima2/l2x0.c diff --git a/arch/arm/boot/dts/marco.dtsi b/arch/arm/boot/dts/marco.dtsi index 0c9647d28765..fb354225740a 100644 --- a/arch/arm/boot/dts/marco.dtsi +++ b/arch/arm/boot/dts/marco.dtsi @@ -36,7 +36,7 @@ ranges = <0x40000000 0x40000000 0xa0000000>; l2-cache-controller@c0030000 { - compatible = "sirf,marco-pl310-cache", "arm,pl310-cache"; + compatible = "arm,pl310-cache"; reg = <0xc0030000 0x1000>; interrupts = <0 59 0>; arm,tag-latency = <1 1 1>; diff --git a/arch/arm/boot/dts/prima2.dtsi b/arch/arm/boot/dts/prima2.dtsi index 1e82571d6823..0d6588d549bf 100644 --- a/arch/arm/boot/dts/prima2.dtsi +++ b/arch/arm/boot/dts/prima2.dtsi @@ -48,7 +48,7 @@ ranges = <0x40000000 0x40000000 0x80000000>; l2-cache-controller@80040000 { - compatible = "arm,pl310-cache", "sirf,prima2-pl310-cache"; + compatible = "arm,pl310-cache"; reg = <0x80040000 0x1000>; interrupts = <59>; arm,tag-latency = <1 1 1>; diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile index 7a6b4a323125..8846e7d87ea5 100644 --- a/arch/arm/mach-prima2/Makefile +++ b/arch/arm/mach-prima2/Makefile @@ -2,7 +2,6 @@ obj-y += rstc.o obj-y += common.o obj-y += rtciobrg.o obj-$(CONFIG_DEBUG_LL) += lluart.o -obj-$(CONFIG_CACHE_L2X0) += l2x0.o obj-$(CONFIG_SUSPEND) += pm.o sleep.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-prima2/common.c b/arch/arm/mach-prima2/common.c index 47c7819edb9b..a860ea27e8ae 100644 --- a/arch/arm/mach-prima2/common.c +++ b/arch/arm/mach-prima2/common.c @@ -34,6 +34,8 @@ static const char *atlas6_dt_match[] __initconst = { DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)") /* Maintainer: Barry Song */ + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, .map_io = sirfsoc_map_io, .init_late = sirfsoc_init_late, .dt_compat = atlas6_dt_match, @@ -48,6 +50,8 @@ static const char *prima2_dt_match[] __initconst = { DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)") /* Maintainer: Barry Song */ + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, .map_io = sirfsoc_map_io, .dma_zone_size = SZ_256M, .init_late = sirfsoc_init_late, @@ -63,6 +67,8 @@ static const char *marco_dt_match[] __initconst = { DT_MACHINE_START(MARCO_DT, "Generic MARCO (Flattened Device Tree)") /* Maintainer: Barry Song */ + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, .smp = smp_ops(sirfsoc_smp_ops), .map_io = sirfsoc_map_io, .init_late = sirfsoc_init_late, diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c deleted file mode 100644 index dbd837bdb7f7..000000000000 --- a/arch/arm/mach-prima2/l2x0.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * l2 cache initialization for CSR SiRFprimaII - * - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. - * - * Licensed under GPLv2 or later. - */ - -#include -#include -#include -#include - -static const struct of_device_id sirf_l2x0_ids[] __initconst = { - { .compatible = "sirf,prima2-pl310-cache", .data = &prima2_l2x0_aux, }, - { .compatible = "sirf,marco-pl310-cache", .data = &marco_l2x0_aux, }, - {}, -}; - -static int __init sirfsoc_l2x0_init(void) -{ - struct device_node *np; - - np = of_find_matching_node(NULL, sirf_l2x0_ids); - if (np) - return l2x0_of_init(0, ~0); - - return 0; -} -early_initcall(sirfsoc_l2x0_init); From 39b53458cc635f103365ef09e9db6980fa01e3fb Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 14:53:54 +0000 Subject: [PATCH 107/142] ARM: l2c: realview: improve commentry about the L2 cache requirements Add better commentry about the L2 cache requirements on these platforms. Unfortunately, the auxiliary control register is not pre-set to indicate the correct cache parameters, so we have to manually program these. Signed-off-by: Russell King --- arch/arm/mach-realview/realview_eb.c | 9 +++++++-- arch/arm/mach-realview/realview_pb1176.c | 8 +++++++- arch/arm/mach-realview/realview_pb11mp.c | 9 +++++++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index c85ddb2a0ad0..b575895037b8 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -442,8 +442,13 @@ static void __init realview_eb_init(void) realview_eb11mp_fixup(); #ifdef CONFIG_CACHE_L2X0 - /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled - * Bits: .... ...0 0111 1001 0000 .... .... .... */ + /* + * The PL220 needs to be manually configured as the hardware + * doesn't report the correct sizes. + * 1MB (128KB/way), 8-way associativity, event monitor and + * parity enabled, ignore share bit, no force write allocate + * Bits: .... ...0 0111 1001 0000 .... .... .... + */ l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff); #endif platform_device_register(&pmu_device); diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index c5eade76461b..e3bddb5ab10f 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -355,7 +355,13 @@ static void __init realview_pb1176_init(void) int i; #ifdef CONFIG_CACHE_L2X0 - /* 128Kb (16Kb/way) 8-way associativity. evmon/parity/share enabled. */ + /* + * The PL220 needs to be manually configured as the hardware + * doesn't report the correct sizes. + * 128kB (16kB/way), 8-way associativity, event monitor and + * parity enabled, ignore share bit, no force write allocate + * Bits: .... ...0 0111 0011 0000 .... .... .... + */ l2x0_init(__io_address(REALVIEW_PB1176_L220_BASE), 0x00730000, 0xfe000fff); #endif diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index f4b0962578fe..101deaf2630b 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -337,8 +337,13 @@ static void __init realview_pb11mp_init(void) int i; #ifdef CONFIG_CACHE_L2X0 - /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled - * Bits: .... ...0 0111 1001 0000 .... .... .... */ + /* + * The PL220 needs to be manually configured as the hardware + * doesn't report the correct sizes. + * 1MB (128KB/way), 8-way associativity, event monitor and + * parity enabled, ignore share bit, no force write allocate + * Bits: .... ...0 0111 1001 0000 .... .... .... + */ l2x0_init(__io_address(REALVIEW_TC11MP_L220_BASE), 0x00790000, 0xfe000fff); #endif From 2a2d2fff1d0bdf0723ebd2b867509dbf89a74846 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:27:59 +0100 Subject: [PATCH 108/142] ARM: l2c: rockchip: convert to generic l2c OF initialisation Remove the explicit call to l2x0_of_init(), converting to the generic infrastructure instead. This also allows us to eliminate the .init_machine function as this becomes the same as the generic version. Signed-off-by: Russell King --- arch/arm/mach-rockchip/rockchip.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c index d252efe3747b..138b9975313a 100644 --- a/arch/arm/mach-rockchip/rockchip.c +++ b/arch/arm/mach-rockchip/rockchip.c @@ -24,12 +24,6 @@ #include #include "core.h" -static void __init rockchip_dt_init(void) -{ - l2x0_of_init(0, ~0); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -} - static const char * const rockchip_board_dt_compat[] = { "rockchip,rk2928", "rockchip,rk3066a", @@ -39,7 +33,8 @@ static const char * const rockchip_board_dt_compat[] = { }; DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)") + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, .smp = smp_ops(rockchip_smp_ops), - .init_machine = rockchip_dt_init, .dt_compat = rockchip_board_dt_compat, MACHINE_END From 2edb89cd8e915d2d826f5704b80da28bde688051 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 12:16:36 +0000 Subject: [PATCH 109/142] ARM: l2c: shmobile: remove cache size override The cache size should already be present in the L2 cache auxiliary control register: it is part of the integration process to configure the hardware IP. Most platforms get this right, yet still many cargo-cult program, and assume that they always need specifying to the L2 cache code. Remove them so we can find out which really need this. Signed-off-by: Russell King --- arch/arm/mach-shmobile/board-armadillo800eva-reference.c | 2 +- arch/arm/mach-shmobile/board-armadillo800eva.c | 2 +- arch/arm/mach-shmobile/board-kzm9g-reference.c | 2 +- arch/arm/mach-shmobile/board-kzm9g.c | 2 +- arch/arm/mach-shmobile/setup-r8a7778.c | 2 +- arch/arm/mach-shmobile/setup-r8a7779.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-shmobile/board-armadillo800eva-reference.c b/arch/arm/mach-shmobile/board-armadillo800eva-reference.c index 34e7f3c17dd2..39e11f48e8bc 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva-reference.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva-reference.c @@ -165,7 +165,7 @@ static void __init eva_init(void) #ifdef CONFIG_CACHE_L2X0 /* Shared attribute override enable, 32K*8way */ - l2x0_init(IOMEM(0xf0002000), 0x00440000, 0xc2000fff); + l2x0_init(IOMEM(0xf0002000), 0x00400000, 0xc20f0fff); #endif r8a7740_add_standard_devices_dt(); diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index a01f867227ac..f8e25fd29b79 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -1272,7 +1272,7 @@ static void __init eva_init(void) #ifdef CONFIG_CACHE_L2X0 /* Shared attribute override enable, 32K*8way */ - l2x0_init(IOMEM(0xf0002000), 0x00440000, 0xc2000fff); + l2x0_init(IOMEM(0xf0002000), 0x00400000, 0xc20f0fff); #endif i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); diff --git a/arch/arm/mach-shmobile/board-kzm9g-reference.c b/arch/arm/mach-shmobile/board-kzm9g-reference.c index 85873f186d77..a735a1d80c28 100644 --- a/arch/arm/mach-shmobile/board-kzm9g-reference.c +++ b/arch/arm/mach-shmobile/board-kzm9g-reference.c @@ -37,7 +37,7 @@ static void __init kzm_init(void) #ifdef CONFIG_CACHE_L2X0 /* Shared attribute override enable, 64K*8way */ - l2x0_init(IOMEM(0xf0100000), 0x00460000, 0xc2000fff); + l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff); #endif } diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index ea9bf39fdc10..f94ec8ca42c1 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c @@ -877,7 +877,7 @@ static void __init kzm_init(void) #ifdef CONFIG_CACHE_L2X0 /* Shared attribute override enable, 64K*8way */ - l2x0_init(IOMEM(0xf0100000), 0x00460000, 0xc2000fff); + l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff); #endif i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c index 3a8e5316671e..6dd7ddf88741 100644 --- a/arch/arm/mach-shmobile/setup-r8a7778.c +++ b/arch/arm/mach-shmobile/setup-r8a7778.c @@ -301,7 +301,7 @@ void __init r8a7778_add_dt_devices(void) * Shared attribute override enable, 64K*16way * don't call iounmap(base) */ - l2x0_init(base, 0x00470000, 0xc2000fff); + l2x0_init(base, 0x00400000, 0xc20f0fff); } #endif diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index 91c90bf0ae83..a6630fccfc45 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c @@ -701,7 +701,7 @@ void __init r8a7779_add_standard_devices(void) { #ifdef CONFIG_CACHE_L2X0 /* Shared attribute override enable, 64K*16way */ - l2x0_init(IOMEM(0xf0100000), 0x00470000, 0xc2000fff); + l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff); #endif r8a7779_pm_init(); From 8b5c18f05621394eb108d3fbc9bf98b05e8162db Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:55:59 +0100 Subject: [PATCH 110/142] ARM: l2c: socfpga: convert to generic l2c OF initialisation Remove the explicit call to l2x0_of_init(), converting to the generic infrastructure instead. Signed-off-by: Russell King --- arch/arm/mach-socfpga/socfpga.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c index 9bbb8177f247..adbf38314ca8 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c @@ -98,22 +98,17 @@ static void socfpga_cyclone5_restart(enum reboot_mode mode, const char *cmd) writel(temp, rst_manager_base_addr + SOCFPGA_RSTMGR_CTRL); } -static void __init socfpga_cyclone5_init(void) -{ - l2x0_of_init(0, ~0); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -} - static const char *altera_dt_match[] = { "altr,socfpga", NULL }; DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA") + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, .smp = smp_ops(socfpga_smp_ops), .map_io = socfpga_map_io, .init_irq = socfpga_init_irq, - .init_machine = socfpga_cyclone5_init, .restart = socfpga_cyclone5_restart, .dt_compat = altera_dt_match, MACHINE_END From adf4b00ebf4e183f36d88d5a5a591c532fb0abe9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 12:18:02 +0000 Subject: [PATCH 111/142] ARM: l2c: spear13xx: remove cache size override The cache size should already be present in the L2 cache auxiliary control register: it is part of the integration process to configure the hardware IP. Most platforms get this right, yet still many cargo-cult program, and assume that they always need specifying to the L2 cache code. Remove them so we can find out which really need this. Signed-off-by: Russell King --- arch/arm/mach-spear/spear13xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-spear/spear13xx.c b/arch/arm/mach-spear/spear13xx.c index dcb300443b66..c9897ea38980 100644 --- a/arch/arm/mach-spear/spear13xx.c +++ b/arch/arm/mach-spear/spear13xx.c @@ -46,7 +46,7 @@ void __init spear13xx_l2x0_init(void) */ 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, 0x30a60001, 0xfe00ffff); + l2x0_init(VA_L2CC_BASE, 0x30a00001, 0xfe0fffff); } /* From 4d6229f6e5ac9364637cb1a162284c35e4369f80 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:49:48 +0100 Subject: [PATCH 112/142] ARM: l2c: sti: convert to generic l2c OF initialisation Remove the explicit call to l2x0_of_init(), converting to the generic infrastructure instead. We can remove the .init_machine as it becomes the same as the generic version. Signed-off-by: Russell King --- arch/arm/mach-sti/board-dt.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/arch/arm/mach-sti/board-dt.c b/arch/arm/mach-sti/board-dt.c index dc8669efc12d..910e978dfbc0 100644 --- a/arch/arm/mach-sti/board-dt.c +++ b/arch/arm/mach-sti/board-dt.c @@ -14,25 +14,6 @@ #include "smp.h" -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 = 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); -} - -static void __init stih41x_machine_init(void) -{ - stih41x_l2x0_init(); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -} - static const char *stih41x_dt_match[] __initdata = { "st,stih415", "st,stih416", @@ -40,7 +21,11 @@ static const char *stih41x_dt_match[] __initdata = { }; DT_MACHINE_START(STM, "STiH415/416 SoC with Flattened Device Tree") - .init_machine = stih41x_machine_init, - .smp = smp_ops(sti_smp_ops), .dt_compat = stih41x_dt_match, + .l2c_aux_val = L2C_AUX_CTRL_SHARED_OVERRIDE | + L310_AUX_CTRL_DATA_PREFETCH | + L310_AUX_CTRL_INSTR_PREFETCH | + L2C_AUX_CTRL_WAY_SIZE(4), + .l2c_aux_mask = 0xc0000fff, + .smp = smp_ops(sti_smp_ops), MACHINE_END From f9040550bef6f05e68af029f11c371a318220a05 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 01:17:21 +0000 Subject: [PATCH 113/142] ARM: l2c: tegra: remove cache size override The cache size should already be present in the L2 cache auxiliary control register: it is part of the integration process to configure the hardware IP. Most platforms get this right, yet still many cargo-cult program, and assume that they always need specifying to the L2 cache code. Remove them so we can find out which really need this. Acked-by: Stephen Warren Tested-by: Stephen Warren Acked-by: Peter De Schrijver Signed-off-by: Russell King --- arch/arm/mach-tegra/tegra.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index ecbb5411a104..fb802e24b647 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c @@ -73,25 +73,9 @@ u32 tegra_uart_config[3] = { static void __init tegra_init_cache(void) { #ifdef CONFIG_CACHE_L2X0 - static const struct of_device_id pl310_ids[] __initconst = { - { .compatible = "arm,pl310-cache", }, - {} - }; - - struct device_node *np; int ret; - void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; - u32 aux_ctrl, cache_type; - np = of_find_matching_node(NULL, pl310_ids); - if (!np) - return; - - cache_type = readl(p + L2X0_CACHE_TYPE); - aux_ctrl = (cache_type & 0x700) << (17-8); - aux_ctrl |= 0x3c400001; - - ret = l2x0_of_init(aux_ctrl, 0xc200c3fe); + ret = l2x0_of_init(0x3c400001, 0xc20fc3fe); if (!ret) l2x0_saved_regs_addr = virt_to_phys(&l2x0_saved_regs); #endif From b16cee70fdadaa500e0f962ae76877843281192e Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Apr 2014 11:50:38 +0100 Subject: [PATCH 114/142] ARM: l2c: tegra: convert to common l2c310 early resume functionality Acked-by: Stephen Warren Tested-by: Stephen Warren Reviewed-by: Joseph Lo Signed-off-by: Russell King --- arch/arm/mach-tegra/pm.h | 2 -- arch/arm/mach-tegra/reset-handler.S | 11 +++------- arch/arm/mach-tegra/sleep.h | 31 ----------------------------- arch/arm/mach-tegra/tegra.c | 6 +----- 4 files changed, 4 insertions(+), 46 deletions(-) diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h index 6e92a7c2ecbd..f4a89698e5b0 100644 --- a/arch/arm/mach-tegra/pm.h +++ b/arch/arm/mach-tegra/pm.h @@ -35,8 +35,6 @@ void tegra20_sleep_core_init(void); void tegra30_lp1_iram_hook(void); void tegra30_sleep_core_init(void); -extern unsigned long l2x0_saved_regs_addr; - void tegra_clear_cpu_in_lp2(void); bool tegra_set_cpu_in_lp2(void); diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S index 8c1ba4fea384..578d4d1ad648 100644 --- a/arch/arm/mach-tegra/reset-handler.S +++ b/arch/arm/mach-tegra/reset-handler.S @@ -19,7 +19,6 @@ #include #include -#include #include "flowctrl.h" #include "fuse.h" @@ -78,8 +77,10 @@ ENTRY(tegra_resume) str r1, [r0] #endif +#ifdef CONFIG_CACHE_L2X0 /* L2 cache resume & re-enable */ - l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr + bl l2c310_early_resume +#endif end_ca9_scu_l2_resume: mov32 r9, 0xc0f cmp r8, r9 @@ -89,12 +90,6 @@ end_ca9_scu_l2_resume: ENDPROC(tegra_resume) #endif -#ifdef CONFIG_CACHE_L2X0 - .globl l2x0_saved_regs_addr -l2x0_saved_regs_addr: - .long 0 -#endif - .align L1_CACHE_SHIFT ENTRY(__tegra_cpu_reset_handler_start) diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h index a032820d2fac..339fe42cd6fb 100644 --- a/arch/arm/mach-tegra/sleep.h +++ b/arch/arm/mach-tegra/sleep.h @@ -120,37 +120,6 @@ mov \tmp1, \tmp1, lsr #8 .endm -/* Macro to resume & re-enable L2 cache */ -#ifndef L2X0_CTRL_EN -#define L2X0_CTRL_EN 1 -#endif - -#ifdef CONFIG_CACHE_L2X0 -.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs - W(adr) \tmp1, \phys_l2x0_saved_regs - ldr \tmp1, [\tmp1] - ldr \tmp2, [\tmp1, #L2X0_R_PHY_BASE] - ldr \tmp3, [\tmp2, #L2X0_CTRL] - tst \tmp3, #L2X0_CTRL_EN - bne exit_l2_resume - ldr \tmp3, [\tmp1, #L2X0_R_TAG_LATENCY] - str \tmp3, [\tmp2, #L310_TAG_LATENCY_CTRL] - ldr \tmp3, [\tmp1, #L2X0_R_DATA_LATENCY] - str \tmp3, [\tmp2, #L310_DATA_LATENCY_CTRL] - ldr \tmp3, [\tmp1, #L2X0_R_PREFETCH_CTRL] - str \tmp3, [\tmp2, #L310_PREFETCH_CTRL] - ldr \tmp3, [\tmp1, #L2X0_R_PWR_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 - str \tmp3, [\tmp2, #L2X0_CTRL] -exit_l2_resume: -.endm -#else /* CONFIG_CACHE_L2X0 */ -.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs -.endm -#endif /* CONFIG_CACHE_L2X0 */ #else void tegra_pen_lock(void); void tegra_pen_unlock(void); diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index fb802e24b647..1bc49f9db015 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c @@ -73,11 +73,7 @@ u32 tegra_uart_config[3] = { static void __init tegra_init_cache(void) { #ifdef CONFIG_CACHE_L2X0 - int ret; - - ret = l2x0_of_init(0x3c400001, 0xc20fc3fe); - if (!ret) - l2x0_saved_regs_addr = virt_to_phys(&l2x0_saved_regs); + l2x0_of_init(0x3c400001, 0xc20fc3fe); #endif } From 00123d9a8d25a90cdd964062f7f7877e510ec7c1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:36:04 +0100 Subject: [PATCH 115/142] ARM: l2c: tegra: convert to generic l2c OF initialisation Remove the explicit call to l2x0_of_init(), converting to the generic infrastructure instead. Acked-by: Stephen Warren Signed-off-by: Russell King --- arch/arm/mach-tegra/tegra.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index 1bc49f9db015..15ac9fcc96b1 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c @@ -70,20 +70,12 @@ u32 tegra_uart_config[3] = { 0, }; -static void __init tegra_init_cache(void) -{ -#ifdef CONFIG_CACHE_L2X0 - l2x0_of_init(0x3c400001, 0xc20fc3fe); -#endif -} - static void __init tegra_init_early(void) { of_register_trusted_foundations(); tegra_apb_io_init(); tegra_init_fuse(); tegra_cpu_reset_handler_init(); - tegra_init_cache(); tegra_powergate_init(); tegra_hotplug_init(); } @@ -171,8 +163,10 @@ static const char * const tegra_dt_board_compat[] = { }; DT_MACHINE_START(TEGRA_DT, "NVIDIA Tegra SoC (Flattened Device Tree)") - .map_io = tegra_map_common_io, + .l2c_aux_val = 0x3c400001, + .l2c_aux_mask = 0xc20fc3fe, .smp = smp_ops(tegra_smp_ops), + .map_io = tegra_map_common_io, .init_early = tegra_init_early, .init_irq = tegra_dt_init_irq, .init_machine = tegra_dt_init, From 6716173347a87790a03fda6b8f978ac096ca7758 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 19:15:21 +0000 Subject: [PATCH 116/142] ARM: l2c: ux500: implement dummy write_sec method ux500 can't write to any of the secure registers on the L2C controllers, so provide a dummy handler which ignores all writes. Acked-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ux500/cache-l2x0.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c index 132cd2b465e7..067c37a054fb 100644 --- a/arch/arm/mach-ux500/cache-l2x0.c +++ b/arch/arm/mach-ux500/cache-l2x0.c @@ -35,6 +35,14 @@ static int __init ux500_l2x0_unlock(void) return 0; } +static void ux500_l2c310_write_sec(unsigned long val, unsigned reg) +{ + /* + * We can't write to secure registers as we are in non-secure + * mode, until we have some SMI service available. + */ +} + static int __init ux500_l2x0_init(void) { u32 aux_val = 0x3e000000; @@ -56,21 +64,14 @@ static int __init ux500_l2x0_init(void) /* 64KB way size */ aux_val |= L2C_AUX_CTRL_WAY_SIZE(3); + outer_cache.write_sec = ux500_l2c310_write_sec; + /* 64KB way size, 8 way associativity, force WA */ if (of_have_populated_dt()) l2x0_of_init(aux_val, 0xc0000fff); else l2x0_init(l2x0_base, aux_val, 0xc0000fff); - /* - * We can't disable l2 as we are in non secure mode, currently - * this seems be called only during kexec path. So let's - * override outer.disable with nasty assignment until we have - * some SMI service available. - */ - outer_cache.disable = NULL; - outer_cache.set_debug = NULL; - return 0; } From c4a202c8ae001e7154a5fe22b64f751d37da2122 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 01:22:05 +0000 Subject: [PATCH 117/142] ARM: l2c: ux500: remove cache size override The cache size should already be present in the L2 cache auxiliary control register: it is part of the integration process to configure the hardware IP. Most platforms get this right, yet still many cargo-cult program, and assume that they always need specifying to the L2 cache code. Remove them so we can find out which really need this. Acked-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ux500/cache-l2x0.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c index 067c37a054fb..5b891d051054 100644 --- a/arch/arm/mach-ux500/cache-l2x0.c +++ b/arch/arm/mach-ux500/cache-l2x0.c @@ -45,8 +45,6 @@ static void ux500_l2c310_write_sec(unsigned long val, unsigned reg) static int __init ux500_l2x0_init(void) { - u32 aux_val = 0x3e000000; - if (cpu_is_u8500_family() || cpu_is_ux540_family()) l2x0_base = __io_address(U8500_L2CC_BASE); else @@ -56,21 +54,12 @@ static int __init ux500_l2x0_init(void) /* Unlock before init */ ux500_l2x0_unlock(); - /* DBx540's L2 has 128KB way size */ - if (cpu_is_ux540_family()) - /* 128KB way size */ - aux_val |= L2C_AUX_CTRL_WAY_SIZE(4); - else - /* 64KB way size */ - aux_val |= L2C_AUX_CTRL_WAY_SIZE(3); - outer_cache.write_sec = ux500_l2c310_write_sec; - /* 64KB way size, 8 way associativity, force WA */ if (of_have_populated_dt()) - l2x0_of_init(aux_val, 0xc0000fff); + l2x0_of_init(0x3e000000, 0xc00f0fff); else - l2x0_init(l2x0_base, aux_val, 0xc0000fff); + l2x0_init(l2x0_base, 0x3e000000, 0xc00f0fff); return 0; } From c59917f877ae9b94d4ba146600c763ed6ae97a1b Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 12:47:58 +0000 Subject: [PATCH 118/142] ARM: l2c: ux500: don't try to change the L2 cache auxiliary control register ux500 can't change the auxiliary control register, so there's no point passing values to try and modify it to the l2x0 init functions. Acked-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-ux500/cache-l2x0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c index 5b891d051054..842ebedbdd1c 100644 --- a/arch/arm/mach-ux500/cache-l2x0.c +++ b/arch/arm/mach-ux500/cache-l2x0.c @@ -57,9 +57,9 @@ static int __init ux500_l2x0_init(void) outer_cache.write_sec = ux500_l2c310_write_sec; if (of_have_populated_dt()) - l2x0_of_init(0x3e000000, 0xc00f0fff); + l2x0_of_init(0, ~0); else - l2x0_init(l2x0_base, 0x3e000000, 0xc00f0fff); + l2x0_init(l2x0_base, 0, ~0); return 0; } From 060bf2af12e3a5cf6af95336f9aa66e2af6ffa43 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 11:15:38 +0000 Subject: [PATCH 119/142] ARM: l2c: vexpress ca9x4: move L2 cache initialisation earlier It is beneficial to have the L2 cache up and running earlier in the system boot. Not only will this allow for simpler code when we come to enable some features, but it also means that we get a more accurate bogomips value for the udelay() loop. Calibrating the loop with the L2 cache off, and then running with the L2 cache on is not the best idea. Signed-off-by: Russell King --- arch/arm/mach-vexpress/ct-ca9x4.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 6c4ffb6c5ad8..204038ef3795 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -45,6 +45,23 @@ static void __init ct_ca9x4_map_io(void) iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); } +static void __init ca9x4_l2_init(void) +{ +#ifdef CONFIG_CACHE_L2X0 + void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K); + + if (l2x0_base) { + /* set RAM latencies to 1 cycle for this core tile. */ + writel(0, l2x0_base + L310_TAG_LATENCY_CTRL); + writel(0, l2x0_base + L310_DATA_LATENCY_CTRL); + + l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff); + } else { + pr_err("L2C: unable to map L2 cache controller\n"); + } +#endif +} + #ifdef CONFIG_HAVE_ARM_TWD static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, A9_MPCORE_TWD, IRQ_LOCALTIMER); @@ -63,6 +80,7 @@ static void __init ct_ca9x4_init_irq(void) gic_init(0, 29, ioremap(A9_MPCORE_GIC_DIST, SZ_4K), ioremap(A9_MPCORE_GIC_CPU, SZ_256)); ca9x4_twd_init(); + ca9x4_l2_init(); } static int ct_ca9x4_clcd_setup(struct clcd_fb *fb) @@ -141,16 +159,6 @@ static void __init ct_ca9x4_init(void) { int i; -#ifdef CONFIG_CACHE_L2X0 - void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K); - - /* set RAM latencies to 1 cycle for this core tile. */ - writel(0, l2x0_base + L310_TAG_LATENCY_CTRL); - writel(0, l2x0_base + L310_DATA_LATENCY_CTRL); - - l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff); -#endif - for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++) amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); From b28dd4ac66de15c48b00184b63180094f2f7fb45 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:43:12 +0100 Subject: [PATCH 120/142] ARM: l2c: vexpress: convert to generic l2c OF initialisation Remove the explicit call to l2x0_of_init(), converting to the generic infrastructure instead. Signed-off-by: Russell King --- arch/arm/mach-vexpress/v2m.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 4f8b8cb17ff5..b2fea70d412d 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -432,7 +432,6 @@ static const struct of_device_id v2m_dt_bus_match[] __initconst = { static void __init v2m_dt_init(void) { - l2x0_of_init(0x00400000, 0xfe0fffff); of_platform_populate(NULL, v2m_dt_bus_match, NULL, NULL); } @@ -443,6 +442,8 @@ static const char * const v2m_dt_match[] __initconst = { DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express") .dt_compat = v2m_dt_match, + .l2c_aux_val = 0x00400000, + .l2c_aux_mask = 0xfe0fffff, .smp = smp_ops(vexpress_smp_ops), .smp_init = smp_init_ops(vexpress_smp_init_ops), .map_io = v2m_dt_map_io, From 2c4133c5d0e98ea5c7faca780e2b846d10f430c8 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 12:22:34 +0000 Subject: [PATCH 121/142] ARM: l2c: zynq: remove cache size override The cache size should already be present in the L2 cache auxiliary control register: it is part of the integration process to configure the hardware IP. Most platforms get this right, yet still many cargo-cult program, and assume that they always need specifying to the L2 cache code. Remove them so we can find out which really need this. Signed-off-by: Russell King --- arch/arm/mach-zynq/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 6fcc584c1a11..1e617a6dedc3 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -70,7 +70,7 @@ static void __init zynq_init_machine(void) /* * 64KB way size, 8-way associativity, parity disabled */ - l2x0_of_init(0x02060000, 0xF0F0FFFF); + l2x0_of_init(0x02000000, 0xf0ffffff); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); From dcf9c7f9f4c5acd9ea72782263d2d76bbeadd9f7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 28 Apr 2014 15:31:11 +0100 Subject: [PATCH 122/142] ARM: l2c: zynq: convert to generic l2c OF initialisation Remove the explicit call to l2x0_of_init(), converting to the generic infrastructure instead. Signed-off-by: Russell King --- arch/arm/mach-zynq/common.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 1e617a6dedc3..d1e992e6403e 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -67,11 +67,6 @@ static void __init zynq_init_machine(void) { struct platform_device_info devinfo = { .name = "cpufreq-cpu0", }; - /* - * 64KB way size, 8-way associativity, parity disabled - */ - l2x0_of_init(0x02000000, 0xf0ffffff); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); platform_device_register(&zynq_cpuidle_device); @@ -133,6 +128,9 @@ static const char * const zynq_dt_match[] = { }; DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform") + /* 64KB way size, 8-way associativity, parity disabled */ + .l2c_aux_val = 0x02000000, + .l2c_aux_mask = 0xf0ffffff, .smp = smp_ops(zynq_smp_ops), .map_io = zynq_map_io, .init_irq = zynq_irq_init, From 851d6d7117b97d72a0ae84a4d6640d310ea63d1b Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 12:24:42 +0000 Subject: [PATCH 123/142] ARM: l2c: kill L2X0_AUX_CTRL_MASK before anyone else makes use of this L2X0_AUX_CTRL_MASK is not useful for PL310s. It would be better if people thought about their value for this rather than cargo-cult programming. Signed-off-by: Russell King --- arch/arm/include/asm/hardware/cache-l2x0.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h index b3ee122c6f24..84bbd31b8910 100644 --- a/arch/arm/include/asm/hardware/cache-l2x0.h +++ b/arch/arm/include/asm/hardware/cache-l2x0.h @@ -87,7 +87,6 @@ #define L310_CACHE_ID_RTL_R3P2 0x08 #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) From 678ea28b7c3cc9a7196192dc77dfc13513db3d5f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 16 Mar 2014 19:38:25 +0000 Subject: [PATCH 124/142] 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(-) 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, }, }; From 314e47b7b651db93bbdeb83f4244240ff5d33baa Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 19 Mar 2014 14:07:12 +0000 Subject: [PATCH 125/142] 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(+) 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 From 560be6136b3605ebbb8bd04b49b175c809d4e953 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 17 Mar 2014 17:02:56 +0000 Subject: [PATCH 126/142] 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(-) 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"); From 8ef418c7178fa611d84e187bacb967880f6f5b69 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Mar 2014 21:40:01 +0000 Subject: [PATCH 127/142] 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(-) 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,9 +642,26 @@ 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) { unsigned rev = readl_relaxed(base + L2X0_CACHE_ID) & L2X0_CACHE_ID_PART_MASK; @@ -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, }, From 8a87411b649c6082aebea613e84dcb3f174f72fb Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 2 May 2014 17:06:19 +0100 Subject: [PATCH 128/142] ARM: 8047/1: rwsem: use asm-generic rwsem implementation asm-generic offers an atomic-add based rwsem implementation, which can avoid the need for heavier, spinlock-based synchronisation on the fast path. This patch makes use of the optimised implementation for ARM CPUs. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/Kconfig | 5 +---- arch/arm/include/asm/Kbuild | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 58506175a3ea..ce64b7f66328 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -165,12 +165,9 @@ config TRACE_IRQFLAGS_SUPPORT bool default y -config RWSEM_GENERIC_SPINLOCK - bool - default y - config RWSEM_XCHGADD_ALGORITHM bool + default y config ARCH_HAS_ILOG2_U32 bool diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index 23e728ecf8ab..f5a357601983 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -21,6 +21,7 @@ generic-y += parport.h generic-y += poll.h generic-y += preempt.h generic-y += resource.h +generic-y += rwsem.h generic-y += sections.h generic-y += segment.h generic-y += sembuf.h From 3780f7ab4928bc05897a7e30cf102c20045823ef Mon Sep 17 00:00:00 2001 From: Arun K S Date: Mon, 19 May 2014 11:43:00 +0100 Subject: [PATCH 129/142] ARM: 8062/1: Modify ldrt fixup handler to re-execute the userspace instruction We will reach fixup handler when one thread(say cpu0) caused an undefined exception, while another thread(say cpu1) is unmmaping the page. Fixup handler returns to the next userspace instruction which has caused the undef execption, rather than going to the same instruction. ARM ARM says that after undefined exception, the PC will be pointing to the next instruction. ie +4 offset in case of ARM and +2 in case of Thumb And there is no correction offset passed to vector_stub in case of undef exception. File: arch/arm/kernel/entry-armv.S +1085 vector_stub und, UND_MODE During an undefined exception, in normal scenario(ie when ldrt instruction does not cause an abort) after resorting the context in VFP hardware, the PC is modified as show below before jumping to ret_from_exception which is in r9. File: arch/arm/vfp/vfphw.S +169 @ The context stored in the VFP hardware is up to date with this thread vfp_hw_state_valid: tst r1, #FPEXC_EX bne process_exception @ might as well handle the pending @ exception before retrying branch @ out before setting an FPEXC that @ stops us reading stuff VFPFMXR FPEXC, r1 @ Restore FPEXC last sub r2, r2, #4 @ Retry current instruction - if Thumb str r2, [sp, #S_PC] @ mode it's two 16-bit instructions, @ else it's one 32-bit instruction, so @ always subtract 4 from the following @ instruction address. But if ldrt results in an abort, we reach the fixup handler and return to ret_from_execption without correcting the pc. This patch modifes the fixup handler to re-execute the same instruction which caused undefined execption. Signed-off-by: Vinayak Menon Signed-off-by: Arun KS Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 5fc897cf409b..0ffdec8eceb7 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -489,7 +489,8 @@ ENDPROC(__und_usr) */ .pushsection .fixup, "ax" .align 2 -4: mov pc, r9 +4: str r4, [sp, #S_PC] @ retry current instruction + mov pc, r9 .popsection .pushsection __ex_table,"a" .long 1b, 4b From 2961b4bf70f833f16d522823ac16c5bb9e277ef7 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Mon, 26 May 2014 10:30:14 +0100 Subject: [PATCH 130/142] ARM: 8065/1: remove last use of CONFIG_CPU_ARM710 Support for ARM710 CPUs was removed in v3.5. Now remove the last code depending on its Kconfig macro. Signed-off-by: Paul Bolle Acked-by: Arnd Bergmann Signed-off-by: Russell King --- arch/arm/include/asm/glue-df.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/arm/include/asm/glue-df.h b/arch/arm/include/asm/glue-df.h index 6b70f1b46a6e..04e18b656659 100644 --- a/arch/arm/include/asm/glue-df.h +++ b/arch/arm/include/asm/glue-df.h @@ -31,14 +31,6 @@ #undef CPU_DABORT_HANDLER #undef MULTI_DABORT -#if defined(CONFIG_CPU_ARM710) -# ifdef CPU_DABORT_HANDLER -# define MULTI_DABORT 1 -# else -# define CPU_DABORT_HANDLER cpu_arm7_data_abort -# endif -#endif - #ifdef CONFIG_CPU_ABRT_EV4 # ifdef CPU_DABORT_HANDLER # define MULTI_DABORT 1 From 9c986661638c69772f5479c4715061239ec61b29 Mon Sep 17 00:00:00 2001 From: Lin Yongting Date: Sun, 4 May 2014 16:27:41 +0100 Subject: [PATCH 131/142] ARM: 8049/1: ftrace/add save_stack_trace_regs() implementation When configure kprobe events of ftrace with "stacktrace" option enabled in arm, there is no stacktrace was recorded after the kprobe event was triggered. The root cause is no save_stack_trace_regs() function implemented. Implement the save_stack_trace_regs() function in arm, then ftrace will call this architecture-related function to record the stacktrace into ring buffer. After this fix, stacktrace can be recorded, for example: # mount -t debugfs nodev /sys/kernel/debug # echo "p:netrx net_rx_action" >> /sys/kernel/debug/tracing/kprobe_events # echo 1 > /sys/kernel/debug/tracing/events/kprobes/netrx/enable # echo 1 > /sys/kernel/debug/tracing/options/stacktrace # echo 1 > /sys/kernel/debug/tracing/tracing_on # ping 127.0.0.1 -c 1 # echo 0 > /sys/kernel/debug/tracing/tracing_on # cat /sys/kernel/debug/tracing/trace # tracer: nop # # entries-in-buffer/entries-written: 12/12 #P:1 # # _-----=> irqs-off # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | <------ missing some entries ----------------> ping-1200 [000] dNs1 667.603250: netrx: (net_rx_action+0x0/0x1f8) ping-1200 [000] dNs1 667.604738: => net_rx_action => do_softirq => local_bh_enable => ip_finish_output => ip_output => ip_local_out => ip_send_skb => ip_push_pending_frames => raw_sendmsg => inet_sendmsg => sock_sendmsg => SyS_sendto => ret_fast_syscall Signed-off-by: Lin Yongting Acked-by: Steven Rostedt Signed-off-by: Russell King --- arch/arm/kernel/stacktrace.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index 5a80ddfe7031..f065eb05d254 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -149,6 +149,25 @@ static noinline void __save_stack_trace(struct task_struct *tsk, trace->entries[trace->nr_entries++] = ULONG_MAX; } +void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) +{ + struct stack_trace_data data; + struct stackframe frame; + + data.trace = trace; + data.skip = trace->skip; + data.no_sched_functions = 0; + + frame.fp = regs->ARM_fp; + frame.sp = regs->ARM_sp; + frame.lr = regs->ARM_lr; + frame.pc = regs->ARM_pc; + + walk_stackframe(&frame, save_trace, &data); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; +} + void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { __save_stack_trace(tsk, trace, 1); From 437b680a222098f67ecb1690f8eb91f550bfaac8 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 30 May 2014 20:58:27 +0100 Subject: [PATCH 132/142] ARM: 8066/1: correction for ARM patch 8031/2 A small mistake slipped through in memory.txt. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- Documentation/arm/memory.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/arm/memory.txt b/Documentation/arm/memory.txt index 256c5e067fb1..38dc06d0a791 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. -fffc0000 ffdfffff Fixmap mapping region. Addresses provided +ffc00000 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 From 1c8c3cf0b5239388e712508a85821f4718f4d889 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Mon, 19 May 2014 11:04:39 +0100 Subject: [PATCH 133/142] 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(-) 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 From 1c2f87c22566cd057bc8cde10c37ae9da1a1bb76 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Sun, 13 Apr 2014 22:54:58 +0100 Subject: [PATCH 134/142] 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 | 119 +++++++---------------- arch/arm/mm/nommu.c | 62 ++++++------ 36 files changed, 178 insertions(+), 332 deletions(-) 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