bus: mvebu: pass the coherency availability information at init time
authorGreg Ungerer <gerg@uclinux.org>
Mon, 14 Apr 2014 13:47:01 +0000 (15:47 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 4 Jul 2015 02:48:09 +0000 (19:48 -0700)
commit 5686a1e5aa436c49187a60052d5885fb1f541ce6 upstream.

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>
Link: https://lkml.kernel.org/r/1397483228-25625-4-git-send-email-thomas.petazzoni@free-electrons.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
[ Greg Ungerer: back ported to linux-3.10.y
  Back port necessary due to large code differences in affected files.
  This change in combination with commit e553554536 ("ARM: mvebu: disable
  I/O coherency on non-SMP situations on Armada 370/375/38x/XP") is
  critical to the hardware I/O coherency being set correctly by both the
  mbus driver and all peripheral hardware drivers. Without this change
  drivers will incorrectly enable I/O coherency window attributes and
  this causes rare unreliable system behavior including oops. ]

Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm/mach-dove/common.c
arch/arm/mach-kirkwood/common.c
arch/arm/mach-mv78xx0/common.c
arch/arm/mach-mvebu/armada-370-xp.c
arch/arm/mach-mvebu/coherency.c
arch/arm/mach-mvebu/coherency.h
arch/arm/mach-orion5x/common.c
drivers/bus/mvebu-mbus.c
include/linux/mbus.h

index e2b5da031f964c013478eb735a988bcb9ff12d0d..8d4f5dc569105af732fa8cb3879694918d847bde 100644 (file)
@@ -226,7 +226,7 @@ void __init dove_init_early(void)
        orion_time_set_base(TIMER_VIRT_BASE);
        mvebu_mbus_init("marvell,dove-mbus",
                        BRIDGE_WINS_BASE, BRIDGE_WINS_SZ,
-                       DOVE_MC_WINS_BASE, DOVE_MC_WINS_SZ);
+                       DOVE_MC_WINS_BASE, DOVE_MC_WINS_SZ, 0);
 }
 
 static int __init dove_find_tclk(void)
index f389228975637cd85d3f9f9444ae30e0f34537cc..4f6831ea88c549dac039f7d57542eb757cb4dd9d 100644 (file)
@@ -530,7 +530,7 @@ void __init kirkwood_init_early(void)
 
        mvebu_mbus_init("marvell,kirkwood-mbus",
                        BRIDGE_WINS_BASE, BRIDGE_WINS_SZ,
-                       DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ);
+                       DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ, 0);
 }
 
 int kirkwood_tclk;
index 749a7f8c4992e9746cccad78c0f4ee8d41553f20..4722c98dc1bb1f0495ea769d4d89aec679c84c7a 100644 (file)
@@ -337,11 +337,11 @@ void __init mv78xx0_init_early(void)
        if (mv78xx0_core_index() == 0)
                mvebu_mbus_init("marvell,mv78xx0-mbus",
                                BRIDGE_WINS_CPU0_BASE, BRIDGE_WINS_SZ,
-                               DDR_WINDOW_CPU0_BASE, DDR_WINDOW_CPU_SZ);
+                               DDR_WINDOW_CPU0_BASE, DDR_WINDOW_CPU_SZ, 0);
        else
                mvebu_mbus_init("marvell,mv78xx0-mbus",
                                BRIDGE_WINS_CPU1_BASE, BRIDGE_WINS_SZ,
-                               DDR_WINDOW_CPU1_BASE, DDR_WINDOW_CPU_SZ);
+                               DDR_WINDOW_CPU1_BASE, DDR_WINDOW_CPU_SZ, 0);
 }
 
 void __init_refok mv78xx0_timer_init(void)
index 1c48890bb72b2c7ad1301cdc9f8bad007362bf57..4377c3484a6260fe47b5a2cbda23a51f2bf0b320 100644 (file)
@@ -66,7 +66,8 @@ void __init armada_370_xp_init_early(void)
                        ARMADA_370_XP_MBUS_WINS_BASE,
                        ARMADA_370_XP_MBUS_WINS_SIZE,
                        ARMADA_370_XP_SDRAM_WINS_BASE,
-                       ARMADA_370_XP_SDRAM_WINS_SIZE);
+                       ARMADA_370_XP_SDRAM_WINS_SIZE,
+                       coherency_available());
 
 #ifdef CONFIG_CACHE_L2X0
        l2x0_of_init(0, ~0UL);
index 3ee701f1d38e1c528855eda600133735ebb5a3b9..ea26ebb5bb5ad122700be9f02085436937685da5 100644 (file)
@@ -137,6 +137,20 @@ static struct notifier_block mvebu_hwcc_platform_nb = {
        .notifier_call = mvebu_hwcc_platform_notifier,
 };
 
+/*
+ * Keep track of whether we have IO hardware coherency enabled or not.
+ * On Armada 370's we will not be using it for example. We need to make
+ * that available [through coherency_available()] so the mbus controller
+ * doesn't enable the IO coherency bit in the attribute bits of the
+ * chip selects.
+ */
+static int coherency_enabled;
+
+int coherency_available(void)
+{
+       return coherency_enabled;
+}
+
 int __init coherency_init(void)
 {
        struct device_node *np;
@@ -170,6 +184,7 @@ int __init coherency_init(void)
                coherency_base = of_iomap(np, 0);
                coherency_cpu_base = of_iomap(np, 1);
                set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
+               coherency_enabled = 1;
                bus_register_notifier(&platform_bus_type,
                                        &mvebu_hwcc_platform_nb);
        }
index 2f428137f6fedf45672146847bb95819c32a0759..1501a4e5eea0d190add8502075af3903bcc819a2 100644 (file)
@@ -19,6 +19,7 @@ int coherency_get_cpu_count(void);
 #endif
 
 int set_cpu_coherent(int cpu_id, int smp_group_id);
+int coherency_available(void);
 int coherency_init(void);
 
 #endif /* __MACH_370_XP_COHERENCY_H */
index f8a6db9239bf3c3ff7a88c29925cdce0961590cb..048773926ad4e82906e587f60a10d4b3211fbe8c 100644 (file)
@@ -213,7 +213,7 @@ void __init orion5x_init_early(void)
                mbus_soc_name = NULL;
        mvebu_mbus_init(mbus_soc_name, ORION5X_BRIDGE_WINS_BASE,
                        ORION5X_BRIDGE_WINS_SZ,
-                       ORION5X_DDR_WINS_BASE, ORION5X_DDR_WINS_SZ);
+                       ORION5X_DDR_WINS_BASE, ORION5X_DDR_WINS_SZ, 0);
 }
 
 void orion5x_setup_wins(void)
index 711dcf4a0313fc059e7991e2a93bf123b98a4693..7c437826c2f994c194de622d344ada6f5dff524b 100644 (file)
@@ -838,7 +838,7 @@ fs_initcall(mvebu_mbus_debugfs_init);
 int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
                           size_t mbuswins_size,
                           phys_addr_t sdramwins_phys_base,
-                          size_t sdramwins_size)
+                          size_t sdramwins_size, int is_coherent)
 {
        struct mvebu_mbus_state *mbus = &mbus_state;
        const struct of_device_id *of_id;
@@ -865,8 +865,7 @@ int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
                return -ENOMEM;
        }
 
-       if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"))
-               mbus->hw_io_coherency = 1;
+       mbus->hw_io_coherency = is_coherent;
 
        for (win = 0; win < mbus->soc->num_wins; win++)
                mvebu_mbus_disable_window(mbus, win);
index dba482e31a130e2e29690bf0c63e36b1e88e6aa8..e80b9c7ec8da36ca68c1fcf655bde677f350c745 100644 (file)
@@ -67,6 +67,6 @@ int mvebu_mbus_add_window(const char *devname, phys_addr_t base,
 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);
+                   size_t sdram_size, int is_coherent);
 
 #endif /* __LINUX_MBUS_H */