xref: /linux/drivers/firmware/arm_ffa/bus.c (revision d01387fc16421cbbf95d1fda8fe1258195396c64)
1e7818584SSudeep Holla // SPDX-License-Identifier: GPL-2.0
2e7818584SSudeep Holla /*
3e7818584SSudeep Holla  * Copyright (C) 2021 ARM Ltd.
4e7818584SSudeep Holla  */
5e7818584SSudeep Holla 
6e7818584SSudeep Holla #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7e7818584SSudeep Holla 
8e7818584SSudeep Holla #include <linux/arm_ffa.h>
9e7818584SSudeep Holla #include <linux/device.h>
10e7818584SSudeep Holla #include <linux/fs.h>
11e7818584SSudeep Holla #include <linux/kernel.h>
12e7818584SSudeep Holla #include <linux/module.h>
13e7818584SSudeep Holla #include <linux/slab.h>
14e7818584SSudeep Holla #include <linux/types.h>
15e7818584SSudeep Holla 
163bbfe987SSudeep Holla #include "common.h"
173bbfe987SSudeep Holla 
18e7818584SSudeep Holla static int ffa_device_match(struct device *dev, struct device_driver *drv)
19e7818584SSudeep Holla {
20e7818584SSudeep Holla 	const struct ffa_device_id *id_table;
21e7818584SSudeep Holla 	struct ffa_device *ffa_dev;
22e7818584SSudeep Holla 
23e7818584SSudeep Holla 	id_table = to_ffa_driver(drv)->id_table;
24e7818584SSudeep Holla 	ffa_dev = to_ffa_dev(dev);
25e7818584SSudeep Holla 
26e7818584SSudeep Holla 	while (!uuid_is_null(&id_table->uuid)) {
27d0c0bce8SSudeep Holla 		/*
28d0c0bce8SSudeep Holla 		 * FF-A v1.0 doesn't provide discovery of UUIDs, just the
29d0c0bce8SSudeep Holla 		 * partition IDs, so fetch the partitions IDs for this
30d0c0bce8SSudeep Holla 		 * id_table UUID and assign the UUID to the device if the
31d0c0bce8SSudeep Holla 		 * partition ID matches
32d0c0bce8SSudeep Holla 		 */
33d0c0bce8SSudeep Holla 		if (uuid_is_null(&ffa_dev->uuid))
34d0c0bce8SSudeep Holla 			ffa_device_match_uuid(ffa_dev, &id_table->uuid);
35d0c0bce8SSudeep Holla 
36e7818584SSudeep Holla 		if (uuid_equal(&ffa_dev->uuid, &id_table->uuid))
37e7818584SSudeep Holla 			return 1;
38e7818584SSudeep Holla 		id_table++;
39e7818584SSudeep Holla 	}
40e7818584SSudeep Holla 
41e7818584SSudeep Holla 	return 0;
42e7818584SSudeep Holla }
43e7818584SSudeep Holla 
44e7818584SSudeep Holla static int ffa_device_probe(struct device *dev)
45e7818584SSudeep Holla {
46e7818584SSudeep Holla 	struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
47e7818584SSudeep Holla 	struct ffa_device *ffa_dev = to_ffa_dev(dev);
48e7818584SSudeep Holla 
49e7818584SSudeep Holla 	return ffa_drv->probe(ffa_dev);
50e7818584SSudeep Holla }
51e7818584SSudeep Holla 
52244f5d59SSudeep Holla static void ffa_device_remove(struct device *dev)
53244f5d59SSudeep Holla {
54244f5d59SSudeep Holla 	struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
55244f5d59SSudeep Holla 
56244f5d59SSudeep Holla 	ffa_drv->remove(to_ffa_dev(dev));
57244f5d59SSudeep Holla }
58244f5d59SSudeep Holla 
59e7818584SSudeep Holla static int ffa_device_uevent(struct device *dev, struct kobj_uevent_env *env)
60e7818584SSudeep Holla {
61e7818584SSudeep Holla 	struct ffa_device *ffa_dev = to_ffa_dev(dev);
62e7818584SSudeep Holla 
63e7818584SSudeep Holla 	return add_uevent_var(env, "MODALIAS=arm_ffa:%04x:%pUb",
64e7818584SSudeep Holla 			      ffa_dev->vm_id, &ffa_dev->uuid);
65e7818584SSudeep Holla }
66e7818584SSudeep Holla 
67e7818584SSudeep Holla static ssize_t partition_id_show(struct device *dev,
68e7818584SSudeep Holla 				 struct device_attribute *attr, char *buf)
69e7818584SSudeep Holla {
70e7818584SSudeep Holla 	struct ffa_device *ffa_dev = to_ffa_dev(dev);
71e7818584SSudeep Holla 
72e7818584SSudeep Holla 	return sprintf(buf, "0x%04x\n", ffa_dev->vm_id);
73e7818584SSudeep Holla }
74e7818584SSudeep Holla static DEVICE_ATTR_RO(partition_id);
75e7818584SSudeep Holla 
76e7818584SSudeep Holla static ssize_t uuid_show(struct device *dev, struct device_attribute *attr,
77e7818584SSudeep Holla 			 char *buf)
78e7818584SSudeep Holla {
79e7818584SSudeep Holla 	struct ffa_device *ffa_dev = to_ffa_dev(dev);
80e7818584SSudeep Holla 
81e7818584SSudeep Holla 	return sprintf(buf, "%pUb\n", &ffa_dev->uuid);
82e7818584SSudeep Holla }
83e7818584SSudeep Holla static DEVICE_ATTR_RO(uuid);
84e7818584SSudeep Holla 
85e7818584SSudeep Holla static struct attribute *ffa_device_attributes_attrs[] = {
86e7818584SSudeep Holla 	&dev_attr_partition_id.attr,
87e7818584SSudeep Holla 	&dev_attr_uuid.attr,
88e7818584SSudeep Holla 	NULL,
89e7818584SSudeep Holla };
90e7818584SSudeep Holla ATTRIBUTE_GROUPS(ffa_device_attributes);
91e7818584SSudeep Holla 
92e7818584SSudeep Holla struct bus_type ffa_bus_type = {
93e7818584SSudeep Holla 	.name		= "arm_ffa",
94e7818584SSudeep Holla 	.match		= ffa_device_match,
95e7818584SSudeep Holla 	.probe		= ffa_device_probe,
96244f5d59SSudeep Holla 	.remove		= ffa_device_remove,
97e7818584SSudeep Holla 	.uevent		= ffa_device_uevent,
98e7818584SSudeep Holla 	.dev_groups	= ffa_device_attributes_groups,
99e7818584SSudeep Holla };
100e7818584SSudeep Holla EXPORT_SYMBOL_GPL(ffa_bus_type);
101e7818584SSudeep Holla 
102e7818584SSudeep Holla int ffa_driver_register(struct ffa_driver *driver, struct module *owner,
103e7818584SSudeep Holla 			const char *mod_name)
104e7818584SSudeep Holla {
105e7818584SSudeep Holla 	int ret;
106e7818584SSudeep Holla 
10792743071SUwe Kleine-König 	if (!driver->probe)
10892743071SUwe Kleine-König 		return -EINVAL;
10992743071SUwe Kleine-König 
110e7818584SSudeep Holla 	driver->driver.bus = &ffa_bus_type;
111e7818584SSudeep Holla 	driver->driver.name = driver->name;
112e7818584SSudeep Holla 	driver->driver.owner = owner;
113e7818584SSudeep Holla 	driver->driver.mod_name = mod_name;
114e7818584SSudeep Holla 
115e7818584SSudeep Holla 	ret = driver_register(&driver->driver);
116e7818584SSudeep Holla 	if (!ret)
117e7818584SSudeep Holla 		pr_debug("registered new ffa driver %s\n", driver->name);
118e7818584SSudeep Holla 
119e7818584SSudeep Holla 	return ret;
120e7818584SSudeep Holla }
121e7818584SSudeep Holla EXPORT_SYMBOL_GPL(ffa_driver_register);
122e7818584SSudeep Holla 
123e7818584SSudeep Holla void ffa_driver_unregister(struct ffa_driver *driver)
124e7818584SSudeep Holla {
125e7818584SSudeep Holla 	driver_unregister(&driver->driver);
126e7818584SSudeep Holla }
127e7818584SSudeep Holla EXPORT_SYMBOL_GPL(ffa_driver_unregister);
128e7818584SSudeep Holla 
129e7818584SSudeep Holla static void ffa_release_device(struct device *dev)
130e7818584SSudeep Holla {
131e7818584SSudeep Holla 	struct ffa_device *ffa_dev = to_ffa_dev(dev);
132e7818584SSudeep Holla 
133e7818584SSudeep Holla 	kfree(ffa_dev);
134e7818584SSudeep Holla }
135e7818584SSudeep Holla 
136e7818584SSudeep Holla static int __ffa_devices_unregister(struct device *dev, void *data)
137e7818584SSudeep Holla {
138eb7b52e6SSudeep Holla 	device_unregister(dev);
139e7818584SSudeep Holla 
140e7818584SSudeep Holla 	return 0;
141e7818584SSudeep Holla }
142e7818584SSudeep Holla 
143e7818584SSudeep Holla static void ffa_devices_unregister(void)
144e7818584SSudeep Holla {
145e7818584SSudeep Holla 	bus_for_each_dev(&ffa_bus_type, NULL, NULL,
146e7818584SSudeep Holla 			 __ffa_devices_unregister);
147e7818584SSudeep Holla }
148e7818584SSudeep Holla 
149e7818584SSudeep Holla bool ffa_device_is_valid(struct ffa_device *ffa_dev)
150e7818584SSudeep Holla {
151e7818584SSudeep Holla 	bool valid = false;
152e7818584SSudeep Holla 	struct device *dev = NULL;
153e7818584SSudeep Holla 	struct ffa_device *tmp_dev;
154e7818584SSudeep Holla 
155e7818584SSudeep Holla 	do {
156e7818584SSudeep Holla 		dev = bus_find_next_device(&ffa_bus_type, dev);
157e7818584SSudeep Holla 		tmp_dev = to_ffa_dev(dev);
158e7818584SSudeep Holla 		if (tmp_dev == ffa_dev) {
159e7818584SSudeep Holla 			valid = true;
160e7818584SSudeep Holla 			break;
161e7818584SSudeep Holla 		}
162e7818584SSudeep Holla 		put_device(dev);
163e7818584SSudeep Holla 	} while (dev);
164e7818584SSudeep Holla 
165e7818584SSudeep Holla 	put_device(dev);
166e7818584SSudeep Holla 
167e7818584SSudeep Holla 	return valid;
168e7818584SSudeep Holla }
169e7818584SSudeep Holla 
170*d01387fcSSudeep Holla struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
171*d01387fcSSudeep Holla 				       const struct ffa_dev_ops *ops)
172e7818584SSudeep Holla {
173e7818584SSudeep Holla 	int ret;
174e7818584SSudeep Holla 	struct device *dev;
175e7818584SSudeep Holla 	struct ffa_device *ffa_dev;
176e7818584SSudeep Holla 
177e7818584SSudeep Holla 	ffa_dev = kzalloc(sizeof(*ffa_dev), GFP_KERNEL);
178e7818584SSudeep Holla 	if (!ffa_dev)
179e7818584SSudeep Holla 		return NULL;
180e7818584SSudeep Holla 
181e7818584SSudeep Holla 	dev = &ffa_dev->dev;
182e7818584SSudeep Holla 	dev->bus = &ffa_bus_type;
183e7818584SSudeep Holla 	dev->release = ffa_release_device;
184e7818584SSudeep Holla 	dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id);
185e7818584SSudeep Holla 
186e7818584SSudeep Holla 	ffa_dev->vm_id = vm_id;
187*d01387fcSSudeep Holla 	ffa_dev->ops = ops;
188e7818584SSudeep Holla 	uuid_copy(&ffa_dev->uuid, uuid);
189e7818584SSudeep Holla 
190e7818584SSudeep Holla 	ret = device_register(&ffa_dev->dev);
191e7818584SSudeep Holla 	if (ret) {
192e7818584SSudeep Holla 		dev_err(dev, "unable to register device %s err=%d\n",
193e7818584SSudeep Holla 			dev_name(dev), ret);
194e7818584SSudeep Holla 		put_device(dev);
195e7818584SSudeep Holla 		return NULL;
196e7818584SSudeep Holla 	}
197e7818584SSudeep Holla 
198e7818584SSudeep Holla 	return ffa_dev;
199e7818584SSudeep Holla }
200e7818584SSudeep Holla EXPORT_SYMBOL_GPL(ffa_device_register);
201e7818584SSudeep Holla 
202e7818584SSudeep Holla void ffa_device_unregister(struct ffa_device *ffa_dev)
203e7818584SSudeep Holla {
204e7818584SSudeep Holla 	if (!ffa_dev)
205e7818584SSudeep Holla 		return;
206e7818584SSudeep Holla 
207e7818584SSudeep Holla 	device_unregister(&ffa_dev->dev);
208e7818584SSudeep Holla }
209e7818584SSudeep Holla EXPORT_SYMBOL_GPL(ffa_device_unregister);
210e7818584SSudeep Holla 
2113bbfe987SSudeep Holla int arm_ffa_bus_init(void)
212e7818584SSudeep Holla {
213e7818584SSudeep Holla 	return bus_register(&ffa_bus_type);
214e7818584SSudeep Holla }
215e7818584SSudeep Holla 
2163bbfe987SSudeep Holla void arm_ffa_bus_exit(void)
217e7818584SSudeep Holla {
218e7818584SSudeep Holla 	ffa_devices_unregister();
219e7818584SSudeep Holla 	bus_unregister(&ffa_bus_type);
220e7818584SSudeep Holla }
221