summaryrefslogtreecommitdiff
path: root/include/dm/uclass-internal.h
blob: fb0edcc296990e32f5972e94c2f1d982eb7ed508 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (c) 2013 Google, Inc
 *
 * (C) Copyright 2012
 * Pavel Herrmann <morpheus.ibis@gmail.com>
 */

#ifndef _DM_UCLASS_INTERNAL_H
#define _DM_UCLASS_INTERNAL_H

#include <dm/ofnode.h>

/*
 * These next two macros DM_UCLASS_INST() and DM_UCLASS_REF() are only allowed
 * in code generated by dtoc, because the ordering is important and if other
 * instances creep in then they may mess up the ordering expected by dtoc.
 *
 * It is OK to use them with 'extern' though, since that does not actually
 * add a new record to the linker_list.
 */

/**
 * DM_UCLASS_INST() - Declare a uclass ready for run-time use
 *
 * This adds an actual struct uclass to a list which is found by driver model
 * on start-up.
 *
 * For example:
 *
 * DM_UCLASS_INST(clk) = {
 *	.uc_drv		= DM_UCLASS_DRIVER_REF(clk),
 * ...
 * };
 *
 * @_name: Name of the uclass. This must be a valid C identifier, used by the
 *	linker_list.
 */
#define DM_UCLASS_INST(_name)						\
	ll_entry_declare(struct uclass, _name, uclass)

/**
 * DM_UCLASS_REF() - Get a reference to a uclass
 *
 * This is useful for referencing a uclass at build time. Before this is used,
 * an extern DM_UCLASS_INST() must have been declared.
 *
 * For example:
 *
 * extern DM_UCLASS_INST(clk);
 *
 * struct uclass *ucs[] = {
 *	DM_UCLASS_REF(clk),
 * }
 *
 * @_name: Name of the uclass. This must be a valid C identifier, used by the
 *	linker_list
 * @returns struct uclass * for the device
 */
#define DM_UCLASS_REF(_name)						\
	ll_entry_ref(struct uclass, _name, uclass)

/**
 * uclass_set_priv() - Set the private data for a uclass
 *
 * This is normally handled by driver model, which automatically allocates
 * private data when an 'auto' size if provided by the uclass driver.
 *
 * Use this function to override normal operation for special situations, such
 * as needing to allocate a variable amount of data.
 *
 * If OF_PLATDATA_RT is enabled, this function cannot be used out of core driver
 * model code, since the pointer must be within the gd->dm_priv_base region.
 *
 * @uc		Uclass to update
 * @priv	New private-data pointer
 */
void uclass_set_priv(struct uclass *uc, void *priv);

/**
 * uclass_find_next_free_seq() - Get the next free sequence number
 *
 * This returns the next free sequence number. This is useful only if
 * OF_CONTROL is not used. The next free sequence number is simply the
 * maximum sequence number used by all devices in the uclass + 1. The value
 * returned is always greater than the largest alias, if DM_SEQ_ALIAS is enabled
 * and the uclass has the DM_UC_FLAG_SEQ_ALIAS flag.
 *
 * This allows assigning the sequence number in the binding order.
 *
 * @uc:		uclass to check
 * @return	The next free sequence number
 */
int uclass_find_next_free_seq(struct uclass *uc);

/**
 * uclass_get_device_tail() - handle the end of a get_device call
 *
 * This handles returning an error or probing a device as needed.
 *
 * @dev: Device that needs to be probed
 * @ret: Error to return. If non-zero then the device is not probed
 * @devp: Returns the value of 'dev' if there is no error
 * @return ret, if non-zero, else the result of the device_probe() call
 */
int uclass_get_device_tail(struct udevice *dev, int ret, struct udevice **devp);

/**
 * dev_get_uclass_index() - Get uclass and index of device
 * @dev:	- in - Device that we want the uclass/index of
 * @ucp:	- out - A pointer to the uclass the device belongs to
 *
 * The device is not prepared for use - this is an internal function.
 *
 * @return the index of the device in the uclass list or -ENODEV if not found.
 */
int dev_get_uclass_index(struct udevice *dev, struct uclass **ucp);

/**
 * uclass_find_device() - Return n-th child of uclass
 * @id:		Id number of the uclass
 * @index:	Position of the child in uclass's list
 * #devp:	Returns pointer to device, or NULL on error
 *
 * The device is not prepared for use - this is an internal function.
 * The function uclass_get_device_tail() can be used to probe the device.
 *
 * @return the uclass pointer of a child at the given index or
 * return NULL on error.
 */
int uclass_find_device(enum uclass_id id, int index, struct udevice **devp);

/**
 * uclass_find_first_device() - Return the first device in a uclass
 * @id:		Id number of the uclass
 * #devp:	Returns pointer to device, or NULL on error
 *
 * The device is not prepared for use - this is an internal function.
 * The function uclass_get_device_tail() can be used to probe the device.
 *
 * @return 0 if OK (found or not found), -ve on error
 */
int uclass_find_first_device(enum uclass_id id, struct udevice **devp);

/**
 * uclass_find_next_device() - Return the next device in a uclass
 * @devp: On entry, pointer to device to lookup. On exit, returns pointer
 * to the next device in the same uclass, or NULL if none
 *
 * The device is not prepared for use - this is an internal function.
 * The function uclass_get_device_tail() can be used to probe the device.
 *
 * @return 0 if OK (found or not found), -ve on error
 */
int uclass_find_next_device(struct udevice **devp);

/**
 * uclass_find_device_by_name() - Find uclass device based on ID and name
 *
 * This searches for a device with the exactly given name.
 *
 * The device is NOT probed, it is merely returned.
 *
 * @id: ID to look up
 * @name: name of a device to find
 * @devp: Returns pointer to device (the first one with the name)
 * @return 0 if OK, -ve on error
 */
int uclass_find_device_by_name(enum uclass_id id, const char *name,
			       struct udevice **devp);

/**
 * uclass_find_device_by_seq() - Find uclass device based on ID and sequence
 *
 * This searches for a device with the given seq.
 *
 * The device is NOT probed, it is merely returned.
 *
 * @id: ID to look up
 * @seq: Sequence number to find (0=first)
 * @devp: Returns pointer to device (there is only one per for each seq)
 * @return 0 if OK, -ENODEV if not found
 */
int uclass_find_device_by_seq(enum uclass_id id, int seq,
			      struct udevice **devp);

/**
 * uclass_find_device_by_of_offset() - Find a uclass device by device tree node
 *
 * This searches the devices in the uclass for one attached to the given
 * device tree node.
 *
 * The device is NOT probed, it is merely returned.
 *
 * @id: ID to look up
 * @node: Device tree offset to search for (if -ve then -ENODEV is returned)
 * @devp: Returns pointer to device (there is only one for each node)
 * @return 0 if OK, -ve on error
 */
int uclass_find_device_by_of_offset(enum uclass_id id, int node,
				    struct udevice **devp);

/**
 * uclass_find_device_by_of_node() - Find a uclass device by device tree node
 *
 * This searches the devices in the uclass for one attached to the given
 * device tree node.
 *
 * The device is NOT probed, it is merely returned.
 *
 * @id: ID to look up
 * @node: Device tree offset to search for (if NULL then -ENODEV is returned)
 * @devp: Returns pointer to device (there is only one for each node)
 * @return 0 if OK, -ve on error
 */
int uclass_find_device_by_ofnode(enum uclass_id id, ofnode node,
				 struct udevice **devp);

/**
 * uclass_find_device_by_phandle() - Find a uclass device by phandle
 *
 * This searches the devices in the uclass for one with the given phandle.
 *
 * The device is NOT probed, it is merely returned.
 *
 * @id: ID to look up
 * @parent: Parent device containing the phandle pointer
 * @name: Name of property in the parent device node
 * @devp: Returns pointer to device (there is only one for each node)
 * @return 0 if OK, -ENOENT if there is no @name present in the node, other
 *	-ve on error
 */
int uclass_find_device_by_phandle(enum uclass_id id, struct udevice *parent,
				  const char *name, struct udevice **devp);

/**
 * uclass_bind_device() - Associate device with a uclass
 *
 * Connect the device into uclass's list of devices.
 *
 * @dev:	Pointer to the device
 * #return 0 on success, -ve on error
 */
int uclass_bind_device(struct udevice *dev);

#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
/**
 * uclass_pre_unbind_device() - Prepare to deassociate device with a uclass
 *
 * Call any handled needed before uclass_unbind_device() is called
 *
 * @dev:	Pointer to the device
 * #return 0 on success, -ve on error
 */
int uclass_pre_unbind_device(struct udevice *dev);

/**
 * uclass_unbind_device() - Deassociate device with a uclass
 *
 * Disconnect the device from uclass's list of devices.
 *
 * @dev:	Pointer to the device
 * #return 0 on success, -ve on error
 */
int uclass_unbind_device(struct udevice *dev);

#else
static inline int uclass_pre_unbind_device(struct udevice *dev) { return 0; }
static inline int uclass_unbind_device(struct udevice *dev) { return 0; }
#endif

/**
 * uclass_pre_probe_device() - Deal with a device that is about to be probed
 *
 * Perform any pre-processing that is needed by the uclass before it can be
 * probed. This includes the uclass' pre-probe() method and the parent
 * uclass' child_pre_probe() method.
 *
 * @dev:	Pointer to the device
 * #return 0 on success, -ve on error
 */
int uclass_pre_probe_device(struct udevice *dev);

/**
 * uclass_post_probe_device() - Deal with a device that has just been probed
 *
 * Perform any post-processing of a probed device that is needed by the
 * uclass.
 *
 * @dev:	Pointer to the device
 * #return 0 on success, -ve on error
 */
int uclass_post_probe_device(struct udevice *dev);

/**
 * uclass_pre_remove_device() - Handle a device which is about to be removed
 *
 * Perform any pre-processing of a device that is about to be removed.
 *
 * @dev:	Pointer to the device
 * #return 0 on success, -ve on error
 */
#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
int uclass_pre_remove_device(struct udevice *dev);
#else
static inline int uclass_pre_remove_device(struct udevice *dev) { return 0; }
#endif

/**
 * uclass_get_count() - Get the number of uclasses
 *
 * Returns the number of uclasses instantiated in driver model
 */
int uclass_get_count(void);

/**
 * uclass_find() - Find uclass by its id
 *
 * @id:		Id to serach for
 * @return pointer to uclass, or NULL if not found
 */
struct uclass *uclass_find(enum uclass_id key);

/**
 * uclass_destroy() - Destroy a uclass
 *
 * Destroy a uclass and all its devices
 *
 * @uc: uclass to destroy
 * @return 0 on success, -ve on error
 */
int uclass_destroy(struct uclass *uc);

#endif