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