|
@@ -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)
|