| /* SPDX-License-Identifier: GPL-2.0-only */ |
| /* |
| * Copyright (c) 2019-2020 Intel Corporation |
| * |
| * Please see Documentation/driver-api/auxiliary_bus.rst for more information. |
| */ |
| |
| #ifndef _AUXILIARY_BUS_H_ |
| #define _AUXILIARY_BUS_H_ |
| |
| #include <linux/device.h> |
| #include <linux/mod_devicetable.h> |
| |
| /** |
| * DOC: DEVICE_LIFESPAN |
| * |
| * The registering driver is the entity that allocates memory for the |
| * auxiliary_device and registers it on the auxiliary bus. It is important to |
| * note that, as opposed to the platform bus, the registering driver is wholly |
| * responsible for the management of the memory used for the device object. |
| * |
| * To be clear the memory for the auxiliary_device is freed in the release() |
| * callback defined by the registering driver. The registering driver should |
| * only call auxiliary_device_delete() and then auxiliary_device_uninit() when |
| * it is done with the device. The release() function is then automatically |
| * called if and when other code releases their reference to the devices. |
| * |
| * A parent object, defined in the shared header file, contains the |
| * auxiliary_device. It also contains a pointer to the shared object(s), which |
| * also is defined in the shared header. Both the parent object and the shared |
| * object(s) are allocated by the registering driver. This layout allows the |
| * auxiliary_driver's registering module to perform a container_of() call to go |
| * from the pointer to the auxiliary_device, that is passed during the call to |
| * the auxiliary_driver's probe function, up to the parent object, and then |
| * have access to the shared object(s). |
| * |
| * The memory for the shared object(s) must have a lifespan equal to, or |
| * greater than, the lifespan of the memory for the auxiliary_device. The |
| * auxiliary_driver should only consider that the shared object is valid as |
| * long as the auxiliary_device is still registered on the auxiliary bus. It |
| * is up to the registering driver to manage (e.g. free or keep available) the |
| * memory for the shared object beyond the life of the auxiliary_device. |
| * |
| * The registering driver must unregister all auxiliary devices before its own |
| * driver.remove() is completed. An easy way to ensure this is to use the |
| * devm_add_action_or_reset() call to register a function against the parent |
| * device which unregisters the auxiliary device object(s). |
| * |
| * Finally, any operations which operate on the auxiliary devices must continue |
| * to function (if only to return an error) after the registering driver |
| * unregisters the auxiliary device. |
| */ |
| |
| /** |
| * struct auxiliary_device - auxiliary device object. |
| * @dev: Device, |
| * The release and parent fields of the device structure must be filled |
| * in |
| * @name: Match name found by the auxiliary device driver, |
| * @id: unique identitier if multiple devices of the same name are exported, |
| * |
| * An auxiliary_device represents a part of its parent device's functionality. |
| * It is given a name that, combined with the registering drivers |
| * KBUILD_MODNAME, creates a match_name that is used for driver binding, and an |
| * id that combined with the match_name provide a unique name to register with |
| * the bus subsystem. For example, a driver registering an auxiliary device is |
| * named 'foo_mod.ko' and the subdevice is named 'foo_dev'. The match name is |
| * therefore 'foo_mod.foo_dev'. |
| * |
| * Registering an auxiliary_device is a three-step process. |
| * |
| * First, a 'struct auxiliary_device' needs to be defined or allocated for each |
| * sub-device desired. The name, id, dev.release, and dev.parent fields of |
| * this structure must be filled in as follows. |
| * |
| * The 'name' field is to be given a name that is recognized by the auxiliary |
| * driver. If two auxiliary_devices with the same match_name, eg |
| * "foo_mod.foo_dev", are registered onto the bus, they must have unique id |
| * values (e.g. "x" and "y") so that the registered devices names are |
| * "foo_mod.foo_dev.x" and "foo_mod.foo_dev.y". If match_name + id are not |
| * unique, then the device_add fails and generates an error message. |
| * |
| * The auxiliary_device.dev.type.release or auxiliary_device.dev.release must |
| * be populated with a non-NULL pointer to successfully register the |
| * auxiliary_device. This release call is where resources associated with the |
| * auxiliary device must be free'ed. Because once the device is placed on the |
| * bus the parent driver can not tell what other code may have a reference to |
| * this data. |
| * |
| * The auxiliary_device.dev.parent should be set. Typically to the registering |
| * drivers device. |
| * |
| * Second, call auxiliary_device_init(), which checks several aspects of the |
| * auxiliary_device struct and performs a device_initialize(). After this step |
| * completes, any error state must have a call to auxiliary_device_uninit() in |
| * its resolution path. |
| * |
| * The third and final step in registering an auxiliary_device is to perform a |
| * call to auxiliary_device_add(), which sets the name of the device and adds |
| * the device to the bus. |
| * |
| * .. code-block:: c |
| * |
| * #define MY_DEVICE_NAME "foo_dev" |
| * |
| * ... |
| * |
| * struct auxiliary_device *my_aux_dev = my_aux_dev_alloc(xxx); |
| * |
| * // Step 1: |
| * my_aux_dev->name = MY_DEVICE_NAME; |
| * my_aux_dev->id = my_unique_id_alloc(xxx); |
| * my_aux_dev->dev.release = my_aux_dev_release; |
| * my_aux_dev->dev.parent = my_dev; |
| * |
| * // Step 2: |
| * if (auxiliary_device_init(my_aux_dev)) |
| * goto fail; |
| * |
| * // Step 3: |
| * if (auxiliary_device_add(my_aux_dev)) { |
| * auxiliary_device_uninit(my_aux_dev); |
| * goto fail; |
| * } |
| * |
| * ... |
| * |
| * |
| * Unregistering an auxiliary_device is a two-step process to mirror the |
| * register process. First call auxiliary_device_delete(), then call |
| * auxiliary_device_uninit(). |
| * |
| * .. code-block:: c |
| * |
| * auxiliary_device_delete(my_dev->my_aux_dev); |
| * auxiliary_device_uninit(my_dev->my_aux_dev); |
| */ |
| struct auxiliary_device { |
| struct device dev; |
| const char *name; |
| u32 id; |
| }; |
| |
| /** |
| * struct auxiliary_driver - Definition of an auxiliary bus driver |
| * @probe: Called when a matching device is added to the bus. |
| * @remove: Called when device is removed from the bus. |
| * @shutdown: Called at shut-down time to quiesce the device. |
| * @suspend: Called to put the device to sleep mode. Usually to a power state. |
| * @resume: Called to bring a device from sleep mode. |
| * @name: Driver name. |
| * @driver: Core driver structure. |
| * @id_table: Table of devices this driver should match on the bus. |
| * |
| * Auxiliary drivers follow the standard driver model convention, where |
| * discovery/enumeration is handled by the core, and drivers provide probe() |
| * and remove() methods. They support power management and shutdown |
| * notifications using the standard conventions. |
| * |
| * Auxiliary drivers register themselves with the bus by calling |
| * auxiliary_driver_register(). The id_table contains the match_names of |
| * auxiliary devices that a driver can bind with. |
| * |
| * .. code-block:: c |
| * |
| * static const struct auxiliary_device_id my_auxiliary_id_table[] = { |
| * { .name = "foo_mod.foo_dev" }, |
| * {}, |
| * }; |
| * |
| * MODULE_DEVICE_TABLE(auxiliary, my_auxiliary_id_table); |
| * |
| * struct auxiliary_driver my_drv = { |
| * .name = "myauxiliarydrv", |
| * .id_table = my_auxiliary_id_table, |
| * .probe = my_drv_probe, |
| * .remove = my_drv_remove |
| * }; |
| */ |
| struct auxiliary_driver { |
| int (*probe)(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id); |
| void (*remove)(struct auxiliary_device *auxdev); |
| void (*shutdown)(struct auxiliary_device *auxdev); |
| int (*suspend)(struct auxiliary_device *auxdev, pm_message_t state); |
| int (*resume)(struct auxiliary_device *auxdev); |
| const char *name; |
| struct device_driver driver; |
| const struct auxiliary_device_id *id_table; |
| }; |
| |
| static inline void *auxiliary_get_drvdata(struct auxiliary_device *auxdev) |
| { |
| return dev_get_drvdata(&auxdev->dev); |
| } |
| |
| static inline void auxiliary_set_drvdata(struct auxiliary_device *auxdev, void *data) |
| { |
| dev_set_drvdata(&auxdev->dev, data); |
| } |
| |
| static inline struct auxiliary_device *to_auxiliary_dev(struct device *dev) |
| { |
| return container_of(dev, struct auxiliary_device, dev); |
| } |
| |
| static inline struct auxiliary_driver *to_auxiliary_drv(struct device_driver *drv) |
| { |
| return container_of(drv, struct auxiliary_driver, driver); |
| } |
| |
| int auxiliary_device_init(struct auxiliary_device *auxdev); |
| int __auxiliary_device_add(struct auxiliary_device *auxdev, const char *modname); |
| #define auxiliary_device_add(auxdev) __auxiliary_device_add(auxdev, KBUILD_MODNAME) |
| |
| static inline void auxiliary_device_uninit(struct auxiliary_device *auxdev) |
| { |
| put_device(&auxdev->dev); |
| } |
| |
| static inline void auxiliary_device_delete(struct auxiliary_device *auxdev) |
| { |
| device_del(&auxdev->dev); |
| } |
| |
| int __auxiliary_driver_register(struct auxiliary_driver *auxdrv, struct module *owner, |
| const char *modname); |
| #define auxiliary_driver_register(auxdrv) \ |
| __auxiliary_driver_register(auxdrv, THIS_MODULE, KBUILD_MODNAME) |
| |
| void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv); |
| |
| /** |
| * module_auxiliary_driver() - Helper macro for registering an auxiliary driver |
| * @__auxiliary_driver: auxiliary driver struct |
| * |
| * Helper macro for auxiliary drivers which do not do anything special in |
| * module init/exit. This eliminates a lot of boilerplate. Each module may only |
| * use this macro once, and calling it replaces module_init() and module_exit() |
| * |
| * .. code-block:: c |
| * |
| * module_auxiliary_driver(my_drv); |
| */ |
| #define module_auxiliary_driver(__auxiliary_driver) \ |
| module_driver(__auxiliary_driver, auxiliary_driver_register, auxiliary_driver_unregister) |
| |
| struct auxiliary_device *auxiliary_find_device(struct device *start, |
| const void *data, |
| int (*match)(struct device *dev, const void *data)); |
| |
| #endif /* _AUXILIARY_BUS_H_ */ |