xref: /optee_os/core/include/drivers/rstctrl.h (revision f84c5df41de3ce78ee6c9b14d43335067bc51cb9)
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