Merge tag 'renesas-clock2-for-v3.17' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / arch / arm / mm / cache-l2x0.c
index efc5cab..076172b 100644 (file)
@@ -1068,6 +1068,33 @@ static const struct l2c_init_data of_l2c310_data __initconst = {
        },
 };
 
+/*
+ * This is a variant of the of_l2c310_data with .sync set to
+ * NULL. Outer sync operations are not needed when the system is I/O
+ * coherent, and potentially harmful in certain situations (PCIe/PL310
+ * deadlock on Armada 375/38x due to hardware I/O coherency). The
+ * other operations are kept because they are infrequent (therefore do
+ * not cause the deadlock in practice) and needed for secondary CPU
+ * boot and other power management activities.
+ */
+static const struct l2c_init_data of_l2c310_coherent_data __initconst = {
+       .type = "L2C-310 Coherent",
+       .way_size_0 = SZ_8K,
+       .num_lock = 8,
+       .of_parse = l2c310_of_parse,
+       .enable = l2c310_enable,
+       .fixup = l2c310_fixup,
+       .save  = l2c310_save,
+       .outer_cache = {
+               .inv_range   = l2c210_inv_range,
+               .clean_range = l2c210_clean_range,
+               .flush_range = l2c210_flush_range,
+               .flush_all   = l2c210_flush_all,
+               .disable     = l2c310_disable,
+               .resume      = l2c310_resume,
+       },
+};
+
 /*
  * Note that the end addresses passed to Linux primitives are
  * noninclusive, while the hardware cache range operations use
@@ -1487,6 +1514,10 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
 
        data = of_match_node(l2x0_ids, np)->data;
 
+       if (of_device_is_compatible(np, "arm,pl310-cache") &&
+           of_property_read_bool(np, "arm,io-coherent"))
+               data = &of_l2c310_coherent_data;
+
        old_aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
        if (old_aux != ((old_aux & aux_mask) | aux_val)) {
                pr_warn("L2C: platform modifies aux control register: 0x%08x -> 0x%08x\n",