Skip to content

Commit 37f5f4e

Browse files
committed
Merge tag 'mvebu-soc-3.16-2' of git://git.infradead.org/linux-mvebu into next/soc
Merge "mvebu SoC changes for v3.16 (incremental #2)" from Jason Cooper <[email protected]>: - mvebu - fix coherency on big-endian in -next - hardware IO coherency - L2/PCIe deadlock workaround - small coherency cleanups * tag 'mvebu-soc-3.16-2' of git://git.infradead.org/linux-mvebu: ARM: mvebu: returns ll_get_cpuid() to ll_get_coherency_cpumask() ARM: mvebu: improve comments in coherency_ll.S ARM: mvebu: fix indentation of assembly instructions in coherency_ll.S ARM: mvebu: fix big endian booting after coherency code rework ARM: mvebu: coherency: fix registration of PCI bus notifier when !PCI ARM: mvebu: implement L2/PCIe deadlock workaround ARM: mvebu: use hardware I/O coherency also for PCI devices Signed-off-by: Arnd Bergmann <[email protected]>
2 parents 650052b + 07ae144 commit 37f5f4e

File tree

2 files changed

+106
-33
lines changed

2 files changed

+106
-33
lines changed

arch/arm/mach-mvebu/coherency.c

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@
2929
#include <linux/slab.h>
3030
#include <linux/mbus.h>
3131
#include <linux/clk.h>
32+
#include <linux/pci.h>
3233
#include <asm/smp_plat.h>
3334
#include <asm/cacheflush.h>
35+
#include <asm/mach/map.h>
3436
#include "armada-370-xp.h"
3537
#include "coherency.h"
3638
#include "mvebu-soc-id.h"
@@ -274,8 +276,8 @@ static struct dma_map_ops mvebu_hwcc_dma_ops = {
274276
.set_dma_mask = arm_dma_set_mask,
275277
};
276278

277-
static int mvebu_hwcc_platform_notifier(struct notifier_block *nb,
278-
unsigned long event, void *__dev)
279+
static int mvebu_hwcc_notifier(struct notifier_block *nb,
280+
unsigned long event, void *__dev)
279281
{
280282
struct device *dev = __dev;
281283

@@ -286,8 +288,8 @@ static int mvebu_hwcc_platform_notifier(struct notifier_block *nb,
286288
return NOTIFY_OK;
287289
}
288290

289-
static struct notifier_block mvebu_hwcc_platform_nb = {
290-
.notifier_call = mvebu_hwcc_platform_notifier,
291+
static struct notifier_block mvebu_hwcc_nb = {
292+
.notifier_call = mvebu_hwcc_notifier,
291293
};
292294

293295
static void __init armada_370_coherency_init(struct device_node *np)
@@ -308,9 +310,47 @@ static void __init armada_370_coherency_init(struct device_node *np)
308310
set_cpu_coherent();
309311
}
310312

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+
311333
static void __init armada_375_380_coherency_init(struct device_node *np)
312334
{
335+
struct device_node *cache_dn;
336+
313337
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+
}
314354
}
315355

316356
static int coherency_type(void)
@@ -375,9 +415,21 @@ static int __init coherency_late_init(void)
375415
}
376416

377417
bus_register_notifier(&platform_bus_type,
378-
&mvebu_hwcc_platform_nb);
418+
&mvebu_hwcc_nb);
379419

380420
return 0;
381421
}
382422

383423
postcore_initcall(coherency_late_init);
424+
425+
#if IS_ENABLED(CONFIG_PCI)
426+
static int __init coherency_pci_init(void)
427+
{
428+
if (coherency_available())
429+
bus_register_notifier(&pci_bus_type,
430+
&mvebu_hwcc_nb);
431+
return 0;
432+
}
433+
434+
arch_initcall(coherency_pci_init);
435+
#endif

arch/arm/mach-mvebu/coherency_ll.S

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,52 +24,69 @@
2424
#include <asm/cp15.h>
2525

2626
.text
27-
/* Returns with the coherency address in r1 (r0 is untouched)*/
27+
/* Returns the coherency base address in r1 (r0 is untouched) */
2828
ENTRY(ll_get_coherency_base)
2929
mrc p15, 0, r1, c1, c0, 0
3030
tst r1, #CR_M @ Check MMU bit enabled
3131
bne 1f
3232

33-
/* use physical address of the coherency register */
33+
/*
34+
* MMU is disabled, use the physical address of the coherency
35+
* base address.
36+
*/
3437
adr r1, 3f
3538
ldr r3, [r1]
3639
ldr r1, [r1, r3]
3740
b 2f
3841
1:
39-
/* use virtual address of the coherency register */
42+
/*
43+
* MMU is enabled, use the virtual address of the coherency
44+
* base address.
45+
*/
4046
ldr r1, =coherency_base
4147
ldr r1, [r1]
4248
2:
4349
mov pc, lr
4450
ENDPROC(ll_get_coherency_base)
4551

46-
/* Returns with the CPU ID in r3 (r0 is untouched)*/
47-
ENTRY(ll_get_cpuid)
52+
/*
53+
* Returns the coherency CPU mask in r3 (r0 is untouched). This
54+
* coherency CPU mask can be used with the coherency fabric
55+
* configuration and control registers. Note that the mask is already
56+
* endian-swapped as appropriate so that the calling functions do not
57+
* have to care about endianness issues while accessing the coherency
58+
* fabric registers
59+
*/
60+
ENTRY(ll_get_coherency_cpumask)
4861
mrc 15, 0, r3, cr0, cr0, 5
4962
and r3, r3, #15
5063
mov r2, #(1 << 24)
5164
lsl r3, r2, r3
52-
ARM_BE8(rev r1, r1)
65+
ARM_BE8(rev r3, r3)
5366
mov pc, lr
54-
ENDPROC(ll_get_cpuid)
67+
ENDPROC(ll_get_coherency_cpumask)
5568

56-
/* ll_add_cpu_to_smp_group, ll_enable_coherency and
57-
* ll_disable_coherency use strex/ldrex whereas MMU can be off. The
58-
* Armada XP SoC has an exclusive monitor that can track transactions
59-
* to Device and/or SO and as such also when MMU is disabled the
60-
* exclusive transactions will be functional
69+
/*
70+
* ll_add_cpu_to_smp_group(), ll_enable_coherency() and
71+
* ll_disable_coherency() use the strex/ldrex instructions while the
72+
* MMU can be disabled. The Armada XP SoC has an exclusive monitor
73+
* that tracks transactions to Device and/or SO memory and thanks to
74+
* that, exclusive transactions are functional even when the MMU is
75+
* disabled.
6176
*/
6277

6378
ENTRY(ll_add_cpu_to_smp_group)
6479
/*
65-
* r0 being untouched in ll_get_coherency_base and
66-
* ll_get_cpuid, we can use it to save lr modifing it with the
67-
* following bl
80+
* As r0 is not modified by ll_get_coherency_base() and
81+
* ll_get_coherency_cpumask(), we use it to temporarly save lr
82+
* and avoid it being modified by the branch and link
83+
* calls. This function is used very early in the secondary
84+
* CPU boot, and no stack is available at this point.
6885
*/
69-
mov r0, lr
86+
mov r0, lr
7087
bl ll_get_coherency_base
71-
bl ll_get_cpuid
72-
mov lr, r0
88+
bl ll_get_coherency_cpumask
89+
mov lr, r0
7390
add r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET
7491
1:
7592
ldrex r2, [r0]
@@ -82,13 +99,15 @@ ENDPROC(ll_add_cpu_to_smp_group)
8299

83100
ENTRY(ll_enable_coherency)
84101
/*
85-
* r0 being untouched in ll_get_coherency_base and
86-
* ll_get_cpuid, we can use it to save lr modifing it with the
87-
* following bl
102+
* As r0 is not modified by ll_get_coherency_base() and
103+
* ll_get_coherency_cpumask(), we use it to temporarly save lr
104+
* and avoid it being modified by the branch and link
105+
* calls. This function is used very early in the secondary
106+
* CPU boot, and no stack is available at this point.
88107
*/
89108
mov r0, lr
90109
bl ll_get_coherency_base
91-
bl ll_get_cpuid
110+
bl ll_get_coherency_cpumask
92111
mov lr, r0
93112
add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
94113
1:
@@ -104,14 +123,16 @@ ENDPROC(ll_enable_coherency)
104123

105124
ENTRY(ll_disable_coherency)
106125
/*
107-
* r0 being untouched in ll_get_coherency_base and
108-
* ll_get_cpuid, we can use it to save lr modifing it with the
109-
* following bl
126+
* As r0 is not modified by ll_get_coherency_base() and
127+
* ll_get_coherency_cpumask(), we use it to temporarly save lr
128+
* and avoid it being modified by the branch and link
129+
* calls. This function is used very early in the secondary
130+
* CPU boot, and no stack is available at this point.
110131
*/
111-
mov r0, lr
132+
mov r0, lr
112133
bl ll_get_coherency_base
113-
bl ll_get_cpuid
114-
mov lr, r0
134+
bl ll_get_coherency_cpumask
135+
mov lr, r0
115136
add r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
116137
1:
117138
ldrex r2, [r0]

0 commit comments

Comments
 (0)