Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'mvebu-soc-4.4-1' of git://git.infradead.org/linux-mvebu into next/soc

Merge "mvebu soc for 4.4 (part 1)" from Gregory CLEMENT:

L2 caches optimization for Armada XP

* tag 'mvebu-soc-4.4-1' of git://git.infradead.org/linux-mvebu:
ARM: mvebu: add support to clear shared L2 bit on Armada XP

+80
+20
Documentation/devicetree/bindings/arm/mvebu-cpu-config.txt
··· 1 + MVEBU CPU Config registers 2 + -------------------------- 3 + 4 + MVEBU (Marvell SOCs: Armada 370/XP) 5 + 6 + Required properties: 7 + 8 + - compatible: one of: 9 + - "marvell,armada-370-cpu-config" 10 + - "marvell,armada-xp-cpu-config" 11 + 12 + - reg: Should contain CPU config registers location and length, in 13 + their per-CPU variant 14 + 15 + Example: 16 + 17 + cpu-config@21000 { 18 + compatible = "marvell,armada-xp-cpu-config"; 19 + reg = <0x21000 0x8>; 20 + };
+60
arch/arm/mach-mvebu/coherency.c
··· 40 40 unsigned long coherency_phys_base; 41 41 void __iomem *coherency_base; 42 42 static void __iomem *coherency_cpu_base; 43 + static void __iomem *cpu_config_base; 43 44 44 45 /* Coherency fabric registers */ 45 46 #define IO_SYNC_BARRIER_CTL_OFFSET 0x0 ··· 66 65 int ll_enable_coherency(void); 67 66 void ll_add_cpu_to_smp_group(void); 68 67 68 + #define CPU_CONFIG_SHARED_L2 BIT(16) 69 + 70 + /* 71 + * Disable the "Shared L2 Present" bit in CPU Configuration register 72 + * on Armada XP. 73 + * 74 + * The "Shared L2 Present" bit affects the "level of coherence" value 75 + * in the clidr CP15 register. Cache operation functions such as 76 + * "flush all" and "invalidate all" operate on all the cache levels 77 + * that included in the defined level of coherence. When HW I/O 78 + * coherency is used, this bit causes unnecessary flushes of the L2 79 + * cache. 80 + */ 81 + static void armada_xp_clear_shared_l2(void) 82 + { 83 + u32 reg; 84 + 85 + if (!cpu_config_base) 86 + return; 87 + 88 + reg = readl(cpu_config_base); 89 + reg &= ~CPU_CONFIG_SHARED_L2; 90 + writel(reg, cpu_config_base); 91 + } 92 + 69 93 static int mvebu_hwcc_notifier(struct notifier_block *nb, 70 94 unsigned long event, void *__dev) 71 95 { ··· 111 85 .notifier_call = mvebu_hwcc_notifier, 112 86 }; 113 87 88 + static int armada_xp_clear_shared_l2_notifier_func(struct notifier_block *nfb, 89 + unsigned long action, void *hcpu) 90 + { 91 + if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) 92 + armada_xp_clear_shared_l2(); 93 + 94 + return NOTIFY_OK; 95 + } 96 + 97 + static struct notifier_block armada_xp_clear_shared_l2_notifier = { 98 + .notifier_call = armada_xp_clear_shared_l2_notifier_func, 99 + .priority = 100, 100 + }; 101 + 114 102 static void __init armada_370_coherency_init(struct device_node *np) 115 103 { 116 104 struct resource res; 105 + struct device_node *cpu_config_np; 117 106 118 107 of_address_to_resource(np, 0, &res); 119 108 coherency_phys_base = res.start; ··· 141 100 sync_cache_w(&coherency_phys_base); 142 101 coherency_base = of_iomap(np, 0); 143 102 coherency_cpu_base = of_iomap(np, 1); 103 + 104 + cpu_config_np = of_find_compatible_node(NULL, NULL, 105 + "marvell,armada-xp-cpu-config"); 106 + if (!cpu_config_np) 107 + goto exit; 108 + 109 + cpu_config_base = of_iomap(cpu_config_np, 0); 110 + if (!cpu_config_base) { 111 + of_node_put(cpu_config_np); 112 + goto exit; 113 + } 114 + 115 + of_node_put(cpu_config_np); 116 + 117 + register_cpu_notifier(&armada_xp_clear_shared_l2_notifier); 118 + 119 + exit: 144 120 set_cpu_coherent(); 145 121 } 146 122 ··· 262 204 pr_warn("Coherency fabric is not initialized\n"); 263 205 return 1; 264 206 } 207 + 208 + armada_xp_clear_shared_l2(); 265 209 ll_add_cpu_to_smp_group(); 266 210 return ll_enable_coherency(); 267 211 }