1*7de3697eSDave Ertman // SPDX-License-Identifier: GPL-2.0-only 2*7de3697eSDave Ertman /* 3*7de3697eSDave Ertman * Copyright (c) 2019-2020 Intel Corporation 4*7de3697eSDave Ertman * 5*7de3697eSDave Ertman * Please see Documentation/driver-api/auxiliary_bus.rst for more information. 6*7de3697eSDave Ertman */ 7*7de3697eSDave Ertman 8*7de3697eSDave Ertman #define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__ 9*7de3697eSDave Ertman 10*7de3697eSDave Ertman #include <linux/device.h> 11*7de3697eSDave Ertman #include <linux/init.h> 12*7de3697eSDave Ertman #include <linux/module.h> 13*7de3697eSDave Ertman #include <linux/pm_domain.h> 14*7de3697eSDave Ertman #include <linux/pm_runtime.h> 15*7de3697eSDave Ertman #include <linux/string.h> 16*7de3697eSDave Ertman #include <linux/auxiliary_bus.h> 17*7de3697eSDave Ertman 18*7de3697eSDave Ertman static const struct auxiliary_device_id *auxiliary_match_id(const struct auxiliary_device_id *id, 19*7de3697eSDave Ertman const struct auxiliary_device *auxdev) 20*7de3697eSDave Ertman { 21*7de3697eSDave Ertman for (; id->name[0]; id++) { 22*7de3697eSDave Ertman const char *p = strrchr(dev_name(&auxdev->dev), '.'); 23*7de3697eSDave Ertman int match_size; 24*7de3697eSDave Ertman 25*7de3697eSDave Ertman if (!p) 26*7de3697eSDave Ertman continue; 27*7de3697eSDave Ertman match_size = p - dev_name(&auxdev->dev); 28*7de3697eSDave Ertman 29*7de3697eSDave Ertman /* use dev_name(&auxdev->dev) prefix before last '.' char to match to */ 30*7de3697eSDave Ertman if (strlen(id->name) == match_size && 31*7de3697eSDave Ertman !strncmp(dev_name(&auxdev->dev), id->name, match_size)) 32*7de3697eSDave Ertman return id; 33*7de3697eSDave Ertman } 34*7de3697eSDave Ertman return NULL; 35*7de3697eSDave Ertman } 36*7de3697eSDave Ertman 37*7de3697eSDave Ertman static int auxiliary_match(struct device *dev, struct device_driver *drv) 38*7de3697eSDave Ertman { 39*7de3697eSDave Ertman struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 40*7de3697eSDave Ertman struct auxiliary_driver *auxdrv = to_auxiliary_drv(drv); 41*7de3697eSDave Ertman 42*7de3697eSDave Ertman return !!auxiliary_match_id(auxdrv->id_table, auxdev); 43*7de3697eSDave Ertman } 44*7de3697eSDave Ertman 45*7de3697eSDave Ertman static int auxiliary_uevent(struct device *dev, struct kobj_uevent_env *env) 46*7de3697eSDave Ertman { 47*7de3697eSDave Ertman const char *name, *p; 48*7de3697eSDave Ertman 49*7de3697eSDave Ertman name = dev_name(dev); 50*7de3697eSDave Ertman p = strrchr(name, '.'); 51*7de3697eSDave Ertman 52*7de3697eSDave Ertman return add_uevent_var(env, "MODALIAS=%s%.*s", AUXILIARY_MODULE_PREFIX, (int)(p - name), 53*7de3697eSDave Ertman name); 54*7de3697eSDave Ertman } 55*7de3697eSDave Ertman 56*7de3697eSDave Ertman static const struct dev_pm_ops auxiliary_dev_pm_ops = { 57*7de3697eSDave Ertman SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend, pm_generic_runtime_resume, NULL) 58*7de3697eSDave Ertman SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume) 59*7de3697eSDave Ertman }; 60*7de3697eSDave Ertman 61*7de3697eSDave Ertman static int auxiliary_bus_probe(struct device *dev) 62*7de3697eSDave Ertman { 63*7de3697eSDave Ertman struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver); 64*7de3697eSDave Ertman struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 65*7de3697eSDave Ertman int ret; 66*7de3697eSDave Ertman 67*7de3697eSDave Ertman ret = dev_pm_domain_attach(dev, true); 68*7de3697eSDave Ertman if (ret) { 69*7de3697eSDave Ertman dev_warn(dev, "Failed to attach to PM Domain : %d\n", ret); 70*7de3697eSDave Ertman return ret; 71*7de3697eSDave Ertman } 72*7de3697eSDave Ertman 73*7de3697eSDave Ertman ret = auxdrv->probe(auxdev, auxiliary_match_id(auxdrv->id_table, auxdev)); 74*7de3697eSDave Ertman if (ret) 75*7de3697eSDave Ertman dev_pm_domain_detach(dev, true); 76*7de3697eSDave Ertman 77*7de3697eSDave Ertman return ret; 78*7de3697eSDave Ertman } 79*7de3697eSDave Ertman 80*7de3697eSDave Ertman static int auxiliary_bus_remove(struct device *dev) 81*7de3697eSDave Ertman { 82*7de3697eSDave Ertman struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver); 83*7de3697eSDave Ertman struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 84*7de3697eSDave Ertman int ret = 0; 85*7de3697eSDave Ertman 86*7de3697eSDave Ertman if (auxdrv->remove) 87*7de3697eSDave Ertman ret = auxdrv->remove(auxdev); 88*7de3697eSDave Ertman dev_pm_domain_detach(dev, true); 89*7de3697eSDave Ertman 90*7de3697eSDave Ertman return ret; 91*7de3697eSDave Ertman } 92*7de3697eSDave Ertman 93*7de3697eSDave Ertman static void auxiliary_bus_shutdown(struct device *dev) 94*7de3697eSDave Ertman { 95*7de3697eSDave Ertman struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver); 96*7de3697eSDave Ertman struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 97*7de3697eSDave Ertman 98*7de3697eSDave Ertman if (auxdrv->shutdown) 99*7de3697eSDave Ertman auxdrv->shutdown(auxdev); 100*7de3697eSDave Ertman } 101*7de3697eSDave Ertman 102*7de3697eSDave Ertman static struct bus_type auxiliary_bus_type = { 103*7de3697eSDave Ertman .name = "auxiliary", 104*7de3697eSDave Ertman .probe = auxiliary_bus_probe, 105*7de3697eSDave Ertman .remove = auxiliary_bus_remove, 106*7de3697eSDave Ertman .shutdown = auxiliary_bus_shutdown, 107*7de3697eSDave Ertman .match = auxiliary_match, 108*7de3697eSDave Ertman .uevent = auxiliary_uevent, 109*7de3697eSDave Ertman .pm = &auxiliary_dev_pm_ops, 110*7de3697eSDave Ertman }; 111*7de3697eSDave Ertman 112*7de3697eSDave Ertman /** 113*7de3697eSDave Ertman * auxiliary_device_init - check auxiliary_device and initialize 114*7de3697eSDave Ertman * @auxdev: auxiliary device struct 115*7de3697eSDave Ertman * 116*7de3697eSDave Ertman * This is the first step in the two-step process to register an auxiliary_device. 117*7de3697eSDave Ertman * 118*7de3697eSDave Ertman * When this function returns an error code, then the device_initialize will *not* have 119*7de3697eSDave Ertman * been performed, and the caller will be responsible to free any memory allocated for the 120*7de3697eSDave Ertman * auxiliary_device in the error path directly. 121*7de3697eSDave Ertman * 122*7de3697eSDave Ertman * It returns 0 on success. On success, the device_initialize has been performed. After this 123*7de3697eSDave Ertman * point any error unwinding will need to include a call to auxiliary_device_uninit(). 124*7de3697eSDave Ertman * In this post-initialize error scenario, a call to the device's .release callback will be 125*7de3697eSDave Ertman * triggered, and all memory clean-up is expected to be handled there. 126*7de3697eSDave Ertman */ 127*7de3697eSDave Ertman int auxiliary_device_init(struct auxiliary_device *auxdev) 128*7de3697eSDave Ertman { 129*7de3697eSDave Ertman struct device *dev = &auxdev->dev; 130*7de3697eSDave Ertman 131*7de3697eSDave Ertman if (!dev->parent) { 132*7de3697eSDave Ertman pr_err("auxiliary_device has a NULL dev->parent\n"); 133*7de3697eSDave Ertman return -EINVAL; 134*7de3697eSDave Ertman } 135*7de3697eSDave Ertman 136*7de3697eSDave Ertman if (!auxdev->name) { 137*7de3697eSDave Ertman pr_err("auxiliary_device has a NULL name\n"); 138*7de3697eSDave Ertman return -EINVAL; 139*7de3697eSDave Ertman } 140*7de3697eSDave Ertman 141*7de3697eSDave Ertman dev->bus = &auxiliary_bus_type; 142*7de3697eSDave Ertman device_initialize(&auxdev->dev); 143*7de3697eSDave Ertman return 0; 144*7de3697eSDave Ertman } 145*7de3697eSDave Ertman EXPORT_SYMBOL_GPL(auxiliary_device_init); 146*7de3697eSDave Ertman 147*7de3697eSDave Ertman /** 148*7de3697eSDave Ertman * __auxiliary_device_add - add an auxiliary bus device 149*7de3697eSDave Ertman * @auxdev: auxiliary bus device to add to the bus 150*7de3697eSDave Ertman * @modname: name of the parent device's driver module 151*7de3697eSDave Ertman * 152*7de3697eSDave Ertman * This is the second step in the two-step process to register an auxiliary_device. 153*7de3697eSDave Ertman * 154*7de3697eSDave Ertman * This function must be called after a successful call to auxiliary_device_init(), which 155*7de3697eSDave Ertman * will perform the device_initialize. This means that if this returns an error code, then a 156*7de3697eSDave Ertman * call to auxiliary_device_uninit() must be performed so that the .release callback will 157*7de3697eSDave Ertman * be triggered to free the memory associated with the auxiliary_device. 158*7de3697eSDave Ertman * 159*7de3697eSDave Ertman * The expectation is that users will call the "auxiliary_device_add" macro so that the caller's 160*7de3697eSDave Ertman * KBUILD_MODNAME is automatically inserted for the modname parameter. Only if a user requires 161*7de3697eSDave Ertman * a custom name would this version be called directly. 162*7de3697eSDave Ertman */ 163*7de3697eSDave Ertman int __auxiliary_device_add(struct auxiliary_device *auxdev, const char *modname) 164*7de3697eSDave Ertman { 165*7de3697eSDave Ertman struct device *dev = &auxdev->dev; 166*7de3697eSDave Ertman int ret; 167*7de3697eSDave Ertman 168*7de3697eSDave Ertman if (!modname) { 169*7de3697eSDave Ertman pr_err("auxiliary device modname is NULL\n"); 170*7de3697eSDave Ertman return -EINVAL; 171*7de3697eSDave Ertman } 172*7de3697eSDave Ertman 173*7de3697eSDave Ertman ret = dev_set_name(dev, "%s.%s.%d", modname, auxdev->name, auxdev->id); 174*7de3697eSDave Ertman if (ret) { 175*7de3697eSDave Ertman pr_err("auxiliary device dev_set_name failed: %d\n", ret); 176*7de3697eSDave Ertman return ret; 177*7de3697eSDave Ertman } 178*7de3697eSDave Ertman 179*7de3697eSDave Ertman ret = device_add(dev); 180*7de3697eSDave Ertman if (ret) 181*7de3697eSDave Ertman dev_err(dev, "adding auxiliary device failed!: %d\n", ret); 182*7de3697eSDave Ertman 183*7de3697eSDave Ertman return ret; 184*7de3697eSDave Ertman } 185*7de3697eSDave Ertman EXPORT_SYMBOL_GPL(__auxiliary_device_add); 186*7de3697eSDave Ertman 187*7de3697eSDave Ertman /** 188*7de3697eSDave Ertman * auxiliary_find_device - auxiliary device iterator for locating a particular device. 189*7de3697eSDave Ertman * @start: Device to begin with 190*7de3697eSDave Ertman * @data: Data to pass to match function 191*7de3697eSDave Ertman * @match: Callback function to check device 192*7de3697eSDave Ertman * 193*7de3697eSDave Ertman * This function returns a reference to a device that is 'found' 194*7de3697eSDave Ertman * for later use, as determined by the @match callback. 195*7de3697eSDave Ertman * 196*7de3697eSDave Ertman * The callback should return 0 if the device doesn't match and non-zero 197*7de3697eSDave Ertman * if it does. If the callback returns non-zero, this function will 198*7de3697eSDave Ertman * return to the caller and not iterate over any more devices. 199*7de3697eSDave Ertman */ 200*7de3697eSDave Ertman struct auxiliary_device * 201*7de3697eSDave Ertman auxiliary_find_device(struct device *start, const void *data, 202*7de3697eSDave Ertman int (*match)(struct device *dev, const void *data)) 203*7de3697eSDave Ertman { 204*7de3697eSDave Ertman struct device *dev; 205*7de3697eSDave Ertman 206*7de3697eSDave Ertman dev = bus_find_device(&auxiliary_bus_type, start, data, match); 207*7de3697eSDave Ertman if (!dev) 208*7de3697eSDave Ertman return NULL; 209*7de3697eSDave Ertman 210*7de3697eSDave Ertman return to_auxiliary_dev(dev); 211*7de3697eSDave Ertman } 212*7de3697eSDave Ertman EXPORT_SYMBOL_GPL(auxiliary_find_device); 213*7de3697eSDave Ertman 214*7de3697eSDave Ertman /** 215*7de3697eSDave Ertman * __auxiliary_driver_register - register a driver for auxiliary bus devices 216*7de3697eSDave Ertman * @auxdrv: auxiliary_driver structure 217*7de3697eSDave Ertman * @owner: owning module/driver 218*7de3697eSDave Ertman * @modname: KBUILD_MODNAME for parent driver 219*7de3697eSDave Ertman */ 220*7de3697eSDave Ertman int __auxiliary_driver_register(struct auxiliary_driver *auxdrv, struct module *owner, 221*7de3697eSDave Ertman const char *modname) 222*7de3697eSDave Ertman { 223*7de3697eSDave Ertman if (WARN_ON(!auxdrv->probe) || WARN_ON(!auxdrv->id_table)) 224*7de3697eSDave Ertman return -EINVAL; 225*7de3697eSDave Ertman 226*7de3697eSDave Ertman if (auxdrv->name) 227*7de3697eSDave Ertman auxdrv->driver.name = kasprintf(GFP_KERNEL, "%s.%s", modname, auxdrv->name); 228*7de3697eSDave Ertman else 229*7de3697eSDave Ertman auxdrv->driver.name = kasprintf(GFP_KERNEL, "%s", modname); 230*7de3697eSDave Ertman if (!auxdrv->driver.name) 231*7de3697eSDave Ertman return -ENOMEM; 232*7de3697eSDave Ertman 233*7de3697eSDave Ertman auxdrv->driver.owner = owner; 234*7de3697eSDave Ertman auxdrv->driver.bus = &auxiliary_bus_type; 235*7de3697eSDave Ertman auxdrv->driver.mod_name = modname; 236*7de3697eSDave Ertman 237*7de3697eSDave Ertman return driver_register(&auxdrv->driver); 238*7de3697eSDave Ertman } 239*7de3697eSDave Ertman EXPORT_SYMBOL_GPL(__auxiliary_driver_register); 240*7de3697eSDave Ertman 241*7de3697eSDave Ertman /** 242*7de3697eSDave Ertman * auxiliary_driver_unregister - unregister a driver 243*7de3697eSDave Ertman * @auxdrv: auxiliary_driver structure 244*7de3697eSDave Ertman */ 245*7de3697eSDave Ertman void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv) 246*7de3697eSDave Ertman { 247*7de3697eSDave Ertman driver_unregister(&auxdrv->driver); 248*7de3697eSDave Ertman kfree(auxdrv->driver.name); 249*7de3697eSDave Ertman } 250*7de3697eSDave Ertman EXPORT_SYMBOL_GPL(auxiliary_driver_unregister); 251*7de3697eSDave Ertman 252*7de3697eSDave Ertman static int __init auxiliary_bus_init(void) 253*7de3697eSDave Ertman { 254*7de3697eSDave Ertman return bus_register(&auxiliary_bus_type); 255*7de3697eSDave Ertman } 256*7de3697eSDave Ertman 257*7de3697eSDave Ertman static void __exit auxiliary_bus_exit(void) 258*7de3697eSDave Ertman { 259*7de3697eSDave Ertman bus_unregister(&auxiliary_bus_type); 260*7de3697eSDave Ertman } 261*7de3697eSDave Ertman 262*7de3697eSDave Ertman module_init(auxiliary_bus_init); 263*7de3697eSDave Ertman module_exit(auxiliary_bus_exit); 264*7de3697eSDave Ertman 265*7de3697eSDave Ertman MODULE_LICENSE("GPL v2"); 266*7de3697eSDave Ertman MODULE_DESCRIPTION("Auxiliary Bus"); 267*7de3697eSDave Ertman MODULE_AUTHOR("David Ertman <david.m.ertman@intel.com>"); 268*7de3697eSDave Ertman MODULE_AUTHOR("Kiran Patil <kiran.patil@intel.com>"); 269