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:
Dylan Hung 2022-11-21 16:56:56 +08:00 committed by Carles Cufí
parent 4224732a57
commit f5794923a1
4 changed files with 126 additions and 0 deletions

View file

@ -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)

View file

@ -29,5 +29,6 @@ comment "Reset Controller Drivers"
rsource "Kconfig.rpi_pico"
rsource "Kconfig.gd32"
rsource "Kconfig.aspeed"
endif # RESET

View 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.

View 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, &reg_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)