1+ /*
2+ * Copyright (c) 2025 ispace, inc.
3+ *
4+ * SPDX-License-Identifier: Apache-2.0
5+ */
6+
7+ #include <soc.h>
8+ #include <zephyr/init.h>
9+ #include <zephyr/spinlock.h>
10+ #include <zephyr/drivers/timer/system_timer.h>
11+ #include <zephyr/irq.h>
12+
13+ #define DT_DRV_COMPAT ti_tms570_rti
14+
15+ #define REG_RTI DT_INST_REG_ADDR_BY_IDX(0, 0)
16+ #define RTI_CLK_FREQ DT_PROP(DT_NODELABEL(clk_rticlk), clock_frequency)
17+
18+ #define RTI_INTFLAG_COMP0 BIT(0)
19+ #define RTI_INTENA_COMP0 BIT(0)
20+
21+ #define RTI_INTCLR_ALL (BIT(18) | BIT(17) | BIT(16) | \
22+ BIT(3) | BIT(2) | BIT(1) | BIT(0))
23+
24+ #define RTIGCTRL (REG_RTI + 0x00)
25+ #define RTITBCTRL (REG_RTI + 0x04)
26+ #define RTICAPCTRL (REG_RTI + 0x08)
27+ #define RTICOMPCTRL (REG_RTI + 0x0C)
28+ #define RTISETINTENA (REG_RTI + 0x80)
29+ #define RTICLEARINTENA (REG_RTI + 0x84)
30+ #define RTIINTFLAG (REG_RTI + 0x88)
31+ #define RTIFRC0 (REG_RTI + 0x10)
32+ #define RTIUC0 (REG_RTI + 0x14)
33+ #define RTICPUC0 (REG_RTI + 0x18)
34+ #define RTICAFRC0 (REG_RTI + 0x20)
35+ #define RTICAUC0 (REG_RTI + 0x24)
36+ #define RTICOMP0 (REG_RTI + 0x50)
37+ #define RTIUDCP0 (REG_RTI + 0x54)
38+
39+ #define RTIGCTRL_COS_OFFSET (15)
40+ #define CNT1EN BIT(1)
41+ #define CNT0EN BIT(0)
42+
43+ static struct k_spinlock ticks_lock ;
44+ static volatile uint64_t ticks ;
45+
46+ uint32_t sys_clock_elapsed (void )
47+ {
48+ return 0 ;
49+ }
50+
51+ uint32_t sys_clock_cycle_get_32 (void )
52+ {
53+ return sys_read32 (RTIFRC0 );
54+ }
55+
56+ static void rti_compare0_isr (const void * arg )
57+ {
58+ ARG_UNUSED (arg );
59+
60+ K_SPINLOCK (& ticks_lock ) {
61+ ticks += k_ticks_to_cyc_floor32 (1 );
62+ }
63+
64+ sys_write32 (RTI_INTFLAG_COMP0 , RTIINTFLAG );
65+ sys_clock_announce (1 );
66+ }
67+
68+ static int rti_timer_init (void )
69+ {
70+ /**
71+ * TODO Counter block 0 can be synchronized with Network Time (NTU),
72+ * we can make use of that.
73+ */
74+
75+ /* disable counters and interrupts */
76+ sys_write32 (1 << RTIGCTRL_COS_OFFSET , RTIGCTRL );
77+ sys_write32 (RTI_INTCLR_ALL , RTICLEARINTENA );
78+
79+ /**
80+ * We use counter 0 and compare register 0.
81+ */
82+
83+ /* default compare control and capture control */
84+ sys_write32 (0 , RTICOMPCTRL );
85+ sys_write32 (0 , RTICAPCTRL );
86+
87+ /* Initialize counter 0 */
88+ sys_write32 (0 , RTIUC0 );
89+ sys_write32 (0 , RTIFRC0 );
90+ sys_write32 (0 , RTITBCTRL );
91+
92+ /**
93+ * Set up free running counter interrupt cycle.
94+ * UCx - up-counter or prescale counter - driven by RTICLK
95+ * CPUCx - compare up-counter, it acts like a prescaler over UCx
96+ * FRCx - when CPUCx value matches UCx, this reg is incremented by one
97+ * COMPx - this is compared with FRCx, a match generates an interrupt
98+ * UDCPx - UDCPx is added to COMPx when a match occues (COMPx matches FRCx),
99+ * so that we can generate periodic interrupts1
100+ */
101+ sys_write32 (RTI_CLK_FREQ / CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC - 1U , RTICPUC0 );
102+ /* free running counter, compare match period = 10 ms */
103+ sys_write32 (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC , RTICOMP0 );
104+ sys_write32 (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC , RTIUDCP0 );
105+
106+ /* Clear all pending interrupts */
107+ sys_write32 (RTI_INTCLR_ALL , RTIINTFLAG );
108+
109+ /* connect irq */
110+ IRQ_CONNECT (IRQ_RTI_COMPARE_0 , IRQ_RTI_COMPARE_0 , rti_compare0_isr , NULL , 0 );
111+ irq_enable (IRQ_RTI_COMPARE_0 );
112+
113+ /* Enable interrupt */
114+ sys_write32 (RTI_INTENA_COMP0 , RTISETINTENA );
115+ /* Enable timer */
116+ sys_write32 (sys_read32 (RTIGCTRL ) | CNT1EN | CNT0EN , RTIGCTRL );
117+
118+ return 0 ;
119+ }
120+
121+ SYS_INIT (rti_timer_init , PRE_KERNEL_2 , CONFIG_SYSTEM_CLOCK_INIT_PRIORITY );
0 commit comments