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.
109 lines
3.1 KiB
109 lines
3.1 KiB
/* |
|
* 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 DEVICE_API(reset, 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, NULL, 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)
|
|
|