Skip to content

Commit ae27a55

Browse files
JasonLin-RealTekadamkondraciuk
authored andcommitted
[nrf fromtree] driver: timer: Add timer driver initial version of RTS5912.
Add timer driver for Realtek RTS5912. Signed-off-by: Adam Kondraciuk <[email protected]> (cherry picked from commit cfb2074) Signed-off-by: Lin Yu-Cheng <[email protected]>
1 parent d441423 commit ae27a55

File tree

8 files changed

+363
-0
lines changed

8 files changed

+363
-0
lines changed

drivers/timer/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ zephyr_library_sources_ifdef(CONFIG_NRF_RTC_TIMER nrf_rtc_timer.c)
3333
zephyr_library_sources_ifdef(CONFIG_RCAR_CMT_TIMER rcar_cmt_timer.c)
3434
zephyr_library_sources_ifdef(CONFIG_RISCV_MACHINE_TIMER riscv_machine_timer.c)
3535
zephyr_library_sources_ifdef(CONFIG_RV32M1_LPTMR_TIMER rv32m1_lptmr_timer.c)
36+
zephyr_library_sources_ifdef(CONFIG_REALTEK_RTS5912_RTMR realtek_rts5912_rtmr.c)
3637
zephyr_library_sources_ifdef(CONFIG_SAM0_RTC_TIMER sam0_rtc_timer.c)
3738
zephyr_library_sources_ifdef(CONFIG_SILABS_SLEEPTIMER_TIMER silabs_sleeptimer_timer.c)
3839
zephyr_library_sources_ifdef(CONFIG_STM32_LPTIM_TIMER stm32_lptim_timer.c)

drivers/timer/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ source "drivers/timer/Kconfig.nrf_xrtc"
9191
source "drivers/timer/Kconfig.rcar_cmt"
9292
source "drivers/timer/Kconfig.riscv_machine"
9393
source "drivers/timer/Kconfig.rv32m1_lptmr"
94+
source "drivers/timer/Kconfig.realtek_rts5912_rtmr"
9495
source "drivers/timer/Kconfig.sam0_rtc"
9596
source "drivers/timer/Kconfig.silabs"
9697
source "drivers/timer/Kconfig.smartbond"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# Copyright (c) 2024 Realtek Semiconductor Corporation, SIBG-SD7
4+
#
5+
6+
config REALTEK_RTS5912_RTMR
7+
bool "Realtek RTS5912 RTOS Timer"
8+
default y if DT_HAS_REALTEK_RTS5912_RTMR_ENABLED
9+
select TICKLESS_CAPABLE
10+
select SYSTEM_TIMER_HAS_DISABLE_SUPPORT
11+
help
12+
This module implements a kernel device driver for the Realtek
13+
RTS5912 series RTOS timer.
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Copyright (c) 2024 Realtek Semiconductor Corporation, SIBG-SD7
5+
* Author: Lin Yu-Cheng <[email protected]>
6+
*/
7+
8+
#define DT_DRV_COMPAT realtek_rts5912_rtmr
9+
10+
#include <stdint.h>
11+
12+
#include <zephyr/init.h>
13+
#include <zephyr/devicetree.h>
14+
#include <zephyr/sys_clock.h>
15+
#include <zephyr/irq.h>
16+
#include <zephyr/spinlock.h>
17+
#include <zephyr/drivers/timer/system_timer.h>
18+
19+
#include <reg/reg_rtmr.h>
20+
#include <reg/reg_system.h>
21+
22+
#define RTS5912_SCCON_REG_BASE ((SYSTEM_Type *)(DT_REG_ADDR(DT_NODELABEL(sccon))))
23+
24+
#define CYCLES_PER_TICK (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
25+
26+
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
27+
"Realtek RTOS timer is not supported multiple instances");
28+
29+
#define RTMR_REG ((RTOSTMR_Type *)DT_INST_REG_ADDR(0))
30+
31+
#define SLWTMR_REG \
32+
((RTOSTMR_Type *)(DT_REG_ADDR(DT_COMPAT_GET_ANY_STATUS_OKAY(realtek_rts5912_slwtimer))))
33+
34+
#define SSCON_REG ((SYSTEM_Type *)(DT_REG_ADDR(DT_NODELABEL(sccon))))
35+
36+
#define RTMR_COUNTER_MAX 0x0ffffffful
37+
#define RTMR_COUNTER_MSK 0x0ffffffful
38+
#define RTMR_TIMER_STOPPED 0xf0000000ul
39+
40+
#define MAX_TICKS ((k_ticks_t)(RTMR_COUNTER_MAX / CYCLES_PER_TICK) - 1)
41+
42+
#define RTMR_ADJUST_LIMIT 2
43+
#define RTMR_ADJUST_CYCLES 1
44+
45+
static struct k_spinlock lock;
46+
static uint32_t accumulated_cycles;
47+
static uint32_t previous_cnt; /* Record the counter set into RTMR */
48+
static uint32_t last_announcement; /* Record the last tick announced to system */
49+
50+
static void rtmr_restart(uint32_t counter)
51+
{
52+
RTMR_REG->CTRL = 0ul;
53+
RTMR_REG->LDCNT = counter;
54+
RTMR_REG->CTRL = RTOSTMR_CTRL_INTEN_Msk | RTOSTMR_CTRL_EN_Msk;
55+
}
56+
57+
static uint32_t rtmr_get_counter(void)
58+
{
59+
uint32_t counter = RTMR_REG->CNT;
60+
61+
if ((counter == 0) && (RTMR_REG->CTRL & RTOSTMR_CTRL_EN_Msk)) {
62+
counter = previous_cnt;
63+
}
64+
65+
return counter;
66+
}
67+
68+
static void rtmr_isr(const void *arg)
69+
{
70+
ARG_UNUSED(arg);
71+
72+
uint32_t cycles;
73+
int32_t ticks;
74+
75+
k_spinlock_key_t key = k_spin_lock(&lock);
76+
77+
rtmr_restart(RTMR_COUNTER_MAX * CYCLES_PER_TICK);
78+
79+
cycles = previous_cnt;
80+
previous_cnt = RTMR_COUNTER_MAX * CYCLES_PER_TICK;
81+
82+
accumulated_cycles += cycles;
83+
84+
if (accumulated_cycles > RTMR_COUNTER_MSK) {
85+
accumulated_cycles &= RTMR_COUNTER_MSK;
86+
}
87+
88+
ticks = accumulated_cycles - last_announcement;
89+
ticks &= RTMR_COUNTER_MSK;
90+
ticks /= CYCLES_PER_TICK;
91+
92+
last_announcement = accumulated_cycles;
93+
94+
k_spin_unlock(&lock, key);
95+
96+
sys_clock_announce(ticks);
97+
}
98+
99+
void sys_clock_set_timeout(int32_t ticks, bool idle)
100+
{
101+
ARG_UNUSED(idle);
102+
103+
uint32_t cur_cnt, temp;
104+
int full_ticks;
105+
uint32_t full_cycles;
106+
uint32_t partial_cycles;
107+
108+
if (idle && (ticks == K_TICKS_FOREVER)) {
109+
RTMR_REG->CTRL = 0U;
110+
previous_cnt = RTMR_TIMER_STOPPED;
111+
return;
112+
}
113+
114+
if (ticks < 1) {
115+
full_ticks = 0;
116+
} else if ((ticks == K_TICKS_FOREVER) || (ticks > MAX_TICKS)) {
117+
full_ticks = MAX_TICKS - 1;
118+
} else {
119+
full_ticks = ticks - 1;
120+
}
121+
122+
full_cycles = full_ticks * CYCLES_PER_TICK;
123+
124+
k_spinlock_key_t key = k_spin_lock(&lock);
125+
126+
cur_cnt = rtmr_get_counter();
127+
128+
RTMR_REG->CTRL = 0U;
129+
130+
temp = accumulated_cycles;
131+
temp += previous_cnt - cur_cnt;
132+
temp &= RTMR_COUNTER_MSK;
133+
accumulated_cycles = temp;
134+
135+
partial_cycles = CYCLES_PER_TICK - (accumulated_cycles % CYCLES_PER_TICK);
136+
previous_cnt = full_cycles + partial_cycles;
137+
138+
temp = previous_cnt;
139+
if (temp > RTMR_ADJUST_LIMIT) {
140+
temp -= RTMR_ADJUST_CYCLES;
141+
}
142+
rtmr_restart(temp);
143+
144+
k_spin_unlock(&lock, key);
145+
}
146+
147+
uint32_t sys_clock_elapsed(void)
148+
{
149+
uint32_t cur_cnt;
150+
uint32_t ticks;
151+
int32_t elapsed;
152+
153+
k_spinlock_key_t key = k_spin_lock(&lock);
154+
155+
cur_cnt = rtmr_get_counter();
156+
157+
elapsed = (int32_t)accumulated_cycles - (int32_t)last_announcement;
158+
if (elapsed < 0) {
159+
elapsed = -1 * elapsed;
160+
}
161+
ticks = (uint32_t)elapsed;
162+
ticks += previous_cnt - cur_cnt;
163+
ticks /= CYCLES_PER_TICK;
164+
ticks &= RTMR_COUNTER_MSK;
165+
166+
k_spin_unlock(&lock, key);
167+
168+
return ticks;
169+
}
170+
171+
void sys_clock_idle_exit(void)
172+
{
173+
if (previous_cnt == RTMR_TIMER_STOPPED) {
174+
previous_cnt = CYCLES_PER_TICK;
175+
rtmr_restart(previous_cnt);
176+
}
177+
}
178+
179+
void sys_clock_disable(void)
180+
{
181+
/* Disable RTMR. */
182+
RTMR_REG->CTRL = 0ul;
183+
}
184+
185+
uint32_t sys_clock_cycle_get_32(void)
186+
{
187+
uint32_t ret;
188+
uint32_t cur_cnt;
189+
190+
k_spinlock_key_t key = k_spin_lock(&lock);
191+
192+
cur_cnt = rtmr_get_counter();
193+
ret = (accumulated_cycles + (previous_cnt - cur_cnt)) & RTMR_COUNTER_MSK;
194+
195+
k_spin_unlock(&lock, key);
196+
197+
return ret;
198+
}
199+
200+
#ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT
201+
202+
void arch_busy_wait(uint32_t n_usec)
203+
{
204+
if (n_usec == 0) {
205+
return;
206+
}
207+
208+
uint32_t start = SLWTMR_REG->CNT;
209+
210+
for (;;) {
211+
uint32_t curr = SLWTMR_REG->CNT;
212+
213+
if ((start - curr) >= n_usec) {
214+
break;
215+
}
216+
}
217+
}
218+
#endif
219+
220+
static int sys_clock_driver_init(void)
221+
{
222+
/* Enable RTMR clock power */
223+
224+
SYSTEM_Type *sys_reg = RTS5912_SCCON_REG_BASE;
225+
226+
sys_reg->PERICLKPWR1 |= SYSTEM_PERICLKPWR1_RTMRCLKPWR_Msk;
227+
228+
/* Enable RTMR interrupt. */
229+
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), rtmr_isr, 0, 0);
230+
irq_enable(DT_INST_IRQN(0));
231+
232+
/* Trigger RTMR and wait it start to counting */
233+
previous_cnt = RTMR_COUNTER_MAX;
234+
235+
rtmr_restart(previous_cnt);
236+
while (RTMR_REG->CNT == 0) {
237+
};
238+
239+
#ifdef CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT
240+
/* Enable SLWTMR0 clock power */
241+
SSCON_REG->PERICLKPWR1 |= BIT(SYSTEM_PERICLKPWR1_SLWTMR0CLKPWR_Pos);
242+
243+
/* Enable SLWTMR0 */
244+
SLWTMR_REG->LDCNT = UINT32_MAX;
245+
SLWTMR_REG->CTRL = RTOSTMR_CTRL_MDSEL_Msk | RTOSTMR_CTRL_EN_Msk;
246+
#endif
247+
248+
return 0;
249+
}
250+
251+
SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY);

dts/arm/realtek/ec/rts5912.dtsi

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,25 @@
7373
clock-names = "rc25m", "pll";
7474
};
7575

76+
slwtmr0: slwtmr0@4000c200 {
77+
compatible = "realtek,rts5912-slwtimer";
78+
reg = <0x4000c200 0x10>;
79+
interrupts = <202 0>;
80+
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP1 PERIPH_GRP1_SLWTMR0_CLKPWR>;
81+
clock-names = "slwtmr";
82+
max-value = <0xFFFFFFFF>;
83+
clock-frequency = <1000000>;
84+
prescaler = <0>;
85+
status = "okay";
86+
};
87+
88+
rtmr: rtmr@4000c500 {
89+
compatible = "realtek,rts5912-rtmr";
90+
reg = <0x4000c500 0x10>;
91+
interrupts = <204 0>;
92+
status = "okay";
93+
};
94+
7695
pinctrl: pin-controller@40090000 {
7796
compatible = "realtek,rts5912-pinctrl";
7897
#address-cells = <1>;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# Copyright (c) 2024 Realtek Semiconductor Corporation, SIBG-SD7
4+
#
5+
6+
description: RTOS Timer on Realtek RTS5912 EC
7+
8+
compatible: "realtek,rts5912-rtmr"
9+
10+
include: base.yaml
11+
12+
properties:
13+
reg:
14+
required: true
15+
16+
interrupts:
17+
required: true
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# Copyright (c) 2024 Realtek Semiconductor Corporation, SIBG-SD7
4+
#
5+
6+
description: Realtek RTS5912 32-bit slow timer
7+
8+
compatible: "realtek,rts5912-slwtimer"
9+
10+
include: rtc.yaml
11+
12+
properties:
13+
reg:
14+
required: true
15+
16+
interrupts:
17+
required: true
18+
19+
max-value:
20+
type: int
21+
required: true
22+
description: Maximum counter value the instance can handle
23+
24+
clock-frequency:
25+
required: true
26+
27+
prescaler:
28+
type: int
29+
required: true
30+
description: Timer frequency equals clock-frequency divided by the prescaler value
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (c) 2023 Realtek, SIBG-SD7
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_SOC_REALTEK_RTS5912_REG_RTMR_H
8+
#define ZEPHYR_SOC_REALTEK_RTS5912_REG_RTMR_H
9+
10+
/*
11+
* @brief RTOS Timer Controller (RTMR)
12+
*/
13+
14+
typedef struct {
15+
volatile uint32_t LDCNT;
16+
volatile uint32_t CNT;
17+
volatile uint32_t CTRL;
18+
volatile uint32_t INTSTS;
19+
} RTOSTMR_Type;
20+
/* CTRL */
21+
#define RTOSTMR_CTRL_EN_Pos (0UL)
22+
#define RTOSTMR_CTRL_EN_Msk BIT(RTOSTMR_CTRL_EN_Pos)
23+
#define RTOSTMR_CTRL_MDSEL_Pos (1UL)
24+
#define RTOSTMR_CTRL_MDSEL_Msk BIT(RTOSTMR_CTRL_MDSEL_Pos)
25+
#define RTOSTMR_CTRL_INTEN_Pos (2UL)
26+
#define RTOSTMR_CTRL_INTEN_Msk BIT(RTOSTMR_CTRL_INTEN_Pos)
27+
/* INTSTS */
28+
#define RTOSTMR_INTSTS_STS_Pos (0UL)
29+
#define RTOSTMR_INTSTS_STS_Msk BIT(RTOSTMR_INTSTS_STS_Pos)
30+
31+
#endif /* ZEPHYR_SOC_REALTEK_RTS5912_REG_RTMR_H */

0 commit comments

Comments
 (0)