File: rstctrl.h

package info (click to toggle)
optee-os 4.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 31,960 kB
  • sloc: ansic: 444,388; asm: 12,922; python: 3,719; makefile: 1,681; sh: 238
file content (230 lines) | stat: -rw-r--r-- 6,930 bytes parent folder | download | duplicates (2)
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
/* SPDX-License-Identifier: BSD-2-Clause */
/*
 * Copyright (c) 2021, Linaro Limited
 */

#ifndef __DRIVERS_RSTCTRL_H
#define __DRIVERS_RSTCTRL_H

#include <kernel/dt_driver.h>
#include <stdint.h>
#include <tee_api_types.h>

struct rstctrl;

struct rstctrl_ops {
	/*
	 * Operators on reset control(s) exposed by a reset controller
	 *
	 * @assert_level: Assert reset level on control with a timeout hint
	 * @deassert_level: Deassert reset level on control with a timeout hint
	 * @get_name: Get a string name for the controller, or NULL is none
	 *
	 * Operator functions @assert_level and @deassert_level use arguments:
	 * @rstctrl: Reset controller
	 * @id: Identifier for the reset level control in the reset controller
	 * @to_ms: Timeout in microseconds or RSTCTRL_NO_TIMEOUT, may be ignored
	 * by reset controller.
	 * Return a TEE_Result compliant code.
	 */
	TEE_Result (*assert_level)(struct rstctrl *rstctrl, unsigned int to_us);
	TEE_Result (*deassert_level)(struct rstctrl *rstctrl,
				     unsigned int to_us);
	const char *(*get_name)(struct rstctrl *rstctrl);
};

/*
 * struct rstctrl - Instance of a control exposed by a reset controller
 * @ops: Operators of the reset controller
 * @exclusive: Set when a consumer has exclusive control on the reset level
 */
struct rstctrl {
	const struct rstctrl_ops *ops;
	bool exclusive;
};

/**
 * RSTCTRL_DECLARE - Declare a reset controller driver with a single
 * device tree compatible string.
 *
 * @__name: Reset controller driver name
 * @__compat: Compatible string
 * @__probe: Reset controller probe function
 */
#define RSTCTRL_DT_DECLARE(__name, __compat, __probe) \
	static const struct dt_device_match __name ## _match_table[] = { \
		{ .compatible = __compat }, \
		{ } \
	}; \
	DEFINE_DT_DRIVER(__name ## _dt_driver) = { \
		.name = # __name, \
		.type = DT_DRIVER_RSTCTRL, \
		.match_table = __name ## _match_table, \
		.probe = __probe, \
	}

/*
 * Platform driver may ignore the timeout hint according to their
 * capabilities. RSTCTRL_NO_TIMEOUT specifies no timeout hint.
 */
#define RSTCTRL_NO_TIMEOUT	0

/*
 * rstctrl_assert_to() - Assert reset control possibly with timeout
 * rstctrl_assert() - Assert reset control
 * rstctrl_deassert_to() - Deassert reset control possibly with timeout
 * rstctrl_deassert() - Deassert reset control
 *
 * @rstctrl: Reset controller
 * @to_us: Timeout in microseconds
 * Return a TEE_Result compliant code
 */
static inline TEE_Result rstctrl_assert_to(struct rstctrl *rstctrl,
					   unsigned int to_us)
{
	return rstctrl->ops->assert_level(rstctrl, to_us);
}

static inline TEE_Result rstctrl_assert(struct rstctrl *rstctrl)
{
	return rstctrl_assert_to(rstctrl, RSTCTRL_NO_TIMEOUT);
}

static inline TEE_Result rstctrl_deassert_to(struct rstctrl *rstctrl,
					     unsigned int to_us)
{
	return rstctrl->ops->deassert_level(rstctrl, to_us);
}

static inline TEE_Result rstctrl_deassert(struct rstctrl *rstctrl)
{
	return rstctrl_deassert_to(rstctrl, RSTCTRL_NO_TIMEOUT);
}

/*
 * rstctrl_name() - Get a name for the reset level control or NULL
 *
 * @rstctrl: Reset controller
 * Return a pointer to controller name or NULL
 */
static inline const char *rstctrl_name(struct rstctrl *rstctrl)
{
	if (rstctrl->ops->get_name)
		return rstctrl->ops->get_name(rstctrl);

	return NULL;
}

/**
 * rstctrl_get_exclusive() - Get exclusive access to reset controller
 *
 * @rstctrl: Reset controller
 * Return a TEE_Result compliant value
 */
TEE_Result rstctrl_get_exclusive(struct rstctrl *rstctrl);

/**
 * rstctrl_put_exclusive() - Release exclusive access to target
 *
 * @rstctrl: Reset controller
 */
void rstctrl_put_exclusive(struct rstctrl *rstctrl);

/**
 * rstctrl_ops_is_valid() - Check reset controller ops is valid
 *
 * @ops: Reference to reset controller operator instance
 */
static inline bool rstctrl_ops_is_valid(const struct rstctrl_ops *ops)
{
	return ops && ops->assert_level && ops->deassert_level;
}

#ifdef CFG_DT
/**
 * rstctrl_dt_get_by_index() - Get a reset controller at a specific index in
 * 'resets' property
 *
 * @fdt: Device tree to work on
 * @nodeoffset: Node offset of the subnode containing a 'resets' property
 * @index: Reset controller index in 'resets' property
 * @rstctrl: Output reset controller reference upon success
 *
 * Return TEE_SUCCESS in case of success
 * Return TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized
 * Return TEE_ERROR_ITEM_NOT_FOUND if the resets property does not exist
 * Return a TEE_Result compliant code in case of error
 */
static inline TEE_Result rstctrl_dt_get_by_index(const void *fdt,
						 int nodeoffset,
						 unsigned int index,
						 struct rstctrl **out_rstctrl)
{
	TEE_Result res = TEE_ERROR_GENERIC;
	void *rstctrl = NULL;

	res = dt_driver_device_from_node_idx_prop("resets", fdt, nodeoffset,
						  index, DT_DRIVER_RSTCTRL,
						  &rstctrl);
	if (!res)
		*out_rstctrl = rstctrl;

	return res;
}
#else
static inline TEE_Result rstctrl_dt_get_by_index(const void *fdt __unused,
						 int nodeoffset __unused,
						 unsigned int index __unused,
						 struct rstctrl **ctrl __unused)
{
	return TEE_ERROR_NOT_SUPPORTED;
}
#endif /*CFG_DT*/

/**
 * rstctrl_dt_get_by_name() - Get a reset controller matching a name in the
 * 'reset-names' property
 *
 * @fdt: Device tree to work on
 * @nodeoffset: Node offset of the subnode containing a 'resets' property
 * @name: Reset controller name to get
 * @rstctrl: Output reset controller reference upon success
 *
 * Return TEE_SUCCESS in case of success
 * Return TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized
 * Return TEE_ERROR_ITEM_NOT_FOUND if the reset-names property does not exist
 * Return a TEE_Result compliant code in case of error
 */
TEE_Result rstctrl_dt_get_by_name(const void *fdt, int nodeoffset,
				  const char *name, struct rstctrl **rstctrl);

/**
 * rstctrl_dt_get_func - Typedef of function to get reset controller from
 * devicetree properties
 *
 * @args: Pointer to devicetree description of the reset controller to parse
 * @data: Pointer to data given at rstctrl_register_provider() call
 * @rstctrl: Output reset controller reference upon success
 */
typedef TEE_Result (*rstctrl_dt_get_func)(struct dt_pargs *args, void *data,
					  struct rstctrl **out_rstctrl);

/**
 * rstctrl_register_provider() - Register a reset controller provider
 *
 * @fdt: Device tree to work on
 * @nodeoffset: Node offset of the reset controller
 * @func: Callback to match the reset controller with a struct rstctrl
 * @data: Data which will be passed to the get_dt_rstctrl callback
 * Returns TEE_Result value
 */
static inline TEE_Result rstctrl_register_provider(const void *fdt,
						   int nodeoffset,
						   rstctrl_dt_get_func func,
						   void *data)
{
	return dt_driver_register_provider(fdt, nodeoffset,
					   (get_of_device_func)func, data,
					   DT_DRIVER_RSTCTRL);
}
#endif /* __DRIVERS_RSTCTRL_H */