diff options
-rw-r--r-- | Documentation/devicetree/bindings/arm/l2cc.txt | 10 | ||||
-rw-r--r-- | arch/arm/mm/cache-l2x0.c | 121 |
2 files changed, 131 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/arm/l2cc.txt b/Documentation/devicetree/bindings/arm/l2cc.txt index af527ee111c2..292ef7ca3058 100644 --- a/Documentation/devicetree/bindings/arm/l2cc.txt +++ b/Documentation/devicetree/bindings/arm/l2cc.txt | |||
@@ -2,6 +2,10 @@ | |||
2 | 2 | ||
3 | ARM cores often have a separate level 2 cache controller. There are various | 3 | ARM cores often have a separate level 2 cache controller. There are various |
4 | implementations of the L2 cache controller with compatible programming models. | 4 | implementations of the L2 cache controller with compatible programming models. |
5 | Some of the properties that are just prefixed "cache-*" are taken from section | ||
6 | 3.7.3 of the ePAPR v1.1 specification which can be found at: | ||
7 | https://www.power.org/wp-content/uploads/2012/06/Power_ePAPR_APPROVED_v1.1.pdf | ||
8 | |||
5 | The ARM L2 cache representation in the device tree should be done as follows: | 9 | The ARM L2 cache representation in the device tree should be done as follows: |
6 | 10 | ||
7 | Required properties: | 11 | Required properties: |
@@ -44,6 +48,12 @@ Optional properties: | |||
44 | I/O coherent mode. Valid only when the arm,pl310-cache compatible | 48 | I/O coherent mode. Valid only when the arm,pl310-cache compatible |
45 | string is used. | 49 | string is used. |
46 | - interrupts : 1 combined interrupt. | 50 | - interrupts : 1 combined interrupt. |
51 | - cache-size : specifies the size in bytes of the cache | ||
52 | - cache-sets : specifies the number of associativity sets of the cache | ||
53 | - cache-block-size : specifies the size in bytes of a cache block | ||
54 | - cache-line-size : specifies the size in bytes of a line in the cache, | ||
55 | if this is not specified, the line size is assumed to be equal to the | ||
56 | cache block size | ||
47 | - cache-id-part: cache id part number to be used if it is not present | 57 | - cache-id-part: cache id part number to be used if it is not present |
48 | on hardware | 58 | on hardware |
49 | - wt-override: If present then L2 is forced to Write through mode | 59 | - wt-override: If present then L2 is forced to Write through mode |
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 */ |
946 | static u32 cache_id_part_number_from_dt; | 947 | static 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 | */ | ||
959 | static 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 | |||
948 | static void __init l2x0_of_parse(const struct device_node *np, | 1041 | static 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 | ||
1052 | static const struct l2c_init_data of_l2c310_data __initconst = { | 1173 | static const struct l2c_init_data of_l2c310_data __initconst = { |