/* * 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 * @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 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 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 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) /** @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 <syscalls/reset.h> #endif /* ZEPHYR_INCLUDE_DRIVERS_RESET_H_ */