Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

111 lines
2.9 KiB

/* Copyright (c) 2025 Google LLC.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/reset.h>
#include <zephyr/kernel.h>
struct reset_mmio_dev_config {
uint32_t base;
uint8_t num_resets;
bool active_low;
};
struct reset_mmio_dev_data {
struct k_spinlock lock;
};
static inline int reset_mmio_status(const struct device *dev, uint32_t id, uint8_t *status)
{
const struct reset_mmio_dev_config *config = dev->config;
uint32_t value;
if (id >= config->num_resets) {
return -EINVAL;
}
value = sys_read32(config->base);
*status = FIELD_GET(BIT(id), value);
/* If active low, invert the logic */
if (config->active_low) {
*status = !(*status);
}
return 0;
}
static inline int reset_mmio_update(const struct device *dev, uint32_t id, uint8_t assert)
{
const struct reset_mmio_dev_config *config = dev->config;
struct reset_mmio_dev_data *data = dev->data;
uint32_t value;
bool set;
if (id >= config->num_resets) {
return -EINVAL;
}
/* If active low, invert the logic */
set = config->active_low ? !assert : assert;
K_SPINLOCK(&data->lock) {
value = sys_read32(config->base);
if (set) {
value |= BIT(id);
} else {
value &= ~BIT(id);
}
sys_write32(value, config->base);
}
return 0;
}
static int reset_mmio_line_assert(const struct device *dev, uint32_t id)
{
return reset_mmio_update(dev, id, 1);
}
static int reset_mmio_line_deassert(const struct device *dev, uint32_t id)
{
return reset_mmio_update(dev, id, 0);
}
static int reset_mmio_line_toggle(const struct device *dev, uint32_t id)
{
uint8_t reset_status = 0;
int status;
status = reset_mmio_status(dev, id, &reset_status);
if (status) {
return status;
}
return reset_mmio_update(dev, id, !reset_status);
}
static DEVICE_API(reset, reset_mmio_driver_api) = {
.status = reset_mmio_status,
.line_assert = reset_mmio_line_assert,
.line_deassert = reset_mmio_line_deassert,
.line_toggle = reset_mmio_line_toggle,
};
#define DT_DRV_COMPAT reset_mmio
#define RESET_MMIO_INIT(n) \
BUILD_ASSERT(DT_INST_PROP(n, num_resets) > 0 && DT_INST_PROP(n, num_resets) < 32, \
"num-resets needs to be in [1, 31]."); \
static const struct reset_mmio_dev_config reset_mmio_dev_config_##n = { \
.base = DT_INST_REG_ADDR(n), \
.num_resets = DT_INST_PROP(n, num_resets), \
.active_low = DT_INST_PROP(n, active_low)}; \
static struct reset_mmio_dev_data reset_mmio_dev_data_##n; \
DEVICE_DT_INST_DEFINE(n, NULL, NULL, &reset_mmio_dev_data_##n, &reset_mmio_dev_config_##n, \
POST_KERNEL, CONFIG_RESET_INIT_PRIORITY, &reset_mmio_driver_api);
DT_INST_FOREACH_STATUS_OKAY(RESET_MMIO_INIT)