1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2017 SiFive
8 #include <linux/of_device.h>
9 #include <asm/cacheinfo.h>
11 static struct riscv_cacheinfo_ops
*rv_cache_ops
;
13 void riscv_set_cacheinfo_ops(struct riscv_cacheinfo_ops
*ops
)
17 EXPORT_SYMBOL_GPL(riscv_set_cacheinfo_ops
);
19 const struct attribute_group
*
20 cache_get_priv_group(struct cacheinfo
*this_leaf
)
22 if (rv_cache_ops
&& rv_cache_ops
->get_priv_group
)
23 return rv_cache_ops
->get_priv_group(this_leaf
);
27 static struct cacheinfo
*get_cacheinfo(u32 level
, enum cache_type type
)
29 struct cpu_cacheinfo
*this_cpu_ci
= get_cpu_cacheinfo(smp_processor_id());
30 struct cacheinfo
*this_leaf
;
33 for (index
= 0; index
< this_cpu_ci
->num_leaves
; index
++) {
34 this_leaf
= this_cpu_ci
->info_list
+ index
;
35 if (this_leaf
->level
== level
&& this_leaf
->type
== type
)
42 uintptr_t get_cache_size(u32 level
, enum cache_type type
)
44 struct cacheinfo
*this_leaf
= get_cacheinfo(level
, type
);
46 return this_leaf
? this_leaf
->size
: 0;
49 uintptr_t get_cache_geometry(u32 level
, enum cache_type type
)
51 struct cacheinfo
*this_leaf
= get_cacheinfo(level
, type
);
53 return this_leaf
? (this_leaf
->ways_of_associativity
<< 16 |
54 this_leaf
->coherency_line_size
) :
58 static void ci_leaf_init(struct cacheinfo
*this_leaf
, enum cache_type type
,
59 unsigned int level
, unsigned int size
,
60 unsigned int sets
, unsigned int line_size
)
62 this_leaf
->level
= level
;
63 this_leaf
->type
= type
;
64 this_leaf
->size
= size
;
65 this_leaf
->number_of_sets
= sets
;
66 this_leaf
->coherency_line_size
= line_size
;
69 * If the cache is fully associative, there is no need to
70 * check the other properties.
76 * Set the ways number for n-ways associative, make sure
77 * all properties are big than zero.
79 if (sets
> 0 && size
> 0 && line_size
> 0)
80 this_leaf
->ways_of_associativity
= (size
/ sets
) / line_size
;
83 static void fill_cacheinfo(struct cacheinfo
**this_leaf
,
84 struct device_node
*node
, unsigned int level
)
86 unsigned int size
, sets
, line_size
;
88 if (!of_property_read_u32(node
, "cache-size", &size
) &&
89 !of_property_read_u32(node
, "cache-block-size", &line_size
) &&
90 !of_property_read_u32(node
, "cache-sets", &sets
)) {
91 ci_leaf_init((*this_leaf
)++, CACHE_TYPE_UNIFIED
, level
, size
, sets
, line_size
);
94 if (!of_property_read_u32(node
, "i-cache-size", &size
) &&
95 !of_property_read_u32(node
, "i-cache-sets", &sets
) &&
96 !of_property_read_u32(node
, "i-cache-block-size", &line_size
)) {
97 ci_leaf_init((*this_leaf
)++, CACHE_TYPE_INST
, level
, size
, sets
, line_size
);
100 if (!of_property_read_u32(node
, "d-cache-size", &size
) &&
101 !of_property_read_u32(node
, "d-cache-sets", &sets
) &&
102 !of_property_read_u32(node
, "d-cache-block-size", &line_size
)) {
103 ci_leaf_init((*this_leaf
)++, CACHE_TYPE_DATA
, level
, size
, sets
, line_size
);
107 static int __init_cache_level(unsigned int cpu
)
109 struct cpu_cacheinfo
*this_cpu_ci
= get_cpu_cacheinfo(cpu
);
110 struct device_node
*np
= of_cpu_device_node_get(cpu
);
111 struct device_node
*prev
= NULL
;
112 int levels
= 0, leaves
= 0, level
;
114 if (of_property_read_bool(np
, "cache-size"))
116 if (of_property_read_bool(np
, "i-cache-size"))
118 if (of_property_read_bool(np
, "d-cache-size"))
124 while ((np
= of_find_next_cache_node(np
))) {
127 if (!of_device_is_compatible(np
, "cache"))
129 if (of_property_read_u32(np
, "cache-level", &level
))
133 if (of_property_read_bool(np
, "cache-size"))
135 if (of_property_read_bool(np
, "i-cache-size"))
137 if (of_property_read_bool(np
, "d-cache-size"))
143 this_cpu_ci
->num_levels
= levels
;
144 this_cpu_ci
->num_leaves
= leaves
;
149 static int __populate_cache_leaves(unsigned int cpu
)
151 struct cpu_cacheinfo
*this_cpu_ci
= get_cpu_cacheinfo(cpu
);
152 struct cacheinfo
*this_leaf
= this_cpu_ci
->info_list
;
153 struct device_node
*np
= of_cpu_device_node_get(cpu
);
154 struct device_node
*prev
= NULL
;
155 int levels
= 1, level
= 1;
157 /* Level 1 caches in cpu node */
158 fill_cacheinfo(&this_leaf
, np
, level
);
160 /* Next level caches in cache nodes */
162 while ((np
= of_find_next_cache_node(np
))) {
166 if (!of_device_is_compatible(np
, "cache"))
168 if (of_property_read_u32(np
, "cache-level", &level
))
173 fill_cacheinfo(&this_leaf
, np
, level
);
182 DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level
)
183 DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves
)