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