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(cpun); 20 cell = of_get_property(cpun, "reg", &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, 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(cpun); 60 cell = of_get_property(cpun, prop_name, &prop_len); 61 if (!cell && !ac && arch_match_cpu_phys_id(cpu, 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, ac); 68 if (arch_match_cpu_phys_id(cpu, 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 "ibm,ppc-interrupt-server#s", 94 cpu, thread)) 95 return true; 96 97 return __of_find_n_match_cpu_property(cpun, "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(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(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(cpu_node, "power-domains", 198 "#power-domain-cells", 0, &args); 199 if (!err) { 200 struct device_node *state_node = 201 of_parse_phandle(args.np, "domain-idle-states", index); 202 203 of_node_put(args.np); 204 if (state_node) 205 return state_node; 206 } 207 208 return of_parse_phandle(cpu_node, "cpu-idle-states", index); 209 } 210 EXPORT_SYMBOL(of_get_cpu_state_node); 211