drivers: reset: add Aspeed AST10x0 reset control
AST10x0 series SOCs provide the reset controller through the syscon hardware block. The current driver supports the reset line assert, deassert and status for the hardware IPs embedded in the SOC. Each reset line has an ID that can simply map to a bit in syscon registers RESET_CTRL0_ASSERT (group 0) or RESET_CTRL1_ASSERT (group 1). Write bits to RESET_CTRL0_DEASSERT or RESET_CTRL1_DEASSERT will clean the corresponding bits in RESET_CTRL0_ASSERT or RESET_CTRL1_ASSERT registers. Signed-off-by: Dylan Hung <dylan_hung@aspeedtech.com>
This commit is contained in:
parent
4224732a57
commit
f5794923a1
|
@ -3,3 +3,4 @@
|
|||
zephyr_library()
|
||||
zephyr_library_sources_ifdef(CONFIG_RESET_GD32 reset_gd32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_RESET_RPI_PICO reset_rpi_pico.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_RESET_AST10X0 reset_ast10x0.c)
|
||||
|
|
|
@ -29,5 +29,6 @@ comment "Reset Controller Drivers"
|
|||
|
||||
rsource "Kconfig.rpi_pico"
|
||||
rsource "Kconfig.gd32"
|
||||
rsource "Kconfig.aspeed"
|
||||
|
||||
endif # RESET
|
||||
|
|
9
drivers/reset/Kconfig.aspeed
Normal file
9
drivers/reset/Kconfig.aspeed
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2022 ASPEED Technology Inc.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config RESET_AST10X0
|
||||
bool "ASPEED reset driver"
|
||||
default y
|
||||
depends on DT_HAS_ASPEED_AST10X0_RESET_ENABLED
|
||||
help
|
||||
This option enables the reset driver for ASPEED AST10X0 series SOC.
|
115
drivers/reset/reset_ast10x0.c
Normal file
115
drivers/reset/reset_ast10x0.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* 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 int aspeed_reset_control_init(const struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)), \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(n, &aspeed_reset_control_init, NULL, NULL, &reset_aspeed_cfg_##n, \
|
||||
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
|
||||
&aspeed_reset_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(ASPEED_RESET_INIT)
|
Loading…
Reference in a new issue