1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2015 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6 
7 #include <common.h>
8 #include <cpu.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <log.h>
12 #include <dm/lists.h>
13 #include <dm/root.h>
14 #include <linux/err.h>
15 
cpu_probe_all(void)16 int cpu_probe_all(void)
17 {
18 	struct udevice *cpu;
19 	int ret;
20 
21 	ret = uclass_first_device(UCLASS_CPU, &cpu);
22 	if (ret) {
23 		debug("%s: No CPU found (err = %d)\n", __func__, ret);
24 		return ret;
25 	}
26 
27 	while (cpu) {
28 		ret = uclass_next_device(&cpu);
29 		if (ret) {
30 			debug("%s: Error while probing CPU (err = %d)\n",
31 			      __func__, ret);
32 			return ret;
33 		}
34 	}
35 
36 	return 0;
37 }
38 
cpu_is_current(struct udevice * cpu)39 int cpu_is_current(struct udevice *cpu)
40 {
41 	struct cpu_ops *ops = cpu_get_ops(cpu);
42 
43 	if (ops->is_current) {
44 		if (ops->is_current(cpu))
45 			return 1;
46 	}
47 
48 	return -ENOSYS;
49 }
50 
cpu_get_current_dev(void)51 struct udevice *cpu_get_current_dev(void)
52 {
53 	struct udevice *cpu;
54 	int ret;
55 
56 	uclass_foreach_dev_probe(UCLASS_CPU, cpu) {
57 		if (cpu_is_current(cpu) > 0)
58 			return cpu;
59 	}
60 
61 	/* If can't find current cpu device, use the first dev instead */
62 	ret = uclass_first_device_err(UCLASS_CPU, &cpu);
63 	if (ret) {
64 		debug("%s: Could not get CPU device (err = %d)\n",
65 		      __func__, ret);
66 		return NULL;
67 	}
68 
69 	return cpu;
70 }
71 
cpu_get_desc(const struct udevice * dev,char * buf,int size)72 int cpu_get_desc(const struct udevice *dev, char *buf, int size)
73 {
74 	struct cpu_ops *ops = cpu_get_ops(dev);
75 
76 	if (!ops->get_desc)
77 		return -ENOSYS;
78 
79 	return ops->get_desc(dev, buf, size);
80 }
81 
cpu_get_info(const struct udevice * dev,struct cpu_info * info)82 int cpu_get_info(const struct udevice *dev, struct cpu_info *info)
83 {
84 	struct cpu_ops *ops = cpu_get_ops(dev);
85 
86 	if (!ops->get_info)
87 		return -ENOSYS;
88 
89 	/* Init cpu_info to 0 */
90 	memset(info, 0, sizeof(struct cpu_info));
91 
92 	return ops->get_info(dev, info);
93 }
94 
cpu_get_count(const struct udevice * dev)95 int cpu_get_count(const struct udevice *dev)
96 {
97 	struct cpu_ops *ops = cpu_get_ops(dev);
98 
99 	if (!ops->get_count)
100 		return -ENOSYS;
101 
102 	return ops->get_count(dev);
103 }
104 
cpu_get_vendor(const struct udevice * dev,char * buf,int size)105 int cpu_get_vendor(const struct udevice *dev, char *buf, int size)
106 {
107 	struct cpu_ops *ops = cpu_get_ops(dev);
108 
109 	if (!ops->get_vendor)
110 		return -ENOSYS;
111 
112 	return ops->get_vendor(dev, buf, size);
113 }
114 
115 U_BOOT_DRIVER(cpu_bus) = {
116 	.name	= "cpu_bus",
117 	.id	= UCLASS_SIMPLE_BUS,
118 	.per_child_plat_auto	= sizeof(struct cpu_plat),
119 };
120 
uclass_cpu_init(struct uclass * uc)121 static int uclass_cpu_init(struct uclass *uc)
122 {
123 	struct udevice *dev;
124 	ofnode node;
125 	int ret;
126 
127 	node = ofnode_path("/cpus");
128 	if (!ofnode_valid(node))
129 		return 0;
130 
131 	ret = device_bind_driver_to_node(dm_root(), "cpu_bus", "cpus", node,
132 					 &dev);
133 
134 	return ret;
135 }
136 
137 UCLASS_DRIVER(cpu) = {
138 	.id		= UCLASS_CPU,
139 	.name		= "cpu",
140 	.flags		= DM_UC_FLAG_SEQ_ALIAS,
141 	.init		= uclass_cpu_init,
142 };
143