1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/cacheinfo.h>
15#include <linux/cpu.h>
16#include <linux/of.h>
17#include <linux/of_device.h>
18
19static void ci_leaf_init(struct cacheinfo *this_leaf,
20 struct device_node *node,
21 enum cache_type type, unsigned int level)
22{
23 this_leaf->level = level;
24 this_leaf->type = type;
25}
26
27static int __init_cache_level(unsigned int cpu)
28{
29 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
30 struct device_node *np = of_cpu_device_node_get(cpu);
31 struct device_node *prev = NULL;
32 int levels = 0, leaves = 0, level;
33
34 if (of_property_read_bool(np, "cache-size"))
35 ++leaves;
36 if (of_property_read_bool(np, "i-cache-size"))
37 ++leaves;
38 if (of_property_read_bool(np, "d-cache-size"))
39 ++leaves;
40 if (leaves > 0)
41 levels = 1;
42
43 prev = np;
44 while ((np = of_find_next_cache_node(np))) {
45 of_node_put(prev);
46 prev = np;
47 if (!of_device_is_compatible(np, "cache"))
48 break;
49 if (of_property_read_u32(np, "cache-level", &level))
50 break;
51 if (level <= levels)
52 break;
53 if (of_property_read_bool(np, "cache-size"))
54 ++leaves;
55 if (of_property_read_bool(np, "i-cache-size"))
56 ++leaves;
57 if (of_property_read_bool(np, "d-cache-size"))
58 ++leaves;
59 levels = level;
60 }
61
62 of_node_put(np);
63 this_cpu_ci->num_levels = levels;
64 this_cpu_ci->num_leaves = leaves;
65
66 return 0;
67}
68
69static int __populate_cache_leaves(unsigned int cpu)
70{
71 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
72 struct cacheinfo *this_leaf = this_cpu_ci->info_list;
73 struct device_node *np = of_cpu_device_node_get(cpu);
74 struct device_node *prev = NULL;
75 int levels = 1, level = 1;
76
77 if (of_property_read_bool(np, "cache-size"))
78 ci_leaf_init(this_leaf++, np, CACHE_TYPE_UNIFIED, level);
79 if (of_property_read_bool(np, "i-cache-size"))
80 ci_leaf_init(this_leaf++, np, CACHE_TYPE_INST, level);
81 if (of_property_read_bool(np, "d-cache-size"))
82 ci_leaf_init(this_leaf++, np, CACHE_TYPE_DATA, level);
83
84 prev = np;
85 while ((np = of_find_next_cache_node(np))) {
86 of_node_put(prev);
87 prev = np;
88 if (!of_device_is_compatible(np, "cache"))
89 break;
90 if (of_property_read_u32(np, "cache-level", &level))
91 break;
92 if (level <= levels)
93 break;
94 if (of_property_read_bool(np, "cache-size"))
95 ci_leaf_init(this_leaf++, np, CACHE_TYPE_UNIFIED, level);
96 if (of_property_read_bool(np, "i-cache-size"))
97 ci_leaf_init(this_leaf++, np, CACHE_TYPE_INST, level);
98 if (of_property_read_bool(np, "d-cache-size"))
99 ci_leaf_init(this_leaf++, np, CACHE_TYPE_DATA, level);
100 levels = level;
101 }
102 of_node_put(np);
103
104 return 0;
105}
106
107DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
108DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)
109