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