xref: /linux/drivers/firmware/arm_ffa/bus.c (revision e781858488b918e30a6ff28e9eab6058b787e3b3)
1*e7818584SSudeep Holla // SPDX-License-Identifier: GPL-2.0
2*e7818584SSudeep Holla /*
3*e7818584SSudeep Holla  * Copyright (C) 2021 ARM Ltd.
4*e7818584SSudeep Holla  */
5*e7818584SSudeep Holla 
6*e7818584SSudeep Holla #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7*e7818584SSudeep Holla 
8*e7818584SSudeep Holla #include <linux/arm_ffa.h>
9*e7818584SSudeep Holla #include <linux/device.h>
10*e7818584SSudeep Holla #include <linux/fs.h>
11*e7818584SSudeep Holla #include <linux/kernel.h>
12*e7818584SSudeep Holla #include <linux/module.h>
13*e7818584SSudeep Holla #include <linux/slab.h>
14*e7818584SSudeep Holla #include <linux/types.h>
15*e7818584SSudeep Holla 
16*e7818584SSudeep Holla static int ffa_device_match(struct device *dev, struct device_driver *drv)
17*e7818584SSudeep Holla {
18*e7818584SSudeep Holla 	const struct ffa_device_id *id_table;
19*e7818584SSudeep Holla 	struct ffa_device *ffa_dev;
20*e7818584SSudeep Holla 
21*e7818584SSudeep Holla 	id_table = to_ffa_driver(drv)->id_table;
22*e7818584SSudeep Holla 	ffa_dev = to_ffa_dev(dev);
23*e7818584SSudeep Holla 
24*e7818584SSudeep Holla 	while (!uuid_is_null(&id_table->uuid)) {
25*e7818584SSudeep Holla 		if (uuid_equal(&ffa_dev->uuid, &id_table->uuid))
26*e7818584SSudeep Holla 			return 1;
27*e7818584SSudeep Holla 		id_table++;
28*e7818584SSudeep Holla 	}
29*e7818584SSudeep Holla 
30*e7818584SSudeep Holla 	return 0;
31*e7818584SSudeep Holla }
32*e7818584SSudeep Holla 
33*e7818584SSudeep Holla static int ffa_device_probe(struct device *dev)
34*e7818584SSudeep Holla {
35*e7818584SSudeep Holla 	struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
36*e7818584SSudeep Holla 	struct ffa_device *ffa_dev = to_ffa_dev(dev);
37*e7818584SSudeep Holla 
38*e7818584SSudeep Holla 	if (!ffa_device_match(dev, dev->driver))
39*e7818584SSudeep Holla 		return -ENODEV;
40*e7818584SSudeep Holla 
41*e7818584SSudeep Holla 	return ffa_drv->probe(ffa_dev);
42*e7818584SSudeep Holla }
43*e7818584SSudeep Holla 
44*e7818584SSudeep Holla static int ffa_device_uevent(struct device *dev, struct kobj_uevent_env *env)
45*e7818584SSudeep Holla {
46*e7818584SSudeep Holla 	struct ffa_device *ffa_dev = to_ffa_dev(dev);
47*e7818584SSudeep Holla 
48*e7818584SSudeep Holla 	return add_uevent_var(env, "MODALIAS=arm_ffa:%04x:%pUb",
49*e7818584SSudeep Holla 			      ffa_dev->vm_id, &ffa_dev->uuid);
50*e7818584SSudeep Holla }
51*e7818584SSudeep Holla 
52*e7818584SSudeep Holla static ssize_t partition_id_show(struct device *dev,
53*e7818584SSudeep Holla 				 struct device_attribute *attr, char *buf)
54*e7818584SSudeep Holla {
55*e7818584SSudeep Holla 	struct ffa_device *ffa_dev = to_ffa_dev(dev);
56*e7818584SSudeep Holla 
57*e7818584SSudeep Holla 	return sprintf(buf, "0x%04x\n", ffa_dev->vm_id);
58*e7818584SSudeep Holla }
59*e7818584SSudeep Holla static DEVICE_ATTR_RO(partition_id);
60*e7818584SSudeep Holla 
61*e7818584SSudeep Holla static ssize_t uuid_show(struct device *dev, struct device_attribute *attr,
62*e7818584SSudeep Holla 			 char *buf)
63*e7818584SSudeep Holla {
64*e7818584SSudeep Holla 	struct ffa_device *ffa_dev = to_ffa_dev(dev);
65*e7818584SSudeep Holla 
66*e7818584SSudeep Holla 	return sprintf(buf, "%pUb\n", &ffa_dev->uuid);
67*e7818584SSudeep Holla }
68*e7818584SSudeep Holla static DEVICE_ATTR_RO(uuid);
69*e7818584SSudeep Holla 
70*e7818584SSudeep Holla static struct attribute *ffa_device_attributes_attrs[] = {
71*e7818584SSudeep Holla 	&dev_attr_partition_id.attr,
72*e7818584SSudeep Holla 	&dev_attr_uuid.attr,
73*e7818584SSudeep Holla 	NULL,
74*e7818584SSudeep Holla };
75*e7818584SSudeep Holla ATTRIBUTE_GROUPS(ffa_device_attributes);
76*e7818584SSudeep Holla 
77*e7818584SSudeep Holla struct bus_type ffa_bus_type = {
78*e7818584SSudeep Holla 	.name		= "arm_ffa",
79*e7818584SSudeep Holla 	.match		= ffa_device_match,
80*e7818584SSudeep Holla 	.probe		= ffa_device_probe,
81*e7818584SSudeep Holla 	.uevent		= ffa_device_uevent,
82*e7818584SSudeep Holla 	.dev_groups	= ffa_device_attributes_groups,
83*e7818584SSudeep Holla };
84*e7818584SSudeep Holla EXPORT_SYMBOL_GPL(ffa_bus_type);
85*e7818584SSudeep Holla 
86*e7818584SSudeep Holla int ffa_driver_register(struct ffa_driver *driver, struct module *owner,
87*e7818584SSudeep Holla 			const char *mod_name)
88*e7818584SSudeep Holla {
89*e7818584SSudeep Holla 	int ret;
90*e7818584SSudeep Holla 
91*e7818584SSudeep Holla 	driver->driver.bus = &ffa_bus_type;
92*e7818584SSudeep Holla 	driver->driver.name = driver->name;
93*e7818584SSudeep Holla 	driver->driver.owner = owner;
94*e7818584SSudeep Holla 	driver->driver.mod_name = mod_name;
95*e7818584SSudeep Holla 
96*e7818584SSudeep Holla 	ret = driver_register(&driver->driver);
97*e7818584SSudeep Holla 	if (!ret)
98*e7818584SSudeep Holla 		pr_debug("registered new ffa driver %s\n", driver->name);
99*e7818584SSudeep Holla 
100*e7818584SSudeep Holla 	return ret;
101*e7818584SSudeep Holla }
102*e7818584SSudeep Holla EXPORT_SYMBOL_GPL(ffa_driver_register);
103*e7818584SSudeep Holla 
104*e7818584SSudeep Holla void ffa_driver_unregister(struct ffa_driver *driver)
105*e7818584SSudeep Holla {
106*e7818584SSudeep Holla 	driver_unregister(&driver->driver);
107*e7818584SSudeep Holla }
108*e7818584SSudeep Holla EXPORT_SYMBOL_GPL(ffa_driver_unregister);
109*e7818584SSudeep Holla 
110*e7818584SSudeep Holla static void ffa_release_device(struct device *dev)
111*e7818584SSudeep Holla {
112*e7818584SSudeep Holla 	struct ffa_device *ffa_dev = to_ffa_dev(dev);
113*e7818584SSudeep Holla 
114*e7818584SSudeep Holla 	kfree(ffa_dev);
115*e7818584SSudeep Holla }
116*e7818584SSudeep Holla 
117*e7818584SSudeep Holla static int __ffa_devices_unregister(struct device *dev, void *data)
118*e7818584SSudeep Holla {
119*e7818584SSudeep Holla 	ffa_release_device(dev);
120*e7818584SSudeep Holla 
121*e7818584SSudeep Holla 	return 0;
122*e7818584SSudeep Holla }
123*e7818584SSudeep Holla 
124*e7818584SSudeep Holla static void ffa_devices_unregister(void)
125*e7818584SSudeep Holla {
126*e7818584SSudeep Holla 	bus_for_each_dev(&ffa_bus_type, NULL, NULL,
127*e7818584SSudeep Holla 			 __ffa_devices_unregister);
128*e7818584SSudeep Holla }
129*e7818584SSudeep Holla 
130*e7818584SSudeep Holla bool ffa_device_is_valid(struct ffa_device *ffa_dev)
131*e7818584SSudeep Holla {
132*e7818584SSudeep Holla 	bool valid = false;
133*e7818584SSudeep Holla 	struct device *dev = NULL;
134*e7818584SSudeep Holla 	struct ffa_device *tmp_dev;
135*e7818584SSudeep Holla 
136*e7818584SSudeep Holla 	do {
137*e7818584SSudeep Holla 		dev = bus_find_next_device(&ffa_bus_type, dev);
138*e7818584SSudeep Holla 		tmp_dev = to_ffa_dev(dev);
139*e7818584SSudeep Holla 		if (tmp_dev == ffa_dev) {
140*e7818584SSudeep Holla 			valid = true;
141*e7818584SSudeep Holla 			break;
142*e7818584SSudeep Holla 		}
143*e7818584SSudeep Holla 		put_device(dev);
144*e7818584SSudeep Holla 	} while (dev);
145*e7818584SSudeep Holla 
146*e7818584SSudeep Holla 	put_device(dev);
147*e7818584SSudeep Holla 
148*e7818584SSudeep Holla 	return valid;
149*e7818584SSudeep Holla }
150*e7818584SSudeep Holla 
151*e7818584SSudeep Holla struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id)
152*e7818584SSudeep Holla {
153*e7818584SSudeep Holla 	int ret;
154*e7818584SSudeep Holla 	struct device *dev;
155*e7818584SSudeep Holla 	struct ffa_device *ffa_dev;
156*e7818584SSudeep Holla 
157*e7818584SSudeep Holla 	ffa_dev = kzalloc(sizeof(*ffa_dev), GFP_KERNEL);
158*e7818584SSudeep Holla 	if (!ffa_dev)
159*e7818584SSudeep Holla 		return NULL;
160*e7818584SSudeep Holla 
161*e7818584SSudeep Holla 	dev = &ffa_dev->dev;
162*e7818584SSudeep Holla 	dev->bus = &ffa_bus_type;
163*e7818584SSudeep Holla 	dev->release = ffa_release_device;
164*e7818584SSudeep Holla 	dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id);
165*e7818584SSudeep Holla 
166*e7818584SSudeep Holla 	ffa_dev->vm_id = vm_id;
167*e7818584SSudeep Holla 	uuid_copy(&ffa_dev->uuid, uuid);
168*e7818584SSudeep Holla 
169*e7818584SSudeep Holla 	ret = device_register(&ffa_dev->dev);
170*e7818584SSudeep Holla 	if (ret) {
171*e7818584SSudeep Holla 		dev_err(dev, "unable to register device %s err=%d\n",
172*e7818584SSudeep Holla 			dev_name(dev), ret);
173*e7818584SSudeep Holla 		put_device(dev);
174*e7818584SSudeep Holla 		return NULL;
175*e7818584SSudeep Holla 	}
176*e7818584SSudeep Holla 
177*e7818584SSudeep Holla 	return ffa_dev;
178*e7818584SSudeep Holla }
179*e7818584SSudeep Holla EXPORT_SYMBOL_GPL(ffa_device_register);
180*e7818584SSudeep Holla 
181*e7818584SSudeep Holla void ffa_device_unregister(struct ffa_device *ffa_dev)
182*e7818584SSudeep Holla {
183*e7818584SSudeep Holla 	if (!ffa_dev)
184*e7818584SSudeep Holla 		return;
185*e7818584SSudeep Holla 
186*e7818584SSudeep Holla 	device_unregister(&ffa_dev->dev);
187*e7818584SSudeep Holla }
188*e7818584SSudeep Holla EXPORT_SYMBOL_GPL(ffa_device_unregister);
189*e7818584SSudeep Holla 
190*e7818584SSudeep Holla static int __init arm_ffa_bus_init(void)
191*e7818584SSudeep Holla {
192*e7818584SSudeep Holla 	return bus_register(&ffa_bus_type);
193*e7818584SSudeep Holla }
194*e7818584SSudeep Holla module_init(arm_ffa_bus_init);
195*e7818584SSudeep Holla 
196*e7818584SSudeep Holla static void __exit arm_ffa_bus_exit(void)
197*e7818584SSudeep Holla {
198*e7818584SSudeep Holla 	ffa_devices_unregister();
199*e7818584SSudeep Holla 	bus_unregister(&ffa_bus_type);
200*e7818584SSudeep Holla }
201*e7818584SSudeep Holla 
202*e7818584SSudeep Holla module_exit(arm_ffa_bus_exit);
203*e7818584SSudeep Holla 
204*e7818584SSudeep Holla MODULE_ALIAS("arm-ffa-bus");
205*e7818584SSudeep Holla MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
206*e7818584SSudeep Holla MODULE_DESCRIPTION("Arm FF-A bus driver");
207*e7818584SSudeep Holla MODULE_LICENSE("GPL v2");
208