* [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x
@ 2014-03-06 16:46 Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 01/10] ARM: mvebu: prepare coherency code to support more SOCs Thomas Petazzoni
` (10 more replies)
0 siblings, 11 replies; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-06 16:46 UTC (permalink / raw)
To: linux-arm-kernel
Jason, Gregory, Andrew, Sebastian,
This set of patches add hardware coherency support for the new Armada
375 and Armada 38x SoCs. The patch set can be divided in three
sections:
* Patches 1, 2, 3 and 4 prepare the introduction of the support for
new SoC in the existing coherency code.
The main change is that the mvebu-mbus driver no longer pokes into
the Device Tree to find whether hardware I/O coherency is available
or not: this information is passed as argument to the mvebu-mbus
initialization function. This avoids changing the mvebu-mbus driver
to add the compatible strings of all possible coherency fabrics,
and also avoids encoding specific conditions in the mvebu-mbus
driver: on Armada 375 and 38x, the hardware I/O coherency can only
be enabled in SMP mode.
These preparation patches had already been sent in the past
(http://permalink.gmane.org/gmane.linux.ports.arm.kernel/290780). This
round has taken into account the comments I had received on this
early version.
* Patches 5, 6, 7 and 8 add the coherency support itself. Patch 4
enables the SCU, patch 5 adds I/O coherency support for 375, patch
6 adds a major workaround to make coherency support actually work
on early 375 SOCs and patch 7 adds I/O coherency support for 38x.
* Patches 9 and 10 add the necessary Device Tree informations to
enable the coherency.
Best regards,
Thomas
Thomas Petazzoni (10):
ARM: mvebu: prepare coherency code to support more SOCs
ARM: mvebu: add a coherency_available() call
bus: mvebu: pass the coherency availability information at init time
ARM: mvebu: ARM: mvebu: use of_find_matching_node_and_match() in
coherency.c
ARM: mvebu: enable the ARM SCU on Armada 375 and Armada 38x
ARM: mvebu: add Armada 375 support to the coherency code
ARM: mvebu: implement Armada 375 coherency workaround
ARM: mvebu: add Armada 38x support to the coherency code
ARM: mvebu: enable the coherency fabric on Armada 375
ARM: mvebu: enable the coherency fabric on Armada 38x
.../devicetree/bindings/arm/coherency-fabric.txt | 32 ++-
arch/arm/boot/dts/armada-375.dtsi | 10 +
arch/arm/boot/dts/armada-38x.dtsi | 10 +
arch/arm/mach-kirkwood/board-dt.c | 2 +-
arch/arm/mach-mvebu/Kconfig | 2 +
arch/arm/mach-mvebu/board-v7.c | 21 +-
arch/arm/mach-mvebu/coherency.c | 251 +++++++++++++++++++--
arch/arm/mach-mvebu/coherency.h | 1 +
drivers/bus/mvebu-mbus.c | 11 +-
include/linux/mbus.h | 2 +-
10 files changed, 305 insertions(+), 37 deletions(-)
--
1.8.3.2
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 01/10] ARM: mvebu: prepare coherency code to support more SOCs
2014-03-06 16:46 [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
@ 2014-03-06 16:46 ` Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 02/10] ARM: mvebu: add a coherency_available() call Thomas Petazzoni
` (9 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-06 16:46 UTC (permalink / raw)
To: linux-arm-kernel
The code that handles the coherency fabric of Armada 370 and Armada XP
in arch/arm/mach-mvebu/coherency.c made the assumption that there was
only one type of coherency fabric. Unfortunately, it turns out that
upcoming SoCs have a slightly different coherency unit.
In preparation to the introduction of the coherency support for more
SoCs, this commit:
* Introduces a data associated to the compatible string in the
compatible string match table, so that the code can differantiate
the variant of coherency unit being used.
* Separates the coherency unit initialization code into its own
function.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
.../devicetree/bindings/arm/coherency-fabric.txt | 5 ++-
arch/arm/mach-mvebu/coherency.c | 46 +++++++++++++++-------
2 files changed, 36 insertions(+), 15 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/coherency-fabric.txt b/Documentation/devicetree/bindings/arm/coherency-fabric.txt
index 17d8cd1..f0bfa37 100644
--- a/Documentation/devicetree/bindings/arm/coherency-fabric.txt
+++ b/Documentation/devicetree/bindings/arm/coherency-fabric.txt
@@ -4,7 +4,10 @@ Available on Marvell SOCs: Armada 370 and Armada XP
Required properties:
-- compatible: "marvell,coherency-fabric"
+- compatible: the possible values are:
+
+ * "marvell,coherency-fabric", to be used for the coherency fabric of
+ the Armada 370 and Armada XP.
- reg: Should contain coherency fabric registers location and
length. First pair for the coherency fabric registers, second pair
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index 4e9d581..72d8d75 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -38,8 +38,13 @@ static void __iomem *coherency_cpu_base;
#define IO_SYNC_BARRIER_CTL_OFFSET 0x0
+enum {
+ COHERENCY_FABRIC_TYPE_ARMADA_370_XP,
+};
+
static struct of_device_id of_coherency_table[] = {
- {.compatible = "marvell,coherency-fabric"},
+ {.compatible = "marvell,coherency-fabric",
+ .data = (void*) COHERENCY_FABRIC_TYPE_ARMADA_370_XP },
{ /* end of list */ },
};
@@ -121,26 +126,39 @@ static struct notifier_block mvebu_hwcc_platform_nb = {
.notifier_call = mvebu_hwcc_platform_notifier,
};
+static void __init armada_370_coherency_init(struct device_node *np)
+{
+ struct resource res;
+ of_address_to_resource(np, 0, &res);
+ coherency_phys_base = res.start;
+ /*
+ * Ensure secondary CPUs will see the updated value,
+ * which they read before they join the coherency
+ * fabric, and therefore before they are coherent with
+ * the boot CPU cache.
+ */
+ sync_cache_w(&coherency_phys_base);
+ coherency_base = of_iomap(np, 0);
+ coherency_cpu_base = of_iomap(np, 1);
+ set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
+}
+
int __init coherency_init(void)
{
struct device_node *np;
np = of_find_matching_node(NULL, of_coherency_table);
if (np) {
- struct resource res;
+ const struct of_device_id *match =
+ of_match_node(of_coherency_table, np);
+ int type;
+
+ type = (int) match->data;
pr_info("Initializing Coherency fabric\n");
- of_address_to_resource(np, 0, &res);
- coherency_phys_base = res.start;
- /*
- * Ensure secondary CPUs will see the updated value,
- * which they read before they join the coherency
- * fabric, and therefore before they are coherent with
- * the boot CPU cache.
- */
- sync_cache_w(&coherency_phys_base);
- coherency_base = of_iomap(np, 0);
- coherency_cpu_base = of_iomap(np, 1);
- set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
+
+ if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP)
+ armada_370_coherency_init(np);
+
of_node_put(np);
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 02/10] ARM: mvebu: add a coherency_available() call
2014-03-06 16:46 [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 01/10] ARM: mvebu: prepare coherency code to support more SOCs Thomas Petazzoni
@ 2014-03-06 16:46 ` Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 03/10] bus: mvebu: pass the coherency availability information at init time Thomas Petazzoni
` (8 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-06 16:46 UTC (permalink / raw)
To: linux-arm-kernel
This commit extends the coherency fabric code to provide a
coherency_available()function that the SoC code can call to be told
whether coherency support is available or not. On Armada 370/XP,
coherency support is available as soon as the relevant DT node is
present. On some upcoming SoCs, the DT node needs to be present *and*
the system running with CONFIG_SMP enabled.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
arch/arm/mach-mvebu/coherency.c | 30 +++++++++++++++++++++++-------
arch/arm/mach-mvebu/coherency.h | 1 +
2 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index 72d8d75..0c440c3 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -39,6 +39,7 @@ static void __iomem *coherency_cpu_base;
#define IO_SYNC_BARRIER_CTL_OFFSET 0x0
enum {
+ COHERENCY_FABRIC_TYPE_NONE,
COHERENCY_FABRIC_TYPE_ARMADA_370_XP,
};
@@ -143,7 +144,7 @@ static void __init armada_370_coherency_init(struct device_node *np)
set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
}
-int __init coherency_init(void)
+static int coherency_type(void)
{
struct device_node *np;
@@ -154,27 +155,42 @@ int __init coherency_init(void)
int type;
type = (int) match->data;
+
pr_info("Initializing Coherency fabric\n");
+ /* Armada 370/XP coherency works in both UP and SMP */
if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP)
- armada_370_coherency_init(np);
+ return type;
of_node_put(np);
}
- return 0;
+ return COHERENCY_FABRIC_TYPE_NONE;
}
-static int __init coherency_late_init(void)
+int coherency_available(void)
{
+ return coherency_type() != COHERENCY_FABRIC_TYPE_NONE;
+}
+
+int __init coherency_init(void)
+{
+ int type = coherency_type();
struct device_node *np;
np = of_find_matching_node(NULL, of_coherency_table);
- if (np) {
+
+ if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP)
+ armada_370_coherency_init(np);
+
+ return 0;
+}
+
+static int __init coherency_late_init(void)
+{
+ if (coherency_available())
bus_register_notifier(&platform_bus_type,
&mvebu_hwcc_platform_nb);
- of_node_put(np);
- }
return 0;
}
diff --git a/arch/arm/mach-mvebu/coherency.h b/arch/arm/mach-mvebu/coherency.h
index 760226c..02f7ec3 100644
--- a/arch/arm/mach-mvebu/coherency.h
+++ b/arch/arm/mach-mvebu/coherency.h
@@ -18,5 +18,6 @@ extern unsigned long coherency_phys_base;
int set_cpu_coherent(unsigned int cpu_id, int smp_group_id);
int coherency_init(void);
+int coherency_available(void);
#endif /* __MACH_370_XP_COHERENCY_H */
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 03/10] bus: mvebu: pass the coherency availability information at init time
2014-03-06 16:46 [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 01/10] ARM: mvebu: prepare coherency code to support more SOCs Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 02/10] ARM: mvebu: add a coherency_available() call Thomas Petazzoni
@ 2014-03-06 16:46 ` Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 04/10] ARM: mvebu: ARM: mvebu: use of_find_matching_node_and_match() in coherency.c Thomas Petazzoni
` (7 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-06 16:46 UTC (permalink / raw)
To: linux-arm-kernel
Until now, the mvebu-mbus was guessing by itself whether hardware I/O
coherency was available or not by poking into the Device Tree to see
if the coherency fabric Device Tree node was present or not.
However, on some upcoming SoCs, the presence or absence of the
coherency fabric DT node isn't sufficient: in CONFIG_SMP, the
coherency can be enabled, but not in !CONFIG_SMP.
In order to clean this up, the mvebu_mbus_dt_init() function is
extended to get a boolean argument telling whether coherency is
enabled or not. Therefore, the logic to decide whether coherency is
available or not now belongs to the core SoC code instead of the
mvebu-mbus driver itself, which is much better.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
arch/arm/mach-kirkwood/board-dt.c | 2 +-
arch/arm/mach-mvebu/board-v7.c | 2 +-
drivers/bus/mvebu-mbus.c | 11 +++--------
include/linux/mbus.h | 2 +-
4 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index 7818815..79e629d 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -116,7 +116,7 @@ static void __init kirkwood_dt_init(void)
*/
writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG);
- BUG_ON(mvebu_mbus_dt_init());
+ BUG_ON(mvebu_mbus_dt_init(false));
kirkwood_l2_init();
diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
index 95ca216..e5d4f69 100644
--- a/arch/arm/mach-mvebu/board-v7.c
+++ b/arch/arm/mach-mvebu/board-v7.c
@@ -62,7 +62,7 @@ static void __init mvebu_timer_and_clk_init(void)
of_clk_init(NULL);
clocksource_of_init();
coherency_init();
- BUG_ON(mvebu_mbus_dt_init());
+ BUG_ON(mvebu_mbus_dt_init(coherency_available()));
#ifdef CONFIG_CACHE_L2X0
l2x0_of_init(0, ~0UL);
#endif
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 725c461..67710b8 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -694,7 +694,6 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
phys_addr_t sdramwins_phys_base,
size_t sdramwins_size)
{
- struct device_node *np;
int win;
mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size);
@@ -707,12 +706,6 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
return -ENOMEM;
}
- np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
- if (np) {
- mbus->hw_io_coherency = 1;
- of_node_put(np);
- }
-
for (win = 0; win < mbus->soc->num_wins; win++)
mvebu_mbus_disable_window(mbus, win);
@@ -882,7 +875,7 @@ static void __init mvebu_mbus_get_pcie_resources(struct device_node *np,
}
}
-int __init mvebu_mbus_dt_init(void)
+int __init mvebu_mbus_dt_init(bool is_coherent)
{
struct resource mbuswins_res, sdramwins_res;
struct device_node *np, *controller;
@@ -921,6 +914,8 @@ int __init mvebu_mbus_dt_init(void)
return -EINVAL;
}
+ mbus_state.hw_io_coherency = is_coherent;
+
/* Get optional pcie-{mem,io}-aperture properties */
mvebu_mbus_get_pcie_resources(np, &mbus_state.pcie_mem_aperture,
&mbus_state.pcie_io_aperture);
diff --git a/include/linux/mbus.h b/include/linux/mbus.h
index 345b8c5..550c88f 100644
--- a/include/linux/mbus.h
+++ b/include/linux/mbus.h
@@ -73,6 +73,6 @@ int mvebu_mbus_del_window(phys_addr_t base, size_t size);
int mvebu_mbus_init(const char *soc, phys_addr_t mbus_phys_base,
size_t mbus_size, phys_addr_t sdram_phys_base,
size_t sdram_size);
-int mvebu_mbus_dt_init(void);
+int mvebu_mbus_dt_init(bool is_coherent);
#endif /* __LINUX_MBUS_H */
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 04/10] ARM: mvebu: ARM: mvebu: use of_find_matching_node_and_match() in coherency.c
2014-03-06 16:46 [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
` (2 preceding siblings ...)
2014-03-06 16:46 ` [PATCH 03/10] bus: mvebu: pass the coherency availability information at init time Thomas Petazzoni
@ 2014-03-06 16:46 ` Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 05/10] ARM: mvebu: enable the ARM SCU on Armada 375 and Armada 38x Thomas Petazzoni
` (6 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-06 16:46 UTC (permalink / raw)
To: linux-arm-kernel
In the mach-mvebu coherency code, instead of using
of_find_matching_node() and then of_match_node(), directly use the
of_find_matching_node_and_match() which does both at once.
We take this opportunity to also simplify the initialization of the
"type" variable.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
arch/arm/mach-mvebu/coherency.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index 0c440c3..15b769d 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -147,14 +147,11 @@ static void __init armada_370_coherency_init(struct device_node *np)
static int coherency_type(void)
{
struct device_node *np;
+ const struct of_device_id *match;
- np = of_find_matching_node(NULL, of_coherency_table);
+ np = of_find_matching_node_and_match(NULL, of_coherency_table, &match);
if (np) {
- const struct of_device_id *match =
- of_match_node(of_coherency_table, np);
- int type;
-
- type = (int) match->data;
+ int type = (int) match->data;
pr_info("Initializing Coherency fabric\n");
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 05/10] ARM: mvebu: enable the ARM SCU on Armada 375 and Armada 38x
2014-03-06 16:46 [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
` (3 preceding siblings ...)
2014-03-06 16:46 ` [PATCH 04/10] ARM: mvebu: ARM: mvebu: use of_find_matching_node_and_match() in coherency.c Thomas Petazzoni
@ 2014-03-06 16:46 ` Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 06/10] ARM: mvebu: add Armada 375 support to the coherency code Thomas Petazzoni
` (5 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-06 16:46 UTC (permalink / raw)
To: linux-arm-kernel
Contrary to the Armada 370 and XP that used the PJ4B Marvell cores,
the Armada 375 and Armada 38x use the ARM Cortex-A9. A consequence of
this is that the unit responsible for the coherency between CPUs is
now the ARM SCU, and not the Marvell coherency unit (which is still
present to do coherency with I/O devices).
Therefore this commit:
* Ensures that the selection of the Armada 375 or Armada 38x SoC
support enables the ARM SCU support in the kernel.
* Make sure to initialize the SCU at boot time.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
arch/arm/mach-mvebu/Kconfig | 2 ++
arch/arm/mach-mvebu/board-v7.c | 19 +++++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 884b275a..8634222 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -44,6 +44,7 @@ config MACH_ARMADA_375
select ARM_GIC
select ARMADA_375_CLK
select CPU_V7
+ select HAVE_ARM_SCU
select MACH_MVEBU_V7
select NEON
select PINCTRL_ARMADA_375
@@ -58,6 +59,7 @@ config MACH_ARMADA_38X
select ARM_GIC
select ARMADA_38X_CLK
select CPU_V7
+ select HAVE_ARM_SCU
select MACH_MVEBU_V7
select NEON
select PINCTRL_ARMADA_38X
diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
index e5d4f69..256e6f6 100644
--- a/arch/arm/mach-mvebu/board-v7.c
+++ b/arch/arm/mach-mvebu/board-v7.c
@@ -26,6 +26,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
+#include <asm/smp_scu.h>
#include "armada-370-xp.h"
#include "common.h"
#include "coherency.h"
@@ -37,6 +38,23 @@ static void __init mvebu_map_io(void)
}
/*
+ * Enables the SCU when available. Obviously, this is only useful on
+ * Cortex-A based SOCs, not on PJ4B based ones.
+ */
+static void __init mvebu_scu_enable(void)
+{
+ void __iomem *scu_base;
+
+ struct device_node *np =
+ of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+ if (np) {
+ scu_base = of_iomap(np, 0);
+ scu_enable(scu_base);
+ of_node_put(np);
+ }
+}
+
+/*
* Early versions of Armada 375 SoC have a bug where the BootROM
* leaves an external data abort pending. The kernel is hit by this
* data abort as soon as it enters userspace, because it unmasks the
@@ -61,6 +79,7 @@ static void __init mvebu_timer_and_clk_init(void)
{
of_clk_init(NULL);
clocksource_of_init();
+ mvebu_scu_enable();
coherency_init();
BUG_ON(mvebu_mbus_dt_init(coherency_available()));
#ifdef CONFIG_CACHE_L2X0
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 06/10] ARM: mvebu: add Armada 375 support to the coherency code
2014-03-06 16:46 [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
` (4 preceding siblings ...)
2014-03-06 16:46 ` [PATCH 05/10] ARM: mvebu: enable the ARM SCU on Armada 375 and Armada 38x Thomas Petazzoni
@ 2014-03-06 16:46 ` Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 07/10] ARM: mvebu: implement Armada 375 coherency workaround Thomas Petazzoni
` (4 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-06 16:46 UTC (permalink / raw)
To: linux-arm-kernel
The Armada 375, like the Armada 370 and Armada XP, has a coherency
unit. However, unlike the coherency unit of 370/XP which does both CPU
and I/O coherency, the one on Armada 735 only does I/O
coherency. Therefore, instead of having two sets of registers (the
first one being used mainly to register each CPU in the coherency
fabric, the second one being used for the I/O coherency barrier), it
has only one set of register (for the I/O coherency barrier).
This commit adds a new "marvell,armada-375-coherency-fabric"
compatible string for this variant of the coherency fabric. The custom
DMA operations, and the way of triggering an I/O barrier is the same
as Armada 370/XP, so the code changes are minimal. However, the
set_cpu_coherent() function is not needed on Armada 375 and will not
work.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
.../devicetree/bindings/arm/coherency-fabric.txt | 22 ++++++++++++++++++----
arch/arm/mach-mvebu/coherency.c | 14 ++++++++++++++
2 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/coherency-fabric.txt b/Documentation/devicetree/bindings/arm/coherency-fabric.txt
index f0bfa37..dcd80d6 100644
--- a/Documentation/devicetree/bindings/arm/coherency-fabric.txt
+++ b/Documentation/devicetree/bindings/arm/coherency-fabric.txt
@@ -1,6 +1,6 @@
Coherency fabric
----------------
-Available on Marvell SOCs: Armada 370 and Armada XP
+Available on Marvell SOCs: Armada 370, Armada 375 and Armada XP
Required properties:
@@ -9,11 +9,20 @@ Required properties:
* "marvell,coherency-fabric", to be used for the coherency fabric of
the Armada 370 and Armada XP.
+ * "marvell,armada-375-coherency-fabric", for the Armada 375 coherency
+ fabric.
+
- reg: Should contain coherency fabric registers location and
- length. First pair for the coherency fabric registers, second pair
- for the per-CPU fabric registers registers.
+ length.
+
+ * For "marvell,coherency-fabric", the first pair for the coherency
+ fabric registers, second pair for the per-CPU fabric registers.
+
+ * For "marvell,armada-375-coherency-fabric", only one pair is needed
+ for the per-CPU fabric registers.
-Example:
+
+Examples:
coherency-fabric at d0020200 {
compatible = "marvell,coherency-fabric";
@@ -22,3 +31,8 @@ coherency-fabric at d0020200 {
};
+coherency-fabric at 21810 {
+ compatible = "marvell,armada-375-coherency-fabric";
+ reg = <0x21810 0x1c>;
+};
+
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index 15b769d..f63c868 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -41,11 +41,14 @@ static void __iomem *coherency_cpu_base;
enum {
COHERENCY_FABRIC_TYPE_NONE,
COHERENCY_FABRIC_TYPE_ARMADA_370_XP,
+ COHERENCY_FABRIC_TYPE_ARMADA_375,
};
static struct of_device_id of_coherency_table[] = {
{.compatible = "marvell,coherency-fabric",
.data = (void*) COHERENCY_FABRIC_TYPE_ARMADA_370_XP },
+ {.compatible = "marvell,armada-375-coherency-fabric",
+ .data = (void*) COHERENCY_FABRIC_TYPE_ARMADA_375 },
{ /* end of list */ },
};
@@ -144,6 +147,11 @@ static void __init armada_370_coherency_init(struct device_node *np)
set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
}
+static void __init armada_375_coherency_init(struct device_node *np)
+{
+ coherency_cpu_base = of_iomap(np, 0);
+}
+
static int coherency_type(void)
{
struct device_node *np;
@@ -159,6 +167,10 @@ static int coherency_type(void)
if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP)
return type;
+ /* Armada 375 coherency works only on SMP */
+ else if (type == COHERENCY_FABRIC_TYPE_ARMADA_375 && is_smp())
+ return type;
+
of_node_put(np);
}
@@ -179,6 +191,8 @@ int __init coherency_init(void)
if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP)
armada_370_coherency_init(np);
+ else if (type == COHERENCY_FABRIC_TYPE_ARMADA_375)
+ armada_375_coherency_init(np);
return 0;
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 07/10] ARM: mvebu: implement Armada 375 coherency workaround
2014-03-06 16:46 [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
` (5 preceding siblings ...)
2014-03-06 16:46 ` [PATCH 06/10] ARM: mvebu: add Armada 375 support to the coherency code Thomas Petazzoni
@ 2014-03-06 16:46 ` Thomas Petazzoni
2014-03-06 18:36 ` Jason Cooper
2014-03-06 16:46 ` [PATCH 08/10] ARM: mvebu: add Armada 38x support to the coherency code Thomas Petazzoni
` (3 subsequent siblings)
10 siblings, 1 reply; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-06 16:46 UTC (permalink / raw)
To: linux-arm-kernel
The early revisions of Armada 375 SOCs (Z1 stepping) have a bug in the
I/O coherency unit that prevents using the normal method for the I/O
coherency barrier. The recommended workaround is to use a XOR memset
transfer to act as the I/O coherency barrier.
This involves "borrowing" a XOR engine, which gets disabled in the
Device Tree so the normal XOR driver doesn't use it. Note also that
the mvebu-mbus driver must be initialized prior to the coherency unit,
because the DRAM windows of the XOR engine must be configured during
the coherency unit initialization, due to this workaround.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
arch/arm/mach-mvebu/board-v7.c | 2 +-
arch/arm/mach-mvebu/coherency.c | 150 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 151 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
index 256e6f6..6260cb8 100644
--- a/arch/arm/mach-mvebu/board-v7.c
+++ b/arch/arm/mach-mvebu/board-v7.c
@@ -80,8 +80,8 @@ static void __init mvebu_timer_and_clk_init(void)
of_clk_init(NULL);
clocksource_of_init();
mvebu_scu_enable();
- coherency_init();
BUG_ON(mvebu_mbus_dt_init(coherency_available()));
+ coherency_init();
#ifdef CONFIG_CACHE_L2X0
l2x0_of_init(0, ~0UL);
#endif
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index f63c868..73d56f2 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -24,6 +24,9 @@
#include <linux/smp.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mbus.h>
+#include <linux/clk.h>
#include <asm/smp_plat.h>
#include <asm/cacheflush.h>
#include "armada-370-xp.h"
@@ -66,8 +69,154 @@ int set_cpu_coherent(unsigned int hw_cpu_id, int smp_group_id)
return ll_set_cpu_coherent(coherency_base, hw_cpu_id);
}
+/*
+ * The below code implements the I/O coherency workaround on Armada
+ * 375. This workaround consists in using the two channels of the
+ * first XOR engine to trigger a XOR transaction that serves as the
+ * I/O coherency barrier.
+ */
+
+static void __iomem *xor_base, *xor_high_base;
+static dma_addr_t coherency_wa_buf_phys[CONFIG_NR_CPUS];
+static void *coherency_wa_buf[CONFIG_NR_CPUS];
+static bool coherency_wa_enabled;
+
+#define XOR_CONFIG(chan) (0x10 + (chan * 4))
+#define XOR_ACTIVATION(chan) (0x20 + (chan * 4))
+#define WINDOW_BAR_ENABLE(chan) (0x240 + ((chan) << 2))
+#define WINDOW_BASE(w) (0x250 + ((w) << 2))
+#define WINDOW_SIZE(w) (0x270 + ((w) << 2))
+#define WINDOW_REMAP_HIGH(w) (0x290 + ((w) << 2))
+#define WINDOW_OVERRIDE_CTRL(chan) (0x2A0 + ((chan) << 2))
+#define XOR_DEST_POINTER(chan) (0x2B0 + (chan * 4))
+#define XOR_BLOCK_SIZE(chan) (0x2C0 + (chan * 4))
+#define XOR_INIT_VALUE_LOW 0x2E0
+#define XOR_INIT_VALUE_HIGH 0x2E4
+
+static inline void mvebu_hwcc_armada375_sync_io_barrier_wa(void)
+{
+ int idx = smp_processor_id();
+
+ /* Write '1' to the first word of the buffer */
+ writel(0x1, coherency_wa_buf[idx]);
+
+ /* Wait until the engine is idle */
+ while ((readl(xor_base + XOR_ACTIVATION(idx)) >> 4) & 0x3)
+ ;
+
+ dmb();
+
+ /* Trigger channel */
+ writel(0x1, xor_base + XOR_ACTIVATION(idx));
+
+ /* Poll the data until it is cleared by the XOR transaction */
+ while (readl(coherency_wa_buf[idx]))
+ ;
+}
+
+static void __init armada_375_coherency_init_wa(void)
+{
+ const struct mbus_dram_target_info *dram;
+ struct device_node *xor_node;
+ struct property *xor_status;
+ struct clk *xor_clk;
+ u32 win_enable = 0;
+ int i;
+
+ /*
+ * Since the workaround uses one XOR engine, we grab a
+ * reference to its Device Tree node first.
+ */
+ xor_node = of_find_compatible_node(NULL, NULL, "marvell,orion-xor");
+ BUG_ON(!xor_node);
+
+ /*
+ * Then we mark it as disabled so that the real XOR driver
+ * will not use it.
+ */
+ xor_status = kzalloc(sizeof(struct property), GFP_KERNEL);
+ BUG_ON(!xor_status);
+
+ xor_status->value = kstrdup("disabled", GFP_KERNEL);
+ BUG_ON(!xor_status->value);
+
+ xor_status->length = 8;
+ xor_status->name = kstrdup("status", GFP_KERNEL);
+ BUG_ON(!xor_status->name);
+
+ of_update_property(xor_node, xor_status);
+
+ /*
+ * And we remap the registers, get the clock, and do the
+ * initial configuration of the XOR engine.
+ */
+ xor_base = of_iomap(xor_node, 0);
+ xor_high_base = of_iomap(xor_node, 1);
+
+ xor_clk = of_clk_get_by_name(xor_node, NULL);
+ BUG_ON(!xor_clk);
+
+ clk_prepare_enable(xor_clk);
+
+ dram = mv_mbus_dram_info();
+
+ for (i = 0; i < 8; i++) {
+ writel(0, xor_base + WINDOW_BASE(i));
+ writel(0, xor_base + WINDOW_SIZE(i));
+ if (i < 4)
+ writel(0, xor_base + WINDOW_REMAP_HIGH(i));
+ }
+
+ for (i = 0; i < dram->num_cs; i++) {
+ const struct mbus_dram_window *cs = dram->cs + i;
+ writel((cs->base & 0xffff0000) |
+ (cs->mbus_attr << 8) |
+ dram->mbus_dram_target_id, xor_base + WINDOW_BASE(i));
+ writel((cs->size - 1) & 0xffff0000, xor_base + WINDOW_SIZE(i));
+
+ win_enable |= (1 << i);
+ win_enable |= 3 << (16 + (2 * i));
+ }
+
+ writel(win_enable, xor_base + WINDOW_BAR_ENABLE(0));
+ writel(win_enable, xor_base + WINDOW_BAR_ENABLE(1));
+ writel(0, xor_base + WINDOW_OVERRIDE_CTRL(0));
+ writel(0, xor_base + WINDOW_OVERRIDE_CTRL(1));
+
+ for (i = 0; i < CONFIG_NR_CPUS; i++) {
+ coherency_wa_buf[i] = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ BUG_ON(!coherency_wa_buf[i]);
+
+ /*
+ * We can't use the DMA mapping API, since we don't
+ * have a valid 'struct device' pointer
+ */
+ coherency_wa_buf_phys[i] =
+ virt_to_phys(coherency_wa_buf[i]);
+ BUG_ON(!coherency_wa_buf_phys[i]);
+
+ /*
+ * Configure the XOR engine for memset operation, with
+ * a 128 bytes block size
+ */
+ writel(0x444, xor_base + XOR_CONFIG(i));
+ writel(128, xor_base + XOR_BLOCK_SIZE(i));
+ writel(coherency_wa_buf_phys[i], xor_base + XOR_DEST_POINTER(i));
+ }
+
+ writel(0x0, xor_base + XOR_INIT_VALUE_LOW);
+ writel(0x0, xor_base + XOR_INIT_VALUE_HIGH);
+
+ coherency_wa_enabled = true;
+}
+
static inline void mvebu_hwcc_sync_io_barrier(void)
{
+ if (coherency_wa_enabled) {
+ mvebu_hwcc_armada375_sync_io_barrier_wa();
+ return;
+ }
+
writel(0x1, coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET);
while (readl(coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET) & 0x1);
}
@@ -150,6 +299,7 @@ static void __init armada_370_coherency_init(struct device_node *np)
static void __init armada_375_coherency_init(struct device_node *np)
{
coherency_cpu_base = of_iomap(np, 0);
+ armada_375_coherency_init_wa();
}
static int coherency_type(void)
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 08/10] ARM: mvebu: add Armada 38x support to the coherency code
2014-03-06 16:46 [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
` (6 preceding siblings ...)
2014-03-06 16:46 ` [PATCH 07/10] ARM: mvebu: implement Armada 375 coherency workaround Thomas Petazzoni
@ 2014-03-06 16:46 ` Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 09/10] ARM: mvebu: enable the coherency fabric on Armada 375 Thomas Petazzoni
` (2 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-06 16:46 UTC (permalink / raw)
To: linux-arm-kernel
The Armada 38x has a coherency unit that is similar to the one of the
Armada 375 SoC, except that it does not have the bug of the Armada 375
coherency unit that requires the XOR based workaround.
This commit therefore extends the Marvell EBU coherency code with a
new compatible string to support the Armada 38x coherency unit.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
Documentation/devicetree/bindings/arm/coherency-fabric.txt | 7 ++++++-
arch/arm/mach-mvebu/coherency.c | 14 ++++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/arm/coherency-fabric.txt b/Documentation/devicetree/bindings/arm/coherency-fabric.txt
index dcd80d6..8dd4661 100644
--- a/Documentation/devicetree/bindings/arm/coherency-fabric.txt
+++ b/Documentation/devicetree/bindings/arm/coherency-fabric.txt
@@ -1,6 +1,6 @@
Coherency fabric
----------------
-Available on Marvell SOCs: Armada 370, Armada 375 and Armada XP
+Available on Marvell SOCs: Armada 370, Armada 375, Armada 38x and Armada XP
Required properties:
@@ -12,6 +12,9 @@ Required properties:
* "marvell,armada-375-coherency-fabric", for the Armada 375 coherency
fabric.
+ * "marvell,armada-380-coherency-fabric", for the Armada 38x coherency
+ fabric.
+
- reg: Should contain coherency fabric registers location and
length.
@@ -21,6 +24,8 @@ Required properties:
* For "marvell,armada-375-coherency-fabric", only one pair is needed
for the per-CPU fabric registers.
+ * For "marvell,armada-380-coherency-fabric", only one pair is needed
+ for the per-CPU fabric registers.
Examples:
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index 73d56f2..1a54907 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -45,6 +45,7 @@ enum {
COHERENCY_FABRIC_TYPE_NONE,
COHERENCY_FABRIC_TYPE_ARMADA_370_XP,
COHERENCY_FABRIC_TYPE_ARMADA_375,
+ COHERENCY_FABRIC_TYPE_ARMADA_380,
};
static struct of_device_id of_coherency_table[] = {
@@ -52,6 +53,8 @@ static struct of_device_id of_coherency_table[] = {
.data = (void*) COHERENCY_FABRIC_TYPE_ARMADA_370_XP },
{.compatible = "marvell,armada-375-coherency-fabric",
.data = (void*) COHERENCY_FABRIC_TYPE_ARMADA_375 },
+ {.compatible = "marvell,armada-380-coherency-fabric",
+ .data = (void*) COHERENCY_FABRIC_TYPE_ARMADA_380 },
{ /* end of list */ },
};
@@ -302,6 +305,11 @@ static void __init armada_375_coherency_init(struct device_node *np)
armada_375_coherency_init_wa();
}
+static void __init armada_380_coherency_init(struct device_node *np)
+{
+ coherency_cpu_base = of_iomap(np, 0);
+}
+
static int coherency_type(void)
{
struct device_node *np;
@@ -321,6 +329,10 @@ static int coherency_type(void)
else if (type == COHERENCY_FABRIC_TYPE_ARMADA_375 && is_smp())
return type;
+ /* Armada 380 coherency works only on SMP */
+ else if (type == COHERENCY_FABRIC_TYPE_ARMADA_380 && is_smp())
+ return type;
+
of_node_put(np);
}
@@ -343,6 +355,8 @@ int __init coherency_init(void)
armada_370_coherency_init(np);
else if (type == COHERENCY_FABRIC_TYPE_ARMADA_375)
armada_375_coherency_init(np);
+ else if (type == COHERENCY_FABRIC_TYPE_ARMADA_380)
+ armada_380_coherency_init(np);
return 0;
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 09/10] ARM: mvebu: enable the coherency fabric on Armada 375
2014-03-06 16:46 [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
` (7 preceding siblings ...)
2014-03-06 16:46 ` [PATCH 08/10] ARM: mvebu: add Armada 38x support to the coherency code Thomas Petazzoni
@ 2014-03-06 16:46 ` Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 10/10] ARM: mvebu: enable the coherency fabric on Armada 38x Thomas Petazzoni
2014-03-24 15:06 ` [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
10 siblings, 0 replies; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-06 16:46 UTC (permalink / raw)
To: linux-arm-kernel
This commit adds the necessary Device Tree information to enable the
coherency fabric on Armada 375.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
arch/arm/boot/dts/armada-375.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm/boot/dts/armada-375.dtsi b/arch/arm/boot/dts/armada-375.dtsi
index 3877693..eceab89 100644
--- a/arch/arm/boot/dts/armada-375.dtsi
+++ b/arch/arm/boot/dts/armada-375.dtsi
@@ -128,6 +128,11 @@
cache-level = <2>;
};
+ scu at c000 {
+ compatible = "arm,cortex-a9-scu";
+ reg = <0xc000 0x58>;
+ };
+
timer at c600 {
compatible = "arm,cortex-a9-twd-timer";
reg = <0xc600 0x20>;
@@ -320,6 +325,11 @@
clocks = <&coreclk 0>;
};
+ coherency-fabric at 21010 {
+ compatible = "marvell,armada-375-coherency-fabric";
+ reg = <0x21010 0x1c>;
+ };
+
xor at 60800 {
compatible = "marvell,orion-xor";
reg = <0x60800 0x100
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 10/10] ARM: mvebu: enable the coherency fabric on Armada 38x
2014-03-06 16:46 [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
` (8 preceding siblings ...)
2014-03-06 16:46 ` [PATCH 09/10] ARM: mvebu: enable the coherency fabric on Armada 375 Thomas Petazzoni
@ 2014-03-06 16:46 ` Thomas Petazzoni
2014-03-24 15:06 ` [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
10 siblings, 0 replies; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-06 16:46 UTC (permalink / raw)
To: linux-arm-kernel
This commit adds the necessary Device Tree information to enable the
coherency fabric on Armada 38x.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
arch/arm/boot/dts/armada-38x.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi
index 812ce28..2332b20 100644
--- a/arch/arm/boot/dts/armada-38x.dtsi
+++ b/arch/arm/boot/dts/armada-38x.dtsi
@@ -108,6 +108,11 @@
cache-level = <2>;
};
+ scu at c000 {
+ compatible = "arm,cortex-a9-scu";
+ reg = <0xc000 0x58>;
+ };
+
timer at c600 {
compatible = "arm,cortex-a9-twd-timer";
reg = <0xc600 0x20>;
@@ -267,6 +272,11 @@
clock-names = "nbclk", "fixed";
};
+ coherency-fabric at 21010 {
+ compatible = "marvell,armada-380-coherency-fabric";
+ reg = <0x21010 0x1c>;
+ };
+
eth1: ethernet at 30000 {
compatible = "marvell,armada-370-neta";
reg = <0x30000 0x4000>;
--
1.8.3.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 07/10] ARM: mvebu: implement Armada 375 coherency workaround
2014-03-06 16:46 ` [PATCH 07/10] ARM: mvebu: implement Armada 375 coherency workaround Thomas Petazzoni
@ 2014-03-06 18:36 ` Jason Cooper
2014-03-06 21:18 ` Thomas Petazzoni
0 siblings, 1 reply; 16+ messages in thread
From: Jason Cooper @ 2014-03-06 18:36 UTC (permalink / raw)
To: linux-arm-kernel
Thomas,
On Thu, Mar 06, 2014 at 05:46:32PM +0100, Thomas Petazzoni wrote:
> The early revisions of Armada 375 SOCs (Z1 stepping) have a bug in the
Do we have a way to determine that we are on a Z1 at runtime? It seems
like we're consuming an XOR engine unconditionally. I presume that
Marvell is going to fix this with the next stepping?
thx,
Jason.
> I/O coherency unit that prevents using the normal method for the I/O
> coherency barrier. The recommended workaround is to use a XOR memset
> transfer to act as the I/O coherency barrier.
>
> This involves "borrowing" a XOR engine, which gets disabled in the
> Device Tree so the normal XOR driver doesn't use it. Note also that
> the mvebu-mbus driver must be initialized prior to the coherency unit,
> because the DRAM windows of the XOR engine must be configured during
> the coherency unit initialization, due to this workaround.
>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> ---
> arch/arm/mach-mvebu/board-v7.c | 2 +-
> arch/arm/mach-mvebu/coherency.c | 150 ++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 151 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/mach-mvebu/board-v7.c b/arch/arm/mach-mvebu/board-v7.c
> index 256e6f6..6260cb8 100644
> --- a/arch/arm/mach-mvebu/board-v7.c
> +++ b/arch/arm/mach-mvebu/board-v7.c
> @@ -80,8 +80,8 @@ static void __init mvebu_timer_and_clk_init(void)
> of_clk_init(NULL);
> clocksource_of_init();
> mvebu_scu_enable();
> - coherency_init();
> BUG_ON(mvebu_mbus_dt_init(coherency_available()));
> + coherency_init();
> #ifdef CONFIG_CACHE_L2X0
> l2x0_of_init(0, ~0UL);
> #endif
> diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
> index f63c868..73d56f2 100644
> --- a/arch/arm/mach-mvebu/coherency.c
> +++ b/arch/arm/mach-mvebu/coherency.c
> @@ -24,6 +24,9 @@
> #include <linux/smp.h>
> #include <linux/dma-mapping.h>
> #include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/mbus.h>
> +#include <linux/clk.h>
> #include <asm/smp_plat.h>
> #include <asm/cacheflush.h>
> #include "armada-370-xp.h"
> @@ -66,8 +69,154 @@ int set_cpu_coherent(unsigned int hw_cpu_id, int smp_group_id)
> return ll_set_cpu_coherent(coherency_base, hw_cpu_id);
> }
>
> +/*
> + * The below code implements the I/O coherency workaround on Armada
> + * 375. This workaround consists in using the two channels of the
> + * first XOR engine to trigger a XOR transaction that serves as the
> + * I/O coherency barrier.
> + */
> +
> +static void __iomem *xor_base, *xor_high_base;
> +static dma_addr_t coherency_wa_buf_phys[CONFIG_NR_CPUS];
> +static void *coherency_wa_buf[CONFIG_NR_CPUS];
> +static bool coherency_wa_enabled;
> +
> +#define XOR_CONFIG(chan) (0x10 + (chan * 4))
> +#define XOR_ACTIVATION(chan) (0x20 + (chan * 4))
> +#define WINDOW_BAR_ENABLE(chan) (0x240 + ((chan) << 2))
> +#define WINDOW_BASE(w) (0x250 + ((w) << 2))
> +#define WINDOW_SIZE(w) (0x270 + ((w) << 2))
> +#define WINDOW_REMAP_HIGH(w) (0x290 + ((w) << 2))
> +#define WINDOW_OVERRIDE_CTRL(chan) (0x2A0 + ((chan) << 2))
> +#define XOR_DEST_POINTER(chan) (0x2B0 + (chan * 4))
> +#define XOR_BLOCK_SIZE(chan) (0x2C0 + (chan * 4))
> +#define XOR_INIT_VALUE_LOW 0x2E0
> +#define XOR_INIT_VALUE_HIGH 0x2E4
> +
> +static inline void mvebu_hwcc_armada375_sync_io_barrier_wa(void)
> +{
> + int idx = smp_processor_id();
> +
> + /* Write '1' to the first word of the buffer */
> + writel(0x1, coherency_wa_buf[idx]);
> +
> + /* Wait until the engine is idle */
> + while ((readl(xor_base + XOR_ACTIVATION(idx)) >> 4) & 0x3)
> + ;
> +
> + dmb();
> +
> + /* Trigger channel */
> + writel(0x1, xor_base + XOR_ACTIVATION(idx));
> +
> + /* Poll the data until it is cleared by the XOR transaction */
> + while (readl(coherency_wa_buf[idx]))
> + ;
> +}
> +
> +static void __init armada_375_coherency_init_wa(void)
> +{
> + const struct mbus_dram_target_info *dram;
> + struct device_node *xor_node;
> + struct property *xor_status;
> + struct clk *xor_clk;
> + u32 win_enable = 0;
> + int i;
> +
> + /*
> + * Since the workaround uses one XOR engine, we grab a
> + * reference to its Device Tree node first.
> + */
> + xor_node = of_find_compatible_node(NULL, NULL, "marvell,orion-xor");
> + BUG_ON(!xor_node);
> +
> + /*
> + * Then we mark it as disabled so that the real XOR driver
> + * will not use it.
> + */
> + xor_status = kzalloc(sizeof(struct property), GFP_KERNEL);
> + BUG_ON(!xor_status);
> +
> + xor_status->value = kstrdup("disabled", GFP_KERNEL);
> + BUG_ON(!xor_status->value);
> +
> + xor_status->length = 8;
> + xor_status->name = kstrdup("status", GFP_KERNEL);
> + BUG_ON(!xor_status->name);
> +
> + of_update_property(xor_node, xor_status);
> +
> + /*
> + * And we remap the registers, get the clock, and do the
> + * initial configuration of the XOR engine.
> + */
> + xor_base = of_iomap(xor_node, 0);
> + xor_high_base = of_iomap(xor_node, 1);
> +
> + xor_clk = of_clk_get_by_name(xor_node, NULL);
> + BUG_ON(!xor_clk);
> +
> + clk_prepare_enable(xor_clk);
> +
> + dram = mv_mbus_dram_info();
> +
> + for (i = 0; i < 8; i++) {
> + writel(0, xor_base + WINDOW_BASE(i));
> + writel(0, xor_base + WINDOW_SIZE(i));
> + if (i < 4)
> + writel(0, xor_base + WINDOW_REMAP_HIGH(i));
> + }
> +
> + for (i = 0; i < dram->num_cs; i++) {
> + const struct mbus_dram_window *cs = dram->cs + i;
> + writel((cs->base & 0xffff0000) |
> + (cs->mbus_attr << 8) |
> + dram->mbus_dram_target_id, xor_base + WINDOW_BASE(i));
> + writel((cs->size - 1) & 0xffff0000, xor_base + WINDOW_SIZE(i));
> +
> + win_enable |= (1 << i);
> + win_enable |= 3 << (16 + (2 * i));
> + }
> +
> + writel(win_enable, xor_base + WINDOW_BAR_ENABLE(0));
> + writel(win_enable, xor_base + WINDOW_BAR_ENABLE(1));
> + writel(0, xor_base + WINDOW_OVERRIDE_CTRL(0));
> + writel(0, xor_base + WINDOW_OVERRIDE_CTRL(1));
> +
> + for (i = 0; i < CONFIG_NR_CPUS; i++) {
> + coherency_wa_buf[i] = kzalloc(PAGE_SIZE, GFP_KERNEL);
> + BUG_ON(!coherency_wa_buf[i]);
> +
> + /*
> + * We can't use the DMA mapping API, since we don't
> + * have a valid 'struct device' pointer
> + */
> + coherency_wa_buf_phys[i] =
> + virt_to_phys(coherency_wa_buf[i]);
> + BUG_ON(!coherency_wa_buf_phys[i]);
> +
> + /*
> + * Configure the XOR engine for memset operation, with
> + * a 128 bytes block size
> + */
> + writel(0x444, xor_base + XOR_CONFIG(i));
> + writel(128, xor_base + XOR_BLOCK_SIZE(i));
> + writel(coherency_wa_buf_phys[i], xor_base + XOR_DEST_POINTER(i));
> + }
> +
> + writel(0x0, xor_base + XOR_INIT_VALUE_LOW);
> + writel(0x0, xor_base + XOR_INIT_VALUE_HIGH);
> +
> + coherency_wa_enabled = true;
> +}
> +
> static inline void mvebu_hwcc_sync_io_barrier(void)
> {
> + if (coherency_wa_enabled) {
> + mvebu_hwcc_armada375_sync_io_barrier_wa();
> + return;
> + }
> +
> writel(0x1, coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET);
> while (readl(coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET) & 0x1);
> }
> @@ -150,6 +299,7 @@ static void __init armada_370_coherency_init(struct device_node *np)
> static void __init armada_375_coherency_init(struct device_node *np)
> {
> coherency_cpu_base = of_iomap(np, 0);
> + armada_375_coherency_init_wa();
> }
>
> static int coherency_type(void)
> --
> 1.8.3.2
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 07/10] ARM: mvebu: implement Armada 375 coherency workaround
2014-03-06 18:36 ` Jason Cooper
@ 2014-03-06 21:18 ` Thomas Petazzoni
0 siblings, 0 replies; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-06 21:18 UTC (permalink / raw)
To: linux-arm-kernel
Dear Jason Cooper,
On Thu, 6 Mar 2014 13:36:56 -0500, Jason Cooper wrote:
> On Thu, Mar 06, 2014 at 05:46:32PM +0100, Thomas Petazzoni wrote:
> > The early revisions of Armada 375 SOCs (Z1 stepping) have a bug in the
>
> Do we have a way to determine that we are on a Z1 at runtime? It seems
> like we're consuming an XOR engine unconditionally. I presume that
> Marvell is going to fix this with the next stepping?
Yes, we believe there will be a way to differentiate the Z1 stepping
for the later steppings, using the mvebu-soc-id. However, since those
later steppings are not available yet, we haven't been able to test
this. Our plan is that as soon as we have newer steppings, we will
improve this code to only apply the XOR workaround on the steppings for
which it is needed. It is not clear at this point which stepping
exactly will fix the problem, so we've written the code with the
information that we have today.
Thanks for the feedback!
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x
2014-03-06 16:46 [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
` (9 preceding siblings ...)
2014-03-06 16:46 ` [PATCH 10/10] ARM: mvebu: enable the coherency fabric on Armada 38x Thomas Petazzoni
@ 2014-03-24 15:06 ` Thomas Petazzoni
2014-03-25 9:32 ` Andrew Lunn
10 siblings, 1 reply; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-24 15:06 UTC (permalink / raw)
To: linux-arm-kernel
Jason, Gregory, Andrew, Sebastian,
Any news about this patch set? It is not aimed at 3.15 as was discussed
already with Jason, but since I'd still like to have some early
comments about this patch series for 3.16, since we would also like to
land the Armada 375/38x SMP support in 3.16, which will sit on top of
this series.
So far, Jason made one comment about runtime detecting the need for the
Armada 375 coherency workaround, to which I already replied. No other
comments have been made, unless I missed them, of course.
Thanks a lot!
Thomas
On Thu, 6 Mar 2014 17:46:25 +0100, Thomas Petazzoni wrote:
> Jason, Gregory, Andrew, Sebastian,
>
> This set of patches add hardware coherency support for the new Armada
> 375 and Armada 38x SoCs. The patch set can be divided in three
> sections:
>
> * Patches 1, 2, 3 and 4 prepare the introduction of the support for
> new SoC in the existing coherency code.
>
> The main change is that the mvebu-mbus driver no longer pokes into
> the Device Tree to find whether hardware I/O coherency is available
> or not: this information is passed as argument to the mvebu-mbus
> initialization function. This avoids changing the mvebu-mbus driver
> to add the compatible strings of all possible coherency fabrics,
> and also avoids encoding specific conditions in the mvebu-mbus
> driver: on Armada 375 and 38x, the hardware I/O coherency can only
> be enabled in SMP mode.
>
> These preparation patches had already been sent in the past
> (http://permalink.gmane.org/gmane.linux.ports.arm.kernel/290780). This
> round has taken into account the comments I had received on this
> early version.
>
> * Patches 5, 6, 7 and 8 add the coherency support itself. Patch 4
> enables the SCU, patch 5 adds I/O coherency support for 375, patch
> 6 adds a major workaround to make coherency support actually work
> on early 375 SOCs and patch 7 adds I/O coherency support for 38x.
>
> * Patches 9 and 10 add the necessary Device Tree informations to
> enable the coherency.
>
> Best regards,
>
> Thomas
>
> Thomas Petazzoni (10):
> ARM: mvebu: prepare coherency code to support more SOCs
> ARM: mvebu: add a coherency_available() call
> bus: mvebu: pass the coherency availability information at init time
> ARM: mvebu: ARM: mvebu: use of_find_matching_node_and_match() in
> coherency.c
> ARM: mvebu: enable the ARM SCU on Armada 375 and Armada 38x
> ARM: mvebu: add Armada 375 support to the coherency code
> ARM: mvebu: implement Armada 375 coherency workaround
> ARM: mvebu: add Armada 38x support to the coherency code
> ARM: mvebu: enable the coherency fabric on Armada 375
> ARM: mvebu: enable the coherency fabric on Armada 38x
>
> .../devicetree/bindings/arm/coherency-fabric.txt | 32 ++-
> arch/arm/boot/dts/armada-375.dtsi | 10 +
> arch/arm/boot/dts/armada-38x.dtsi | 10 +
> arch/arm/mach-kirkwood/board-dt.c | 2 +-
> arch/arm/mach-mvebu/Kconfig | 2 +
> arch/arm/mach-mvebu/board-v7.c | 21 +-
> arch/arm/mach-mvebu/coherency.c | 251 +++++++++++++++++++--
> arch/arm/mach-mvebu/coherency.h | 1 +
> drivers/bus/mvebu-mbus.c | 11 +-
> include/linux/mbus.h | 2 +-
> 10 files changed, 305 insertions(+), 37 deletions(-)
>
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x
2014-03-24 15:06 ` [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
@ 2014-03-25 9:32 ` Andrew Lunn
2014-03-25 10:36 ` Thomas Petazzoni
0 siblings, 1 reply; 16+ messages in thread
From: Andrew Lunn @ 2014-03-25 9:32 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Mar 24, 2014 at 04:06:20PM +0100, Thomas Petazzoni wrote:
> Jason, Gregory, Andrew, Sebastian,
>
> Any news about this patch set? It is not aimed at 3.15 as was discussed
> already with Jason, but since I'd still like to have some early
> comments about this patch series for 3.16, since we would also like to
> land the Armada 375/38x SMP support in 3.16, which will sit on top of
> this series.
Hi Thomas
I took a look at them. The XOR code is interesting. I guess it is not
good for performance. A loud debug message would be useful to know
when the workaround has been turned on.
Once you send a rebase on 3.15 i can send an ACK.
Andrew
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x
2014-03-25 9:32 ` Andrew Lunn
@ 2014-03-25 10:36 ` Thomas Petazzoni
0 siblings, 0 replies; 16+ messages in thread
From: Thomas Petazzoni @ 2014-03-25 10:36 UTC (permalink / raw)
To: linux-arm-kernel
Dear Andrew Lunn,
On Tue, 25 Mar 2014 10:32:32 +0100, Andrew Lunn wrote:
> I took a look at them. The XOR code is interesting. I guess it is not
> good for performance. A loud debug message would be useful to know
> when the workaround has been turned on.
I haven't measured the performance impact, but indeed I suspect there
is one. I'm fine with printing a warning.
> Once you send a rebase on 3.15 i can send an ACK.
Great, thanks!
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2014-03-25 10:36 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-06 16:46 [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 01/10] ARM: mvebu: prepare coherency code to support more SOCs Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 02/10] ARM: mvebu: add a coherency_available() call Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 03/10] bus: mvebu: pass the coherency availability information at init time Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 04/10] ARM: mvebu: ARM: mvebu: use of_find_matching_node_and_match() in coherency.c Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 05/10] ARM: mvebu: enable the ARM SCU on Armada 375 and Armada 38x Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 06/10] ARM: mvebu: add Armada 375 support to the coherency code Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 07/10] ARM: mvebu: implement Armada 375 coherency workaround Thomas Petazzoni
2014-03-06 18:36 ` Jason Cooper
2014-03-06 21:18 ` Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 08/10] ARM: mvebu: add Armada 38x support to the coherency code Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 09/10] ARM: mvebu: enable the coherency fabric on Armada 375 Thomas Petazzoni
2014-03-06 16:46 ` [PATCH 10/10] ARM: mvebu: enable the coherency fabric on Armada 38x Thomas Petazzoni
2014-03-24 15:06 ` [PATCH 00/10] ARM: mvebu: Hardware coherency support for Armada 375 and 38x Thomas Petazzoni
2014-03-25 9:32 ` Andrew Lunn
2014-03-25 10:36 ` Thomas Petazzoni
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).