1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2018-2021 Intel Corporation
5 #include <linux/device.h>
6 #include <linux/export.h>
8 #include <linux/module.h>
10 #include <linux/peci.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/property.h>
13 #include <linux/slab.h>
17 static DEFINE_IDA(peci_controller_ida
);
19 static void peci_controller_dev_release(struct device
*dev
)
21 struct peci_controller
*controller
= to_peci_controller(dev
);
23 mutex_destroy(&controller
->bus_lock
);
24 ida_free(&peci_controller_ida
, controller
->id
);
28 const struct device_type peci_controller_type
= {
29 .release
= peci_controller_dev_release
,
32 int peci_controller_scan_devices(struct peci_controller
*controller
)
37 for (addr
= PECI_BASE_ADDR
; addr
< PECI_BASE_ADDR
+ PECI_DEVICE_NUM_MAX
; addr
++) {
38 ret
= peci_device_create(controller
, addr
);
46 static struct peci_controller
*peci_controller_alloc(struct device
*dev
,
47 const struct peci_controller_ops
*ops
)
49 struct peci_controller
*controller
;
53 return ERR_PTR(-EINVAL
);
55 controller
= kzalloc(sizeof(*controller
), GFP_KERNEL
);
57 return ERR_PTR(-ENOMEM
);
59 ret
= ida_alloc_max(&peci_controller_ida
, U8_MAX
, GFP_KERNEL
);
64 controller
->ops
= ops
;
66 controller
->dev
.parent
= dev
;
67 controller
->dev
.bus
= &peci_bus_type
;
68 controller
->dev
.type
= &peci_controller_type
;
70 device_initialize(&controller
->dev
);
72 mutex_init(&controller
->bus_lock
);
81 static int unregister_child(struct device
*dev
, void *dummy
)
83 peci_device_destroy(to_peci_device(dev
));
88 static void unregister_controller(void *_controller
)
90 struct peci_controller
*controller
= _controller
;
93 * Detach any active PECI devices. This can't fail, thus we do not
94 * check the returned value.
96 device_for_each_child_reverse(&controller
->dev
, NULL
, unregister_child
);
98 device_unregister(&controller
->dev
);
100 fwnode_handle_put(controller
->dev
.fwnode
);
102 pm_runtime_disable(&controller
->dev
);
106 * devm_peci_controller_add() - add PECI controller
107 * @dev: device for devm operations
108 * @ops: pointer to controller specific methods
110 * In final stage of its probe(), peci_controller driver calls
111 * devm_peci_controller_add() to register itself with the PECI bus.
113 * Return: Pointer to the newly allocated controller or ERR_PTR() in case of failure.
115 struct peci_controller
*devm_peci_controller_add(struct device
*dev
,
116 const struct peci_controller_ops
*ops
)
118 struct peci_controller
*controller
;
121 controller
= peci_controller_alloc(dev
, ops
);
122 if (IS_ERR(controller
))
125 ret
= dev_set_name(&controller
->dev
, "peci-%d", controller
->id
);
129 pm_runtime_no_callbacks(&controller
->dev
);
130 pm_suspend_ignore_children(&controller
->dev
, true);
131 pm_runtime_enable(&controller
->dev
);
133 device_set_node(&controller
->dev
, fwnode_handle_get(dev_fwnode(dev
)));
135 ret
= device_add(&controller
->dev
);
139 ret
= devm_add_action_or_reset(dev
, unregister_controller
, controller
);
144 * Ignoring retval since failures during scan are non-critical for
147 peci_controller_scan_devices(controller
);
152 fwnode_handle_put(controller
->dev
.fwnode
);
154 pm_runtime_disable(&controller
->dev
);
157 put_device(&controller
->dev
);
161 EXPORT_SYMBOL_NS_GPL(devm_peci_controller_add
, PECI
);
163 static const struct peci_device_id
*
164 peci_bus_match_device_id(const struct peci_device_id
*id
, struct peci_device
*device
)
166 while (id
->x86_vfm
!= 0) {
167 if (id
->x86_vfm
== device
->info
.x86_vfm
)
175 static int peci_bus_device_match(struct device
*dev
, const struct device_driver
*drv
)
177 struct peci_device
*device
= to_peci_device(dev
);
178 const struct peci_driver
*peci_drv
= to_peci_driver(drv
);
180 if (dev
->type
!= &peci_device_type
)
183 return !!peci_bus_match_device_id(peci_drv
->id_table
, device
);
186 static int peci_bus_device_probe(struct device
*dev
)
188 struct peci_device
*device
= to_peci_device(dev
);
189 struct peci_driver
*driver
= to_peci_driver(dev
->driver
);
191 return driver
->probe(device
, peci_bus_match_device_id(driver
->id_table
, device
));
194 static void peci_bus_device_remove(struct device
*dev
)
196 struct peci_device
*device
= to_peci_device(dev
);
197 struct peci_driver
*driver
= to_peci_driver(dev
->driver
);
200 driver
->remove(device
);
203 const struct bus_type peci_bus_type
= {
205 .match
= peci_bus_device_match
,
206 .probe
= peci_bus_device_probe
,
207 .remove
= peci_bus_device_remove
,
208 .bus_groups
= peci_bus_groups
,
211 static int __init
peci_init(void)
215 ret
= bus_register(&peci_bus_type
);
217 pr_err("peci: failed to register PECI bus type!\n");
223 module_init(peci_init
);
225 static void __exit
peci_exit(void)
227 bus_unregister(&peci_bus_type
);
229 module_exit(peci_exit
);
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");