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