summaryrefslogtreecommitdiff
path: root/include/reset.h
blob: 965f02e0ceef64719403dd77195e49fd5c859a27 (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
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2016, NVIDIA CORPORATION.
 */

#ifndef _RESET_H
#define _RESET_H

#include <dm/ofnode.h>
#include <linux/err.h>

/**
 * A reset is a hardware signal indicating that a HW module (or IP block, or
 * sometimes an entire off-CPU chip) reset all of its internal state to some
 * known-good initial state. Drivers will often reset HW modules when they
 * begin execution to ensure that hardware correctly responds to all requests,
 * or in response to some error condition. Reset signals are often controlled
 * externally to the HW module being reset, by an entity this API calls a reset
 * controller. This API provides a standard means for drivers to request that
 * reset controllers set or clear reset signals.
 *
 * A driver that implements UCLASS_RESET is a reset controller or provider. A
 * controller will often implement multiple separate reset signals, since the
 * hardware it manages often has this capability. reset-uclass.h describes the
 * interface which reset controllers must implement.
 *
 * Reset consumers/clients are the HW modules affected by reset signals. This
 * header file describes the API used by drivers for those HW modules.
 */

struct udevice;

/**
 * struct reset_ctl - A handle to (allowing control of) a single reset signal.
 *
 * Clients provide storage for reset control handles. The content of the
 * structure is managed solely by the reset API and reset drivers. A reset
 * control struct is initialized by "get"ing the reset control struct. The
 * reset control struct is passed to all other reset APIs to identify which
 * reset signal to operate upon.
 *
 * @dev: The device which implements the reset signal.
 * @id: The reset signal ID within the provider.
 * @data: An optional data field for scenarios where a single integer ID is not
 *	  sufficient. If used, it can be populated through an .of_xlate op and
 *	  processed during the various reset ops.
 * @polarity: An optional polarity field for drivers that support
 *	  different reset polarities.
 *
 * Should additional information to identify and configure any reset signal
 * for any provider be required in the future, the struct could be expanded to
 * either (a) add more fields to allow reset providers to store additional
 * information, or (b) replace the id field with an opaque pointer, which the
 * provider would dynamically allocated during its .of_xlate op, and process
 * during is .request op. This may require the addition of an extra op to clean
 * up the allocation.
 */
struct reset_ctl {
	struct udevice *dev;
	/*
	 * Written by of_xlate. In the future, we might add more fields here.
	 */
	unsigned long id;
	unsigned long data;
	unsigned long polarity;
};

/**
 * struct reset_ctl_bulk - A handle to (allowing control of) a bulk of reset
 * signals.
 *
 * Clients provide storage for the reset control bulk. The content of the
 * structure is managed solely by the reset API. A reset control bulk struct is
 * initialized by "get"ing the reset control bulk struct.
 * The reset control bulk struct is passed to all other bulk reset APIs to apply
 * the API to all the reset signals in the bulk struct.
 *
 * @resets: An array of reset signal handles handles.
 * @count: The number of reset signal handles in the reset array.
 */
struct reset_ctl_bulk {
	struct reset_ctl *resets;
	unsigned int count;
};

#if CONFIG_IS_ENABLED(DM_RESET)

/**
 * devm_reset_control_get - resource managed reset_get_by_name()
 * @dev: device to be reset by the controller
 * @id: reset line name
 *
 * Managed reset_get_by_name(). For reset controllers returned
 * from this function, reset_free() is called automatically on driver
 * detach.
 *
 * Returns a struct reset_ctl or IS_ERR() condition containing errno.
 */
struct reset_ctl *devm_reset_control_get(struct udevice *dev, const char *id);

/**
 * devm_reset_control_get_optional - resource managed reset_get_by_name() that
 *                                   can fail
 * @dev:	The client device.
 * @id:		reset line name
 *
 * Managed reset_get_by_name(). For reset controllers returned
 * from this function, reset_free() is called automatically on driver
 * detach.
 *
 * Returns a struct reset_ctl or a dummy reset controller if it failed.
 */
struct reset_ctl *devm_reset_control_get_optional(struct udevice *dev,
						  const char *id);

/**
 * devm_reset_control_get - resource managed reset_get_by_index()
 * @dev:	The client device.
 * @index:	The index of the reset signal to request, within the client's
 *		list of reset signals.
 *
 * Managed reset_get_by_index(). For reset controllers returned
 * from this function, reset_free() is called automatically on driver
 * detach.
 *
 * Returns a struct reset_ctl or IS_ERR() condition containing errno.
 */
struct reset_ctl *devm_reset_control_get_by_index(struct udevice *dev,
						  int index);

/**
 * devm_reset_bulk_get - resource managed reset_get_bulk()
 * @dev: device to be reset by the controller
 *
 * Managed reset_get_bulk(). For reset controllers returned
 * from this function, reset_free() is called automatically on driver
 * detach.
 *
 * Returns a struct reset_ctl or IS_ERR() condition containing errno.
 */
struct reset_ctl_bulk *devm_reset_bulk_get(struct udevice *dev);

/**
 * devm_reset_bulk_get_optional - resource managed reset_get_bulk() that
 *                                can fail
 * @dev:	The client device.
 *
 * Managed reset_get_bulk(). For reset controllers returned
 * from this function, reset_free() is called automatically on driver
 * detach.
 *
 * Returns a struct reset_ctl or NULL if it failed.
 */
struct reset_ctl_bulk *devm_reset_bulk_get_optional(struct udevice *dev);

/**
 * devm_reset_bulk_get_by_node - resource managed reset_get_bulk()
 * @dev: device to be reset by the controller
 * @node: ofnode where the "resets" property is. Usually a sub-node of
 *        the dev's node.
 *
 * see devm_reset_bulk_get()
 */
struct reset_ctl_bulk *devm_reset_bulk_get_by_node(struct udevice *dev,
						   ofnode node);

/**
 * devm_reset_bulk_get_optional_by_node - resource managed reset_get_bulk()
 *                                        that can fail
 * @dev: device to be reset by the controller
 * @node: ofnode where the "resets" property is. Usually a sub-node of
 *        the dev's node.
 *
 * see devm_reset_bulk_get_optional()
 */
struct reset_ctl_bulk *devm_reset_bulk_get_optional_by_node(struct udevice *dev,
							    ofnode node);

/**
 * reset_get_by_index - Get/request a reset signal by integer index.
 *
 * This looks up and requests a reset signal. The index is relative to the
 * client device; each device is assumed to have n reset signals associated
 * with it somehow, and this function finds and requests one of them. The
 * mapping of client device reset signal indices to provider reset signals may
 * be via device-tree properties, board-provided mapping tables, or some other
 * mechanism.
 *
 * @dev:	The client device.
 * @index:	The index of the reset signal to request, within the client's
 *		list of reset signals.
 * @reset_ctl	A pointer to a reset control struct to initialize.
 * Return: 0 if OK, or a negative error code.
 */
int reset_get_by_index(struct udevice *dev, int index,
		       struct reset_ctl *reset_ctl);

/**
 * reset_get_by_index_nodev - Get/request a reset signal by integer index
 * without a device.
 *
 * This is a version of reset_get_by_index() that does not use a device.
 *
 * @node:	The client ofnode.
 * @index:	The index of the reset signal to request, within the client's
 *		list of reset signals.
 * @reset_ctl	A pointer to a reset control struct to initialize.
 * Return: 0 if OK, or a negative error code.
 */
int reset_get_by_index_nodev(ofnode node, int index,
			     struct reset_ctl *reset_ctl);

/**
 * reset_get_bulk - Get/request all reset signals of a device.
 *
 * This looks up and requests all reset signals of the client device; each
 * device is assumed to have n reset signals associated with it somehow,
 * and this function finds and requests all of them in a separate structure.
 * The mapping of client device reset signals indices to provider reset signals
 * may be via device-tree properties, board-provided mapping tables, or some
 * other mechanism.
 *
 * @dev:	The client device.
 * @bulk	A pointer to a reset control bulk struct to initialize.
 * Return: 0 if OK, or a negative error code.
 */
int reset_get_bulk(struct udevice *dev, struct reset_ctl_bulk *bulk);

/**
 * reset_get_by_name - Get/request a reset signal by name.
 *
 * This looks up and requests a reset signal. The name is relative to the
 * client device; each device is assumed to have n reset signals associated
 * with it somehow, and this function finds and requests one of them. The
 * mapping of client device reset signal names to provider reset signal may be
 * via device-tree properties, board-provided mapping tables, or some other
 * mechanism.
 *
 * @dev:	The client device.
 * @name:	The name of the reset signal to request, within the client's
 *		list of reset signals.
 * @reset_ctl:	A pointer to a reset control struct to initialize.
 * Return: 0 if OK, or a negative error code.
 */
int reset_get_by_name(struct udevice *dev, const char *name,
		      struct reset_ctl *reset_ctl);

/**
 * reset_request - Request a reset signal.
 *
 * @reset_ctl:	A reset control struct.
 *
 * Return: 0 if OK, or a negative error code.
 */
int reset_request(struct reset_ctl *reset_ctl);

/**
 * reset_free - Free a previously requested reset signal.
 *
 * @reset_ctl:	A reset control struct that was previously successfully
 *		requested by reset_get_by_*().
 * Return: 0 if OK, or a negative error code.
 */
int reset_free(struct reset_ctl *reset_ctl);

/**
 * reset_assert - Assert a reset signal.
 *
 * This function will assert the specified reset signal, thus resetting the
 * affected HW module(s). Depending on the reset controller hardware, the reset
 * signal will either stay asserted until reset_deassert() is called, or the
 * hardware may autonomously clear the reset signal itself.
 *
 * @reset_ctl:	A reset control struct that was previously successfully
 *		requested by reset_get_by_*().
 * Return: 0 if OK, or a negative error code.
 */
int reset_assert(struct reset_ctl *reset_ctl);

/**
 * reset_assert_bulk - Assert all reset signals in a reset control bulk struct.
 *
 * This function will assert the specified reset signals in a reset control
 * bulk struct, thus resetting the affected HW module(s). Depending on the
 * reset controller hardware, the reset signals will either stay asserted
 * until reset_deassert_bulk() is called, or the hardware may autonomously
 * clear the reset signals itself.
 *
 * @bulk:	A reset control bulk struct that was previously successfully
 *		requested by reset_get_bulk().
 * Return: 0 if OK, or a negative error code.
 */
int reset_assert_bulk(struct reset_ctl_bulk *bulk);

/**
 * reset_deassert - Deassert a reset signal.
 *
 * This function will deassert the specified reset signal, thus releasing the
 * affected HW modules() from reset, and allowing them to continue normal
 * operation.
 *
 * @reset_ctl:	A reset control struct that was previously successfully
 *		requested by reset_get_by_*().
 * Return: 0 if OK, or a negative error code.
 */
int reset_deassert(struct reset_ctl *reset_ctl);

/**
 * reset_deassert_bulk - Deassert all reset signals in a reset control bulk
 * struct.
 *
 * This function will deassert the specified reset signals in a reset control
 * bulk struct, thus releasing the affected HW modules() from reset, and
 * allowing them to continue normal operation.
 *
 * @bulk:	A reset control bulk struct that was previously successfully
 *		requested by reset_get_bulk().
 * Return: 0 if OK, or a negative error code.
 */
int reset_deassert_bulk(struct reset_ctl_bulk *bulk);

/**
 * rst_status - Check reset signal status.
 *
 * @reset_ctl:	The reset signal to check.
 * Return: 0 if deasserted, positive if asserted, or a negative
 *           error code.
 */
int reset_status(struct reset_ctl *reset_ctl);

/**
 * reset_release_all - Assert/Free an array of previously requested resets.
 *
 * For each reset contained in the reset array, this function will check if
 * reset has been previously requested and then will assert and free it.
 *
 * @reset_ctl:	A reset struct array that was previously successfully
 *		requested by reset_get_by_*().
 * @count	Number of reset contained in the array
 * Return: 0 if OK, or a negative error code.
 */
int reset_release_all(struct reset_ctl *reset_ctl, int count);

/**
 * reset_release_bulk - Assert/Free an array of previously requested reset
 * signals in a reset control bulk struct.
 *
 * For each reset contained in the reset control bulk struct, this function
 * will check if reset has been previously requested and then will assert
 * and free it.
 *
 * @bulk:	A reset control bulk struct that was previously successfully
 *		requested by reset_get_bulk().
 * Return: 0 if OK, or a negative error code.
 */
static inline int reset_release_bulk(struct reset_ctl_bulk *bulk)
{
	return reset_release_all(bulk->resets, bulk->count);
}

#else
static inline struct reset_ctl *devm_reset_control_get(struct udevice *dev,
						       const char *id)
{
	return ERR_PTR(-ENOTSUPP);
}

static inline struct reset_ctl *devm_reset_control_get_optional(struct udevice *dev,
								const char *id)
{
	return NULL;
}

static inline struct reset_ctl *devm_reset_control_get_by_index(struct udevice *dev,
								int index)
{
	return ERR_PTR(-ENOTSUPP);
}

static inline struct reset_ctl_bulk *devm_reset_bulk_get(struct udevice *dev)
{
	return ERR_PTR(-ENOTSUPP);
}

static inline struct reset_ctl_bulk *devm_reset_bulk_get_optional(struct udevice *dev)
{
	return NULL;
}

static inline struct reset_ctl_bulk *devm_reset_bulk_get_by_node(struct udevice *dev,
								 ofnode node)
{
	return ERR_PTR(-ENOTSUPP);
}

static inline struct reset_ctl_bulk *devm_reset_bulk_get_optional_by_node(struct udevice *dev,
									  ofnode node)
{
	return NULL;
}

static inline int reset_get_by_index(struct udevice *dev, int index,
				     struct reset_ctl *reset_ctl)
{
	return -ENOTSUPP;
}

static inline int reset_get_bulk(struct udevice *dev,
				 struct reset_ctl_bulk *bulk)
{
	return -ENOTSUPP;
}

static inline int reset_get_by_name(struct udevice *dev, const char *name,
				    struct reset_ctl *reset_ctl)
{
	return -ENOTSUPP;
}

static inline int reset_free(struct reset_ctl *reset_ctl)
{
	return 0;
}

static inline int reset_assert(struct reset_ctl *reset_ctl)
{
	return 0;
}

static inline int reset_assert_bulk(struct reset_ctl_bulk *bulk)
{
	return 0;
}

static inline int reset_deassert(struct reset_ctl *reset_ctl)
{
	return 0;
}

static inline int reset_deassert_bulk(struct reset_ctl_bulk *bulk)
{
	return 0;
}

static inline int reset_status(struct reset_ctl *reset_ctl)
{
	return -ENOTSUPP;
}

static inline int reset_release_all(struct reset_ctl *reset_ctl, int count)
{
	return 0;
}

static inline int reset_release_bulk(struct reset_ctl_bulk *bulk)
{
	return 0;
}
#endif

/**
 * reset_valid() - check if reset is valid
 *
 * @reset_ctl:		the reset to check
 * Return: TRUE if valid, or FALSE
 */
static inline bool reset_valid(struct reset_ctl *reset_ctl)
{
	return !!reset_ctl->dev;
}

#endif