Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * System Control and Management Interface (SCMI) Message Protocol bus layer
  4 *
  5 * Copyright (C) 2018 ARM Ltd.
  6 */
  7
  8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  9
 10#include <linux/types.h>
 11#include <linux/module.h>
 12#include <linux/kernel.h>
 13#include <linux/slab.h>
 14#include <linux/device.h>
 15
 16#include "common.h"
 17
 18static DEFINE_IDA(scmi_bus_id);
 19static DEFINE_IDR(scmi_protocols);
 20static DEFINE_SPINLOCK(protocol_lock);
 21
 22static const struct scmi_device_id *
 23scmi_dev_match_id(struct scmi_device *scmi_dev, struct scmi_driver *scmi_drv)
 24{
 25	const struct scmi_device_id *id = scmi_drv->id_table;
 26
 27	if (!id)
 28		return NULL;
 29
 30	for (; id->protocol_id; id++)
 31		if (id->protocol_id == scmi_dev->protocol_id) {
 32			if (!id->name)
 33				return id;
 34			else if (!strcmp(id->name, scmi_dev->name))
 35				return id;
 36		}
 37
 38	return NULL;
 39}
 40
 41static int scmi_dev_match(struct device *dev, struct device_driver *drv)
 42{
 43	struct scmi_driver *scmi_drv = to_scmi_driver(drv);
 44	struct scmi_device *scmi_dev = to_scmi_dev(dev);
 45	const struct scmi_device_id *id;
 46
 47	id = scmi_dev_match_id(scmi_dev, scmi_drv);
 48	if (id)
 49		return 1;
 50
 51	return 0;
 52}
 53
 54static int scmi_protocol_init(int protocol_id, struct scmi_handle *handle)
 55{
 56	scmi_prot_init_fn_t fn = idr_find(&scmi_protocols, protocol_id);
 57
 58	if (unlikely(!fn))
 59		return -EINVAL;
 60	return fn(handle);
 61}
 62
 63static int scmi_protocol_dummy_init(struct scmi_handle *handle)
 64{
 65	return 0;
 66}
 67
 68static int scmi_dev_probe(struct device *dev)
 69{
 70	struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
 71	struct scmi_device *scmi_dev = to_scmi_dev(dev);
 72	const struct scmi_device_id *id;
 73	int ret;
 74
 75	id = scmi_dev_match_id(scmi_dev, scmi_drv);
 76	if (!id)
 77		return -ENODEV;
 78
 79	if (!scmi_dev->handle)
 80		return -EPROBE_DEFER;
 81
 82	ret = scmi_protocol_init(scmi_dev->protocol_id, scmi_dev->handle);
 83	if (ret)
 84		return ret;
 85
 86	/* Skip protocol initialisation for additional devices */
 87	idr_replace(&scmi_protocols, &scmi_protocol_dummy_init,
 88		    scmi_dev->protocol_id);
 89
 90	return scmi_drv->probe(scmi_dev);
 91}
 92
 93static int scmi_dev_remove(struct device *dev)
 94{
 95	struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
 96	struct scmi_device *scmi_dev = to_scmi_dev(dev);
 97
 98	if (scmi_drv->remove)
 99		scmi_drv->remove(scmi_dev);
100
101	return 0;
102}
103
104static struct bus_type scmi_bus_type = {
105	.name =	"scmi_protocol",
106	.match = scmi_dev_match,
107	.probe = scmi_dev_probe,
108	.remove = scmi_dev_remove,
109};
110
111int scmi_driver_register(struct scmi_driver *driver, struct module *owner,
112			 const char *mod_name)
113{
114	int retval;
115
116	driver->driver.bus = &scmi_bus_type;
117	driver->driver.name = driver->name;
118	driver->driver.owner = owner;
119	driver->driver.mod_name = mod_name;
120
121	retval = driver_register(&driver->driver);
122	if (!retval)
123		pr_debug("registered new scmi driver %s\n", driver->name);
124
125	return retval;
126}
127EXPORT_SYMBOL_GPL(scmi_driver_register);
128
129void scmi_driver_unregister(struct scmi_driver *driver)
130{
131	driver_unregister(&driver->driver);
132}
133EXPORT_SYMBOL_GPL(scmi_driver_unregister);
134
135static void scmi_device_release(struct device *dev)
136{
137	kfree(to_scmi_dev(dev));
138}
139
140struct scmi_device *
141scmi_device_create(struct device_node *np, struct device *parent, int protocol,
142		   const char *name)
143{
144	int id, retval;
145	struct scmi_device *scmi_dev;
146
147	scmi_dev = kzalloc(sizeof(*scmi_dev), GFP_KERNEL);
148	if (!scmi_dev)
149		return NULL;
150
151	scmi_dev->name = kstrdup_const(name ?: "unknown", GFP_KERNEL);
152	if (!scmi_dev->name) {
153		kfree(scmi_dev);
154		return NULL;
155	}
156
157	id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
158	if (id < 0) {
159		kfree_const(scmi_dev->name);
160		kfree(scmi_dev);
161		return NULL;
162	}
163
164	scmi_dev->id = id;
165	scmi_dev->protocol_id = protocol;
166	scmi_dev->dev.parent = parent;
167	scmi_dev->dev.of_node = np;
168	scmi_dev->dev.bus = &scmi_bus_type;
169	scmi_dev->dev.release = scmi_device_release;
170	dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
171
172	retval = device_register(&scmi_dev->dev);
173	if (retval)
174		goto put_dev;
175
176	return scmi_dev;
177put_dev:
178	kfree_const(scmi_dev->name);
179	put_device(&scmi_dev->dev);
180	ida_simple_remove(&scmi_bus_id, id);
 
 
181	return NULL;
182}
183
184void scmi_device_destroy(struct scmi_device *scmi_dev)
185{
186	kfree_const(scmi_dev->name);
187	scmi_handle_put(scmi_dev->handle);
188	ida_simple_remove(&scmi_bus_id, scmi_dev->id);
189	device_unregister(&scmi_dev->dev);
190}
191
192void scmi_set_handle(struct scmi_device *scmi_dev)
193{
194	scmi_dev->handle = scmi_handle_get(&scmi_dev->dev);
195}
196
197int scmi_protocol_register(int protocol_id, scmi_prot_init_fn_t fn)
198{
199	int ret;
200
201	spin_lock(&protocol_lock);
202	ret = idr_alloc(&scmi_protocols, fn, protocol_id, protocol_id + 1,
203			GFP_ATOMIC);
204	spin_unlock(&protocol_lock);
205	if (ret != protocol_id)
206		pr_err("unable to allocate SCMI idr slot, err %d\n", ret);
207
208	return ret;
209}
210EXPORT_SYMBOL_GPL(scmi_protocol_register);
211
212void scmi_protocol_unregister(int protocol_id)
213{
214	spin_lock(&protocol_lock);
215	idr_remove(&scmi_protocols, protocol_id);
216	spin_unlock(&protocol_lock);
217}
218EXPORT_SYMBOL_GPL(scmi_protocol_unregister);
219
220static int __scmi_devices_unregister(struct device *dev, void *data)
221{
222	struct scmi_device *scmi_dev = to_scmi_dev(dev);
223
224	scmi_device_destroy(scmi_dev);
225	return 0;
226}
227
228static void scmi_devices_unregister(void)
229{
230	bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister);
231}
232
233static int __init scmi_bus_init(void)
234{
235	int retval;
236
237	retval = bus_register(&scmi_bus_type);
238	if (retval)
239		pr_err("scmi protocol bus register failed (%d)\n", retval);
240
241	return retval;
242}
243subsys_initcall(scmi_bus_init);
244
245static void __exit scmi_bus_exit(void)
246{
247	scmi_devices_unregister();
248	bus_unregister(&scmi_bus_type);
249	ida_destroy(&scmi_bus_id);
250}
251module_exit(scmi_bus_exit);
v5.4
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * System Control and Management Interface (SCMI) Message Protocol bus layer
  4 *
  5 * Copyright (C) 2018 ARM Ltd.
  6 */
  7
  8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  9
 10#include <linux/types.h>
 11#include <linux/module.h>
 12#include <linux/kernel.h>
 13#include <linux/slab.h>
 14#include <linux/device.h>
 15
 16#include "common.h"
 17
 18static DEFINE_IDA(scmi_bus_id);
 19static DEFINE_IDR(scmi_protocols);
 20static DEFINE_SPINLOCK(protocol_lock);
 21
 22static const struct scmi_device_id *
 23scmi_dev_match_id(struct scmi_device *scmi_dev, struct scmi_driver *scmi_drv)
 24{
 25	const struct scmi_device_id *id = scmi_drv->id_table;
 26
 27	if (!id)
 28		return NULL;
 29
 30	for (; id->protocol_id; id++)
 31		if (id->protocol_id == scmi_dev->protocol_id)
 32			return id;
 
 
 
 
 33
 34	return NULL;
 35}
 36
 37static int scmi_dev_match(struct device *dev, struct device_driver *drv)
 38{
 39	struct scmi_driver *scmi_drv = to_scmi_driver(drv);
 40	struct scmi_device *scmi_dev = to_scmi_dev(dev);
 41	const struct scmi_device_id *id;
 42
 43	id = scmi_dev_match_id(scmi_dev, scmi_drv);
 44	if (id)
 45		return 1;
 46
 47	return 0;
 48}
 49
 50static int scmi_protocol_init(int protocol_id, struct scmi_handle *handle)
 51{
 52	scmi_prot_init_fn_t fn = idr_find(&scmi_protocols, protocol_id);
 53
 54	if (unlikely(!fn))
 55		return -EINVAL;
 56	return fn(handle);
 57}
 58
 
 
 
 
 
 59static int scmi_dev_probe(struct device *dev)
 60{
 61	struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
 62	struct scmi_device *scmi_dev = to_scmi_dev(dev);
 63	const struct scmi_device_id *id;
 64	int ret;
 65
 66	id = scmi_dev_match_id(scmi_dev, scmi_drv);
 67	if (!id)
 68		return -ENODEV;
 69
 70	if (!scmi_dev->handle)
 71		return -EPROBE_DEFER;
 72
 73	ret = scmi_protocol_init(scmi_dev->protocol_id, scmi_dev->handle);
 74	if (ret)
 75		return ret;
 76
 
 
 
 
 77	return scmi_drv->probe(scmi_dev);
 78}
 79
 80static int scmi_dev_remove(struct device *dev)
 81{
 82	struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
 83	struct scmi_device *scmi_dev = to_scmi_dev(dev);
 84
 85	if (scmi_drv->remove)
 86		scmi_drv->remove(scmi_dev);
 87
 88	return 0;
 89}
 90
 91static struct bus_type scmi_bus_type = {
 92	.name =	"scmi_protocol",
 93	.match = scmi_dev_match,
 94	.probe = scmi_dev_probe,
 95	.remove = scmi_dev_remove,
 96};
 97
 98int scmi_driver_register(struct scmi_driver *driver, struct module *owner,
 99			 const char *mod_name)
100{
101	int retval;
102
103	driver->driver.bus = &scmi_bus_type;
104	driver->driver.name = driver->name;
105	driver->driver.owner = owner;
106	driver->driver.mod_name = mod_name;
107
108	retval = driver_register(&driver->driver);
109	if (!retval)
110		pr_debug("registered new scmi driver %s\n", driver->name);
111
112	return retval;
113}
114EXPORT_SYMBOL_GPL(scmi_driver_register);
115
116void scmi_driver_unregister(struct scmi_driver *driver)
117{
118	driver_unregister(&driver->driver);
119}
120EXPORT_SYMBOL_GPL(scmi_driver_unregister);
121
122static void scmi_device_release(struct device *dev)
123{
124	kfree(to_scmi_dev(dev));
125}
126
127struct scmi_device *
128scmi_device_create(struct device_node *np, struct device *parent, int protocol)
 
129{
130	int id, retval;
131	struct scmi_device *scmi_dev;
132
133	scmi_dev = kzalloc(sizeof(*scmi_dev), GFP_KERNEL);
134	if (!scmi_dev)
135		return NULL;
136
 
 
 
 
 
 
137	id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
138	if (id < 0)
139		goto free_mem;
 
 
 
140
141	scmi_dev->id = id;
142	scmi_dev->protocol_id = protocol;
143	scmi_dev->dev.parent = parent;
144	scmi_dev->dev.of_node = np;
145	scmi_dev->dev.bus = &scmi_bus_type;
146	scmi_dev->dev.release = scmi_device_release;
147	dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
148
149	retval = device_register(&scmi_dev->dev);
150	if (retval)
151		goto put_dev;
152
153	return scmi_dev;
154put_dev:
 
155	put_device(&scmi_dev->dev);
156	ida_simple_remove(&scmi_bus_id, id);
157free_mem:
158	kfree(scmi_dev);
159	return NULL;
160}
161
162void scmi_device_destroy(struct scmi_device *scmi_dev)
163{
 
164	scmi_handle_put(scmi_dev->handle);
165	ida_simple_remove(&scmi_bus_id, scmi_dev->id);
166	device_unregister(&scmi_dev->dev);
167}
168
169void scmi_set_handle(struct scmi_device *scmi_dev)
170{
171	scmi_dev->handle = scmi_handle_get(&scmi_dev->dev);
172}
173
174int scmi_protocol_register(int protocol_id, scmi_prot_init_fn_t fn)
175{
176	int ret;
177
178	spin_lock(&protocol_lock);
179	ret = idr_alloc(&scmi_protocols, fn, protocol_id, protocol_id + 1,
180			GFP_ATOMIC);
181	spin_unlock(&protocol_lock);
182	if (ret != protocol_id)
183		pr_err("unable to allocate SCMI idr slot, err %d\n", ret);
184
185	return ret;
186}
187EXPORT_SYMBOL_GPL(scmi_protocol_register);
188
189void scmi_protocol_unregister(int protocol_id)
190{
191	spin_lock(&protocol_lock);
192	idr_remove(&scmi_protocols, protocol_id);
193	spin_unlock(&protocol_lock);
194}
195EXPORT_SYMBOL_GPL(scmi_protocol_unregister);
196
197static int __scmi_devices_unregister(struct device *dev, void *data)
198{
199	struct scmi_device *scmi_dev = to_scmi_dev(dev);
200
201	scmi_device_destroy(scmi_dev);
202	return 0;
203}
204
205static void scmi_devices_unregister(void)
206{
207	bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister);
208}
209
210static int __init scmi_bus_init(void)
211{
212	int retval;
213
214	retval = bus_register(&scmi_bus_type);
215	if (retval)
216		pr_err("scmi protocol bus register failed (%d)\n", retval);
217
218	return retval;
219}
220subsys_initcall(scmi_bus_init);
221
222static void __exit scmi_bus_exit(void)
223{
224	scmi_devices_unregister();
225	bus_unregister(&scmi_bus_type);
226	ida_destroy(&scmi_bus_id);
227}
228module_exit(scmi_bus_exit);