aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorTomasz Figa <t.figa@samsung.com>2015-01-08 01:50:29 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2015-01-16 09:35:28 -0500
commit6b49241ac2525818508ee2baff9a58541c65421c (patch)
tree70a20680a1f5bfd67566fa10d5cd0c523067eba9 /arch
parent00218241aa0846e75d31b1dbadb5f8a76be1cc97 (diff)
ARM: 8259/1: l2c: Refactor the driver to use commit-like interface
Certain implementations of secure hypervisors (namely the one found on Samsung Exynos-based boards) do not provide access to individual L2C registers. This makes the .write_sec()-based interface insufficient and provoking ugly hacks. This patch is first step to make the driver not rely on availability of writes to individual registers. This is achieved by refactoring the driver to use a commit-like operation scheme: all register values are prepared first and stored in an instance of l2x0_regs struct and then a single callback is responsible to flush those values to the hardware. [mszyprow: rebased onto 'ARM: l2c: use l2c_write_sec() for restoring latency and filter regs' patch] Signed-off-by: Tomasz Figa <t.figa@samsung.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Tested-by: Nishanth Menon <nm@ti.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mm/cache-l2x0.c212
1 files changed, 116 insertions, 96 deletions
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index b83c401ca50c..dde0d54ac41e 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -41,12 +41,14 @@ struct l2c_init_data {
41 void (*enable)(void __iomem *, u32, unsigned); 41 void (*enable)(void __iomem *, u32, unsigned);
42 void (*fixup)(void __iomem *, u32, struct outer_cache_fns *); 42 void (*fixup)(void __iomem *, u32, struct outer_cache_fns *);
43 void (*save)(void __iomem *); 43 void (*save)(void __iomem *);
44 void (*configure)(void __iomem *);
44 struct outer_cache_fns outer_cache; 45 struct outer_cache_fns outer_cache;
45}; 46};
46 47
47#define CACHE_LINE_SIZE 32 48#define CACHE_LINE_SIZE 32
48 49
49static void __iomem *l2x0_base; 50static void __iomem *l2x0_base;
51static const struct l2c_init_data *l2x0_data;
50static DEFINE_RAW_SPINLOCK(l2x0_lock); 52static DEFINE_RAW_SPINLOCK(l2x0_lock);
51static u32 l2x0_way_mask; /* Bitmask of active ways */ 53static u32 l2x0_way_mask; /* Bitmask of active ways */
52static u32 l2x0_size; 54static u32 l2x0_size;
@@ -106,6 +108,14 @@ static inline void l2c_unlock(void __iomem *base, unsigned num)
106 } 108 }
107} 109}
108 110
111static void l2c_configure(void __iomem *base)
112{
113 if (l2x0_data->configure)
114 l2x0_data->configure(base);
115
116 l2c_write_sec(l2x0_saved_regs.aux_ctrl, base, L2X0_AUX_CTRL);
117}
118
109/* 119/*
110 * Enable the L2 cache controller. This function must only be 120 * Enable the L2 cache controller. This function must only be
111 * called when the cache controller is known to be disabled. 121 * called when the cache controller is known to be disabled.
@@ -114,7 +124,12 @@ static void l2c_enable(void __iomem *base, u32 aux, unsigned num_lock)
114{ 124{
115 unsigned long flags; 125 unsigned long flags;
116 126
117 l2c_write_sec(aux, base, L2X0_AUX_CTRL); 127 /* Do not touch the controller if already enabled. */
128 if (readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)
129 return;
130
131 l2x0_saved_regs.aux_ctrl = aux;
132 l2c_configure(base);
118 133
119 l2c_unlock(base, num_lock); 134 l2c_unlock(base, num_lock);
120 135
@@ -208,6 +223,11 @@ static void l2c_save(void __iomem *base)
208 l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); 223 l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
209} 224}
210 225
226static void l2c_resume(void)
227{
228 l2c_enable(l2x0_base, l2x0_saved_regs.aux_ctrl, l2x0_data->num_lock);
229}
230
211/* 231/*
212 * L2C-210 specific code. 232 * L2C-210 specific code.
213 * 233 *
@@ -288,14 +308,6 @@ static void l2c210_sync(void)
288 __l2c210_cache_sync(l2x0_base); 308 __l2c210_cache_sync(l2x0_base);
289} 309}
290 310
291static void l2c210_resume(void)
292{
293 void __iomem *base = l2x0_base;
294
295 if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN))
296 l2c_enable(base, l2x0_saved_regs.aux_ctrl, 1);
297}
298
299static const struct l2c_init_data l2c210_data __initconst = { 311static const struct l2c_init_data l2c210_data __initconst = {
300 .type = "L2C-210", 312 .type = "L2C-210",
301 .way_size_0 = SZ_8K, 313 .way_size_0 = SZ_8K,
@@ -309,7 +321,7 @@ static const struct l2c_init_data l2c210_data __initconst = {
309 .flush_all = l2c210_flush_all, 321 .flush_all = l2c210_flush_all,
310 .disable = l2c_disable, 322 .disable = l2c_disable,
311 .sync = l2c210_sync, 323 .sync = l2c210_sync,
312 .resume = l2c210_resume, 324 .resume = l2c_resume,
313 }, 325 },
314}; 326};
315 327
@@ -466,7 +478,7 @@ static const struct l2c_init_data l2c220_data = {
466 .flush_all = l2c220_flush_all, 478 .flush_all = l2c220_flush_all,
467 .disable = l2c_disable, 479 .disable = l2c_disable,
468 .sync = l2c220_sync, 480 .sync = l2c220_sync,
469 .resume = l2c210_resume, 481 .resume = l2c_resume,
470 }, 482 },
471}; 483};
472 484
@@ -615,39 +627,29 @@ static void __init l2c310_save(void __iomem *base)
615 L310_POWER_CTRL); 627 L310_POWER_CTRL);
616} 628}
617 629
618static void l2c310_resume(void) 630static void l2c310_configure(void __iomem *base)
619{ 631{
620 void __iomem *base = l2x0_base; 632 unsigned revision;
621 633
622 if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) { 634 /* restore pl310 setup */
623 unsigned revision; 635 l2c_write_sec(l2x0_saved_regs.tag_latency, base,
624 636 L310_TAG_LATENCY_CTRL);
625 /* restore pl310 setup */ 637 l2c_write_sec(l2x0_saved_regs.data_latency, base,
626 l2c_write_sec(l2x0_saved_regs.tag_latency, base, 638 L310_DATA_LATENCY_CTRL);
627 L310_TAG_LATENCY_CTRL); 639 l2c_write_sec(l2x0_saved_regs.filter_end, base,
628 l2c_write_sec(l2x0_saved_regs.data_latency, base, 640 L310_ADDR_FILTER_END);
629 L310_DATA_LATENCY_CTRL); 641 l2c_write_sec(l2x0_saved_regs.filter_start, base,
630 l2c_write_sec(l2x0_saved_regs.filter_end, base, 642 L310_ADDR_FILTER_START);
631 L310_ADDR_FILTER_END); 643
632 l2c_write_sec(l2x0_saved_regs.filter_start, base, 644 revision = readl_relaxed(base + L2X0_CACHE_ID) &
633 L310_ADDR_FILTER_START); 645 L2X0_CACHE_ID_RTL_MASK;
634 646
635 revision = readl_relaxed(base + L2X0_CACHE_ID) & 647 if (revision >= L310_CACHE_ID_RTL_R2P0)
636 L2X0_CACHE_ID_RTL_MASK; 648 l2c_write_sec(l2x0_saved_regs.prefetch_ctrl, base,
637 649 L310_PREFETCH_CTRL);
638 if (revision >= L310_CACHE_ID_RTL_R2P0) 650 if (revision >= L310_CACHE_ID_RTL_R3P0)
639 l2c_write_sec(l2x0_saved_regs.prefetch_ctrl, base, 651 l2c_write_sec(l2x0_saved_regs.pwr_ctrl, base,
640 L310_PREFETCH_CTRL); 652 L310_POWER_CTRL);
641 if (revision >= L310_CACHE_ID_RTL_R3P0)
642 l2c_write_sec(l2x0_saved_regs.pwr_ctrl, base,
643 L310_POWER_CTRL);
644
645 l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8);
646
647 /* Re-enable full-line-of-zeros for Cortex-A9 */
648 if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO)
649 set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1));
650 }
651} 653}
652 654
653static int l2c310_cpu_enable_flz(struct notifier_block *nb, unsigned long act, void *data) 655static int l2c310_cpu_enable_flz(struct notifier_block *nb, unsigned long act, void *data)
@@ -699,6 +701,23 @@ static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock)
699 aux &= ~(L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP); 701 aux &= ~(L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP);
700 } 702 }
701 703
704 /* r3p0 or later has power control register */
705 if (rev >= L310_CACHE_ID_RTL_R3P0)
706 l2x0_saved_regs.pwr_ctrl = L310_DYNAMIC_CLK_GATING_EN |
707 L310_STNDBY_MODE_EN;
708
709 /*
710 * Always enable non-secure access to the lockdown registers -
711 * we write to them as part of the L2C enable sequence so they
712 * need to be accessible.
713 */
714 aux |= L310_AUX_CTRL_NS_LOCKDOWN;
715
716 l2c_enable(base, aux, num_lock);
717
718 /* Read back resulting AUX_CTRL value as it could have been altered. */
719 aux = readl_relaxed(base + L2X0_AUX_CTRL);
720
702 if (aux & (L310_AUX_CTRL_DATA_PREFETCH | L310_AUX_CTRL_INSTR_PREFETCH)) { 721 if (aux & (L310_AUX_CTRL_DATA_PREFETCH | L310_AUX_CTRL_INSTR_PREFETCH)) {
703 u32 prefetch = readl_relaxed(base + L310_PREFETCH_CTRL); 722 u32 prefetch = readl_relaxed(base + L310_PREFETCH_CTRL);
704 723
@@ -712,23 +731,12 @@ static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock)
712 if (rev >= L310_CACHE_ID_RTL_R3P0) { 731 if (rev >= L310_CACHE_ID_RTL_R3P0) {
713 u32 power_ctrl; 732 u32 power_ctrl;
714 733
715 l2c_write_sec(L310_DYNAMIC_CLK_GATING_EN | L310_STNDBY_MODE_EN,
716 base, L310_POWER_CTRL);
717 power_ctrl = readl_relaxed(base + L310_POWER_CTRL); 734 power_ctrl = readl_relaxed(base + L310_POWER_CTRL);
718 pr_info("L2C-310 dynamic clock gating %sabled, standby mode %sabled\n", 735 pr_info("L2C-310 dynamic clock gating %sabled, standby mode %sabled\n",
719 power_ctrl & L310_DYNAMIC_CLK_GATING_EN ? "en" : "dis", 736 power_ctrl & L310_DYNAMIC_CLK_GATING_EN ? "en" : "dis",
720 power_ctrl & L310_STNDBY_MODE_EN ? "en" : "dis"); 737 power_ctrl & L310_STNDBY_MODE_EN ? "en" : "dis");
721 } 738 }
722 739
723 /*
724 * Always enable non-secure access to the lockdown registers -
725 * we write to them as part of the L2C enable sequence so they
726 * need to be accessible.
727 */
728 aux |= L310_AUX_CTRL_NS_LOCKDOWN;
729
730 l2c_enable(base, aux, num_lock);
731
732 if (aux & L310_AUX_CTRL_FULL_LINE_ZERO) { 740 if (aux & L310_AUX_CTRL_FULL_LINE_ZERO) {
733 set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1)); 741 set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1));
734 cpu_notifier(l2c310_cpu_enable_flz, 0); 742 cpu_notifier(l2c310_cpu_enable_flz, 0);
@@ -760,11 +768,11 @@ static void __init l2c310_fixup(void __iomem *base, u32 cache_id,
760 768
761 if (revision >= L310_CACHE_ID_RTL_R3P0 && 769 if (revision >= L310_CACHE_ID_RTL_R3P0 &&
762 revision < L310_CACHE_ID_RTL_R3P2) { 770 revision < L310_CACHE_ID_RTL_R3P2) {
763 u32 val = readl_relaxed(base + L310_PREFETCH_CTRL); 771 u32 val = l2x0_saved_regs.prefetch_ctrl;
764 /* I don't think bit23 is required here... but iMX6 does so */ 772 /* I don't think bit23 is required here... but iMX6 does so */
765 if (val & (BIT(30) | BIT(23))) { 773 if (val & (BIT(30) | BIT(23))) {
766 val &= ~(BIT(30) | BIT(23)); 774 val &= ~(BIT(30) | BIT(23));
767 l2c_write_sec(val, base, L310_PREFETCH_CTRL); 775 l2x0_saved_regs.prefetch_ctrl = val;
768 errata[n++] = "752271"; 776 errata[n++] = "752271";
769 } 777 }
770 } 778 }
@@ -800,6 +808,15 @@ static void l2c310_disable(void)
800 l2c_disable(); 808 l2c_disable();
801} 809}
802 810
811static void l2c310_resume(void)
812{
813 l2c_resume();
814
815 /* Re-enable full-line-of-zeros for Cortex-A9 */
816 if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO)
817 set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1));
818}
819
803static const struct l2c_init_data l2c310_init_fns __initconst = { 820static const struct l2c_init_data l2c310_init_fns __initconst = {
804 .type = "L2C-310", 821 .type = "L2C-310",
805 .way_size_0 = SZ_8K, 822 .way_size_0 = SZ_8K,
@@ -807,6 +824,7 @@ static const struct l2c_init_data l2c310_init_fns __initconst = {
807 .enable = l2c310_enable, 824 .enable = l2c310_enable,
808 .fixup = l2c310_fixup, 825 .fixup = l2c310_fixup,
809 .save = l2c310_save, 826 .save = l2c310_save,
827 .configure = l2c310_configure,
810 .outer_cache = { 828 .outer_cache = {
811 .inv_range = l2c210_inv_range, 829 .inv_range = l2c210_inv_range,
812 .clean_range = l2c210_clean_range, 830 .clean_range = l2c210_clean_range,
@@ -818,14 +836,22 @@ static const struct l2c_init_data l2c310_init_fns __initconst = {
818 }, 836 },
819}; 837};
820 838
821static void __init __l2c_init(const struct l2c_init_data *data, 839static int __init __l2c_init(const struct l2c_init_data *data,
822 u32 aux_val, u32 aux_mask, u32 cache_id) 840 u32 aux_val, u32 aux_mask, u32 cache_id)
823{ 841{
824 struct outer_cache_fns fns; 842 struct outer_cache_fns fns;
825 unsigned way_size_bits, ways; 843 unsigned way_size_bits, ways;
826 u32 aux, old_aux; 844 u32 aux, old_aux;
827 845
828 /* 846 /*
847 * Save the pointer globally so that callbacks which do not receive
848 * context from callers can access the structure.
849 */
850 l2x0_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
851 if (!l2x0_data)
852 return -ENOMEM;
853
854 /*
829 * Sanity check the aux values. aux_mask is the bits we preserve 855 * Sanity check the aux values. aux_mask is the bits we preserve
830 * from reading the hardware register, and aux_val is the bits we 856 * from reading the hardware register, and aux_val is the bits we
831 * set. 857 * set.
@@ -910,6 +936,8 @@ static void __init __l2c_init(const struct l2c_init_data *data,
910 data->type, ways, l2x0_size >> 10); 936 data->type, ways, l2x0_size >> 10);
911 pr_info("%s: CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n", 937 pr_info("%s: CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n",
912 data->type, cache_id, aux); 938 data->type, cache_id, aux);
939
940 return 0;
913} 941}
914 942
915void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) 943void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
@@ -936,6 +964,10 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
936 break; 964 break;
937 } 965 }
938 966
967 /* Read back current (default) hardware configuration */
968 if (data->save)
969 data->save(l2x0_base);
970
939 __l2c_init(data, aux_val, aux_mask, cache_id); 971 __l2c_init(data, aux_val, aux_mask, cache_id);
940} 972}
941 973
@@ -1102,7 +1134,7 @@ static const struct l2c_init_data of_l2c210_data __initconst = {
1102 .flush_all = l2c210_flush_all, 1134 .flush_all = l2c210_flush_all,
1103 .disable = l2c_disable, 1135 .disable = l2c_disable,
1104 .sync = l2c210_sync, 1136 .sync = l2c210_sync,
1105 .resume = l2c210_resume, 1137 .resume = l2c_resume,
1106 }, 1138 },
1107}; 1139};
1108 1140
@@ -1120,7 +1152,7 @@ static const struct l2c_init_data of_l2c220_data __initconst = {
1120 .flush_all = l2c220_flush_all, 1152 .flush_all = l2c220_flush_all,
1121 .disable = l2c_disable, 1153 .disable = l2c_disable,
1122 .sync = l2c220_sync, 1154 .sync = l2c220_sync,
1123 .resume = l2c210_resume, 1155 .resume = l2c_resume,
1124 }, 1156 },
1125}; 1157};
1126 1158
@@ -1135,28 +1167,26 @@ static void __init l2c310_of_parse(const struct device_node *np,
1135 1167
1136 of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag)); 1168 of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag));
1137 if (tag[0] && tag[1] && tag[2]) 1169 if (tag[0] && tag[1] && tag[2])
1138 l2c_write_sec( 1170 l2x0_saved_regs.tag_latency =
1139 L310_LATENCY_CTRL_RD(tag[0] - 1) | 1171 L310_LATENCY_CTRL_RD(tag[0] - 1) |
1140 L310_LATENCY_CTRL_WR(tag[1] - 1) | 1172 L310_LATENCY_CTRL_WR(tag[1] - 1) |
1141 L310_LATENCY_CTRL_SETUP(tag[2] - 1), 1173 L310_LATENCY_CTRL_SETUP(tag[2] - 1);
1142 l2x0_base, L310_TAG_LATENCY_CTRL);
1143 1174
1144 of_property_read_u32_array(np, "arm,data-latency", 1175 of_property_read_u32_array(np, "arm,data-latency",
1145 data, ARRAY_SIZE(data)); 1176 data, ARRAY_SIZE(data));
1146 if (data[0] && data[1] && data[2]) 1177 if (data[0] && data[1] && data[2])
1147 l2c_write_sec( 1178 l2x0_saved_regs.data_latency =
1148 L310_LATENCY_CTRL_RD(data[0] - 1) | 1179 L310_LATENCY_CTRL_RD(data[0] - 1) |
1149 L310_LATENCY_CTRL_WR(data[1] - 1) | 1180 L310_LATENCY_CTRL_WR(data[1] - 1) |
1150 L310_LATENCY_CTRL_SETUP(data[2] - 1), 1181 L310_LATENCY_CTRL_SETUP(data[2] - 1);
1151 l2x0_base, L310_DATA_LATENCY_CTRL);
1152 1182
1153 of_property_read_u32_array(np, "arm,filter-ranges", 1183 of_property_read_u32_array(np, "arm,filter-ranges",
1154 filter, ARRAY_SIZE(filter)); 1184 filter, ARRAY_SIZE(filter));
1155 if (filter[1]) { 1185 if (filter[1]) {
1156 l2c_write_sec(ALIGN(filter[0] + filter[1], SZ_1M), 1186 l2x0_saved_regs.filter_end =
1157 l2x0_base, L310_ADDR_FILTER_END); 1187 ALIGN(filter[0] + filter[1], SZ_1M);
1158 l2c_write_sec((filter[0] & ~(SZ_1M - 1)) | L310_ADDR_FILTER_EN, 1188 l2x0_saved_regs.filter_start = (filter[0] & ~(SZ_1M - 1))
1159 l2x0_base, L310_ADDR_FILTER_START); 1189 | L310_ADDR_FILTER_EN;
1160 } 1190 }
1161 1191
1162 ret = l2x0_cache_size_of_parse(np, aux_val, aux_mask, &assoc, SZ_512K); 1192 ret = l2x0_cache_size_of_parse(np, aux_val, aux_mask, &assoc, SZ_512K);
@@ -1188,6 +1218,7 @@ static const struct l2c_init_data of_l2c310_data __initconst = {
1188 .enable = l2c310_enable, 1218 .enable = l2c310_enable,
1189 .fixup = l2c310_fixup, 1219 .fixup = l2c310_fixup,
1190 .save = l2c310_save, 1220 .save = l2c310_save,
1221 .configure = l2c310_configure,
1191 .outer_cache = { 1222 .outer_cache = {
1192 .inv_range = l2c210_inv_range, 1223 .inv_range = l2c210_inv_range,
1193 .clean_range = l2c210_clean_range, 1224 .clean_range = l2c210_clean_range,
@@ -1216,6 +1247,7 @@ static const struct l2c_init_data of_l2c310_coherent_data __initconst = {
1216 .enable = l2c310_enable, 1247 .enable = l2c310_enable,
1217 .fixup = l2c310_fixup, 1248 .fixup = l2c310_fixup,
1218 .save = l2c310_save, 1249 .save = l2c310_save,
1250 .configure = l2c310_configure,
1219 .outer_cache = { 1251 .outer_cache = {
1220 .inv_range = l2c210_inv_range, 1252 .inv_range = l2c210_inv_range,
1221 .clean_range = l2c210_clean_range, 1253 .clean_range = l2c210_clean_range,
@@ -1330,16 +1362,6 @@ static void aurora_save(void __iomem *base)
1330 l2x0_saved_regs.aux_ctrl = readl_relaxed(base + L2X0_AUX_CTRL); 1362 l2x0_saved_regs.aux_ctrl = readl_relaxed(base + L2X0_AUX_CTRL);
1331} 1363}
1332 1364
1333static void aurora_resume(void)
1334{
1335 void __iomem *base = l2x0_base;
1336
1337 if (!(readl(base + L2X0_CTRL) & L2X0_CTRL_EN)) {
1338 writel_relaxed(l2x0_saved_regs.aux_ctrl, base + L2X0_AUX_CTRL);
1339 writel_relaxed(l2x0_saved_regs.ctrl, base + L2X0_CTRL);
1340 }
1341}
1342
1343/* 1365/*
1344 * For Aurora cache in no outer mode, enable via the CP15 coprocessor 1366 * For Aurora cache in no outer mode, enable via the CP15 coprocessor
1345 * broadcasting of cache commands to L2. 1367 * broadcasting of cache commands to L2.
@@ -1401,7 +1423,7 @@ static const struct l2c_init_data of_aurora_with_outer_data __initconst = {
1401 .flush_all = l2x0_flush_all, 1423 .flush_all = l2x0_flush_all,
1402 .disable = l2x0_disable, 1424 .disable = l2x0_disable,
1403 .sync = l2x0_cache_sync, 1425 .sync = l2x0_cache_sync,
1404 .resume = aurora_resume, 1426 .resume = l2c_resume,
1405 }, 1427 },
1406}; 1428};
1407 1429
@@ -1414,7 +1436,7 @@ static const struct l2c_init_data of_aurora_no_outer_data __initconst = {
1414 .fixup = aurora_fixup, 1436 .fixup = aurora_fixup,
1415 .save = aurora_save, 1437 .save = aurora_save,
1416 .outer_cache = { 1438 .outer_cache = {
1417 .resume = aurora_resume, 1439 .resume = l2c_resume,
1418 }, 1440 },
1419}; 1441};
1420 1442
@@ -1562,6 +1584,7 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = {
1562 .of_parse = l2c310_of_parse, 1584 .of_parse = l2c310_of_parse,
1563 .enable = l2c310_enable, 1585 .enable = l2c310_enable,
1564 .save = l2c310_save, 1586 .save = l2c310_save,
1587 .configure = l2c310_configure,
1565 .outer_cache = { 1588 .outer_cache = {
1566 .inv_range = bcm_inv_range, 1589 .inv_range = bcm_inv_range,
1567 .clean_range = bcm_clean_range, 1590 .clean_range = bcm_clean_range,
@@ -1583,18 +1606,12 @@ static void __init tauros3_save(void __iomem *base)
1583 readl_relaxed(base + L310_PREFETCH_CTRL); 1606 readl_relaxed(base + L310_PREFETCH_CTRL);
1584} 1607}
1585 1608
1586static void tauros3_resume(void) 1609static void tauros3_configure(void __iomem *base)
1587{ 1610{
1588 void __iomem *base = l2x0_base; 1611 writel_relaxed(l2x0_saved_regs.aux2_ctrl,
1589 1612 base + TAUROS3_AUX2_CTRL);
1590 if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) { 1613 writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
1591 writel_relaxed(l2x0_saved_regs.aux2_ctrl, 1614 base + L310_PREFETCH_CTRL);
1592 base + TAUROS3_AUX2_CTRL);
1593 writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
1594 base + L310_PREFETCH_CTRL);
1595
1596 l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8);
1597 }
1598} 1615}
1599 1616
1600static const struct l2c_init_data of_tauros3_data __initconst = { 1617static const struct l2c_init_data of_tauros3_data __initconst = {
@@ -1603,9 +1620,10 @@ static const struct l2c_init_data of_tauros3_data __initconst = {
1603 .num_lock = 8, 1620 .num_lock = 8,
1604 .enable = l2c_enable, 1621 .enable = l2c_enable,
1605 .save = tauros3_save, 1622 .save = tauros3_save,
1623 .configure = tauros3_configure,
1606 /* Tauros3 broadcasts L1 cache operations to L2 */ 1624 /* Tauros3 broadcasts L1 cache operations to L2 */
1607 .outer_cache = { 1625 .outer_cache = {
1608 .resume = tauros3_resume, 1626 .resume = l2c_resume,
1609 }, 1627 },
1610}; 1628};
1611 1629
@@ -1661,6 +1679,10 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
1661 if (!of_property_read_bool(np, "cache-unified")) 1679 if (!of_property_read_bool(np, "cache-unified"))
1662 pr_err("L2C: device tree omits to specify unified cache\n"); 1680 pr_err("L2C: device tree omits to specify unified cache\n");
1663 1681
1682 /* Read back current (default) hardware configuration */
1683 if (data->save)
1684 data->save(l2x0_base);
1685
1664 /* L2 configuration can only be changed if the cache is disabled */ 1686 /* L2 configuration can only be changed if the cache is disabled */
1665 if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) 1687 if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN))
1666 if (data->of_parse) 1688 if (data->of_parse)
@@ -1671,8 +1693,6 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
1671 else 1693 else
1672 cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID); 1694 cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
1673 1695
1674 __l2c_init(data, aux_val, aux_mask, cache_id); 1696 return __l2c_init(data, aux_val, aux_mask, cache_id);
1675
1676 return 0;
1677} 1697}
1678#endif 1698#endif