/* * Copyright (c) 2022 ASPEED Technology Inc. * * SPDX-License-Identifier: Apache-2.0 */ #define DT_DRV_COMPAT aspeed_ast10x0_reset #include #include #include #include #include /* * 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)), \ }; \ 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)