aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-08-22 18:57:19 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-08-22 18:57:19 -0400
commit09198f8feff1fcdf03994f35955292f85b299bd6 (patch)
treed847a584546c13d1761036a2aae8d28437550df0
parent4eb5178c9cc09295111b79a99183f555c51887b4 (diff)
parent1037b2752345cc5666e90b711a913ab2ae6c5920 (diff)
Merge branch 'cpu_of_node' of git://linux-arm.org/linux-skn into pm-cpufreq-next
Pull DT/core/cpufreq cpu_ofnode updates for v3.12 from Sudeep KarkadaNagesha. * 'cpu_of_node' of git://linux-arm.org/linux-skn: cpufreq: pmac32-cpufreq: remove device tree parsing for cpu nodes cpufreq: pmac64-cpufreq: remove device tree parsing for cpu nodes cpufreq: maple-cpufreq: remove device tree parsing for cpu nodes cpufreq: arm_big_little: remove device tree parsing for cpu nodes cpufreq: kirkwood-cpufreq: remove device tree parsing for cpu nodes cpufreq: spear-cpufreq: remove device tree parsing for cpu nodes cpufreq: highbank-cpufreq: remove device tree parsing for cpu nodes cpufreq: cpufreq-cpu0: remove device tree parsing for cpu nodes cpufreq: imx6q-cpufreq: remove device tree parsing for cpu nodes drivers/bus: arm-cci: avoid parsing DT for cpu device nodes ARM: mvebu: remove device tree parsing for cpu nodes ARM: topology: remove hwid/MPIDR dependency from cpu_capacity of/device: add helper to get cpu device node from logical cpu index driver/core: cpu: initialize of_node in cpu's device struture ARM: DT/kernel: define ARM specific arch_match_cpu_phys_id of: move of_get_cpu_node implementation to DT core library powerpc: refactor of_get_cpu_node to support other architectures openrisc: remove undefined of_get_cpu_node declaration microblaze: remove undefined of_get_cpu_node declaration
-rw-r--r--arch/arm/kernel/devtree.c5
-rw-r--r--arch/arm/kernel/topology.c61
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c3
-rw-r--r--arch/arm/mach-mvebu/platsmp.c51
-rw-r--r--arch/microblaze/include/asm/prom.h3
-rw-r--r--arch/openrisc/include/asm/prom.h3
-rw-r--r--arch/powerpc/include/asm/prom.h3
-rw-r--r--arch/powerpc/kernel/prom.c43
-rw-r--r--drivers/base/cpu.c2
-rw-r--r--drivers/bus/arm-cci.c28
-rw-r--r--drivers/cpufreq/arm_big_little_dt.c40
-rw-r--r--drivers/cpufreq/cpufreq-cpu0.c23
-rw-r--r--drivers/cpufreq/highbank-cpufreq.c18
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c4
-rw-r--r--drivers/cpufreq/kirkwood-cpufreq.c8
-rw-r--r--drivers/cpufreq/maple-cpufreq.c23
-rw-r--r--drivers/cpufreq/pmac32-cpufreq.c5
-rw-r--r--drivers/cpufreq/pmac64-cpufreq.c47
-rw-r--r--drivers/cpufreq/spear-cpufreq.c4
-rw-r--r--drivers/of/base.c95
-rw-r--r--include/linux/cpu.h1
-rw-r--r--include/linux/of.h7
-rw-r--r--include/linux/of_device.h15
23 files changed, 226 insertions, 266 deletions
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index 5859c8bc727c..2ee8a17d2b01 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -169,6 +169,11 @@ void __init arm_dt_init_cpu_maps(void)
169 } 169 }
170} 170}
171 171
172bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
173{
174 return (phys_id & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu);
175}
176
172/** 177/**
173 * setup_machine_fdt - Machine setup when an dtb was passed to the kernel 178 * setup_machine_fdt - Machine setup when an dtb was passed to the kernel
174 * @dt_phys: physical address of dt blob 179 * @dt_phys: physical address of dt blob
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index c5a59546a256..85a87370f144 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -74,12 +74,8 @@ struct cpu_efficiency table_efficiency[] = {
74 {NULL, }, 74 {NULL, },
75}; 75};
76 76
77struct cpu_capacity { 77unsigned long *__cpu_capacity;
78 unsigned long hwid; 78#define cpu_capacity(cpu) __cpu_capacity[cpu]
79 unsigned long capacity;
80};
81
82struct cpu_capacity *cpu_capacity;
83 79
84unsigned long middle_capacity = 1; 80unsigned long middle_capacity = 1;
85 81
@@ -100,15 +96,19 @@ static void __init parse_dt_topology(void)
100 unsigned long capacity = 0; 96 unsigned long capacity = 0;
101 int alloc_size, cpu = 0; 97 int alloc_size, cpu = 0;
102 98
103 alloc_size = nr_cpu_ids * sizeof(struct cpu_capacity); 99 alloc_size = nr_cpu_ids * sizeof(*__cpu_capacity);
104 cpu_capacity = kzalloc(alloc_size, GFP_NOWAIT); 100 __cpu_capacity = kzalloc(alloc_size, GFP_NOWAIT);
105 101
106 while ((cn = of_find_node_by_type(cn, "cpu"))) { 102 for_each_possible_cpu(cpu) {
107 const u32 *rate, *reg; 103 const u32 *rate;
108 int len; 104 int len;
109 105
110 if (cpu >= num_possible_cpus()) 106 /* too early to use cpu->of_node */
111 break; 107 cn = of_get_cpu_node(cpu, NULL);
108 if (!cn) {
109 pr_err("missing device node for CPU %d\n", cpu);
110 continue;
111 }
112 112
113 for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++) 113 for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++)
114 if (of_device_is_compatible(cn, cpu_eff->compatible)) 114 if (of_device_is_compatible(cn, cpu_eff->compatible))
@@ -124,12 +124,6 @@ static void __init parse_dt_topology(void)
124 continue; 124 continue;
125 } 125 }
126 126
127 reg = of_get_property(cn, "reg", &len);
128 if (!reg || len != 4) {
129 pr_err("%s missing reg property\n", cn->full_name);
130 continue;
131 }
132
133 capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency; 127 capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency;
134 128
135 /* Save min capacity of the system */ 129 /* Save min capacity of the system */
@@ -140,13 +134,9 @@ static void __init parse_dt_topology(void)
140 if (capacity > max_capacity) 134 if (capacity > max_capacity)
141 max_capacity = capacity; 135 max_capacity = capacity;
142 136
143 cpu_capacity[cpu].capacity = capacity; 137 cpu_capacity(cpu) = capacity;
144 cpu_capacity[cpu++].hwid = be32_to_cpup(reg);
145 } 138 }
146 139
147 if (cpu < num_possible_cpus())
148 cpu_capacity[cpu].hwid = (unsigned long)(-1);
149
150 /* If min and max capacities are equals, we bypass the update of the 140 /* If min and max capacities are equals, we bypass the update of the
151 * cpu_scale because all CPUs have the same capacity. Otherwise, we 141 * cpu_scale because all CPUs have the same capacity. Otherwise, we
152 * compute a middle_capacity factor that will ensure that the capacity 142 * compute a middle_capacity factor that will ensure that the capacity
@@ -154,9 +144,7 @@ static void __init parse_dt_topology(void)
154 * SCHED_POWER_SCALE, which is the default value, but with the 144 * SCHED_POWER_SCALE, which is the default value, but with the
155 * constraint explained near table_efficiency[]. 145 * constraint explained near table_efficiency[].
156 */ 146 */
157 if (min_capacity == max_capacity) 147 if (4*max_capacity < (3*(max_capacity + min_capacity)))
158 cpu_capacity[0].hwid = (unsigned long)(-1);
159 else if (4*max_capacity < (3*(max_capacity + min_capacity)))
160 middle_capacity = (min_capacity + max_capacity) 148 middle_capacity = (min_capacity + max_capacity)
161 >> (SCHED_POWER_SHIFT+1); 149 >> (SCHED_POWER_SHIFT+1);
162 else 150 else
@@ -170,23 +158,12 @@ static void __init parse_dt_topology(void)
170 * boot. The update of all CPUs is in O(n^2) for heteregeneous system but the 158 * boot. The update of all CPUs is in O(n^2) for heteregeneous system but the
171 * function returns directly for SMP system. 159 * function returns directly for SMP system.
172 */ 160 */
173void update_cpu_power(unsigned int cpu, unsigned long hwid) 161void update_cpu_power(unsigned int cpu)
174{ 162{
175 unsigned int idx = 0; 163 if (!cpu_capacity(cpu))
176
177 /* look for the cpu's hwid in the cpu capacity table */
178 for (idx = 0; idx < num_possible_cpus(); idx++) {
179 if (cpu_capacity[idx].hwid == hwid)
180 break;
181
182 if (cpu_capacity[idx].hwid == -1)
183 return;
184 }
185
186 if (idx == num_possible_cpus())
187 return; 164 return;
188 165
189 set_power_scale(cpu, cpu_capacity[idx].capacity / middle_capacity); 166 set_power_scale(cpu, cpu_capacity(cpu) / middle_capacity);
190 167
191 printk(KERN_INFO "CPU%u: update cpu_power %lu\n", 168 printk(KERN_INFO "CPU%u: update cpu_power %lu\n",
192 cpu, arch_scale_freq_power(NULL, cpu)); 169 cpu, arch_scale_freq_power(NULL, cpu));
@@ -194,7 +171,7 @@ void update_cpu_power(unsigned int cpu, unsigned long hwid)
194 171
195#else 172#else
196static inline void parse_dt_topology(void) {} 173static inline void parse_dt_topology(void) {}
197static inline void update_cpu_power(unsigned int cpuid, unsigned int mpidr) {} 174static inline void update_cpu_power(unsigned int cpuid) {}
198#endif 175#endif
199 176
200 /* 177 /*
@@ -281,7 +258,7 @@ void store_cpu_topology(unsigned int cpuid)
281 258
282 update_siblings_masks(cpuid); 259 update_siblings_masks(cpuid);
283 260
284 update_cpu_power(cpuid, mpidr & MPIDR_HWID_BITMASK); 261 update_cpu_power(cpuid);
285 262
286 printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", 263 printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n",
287 cpuid, cpu_topology[cpuid].thread_id, 264 cpuid, cpu_topology[cpuid].thread_id,
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 7be13f8e69a0..a02f275a198d 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -254,13 +254,12 @@ static void __init imx6q_opp_init(struct device *cpu_dev)
254{ 254{
255 struct device_node *np; 255 struct device_node *np;
256 256
257 np = of_find_node_by_path("/cpus/cpu@0"); 257 np = of_node_get(cpu_dev->of_node);
258 if (!np) { 258 if (!np) {
259 pr_warn("failed to find cpu0 node\n"); 259 pr_warn("failed to find cpu0 node\n");
260 return; 260 return;
261 } 261 }
262 262
263 cpu_dev->of_node = np;
264 if (of_init_opp_table(cpu_dev)) { 263 if (of_init_opp_table(cpu_dev)) {
265 pr_warn("failed to init OPP table\n"); 264 pr_warn("failed to init OPP table\n");
266 goto put_node; 265 goto put_node;
diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c
index ce81d3031405..594b63db4215 100644
--- a/arch/arm/mach-mvebu/platsmp.c
+++ b/arch/arm/mach-mvebu/platsmp.c
@@ -29,45 +29,40 @@
29#include "pmsu.h" 29#include "pmsu.h"
30#include "coherency.h" 30#include "coherency.h"
31 31
32static struct clk *__init get_cpu_clk(int cpu)
33{
34 struct clk *cpu_clk;
35 struct device_node *np = of_get_cpu_node(cpu, NULL);
36
37 if (WARN(!np, "missing cpu node\n"))
38 return NULL;
39 cpu_clk = of_clk_get(np, 0);
40 if (WARN_ON(IS_ERR(cpu_clk)))
41 return NULL;
42 return cpu_clk;
43}
44
32void __init set_secondary_cpus_clock(void) 45void __init set_secondary_cpus_clock(void)
33{ 46{
34 int thiscpu; 47 int thiscpu, cpu;
35 unsigned long rate; 48 unsigned long rate;
36 struct clk *cpu_clk = NULL; 49 struct clk *cpu_clk;
37 struct device_node *np = NULL;
38 50
39 thiscpu = smp_processor_id(); 51 thiscpu = smp_processor_id();
40 for_each_node_by_type(np, "cpu") { 52 cpu_clk = get_cpu_clk(thiscpu);
41 int err; 53 if (!cpu_clk)
42 int cpu;
43
44 err = of_property_read_u32(np, "reg", &cpu);
45 if (WARN_ON(err))
46 return;
47
48 if (cpu == thiscpu) {
49 cpu_clk = of_clk_get(np, 0);
50 break;
51 }
52 }
53 if (WARN_ON(IS_ERR(cpu_clk)))
54 return; 54 return;
55 clk_prepare_enable(cpu_clk); 55 clk_prepare_enable(cpu_clk);
56 rate = clk_get_rate(cpu_clk); 56 rate = clk_get_rate(cpu_clk);
57 57
58 /* set all the other CPU clk to the same rate than the boot CPU */ 58 /* set all the other CPU clk to the same rate than the boot CPU */
59 for_each_node_by_type(np, "cpu") { 59 for_each_possible_cpu(cpu) {
60 int err; 60 if (cpu == thiscpu)
61 int cpu; 61 continue;
62 62 cpu_clk = get_cpu_clk(cpu);
63 err = of_property_read_u32(np, "reg", &cpu); 63 if (!cpu_clk)
64 if (WARN_ON(err))
65 return; 64 return;
66 65 clk_set_rate(cpu_clk, rate);
67 if (cpu != thiscpu) {
68 cpu_clk = of_clk_get(np, 0);
69 clk_set_rate(cpu_clk, rate);
70 }
71 } 66 }
72} 67}
73 68
diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h
index 20c5e8e5121b..9977816c5ad3 100644
--- a/arch/microblaze/include/asm/prom.h
+++ b/arch/microblaze/include/asm/prom.h
@@ -50,9 +50,6 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
50 50
51extern void kdump_move_device_tree(void); 51extern void kdump_move_device_tree(void);
52 52
53/* CPU OF node matching */
54struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
55
56#endif /* __ASSEMBLY__ */ 53#endif /* __ASSEMBLY__ */
57#endif /* __KERNEL__ */ 54#endif /* __KERNEL__ */
58 55
diff --git a/arch/openrisc/include/asm/prom.h b/arch/openrisc/include/asm/prom.h
index bbb34e5343a2..eb59bfe23e85 100644
--- a/arch/openrisc/include/asm/prom.h
+++ b/arch/openrisc/include/asm/prom.h
@@ -44,9 +44,6 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
44 44
45extern void kdump_move_device_tree(void); 45extern void kdump_move_device_tree(void);
46 46
47/* CPU OF node matching */
48struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
49
50/* Get the MAC address */ 47/* Get the MAC address */
51extern const void *of_get_mac_address(struct device_node *np); 48extern const void *of_get_mac_address(struct device_node *np);
52 49
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index bc2da154f68b..ac204e022922 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -43,9 +43,6 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
43 43
44extern void kdump_move_device_tree(void); 44extern void kdump_move_device_tree(void);
45 45
46/* CPU OF node matching */
47struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
48
49/* cache lookup */ 46/* cache lookup */
50struct device_node *of_find_next_cache_node(struct device_node *np); 47struct device_node *of_find_next_cache_node(struct device_node *np);
51 48
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index eb23ac92abb9..1c14cd4a5e05 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -865,49 +865,10 @@ static int __init prom_reconfig_setup(void)
865__initcall(prom_reconfig_setup); 865__initcall(prom_reconfig_setup);
866#endif 866#endif
867 867
868/* Find the device node for a given logical cpu number, also returns the cpu 868bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
869 * local thread number (index in ibm,interrupt-server#s) if relevant and
870 * asked for (non NULL)
871 */
872struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
873{ 869{
874 int hardid; 870 return (int)phys_id == get_hard_smp_processor_id(cpu);
875 struct device_node *np;
876
877 hardid = get_hard_smp_processor_id(cpu);
878
879 for_each_node_by_type(np, "cpu") {
880 const u32 *intserv;
881 unsigned int plen, t;
882
883 /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist
884 * fallback to "reg" property and assume no threads
885 */
886 intserv = of_get_property(np, "ibm,ppc-interrupt-server#s",
887 &plen);
888 if (intserv == NULL) {
889 const u32 *reg = of_get_property(np, "reg", NULL);
890 if (reg == NULL)
891 continue;
892 if (*reg == hardid) {
893 if (thread)
894 *thread = 0;
895 return np;
896 }
897 } else {
898 plen /= sizeof(u32);
899 for (t = 0; t < plen; t++) {
900 if (hardid == intserv[t]) {
901 if (thread)
902 *thread = t;
903 return np;
904 }
905 }
906 }
907 }
908 return NULL;
909} 871}
910EXPORT_SYMBOL(of_get_cpu_node);
911 872
912#if defined(CONFIG_DEBUG_FS) && defined(DEBUG) 873#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
913static struct debugfs_blob_wrapper flat_dt_blob; 874static struct debugfs_blob_wrapper flat_dt_blob;
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 4c358bc44c72..4cf071764be3 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -14,6 +14,7 @@
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/percpu.h> 15#include <linux/percpu.h>
16#include <linux/acpi.h> 16#include <linux/acpi.h>
17#include <linux/of.h>
17 18
18#include "base.h" 19#include "base.h"
19 20
@@ -289,6 +290,7 @@ int register_cpu(struct cpu *cpu, int num)
289 cpu->dev.release = cpu_device_release; 290 cpu->dev.release = cpu_device_release;
290 cpu->dev.offline_disabled = !cpu->hotpluggable; 291 cpu->dev.offline_disabled = !cpu->hotpluggable;
291 cpu->dev.offline = !cpu_online(num); 292 cpu->dev.offline = !cpu_online(num);
293 cpu->dev.of_node = of_get_cpu_node(num, NULL);
292#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE 294#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
293 cpu->dev.bus->uevent = arch_cpu_uevent; 295 cpu->dev.bus->uevent = arch_cpu_uevent;
294#endif 296#endif
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index 733288967d4d..200926699778 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -122,17 +122,8 @@ EXPORT_SYMBOL_GPL(cci_ace_get_port);
122 122
123static void __init cci_ace_init_ports(void) 123static void __init cci_ace_init_ports(void)
124{ 124{
125 int port, ac, cpu; 125 int port, cpu;
126 u64 hwid; 126 struct device_node *cpun;
127 const u32 *cell;
128 struct device_node *cpun, *cpus;
129
130 cpus = of_find_node_by_path("/cpus");
131 if (WARN(!cpus, "Missing cpus node, bailing out\n"))
132 return;
133
134 if (WARN_ON(of_property_read_u32(cpus, "#address-cells", &ac)))
135 ac = of_n_addr_cells(cpus);
136 127
137 /* 128 /*
138 * Port index look-up speeds up the function disabling ports by CPU, 129 * Port index look-up speeds up the function disabling ports by CPU,
@@ -141,18 +132,13 @@ static void __init cci_ace_init_ports(void)
141 * The stashed index array is initialized for all possible CPUs 132 * The stashed index array is initialized for all possible CPUs
142 * at probe time. 133 * at probe time.
143 */ 134 */
144 for_each_child_of_node(cpus, cpun) { 135 for_each_possible_cpu(cpu) {
145 if (of_node_cmp(cpun->type, "cpu")) 136 /* too early to use cpu->of_node */
146 continue; 137 cpun = of_get_cpu_node(cpu, NULL);
147 cell = of_get_property(cpun, "reg", NULL);
148 if (WARN(!cell, "%s: missing reg property\n", cpun->full_name))
149 continue;
150
151 hwid = of_read_number(cell, ac);
152 cpu = get_logical_index(hwid & MPIDR_HWID_BITMASK);
153 138
154 if (cpu < 0 || !cpu_possible(cpu)) 139 if (WARN(!cpun, "Missing cpu device node\n"))
155 continue; 140 continue;
141
156 port = __cci_ace_get_port(cpun, ACE_PORT); 142 port = __cci_ace_get_port(cpun, ACE_PORT);
157 if (port < 0) 143 if (port < 0)
158 continue; 144 continue;
diff --git a/drivers/cpufreq/arm_big_little_dt.c b/drivers/cpufreq/arm_big_little_dt.c
index fd9e3ea6a480..480c0bd0468d 100644
--- a/drivers/cpufreq/arm_big_little_dt.c
+++ b/drivers/cpufreq/arm_big_little_dt.c
@@ -19,12 +19,11 @@
19 19
20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21 21
22#include <linux/cpu.h>
23#include <linux/cpufreq.h> 22#include <linux/cpufreq.h>
24#include <linux/device.h> 23#include <linux/device.h>
25#include <linux/export.h> 24#include <linux/export.h>
26#include <linux/module.h> 25#include <linux/module.h>
27#include <linux/of.h> 26#include <linux/of_device.h>
28#include <linux/opp.h> 27#include <linux/opp.h>
29#include <linux/platform_device.h> 28#include <linux/platform_device.h>
30#include <linux/slab.h> 29#include <linux/slab.h>
@@ -34,27 +33,13 @@
34/* get cpu node with valid operating-points */ 33/* get cpu node with valid operating-points */
35static struct device_node *get_cpu_node_with_valid_op(int cpu) 34static struct device_node *get_cpu_node_with_valid_op(int cpu)
36{ 35{
37 struct device_node *np = NULL, *parent; 36 struct device_node *np = of_cpu_device_node_get(cpu);
38 int count = 0;
39 37
40 parent = of_find_node_by_path("/cpus"); 38 if (!of_get_property(np, "operating-points", NULL)) {
41 if (!parent) { 39 of_node_put(np);
42 pr_err("failed to find OF /cpus\n"); 40 np = NULL;
43 return NULL;
44 } 41 }
45 42
46 for_each_child_of_node(parent, np) {
47 if (count++ != cpu)
48 continue;
49 if (!of_get_property(np, "operating-points", NULL)) {
50 of_node_put(np);
51 np = NULL;
52 }
53
54 break;
55 }
56
57 of_node_put(parent);
58 return np; 43 return np;
59} 44}
60 45
@@ -63,11 +48,12 @@ static int dt_init_opp_table(struct device *cpu_dev)
63 struct device_node *np; 48 struct device_node *np;
64 int ret; 49 int ret;
65 50
66 np = get_cpu_node_with_valid_op(cpu_dev->id); 51 np = of_node_get(cpu_dev->of_node);
67 if (!np) 52 if (!np) {
68 return -ENODATA; 53 pr_err("failed to find cpu%d node\n", cpu_dev->id);
54 return -ENOENT;
55 }
69 56
70 cpu_dev->of_node = np;
71 ret = of_init_opp_table(cpu_dev); 57 ret = of_init_opp_table(cpu_dev);
72 of_node_put(np); 58 of_node_put(np);
73 59
@@ -79,9 +65,11 @@ static int dt_get_transition_latency(struct device *cpu_dev)
79 struct device_node *np; 65 struct device_node *np;
80 u32 transition_latency = CPUFREQ_ETERNAL; 66 u32 transition_latency = CPUFREQ_ETERNAL;
81 67
82 np = get_cpu_node_with_valid_op(cpu_dev->id); 68 np = of_node_get(cpu_dev->of_node);
83 if (!np) 69 if (!np) {
70 pr_info("Failed to find cpu node. Use CPUFREQ_ETERNAL transition latency\n");
84 return CPUFREQ_ETERNAL; 71 return CPUFREQ_ETERNAL;
72 }
85 73
86 of_property_read_u32(np, "clock-latency", &transition_latency); 74 of_property_read_u32(np, "clock-latency", &transition_latency);
87 of_node_put(np); 75 of_node_put(np);
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index 09cd3a76fb2e..bad620e996e5 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -174,29 +174,17 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
174 174
175static int cpu0_cpufreq_probe(struct platform_device *pdev) 175static int cpu0_cpufreq_probe(struct platform_device *pdev)
176{ 176{
177 struct device_node *np, *parent; 177 struct device_node *np;
178 int ret; 178 int ret;
179 179
180 parent = of_find_node_by_path("/cpus"); 180 cpu_dev = &pdev->dev;
181 if (!parent) {
182 pr_err("failed to find OF /cpus\n");
183 return -ENOENT;
184 }
185
186 for_each_child_of_node(parent, np) {
187 if (of_get_property(np, "operating-points", NULL))
188 break;
189 }
190 181
182 np = of_node_get(cpu_dev->of_node);
191 if (!np) { 183 if (!np) {
192 pr_err("failed to find cpu0 node\n"); 184 pr_err("failed to find cpu0 node\n");
193 ret = -ENOENT; 185 return -ENOENT;
194 goto out_put_parent;
195 } 186 }
196 187
197 cpu_dev = &pdev->dev;
198 cpu_dev->of_node = np;
199
200 cpu_reg = devm_regulator_get(cpu_dev, "cpu0"); 188 cpu_reg = devm_regulator_get(cpu_dev, "cpu0");
201 if (IS_ERR(cpu_reg)) { 189 if (IS_ERR(cpu_reg)) {
202 /* 190 /*
@@ -268,15 +256,12 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
268 } 256 }
269 257
270 of_node_put(np); 258 of_node_put(np);
271 of_node_put(parent);
272 return 0; 259 return 0;
273 260
274out_free_table: 261out_free_table:
275 opp_free_cpufreq_table(cpu_dev, &freq_table); 262 opp_free_cpufreq_table(cpu_dev, &freq_table);
276out_put_node: 263out_put_node:
277 of_node_put(np); 264 of_node_put(np);
278out_put_parent:
279 of_node_put(parent);
280 return ret; 265 return ret;
281} 266}
282 267
diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c
index b61b5a3fad64..794123fcf3e3 100644
--- a/drivers/cpufreq/highbank-cpufreq.c
+++ b/drivers/cpufreq/highbank-cpufreq.c
@@ -69,23 +69,17 @@ static int hb_cpufreq_driver_init(void)
69 if (!of_machine_is_compatible("calxeda,highbank")) 69 if (!of_machine_is_compatible("calxeda,highbank"))
70 return -ENODEV; 70 return -ENODEV;
71 71
72 for_each_child_of_node(of_find_node_by_path("/cpus"), np)
73 if (of_get_property(np, "operating-points", NULL))
74 break;
75
76 if (!np) {
77 pr_err("failed to find highbank cpufreq node\n");
78 return -ENOENT;
79 }
80
81 cpu_dev = get_cpu_device(0); 72 cpu_dev = get_cpu_device(0);
82 if (!cpu_dev) { 73 if (!cpu_dev) {
83 pr_err("failed to get highbank cpufreq device\n"); 74 pr_err("failed to get highbank cpufreq device\n");
84 ret = -ENODEV; 75 return -ENODEV;
85 goto out_put_node;
86 } 76 }
87 77
88 cpu_dev->of_node = np; 78 np = of_node_get(cpu_dev->of_node);
79 if (!np) {
80 pr_err("failed to find highbank cpufreq node\n");
81 return -ENOENT;
82 }
89 83
90 cpu_clk = clk_get(cpu_dev, NULL); 84 cpu_clk = clk_get(cpu_dev, NULL);
91 if (IS_ERR(cpu_clk)) { 85 if (IS_ERR(cpu_clk)) {
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index e37cdaedbb5b..b16632bb5a56 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -221,14 +221,12 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
221 221
222 cpu_dev = &pdev->dev; 222 cpu_dev = &pdev->dev;
223 223
224 np = of_find_node_by_path("/cpus/cpu@0"); 224 np = of_node_get(cpu_dev->of_node);
225 if (!np) { 225 if (!np) {
226 dev_err(cpu_dev, "failed to find cpu0 node\n"); 226 dev_err(cpu_dev, "failed to find cpu0 node\n");
227 return -ENOENT; 227 return -ENOENT;
228 } 228 }
229 229
230 cpu_dev->of_node = np;
231
232 arm_clk = devm_clk_get(cpu_dev, "arm"); 230 arm_clk = devm_clk_get(cpu_dev, "arm");
233 pll1_sys_clk = devm_clk_get(cpu_dev, "pll1_sys"); 231 pll1_sys_clk = devm_clk_get(cpu_dev, "pll1_sys");
234 pll1_sw_clk = devm_clk_get(cpu_dev, "pll1_sw"); 232 pll1_sw_clk = devm_clk_get(cpu_dev, "pll1_sw");
diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
index 45e4d7fc261d..ba10658a9394 100644
--- a/drivers/cpufreq/kirkwood-cpufreq.c
+++ b/drivers/cpufreq/kirkwood-cpufreq.c
@@ -14,7 +14,7 @@
14#include <linux/clk.h> 14#include <linux/clk.h>
15#include <linux/clk-provider.h> 15#include <linux/clk-provider.h>
16#include <linux/cpufreq.h> 16#include <linux/cpufreq.h>
17#include <linux/of.h> 17#include <linux/of_device.h>
18#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/io.h> 19#include <linux/io.h>
20#include <asm/proc-fns.h> 20#include <asm/proc-fns.h>
@@ -174,9 +174,11 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
174 if (IS_ERR(priv.base)) 174 if (IS_ERR(priv.base))
175 return PTR_ERR(priv.base); 175 return PTR_ERR(priv.base);
176 176
177 np = of_find_node_by_path("/cpus/cpu@0"); 177 np = of_cpu_device_node_get(0);
178 if (!np) 178 if (!np) {
179 dev_err(&pdev->dev, "failed to get cpu device node\n");
179 return -ENODEV; 180 return -ENODEV;
181 }
180 182
181 priv.cpu_clk = of_clk_get_by_name(np, "cpu_clk"); 183 priv.cpu_clk = of_clk_get_by_name(np, "cpu_clk");
182 if (IS_ERR(priv.cpu_clk)) { 184 if (IS_ERR(priv.cpu_clk)) {
diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c
index 41c601f4631e..6168d77b296d 100644
--- a/drivers/cpufreq/maple-cpufreq.c
+++ b/drivers/cpufreq/maple-cpufreq.c
@@ -24,7 +24,7 @@
24#include <linux/completion.h> 24#include <linux/completion.h>
25#include <linux/mutex.h> 25#include <linux/mutex.h>
26#include <linux/time.h> 26#include <linux/time.h>
27#include <linux/of.h> 27#include <linux/of_device.h>
28 28
29#define DBG(fmt...) pr_debug(fmt) 29#define DBG(fmt...) pr_debug(fmt)
30 30
@@ -200,7 +200,6 @@ static struct cpufreq_driver maple_cpufreq_driver = {
200 200
201static int __init maple_cpufreq_init(void) 201static int __init maple_cpufreq_init(void)
202{ 202{
203 struct device_node *cpus;
204 struct device_node *cpunode; 203 struct device_node *cpunode;
205 unsigned int psize; 204 unsigned int psize;
206 unsigned long max_freq; 205 unsigned long max_freq;
@@ -216,24 +215,11 @@ static int __init maple_cpufreq_init(void)
216 !of_machine_is_compatible("Momentum,Apache")) 215 !of_machine_is_compatible("Momentum,Apache"))
217 return 0; 216 return 0;
218 217
219 cpus = of_find_node_by_path("/cpus");
220 if (cpus == NULL) {
221 DBG("No /cpus node !\n");
222 return -ENODEV;
223 }
224
225 /* Get first CPU node */ 218 /* Get first CPU node */
226 for (cpunode = NULL; 219 cpunode = of_cpu_device_node_get(0);
227 (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
228 const u32 *reg = of_get_property(cpunode, "reg", NULL);
229 if (reg == NULL || (*reg) != 0)
230 continue;
231 if (!strcmp(cpunode->type, "cpu"))
232 break;
233 }
234 if (cpunode == NULL) { 220 if (cpunode == NULL) {
235 printk(KERN_ERR "cpufreq: Can't find any CPU 0 node\n"); 221 printk(KERN_ERR "cpufreq: Can't find any CPU 0 node\n");
236 goto bail_cpus; 222 goto bail_noprops;
237 } 223 }
238 224
239 /* Check 970FX for now */ 225 /* Check 970FX for now */
@@ -289,14 +275,11 @@ static int __init maple_cpufreq_init(void)
289 rc = cpufreq_register_driver(&maple_cpufreq_driver); 275 rc = cpufreq_register_driver(&maple_cpufreq_driver);
290 276
291 of_node_put(cpunode); 277 of_node_put(cpunode);
292 of_node_put(cpus);
293 278
294 return rc; 279 return rc;
295 280
296bail_noprops: 281bail_noprops:
297 of_node_put(cpunode); 282 of_node_put(cpunode);
298bail_cpus:
299 of_node_put(cpus);
300 283
301 return rc; 284 return rc;
302} 285}
diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c
index 38cdc63c38da..a096cd3fa23d 100644
--- a/drivers/cpufreq/pmac32-cpufreq.c
+++ b/drivers/cpufreq/pmac32-cpufreq.c
@@ -25,6 +25,7 @@
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/device.h> 26#include <linux/device.h>
27#include <linux/hardirq.h> 27#include <linux/hardirq.h>
28#include <linux/of_device.h>
28#include <asm/prom.h> 29#include <asm/prom.h>
29#include <asm/machdep.h> 30#include <asm/machdep.h>
30#include <asm/irq.h> 31#include <asm/irq.h>
@@ -648,8 +649,8 @@ static int __init pmac_cpufreq_setup(void)
648 if (strstr(cmd_line, "nocpufreq")) 649 if (strstr(cmd_line, "nocpufreq"))
649 return 0; 650 return 0;
650 651
651 /* Assume only one CPU */ 652 /* Get first CPU node */
652 cpunode = of_find_node_by_type(NULL, "cpu"); 653 cpunode = of_cpu_device_node_get(0);
653 if (!cpunode) 654 if (!cpunode)
654 goto out; 655 goto out;
655 656
diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c
index b6850d97f0d5..3a51ad7e47c8 100644
--- a/drivers/cpufreq/pmac64-cpufreq.c
+++ b/drivers/cpufreq/pmac64-cpufreq.c
@@ -22,6 +22,7 @@
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/completion.h> 23#include <linux/completion.h>
24#include <linux/mutex.h> 24#include <linux/mutex.h>
25#include <linux/of_device.h>
25#include <asm/prom.h> 26#include <asm/prom.h>
26#include <asm/machdep.h> 27#include <asm/machdep.h>
27#include <asm/irq.h> 28#include <asm/irq.h>
@@ -382,9 +383,8 @@ static struct cpufreq_driver g5_cpufreq_driver = {
382 383
383#ifdef CONFIG_PMAC_SMU 384#ifdef CONFIG_PMAC_SMU
384 385
385static int __init g5_neo2_cpufreq_init(struct device_node *cpus) 386static int __init g5_neo2_cpufreq_init(struct device_node *cpunode)
386{ 387{
387 struct device_node *cpunode;
388 unsigned int psize, ssize; 388 unsigned int psize, ssize;
389 unsigned long max_freq; 389 unsigned long max_freq;
390 char *freq_method, *volt_method; 390 char *freq_method, *volt_method;
@@ -404,20 +404,6 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
404 else 404 else
405 return -ENODEV; 405 return -ENODEV;
406 406
407 /* Get first CPU node */
408 for (cpunode = NULL;
409 (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
410 const u32 *reg = of_get_property(cpunode, "reg", NULL);
411 if (reg == NULL || (*reg) != 0)
412 continue;
413 if (!strcmp(cpunode->type, "cpu"))
414 break;
415 }
416 if (cpunode == NULL) {
417 printk(KERN_ERR "cpufreq: Can't find any CPU 0 node\n");
418 return -ENODEV;
419 }
420
421 /* Check 970FX for now */ 407 /* Check 970FX for now */
422 valp = of_get_property(cpunode, "cpu-version", NULL); 408 valp = of_get_property(cpunode, "cpu-version", NULL);
423 if (!valp) { 409 if (!valp) {
@@ -535,9 +521,9 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
535#endif /* CONFIG_PMAC_SMU */ 521#endif /* CONFIG_PMAC_SMU */
536 522
537 523
538static int __init g5_pm72_cpufreq_init(struct device_node *cpus) 524static int __init g5_pm72_cpufreq_init(struct device_node *cpunode)
539{ 525{
540 struct device_node *cpuid = NULL, *hwclock = NULL, *cpunode = NULL; 526 struct device_node *cpuid = NULL, *hwclock = NULL;
541 const u8 *eeprom = NULL; 527 const u8 *eeprom = NULL;
542 const u32 *valp; 528 const u32 *valp;
543 u64 max_freq, min_freq, ih, il; 529 u64 max_freq, min_freq, ih, il;
@@ -546,17 +532,6 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
546 DBG("cpufreq: Initializing for PowerMac7,2, PowerMac7,3 and" 532 DBG("cpufreq: Initializing for PowerMac7,2, PowerMac7,3 and"
547 " RackMac3,1...\n"); 533 " RackMac3,1...\n");
548 534
549 /* Get first CPU node */
550 for (cpunode = NULL;
551 (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
552 if (!strcmp(cpunode->type, "cpu"))
553 break;
554 }
555 if (cpunode == NULL) {
556 printk(KERN_ERR "cpufreq: Can't find any CPU node\n");
557 return -ENODEV;
558 }
559
560 /* Lookup the cpuid eeprom node */ 535 /* Lookup the cpuid eeprom node */
561 cpuid = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/cpuid@a0"); 536 cpuid = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/cpuid@a0");
562 if (cpuid != NULL) 537 if (cpuid != NULL)
@@ -716,25 +691,25 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
716 691
717static int __init g5_cpufreq_init(void) 692static int __init g5_cpufreq_init(void)
718{ 693{
719 struct device_node *cpus; 694 struct device_node *cpunode;
720 int rc = 0; 695 int rc = 0;
721 696
722 cpus = of_find_node_by_path("/cpus"); 697 /* Get first CPU node */
723 if (cpus == NULL) { 698 cpunode = of_cpu_device_node_get(0);
724 DBG("No /cpus node !\n"); 699 if (cpunode == NULL) {
700 pr_err("cpufreq: Can't find any CPU node\n");
725 return -ENODEV; 701 return -ENODEV;
726 } 702 }
727 703
728 if (of_machine_is_compatible("PowerMac7,2") || 704 if (of_machine_is_compatible("PowerMac7,2") ||
729 of_machine_is_compatible("PowerMac7,3") || 705 of_machine_is_compatible("PowerMac7,3") ||
730 of_machine_is_compatible("RackMac3,1")) 706 of_machine_is_compatible("RackMac3,1"))
731 rc = g5_pm72_cpufreq_init(cpus); 707 rc = g5_pm72_cpufreq_init(cpunode);
732#ifdef CONFIG_PMAC_SMU 708#ifdef CONFIG_PMAC_SMU
733 else 709 else
734 rc = g5_neo2_cpufreq_init(cpus); 710 rc = g5_neo2_cpufreq_init(cpunode);
735#endif /* CONFIG_PMAC_SMU */ 711#endif /* CONFIG_PMAC_SMU */
736 712
737 of_node_put(cpus);
738 return rc; 713 return rc;
739} 714}
740 715
diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c
index c3efa7f2a908..19e364fa5955 100644
--- a/drivers/cpufreq/spear-cpufreq.c
+++ b/drivers/cpufreq/spear-cpufreq.c
@@ -18,7 +18,7 @@
18#include <linux/err.h> 18#include <linux/err.h>
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/of.h> 21#include <linux/of_device.h>
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/types.h> 23#include <linux/types.h>
24 24
@@ -223,7 +223,7 @@ static int spear_cpufreq_driver_init(void)
223 const __be32 *val; 223 const __be32 *val;
224 int cnt, i, ret; 224 int cnt, i, ret;
225 225
226 np = of_find_node_by_path("/cpus/cpu@0"); 226 np = of_cpu_device_node_get(0);
227 if (!np) { 227 if (!np) {
228 pr_err("No cpu node found"); 228 pr_err("No cpu node found");
229 return -ENODEV; 229 return -ENODEV;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 5c5427918eb2..605afa9fbe5e 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -18,6 +18,7 @@
18 * 2 of the License, or (at your option) any later version. 18 * 2 of the License, or (at your option) any later version.
19 */ 19 */
20#include <linux/ctype.h> 20#include <linux/ctype.h>
21#include <linux/cpu.h>
21#include <linux/module.h> 22#include <linux/module.h>
22#include <linux/of.h> 23#include <linux/of.h>
23#include <linux/spinlock.h> 24#include <linux/spinlock.h>
@@ -230,6 +231,100 @@ const void *of_get_property(const struct device_node *np, const char *name,
230} 231}
231EXPORT_SYMBOL(of_get_property); 232EXPORT_SYMBOL(of_get_property);
232 233
234/*
235 * arch_match_cpu_phys_id - Match the given logical CPU and physical id
236 *
237 * @cpu: logical cpu index of a core/thread
238 * @phys_id: physical identifier of a core/thread
239 *
240 * CPU logical to physical index mapping is architecture specific.
241 * However this __weak function provides a default match of physical
242 * id to logical cpu index. phys_id provided here is usually values read
243 * from the device tree which must match the hardware internal registers.
244 *
245 * Returns true if the physical identifier and the logical cpu index
246 * correspond to the same core/thread, false otherwise.
247 */
248bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id)
249{
250 return (u32)phys_id == cpu;
251}
252
253/**
254 * Checks if the given "prop_name" property holds the physical id of the
255 * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not
256 * NULL, local thread number within the core is returned in it.
257 */
258static bool __of_find_n_match_cpu_property(struct device_node *cpun,
259 const char *prop_name, int cpu, unsigned int *thread)
260{
261 const __be32 *cell;
262 int ac, prop_len, tid;
263 u64 hwid;
264
265 ac = of_n_addr_cells(cpun);
266 cell = of_get_property(cpun, prop_name, &prop_len);
267 if (!cell)
268 return false;
269 prop_len /= sizeof(*cell);
270 for (tid = 0; tid < prop_len; tid++) {
271 hwid = of_read_number(cell, ac);
272 if (arch_match_cpu_phys_id(cpu, hwid)) {
273 if (thread)
274 *thread = tid;
275 return true;
276 }
277 cell += ac;
278 }
279 return false;
280}
281
282/**
283 * of_get_cpu_node - Get device node associated with the given logical CPU
284 *
285 * @cpu: CPU number(logical index) for which device node is required
286 * @thread: if not NULL, local thread number within the physical core is
287 * returned
288 *
289 * The main purpose of this function is to retrieve the device node for the
290 * given logical CPU index. It should be used to initialize the of_node in
291 * cpu device. Once of_node in cpu device is populated, all the further
292 * references can use that instead.
293 *
294 * CPU logical to physical index mapping is architecture specific and is built
295 * before booting secondary cores. This function uses arch_match_cpu_phys_id
296 * which can be overridden by architecture specific implementation.
297 *
298 * Returns a node pointer for the logical cpu if found, else NULL.
299 */
300struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
301{
302 struct device_node *cpun, *cpus;
303
304 cpus = of_find_node_by_path("/cpus");
305 if (!cpus) {
306 pr_warn("Missing cpus node, bailing out\n");
307 return NULL;
308 }
309
310 for_each_child_of_node(cpus, cpun) {
311 if (of_node_cmp(cpun->type, "cpu"))
312 continue;
313 /* Check for non-standard "ibm,ppc-interrupt-server#s" property
314 * for thread ids on PowerPC. If it doesn't exist fallback to
315 * standard "reg" property.
316 */
317 if (IS_ENABLED(CONFIG_PPC) &&
318 __of_find_n_match_cpu_property(cpun,
319 "ibm,ppc-interrupt-server#s", cpu, thread))
320 return cpun;
321 if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread))
322 return cpun;
323 }
324 return NULL;
325}
326EXPORT_SYMBOL(of_get_cpu_node);
327
233/** Checks if the given "compat" string matches one of the strings in 328/** Checks if the given "compat" string matches one of the strings in
234 * the device's "compatible" property 329 * the device's "compatible" property
235 */ 330 */
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index ab0eade73039..3dfed2b9ae2e 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -28,6 +28,7 @@ struct cpu {
28extern int register_cpu(struct cpu *cpu, int num); 28extern int register_cpu(struct cpu *cpu, int num);
29extern struct device *get_cpu_device(unsigned cpu); 29extern struct device *get_cpu_device(unsigned cpu);
30extern bool cpu_is_hotpluggable(unsigned cpu); 30extern bool cpu_is_hotpluggable(unsigned cpu);
31extern bool arch_match_cpu_phys_id(int cpu, u64 phys_id);
31 32
32extern int cpu_add_dev_attr(struct device_attribute *attr); 33extern int cpu_add_dev_attr(struct device_attribute *attr);
33extern void cpu_remove_dev_attr(struct device_attribute *attr); 34extern void cpu_remove_dev_attr(struct device_attribute *attr);
diff --git a/include/linux/of.h b/include/linux/of.h
index 1fd08ca23106..c0bb2f188048 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -266,6 +266,7 @@ extern int of_device_is_available(const struct device_node *device);
266extern const void *of_get_property(const struct device_node *node, 266extern const void *of_get_property(const struct device_node *node,
267 const char *name, 267 const char *name,
268 int *lenp); 268 int *lenp);
269extern struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
269#define for_each_property_of_node(dn, pp) \ 270#define for_each_property_of_node(dn, pp) \
270 for (pp = dn->properties; pp != NULL; pp = pp->next) 271 for (pp = dn->properties; pp != NULL; pp = pp->next)
271 272
@@ -459,6 +460,12 @@ static inline const void *of_get_property(const struct device_node *node,
459 return NULL; 460 return NULL;
460} 461}
461 462
463static inline struct device_node *of_get_cpu_node(int cpu,
464 unsigned int *thread)
465{
466 return NULL;
467}
468
462static inline int of_property_read_u64(const struct device_node *np, 469static inline int of_property_read_u64(const struct device_node *np,
463 const char *propname, u64 *out_value) 470 const char *propname, u64 *out_value)
464{ 471{
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 9d27475feec1..82ce324fdce7 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -1,6 +1,7 @@
1#ifndef _LINUX_OF_DEVICE_H 1#ifndef _LINUX_OF_DEVICE_H
2#define _LINUX_OF_DEVICE_H 2#define _LINUX_OF_DEVICE_H
3 3
4#include <linux/cpu.h>
4#include <linux/platform_device.h> 5#include <linux/platform_device.h>
5#include <linux/of_platform.h> /* temporary until merge */ 6#include <linux/of_platform.h> /* temporary until merge */
6 7
@@ -43,6 +44,15 @@ static inline void of_device_node_put(struct device *dev)
43 of_node_put(dev->of_node); 44 of_node_put(dev->of_node);
44} 45}
45 46
47static inline struct device_node *of_cpu_device_node_get(int cpu)
48{
49 struct device *cpu_dev;
50 cpu_dev = get_cpu_device(cpu);
51 if (!cpu_dev)
52 return NULL;
53 return of_node_get(cpu_dev->of_node);
54}
55
46#else /* CONFIG_OF */ 56#else /* CONFIG_OF */
47 57
48static inline int of_driver_match_device(struct device *dev, 58static inline int of_driver_match_device(struct device *dev,
@@ -67,6 +77,11 @@ static inline const struct of_device_id *of_match_device(
67{ 77{
68 return NULL; 78 return NULL;
69} 79}
80
81static inline struct device_node *of_cpu_device_node_get(int cpu)
82{
83 return NULL;
84}
70#endif /* CONFIG_OF */ 85#endif /* CONFIG_OF */
71 86
72#endif /* _LINUX_OF_DEVICE_H */ 87#endif /* _LINUX_OF_DEVICE_H */