17de3697eSDave Ertman // SPDX-License-Identifier: GPL-2.0-only 27de3697eSDave Ertman /* 37de3697eSDave Ertman * Copyright (c) 2019-2020 Intel Corporation 47de3697eSDave Ertman * 57de3697eSDave Ertman * Please see Documentation/driver-api/auxiliary_bus.rst for more information. 67de3697eSDave Ertman */ 77de3697eSDave Ertman 87de3697eSDave Ertman #define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__ 97de3697eSDave Ertman 107de3697eSDave Ertman #include <linux/device.h> 117de3697eSDave Ertman #include <linux/init.h> 127bbb79ffSGreg Kroah-Hartman #include <linux/slab.h> 137de3697eSDave Ertman #include <linux/module.h> 147de3697eSDave Ertman #include <linux/pm_domain.h> 157de3697eSDave Ertman #include <linux/pm_runtime.h> 167de3697eSDave Ertman #include <linux/string.h> 177de3697eSDave Ertman #include <linux/auxiliary_bus.h> 187de3697eSDave Ertman 197de3697eSDave Ertman static const struct auxiliary_device_id *auxiliary_match_id(const struct auxiliary_device_id *id, 207de3697eSDave Ertman const struct auxiliary_device *auxdev) 217de3697eSDave Ertman { 227de3697eSDave Ertman for (; id->name[0]; id++) { 237de3697eSDave Ertman const char *p = strrchr(dev_name(&auxdev->dev), '.'); 247de3697eSDave Ertman int match_size; 257de3697eSDave Ertman 267de3697eSDave Ertman if (!p) 277de3697eSDave Ertman continue; 287de3697eSDave Ertman match_size = p - dev_name(&auxdev->dev); 297de3697eSDave Ertman 307de3697eSDave Ertman /* use dev_name(&auxdev->dev) prefix before last '.' char to match to */ 317de3697eSDave Ertman if (strlen(id->name) == match_size && 327de3697eSDave Ertman !strncmp(dev_name(&auxdev->dev), id->name, match_size)) 337de3697eSDave Ertman return id; 347de3697eSDave Ertman } 357de3697eSDave Ertman return NULL; 367de3697eSDave Ertman } 377de3697eSDave Ertman 387de3697eSDave Ertman static int auxiliary_match(struct device *dev, struct device_driver *drv) 397de3697eSDave Ertman { 407de3697eSDave Ertman struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 417de3697eSDave Ertman struct auxiliary_driver *auxdrv = to_auxiliary_drv(drv); 427de3697eSDave Ertman 437de3697eSDave Ertman return !!auxiliary_match_id(auxdrv->id_table, auxdev); 447de3697eSDave Ertman } 457de3697eSDave Ertman 467de3697eSDave Ertman static int auxiliary_uevent(struct device *dev, struct kobj_uevent_env *env) 477de3697eSDave Ertman { 487de3697eSDave Ertman const char *name, *p; 497de3697eSDave Ertman 507de3697eSDave Ertman name = dev_name(dev); 517de3697eSDave Ertman p = strrchr(name, '.'); 527de3697eSDave Ertman 537de3697eSDave Ertman return add_uevent_var(env, "MODALIAS=%s%.*s", AUXILIARY_MODULE_PREFIX, (int)(p - name), 547de3697eSDave Ertman name); 557de3697eSDave Ertman } 567de3697eSDave Ertman 577de3697eSDave Ertman static const struct dev_pm_ops auxiliary_dev_pm_ops = { 587de3697eSDave Ertman SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend, pm_generic_runtime_resume, NULL) 597de3697eSDave Ertman SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume) 607de3697eSDave Ertman }; 617de3697eSDave Ertman 627de3697eSDave Ertman static int auxiliary_bus_probe(struct device *dev) 637de3697eSDave Ertman { 647de3697eSDave Ertman struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver); 657de3697eSDave Ertman struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 667de3697eSDave Ertman int ret; 677de3697eSDave Ertman 687de3697eSDave Ertman ret = dev_pm_domain_attach(dev, true); 697de3697eSDave Ertman if (ret) { 707de3697eSDave Ertman dev_warn(dev, "Failed to attach to PM Domain : %d\n", ret); 717de3697eSDave Ertman return ret; 727de3697eSDave Ertman } 737de3697eSDave Ertman 747de3697eSDave Ertman ret = auxdrv->probe(auxdev, auxiliary_match_id(auxdrv->id_table, auxdev)); 757de3697eSDave Ertman if (ret) 767de3697eSDave Ertman dev_pm_domain_detach(dev, true); 777de3697eSDave Ertman 787de3697eSDave Ertman return ret; 797de3697eSDave Ertman } 807de3697eSDave Ertman 817de3697eSDave Ertman static int auxiliary_bus_remove(struct device *dev) 827de3697eSDave Ertman { 837de3697eSDave Ertman struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver); 847de3697eSDave Ertman struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 857de3697eSDave Ertman 867de3697eSDave Ertman if (auxdrv->remove) 87*8142a46cSGreg Kroah-Hartman auxdrv->remove(auxdev); 887de3697eSDave Ertman dev_pm_domain_detach(dev, true); 897de3697eSDave Ertman 90*8142a46cSGreg Kroah-Hartman return 0; 917de3697eSDave Ertman } 927de3697eSDave Ertman 937de3697eSDave Ertman static void auxiliary_bus_shutdown(struct device *dev) 947de3697eSDave Ertman { 957de3697eSDave Ertman struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver); 967de3697eSDave Ertman struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 977de3697eSDave Ertman 987de3697eSDave Ertman if (auxdrv->shutdown) 997de3697eSDave Ertman auxdrv->shutdown(auxdev); 1007de3697eSDave Ertman } 1017de3697eSDave Ertman 1027de3697eSDave Ertman static struct bus_type auxiliary_bus_type = { 1037de3697eSDave Ertman .name = "auxiliary", 1047de3697eSDave Ertman .probe = auxiliary_bus_probe, 1057de3697eSDave Ertman .remove = auxiliary_bus_remove, 1067de3697eSDave Ertman .shutdown = auxiliary_bus_shutdown, 1077de3697eSDave Ertman .match = auxiliary_match, 1087de3697eSDave Ertman .uevent = auxiliary_uevent, 1097de3697eSDave Ertman .pm = &auxiliary_dev_pm_ops, 1107de3697eSDave Ertman }; 1117de3697eSDave Ertman 1127de3697eSDave Ertman /** 1137de3697eSDave Ertman * auxiliary_device_init - check auxiliary_device and initialize 1147de3697eSDave Ertman * @auxdev: auxiliary device struct 1157de3697eSDave Ertman * 1167de3697eSDave Ertman * This is the first step in the two-step process to register an auxiliary_device. 1177de3697eSDave Ertman * 1187de3697eSDave Ertman * When this function returns an error code, then the device_initialize will *not* have 1197de3697eSDave Ertman * been performed, and the caller will be responsible to free any memory allocated for the 1207de3697eSDave Ertman * auxiliary_device in the error path directly. 1217de3697eSDave Ertman * 1227de3697eSDave Ertman * It returns 0 on success. On success, the device_initialize has been performed. After this 1237de3697eSDave Ertman * point any error unwinding will need to include a call to auxiliary_device_uninit(). 1247de3697eSDave Ertman * In this post-initialize error scenario, a call to the device's .release callback will be 1257de3697eSDave Ertman * triggered, and all memory clean-up is expected to be handled there. 1267de3697eSDave Ertman */ 1277de3697eSDave Ertman int auxiliary_device_init(struct auxiliary_device *auxdev) 1287de3697eSDave Ertman { 1297de3697eSDave Ertman struct device *dev = &auxdev->dev; 1307de3697eSDave Ertman 1317de3697eSDave Ertman if (!dev->parent) { 1327de3697eSDave Ertman pr_err("auxiliary_device has a NULL dev->parent\n"); 1337de3697eSDave Ertman return -EINVAL; 1347de3697eSDave Ertman } 1357de3697eSDave Ertman 1367de3697eSDave Ertman if (!auxdev->name) { 1377de3697eSDave Ertman pr_err("auxiliary_device has a NULL name\n"); 1387de3697eSDave Ertman return -EINVAL; 1397de3697eSDave Ertman } 1407de3697eSDave Ertman 1417de3697eSDave Ertman dev->bus = &auxiliary_bus_type; 1427de3697eSDave Ertman device_initialize(&auxdev->dev); 1437de3697eSDave Ertman return 0; 1447de3697eSDave Ertman } 1457de3697eSDave Ertman EXPORT_SYMBOL_GPL(auxiliary_device_init); 1467de3697eSDave Ertman 1477de3697eSDave Ertman /** 1487de3697eSDave Ertman * __auxiliary_device_add - add an auxiliary bus device 1497de3697eSDave Ertman * @auxdev: auxiliary bus device to add to the bus 1507de3697eSDave Ertman * @modname: name of the parent device's driver module 1517de3697eSDave Ertman * 1527de3697eSDave Ertman * This is the second step in the two-step process to register an auxiliary_device. 1537de3697eSDave Ertman * 1547de3697eSDave Ertman * This function must be called after a successful call to auxiliary_device_init(), which 1557de3697eSDave Ertman * will perform the device_initialize. This means that if this returns an error code, then a 1567de3697eSDave Ertman * call to auxiliary_device_uninit() must be performed so that the .release callback will 1577de3697eSDave Ertman * be triggered to free the memory associated with the auxiliary_device. 1587de3697eSDave Ertman * 1597de3697eSDave Ertman * The expectation is that users will call the "auxiliary_device_add" macro so that the caller's 1607de3697eSDave Ertman * KBUILD_MODNAME is automatically inserted for the modname parameter. Only if a user requires 1617de3697eSDave Ertman * a custom name would this version be called directly. 1627de3697eSDave Ertman */ 1637de3697eSDave Ertman int __auxiliary_device_add(struct auxiliary_device *auxdev, const char *modname) 1647de3697eSDave Ertman { 1657de3697eSDave Ertman struct device *dev = &auxdev->dev; 1667de3697eSDave Ertman int ret; 1677de3697eSDave Ertman 1687de3697eSDave Ertman if (!modname) { 1697de3697eSDave Ertman pr_err("auxiliary device modname is NULL\n"); 1707de3697eSDave Ertman return -EINVAL; 1717de3697eSDave Ertman } 1727de3697eSDave Ertman 1737de3697eSDave Ertman ret = dev_set_name(dev, "%s.%s.%d", modname, auxdev->name, auxdev->id); 1747de3697eSDave Ertman if (ret) { 1757de3697eSDave Ertman pr_err("auxiliary device dev_set_name failed: %d\n", ret); 1767de3697eSDave Ertman return ret; 1777de3697eSDave Ertman } 1787de3697eSDave Ertman 1797de3697eSDave Ertman ret = device_add(dev); 1807de3697eSDave Ertman if (ret) 1817de3697eSDave Ertman dev_err(dev, "adding auxiliary device failed!: %d\n", ret); 1827de3697eSDave Ertman 1837de3697eSDave Ertman return ret; 1847de3697eSDave Ertman } 1857de3697eSDave Ertman EXPORT_SYMBOL_GPL(__auxiliary_device_add); 1867de3697eSDave Ertman 1877de3697eSDave Ertman /** 1887de3697eSDave Ertman * auxiliary_find_device - auxiliary device iterator for locating a particular device. 1897de3697eSDave Ertman * @start: Device to begin with 1907de3697eSDave Ertman * @data: Data to pass to match function 1917de3697eSDave Ertman * @match: Callback function to check device 1927de3697eSDave Ertman * 1937de3697eSDave Ertman * This function returns a reference to a device that is 'found' 1947de3697eSDave Ertman * for later use, as determined by the @match callback. 1957de3697eSDave Ertman * 1967de3697eSDave Ertman * The callback should return 0 if the device doesn't match and non-zero 1977de3697eSDave Ertman * if it does. If the callback returns non-zero, this function will 1987de3697eSDave Ertman * return to the caller and not iterate over any more devices. 1997de3697eSDave Ertman */ 2007de3697eSDave Ertman struct auxiliary_device * 2017de3697eSDave Ertman auxiliary_find_device(struct device *start, const void *data, 2027de3697eSDave Ertman int (*match)(struct device *dev, const void *data)) 2037de3697eSDave Ertman { 2047de3697eSDave Ertman struct device *dev; 2057de3697eSDave Ertman 2067de3697eSDave Ertman dev = bus_find_device(&auxiliary_bus_type, start, data, match); 2077de3697eSDave Ertman if (!dev) 2087de3697eSDave Ertman return NULL; 2097de3697eSDave Ertman 2107de3697eSDave Ertman return to_auxiliary_dev(dev); 2117de3697eSDave Ertman } 2127de3697eSDave Ertman EXPORT_SYMBOL_GPL(auxiliary_find_device); 2137de3697eSDave Ertman 2147de3697eSDave Ertman /** 2157de3697eSDave Ertman * __auxiliary_driver_register - register a driver for auxiliary bus devices 2167de3697eSDave Ertman * @auxdrv: auxiliary_driver structure 2177de3697eSDave Ertman * @owner: owning module/driver 2187de3697eSDave Ertman * @modname: KBUILD_MODNAME for parent driver 2197de3697eSDave Ertman */ 2207de3697eSDave Ertman int __auxiliary_driver_register(struct auxiliary_driver *auxdrv, struct module *owner, 2217de3697eSDave Ertman const char *modname) 2227de3697eSDave Ertman { 2237de3697eSDave Ertman if (WARN_ON(!auxdrv->probe) || WARN_ON(!auxdrv->id_table)) 2247de3697eSDave Ertman return -EINVAL; 2257de3697eSDave Ertman 2267de3697eSDave Ertman if (auxdrv->name) 2277de3697eSDave Ertman auxdrv->driver.name = kasprintf(GFP_KERNEL, "%s.%s", modname, auxdrv->name); 2287de3697eSDave Ertman else 2297de3697eSDave Ertman auxdrv->driver.name = kasprintf(GFP_KERNEL, "%s", modname); 2307de3697eSDave Ertman if (!auxdrv->driver.name) 2317de3697eSDave Ertman return -ENOMEM; 2327de3697eSDave Ertman 2337de3697eSDave Ertman auxdrv->driver.owner = owner; 2347de3697eSDave Ertman auxdrv->driver.bus = &auxiliary_bus_type; 2357de3697eSDave Ertman auxdrv->driver.mod_name = modname; 2367de3697eSDave Ertman 2377de3697eSDave Ertman return driver_register(&auxdrv->driver); 2387de3697eSDave Ertman } 2397de3697eSDave Ertman EXPORT_SYMBOL_GPL(__auxiliary_driver_register); 2407de3697eSDave Ertman 2417de3697eSDave Ertman /** 2427de3697eSDave Ertman * auxiliary_driver_unregister - unregister a driver 2437de3697eSDave Ertman * @auxdrv: auxiliary_driver structure 2447de3697eSDave Ertman */ 2457de3697eSDave Ertman void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv) 2467de3697eSDave Ertman { 2477de3697eSDave Ertman driver_unregister(&auxdrv->driver); 2487de3697eSDave Ertman kfree(auxdrv->driver.name); 2497de3697eSDave Ertman } 2507de3697eSDave Ertman EXPORT_SYMBOL_GPL(auxiliary_driver_unregister); 2517de3697eSDave Ertman 2527de3697eSDave Ertman static int __init auxiliary_bus_init(void) 2537de3697eSDave Ertman { 2547de3697eSDave Ertman return bus_register(&auxiliary_bus_type); 2557de3697eSDave Ertman } 2567de3697eSDave Ertman 2577de3697eSDave Ertman static void __exit auxiliary_bus_exit(void) 2587de3697eSDave Ertman { 2597de3697eSDave Ertman bus_unregister(&auxiliary_bus_type); 2607de3697eSDave Ertman } 2617de3697eSDave Ertman 2627de3697eSDave Ertman module_init(auxiliary_bus_init); 2637de3697eSDave Ertman module_exit(auxiliary_bus_exit); 2647de3697eSDave Ertman 2657de3697eSDave Ertman MODULE_LICENSE("GPL v2"); 2667de3697eSDave Ertman MODULE_DESCRIPTION("Auxiliary Bus"); 2677de3697eSDave Ertman MODULE_AUTHOR("David Ertman <david.m.ertman@intel.com>"); 2687de3697eSDave Ertman MODULE_AUTHOR("Kiran Patil <kiran.patil@intel.com>"); 269