diff options
Diffstat (limited to 'arch/arm/mm/cache-l2x0.c')
-rw-r--r-- | arch/arm/mm/cache-l2x0.c | 212 |
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 | ||
49 | static void __iomem *l2x0_base; | 50 | static void __iomem *l2x0_base; |
51 | static const struct l2c_init_data *l2x0_data; | ||
50 | static DEFINE_RAW_SPINLOCK(l2x0_lock); | 52 | static DEFINE_RAW_SPINLOCK(l2x0_lock); |
51 | static u32 l2x0_way_mask; /* Bitmask of active ways */ | 53 | static u32 l2x0_way_mask; /* Bitmask of active ways */ |
52 | static u32 l2x0_size; | 54 | static u32 l2x0_size; |
@@ -106,6 +108,14 @@ static inline void l2c_unlock(void __iomem *base, unsigned num) | |||
106 | } | 108 | } |
107 | } | 109 | } |
108 | 110 | ||
111 | static 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 | ||
226 | static 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 | ||
291 | static 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 | |||
299 | static const struct l2c_init_data l2c210_data __initconst = { | 311 | static 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 | ||
618 | static void l2c310_resume(void) | 630 | static 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 | ||
653 | static int l2c310_cpu_enable_flz(struct notifier_block *nb, unsigned long act, void *data) | 655 | static 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 | ||
811 | static 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 | |||
803 | static const struct l2c_init_data l2c310_init_fns __initconst = { | 820 | static 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 | ||
821 | static void __init __l2c_init(const struct l2c_init_data *data, | 839 | static 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 | ||
915 | void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) | 943 | void __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 | ||
1333 | static 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 | ||
1586 | static void tauros3_resume(void) | 1609 | static 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 | ||
1600 | static const struct l2c_init_data of_tauros3_data __initconst = { | 1617 | static 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 |