1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2011-2017, The Linux Foundation 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/errno.h> 8 #include <linux/slab.h> 9 #include <linux/init.h> 10 #include <linux/slimbus.h> 11 12 static const struct slim_device_id *slim_match(const struct slim_device_id *id, 13 const struct slim_device *sbdev) 14 { 15 while (id->manf_id != 0 || id->prod_code != 0) { 16 if (id->manf_id == sbdev->e_addr.manf_id && 17 id->prod_code == sbdev->e_addr.prod_code) 18 return id; 19 id++; 20 } 21 return NULL; 22 } 23 24 static int slim_device_match(struct device *dev, struct device_driver *drv) 25 { 26 struct slim_device *sbdev = to_slim_device(dev); 27 struct slim_driver *sbdrv = to_slim_driver(drv); 28 29 return !!slim_match(sbdrv->id_table, sbdev); 30 } 31 32 static int slim_device_probe(struct device *dev) 33 { 34 struct slim_device *sbdev = to_slim_device(dev); 35 struct slim_driver *sbdrv = to_slim_driver(dev->driver); 36 37 return sbdrv->probe(sbdev); 38 } 39 40 static int slim_device_remove(struct device *dev) 41 { 42 struct slim_device *sbdev = to_slim_device(dev); 43 struct slim_driver *sbdrv; 44 45 if (dev->driver) { 46 sbdrv = to_slim_driver(dev->driver); 47 if (sbdrv->remove) 48 sbdrv->remove(sbdev); 49 } 50 51 return 0; 52 } 53 54 struct bus_type slimbus_bus = { 55 .name = "slimbus", 56 .match = slim_device_match, 57 .probe = slim_device_probe, 58 .remove = slim_device_remove, 59 }; 60 EXPORT_SYMBOL_GPL(slimbus_bus); 61 62 /* 63 * __slim_driver_register() - Client driver registration with SLIMbus 64 * 65 * @drv:Client driver to be associated with client-device. 66 * @owner: owning module/driver 67 * 68 * This API will register the client driver with the SLIMbus 69 * It is called from the driver's module-init function. 70 */ 71 int __slim_driver_register(struct slim_driver *drv, struct module *owner) 72 { 73 /* ID table and probe are mandatory */ 74 if (!drv->id_table || !drv->probe) 75 return -EINVAL; 76 77 drv->driver.bus = &slimbus_bus; 78 drv->driver.owner = owner; 79 80 return driver_register(&drv->driver); 81 } 82 EXPORT_SYMBOL_GPL(__slim_driver_register); 83 84 /* 85 * slim_driver_unregister() - Undo effect of slim_driver_register 86 * 87 * @drv: Client driver to be unregistered 88 */ 89 void slim_driver_unregister(struct slim_driver *drv) 90 { 91 driver_unregister(&drv->driver); 92 } 93 EXPORT_SYMBOL_GPL(slim_driver_unregister); 94 95 static void __exit slimbus_exit(void) 96 { 97 bus_unregister(&slimbus_bus); 98 } 99 module_exit(slimbus_exit); 100 101 static int __init slimbus_init(void) 102 { 103 return bus_register(&slimbus_bus); 104 } 105 postcore_initcall(slimbus_init); 106 107 MODULE_LICENSE("GPL v2"); 108 MODULE_DESCRIPTION("SLIMbus core"); 109