Merge tag 'v3.10.92'
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-mvebu / coherency.c
index 8278960066c33a86c4218be10d54a68b0b5c59c3..ea26ebb5bb5ad122700be9f02085436937685da5 100644 (file)
@@ -137,16 +137,54 @@ 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;
 
+       /*
+        * The coherency fabric is needed:
+        * - For coherency between processors on Armada XP, so only
+        *   when SMP is enabled.
+        * - For coherency between the processor and I/O devices, but
+        *   this coherency requires many pre-requisites (write
+        *   allocate cache policy, shareable pages, SMP bit set) that
+        *   are only meant in SMP situations.
+        *
+        * Note that this means that on Armada 370, there is currently
+        * no way to use hardware I/O coherency, because even when
+        * CONFIG_SMP is enabled, is_smp() returns false due to the
+        * Armada 370 being a single-core processor. To lift this
+        * limitation, we would have to find a way to make the cache
+        * policy set to write-allocate (on all Armada SoCs), and to
+        * set the shareable attribute in page tables (on all Armada
+        * SoCs except the Armada 370). Unfortunately, such decisions
+        * are taken very early in the kernel boot process, at a point
+        * where we don't know yet on which SoC we are running.
+        */
+       if (!is_smp())
+               return 0;
+
        np = of_find_matching_node(NULL, of_coherency_table);
        if (np) {
                pr_info("Initializing Coherency fabric\n");
                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);
        }