Skip to content

Commit 1a24ae0

Browse files
authored
[DM/FEATURE] Support reset controller (#9630)
* [DM/FEATURE] Support reset controller Reset controllers are central units that control the reset signals to multiple peripherals. The reset controller API is split into two parts: 1. The consumer driver interface, which allows peripheral drivers to request control over their reset input signals 2. The reset controller driver interface which is used by drivers for reset controller devices to register their reset controls to provide them to the consumers. * [RESET/SIMPLE] Support simple reset Currently this driver supports: - Altera SoCFPGAs - ASPEED BMC SoCs - Bitmain BM1880 SoC - Realtek SoCs - RCC reset controller in STM32 MCUs - Allwinner SoCs - SiFive FU740 SoCs - Sophgo SoCs Signed-off-by: GuEe-GUI <[email protected]>
1 parent 9afe6a5 commit 1a24ae0

File tree

9 files changed

+806
-0
lines changed

9 files changed

+806
-0
lines changed

components/drivers/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ rsource "phye/Kconfig"
2626
rsource "block/Kconfig"
2727
rsource "nvme/Kconfig"
2828
rsource "scsi/Kconfig"
29+
rsource "reset/Kconfig"
2930
rsource "virtio/Kconfig"
3031
rsource "dma/Kconfig"
3132
rsource "mfd/Kconfig"
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright (c) 2006-2022, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2022-11-26 GuEe-GUI first version
9+
*/
10+
11+
#ifndef __RESET_H__
12+
#define __RESET_H__
13+
14+
#include <rthw.h>
15+
#include <rtthread.h>
16+
#include <drivers/ofw.h>
17+
18+
#define RT_RESET_CONTROLLER_OBJ_NAME "RSTC"
19+
20+
struct rt_reset_control_ops;
21+
22+
struct rt_reset_controller
23+
{
24+
struct rt_object parent;
25+
26+
rt_list_t rstc_nodes;
27+
28+
const char *name;
29+
const struct rt_reset_control_ops *ops;
30+
31+
struct rt_ofw_node *ofw_node;
32+
void *priv;
33+
34+
struct rt_spinlock spinlock;
35+
};
36+
37+
struct rt_reset_control
38+
{
39+
rt_list_t list;
40+
41+
struct rt_reset_controller *rstcer;
42+
43+
int id;
44+
const char *con_id;
45+
rt_bool_t is_array;
46+
47+
void *priv;
48+
};
49+
50+
struct rt_reset_control_ops
51+
{
52+
/*
53+
* rt_ofw_cell_args return:
54+
* args[0] = rstc.id
55+
*/
56+
rt_err_t (*ofw_parse)(struct rt_reset_control *rstc, struct rt_ofw_cell_args *args);
57+
/* API */
58+
rt_err_t (*reset)(struct rt_reset_control *rstc);
59+
rt_err_t (*assert)(struct rt_reset_control *rstc);
60+
rt_err_t (*deassert)(struct rt_reset_control *rstc);
61+
int (*status)(struct rt_reset_control *rstc);
62+
};
63+
64+
rt_err_t rt_reset_controller_register(struct rt_reset_controller *rstcer);
65+
rt_err_t rt_reset_controller_unregister(struct rt_reset_controller *rstcer);
66+
67+
rt_err_t rt_reset_control_reset(struct rt_reset_control *rstc);
68+
rt_err_t rt_reset_control_assert(struct rt_reset_control *rstc);
69+
rt_err_t rt_reset_control_deassert(struct rt_reset_control *rstc);
70+
int rt_reset_control_status(struct rt_reset_control *rstc);
71+
72+
rt_ssize_t rt_reset_control_get_count(struct rt_device *dev);
73+
struct rt_reset_control *rt_reset_control_get_array(struct rt_device *dev);
74+
struct rt_reset_control *rt_reset_control_get_by_index(struct rt_device *dev, int index);
75+
struct rt_reset_control *rt_reset_control_get_by_name(struct rt_device *dev, const char *name);
76+
void rt_reset_control_put(struct rt_reset_control *rstc);
77+
78+
struct rt_reset_control *rt_ofw_get_reset_control_array(struct rt_ofw_node *np);
79+
struct rt_reset_control *rt_ofw_get_reset_control_by_index(struct rt_ofw_node *np, int index);
80+
struct rt_reset_control *rt_ofw_get_reset_control_by_name(struct rt_ofw_node *np, const char *name);
81+
82+
#endif /* __RESET_H__ */

components/drivers/include/rtdevice.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ extern "C" {
7979
#include "drivers/pic.h"
8080
#endif /* RT_USING_PIC */
8181

82+
#ifdef RT_USING_RESET
83+
#include "drivers/reset.h"
84+
#endif /* RT_USING_RESET */
85+
8286
#ifdef RT_USING_SCSI
8387
#include "drivers/scsi.h"
8488
#endif /* RT_USING_SCSI */

components/drivers/ofw/ofw.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ static const struct ofw_obj_cmp_list ofw_obj_cmp_list[] =
7171
{
7272
#ifdef RT_USING_CLK
7373
{ "#clock-cells", RT_CLK_NODE_OBJ_NAME, sizeof(struct rt_clk_node) },
74+
#endif
75+
#ifdef RT_USING_RESET
76+
{ "#reset-cells", RT_RESET_CONTROLLER_OBJ_NAME, sizeof(struct rt_reset_controller) },
7477
#endif
7578
{ "#power-domain-cells", RT_POWER_DOMAIN_PROXY_OBJ_NAME, sizeof(struct rt_dm_power_domain_proxy) },
7679
{ "#power-domain-cells", RT_POWER_DOMAIN_OBJ_NAME, sizeof(struct rt_dm_power_domain) },

components/drivers/reset/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
menuconfig RT_USING_RESET
2+
bool "Using Reset Controller support"
3+
depends on RT_USING_DM
4+
depends on RT_USING_OFW
5+
default n
6+
7+
config RT_RESET_SIMPLE
8+
bool "Simple Reset Controller Driver"
9+
depends on RT_USING_RESET
10+
default n
11+
12+
if RT_USING_RESET
13+
osource "$(SOC_DM_RESET_DIR)/Kconfig"
14+
endif
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from building import *
2+
3+
group = []
4+
5+
if not GetDepend(['RT_USING_RESET']):
6+
Return('group')
7+
8+
cwd = GetCurrentDir()
9+
CPPPATH = [cwd + '/../include']
10+
11+
src = ['reset.c']
12+
13+
if GetDepend(['RT_RESET_SIMPLE']):
14+
src += ['reset-simple.c']
15+
16+
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
17+
18+
Return('group')
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/*
2+
* Copyright (c) 2006-2022, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2022-11-26 GuEe-GUI first version
9+
*/
10+
11+
#include "reset-simple.h"
12+
13+
struct reset_simple_data
14+
{
15+
rt_uint32_t reg_offset;
16+
rt_bool_t active_low;
17+
rt_bool_t status_active_low;
18+
};
19+
20+
#define raw_to_reset_simple(raw) rt_container_of(raw, struct reset_simple, parent)
21+
22+
static rt_err_t reset_simple_update(struct reset_simple *rsts, int id, rt_bool_t assert)
23+
{
24+
rt_uint32_t reg;
25+
rt_ubase_t level;
26+
int reg_width = sizeof(rt_uint32_t);
27+
int bank = id / (reg_width * 8);
28+
int offset = id % (reg_width * 8);
29+
30+
level = rt_spin_lock_irqsave(&rsts->lock);
31+
32+
reg = HWREG32(rsts->mmio_base + (bank * reg_width));
33+
34+
if (assert ^ rsts->active_low)
35+
{
36+
reg |= RT_BIT(offset);
37+
}
38+
else
39+
{
40+
reg &= ~RT_BIT(offset);
41+
}
42+
43+
HWREG32(rsts->mmio_base + (bank * reg_width)) = reg;
44+
45+
rt_spin_unlock_irqrestore(&rsts->lock, level);
46+
47+
return RT_EOK;
48+
}
49+
50+
static rt_err_t reset_simple_assert(struct rt_reset_control *rstc)
51+
{
52+
struct reset_simple *rsts = raw_to_reset_simple(rstc);
53+
54+
return reset_simple_update(rsts, rstc->id, RT_TRUE);
55+
}
56+
57+
static rt_err_t reset_simple_deassert(struct rt_reset_control *rstc)
58+
{
59+
struct reset_simple *rsts = raw_to_reset_simple(rstc);
60+
61+
return reset_simple_update(rsts, rstc->id, RT_FALSE);
62+
}
63+
64+
static rt_err_t reset_simple_reset(struct rt_reset_control *rstc)
65+
{
66+
rt_err_t err;
67+
struct reset_simple *rsts = raw_to_reset_simple(rstc);
68+
69+
if (!rsts->reset_us)
70+
{
71+
return -RT_ENOSYS;
72+
}
73+
74+
if ((err = reset_simple_assert(rstc)))
75+
{
76+
return err;
77+
}
78+
79+
rt_hw_us_delay(rsts->reset_us + (rsts->reset_us >> 1));
80+
81+
return reset_simple_deassert(rstc);
82+
}
83+
84+
static int reset_simple_status(struct rt_reset_control *rstc)
85+
{
86+
rt_uint32_t value;
87+
int reg_width = sizeof(rt_uint32_t);
88+
int bank = rstc->id / (reg_width * 8);
89+
int offset = rstc->id % (reg_width * 8);
90+
struct reset_simple *rsts = raw_to_reset_simple(rstc);
91+
92+
value = HWREG32(rsts->mmio_base + (bank * reg_width));
93+
94+
return !(value & RT_BIT(offset)) ^ !rsts->status_active_low;
95+
}
96+
97+
const struct rt_reset_control_ops reset_simple_ops =
98+
{
99+
.reset = reset_simple_reset,
100+
.assert = reset_simple_assert,
101+
.deassert = reset_simple_deassert,
102+
.status = reset_simple_status,
103+
};
104+
105+
static rt_err_t reset_simple_probe(struct rt_platform_device *pdev)
106+
{
107+
rt_err_t err;
108+
struct rt_reset_controller *rstcer;
109+
struct rt_device *dev = &pdev->parent;
110+
const struct reset_simple_data *rsts_data = pdev->id->data;
111+
struct reset_simple *rsts = rt_calloc(1, sizeof(*rsts));
112+
113+
if (!rsts)
114+
{
115+
return -RT_ENOMEM;
116+
}
117+
118+
rsts->mmio_base = rt_dm_dev_iomap(dev, 0);
119+
120+
if (!rsts->mmio_base)
121+
{
122+
err = -RT_EIO;
123+
goto _fail;
124+
}
125+
126+
rt_spin_lock_init(&rsts->lock);
127+
128+
rstcer = &rsts->parent;
129+
130+
rstcer->priv = rsts;
131+
rstcer->ofw_node = dev->ofw_node;
132+
rstcer->ops = &reset_simple_ops;
133+
134+
if ((err = rt_reset_controller_register(rstcer)))
135+
{
136+
goto _fail;
137+
}
138+
139+
if (rsts_data)
140+
{
141+
rsts->mmio_base += rsts_data->reg_offset;
142+
rsts->active_low = rsts_data->active_low;
143+
rsts->status_active_low = rsts_data->status_active_low;
144+
}
145+
146+
return RT_EOK;
147+
148+
_fail:
149+
if (rsts->mmio_base)
150+
{
151+
rt_iounmap(rsts->mmio_base);
152+
}
153+
154+
rt_free(rsts);
155+
156+
return err;
157+
}
158+
159+
static const struct reset_simple_data reset_simple_socfpga =
160+
{
161+
.reg_offset = 0x20,
162+
.status_active_low = RT_TRUE,
163+
};
164+
165+
static const struct reset_simple_data reset_simple_active_low =
166+
{
167+
.active_low = RT_TRUE,
168+
.status_active_low = RT_TRUE,
169+
};
170+
171+
static const struct rt_ofw_node_id reset_simple_ofw_ids[] =
172+
{
173+
{ .compatible = "altr,stratix10-rst-mgr", .data = &reset_simple_socfpga },
174+
{ .compatible = "st,stm32-rcc", },
175+
{ .compatible = "allwinner,sun6i-a31-clock-reset", .data = &reset_simple_active_low },
176+
{ .compatible = "zte,zx296718-reset", .data = &reset_simple_active_low },
177+
{ .compatible = "aspeed,ast2400-lpc-reset" },
178+
{ .compatible = "aspeed,ast2500-lpc-reset" },
179+
{ .compatible = "aspeed,ast2600-lpc-reset" },
180+
{ .compatible = "bitmain,bm1880-reset", .data = &reset_simple_active_low },
181+
{ .compatible = "brcm,bcm4908-misc-pcie-reset", .data = &reset_simple_active_low },
182+
{ .compatible = "snps,dw-high-reset" },
183+
{ .compatible = "snps,dw-low-reset", .data = &reset_simple_active_low },
184+
{ .compatible = "sophgo,sg2042-reset", .data = &reset_simple_active_low },
185+
{ /* sentinel */ }
186+
};
187+
188+
static struct rt_platform_driver reset_simple_driver =
189+
{
190+
.name = "reset-simple",
191+
.ids = reset_simple_ofw_ids,
192+
193+
.probe = reset_simple_probe,
194+
};
195+
196+
static int reset_simple_register(void)
197+
{
198+
rt_platform_driver_register(&reset_simple_driver);
199+
200+
return 0;
201+
}
202+
INIT_SUBSYS_EXPORT(reset_simple_register);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright (c) 2006-2022, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2022-11-26 GuEe-GUI first version
9+
*/
10+
11+
#ifndef __RESET_SIMPLE_H__
12+
#define __RESET_SIMPLE_H__
13+
14+
#include <rtthread.h>
15+
#include <rtdevice.h>
16+
17+
struct reset_simple
18+
{
19+
struct rt_reset_controller parent;
20+
21+
void *mmio_base;
22+
23+
/*
24+
* If true, bits are cleared to assert the reset.
25+
* Otherwise, bits are set to assert the reset.
26+
*/
27+
rt_bool_t active_low;
28+
/*
29+
* If true, bits read back as cleared while the reset is asserted.
30+
* Otherwise, bits read back as set while the reset is asserted.
31+
*/
32+
rt_bool_t status_active_low;
33+
34+
/*
35+
* Minimum delay in microseconds needed that needs to be
36+
* waited for between an assert and a deassert to reset the device.
37+
* If multiple consumers with different delay
38+
* requirements are connected to this controller, it must
39+
* be the largest minimum delay. 0 means that such a delay is
40+
* unknown and the reset operation is unsupported.
41+
*/
42+
rt_uint32_t reset_us;
43+
44+
/* protect registers during read-modify-write cycles */
45+
struct rt_spinlock lock;
46+
};
47+
48+
extern const struct rt_reset_control_ops reset_simple_ops;
49+
50+
#endif /* __RESET_SIMPLE_H__ */

0 commit comments

Comments
 (0)