diff options
| -rw-r--r-- | arch/arm/mach-mvebu/coherency.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index 5723178f6589..a2225070ac3d 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/pci.h> | 32 | #include <linux/pci.h> |
| 33 | #include <asm/smp_plat.h> | 33 | #include <asm/smp_plat.h> |
| 34 | #include <asm/cacheflush.h> | 34 | #include <asm/cacheflush.h> |
| 35 | #include <asm/mach/map.h> | ||
| 35 | #include "armada-370-xp.h" | 36 | #include "armada-370-xp.h" |
| 36 | #include "coherency.h" | 37 | #include "coherency.h" |
| 37 | #include "mvebu-soc-id.h" | 38 | #include "mvebu-soc-id.h" |
| @@ -309,9 +310,47 @@ static void __init armada_370_coherency_init(struct device_node *np) | |||
| 309 | set_cpu_coherent(); | 310 | set_cpu_coherent(); |
| 310 | } | 311 | } |
| 311 | 312 | ||
| 313 | /* | ||
| 314 | * This ioremap hook is used on Armada 375/38x to ensure that PCIe | ||
| 315 | * memory areas are mapped as MT_UNCACHED instead of MT_DEVICE. This | ||
| 316 | * is needed as a workaround for a deadlock issue between the PCIe | ||
| 317 | * interface and the cache controller. | ||
| 318 | */ | ||
| 319 | static void __iomem * | ||
| 320 | armada_pcie_wa_ioremap_caller(phys_addr_t phys_addr, size_t size, | ||
| 321 | unsigned int mtype, void *caller) | ||
| 322 | { | ||
| 323 | struct resource pcie_mem; | ||
| 324 | |||
| 325 | mvebu_mbus_get_pcie_mem_aperture(&pcie_mem); | ||
| 326 | |||
| 327 | if (pcie_mem.start <= phys_addr && (phys_addr + size) <= pcie_mem.end) | ||
| 328 | mtype = MT_UNCACHED; | ||
| 329 | |||
| 330 | return __arm_ioremap_caller(phys_addr, size, mtype, caller); | ||
| 331 | } | ||
| 332 | |||
| 312 | static void __init armada_375_380_coherency_init(struct device_node *np) | 333 | static void __init armada_375_380_coherency_init(struct device_node *np) |
| 313 | { | 334 | { |
| 335 | struct device_node *cache_dn; | ||
| 336 | |||
| 314 | coherency_cpu_base = of_iomap(np, 0); | 337 | coherency_cpu_base = of_iomap(np, 0); |
| 338 | arch_ioremap_caller = armada_pcie_wa_ioremap_caller; | ||
| 339 | |||
| 340 | /* | ||
| 341 | * Add the PL310 property "arm,io-coherent". This makes sure the | ||
| 342 | * outer sync operation is not used, which allows to | ||
| 343 | * workaround the system erratum that causes deadlocks when | ||
| 344 | * doing PCIe in an SMP situation on Armada 375 and Armada | ||
| 345 | * 38x. | ||
| 346 | */ | ||
| 347 | for_each_compatible_node(cache_dn, NULL, "arm,pl310-cache") { | ||
| 348 | struct property *p; | ||
| 349 | |||
| 350 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 351 | p->name = kstrdup("arm,io-coherent", GFP_KERNEL); | ||
| 352 | of_add_property(cache_dn, p); | ||
| 353 | } | ||
| 315 | } | 354 | } |
| 316 | 355 | ||
| 317 | static int coherency_type(void) | 356 | static int coherency_type(void) |
