2022-11-21 16:56:56 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2022 ASPEED Technology Inc.
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define DT_DRV_COMPAT aspeed_ast10x0_reset
|
|
|
|
#include <errno.h>
|
|
|
|
#include <zephyr/dt-bindings/reset/ast10x0_reset.h>
|
|
|
|
#include <zephyr/drivers/reset.h>
|
|
|
|
#include <zephyr/drivers/syscon.h>
|
|
|
|
#include <zephyr/sys/util.h>
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* RESET_CTRL0/1_ASSERT registers:
|
|
|
|
* - Each bit in these registers controls a reset line
|
|
|
|
* - Write '1' to a bit: assert the corresponding reset line
|
|
|
|
* - Write '0' to a bit: no effect
|
|
|
|
* RESET_CTRL0/1_DEASSERT register:
|
|
|
|
* - Write '1' to a bit: clear the corresponding bit in RESET_CTRL0/1_ASSERT.
|
|
|
|
* (deassert the corresponding reset line)
|
|
|
|
*/
|
|
|
|
#define RESET_CTRL0_ASSERT 0x40
|
|
|
|
#define RESET_CTRL0_DEASSERT 0x44
|
|
|
|
#define RESET_CTRL1_ASSERT 0x50
|
|
|
|
#define RESET_CTRL1_DEASSERT 0x54
|
|
|
|
|
|
|
|
struct reset_aspeed_config {
|
|
|
|
const struct device *syscon;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int aspeed_reset_line_assert(const struct device *dev, uint32_t id)
|
|
|
|
{
|
|
|
|
const struct reset_aspeed_config *config = dev->config;
|
|
|
|
const struct device *syscon = config->syscon;
|
|
|
|
uint32_t addr = RESET_CTRL0_ASSERT;
|
|
|
|
|
|
|
|
if (id >= ASPEED_RESET_GRP_1_OFFSET) {
|
|
|
|
id -= ASPEED_RESET_GRP_1_OFFSET;
|
|
|
|
addr = RESET_CTRL1_ASSERT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return syscon_write_reg(syscon, addr, BIT(id));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aspeed_reset_line_deassert(const struct device *dev, uint32_t id)
|
|
|
|
{
|
|
|
|
const struct reset_aspeed_config *config = dev->config;
|
|
|
|
const struct device *syscon = config->syscon;
|
|
|
|
uint32_t addr = RESET_CTRL0_DEASSERT;
|
|
|
|
|
|
|
|
if (id >= ASPEED_RESET_GRP_1_OFFSET) {
|
|
|
|
id -= ASPEED_RESET_GRP_1_OFFSET;
|
|
|
|
addr = RESET_CTRL1_DEASSERT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return syscon_write_reg(syscon, addr, BIT(id));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aspeed_reset_status(const struct device *dev, uint32_t id, uint8_t *status)
|
|
|
|
{
|
|
|
|
const struct reset_aspeed_config *config = dev->config;
|
|
|
|
const struct device *syscon = config->syscon;
|
|
|
|
uint32_t addr = RESET_CTRL0_ASSERT;
|
|
|
|
uint32_t reg_value;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (id >= ASPEED_RESET_GRP_1_OFFSET) {
|
|
|
|
id -= ASPEED_RESET_GRP_1_OFFSET;
|
|
|
|
addr = RESET_CTRL1_ASSERT;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = syscon_read_reg(syscon, addr, ®_value);
|
|
|
|
if (ret == 0) {
|
|
|
|
*status = !!(reg_value & BIT(id));
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aspeed_reset_line_toggle(const struct device *dev, uint32_t id)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = aspeed_reset_line_assert(dev, id);
|
|
|
|
if (ret == 0) {
|
|
|
|
ret = aspeed_reset_line_deassert(dev, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct reset_driver_api aspeed_reset_api = {
|
|
|
|
.status = aspeed_reset_status,
|
|
|
|
.line_assert = aspeed_reset_line_assert,
|
|
|
|
.line_deassert = aspeed_reset_line_deassert,
|
|
|
|
.line_toggle = aspeed_reset_line_toggle
|
|
|
|
};
|
|
|
|
|
|
|
|
#define ASPEED_RESET_INIT(n) \
|
|
|
|
static const struct reset_aspeed_config reset_aspeed_cfg_##n = { \
|
|
|
|
.syscon = DEVICE_DT_GET(DT_NODELABEL(syscon)), \
|
|
|
|
}; \
|
2023-04-18 18:25:15 +08:00
|
|
|
DEVICE_DT_INST_DEFINE(n, NULL, NULL, NULL, &reset_aspeed_cfg_##n, \
|
2022-11-21 16:56:56 +08:00
|
|
|
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
|
|
|
|
&aspeed_reset_api);
|
|
|
|
|
|
|
|
DT_INST_FOREACH_STATUS_OKAY(ASPEED_RESET_INIT)
|