1 /*
2 * Copyright (c) 2022 ASPEED Technology Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT aspeed_ast10x0_reset
8 #include <errno.h>
9 #include <zephyr/dt-bindings/reset/ast10x0_reset.h>
10 #include <zephyr/drivers/reset.h>
11 #include <zephyr/drivers/syscon.h>
12 #include <zephyr/sys/util.h>
13
14
15 /*
16 * RESET_CTRL0/1_ASSERT registers:
17 * - Each bit in these registers controls a reset line
18 * - Write '1' to a bit: assert the corresponding reset line
19 * - Write '0' to a bit: no effect
20 * RESET_CTRL0/1_DEASSERT register:
21 * - Write '1' to a bit: clear the corresponding bit in RESET_CTRL0/1_ASSERT.
22 * (deassert the corresponding reset line)
23 */
24 #define RESET_CTRL0_ASSERT 0x40
25 #define RESET_CTRL0_DEASSERT 0x44
26 #define RESET_CTRL1_ASSERT 0x50
27 #define RESET_CTRL1_DEASSERT 0x54
28
29 struct reset_aspeed_config {
30 const struct device *syscon;
31 };
32
aspeed_reset_line_assert(const struct device * dev,uint32_t id)33 static int aspeed_reset_line_assert(const struct device *dev, uint32_t id)
34 {
35 const struct reset_aspeed_config *config = dev->config;
36 const struct device *syscon = config->syscon;
37 uint32_t addr = RESET_CTRL0_ASSERT;
38
39 if (id >= ASPEED_RESET_GRP_1_OFFSET) {
40 id -= ASPEED_RESET_GRP_1_OFFSET;
41 addr = RESET_CTRL1_ASSERT;
42 }
43
44 return syscon_write_reg(syscon, addr, BIT(id));
45 }
46
aspeed_reset_line_deassert(const struct device * dev,uint32_t id)47 static int aspeed_reset_line_deassert(const struct device *dev, uint32_t id)
48 {
49 const struct reset_aspeed_config *config = dev->config;
50 const struct device *syscon = config->syscon;
51 uint32_t addr = RESET_CTRL0_DEASSERT;
52
53 if (id >= ASPEED_RESET_GRP_1_OFFSET) {
54 id -= ASPEED_RESET_GRP_1_OFFSET;
55 addr = RESET_CTRL1_DEASSERT;
56 }
57
58 return syscon_write_reg(syscon, addr, BIT(id));
59 }
60
aspeed_reset_status(const struct device * dev,uint32_t id,uint8_t * status)61 static int aspeed_reset_status(const struct device *dev, uint32_t id, uint8_t *status)
62 {
63 const struct reset_aspeed_config *config = dev->config;
64 const struct device *syscon = config->syscon;
65 uint32_t addr = RESET_CTRL0_ASSERT;
66 uint32_t reg_value;
67 int ret;
68
69 if (id >= ASPEED_RESET_GRP_1_OFFSET) {
70 id -= ASPEED_RESET_GRP_1_OFFSET;
71 addr = RESET_CTRL1_ASSERT;
72 }
73
74 ret = syscon_read_reg(syscon, addr, ®_value);
75 if (ret == 0) {
76 *status = !!(reg_value & BIT(id));
77 }
78
79 return ret;
80 }
81
aspeed_reset_line_toggle(const struct device * dev,uint32_t id)82 static int aspeed_reset_line_toggle(const struct device *dev, uint32_t id)
83 {
84 int ret;
85
86 ret = aspeed_reset_line_assert(dev, id);
87 if (ret == 0) {
88 ret = aspeed_reset_line_deassert(dev, id);
89 }
90
91 return ret;
92 }
93
94 static const struct reset_driver_api aspeed_reset_api = {
95 .status = aspeed_reset_status,
96 .line_assert = aspeed_reset_line_assert,
97 .line_deassert = aspeed_reset_line_deassert,
98 .line_toggle = aspeed_reset_line_toggle
99 };
100
101 #define ASPEED_RESET_INIT(n) \
102 static const struct reset_aspeed_config reset_aspeed_cfg_##n = { \
103 .syscon = DEVICE_DT_GET(DT_NODELABEL(syscon)), \
104 }; \
105 DEVICE_DT_INST_DEFINE(n, NULL, NULL, NULL, &reset_aspeed_cfg_##n, \
106 PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
107 &aspeed_reset_api);
108
109 DT_INST_FOREACH_STATUS_OKAY(ASPEED_RESET_INIT)
110