xref: /linux-6.15/include/linux/component.h (revision a6ba2dad)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
22a41e607SRussell King #ifndef COMPONENT_H
32a41e607SRussell King #define COMPONENT_H
42a41e607SRussell King 
5ce657b1cSRussell King #include <linux/stddef.h>
6*a6ba2dadSHeiko Stuebner #include <linux/types.h>
74d69c80eSDaniel Vetter 
82a41e607SRussell King struct device;
92a41e607SRussell King 
104d69c80eSDaniel Vetter /**
114d69c80eSDaniel Vetter  * struct component_ops - callbacks for component drivers
124d69c80eSDaniel Vetter  *
134d69c80eSDaniel Vetter  * Components are registered with component_add() and unregistered with
144d69c80eSDaniel Vetter  * component_del().
154d69c80eSDaniel Vetter  */
162a41e607SRussell King struct component_ops {
174d69c80eSDaniel Vetter 	/**
184d69c80eSDaniel Vetter 	 * @bind:
194d69c80eSDaniel Vetter 	 *
204d69c80eSDaniel Vetter 	 * Called through component_bind_all() when the aggregate driver is
214d69c80eSDaniel Vetter 	 * ready to bind the overall driver.
224d69c80eSDaniel Vetter 	 */
23ce657b1cSRussell King 	int (*bind)(struct device *comp, struct device *master,
24ce657b1cSRussell King 		    void *master_data);
254d69c80eSDaniel Vetter 	/**
264d69c80eSDaniel Vetter 	 * @unbind:
274d69c80eSDaniel Vetter 	 *
284d69c80eSDaniel Vetter 	 * Called through component_unbind_all() when the aggregate driver is
294d69c80eSDaniel Vetter 	 * ready to bind the overall driver, or when component_bind_all() fails
304d69c80eSDaniel Vetter 	 * part-ways through and needs to unbind some already bound components.
314d69c80eSDaniel Vetter 	 */
32ce657b1cSRussell King 	void (*unbind)(struct device *comp, struct device *master,
33ce657b1cSRussell King 		       void *master_data);
342a41e607SRussell King };
352a41e607SRussell King 
362a41e607SRussell King int component_add(struct device *, const struct component_ops *);
373521ee99SDaniel Vetter int component_add_typed(struct device *dev, const struct component_ops *ops,
383521ee99SDaniel Vetter 	int subcomponent);
392a41e607SRussell King void component_del(struct device *, const struct component_ops *);
402a41e607SRussell King 
4113e906e5SStephen Boyd int component_bind_all(struct device *parent, void *data);
4213e906e5SStephen Boyd void component_unbind_all(struct device *parent, void *data);
432a41e607SRussell King 
4413e906e5SStephen Boyd struct aggregate_device;
452a41e607SRussell King 
464d69c80eSDaniel Vetter /**
474d69c80eSDaniel Vetter  * struct component_master_ops - callback for the aggregate driver
484d69c80eSDaniel Vetter  *
494d69c80eSDaniel Vetter  * Aggregate drivers are registered with component_master_add_with_match() and
504d69c80eSDaniel Vetter  * unregistered with component_master_del().
514d69c80eSDaniel Vetter  */
522a41e607SRussell King struct component_master_ops {
534d69c80eSDaniel Vetter 	/**
544d69c80eSDaniel Vetter 	 * @bind:
554d69c80eSDaniel Vetter 	 *
564d69c80eSDaniel Vetter 	 * Called when all components or the aggregate driver, as specified in
574d69c80eSDaniel Vetter 	 * the match list passed to component_master_add_with_match(), are
584d69c80eSDaniel Vetter 	 * ready. Usually there are 3 steps to bind an aggregate driver:
594d69c80eSDaniel Vetter 	 *
604d69c80eSDaniel Vetter 	 * 1. Allocate a structure for the aggregate driver.
614d69c80eSDaniel Vetter 	 *
624d69c80eSDaniel Vetter 	 * 2. Bind all components to the aggregate driver by calling
634d69c80eSDaniel Vetter 	 *    component_bind_all() with the aggregate driver structure as opaque
644d69c80eSDaniel Vetter 	 *    pointer data.
654d69c80eSDaniel Vetter 	 *
664d69c80eSDaniel Vetter 	 * 3. Register the aggregate driver with the subsystem to publish its
674d69c80eSDaniel Vetter 	 *    interfaces.
684d69c80eSDaniel Vetter 	 *
694d69c80eSDaniel Vetter 	 * Note that the lifetime of the aggregate driver does not align with
704d69c80eSDaniel Vetter 	 * any of the underlying &struct device instances. Therefore devm cannot
714d69c80eSDaniel Vetter 	 * be used and all resources acquired or allocated in this callback must
724d69c80eSDaniel Vetter 	 * be explicitly released in the @unbind callback.
734d69c80eSDaniel Vetter 	 */
74ce657b1cSRussell King 	int (*bind)(struct device *master);
754d69c80eSDaniel Vetter 	/**
764d69c80eSDaniel Vetter 	 * @unbind:
774d69c80eSDaniel Vetter 	 *
784d69c80eSDaniel Vetter 	 * Called when either the aggregate driver, using
794d69c80eSDaniel Vetter 	 * component_master_del(), or one of its components, using
804d69c80eSDaniel Vetter 	 * component_del(), is unregistered.
814d69c80eSDaniel Vetter 	 */
82ce657b1cSRussell King 	void (*unbind)(struct device *master);
832a41e607SRussell King };
842a41e607SRussell King 
852502960fSYong Wu /* A set helper functions for component compare/release */
862502960fSYong Wu int component_compare_of(struct device *dev, void *data);
872502960fSYong Wu void component_release_of(struct device *dev, void *data);
882502960fSYong Wu int component_compare_dev(struct device *dev, void *data);
892502960fSYong Wu int component_compare_dev_name(struct device *dev, void *data);
902502960fSYong Wu 
912a41e607SRussell King void component_master_del(struct device *,
922a41e607SRussell King 	const struct component_master_ops *);
93*a6ba2dadSHeiko Stuebner bool component_master_is_bound(struct device *parent,
94*a6ba2dadSHeiko Stuebner 	const struct component_master_ops *ops);
952a41e607SRussell King 
966955b582SRussell King struct component_match;
976955b582SRussell King 
986955b582SRussell King int component_master_add_with_match(struct device *,
996955b582SRussell King 	const struct component_master_ops *, struct component_match *);
10013e906e5SStephen Boyd void component_match_add_release(struct device *parent,
101ce657b1cSRussell King 	struct component_match **matchptr,
102ce657b1cSRussell King 	void (*release)(struct device *, void *),
1036955b582SRussell King 	int (*compare)(struct device *, void *), void *compare_data);
10413e906e5SStephen Boyd void component_match_add_typed(struct device *parent,
1053521ee99SDaniel Vetter 	struct component_match **matchptr,
1063521ee99SDaniel Vetter 	int (*compare_typed)(struct device *, int, void *), void *compare_data);
1076955b582SRussell King 
1084d69c80eSDaniel Vetter /**
109e4246b05SDaniel Vetter  * component_match_add - add a component match entry
11013e906e5SStephen Boyd  * @parent: device with the aggregate driver
1114d69c80eSDaniel Vetter  * @matchptr: pointer to the list of component matches
1124d69c80eSDaniel Vetter  * @compare: compare function to match against all components
1134d69c80eSDaniel Vetter  * @compare_data: opaque pointer passed to the @compare function
1144d69c80eSDaniel Vetter  *
11513e906e5SStephen Boyd  * Adds a new component match to the list stored in @matchptr, which the @parent
1164d69c80eSDaniel Vetter  * aggregate driver needs to function. The list of component matches pointed to
1173521ee99SDaniel Vetter  * by @matchptr must be initialized to NULL before adding the first match. This
1183521ee99SDaniel Vetter  * only matches against components added with component_add().
1194d69c80eSDaniel Vetter  *
1204d69c80eSDaniel Vetter  * The allocated match list in @matchptr is automatically released using devm
1214d69c80eSDaniel Vetter  * actions.
1224d69c80eSDaniel Vetter  *
1233521ee99SDaniel Vetter  * See also component_match_add_release() and component_match_add_typed().
1244d69c80eSDaniel Vetter  */
component_match_add(struct device * parent,struct component_match ** matchptr,int (* compare)(struct device *,void *),void * compare_data)12513e906e5SStephen Boyd static inline void component_match_add(struct device *parent,
126ce657b1cSRussell King 	struct component_match **matchptr,
127ce657b1cSRussell King 	int (*compare)(struct device *, void *), void *compare_data)
128ce657b1cSRussell King {
12913e906e5SStephen Boyd 	component_match_add_release(parent, matchptr, NULL, compare,
130ce657b1cSRussell King 				    compare_data);
131ce657b1cSRussell King }
132ce657b1cSRussell King 
1332a41e607SRussell King #endif
134