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