0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #define pr_fmt(fmt) "mvebu-coherency: " fmt
0019
0020 #include <linux/kernel.h>
0021 #include <linux/init.h>
0022 #include <linux/of_address.h>
0023 #include <linux/io.h>
0024 #include <linux/smp.h>
0025 #include <linux/dma-map-ops.h>
0026 #include <linux/platform_device.h>
0027 #include <linux/slab.h>
0028 #include <linux/mbus.h>
0029 #include <linux/pci.h>
0030 #include <asm/smp_plat.h>
0031 #include <asm/cacheflush.h>
0032 #include <asm/mach/map.h>
0033 #include <asm/dma-mapping.h>
0034 #include "coherency.h"
0035 #include "mvebu-soc-id.h"
0036
0037 unsigned long coherency_phys_base;
0038 void __iomem *coherency_base;
0039 static void __iomem *coherency_cpu_base;
0040 static void __iomem *cpu_config_base;
0041
0042
0043 #define IO_SYNC_BARRIER_CTL_OFFSET 0x0
0044
0045 enum {
0046 COHERENCY_FABRIC_TYPE_NONE,
0047 COHERENCY_FABRIC_TYPE_ARMADA_370_XP,
0048 COHERENCY_FABRIC_TYPE_ARMADA_375,
0049 COHERENCY_FABRIC_TYPE_ARMADA_380,
0050 };
0051
0052 static const struct of_device_id of_coherency_table[] = {
0053 {.compatible = "marvell,coherency-fabric",
0054 .data = (void *) COHERENCY_FABRIC_TYPE_ARMADA_370_XP },
0055 {.compatible = "marvell,armada-375-coherency-fabric",
0056 .data = (void *) COHERENCY_FABRIC_TYPE_ARMADA_375 },
0057 {.compatible = "marvell,armada-380-coherency-fabric",
0058 .data = (void *) COHERENCY_FABRIC_TYPE_ARMADA_380 },
0059 { },
0060 };
0061
0062
0063 int ll_enable_coherency(void);
0064 void ll_add_cpu_to_smp_group(void);
0065
0066 #define CPU_CONFIG_SHARED_L2 BIT(16)
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079 static void armada_xp_clear_shared_l2(void)
0080 {
0081 u32 reg;
0082
0083 if (!cpu_config_base)
0084 return;
0085
0086 reg = readl(cpu_config_base);
0087 reg &= ~CPU_CONFIG_SHARED_L2;
0088 writel(reg, cpu_config_base);
0089 }
0090
0091 static int mvebu_hwcc_notifier(struct notifier_block *nb,
0092 unsigned long event, void *__dev)
0093 {
0094 struct device *dev = __dev;
0095
0096 if (event != BUS_NOTIFY_ADD_DEVICE)
0097 return NOTIFY_DONE;
0098 dev->dma_coherent = true;
0099
0100 return NOTIFY_OK;
0101 }
0102
0103 static struct notifier_block mvebu_hwcc_nb = {
0104 .notifier_call = mvebu_hwcc_notifier,
0105 };
0106
0107 static struct notifier_block mvebu_hwcc_pci_nb __maybe_unused = {
0108 .notifier_call = mvebu_hwcc_notifier,
0109 };
0110
0111 static int armada_xp_clear_l2_starting(unsigned int cpu)
0112 {
0113 armada_xp_clear_shared_l2();
0114 return 0;
0115 }
0116
0117 static void __init armada_370_coherency_init(struct device_node *np)
0118 {
0119 struct resource res;
0120 struct device_node *cpu_config_np;
0121
0122 of_address_to_resource(np, 0, &res);
0123 coherency_phys_base = res.start;
0124
0125
0126
0127
0128
0129
0130 sync_cache_w(&coherency_phys_base);
0131 coherency_base = of_iomap(np, 0);
0132 coherency_cpu_base = of_iomap(np, 1);
0133
0134 cpu_config_np = of_find_compatible_node(NULL, NULL,
0135 "marvell,armada-xp-cpu-config");
0136 if (!cpu_config_np)
0137 goto exit;
0138
0139 cpu_config_base = of_iomap(cpu_config_np, 0);
0140 if (!cpu_config_base) {
0141 of_node_put(cpu_config_np);
0142 goto exit;
0143 }
0144
0145 of_node_put(cpu_config_np);
0146
0147 cpuhp_setup_state_nocalls(CPUHP_AP_ARM_MVEBU_COHERENCY,
0148 "arm/mvebu/coherency:starting",
0149 armada_xp_clear_l2_starting, NULL);
0150 exit:
0151 set_cpu_coherent();
0152 }
0153
0154
0155
0156
0157
0158
0159
0160 static void __iomem *
0161 armada_wa_ioremap_caller(phys_addr_t phys_addr, size_t size,
0162 unsigned int mtype, void *caller)
0163 {
0164 mtype = MT_UNCACHED;
0165 return __arm_ioremap_caller(phys_addr, size, mtype, caller);
0166 }
0167
0168 static void __init armada_375_380_coherency_init(struct device_node *np)
0169 {
0170 struct device_node *cache_dn;
0171
0172 coherency_cpu_base = of_iomap(np, 0);
0173 arch_ioremap_caller = armada_wa_ioremap_caller;
0174 pci_ioremap_set_mem_type(MT_UNCACHED);
0175
0176
0177
0178
0179
0180 if (!coherency_available())
0181 return;
0182
0183
0184
0185
0186
0187
0188
0189
0190 for_each_compatible_node(cache_dn, NULL, "arm,pl310-cache") {
0191 struct property *p;
0192
0193 p = kzalloc(sizeof(*p), GFP_KERNEL);
0194 p->name = kstrdup("arm,io-coherent", GFP_KERNEL);
0195 of_add_property(cache_dn, p);
0196 }
0197 }
0198
0199 static int coherency_type(void)
0200 {
0201 struct device_node *np;
0202 const struct of_device_id *match;
0203 int type;
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 if (!is_smp())
0227 return COHERENCY_FABRIC_TYPE_NONE;
0228
0229 np = of_find_matching_node_and_match(NULL, of_coherency_table, &match);
0230 if (!np)
0231 return COHERENCY_FABRIC_TYPE_NONE;
0232
0233 type = (int) match->data;
0234
0235 of_node_put(np);
0236
0237 return type;
0238 }
0239
0240 int set_cpu_coherent(void)
0241 {
0242 int type = coherency_type();
0243
0244 if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP) {
0245 if (!coherency_base) {
0246 pr_warn("Can't make current CPU cache coherent.\n");
0247 pr_warn("Coherency fabric is not initialized\n");
0248 return 1;
0249 }
0250
0251 armada_xp_clear_shared_l2();
0252 ll_add_cpu_to_smp_group();
0253 return ll_enable_coherency();
0254 }
0255
0256 return 0;
0257 }
0258
0259 int coherency_available(void)
0260 {
0261 return coherency_type() != COHERENCY_FABRIC_TYPE_NONE;
0262 }
0263
0264 int __init coherency_init(void)
0265 {
0266 int type = coherency_type();
0267 struct device_node *np;
0268
0269 np = of_find_matching_node(NULL, of_coherency_table);
0270
0271 if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP)
0272 armada_370_coherency_init(np);
0273 else if (type == COHERENCY_FABRIC_TYPE_ARMADA_375 ||
0274 type == COHERENCY_FABRIC_TYPE_ARMADA_380)
0275 armada_375_380_coherency_init(np);
0276
0277 of_node_put(np);
0278
0279 return 0;
0280 }
0281
0282 static int __init coherency_late_init(void)
0283 {
0284 if (coherency_available())
0285 bus_register_notifier(&platform_bus_type,
0286 &mvebu_hwcc_nb);
0287 return 0;
0288 }
0289
0290 postcore_initcall(coherency_late_init);
0291
0292 #if IS_ENABLED(CONFIG_PCI)
0293 static int __init coherency_pci_init(void)
0294 {
0295 if (coherency_available())
0296 bus_register_notifier(&pci_bus_type,
0297 &mvebu_hwcc_pci_nb);
0298 return 0;
0299 }
0300
0301 arch_initcall(coherency_pci_init);
0302 #endif