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