1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2021 ARM Ltd.
6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8 #include <linux/arm_ffa.h>
9 #include <linux/device.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 #include <linux/types.h>
18 #define SCMI_UEVENT_MODALIAS_FMT "arm_ffa:%04x:%pUb"
20 static DEFINE_IDA(ffa_bus_id
);
22 static int ffa_device_match(struct device
*dev
, const struct device_driver
*drv
)
24 const struct ffa_device_id
*id_table
;
25 struct ffa_device
*ffa_dev
;
27 id_table
= to_ffa_driver(drv
)->id_table
;
28 ffa_dev
= to_ffa_dev(dev
);
30 while (!uuid_is_null(&id_table
->uuid
)) {
32 * FF-A v1.0 doesn't provide discovery of UUIDs, just the
33 * partition IDs, so match it unconditionally here and handle
34 * it via the installed bus notifier during driver binding.
36 if (uuid_is_null(&ffa_dev
->uuid
))
39 if (uuid_equal(&ffa_dev
->uuid
, &id_table
->uuid
))
47 static int ffa_device_probe(struct device
*dev
)
49 struct ffa_driver
*ffa_drv
= to_ffa_driver(dev
->driver
);
50 struct ffa_device
*ffa_dev
= to_ffa_dev(dev
);
52 /* UUID can be still NULL with FF-A v1.0, so just skip probing them */
53 if (uuid_is_null(&ffa_dev
->uuid
))
56 return ffa_drv
->probe(ffa_dev
);
59 static void ffa_device_remove(struct device
*dev
)
61 struct ffa_driver
*ffa_drv
= to_ffa_driver(dev
->driver
);
64 ffa_drv
->remove(to_ffa_dev(dev
));
67 static int ffa_device_uevent(const struct device
*dev
, struct kobj_uevent_env
*env
)
69 const struct ffa_device
*ffa_dev
= to_ffa_dev(dev
);
71 return add_uevent_var(env
, "MODALIAS=" SCMI_UEVENT_MODALIAS_FMT
,
72 ffa_dev
->vm_id
, &ffa_dev
->uuid
);
75 static ssize_t
modalias_show(struct device
*dev
,
76 struct device_attribute
*attr
, char *buf
)
78 struct ffa_device
*ffa_dev
= to_ffa_dev(dev
);
80 return sysfs_emit(buf
, SCMI_UEVENT_MODALIAS_FMT
, ffa_dev
->vm_id
,
83 static DEVICE_ATTR_RO(modalias
);
85 static ssize_t
partition_id_show(struct device
*dev
,
86 struct device_attribute
*attr
, char *buf
)
88 struct ffa_device
*ffa_dev
= to_ffa_dev(dev
);
90 return sprintf(buf
, "0x%04x\n", ffa_dev
->vm_id
);
92 static DEVICE_ATTR_RO(partition_id
);
94 static ssize_t
uuid_show(struct device
*dev
, struct device_attribute
*attr
,
97 struct ffa_device
*ffa_dev
= to_ffa_dev(dev
);
99 return sprintf(buf
, "%pUb\n", &ffa_dev
->uuid
);
101 static DEVICE_ATTR_RO(uuid
);
103 static struct attribute
*ffa_device_attributes_attrs
[] = {
104 &dev_attr_partition_id
.attr
,
106 &dev_attr_modalias
.attr
,
109 ATTRIBUTE_GROUPS(ffa_device_attributes
);
111 const struct bus_type ffa_bus_type
= {
113 .match
= ffa_device_match
,
114 .probe
= ffa_device_probe
,
115 .remove
= ffa_device_remove
,
116 .uevent
= ffa_device_uevent
,
117 .dev_groups
= ffa_device_attributes_groups
,
119 EXPORT_SYMBOL_GPL(ffa_bus_type
);
121 int ffa_driver_register(struct ffa_driver
*driver
, struct module
*owner
,
122 const char *mod_name
)
129 driver
->driver
.bus
= &ffa_bus_type
;
130 driver
->driver
.name
= driver
->name
;
131 driver
->driver
.owner
= owner
;
132 driver
->driver
.mod_name
= mod_name
;
134 ret
= driver_register(&driver
->driver
);
136 pr_debug("registered new ffa driver %s\n", driver
->name
);
140 EXPORT_SYMBOL_GPL(ffa_driver_register
);
142 void ffa_driver_unregister(struct ffa_driver
*driver
)
144 driver_unregister(&driver
->driver
);
146 EXPORT_SYMBOL_GPL(ffa_driver_unregister
);
148 static void ffa_release_device(struct device
*dev
)
150 struct ffa_device
*ffa_dev
= to_ffa_dev(dev
);
152 ida_free(&ffa_bus_id
, ffa_dev
->id
);
156 static int __ffa_devices_unregister(struct device
*dev
, void *data
)
158 device_unregister(dev
);
163 static void ffa_devices_unregister(void)
165 bus_for_each_dev(&ffa_bus_type
, NULL
, NULL
,
166 __ffa_devices_unregister
);
169 bool ffa_device_is_valid(struct ffa_device
*ffa_dev
)
172 struct device
*dev
= NULL
;
173 struct ffa_device
*tmp_dev
;
176 dev
= bus_find_next_device(&ffa_bus_type
, dev
);
177 tmp_dev
= to_ffa_dev(dev
);
178 if (tmp_dev
== ffa_dev
) {
190 struct ffa_device
*ffa_device_register(const uuid_t
*uuid
, int vm_id
,
191 const struct ffa_ops
*ops
)
195 struct ffa_device
*ffa_dev
;
197 id
= ida_alloc_min(&ffa_bus_id
, 1, GFP_KERNEL
);
201 ffa_dev
= kzalloc(sizeof(*ffa_dev
), GFP_KERNEL
);
203 ida_free(&ffa_bus_id
, id
);
208 dev
->bus
= &ffa_bus_type
;
209 dev
->release
= ffa_release_device
;
210 dev_set_name(&ffa_dev
->dev
, "arm-ffa-%d", id
);
213 ffa_dev
->vm_id
= vm_id
;
215 uuid_copy(&ffa_dev
->uuid
, uuid
);
217 ret
= device_register(&ffa_dev
->dev
);
219 dev_err(dev
, "unable to register device %s err=%d\n",
227 EXPORT_SYMBOL_GPL(ffa_device_register
);
229 void ffa_device_unregister(struct ffa_device
*ffa_dev
)
234 device_unregister(&ffa_dev
->dev
);
236 EXPORT_SYMBOL_GPL(ffa_device_unregister
);
238 static int __init
arm_ffa_bus_init(void)
240 return bus_register(&ffa_bus_type
);
242 subsys_initcall(arm_ffa_bus_init
);
244 static void __exit
arm_ffa_bus_exit(void)
246 ffa_devices_unregister();
247 bus_unregister(&ffa_bus_type
);
248 ida_destroy(&ffa_bus_id
);
250 module_exit(arm_ffa_bus_exit
);
252 MODULE_ALIAS("ffa-core");
253 MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
254 MODULE_DESCRIPTION("ARM FF-A bus");
255 MODULE_LICENSE("GPL");