blob: 0bf2031b9ccf995426d9d2d65132492fb12465ad [file] [log] [blame]
/*
* 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_ */