xref: /linux/drivers/peci/core.c (revision cdd30ebb1b9f36159d66f088b61aee264e649d7a)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2018-2021 Intel Corporation
3 
4 #include <linux/bug.h>
5 #include <linux/device.h>
6 #include <linux/export.h>
7 #include <linux/idr.h>
8 #include <linux/module.h>
9 #include <linux/of.h>
10 #include <linux/peci.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/property.h>
13 #include <linux/slab.h>
14 
15 #include "internal.h"
16 
17 static DEFINE_IDA(peci_controller_ida);
18 
peci_controller_dev_release(struct device * dev)19 static void peci_controller_dev_release(struct device *dev)
20 {
21 	struct peci_controller *controller = to_peci_controller(dev);
22 
23 	mutex_destroy(&controller->bus_lock);
24 	ida_free(&peci_controller_ida, controller->id);
25 	kfree(controller);
26 }
27 
28 const struct device_type peci_controller_type = {
29 	.release	= peci_controller_dev_release,
30 };
31 
peci_controller_scan_devices(struct peci_controller * controller)32 int peci_controller_scan_devices(struct peci_controller *controller)
33 {
34 	int ret;
35 	u8 addr;
36 
37 	for (addr = PECI_BASE_ADDR; addr < PECI_BASE_ADDR + PECI_DEVICE_NUM_MAX; addr++) {
38 		ret = peci_device_create(controller, addr);
39 		if (ret)
40 			return ret;
41 	}
42 
43 	return 0;
44 }
45 
peci_controller_alloc(struct device * dev,const struct peci_controller_ops * ops)46 static struct peci_controller *peci_controller_alloc(struct device *dev,
47 						     const struct peci_controller_ops *ops)
48 {
49 	struct peci_controller *controller;
50 	int ret;
51 
52 	if (!ops->xfer)
53 		return ERR_PTR(-EINVAL);
54 
55 	controller = kzalloc(sizeof(*controller), GFP_KERNEL);
56 	if (!controller)
57 		return ERR_PTR(-ENOMEM);
58 
59 	ret = ida_alloc_max(&peci_controller_ida, U8_MAX, GFP_KERNEL);
60 	if (ret < 0)
61 		goto err;
62 	controller->id = ret;
63 
64 	controller->ops = ops;
65 
66 	controller->dev.parent = dev;
67 	controller->dev.bus = &peci_bus_type;
68 	controller->dev.type = &peci_controller_type;
69 
70 	device_initialize(&controller->dev);
71 
72 	mutex_init(&controller->bus_lock);
73 
74 	return controller;
75 
76 err:
77 	kfree(controller);
78 	return ERR_PTR(ret);
79 }
80 
unregister_child(struct device * dev,void * dummy)81 static int unregister_child(struct device *dev, void *dummy)
82 {
83 	peci_device_destroy(to_peci_device(dev));
84 
85 	return 0;
86 }
87 
unregister_controller(void * _controller)88 static void unregister_controller(void *_controller)
89 {
90 	struct peci_controller *controller = _controller;
91 
92 	/*
93 	 * Detach any active PECI devices. This can't fail, thus we do not
94 	 * check the returned value.
95 	 */
96 	device_for_each_child_reverse(&controller->dev, NULL, unregister_child);
97 
98 	device_unregister(&controller->dev);
99 
100 	fwnode_handle_put(controller->dev.fwnode);
101 
102 	pm_runtime_disable(&controller->dev);
103 }
104 
105 /**
106  * devm_peci_controller_add() - add PECI controller
107  * @dev: device for devm operations
108  * @ops: pointer to controller specific methods
109  *
110  * In final stage of its probe(), peci_controller driver calls
111  * devm_peci_controller_add() to register itself with the PECI bus.
112  *
113  * Return: Pointer to the newly allocated controller or ERR_PTR() in case of failure.
114  */
devm_peci_controller_add(struct device * dev,const struct peci_controller_ops * ops)115 struct peci_controller *devm_peci_controller_add(struct device *dev,
116 						 const struct peci_controller_ops *ops)
117 {
118 	struct peci_controller *controller;
119 	int ret;
120 
121 	controller = peci_controller_alloc(dev, ops);
122 	if (IS_ERR(controller))
123 		return controller;
124 
125 	ret = dev_set_name(&controller->dev, "peci-%d", controller->id);
126 	if (ret)
127 		goto err_put;
128 
129 	pm_runtime_no_callbacks(&controller->dev);
130 	pm_suspend_ignore_children(&controller->dev, true);
131 	pm_runtime_enable(&controller->dev);
132 
133 	device_set_node(&controller->dev, fwnode_handle_get(dev_fwnode(dev)));
134 
135 	ret = device_add(&controller->dev);
136 	if (ret)
137 		goto err_fwnode;
138 
139 	ret = devm_add_action_or_reset(dev, unregister_controller, controller);
140 	if (ret)
141 		return ERR_PTR(ret);
142 
143 	/*
144 	 * Ignoring retval since failures during scan are non-critical for
145 	 * controller itself.
146 	 */
147 	peci_controller_scan_devices(controller);
148 
149 	return controller;
150 
151 err_fwnode:
152 	fwnode_handle_put(controller->dev.fwnode);
153 
154 	pm_runtime_disable(&controller->dev);
155 
156 err_put:
157 	put_device(&controller->dev);
158 
159 	return ERR_PTR(ret);
160 }
161 EXPORT_SYMBOL_NS_GPL(devm_peci_controller_add, "PECI");
162 
163 static const struct peci_device_id *
peci_bus_match_device_id(const struct peci_device_id * id,struct peci_device * device)164 peci_bus_match_device_id(const struct peci_device_id *id, struct peci_device *device)
165 {
166 	while (id->x86_vfm != 0) {
167 		if (id->x86_vfm == device->info.x86_vfm)
168 			return id;
169 		id++;
170 	}
171 
172 	return NULL;
173 }
174 
peci_bus_device_match(struct device * dev,const struct device_driver * drv)175 static int peci_bus_device_match(struct device *dev, const struct device_driver *drv)
176 {
177 	struct peci_device *device = to_peci_device(dev);
178 	const struct peci_driver *peci_drv = to_peci_driver(drv);
179 
180 	if (dev->type != &peci_device_type)
181 		return 0;
182 
183 	return !!peci_bus_match_device_id(peci_drv->id_table, device);
184 }
185 
peci_bus_device_probe(struct device * dev)186 static int peci_bus_device_probe(struct device *dev)
187 {
188 	struct peci_device *device = to_peci_device(dev);
189 	struct peci_driver *driver = to_peci_driver(dev->driver);
190 
191 	return driver->probe(device, peci_bus_match_device_id(driver->id_table, device));
192 }
193 
peci_bus_device_remove(struct device * dev)194 static void peci_bus_device_remove(struct device *dev)
195 {
196 	struct peci_device *device = to_peci_device(dev);
197 	struct peci_driver *driver = to_peci_driver(dev->driver);
198 
199 	if (driver->remove)
200 		driver->remove(device);
201 }
202 
203 const struct bus_type peci_bus_type = {
204 	.name		= "peci",
205 	.match		= peci_bus_device_match,
206 	.probe		= peci_bus_device_probe,
207 	.remove		= peci_bus_device_remove,
208 	.bus_groups	= peci_bus_groups,
209 };
210 
peci_init(void)211 static int __init peci_init(void)
212 {
213 	int ret;
214 
215 	ret = bus_register(&peci_bus_type);
216 	if (ret < 0) {
217 		pr_err("peci: failed to register PECI bus type!\n");
218 		return ret;
219 	}
220 
221 	return 0;
222 }
223 module_init(peci_init);
224 
peci_exit(void)225 static void __exit peci_exit(void)
226 {
227 	bus_unregister(&peci_bus_type);
228 }
229 module_exit(peci_exit);
230 
231 MODULE_AUTHOR("Jason M Bills <jason.m.bills@linux.intel.com>");
232 MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
233 MODULE_AUTHOR("Iwona Winiarska <iwona.winiarska@intel.com>");
234 MODULE_DESCRIPTION("PECI bus core module");
235 MODULE_LICENSE("GPL");
236