summaryrefslogtreecommitdiff
path: root/include/linux/component.h
blob: df4aa75c9e7c86e88c95f5729791384104f94fa9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef COMPONENT_H
#define COMPONENT_H

#include <linux/stddef.h>


struct device;

/**
 * struct component_ops - callbacks for component drivers
 *
 * Components are registered with component_add() and unregistered with
 * component_del().
 */
struct component_ops {
	/**
	 * @bind:
	 *
	 * Called through component_bind_all() when the aggregate driver is
	 * ready to bind the overall driver.
	 */
	int (*bind)(struct device *comp, struct device *master,
		    void *master_data);
	/**
	 * @unbind:
	 *
	 * Called through component_unbind_all() when the aggregate driver is
	 * ready to bind the overall driver, or when component_bind_all() fails
	 * part-ways through and needs to unbind some already bound components.
	 */
	void (*unbind)(struct device *comp, struct device *master,
		       void *master_data);
};

int component_add(struct device *, const struct component_ops *);
int component_add_typed(struct device *dev, const struct component_ops *ops,
	int subcomponent);
void component_del(struct device *, const struct component_ops *);

int component_bind_all(struct device *parent, void *data);
void component_unbind_all(struct device *parent, void *data);

struct aggregate_device;

/**
 * struct component_master_ops - callback for the aggregate driver
 *
 * Aggregate drivers are registered with component_master_add_with_match() and
 * unregistered with component_master_del().
 */
struct component_master_ops {
	/**
	 * @bind:
	 *
	 * Called when all components or the aggregate driver, as specified in
	 * the match list passed to component_master_add_with_match(), are
	 * ready. Usually there are 3 steps to bind an aggregate driver:
	 *
	 * 1. Allocate a structure for the aggregate driver.
	 *
	 * 2. Bind all components to the aggregate driver by calling
	 *    component_bind_all() with the aggregate driver structure as opaque
	 *    pointer data.
	 *
	 * 3. Register the aggregate driver with the subsystem to publish its
	 *    interfaces.
	 *
	 * Note that the lifetime of the aggregate driver does not align with
	 * any of the underlying &struct device instances. Therefore devm cannot
	 * be used and all resources acquired or allocated in this callback must
	 * be explicitly released in the @unbind callback.
	 */
	int (*bind)(struct device *master);
	/**
	 * @unbind:
	 *
	 * Called when either the aggregate driver, using
	 * component_master_del(), or one of its components, using
	 * component_del(), is unregistered.
	 */
	void (*unbind)(struct device *master);
};

/* A set helper functions for component compare/release */
int component_compare_of(struct device *dev, void *data);
void component_release_of(struct device *dev, void *data);
int component_compare_dev(struct device *dev, void *data);
int component_compare_dev_name(struct device *dev, void *data);

void component_master_del(struct device *,
	const struct component_master_ops *);

struct component_match;

int component_master_add_with_match(struct device *,
	const struct component_master_ops *, struct component_match *);
void component_match_add_release(struct device *parent,
	struct component_match **matchptr,
	void (*release)(struct device *, void *),
	int (*compare)(struct device *, void *), void *compare_data);
void component_match_add_typed(struct device *parent,
	struct component_match **matchptr,
	int (*compare_typed)(struct device *, int, void *), void *compare_data);

/**
 * component_match_add - add a component match entry
 * @parent: device with the aggregate driver
 * @matchptr: pointer to the list of component matches
 * @compare: compare function to match against all components
 * @compare_data: opaque pointer passed to the @compare function
 *
 * Adds a new component match to the list stored in @matchptr, which the @parent
 * aggregate driver needs to function. The list of component matches pointed to
 * by @matchptr must be initialized to NULL before adding the first match. This
 * only matches against components added with component_add().
 *
 * The allocated match list in @matchptr is automatically released using devm
 * actions.
 *
 * See also component_match_add_release() and component_match_add_typed().
 */
static inline void component_match_add(struct device *parent,
	struct component_match **matchptr,
	int (*compare)(struct device *, void *), void *compare_data)
{
	component_match_add_release(parent, matchptr, NULL, compare,
				    compare_data);
}

#endif