2022-03-22 01:25:39 +01:00
|
|
|
/*
|
|
|
|
* 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
|
2023-08-26 00:24:48 +02:00
|
|
|
* @since 3.1
|
2024-05-01 02:11:53 +02:00
|
|
|
* @version 0.2.0
|
2022-03-22 01:25:39 +01:00
|
|
|
* @ingroup io_interfaces
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2022-10-04 14:43:49 +02:00
|
|
|
#include <errno.h>
|
|
|
|
|
2022-03-22 01:25:39 +01:00
|
|
|
#include <zephyr/types.h>
|
2022-04-21 06:07:09 +02:00
|
|
|
#include <zephyr/device.h>
|
2022-03-22 01:25:39 +01:00
|
|
|
|
|
|
|
#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) \
|
|
|
|
}
|
|
|
|
|
2024-05-01 02:11:53 +02:00
|
|
|
/**
|
|
|
|
* @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))
|
|
|
|
|
2022-03-22 01:25:39 +01:00
|
|
|
/**
|
|
|
|
* @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)
|
|
|
|
|
2024-05-01 02:11:53 +02:00
|
|
|
/**
|
|
|
|
* @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)
|
|
|
|
|
2022-03-22 01:25:39 +01:00
|
|
|
/**
|
|
|
|
* @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)
|
|
|
|
|
2024-05-01 02:11:53 +02:00
|
|
|
/**
|
|
|
|
* @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))
|
|
|
|
|
2022-03-22 01:25:39 +01:00
|
|
|
/**
|
|
|
|
* @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)
|
|
|
|
|
2024-05-01 02:11:53 +02:00
|
|
|
/**
|
|
|
|
* @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)
|
|
|
|
|
2022-03-22 01:25:39 +01:00
|
|
|
/** @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.
|
|
|
|
*
|
2022-05-26 18:10:57 +02:00
|
|
|
* @see reset_line_assert
|
2022-03-22 01:25:39 +01:00
|
|
|
*/
|
2022-05-26 18:10:57 +02:00
|
|
|
typedef int (*reset_api_line_assert)(const struct device *dev, uint32_t id);
|
2022-03-22 01:25:39 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* API template to take out the device from reset state.
|
|
|
|
*
|
2022-05-26 18:10:57 +02:00
|
|
|
* @see reset_line_deassert
|
2022-03-22 01:25:39 +01:00
|
|
|
*/
|
2022-05-26 18:10:57 +02:00
|
|
|
typedef int (*reset_api_line_deassert)(const struct device *dev, uint32_t id);
|
2022-03-22 01:25:39 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* API template to reset the device.
|
|
|
|
*
|
2022-05-26 18:10:57 +02:00
|
|
|
* @see reset_line_toggle
|
2022-03-22 01:25:39 +01:00
|
|
|
*/
|
2022-05-26 18:10:57 +02:00
|
|
|
typedef int (*reset_api_line_toggle)(const struct device *dev, uint32_t id);
|
2022-03-22 01:25:39 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Reset Controller driver API
|
|
|
|
*/
|
|
|
|
__subsystem struct reset_driver_api {
|
|
|
|
reset_api_status status;
|
2022-05-26 18:10:57 +02:00
|
|
|
reset_api_line_assert line_assert;
|
|
|
|
reset_api_line_deassert line_deassert;
|
|
|
|
reset_api_line_toggle line_toggle;
|
2022-03-22 01:25:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/** @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)
|
|
|
|
{
|
2022-04-07 10:55:07 +02:00
|
|
|
const struct reset_driver_api *api = (const struct reset_driver_api *)dev->api;
|
2022-03-22 01:25:39 +01:00
|
|
|
|
2022-04-07 10:55:07 +02:00
|
|
|
if (api->status == NULL) {
|
2022-03-22 01:25:39 +01:00
|
|
|
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.
|
|
|
|
*/
|
2022-05-26 18:10:57 +02:00
|
|
|
__syscall int reset_line_assert(const struct device *dev, uint32_t id);
|
2022-03-22 01:25:39 +01:00
|
|
|
|
2022-05-26 18:10:57 +02:00
|
|
|
static inline int z_impl_reset_line_assert(const struct device *dev, uint32_t id)
|
2022-03-22 01:25:39 +01:00
|
|
|
{
|
2022-04-07 10:55:07 +02:00
|
|
|
const struct reset_driver_api *api = (const struct reset_driver_api *)dev->api;
|
2022-03-22 01:25:39 +01:00
|
|
|
|
2022-05-26 18:10:57 +02:00
|
|
|
if (api->line_assert == NULL) {
|
2022-03-22 01:25:39 +01:00
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2022-05-26 18:10:57 +02:00
|
|
|
return api->line_assert(dev, id);
|
2022-03-22 01:25:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Assert the reset state from a @p reset_dt_spec.
|
|
|
|
*
|
|
|
|
* This is equivalent to:
|
|
|
|
*
|
2022-05-26 18:10:57 +02:00
|
|
|
* reset_line_assert(spec->dev, spec->id);
|
2022-03-22 01:25:39 +01:00
|
|
|
*
|
|
|
|
* @param spec Reset controller specification from devicetree
|
|
|
|
*
|
2022-05-26 18:10:57 +02:00
|
|
|
* @return a value from reset_line_assert()
|
2022-03-22 01:25:39 +01:00
|
|
|
*/
|
2022-05-26 18:10:57 +02:00
|
|
|
static inline int reset_line_assert_dt(const struct reset_dt_spec *spec)
|
2022-03-22 01:25:39 +01:00
|
|
|
{
|
2022-05-26 18:10:57 +02:00
|
|
|
return reset_line_assert(spec->dev, spec->id);
|
2022-03-22 01:25:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2022-05-26 18:10:57 +02:00
|
|
|
__syscall int reset_line_deassert(const struct device *dev, uint32_t id);
|
2022-03-22 01:25:39 +01:00
|
|
|
|
2022-05-26 18:10:57 +02:00
|
|
|
static inline int z_impl_reset_line_deassert(const struct device *dev, uint32_t id)
|
2022-03-22 01:25:39 +01:00
|
|
|
{
|
2022-04-07 10:55:07 +02:00
|
|
|
const struct reset_driver_api *api = (const struct reset_driver_api *)dev->api;
|
2022-03-22 01:25:39 +01:00
|
|
|
|
2022-05-26 18:10:57 +02:00
|
|
|
if (api->line_deassert == NULL) {
|
2022-03-22 01:25:39 +01:00
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2022-05-26 18:10:57 +02:00
|
|
|
return api->line_deassert(dev, id);
|
2022-03-22 01:25:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Deassert the reset state from a @p reset_dt_spec.
|
|
|
|
*
|
|
|
|
* This is equivalent to:
|
|
|
|
*
|
2022-05-26 18:10:57 +02:00
|
|
|
* reset_line_deassert(spec->dev, spec->id)
|
2022-03-22 01:25:39 +01:00
|
|
|
*
|
|
|
|
* @param spec Reset controller specification from devicetree
|
|
|
|
*
|
2022-05-26 18:10:57 +02:00
|
|
|
* @return a value from reset_line_deassert()
|
2022-03-22 01:25:39 +01:00
|
|
|
*/
|
2022-05-26 18:10:57 +02:00
|
|
|
static inline int reset_line_deassert_dt(const struct reset_dt_spec *spec)
|
2022-03-22 01:25:39 +01:00
|
|
|
{
|
2022-05-26 18:10:57 +02:00
|
|
|
return reset_line_deassert(spec->dev, spec->id);
|
2022-03-22 01:25:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @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.
|
|
|
|
*/
|
2022-05-26 18:10:57 +02:00
|
|
|
__syscall int reset_line_toggle(const struct device *dev, uint32_t id);
|
2022-03-22 01:25:39 +01:00
|
|
|
|
2022-05-26 18:10:57 +02:00
|
|
|
static inline int z_impl_reset_line_toggle(const struct device *dev, uint32_t id)
|
2022-03-22 01:25:39 +01:00
|
|
|
{
|
2022-04-07 10:55:07 +02:00
|
|
|
const struct reset_driver_api *api = (const struct reset_driver_api *)dev->api;
|
2022-03-22 01:25:39 +01:00
|
|
|
|
2022-05-26 18:10:57 +02:00
|
|
|
if (api->line_toggle == NULL) {
|
2022-03-22 01:25:39 +01:00
|
|
|
return -ENOSYS;
|
|
|
|
}
|
|
|
|
|
2022-05-26 18:10:57 +02:00
|
|
|
return api->line_toggle(dev, id);
|
2022-03-22 01:25:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Reset the device from a @p reset_dt_spec.
|
|
|
|
*
|
|
|
|
* This is equivalent to:
|
|
|
|
*
|
2022-05-26 18:10:57 +02:00
|
|
|
* reset_line_toggle(spec->dev, spec->id)
|
2022-03-22 01:25:39 +01:00
|
|
|
*
|
|
|
|
* @param spec Reset controller specification from devicetree
|
|
|
|
*
|
2022-05-26 18:10:57 +02:00
|
|
|
* @return a value from reset_line_toggle()
|
2022-03-22 01:25:39 +01:00
|
|
|
*/
|
2022-05-26 18:10:57 +02:00
|
|
|
static inline int reset_line_toggle_dt(const struct reset_dt_spec *spec)
|
2022-03-22 01:25:39 +01:00
|
|
|
{
|
2022-05-26 18:10:57 +02:00
|
|
|
return reset_line_toggle(spec->dev, spec->id);
|
2022-03-22 01:25:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2024-01-24 10:35:04 +01:00
|
|
|
#include <zephyr/syscalls/reset.h>
|
2022-03-22 01:25:39 +01:00
|
|
|
|
|
|
|
#endif /* ZEPHYR_INCLUDE_DRIVERS_RESET_H_ */
|