1 /*
2 * Copyright (c) 2022 Andrei-Edward Popa <andrei.popa105@yahoo.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Public Reset Controller driver APIs
10 */
11
12 #ifndef ZEPHYR_INCLUDE_DRIVERS_RESET_H_
13 #define ZEPHYR_INCLUDE_DRIVERS_RESET_H_
14
15 /**
16 * @brief Reset Controller Interface
17 * @defgroup reset_controller_interface Reset Controller Interface
18 * @ingroup io_interfaces
19 * @{
20 */
21
22 #include <errno.h>
23
24 #include <zephyr/types.h>
25 #include <zephyr/device.h>
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30
31 /** Reset controller device configuration. */
32 struct reset_dt_spec {
33 /** Reset controller device. */
34 const struct device *dev;
35 /** Reset line. */
36 uint32_t id;
37 };
38
39 /**
40 * @brief Static initializer for a @p reset_dt_spec
41 *
42 * This returns a static initializer for a @p reset_dt_spec structure given a
43 * devicetree node identifier, a property specifying a Reset Controller and an index.
44 *
45 * Example devicetree fragment:
46 *
47 * n: node {
48 * resets = <&reset 10>;
49 * }
50 *
51 * Example usage:
52 *
53 * const struct reset_dt_spec spec = RESET_DT_SPEC_GET_BY_IDX(DT_NODELABEL(n), 0);
54 * // Initializes 'spec' to:
55 * // {
56 * // .dev = DEVICE_DT_GET(DT_NODELABEL(reset)),
57 * // .id = 10
58 * // }
59 *
60 * The 'reset' field must still be checked for readiness, e.g. using
61 * device_is_ready(). It is an error to use this macro unless the node
62 * exists, has the given property, and that property specifies a reset
63 * controller reset line id as shown above.
64 *
65 * @param node_id devicetree node identifier
66 * @param idx logical index into "resets"
67 * @return static initializer for a struct reset_dt_spec for the property
68 */
69 #define RESET_DT_SPEC_GET_BY_IDX(node_id, idx) \
70 { \
71 .dev = DEVICE_DT_GET(DT_RESET_CTLR_BY_IDX(node_id, idx)), \
72 .id = DT_RESET_ID_BY_IDX(node_id, idx) \
73 }
74
75 /**
76 * @brief Equivalent to RESET_DT_SPEC_GET_BY_IDX(node_id, 0).
77 *
78 * @param node_id devicetree node identifier
79 * @return static initializer for a struct reset_dt_spec for the property
80 * @see RESET_DT_SPEC_GET_BY_IDX()
81 */
82 #define RESET_DT_SPEC_GET(node_id) \
83 RESET_DT_SPEC_GET_BY_IDX(node_id, 0)
84
85 /**
86 * @brief Static initializer for a @p reset_dt_spec from a DT_DRV_COMPAT
87 * instance's Reset Controller property at an index.
88 *
89 * @param inst DT_DRV_COMPAT instance number
90 * @param idx logical index into "resets"
91 * @return static initializer for a struct reset_dt_spec for the property
92 * @see RESET_DT_SPEC_GET_BY_IDX()
93 */
94 #define RESET_DT_SPEC_INST_GET_BY_IDX(inst, idx) \
95 RESET_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx)
96
97 /**
98 * @brief Equivalent to RESET_DT_SPEC_INST_GET_BY_IDX(inst, 0).
99 *
100 * @param inst DT_DRV_COMPAT instance number
101 * @return static initializer for a struct reset_dt_spec for the property
102 * @see RESET_DT_SPEC_INST_GET_BY_IDX()
103 */
104 #define RESET_DT_SPEC_INST_GET(inst) \
105 RESET_DT_SPEC_INST_GET_BY_IDX(inst, 0)
106
107 /** @cond INTERNAL_HIDDEN */
108
109 /**
110 * API template to get the reset status of the device.
111 *
112 * @see reset_status
113 */
114 typedef int (*reset_api_status)(const struct device *dev, uint32_t id, uint8_t *status);
115
116 /**
117 * API template to put the device in reset state.
118 *
119 * @see reset_line_assert
120 */
121 typedef int (*reset_api_line_assert)(const struct device *dev, uint32_t id);
122
123 /**
124 * API template to take out the device from reset state.
125 *
126 * @see reset_line_deassert
127 */
128 typedef int (*reset_api_line_deassert)(const struct device *dev, uint32_t id);
129
130 /**
131 * API template to reset the device.
132 *
133 * @see reset_line_toggle
134 */
135 typedef int (*reset_api_line_toggle)(const struct device *dev, uint32_t id);
136
137 /**
138 * @brief Reset Controller driver API
139 */
140 __subsystem struct reset_driver_api {
141 reset_api_status status;
142 reset_api_line_assert line_assert;
143 reset_api_line_deassert line_deassert;
144 reset_api_line_toggle line_toggle;
145 };
146
147 /** @endcond */
148
149 /**
150 * @brief Get the reset status
151 *
152 * This function returns the reset status of the device.
153 *
154 * @param dev Reset controller device.
155 * @param id Reset line.
156 * @param status Where to write the reset status.
157 *
158 * @retval 0 On success.
159 * @retval -ENOSYS If the functionality is not implemented by the driver.
160 * @retval -errno Other negative errno in case of failure.
161 */
162 __syscall int reset_status(const struct device *dev, uint32_t id, uint8_t *status);
163
z_impl_reset_status(const struct device * dev,uint32_t id,uint8_t * status)164 static inline int z_impl_reset_status(const struct device *dev, uint32_t id, uint8_t *status)
165 {
166 const struct reset_driver_api *api = (const struct reset_driver_api *)dev->api;
167
168 if (api->status == NULL) {
169 return -ENOSYS;
170 }
171
172 return api->status(dev, id, status);
173 }
174
175 /**
176 * @brief Get the reset status from a @p reset_dt_spec.
177 *
178 * This is equivalent to:
179 *
180 * reset_status(spec->dev, spec->id, status);
181 *
182 * @param spec Reset controller specification from devicetree
183 * @param status Where to write the reset status.
184 *
185 * @return a value from reset_status()
186 */
reset_status_dt(const struct reset_dt_spec * spec,uint8_t * status)187 static inline int reset_status_dt(const struct reset_dt_spec *spec, uint8_t *status)
188 {
189 return reset_status(spec->dev, spec->id, status);
190 }
191
192 /**
193 * @brief Put the device in reset state
194 *
195 * This function sets/clears the reset bits of the device,
196 * depending on the logic level (active-high/active-low).
197 *
198 * @param dev Reset controller device.
199 * @param id Reset line.
200 *
201 * @retval 0 On success.
202 * @retval -ENOSYS If the functionality is not implemented by the driver.
203 * @retval -errno Other negative errno in case of failure.
204 */
205 __syscall int reset_line_assert(const struct device *dev, uint32_t id);
206
z_impl_reset_line_assert(const struct device * dev,uint32_t id)207 static inline int z_impl_reset_line_assert(const struct device *dev, uint32_t id)
208 {
209 const struct reset_driver_api *api = (const struct reset_driver_api *)dev->api;
210
211 if (api->line_assert == NULL) {
212 return -ENOSYS;
213 }
214
215 return api->line_assert(dev, id);
216 }
217
218 /**
219 * @brief Assert the reset state from a @p reset_dt_spec.
220 *
221 * This is equivalent to:
222 *
223 * reset_line_assert(spec->dev, spec->id);
224 *
225 * @param spec Reset controller specification from devicetree
226 *
227 * @return a value from reset_line_assert()
228 */
reset_line_assert_dt(const struct reset_dt_spec * spec)229 static inline int reset_line_assert_dt(const struct reset_dt_spec *spec)
230 {
231 return reset_line_assert(spec->dev, spec->id);
232 }
233
234 /**
235 * @brief Take out the device from reset state.
236 *
237 * This function sets/clears the reset bits of the device,
238 * depending on the logic level (active-low/active-high).
239 *
240 * @param dev Reset controller device.
241 * @param id Reset line.
242 *
243 * @retval 0 On success.
244 * @retval -ENOSYS If the functionality is not implemented by the driver.
245 * @retval -errno Other negative errno in case of failure.
246 */
247 __syscall int reset_line_deassert(const struct device *dev, uint32_t id);
248
z_impl_reset_line_deassert(const struct device * dev,uint32_t id)249 static inline int z_impl_reset_line_deassert(const struct device *dev, uint32_t id)
250 {
251 const struct reset_driver_api *api = (const struct reset_driver_api *)dev->api;
252
253 if (api->line_deassert == NULL) {
254 return -ENOSYS;
255 }
256
257 return api->line_deassert(dev, id);
258 }
259
260 /**
261 * @brief Deassert the reset state from a @p reset_dt_spec.
262 *
263 * This is equivalent to:
264 *
265 * reset_line_deassert(spec->dev, spec->id)
266 *
267 * @param spec Reset controller specification from devicetree
268 *
269 * @return a value from reset_line_deassert()
270 */
reset_line_deassert_dt(const struct reset_dt_spec * spec)271 static inline int reset_line_deassert_dt(const struct reset_dt_spec *spec)
272 {
273 return reset_line_deassert(spec->dev, spec->id);
274 }
275
276 /**
277 * @brief Reset the device.
278 *
279 * This function performs reset for a device (assert + deassert).
280 *
281 * @param dev Reset controller device.
282 * @param id Reset line.
283 *
284 * @retval 0 On success.
285 * @retval -ENOSYS If the functionality is not implemented by the driver.
286 * @retval -errno Other negative errno in case of failure.
287 */
288 __syscall int reset_line_toggle(const struct device *dev, uint32_t id);
289
z_impl_reset_line_toggle(const struct device * dev,uint32_t id)290 static inline int z_impl_reset_line_toggle(const struct device *dev, uint32_t id)
291 {
292 const struct reset_driver_api *api = (const struct reset_driver_api *)dev->api;
293
294 if (api->line_toggle == NULL) {
295 return -ENOSYS;
296 }
297
298 return api->line_toggle(dev, id);
299 }
300
301 /**
302 * @brief Reset the device from a @p reset_dt_spec.
303 *
304 * This is equivalent to:
305 *
306 * reset_line_toggle(spec->dev, spec->id)
307 *
308 * @param spec Reset controller specification from devicetree
309 *
310 * @return a value from reset_line_toggle()
311 */
reset_line_toggle_dt(const struct reset_dt_spec * spec)312 static inline int reset_line_toggle_dt(const struct reset_dt_spec *spec)
313 {
314 return reset_line_toggle(spec->dev, spec->id);
315 }
316
317 /**
318 * @}
319 */
320
321 #ifdef __cplusplus
322 }
323 #endif
324
325 #include <syscalls/reset.h>
326
327 #endif /* ZEPHYR_INCLUDE_DRIVERS_RESET_H_ */
328