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

ARM: mvebu: add support to clear shared L2 bit on Armada XP

For optimal performance, in a HW I/O coherency context such as the one
used on Armada XP, the shared L2 bit of the CPU configuration register
should be cleared.

This commit adjusts the coherency fabric code used by Marvell EBU
processors to clear this bit on Armada XP. Since it's a per-CPU
register, it's cleared in set_cpu_coherent() for the boot CPU, and
through a CPU notifier for the non-boot CPUs.

[gregory.clement@free-electrons.com: rebasd on 4.3-rc1]

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>

authored by

Thomas Petazzoni and committed by
Gregory CLEMENT
d492ccca 6ff33f39

+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 }