aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/cache-l2x0.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mm/cache-l2x0.c')
-rw-r--r--arch/arm/mm/cache-l2x0.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 5f2c988a06ac..55f9d6e0cc88 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -21,6 +21,7 @@
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/smp.h> 22#include <linux/smp.h>
23#include <linux/spinlock.h> 23#include <linux/spinlock.h>
24#include <linux/log2.h>
24#include <linux/io.h> 25#include <linux/io.h>
25#include <linux/of.h> 26#include <linux/of.h>
26#include <linux/of_address.h> 27#include <linux/of_address.h>
@@ -945,6 +946,98 @@ static int l2_wt_override;
945 * pass it though the device tree */ 946 * pass it though the device tree */
946static u32 cache_id_part_number_from_dt; 947static u32 cache_id_part_number_from_dt;
947 948
949/**
950 * l2x0_cache_size_of_parse() - read cache size parameters from DT
951 * @np: the device tree node for the l2 cache
952 * @aux_val: pointer to machine-supplied auxilary register value, to
953 * be augmented by the call (bits to be set to 1)
954 * @aux_mask: pointer to machine-supplied auxilary register mask, to
955 * be augmented by the call (bits to be set to 0)
956 * @associativity: variable to return the calculated associativity in
957 * @max_way_size: the maximum size in bytes for the cache ways
958 */
959static void __init l2x0_cache_size_of_parse(const struct device_node *np,
960 u32 *aux_val, u32 *aux_mask,
961 u32 *associativity,
962 u32 max_way_size)
963{
964 u32 mask = 0, val = 0;
965 u32 cache_size = 0, sets = 0;
966 u32 way_size_bits = 1;
967 u32 way_size = 0;
968 u32 block_size = 0;
969 u32 line_size = 0;
970
971 of_property_read_u32(np, "cache-size", &cache_size);
972 of_property_read_u32(np, "cache-sets", &sets);
973 of_property_read_u32(np, "cache-block-size", &block_size);
974 of_property_read_u32(np, "cache-line-size", &line_size);
975
976 if (!cache_size || !sets)
977 return;
978
979 /* All these l2 caches have the same line = block size actually */
980 if (!line_size) {
981 if (block_size) {
982 /* If linesize if not given, it is equal to blocksize */
983 line_size = block_size;
984 } else {
985 /* Fall back to known size */
986 pr_warn("L2C OF: no cache block/line size given: "
987 "falling back to default size %d bytes\n",
988 CACHE_LINE_SIZE);
989 line_size = CACHE_LINE_SIZE;
990 }
991 }
992
993 if (line_size != CACHE_LINE_SIZE)
994 pr_warn("L2C OF: DT supplied line size %d bytes does "
995 "not match hardware line size of %d bytes\n",
996 line_size,
997 CACHE_LINE_SIZE);
998
999 /*
1000 * Since:
1001 * set size = cache size / sets
1002 * ways = cache size / (sets * line size)
1003 * way size = cache size / (cache size / (sets * line size))
1004 * way size = sets * line size
1005 * associativity = ways = cache size / way size
1006 */
1007 way_size = sets * line_size;
1008 *associativity = cache_size / way_size;
1009
1010 if (way_size > max_way_size) {
1011 pr_err("L2C OF: set size %dKB is too large\n", way_size);
1012 return;
1013 }
1014
1015 pr_info("L2C OF: override cache size: %d bytes (%dKB)\n",
1016 cache_size, cache_size >> 10);
1017 pr_info("L2C OF: override line size: %d bytes\n", line_size);
1018 pr_info("L2C OF: override way size: %d bytes (%dKB)\n",
1019 way_size, way_size >> 10);
1020 pr_info("L2C OF: override associativity: %d\n", *associativity);
1021
1022 /*
1023 * Calculates the bits 17:19 to set for way size:
1024 * 512KB -> 6, 256KB -> 5, ... 16KB -> 1
1025 */
1026 way_size_bits = ilog2(way_size >> 10) - 3;
1027 if (way_size_bits < 1 || way_size_bits > 6) {
1028 pr_err("L2C OF: cache way size illegal: %dKB is not mapped\n",
1029 way_size);
1030 return;
1031 }
1032
1033 mask |= L2C_AUX_CTRL_WAY_SIZE_MASK;
1034 val |= (way_size_bits << L2C_AUX_CTRL_WAY_SIZE_SHIFT);
1035
1036 *aux_val &= ~mask;
1037 *aux_val |= val;
1038 *aux_mask &= ~mask;
1039}
1040
948static void __init l2x0_of_parse(const struct device_node *np, 1041static void __init l2x0_of_parse(const struct device_node *np,
949 u32 *aux_val, u32 *aux_mask) 1042 u32 *aux_val, u32 *aux_mask)
950{ 1043{
@@ -952,6 +1045,7 @@ static void __init l2x0_of_parse(const struct device_node *np,
952 u32 tag = 0; 1045 u32 tag = 0;
953 u32 dirty = 0; 1046 u32 dirty = 0;
954 u32 val = 0, mask = 0; 1047 u32 val = 0, mask = 0;
1048 u32 assoc;
955 1049
956 of_property_read_u32(np, "arm,tag-latency", &tag); 1050 of_property_read_u32(np, "arm,tag-latency", &tag);
957 if (tag) { 1051 if (tag) {
@@ -974,6 +1068,15 @@ static void __init l2x0_of_parse(const struct device_node *np,
974 val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT; 1068 val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT;
975 } 1069 }
976 1070
1071 l2x0_cache_size_of_parse(np, aux_val, aux_mask, &assoc, SZ_256K);
1072 if (assoc > 8) {
1073 pr_err("l2x0 of: cache setting yield too high associativity\n");
1074 pr_err("l2x0 of: %d calculated, max 8\n", assoc);
1075 } else {
1076 mask |= L2X0_AUX_CTRL_ASSOC_MASK;
1077 val |= (assoc << L2X0_AUX_CTRL_ASSOC_SHIFT);
1078 }
1079
977 *aux_val &= ~mask; 1080 *aux_val &= ~mask;
978 *aux_val |= val; 1081 *aux_val |= val;
979 *aux_mask &= ~mask; 1082 *aux_mask &= ~mask;
@@ -1021,6 +1124,7 @@ static void __init l2c310_of_parse(const struct device_node *np,
1021 u32 data[3] = { 0, 0, 0 }; 1124 u32 data[3] = { 0, 0, 0 };
1022 u32 tag[3] = { 0, 0, 0 }; 1125 u32 tag[3] = { 0, 0, 0 };
1023 u32 filter[2] = { 0, 0 }; 1126 u32 filter[2] = { 0, 0 };
1127 u32 assoc;
1024 1128
1025 of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag)); 1129 of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag));
1026 if (tag[0] && tag[1] && tag[2]) 1130 if (tag[0] && tag[1] && tag[2])
@@ -1047,6 +1151,23 @@ static void __init l2c310_of_parse(const struct device_node *np,
1047 writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L310_ADDR_FILTER_EN, 1151 writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L310_ADDR_FILTER_EN,
1048 l2x0_base + L310_ADDR_FILTER_START); 1152 l2x0_base + L310_ADDR_FILTER_START);
1049 } 1153 }
1154
1155 l2x0_cache_size_of_parse(np, aux_val, aux_mask, &assoc, SZ_512K);
1156 switch (assoc) {
1157 case 16:
1158 *aux_val &= ~L2X0_AUX_CTRL_ASSOC_MASK;
1159 *aux_val |= L310_AUX_CTRL_ASSOCIATIVITY_16;
1160 *aux_mask &= ~L2X0_AUX_CTRL_ASSOC_MASK;
1161 break;
1162 case 8:
1163 *aux_val &= ~L2X0_AUX_CTRL_ASSOC_MASK;
1164 *aux_mask &= ~L2X0_AUX_CTRL_ASSOC_MASK;
1165 break;
1166 default:
1167 pr_err("PL310 OF: cache setting yield illegal associativity\n");
1168 pr_err("PL310 OF: %d calculated, only 8 and 16 legal\n", assoc);
1169 break;
1170 }
1050} 1171}
1051 1172
1052static const struct l2c_init_data of_l2c310_data __initconst = { 1173static const struct l2c_init_data of_l2c310_data __initconst = {