aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2015-10-15 16:03:35 -0400
committerArnd Bergmann <arnd@arndb.de>2015-10-15 16:03:35 -0400
commit19f47051e59d1366912705b367ceca26cdbe3428 (patch)
tree99711510fe73913b7b4e20ccb94c192aaeccb1e2
parent55fa3ee0815a355490c109416935563223af0ccc (diff)
parentd492cccac28493f26bb70038385a9ef4df19bdee (diff)
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
-rw-r--r--Documentation/devicetree/bindings/arm/mvebu-cpu-config.txt20
-rw-r--r--arch/arm/mach-mvebu/coherency.c60
2 files changed, 80 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/arm/mvebu-cpu-config.txt b/Documentation/devicetree/bindings/arm/mvebu-cpu-config.txt
new file mode 100644
index 000000000000..2cdcd716da40
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mvebu-cpu-config.txt
@@ -0,0 +1,20 @@
1MVEBU CPU Config registers
2--------------------------
3
4MVEBU (Marvell SOCs: Armada 370/XP)
5
6Required 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
15Example:
16
17 cpu-config@21000 {
18 compatible = "marvell,armada-xp-cpu-config";
19 reg = <0x21000 0x8>;
20 };
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index 44eedf331ae7..55348ee5a352 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -40,6 +40,7 @@
40unsigned long coherency_phys_base; 40unsigned long coherency_phys_base;
41void __iomem *coherency_base; 41void __iomem *coherency_base;
42static void __iomem *coherency_cpu_base; 42static void __iomem *coherency_cpu_base;
43static void __iomem *cpu_config_base;
43 44
44/* Coherency fabric registers */ 45/* Coherency fabric registers */
45#define IO_SYNC_BARRIER_CTL_OFFSET 0x0 46#define IO_SYNC_BARRIER_CTL_OFFSET 0x0
@@ -65,6 +66,31 @@ static const struct of_device_id of_coherency_table[] = {
65int ll_enable_coherency(void); 66int ll_enable_coherency(void);
66void ll_add_cpu_to_smp_group(void); 67void ll_add_cpu_to_smp_group(void);
67 68
69#define CPU_CONFIG_SHARED_L2 BIT(16)
70
71/*
72 * Disable the "Shared L2 Present" bit in CPU Configuration register
73 * on Armada XP.
74 *
75 * The "Shared L2 Present" bit affects the "level of coherence" value
76 * in the clidr CP15 register. Cache operation functions such as
77 * "flush all" and "invalidate all" operate on all the cache levels
78 * that included in the defined level of coherence. When HW I/O
79 * coherency is used, this bit causes unnecessary flushes of the L2
80 * cache.
81 */
82static void armada_xp_clear_shared_l2(void)
83{
84 u32 reg;
85
86 if (!cpu_config_base)
87 return;
88
89 reg = readl(cpu_config_base);
90 reg &= ~CPU_CONFIG_SHARED_L2;
91 writel(reg, cpu_config_base);
92}
93
68static int mvebu_hwcc_notifier(struct notifier_block *nb, 94static int mvebu_hwcc_notifier(struct notifier_block *nb,
69 unsigned long event, void *__dev) 95 unsigned long event, void *__dev)
70{ 96{
@@ -85,9 +111,24 @@ static struct notifier_block mvebu_hwcc_pci_nb = {
85 .notifier_call = mvebu_hwcc_notifier, 111 .notifier_call = mvebu_hwcc_notifier,
86}; 112};
87 113
114static int armada_xp_clear_shared_l2_notifier_func(struct notifier_block *nfb,
115 unsigned long action, void *hcpu)
116{
117 if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
118 armada_xp_clear_shared_l2();
119
120 return NOTIFY_OK;
121}
122
123static struct notifier_block armada_xp_clear_shared_l2_notifier = {
124 .notifier_call = armada_xp_clear_shared_l2_notifier_func,
125 .priority = 100,
126};
127
88static void __init armada_370_coherency_init(struct device_node *np) 128static void __init armada_370_coherency_init(struct device_node *np)
89{ 129{
90 struct resource res; 130 struct resource res;
131 struct device_node *cpu_config_np;
91 132
92 of_address_to_resource(np, 0, &res); 133 of_address_to_resource(np, 0, &res);
93 coherency_phys_base = res.start; 134 coherency_phys_base = res.start;
@@ -100,6 +141,23 @@ static void __init armada_370_coherency_init(struct device_node *np)
100 sync_cache_w(&coherency_phys_base); 141 sync_cache_w(&coherency_phys_base);
101 coherency_base = of_iomap(np, 0); 142 coherency_base = of_iomap(np, 0);
102 coherency_cpu_base = of_iomap(np, 1); 143 coherency_cpu_base = of_iomap(np, 1);
144
145 cpu_config_np = of_find_compatible_node(NULL, NULL,
146 "marvell,armada-xp-cpu-config");
147 if (!cpu_config_np)
148 goto exit;
149
150 cpu_config_base = of_iomap(cpu_config_np, 0);
151 if (!cpu_config_base) {
152 of_node_put(cpu_config_np);
153 goto exit;
154 }
155
156 of_node_put(cpu_config_np);
157
158 register_cpu_notifier(&armada_xp_clear_shared_l2_notifier);
159
160exit:
103 set_cpu_coherent(); 161 set_cpu_coherent();
104} 162}
105 163
@@ -204,6 +262,8 @@ int set_cpu_coherent(void)
204 pr_warn("Coherency fabric is not initialized\n"); 262 pr_warn("Coherency fabric is not initialized\n");
205 return 1; 263 return 1;
206 } 264 }
265
266 armada_xp_clear_shared_l2();
207 ll_add_cpu_to_smp_group(); 267 ll_add_cpu_to_smp_group();
208 return ll_enable_coherency(); 268 return ll_enable_coherency();
209 } 269 }