Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: 8482/1: l2x0: make it possible to disable outer sync from DT

According to commit 2503a5ecd86c002506001eba432c524ea009fe7f
"ARM: 6201/1: RealView: Do not use outer_sync() on ARM11MPCore
boards with L220" Some PB11MPCore RealView core tiles have broken
outer_sync.

We got rid of the custom barriers from the machine by disabling
outer sync, but that was just for the boardfile case. We have
to be able to do the same in the device tree case.

Since __l2c_init() is cloning and copying the L2C vtable,
we pass an argument to this function to optionally numb
the outer sync operation if desired, before initializing
the cache.

After this we can set up the cache correctly on the RealView
PB11MPCore. This was tested on a PB11MPCore known to have the
issue. Before this, spurious crashes would occur if we try to
set up the cache properly, after this it boots rock solid.

Cc: Arnd Bergmann <arnd@arndb.de>
Cc: devicetree@vger.kernel.org
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Linus Walleij and committed by
Russell King
36f46d6d e7273ff4

+13 -3
+3
Documentation/devicetree/bindings/arm/l2cc.txt
··· 75 75 specified to indicate that such transforms are precluded. 76 76 - arm,parity-enable : enable parity checking on the L2 cache (L220 or PL310). 77 77 - arm,parity-disable : disable parity checking on the L2 cache (L220 or PL310). 78 + - arm,outer-sync-disable : disable the outer sync operation on the L2 cache. 79 + Some core tiles, especially ARM PB11MPCore have a faulty L220 cache that 80 + will randomly hang unless outer sync operations are disabled. 78 81 - prefetch-data : Data prefetch. Value: <0> (forcibly disable), <1> 79 82 (forcibly enable), property absent (retain settings set by firmware) 80 83 - prefetch-instr : Instruction prefetch. Value: <0> (forcibly disable),
+10 -3
arch/arm/mm/cache-l2x0.c
··· 790 790 }; 791 791 792 792 static int __init __l2c_init(const struct l2c_init_data *data, 793 - u32 aux_val, u32 aux_mask, u32 cache_id) 793 + u32 aux_val, u32 aux_mask, u32 cache_id, bool nosync) 794 794 { 795 795 struct outer_cache_fns fns; 796 796 unsigned way_size_bits, ways; ··· 866 866 fns.configure = outer_cache.configure; 867 867 if (data->fixup) 868 868 data->fixup(l2x0_base, cache_id, &fns); 869 + if (nosync) { 870 + pr_info("L2C: disabling outer sync\n"); 871 + fns.sync = NULL; 872 + } 869 873 870 874 /* 871 875 * Check if l2x0 controller is already enabled. If we are booting ··· 929 925 if (data->save) 930 926 data->save(l2x0_base); 931 927 932 - __l2c_init(data, aux_val, aux_mask, cache_id); 928 + __l2c_init(data, aux_val, aux_mask, cache_id, false); 933 929 } 934 930 935 931 #ifdef CONFIG_OF ··· 1728 1724 struct resource res; 1729 1725 u32 cache_id, old_aux; 1730 1726 u32 cache_level = 2; 1727 + bool nosync = false; 1731 1728 1732 1729 np = of_find_matching_node(NULL, l2x0_ids); 1733 1730 if (!np) ··· 1767 1762 if (cache_level != 2) 1768 1763 pr_err("L2C: device tree specifies invalid cache level\n"); 1769 1764 1765 + nosync = of_property_read_bool(np, "arm,outer-sync-disable"); 1766 + 1770 1767 /* Read back current (default) hardware configuration */ 1771 1768 if (data->save) 1772 1769 data->save(l2x0_base); ··· 1783 1776 else 1784 1777 cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID); 1785 1778 1786 - return __l2c_init(data, aux_val, aux_mask, cache_id); 1779 + return __l2c_init(data, aux_val, aux_mask, cache_id, nosync); 1787 1780 } 1788 1781 #endif