1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <linux/cpu.h> |
3 | #include <linux/kernel.h> |
4 | #include <linux/of.h> |
5 | |
6 | /** |
7 | * of_get_cpu_hwid - Get the hardware ID from a CPU device node |
8 | * |
9 | * @cpun: CPU number(logical index) for which device node is required |
10 | * @thread: The local thread number to get the hardware ID for. |
11 | * |
12 | * Return: The hardware ID for the CPU node or ~0ULL if not found. |
13 | */ |
14 | u64 of_get_cpu_hwid(struct device_node *cpun, unsigned int thread) |
15 | { |
16 | const __be32 *cell; |
17 | int ac, len; |
18 | |
19 | ac = of_n_addr_cells(np: cpun); |
20 | cell = of_get_property(node: cpun, name: "reg" , lenp: &len); |
21 | if (!cell || !ac || ((sizeof(*cell) * ac * (thread + 1)) > len)) |
22 | return ~0ULL; |
23 | |
24 | cell += ac * thread; |
25 | return of_read_number(cell, size: ac); |
26 | } |
27 | |
28 | /* |
29 | * arch_match_cpu_phys_id - Match the given logical CPU and physical id |
30 | * |
31 | * @cpu: logical cpu index of a core/thread |
32 | * @phys_id: physical identifier of a core/thread |
33 | * |
34 | * CPU logical to physical index mapping is architecture specific. |
35 | * However this __weak function provides a default match of physical |
36 | * id to logical cpu index. phys_id provided here is usually values read |
37 | * from the device tree which must match the hardware internal registers. |
38 | * |
39 | * Returns true if the physical identifier and the logical cpu index |
40 | * correspond to the same core/thread, false otherwise. |
41 | */ |
42 | bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id) |
43 | { |
44 | return (u32)phys_id == cpu; |
45 | } |
46 | |
47 | /* |
48 | * Checks if the given "prop_name" property holds the physical id of the |
49 | * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not |
50 | * NULL, local thread number within the core is returned in it. |
51 | */ |
52 | static bool __of_find_n_match_cpu_property(struct device_node *cpun, |
53 | const char *prop_name, int cpu, unsigned int *thread) |
54 | { |
55 | const __be32 *cell; |
56 | int ac, prop_len, tid; |
57 | u64 hwid; |
58 | |
59 | ac = of_n_addr_cells(np: cpun); |
60 | cell = of_get_property(node: cpun, name: prop_name, lenp: &prop_len); |
61 | if (!cell && !ac && arch_match_cpu_phys_id(cpu, phys_id: 0)) |
62 | return true; |
63 | if (!cell || !ac) |
64 | return false; |
65 | prop_len /= sizeof(*cell) * ac; |
66 | for (tid = 0; tid < prop_len; tid++) { |
67 | hwid = of_read_number(cell, size: ac); |
68 | if (arch_match_cpu_phys_id(cpu, phys_id: hwid)) { |
69 | if (thread) |
70 | *thread = tid; |
71 | return true; |
72 | } |
73 | cell += ac; |
74 | } |
75 | return false; |
76 | } |
77 | |
78 | /* |
79 | * arch_find_n_match_cpu_physical_id - See if the given device node is |
80 | * for the cpu corresponding to logical cpu 'cpu'. Return true if so, |
81 | * else false. If 'thread' is non-NULL, the local thread number within the |
82 | * core is returned in it. |
83 | */ |
84 | bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, |
85 | int cpu, unsigned int *thread) |
86 | { |
87 | /* Check for non-standard "ibm,ppc-interrupt-server#s" property |
88 | * for thread ids on PowerPC. If it doesn't exist fallback to |
89 | * standard "reg" property. |
90 | */ |
91 | if (IS_ENABLED(CONFIG_PPC) && |
92 | __of_find_n_match_cpu_property(cpun, |
93 | prop_name: "ibm,ppc-interrupt-server#s" , |
94 | cpu, thread)) |
95 | return true; |
96 | |
97 | return __of_find_n_match_cpu_property(cpun, prop_name: "reg" , cpu, thread); |
98 | } |
99 | |
100 | /** |
101 | * of_get_cpu_node - Get device node associated with the given logical CPU |
102 | * |
103 | * @cpu: CPU number(logical index) for which device node is required |
104 | * @thread: if not NULL, local thread number within the physical core is |
105 | * returned |
106 | * |
107 | * The main purpose of this function is to retrieve the device node for the |
108 | * given logical CPU index. It should be used to initialize the of_node in |
109 | * cpu device. Once of_node in cpu device is populated, all the further |
110 | * references can use that instead. |
111 | * |
112 | * CPU logical to physical index mapping is architecture specific and is built |
113 | * before booting secondary cores. This function uses arch_match_cpu_phys_id |
114 | * which can be overridden by architecture specific implementation. |
115 | * |
116 | * Return: A node pointer for the logical cpu with refcount incremented, use |
117 | * of_node_put() on it when done. Returns NULL if not found. |
118 | */ |
119 | struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) |
120 | { |
121 | struct device_node *cpun; |
122 | |
123 | for_each_of_cpu_node(cpun) { |
124 | if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread)) |
125 | return cpun; |
126 | } |
127 | return NULL; |
128 | } |
129 | EXPORT_SYMBOL(of_get_cpu_node); |
130 | |
131 | /** |
132 | * of_cpu_device_node_get: Get the CPU device_node for a given logical CPU number |
133 | * |
134 | * @cpu: The logical CPU number |
135 | * |
136 | * Return: Pointer to the device_node for CPU with its reference count |
137 | * incremented of the given logical CPU number or NULL if the CPU device_node |
138 | * is not found. |
139 | */ |
140 | struct device_node *of_cpu_device_node_get(int cpu) |
141 | { |
142 | struct device *cpu_dev; |
143 | cpu_dev = get_cpu_device(cpu); |
144 | if (!cpu_dev) |
145 | return of_get_cpu_node(cpu, NULL); |
146 | return of_node_get(node: cpu_dev->of_node); |
147 | } |
148 | EXPORT_SYMBOL(of_cpu_device_node_get); |
149 | |
150 | /** |
151 | * of_cpu_node_to_id: Get the logical CPU number for a given device_node |
152 | * |
153 | * @cpu_node: Pointer to the device_node for CPU. |
154 | * |
155 | * Return: The logical CPU number of the given CPU device_node or -ENODEV if the |
156 | * CPU is not found. |
157 | */ |
158 | int of_cpu_node_to_id(struct device_node *cpu_node) |
159 | { |
160 | int cpu; |
161 | bool found = false; |
162 | struct device_node *np; |
163 | |
164 | for_each_possible_cpu(cpu) { |
165 | np = of_cpu_device_node_get(cpu); |
166 | found = (cpu_node == np); |
167 | of_node_put(node: np); |
168 | if (found) |
169 | return cpu; |
170 | } |
171 | |
172 | return -ENODEV; |
173 | } |
174 | EXPORT_SYMBOL(of_cpu_node_to_id); |
175 | |
176 | /** |
177 | * of_get_cpu_state_node - Get CPU's idle state node at the given index |
178 | * |
179 | * @cpu_node: The device node for the CPU |
180 | * @index: The index in the list of the idle states |
181 | * |
182 | * Two generic methods can be used to describe a CPU's idle states, either via |
183 | * a flattened description through the "cpu-idle-states" binding or via the |
184 | * hierarchical layout, using the "power-domains" and the "domain-idle-states" |
185 | * bindings. This function check for both and returns the idle state node for |
186 | * the requested index. |
187 | * |
188 | * Return: An idle state node if found at @index. The refcount is incremented |
189 | * for it, so call of_node_put() on it when done. Returns NULL if not found. |
190 | */ |
191 | struct device_node *of_get_cpu_state_node(struct device_node *cpu_node, |
192 | int index) |
193 | { |
194 | struct of_phandle_args args; |
195 | int err; |
196 | |
197 | err = of_parse_phandle_with_args(np: cpu_node, list_name: "power-domains" , |
198 | cells_name: "#power-domain-cells" , index: 0, out_args: &args); |
199 | if (!err) { |
200 | struct device_node *state_node = |
201 | of_parse_phandle(np: args.np, phandle_name: "domain-idle-states" , index); |
202 | |
203 | of_node_put(node: args.np); |
204 | if (state_node) |
205 | return state_node; |
206 | } |
207 | |
208 | return of_parse_phandle(np: cpu_node, phandle_name: "cpu-idle-states" , index); |
209 | } |
210 | EXPORT_SYMBOL(of_get_cpu_state_node); |
211 | |