| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | 
|---|
| 2 | #ifndef COMPONENT_H | 
|---|
| 3 | #define COMPONENT_H | 
|---|
| 4 |  | 
|---|
| 5 | #include <linux/stddef.h> | 
|---|
| 6 | #include <linux/types.h> | 
|---|
| 7 |  | 
|---|
| 8 | struct device; | 
|---|
| 9 |  | 
|---|
| 10 | /** | 
|---|
| 11 | * struct component_ops - callbacks for component drivers | 
|---|
| 12 | * | 
|---|
| 13 | * Components are registered with component_add() and unregistered with | 
|---|
| 14 | * component_del(). | 
|---|
| 15 | */ | 
|---|
| 16 | struct component_ops { | 
|---|
| 17 | /** | 
|---|
| 18 | * @bind: | 
|---|
| 19 | * | 
|---|
| 20 | * Called through component_bind_all() when the aggregate driver is | 
|---|
| 21 | * ready to bind the overall driver. | 
|---|
| 22 | */ | 
|---|
| 23 | int (*bind)(struct device *comp, struct device *master, | 
|---|
| 24 | void *master_data); | 
|---|
| 25 | /** | 
|---|
| 26 | * @unbind: | 
|---|
| 27 | * | 
|---|
| 28 | * Called through component_unbind_all() when the aggregate driver is | 
|---|
| 29 | * ready to bind the overall driver, or when component_bind_all() fails | 
|---|
| 30 | * part-ways through and needs to unbind some already bound components. | 
|---|
| 31 | */ | 
|---|
| 32 | void (*unbind)(struct device *comp, struct device *master, | 
|---|
| 33 | void *master_data); | 
|---|
| 34 | }; | 
|---|
| 35 |  | 
|---|
| 36 | int component_add(struct device *, const struct component_ops *); | 
|---|
| 37 | int component_add_typed(struct device *dev, const struct component_ops *ops, | 
|---|
| 38 | int subcomponent); | 
|---|
| 39 | void component_del(struct device *, const struct component_ops *); | 
|---|
| 40 |  | 
|---|
| 41 | int component_bind_all(struct device *parent, void *data); | 
|---|
| 42 | void component_unbind_all(struct device *parent, void *data); | 
|---|
| 43 |  | 
|---|
| 44 | struct aggregate_device; | 
|---|
| 45 |  | 
|---|
| 46 | /** | 
|---|
| 47 | * struct component_master_ops - callback for the aggregate driver | 
|---|
| 48 | * | 
|---|
| 49 | * Aggregate drivers are registered with component_master_add_with_match() and | 
|---|
| 50 | * unregistered with component_master_del(). | 
|---|
| 51 | */ | 
|---|
| 52 | struct component_master_ops { | 
|---|
| 53 | /** | 
|---|
| 54 | * @bind: | 
|---|
| 55 | * | 
|---|
| 56 | * Called when all components or the aggregate driver, as specified in | 
|---|
| 57 | * the match list passed to component_master_add_with_match(), are | 
|---|
| 58 | * ready. Usually there are 3 steps to bind an aggregate driver: | 
|---|
| 59 | * | 
|---|
| 60 | * 1. Allocate a structure for the aggregate driver. | 
|---|
| 61 | * | 
|---|
| 62 | * 2. Bind all components to the aggregate driver by calling | 
|---|
| 63 | *    component_bind_all() with the aggregate driver structure as opaque | 
|---|
| 64 | *    pointer data. | 
|---|
| 65 | * | 
|---|
| 66 | * 3. Register the aggregate driver with the subsystem to publish its | 
|---|
| 67 | *    interfaces. | 
|---|
| 68 | * | 
|---|
| 69 | * Note that the lifetime of the aggregate driver does not align with | 
|---|
| 70 | * any of the underlying &struct device instances. Therefore devm cannot | 
|---|
| 71 | * be used and all resources acquired or allocated in this callback must | 
|---|
| 72 | * be explicitly released in the @unbind callback. | 
|---|
| 73 | */ | 
|---|
| 74 | int (*bind)(struct device *master); | 
|---|
| 75 | /** | 
|---|
| 76 | * @unbind: | 
|---|
| 77 | * | 
|---|
| 78 | * Called when either the aggregate driver, using | 
|---|
| 79 | * component_master_del(), or one of its components, using | 
|---|
| 80 | * component_del(), is unregistered. | 
|---|
| 81 | */ | 
|---|
| 82 | void (*unbind)(struct device *master); | 
|---|
| 83 | }; | 
|---|
| 84 |  | 
|---|
| 85 | /* A set helper functions for component compare/release */ | 
|---|
| 86 | int component_compare_of(struct device *dev, void *data); | 
|---|
| 87 | void component_release_of(struct device *dev, void *data); | 
|---|
| 88 | int component_compare_dev(struct device *dev, void *data); | 
|---|
| 89 | int component_compare_dev_name(struct device *dev, void *data); | 
|---|
| 90 |  | 
|---|
| 91 | void component_master_del(struct device *, | 
|---|
| 92 | const struct component_master_ops *); | 
|---|
| 93 | bool component_master_is_bound(struct device *parent, | 
|---|
| 94 | const struct component_master_ops *ops); | 
|---|
| 95 |  | 
|---|
| 96 | struct component_match; | 
|---|
| 97 |  | 
|---|
| 98 | int component_master_add_with_match(struct device *, | 
|---|
| 99 | const struct component_master_ops *, struct component_match *); | 
|---|
| 100 | void component_match_add_release(struct device *parent, | 
|---|
| 101 | struct component_match **matchptr, | 
|---|
| 102 | void (*release)(struct device *, void *), | 
|---|
| 103 | int (*compare)(struct device *, void *), void *compare_data); | 
|---|
| 104 | void component_match_add_typed(struct device *parent, | 
|---|
| 105 | struct component_match **matchptr, | 
|---|
| 106 | int (*compare_typed)(struct device *, int, void *), void *compare_data); | 
|---|
| 107 |  | 
|---|
| 108 | /** | 
|---|
| 109 | * component_match_add - add a component match entry | 
|---|
| 110 | * @parent: device with the aggregate driver | 
|---|
| 111 | * @matchptr: pointer to the list of component matches | 
|---|
| 112 | * @compare: compare function to match against all components | 
|---|
| 113 | * @compare_data: opaque pointer passed to the @compare function | 
|---|
| 114 | * | 
|---|
| 115 | * Adds a new component match to the list stored in @matchptr, which the @parent | 
|---|
| 116 | * aggregate driver needs to function. The list of component matches pointed to | 
|---|
| 117 | * by @matchptr must be initialized to NULL before adding the first match. This | 
|---|
| 118 | * only matches against components added with component_add(). | 
|---|
| 119 | * | 
|---|
| 120 | * The allocated match list in @matchptr is automatically released using devm | 
|---|
| 121 | * actions. | 
|---|
| 122 | * | 
|---|
| 123 | * See also component_match_add_release() and component_match_add_typed(). | 
|---|
| 124 | */ | 
|---|
| 125 | static inline void component_match_add(struct device *parent, | 
|---|
| 126 | struct component_match **matchptr, | 
|---|
| 127 | int (*compare)(struct device *, void *), void *compare_data) | 
|---|
| 128 | { | 
|---|
| 129 | component_match_add_release(parent, matchptr, NULL, compare, | 
|---|
| 130 | compare_data); | 
|---|
| 131 | } | 
|---|
| 132 |  | 
|---|
| 133 | #endif | 
|---|
| 134 |  | 
|---|