forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreset_ast10x0.c
109 lines (89 loc) · 3.13 KB
/
reset_ast10x0.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
* 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)