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