ARM: mvebu: implement L2/PCIe deadlock workaround
[deliverable/linux.git] / arch / arm / mach-mvebu / coherency.c
index 5723178f658954a2328964f380278fc0c4ae7757..a2225070ac3d62314425b738a4fcbcf7319c0f1e 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/pci.h>
 #include <asm/smp_plat.h>
 #include <asm/cacheflush.h>
+#include <asm/mach/map.h>
 #include "armada-370-xp.h"
 #include "coherency.h"
 #include "mvebu-soc-id.h"
@@ -309,9 +310,47 @@ static void __init armada_370_coherency_init(struct device_node *np)
        set_cpu_coherent();
 }
 
+/*
+ * This ioremap hook is used on Armada 375/38x to ensure that PCIe
+ * memory areas are mapped as MT_UNCACHED instead of MT_DEVICE. This
+ * is needed as a workaround for a deadlock issue between the PCIe
+ * interface and the cache controller.
+ */
+static void __iomem *
+armada_pcie_wa_ioremap_caller(phys_addr_t phys_addr, size_t size,
+                             unsigned int mtype, void *caller)
+{
+       struct resource pcie_mem;
+
+       mvebu_mbus_get_pcie_mem_aperture(&pcie_mem);
+
+       if (pcie_mem.start <= phys_addr && (phys_addr + size) <= pcie_mem.end)
+               mtype = MT_UNCACHED;
+
+       return __arm_ioremap_caller(phys_addr, size, mtype, caller);
+}
+
 static void __init armada_375_380_coherency_init(struct device_node *np)
 {
+       struct device_node *cache_dn;
+
        coherency_cpu_base = of_iomap(np, 0);
+       arch_ioremap_caller = armada_pcie_wa_ioremap_caller;
+
+       /*
+        * Add the PL310 property "arm,io-coherent". This makes sure the
+        * outer sync operation is not used, which allows to
+        * workaround the system erratum that causes deadlocks when
+        * doing PCIe in an SMP situation on Armada 375 and Armada
+        * 38x.
+        */
+       for_each_compatible_node(cache_dn, NULL, "arm,pl310-cache") {
+               struct property *p;
+
+               p = kzalloc(sizeof(*p), GFP_KERNEL);
+               p->name = kstrdup("arm,io-coherent", GFP_KERNEL);
+               of_add_property(cache_dn, p);
+       }
 }
 
 static int coherency_type(void)
This page took 0.131721 seconds and 5 git commands to generate.