1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3 * Copyright (c) 2021, Linaro Limited
4 */
5
6 #ifndef __DRIVERS_RSTCTRL_H
7 #define __DRIVERS_RSTCTRL_H
8
9 #include <kernel/dt_driver.h>
10 #include <stdint.h>
11 #include <tee_api_types.h>
12
13 struct rstctrl;
14
15 struct rstctrl_ops {
16 /*
17 * Operators on reset control(s) exposed by a reset controller
18 *
19 * @assert_level: Assert reset level on control with a timeout hint
20 * @deassert_level: Deassert reset level on control with a timeout hint
21 * @get_name: Get a string name for the controller, or NULL is none
22 *
23 * Operator functions @assert_level and @deassert_level use arguments:
24 * @rstctrl: Reset controller
25 * @id: Identifier for the reset level control in the reset controller
26 * @to_ms: Timeout in microseconds or RSTCTRL_NO_TIMEOUT, may be ignored
27 * by reset controller.
28 * Return a TEE_Result compliant code.
29 */
30 TEE_Result (*assert_level)(struct rstctrl *rstctrl, unsigned int to_us);
31 TEE_Result (*deassert_level)(struct rstctrl *rstctrl,
32 unsigned int to_us);
33 const char *(*get_name)(struct rstctrl *rstctrl);
34 };
35
36 /*
37 * struct rstctrl - Instance of a control exposed by a reset controller
38 * @ops: Operators of the reset controller
39 * @exclusive: Set when a consumer has exclusive control on the reset level
40 */
41 struct rstctrl {
42 const struct rstctrl_ops *ops;
43 bool exclusive;
44 };
45
46 /**
47 * RSTCTRL_DECLARE - Declare a reset controller driver with a single
48 * device tree compatible string.
49 *
50 * @__name: Reset controller driver name
51 * @__compat: Compatible string
52 * @__probe: Reset controller probe function
53 */
54 #define RSTCTRL_DT_DECLARE(__name, __compat, __probe) \
55 static const struct dt_device_match __name ## _match_table[] = { \
56 { .compatible = __compat }, \
57 { } \
58 }; \
59 DEFINE_DT_DRIVER(__name ## _dt_driver) = { \
60 .name = # __name, \
61 .type = DT_DRIVER_RSTCTRL, \
62 .match_table = __name ## _match_table, \
63 .probe = __probe, \
64 }
65
66 /*
67 * Platform driver may ignore the timeout hint according to their
68 * capabilities. RSTCTRL_NO_TIMEOUT specifies no timeout hint.
69 */
70 #define RSTCTRL_NO_TIMEOUT 0
71
72 /*
73 * rstctrl_assert_to() - Assert reset control possibly with timeout
74 * rstctrl_assert() - Assert reset control
75 * rstctrl_deassert_to() - Deassert reset control possibly with timeout
76 * rstctrl_deassert() - Deassert reset control
77 *
78 * @rstctrl: Reset controller
79 * @to_us: Timeout in microseconds
80 * Return a TEE_Result compliant code
81 */
rstctrl_assert_to(struct rstctrl * rstctrl,unsigned int to_us)82 static inline TEE_Result rstctrl_assert_to(struct rstctrl *rstctrl,
83 unsigned int to_us)
84 {
85 return rstctrl->ops->assert_level(rstctrl, to_us);
86 }
87
rstctrl_assert(struct rstctrl * rstctrl)88 static inline TEE_Result rstctrl_assert(struct rstctrl *rstctrl)
89 {
90 return rstctrl_assert_to(rstctrl, RSTCTRL_NO_TIMEOUT);
91 }
92
rstctrl_deassert_to(struct rstctrl * rstctrl,unsigned int to_us)93 static inline TEE_Result rstctrl_deassert_to(struct rstctrl *rstctrl,
94 unsigned int to_us)
95 {
96 return rstctrl->ops->deassert_level(rstctrl, to_us);
97 }
98
rstctrl_deassert(struct rstctrl * rstctrl)99 static inline TEE_Result rstctrl_deassert(struct rstctrl *rstctrl)
100 {
101 return rstctrl_deassert_to(rstctrl, RSTCTRL_NO_TIMEOUT);
102 }
103
104 /*
105 * rstctrl_name() - Get a name for the reset level control or NULL
106 *
107 * @rstctrl: Reset controller
108 * Return a pointer to controller name or NULL
109 */
rstctrl_name(struct rstctrl * rstctrl)110 static inline const char *rstctrl_name(struct rstctrl *rstctrl)
111 {
112 if (rstctrl->ops->get_name)
113 return rstctrl->ops->get_name(rstctrl);
114
115 return NULL;
116 }
117
118 /**
119 * rstctrl_get_exclusive() - Get exclusive access to reset controller
120 *
121 * @rstctrl: Reset controller
122 * Return a TEE_Result compliant value
123 */
124 TEE_Result rstctrl_get_exclusive(struct rstctrl *rstctrl);
125
126 /**
127 * rstctrl_put_exclusive() - Release exclusive access to target
128 *
129 * @rstctrl: Reset controller
130 */
131 void rstctrl_put_exclusive(struct rstctrl *rstctrl);
132
133 /**
134 * rstctrl_ops_is_valid() - Check reset controller ops is valid
135 *
136 * @ops: Reference to reset controller operator instance
137 */
rstctrl_ops_is_valid(const struct rstctrl_ops * ops)138 static inline bool rstctrl_ops_is_valid(const struct rstctrl_ops *ops)
139 {
140 return ops && ops->assert_level && ops->deassert_level;
141 }
142
143 #ifdef CFG_DT
144 /**
145 * rstctrl_dt_get_by_index() - Get a reset controller at a specific index in
146 * 'resets' property
147 *
148 * @fdt: Device tree to work on
149 * @nodeoffset: Node offset of the subnode containing a 'resets' property
150 * @index: Reset controller index in 'resets' property
151 * @rstctrl: Output reset controller reference upon success
152 *
153 * Return TEE_SUCCESS in case of success
154 * Return TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized
155 * Return TEE_ERROR_ITEM_NOT_FOUND if the resets property does not exist
156 * Return a TEE_Result compliant code in case of error
157 */
rstctrl_dt_get_by_index(const void * fdt,int nodeoffset,unsigned int index,struct rstctrl ** out_rstctrl)158 static inline TEE_Result rstctrl_dt_get_by_index(const void *fdt,
159 int nodeoffset,
160 unsigned int index,
161 struct rstctrl **out_rstctrl)
162 {
163 TEE_Result res = TEE_ERROR_GENERIC;
164 void *rstctrl = NULL;
165
166 res = dt_driver_device_from_node_idx_prop("resets", fdt, nodeoffset,
167 index, DT_DRIVER_RSTCTRL,
168 &rstctrl);
169 if (!res)
170 *out_rstctrl = rstctrl;
171
172 return res;
173 }
174 #else
rstctrl_dt_get_by_index(const void * fdt __unused,int nodeoffset __unused,unsigned int index __unused,struct rstctrl ** ctrl __unused)175 static inline TEE_Result rstctrl_dt_get_by_index(const void *fdt __unused,
176 int nodeoffset __unused,
177 unsigned int index __unused,
178 struct rstctrl **ctrl __unused)
179 {
180 return TEE_ERROR_NOT_SUPPORTED;
181 }
182 #endif /*CFG_DT*/
183
184 /**
185 * rstctrl_dt_get_by_name() - Get a reset controller matching a name in the
186 * 'reset-names' property
187 *
188 * @fdt: Device tree to work on
189 * @nodeoffset: Node offset of the subnode containing a 'resets' property
190 * @name: Reset controller name to get
191 * @rstctrl: Output reset controller reference upon success
192 *
193 * Return TEE_SUCCESS in case of success
194 * Return TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized
195 * Return TEE_ERROR_ITEM_NOT_FOUND if the reset-names property does not exist
196 * Return a TEE_Result compliant code in case of error
197 */
198 TEE_Result rstctrl_dt_get_by_name(const void *fdt, int nodeoffset,
199 const char *name, struct rstctrl **rstctrl);
200
201 /**
202 * rstctrl_dt_get_func - Typedef of function to get reset controller from
203 * devicetree properties
204 *
205 * @args: Pointer to devicetree description of the reset controller to parse
206 * @data: Pointer to data given at rstctrl_register_provider() call
207 * @rstctrl: Output reset controller reference upon success
208 */
209 typedef TEE_Result (*rstctrl_dt_get_func)(struct dt_pargs *args, void *data,
210 struct rstctrl **out_rstctrl);
211
212 /**
213 * rstctrl_register_provider() - Register a reset controller provider
214 *
215 * @fdt: Device tree to work on
216 * @nodeoffset: Node offset of the reset controller
217 * @func: Callback to match the reset controller with a struct rstctrl
218 * @data: Data which will be passed to the get_dt_rstctrl callback
219 * Returns TEE_Result value
220 */
rstctrl_register_provider(const void * fdt,int nodeoffset,rstctrl_dt_get_func func,void * data)221 static inline TEE_Result rstctrl_register_provider(const void *fdt,
222 int nodeoffset,
223 rstctrl_dt_get_func func,
224 void *data)
225 {
226 return dt_driver_register_provider(fdt, nodeoffset,
227 (get_of_device_func)func, data,
228 DT_DRIVER_RSTCTRL);
229 }
230 #endif /* __DRIVERS_RSTCTRL_H */
231