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