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