| /* |
| * Copyright (c) 2022 Andrei-Edward Popa <andrei.popa105@yahoo.com> |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** |
| * @file |
| * @brief Public Reset Controller driver APIs |
| */ |
| |
| #ifndef ZEPHYR_INCLUDE_DRIVERS_RESET_H_ |
| #define ZEPHYR_INCLUDE_DRIVERS_RESET_H_ |
| |
| /** |
| * @brief Reset Controller Interface |
| * @defgroup reset_controller_interface Reset Controller Interface |
| * @since 3.1 |
| * @version 0.2.0 |
| * @ingroup io_interfaces |
| * @{ |
| */ |
| |
| #include <errno.h> |
| |
| #include <zephyr/types.h> |
| #include <zephyr/device.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /** Reset controller device configuration. */ |
| struct reset_dt_spec { |
| /** Reset controller device. */ |
| const struct device *dev; |
| /** Reset line. */ |
| uint32_t id; |
| }; |
| |
| /** |
| * @brief Static initializer for a @p reset_dt_spec |
| * |
| * This returns a static initializer for a @p reset_dt_spec structure given a |
| * devicetree node identifier, a property specifying a Reset Controller and an index. |
| * |
| * Example devicetree fragment: |
| * |
| * n: node { |
| * resets = <&reset 10>; |
| * } |
| * |
| * Example usage: |
| * |
| * const struct reset_dt_spec spec = RESET_DT_SPEC_GET_BY_IDX(DT_NODELABEL(n), 0); |
| * // Initializes 'spec' to: |
| * // { |
| * // .dev = DEVICE_DT_GET(DT_NODELABEL(reset)), |
| * // .id = 10 |
| * // } |
| * |
| * The 'reset' field must still be checked for readiness, e.g. using |
| * device_is_ready(). It is an error to use this macro unless the node |
| * exists, has the given property, and that property specifies a reset |
| * controller reset line id as shown above. |
| * |
| * @param node_id devicetree node identifier |
| * @param idx logical index into "resets" |
| * @return static initializer for a struct reset_dt_spec for the property |
| */ |
| #define RESET_DT_SPEC_GET_BY_IDX(node_id, idx) \ |
| { \ |
| .dev = DEVICE_DT_GET(DT_RESET_CTLR_BY_IDX(node_id, idx)), \ |
| .id = DT_RESET_ID_BY_IDX(node_id, idx) \ |
| } |
| |
| /** |
| * @brief Like RESET_DT_SPEC_GET_BY_IDX(), with a fallback to a default value |
| * |
| * If the devicetree node identifier 'node_id' refers to a node with a |
| * 'resets' property, this expands to |
| * <tt>RESET_DT_SPEC_GET_BY_IDX(node_id, idx)</tt>. The @p |
| * default_value parameter is not expanded in this case. |
| * |
| * Otherwise, this expands to @p default_value. |
| * |
| * @param node_id devicetree node identifier |
| * @param idx logical index into the 'resets' property |
| * @param default_value fallback value to expand to |
| * @return static initializer for a struct reset_dt_spec for the property, |
| * or default_value if the node or property do not exist |
| */ |
| #define RESET_DT_SPEC_GET_BY_IDX_OR(node_id, idx, default_value) \ |
| COND_CODE_1(DT_NODE_HAS_PROP(node_id, resets), \ |
| (RESET_DT_SPEC_GET_BY_IDX(node_id, idx)), \ |
| (default_value)) |
| |
| /** |
| * @brief Equivalent to RESET_DT_SPEC_GET_BY_IDX(node_id, 0). |
| * |
| * @param node_id devicetree node identifier |
| * @return static initializer for a struct reset_dt_spec for the property |
| * @see RESET_DT_SPEC_GET_BY_IDX() |
| */ |
| #define RESET_DT_SPEC_GET(node_id) \ |
| RESET_DT_SPEC_GET_BY_IDX(node_id, 0) |
| |
| /** |
| * @brief Equivalent to |
| * RESET_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value). |
| * |
| * @param node_id devicetree node identifier |
| * @param default_value fallback value to expand to |
| * @return static initializer for a struct reset_dt_spec for the property, |
| * or default_value if the node or property do not exist |
| */ |
| #define RESET_DT_SPEC_GET_OR(node_id, default_value) \ |
| RESET_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value) |
| |
| /** |
| * @brief Static initializer for a @p reset_dt_spec from a DT_DRV_COMPAT |
| * instance's Reset Controller property at an index. |
| * |
| * @param inst DT_DRV_COMPAT instance number |
| * @param idx logical index into "resets" |
| * @return static initializer for a struct reset_dt_spec for the property |
| * @see RESET_DT_SPEC_GET_BY_IDX() |
| */ |
| #define RESET_DT_SPEC_INST_GET_BY_IDX(inst, idx) \ |
| RESET_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx) |
| |
| /** |
| * @brief Static initializer for a @p reset_dt_spec from a DT_DRV_COMPAT |
| * instance's 'resets' property at an index, with fallback |
| * |
| * @param inst DT_DRV_COMPAT instance number |
| * @param idx logical index into the 'resets' property |
| * @param default_value fallback value to expand to |
| * @return static initializer for a struct reset_dt_spec for the property, |
| * or default_value if the node or property do not exist |
| */ |
| #define RESET_DT_SPEC_INST_GET_BY_IDX_OR(inst, idx, default_value) \ |
| COND_CODE_1(DT_PROP_HAS_IDX(DT_DRV_INST(inst), resets, idx), \ |
| (RESET_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx)), \ |
| (default_value)) |
| |
| /** |
| * @brief Equivalent to RESET_DT_SPEC_INST_GET_BY_IDX(inst, 0). |
| * |
| * @param inst DT_DRV_COMPAT instance number |
| * @return static initializer for a struct reset_dt_spec for the property |
| * @see RESET_DT_SPEC_INST_GET_BY_IDX() |
| */ |
| #define RESET_DT_SPEC_INST_GET(inst) \ |
| RESET_DT_SPEC_INST_GET_BY_IDX(inst, 0) |
| |
| /** |
| * @brief Equivalent to |
| * RESET_DT_SPEC_INST_GET_BY_IDX_OR(node_id, 0, default_value). |
| * |
| * @param inst DT_DRV_COMPAT instance number |
| * @param default_value fallback value to expand to |
| * @return static initializer for a struct reset_dt_spec for the property, |
| * or default_value if the node or property do not exist |
| */ |
| #define RESET_DT_SPEC_INST_GET_OR(inst, default_value) \ |
| RESET_DT_SPEC_INST_GET_BY_IDX_OR(inst, 0, default_value) |
| |
| /** @cond INTERNAL_HIDDEN */ |
| |
| /** |
| * API template to get the reset status of the device. |
| * |
| * @see reset_status |
| */ |
| typedef int (*reset_api_status)(const struct device *dev, uint32_t id, uint8_t *status); |
| |
| /** |
| * API template to put the device in reset state. |
| * |
| * @see reset_line_assert |
| */ |
| typedef int (*reset_api_line_assert)(const struct device *dev, uint32_t id); |
| |
| /** |
| * API template to take out the device from reset state. |
| * |
| * @see reset_line_deassert |
| */ |
| typedef int (*reset_api_line_deassert)(const struct device *dev, uint32_t id); |
| |
| /** |
| * API template to reset the device. |
| * |
| * @see reset_line_toggle |
| */ |
| typedef int (*reset_api_line_toggle)(const struct device *dev, uint32_t id); |
| |
| /** |
| * @brief Reset Controller driver API |
| */ |
| __subsystem struct reset_driver_api { |
| reset_api_status status; |
| reset_api_line_assert line_assert; |
| reset_api_line_deassert line_deassert; |
| reset_api_line_toggle line_toggle; |
| }; |
| |
| /** @endcond */ |
| |
| /** |
| * @brief Get the reset status |
| * |
| * This function returns the reset status of the device. |
| * |
| * @param dev Reset controller device. |
| * @param id Reset line. |
| * @param status Where to write the reset status. |
| * |
| * @retval 0 On success. |
| * @retval -ENOSYS If the functionality is not implemented by the driver. |
| * @retval -errno Other negative errno in case of failure. |
| */ |
| __syscall int reset_status(const struct device *dev, uint32_t id, uint8_t *status); |
| |
| static inline int z_impl_reset_status(const struct device *dev, uint32_t id, uint8_t *status) |
| { |
| const struct reset_driver_api *api = (const struct reset_driver_api *)dev->api; |
| |
| if (api->status == NULL) { |
| return -ENOSYS; |
| } |
| |
| return api->status(dev, id, status); |
| } |
| |
| /** |
| * @brief Get the reset status from a @p reset_dt_spec. |
| * |
| * This is equivalent to: |
| * |
| * reset_status(spec->dev, spec->id, status); |
| * |
| * @param spec Reset controller specification from devicetree |
| * @param status Where to write the reset status. |
| * |
| * @return a value from reset_status() |
| */ |
| static inline int reset_status_dt(const struct reset_dt_spec *spec, uint8_t *status) |
| { |
| return reset_status(spec->dev, spec->id, status); |
| } |
| |
| /** |
| * @brief Put the device in reset state |
| * |
| * This function sets/clears the reset bits of the device, |
| * depending on the logic level (active-high/active-low). |
| * |
| * @param dev Reset controller device. |
| * @param id Reset line. |
| * |
| * @retval 0 On success. |
| * @retval -ENOSYS If the functionality is not implemented by the driver. |
| * @retval -errno Other negative errno in case of failure. |
| */ |
| __syscall int reset_line_assert(const struct device *dev, uint32_t id); |
| |
| static inline int z_impl_reset_line_assert(const struct device *dev, uint32_t id) |
| { |
| const struct reset_driver_api *api = (const struct reset_driver_api *)dev->api; |
| |
| if (api->line_assert == NULL) { |
| return -ENOSYS; |
| } |
| |
| return api->line_assert(dev, id); |
| } |
| |
| /** |
| * @brief Assert the reset state from a @p reset_dt_spec. |
| * |
| * This is equivalent to: |
| * |
| * reset_line_assert(spec->dev, spec->id); |
| * |
| * @param spec Reset controller specification from devicetree |
| * |
| * @return a value from reset_line_assert() |
| */ |
| static inline int reset_line_assert_dt(const struct reset_dt_spec *spec) |
| { |
| return reset_line_assert(spec->dev, spec->id); |
| } |
| |
| /** |
| * @brief Take out the device from reset state. |
| * |
| * This function sets/clears the reset bits of the device, |
| * depending on the logic level (active-low/active-high). |
| * |
| * @param dev Reset controller device. |
| * @param id Reset line. |
| * |
| * @retval 0 On success. |
| * @retval -ENOSYS If the functionality is not implemented by the driver. |
| * @retval -errno Other negative errno in case of failure. |
| */ |
| __syscall int reset_line_deassert(const struct device *dev, uint32_t id); |
| |
| static inline int z_impl_reset_line_deassert(const struct device *dev, uint32_t id) |
| { |
| const struct reset_driver_api *api = (const struct reset_driver_api *)dev->api; |
| |
| if (api->line_deassert == NULL) { |
| return -ENOSYS; |
| } |
| |
| return api->line_deassert(dev, id); |
| } |
| |
| /** |
| * @brief Deassert the reset state from a @p reset_dt_spec. |
| * |
| * This is equivalent to: |
| * |
| * reset_line_deassert(spec->dev, spec->id) |
| * |
| * @param spec Reset controller specification from devicetree |
| * |
| * @return a value from reset_line_deassert() |
| */ |
| static inline int reset_line_deassert_dt(const struct reset_dt_spec *spec) |
| { |
| return reset_line_deassert(spec->dev, spec->id); |
| } |
| |
| /** |
| * @brief Reset the device. |
| * |
| * This function performs reset for a device (assert + deassert). |
| * |
| * @param dev Reset controller device. |
| * @param id Reset line. |
| * |
| * @retval 0 On success. |
| * @retval -ENOSYS If the functionality is not implemented by the driver. |
| * @retval -errno Other negative errno in case of failure. |
| */ |
| __syscall int reset_line_toggle(const struct device *dev, uint32_t id); |
| |
| static inline int z_impl_reset_line_toggle(const struct device *dev, uint32_t id) |
| { |
| const struct reset_driver_api *api = (const struct reset_driver_api *)dev->api; |
| |
| if (api->line_toggle == NULL) { |
| return -ENOSYS; |
| } |
| |
| return api->line_toggle(dev, id); |
| } |
| |
| /** |
| * @brief Reset the device from a @p reset_dt_spec. |
| * |
| * This is equivalent to: |
| * |
| * reset_line_toggle(spec->dev, spec->id) |
| * |
| * @param spec Reset controller specification from devicetree |
| * |
| * @return a value from reset_line_toggle() |
| */ |
| static inline int reset_line_toggle_dt(const struct reset_dt_spec *spec) |
| { |
| return reset_line_toggle(spec->dev, spec->id); |
| } |
| |
| /** |
| * @} |
| */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #include <zephyr/syscalls/reset.h> |
| |
| #endif /* ZEPHYR_INCLUDE_DRIVERS_RESET_H_ */ |