Skip to content

Commit e633c0a

Browse files
committed
[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 66df489 commit e633c0a

File tree

4 files changed

+260
-0
lines changed

4 files changed

+260
-0
lines changed

components/drivers/reset/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ menuconfig RT_USING_RESET
44
depends on RT_USING_OFW
55
default n
66

7+
config RT_RESET_SIMPLE
8+
bool "Simple Reset Controller Driver"
9+
depends on RT_USING_RESET
10+
default n
11+
712
if RT_USING_RESET
813
osource "$(SOC_DM_RESET_DIR)/Kconfig"
914
endif

components/drivers/reset/SConscript

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ CPPPATH = [cwd + '/../include']
1010

1111
src = ['reset.c']
1212

13+
if GetDepend(['RT_RESET_SIMPLE']):
14+
src += ['reset-simple.c']
15+
1316
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
1417

1518
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)