1 /*
2 * Renesas SCP/MCP Software
3 * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights
4 * reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "FreeRTOS.h"
10 #include "arch_gic.h"
11 #include "mmio.h"
12 #include "rcar_irq.h"
13 #include "rcar_mmap.h"
14 #include "task.h"
15
16 uint32_t c_interrupt;
17
18 /* ARM Generic Timer */
19 #define CORE0_TIMER_IRQCNTL ((volatile uint32_t *)(0x40000040))
20 static uint32_t timer_cntfrq = 0;
21 static uint32_t timer_tick = 0;
22
init_generic_timer(void)23 static void init_generic_timer(void)
24 {
25 uint32_t reg;
26 uint32_t reg_cntfid;
27 uint32_t modemr;
28 uint32_t modemr_pll;
29
30 uint32_t pll_table[] = {
31 EXTAL_MD14_MD13_TYPE_0, /* MD14/MD13 : 0b00 */
32 EXTAL_MD14_MD13_TYPE_1, /* MD14/MD13 : 0b01 */
33 EXTAL_MD14_MD13_TYPE_2, /* MD14/MD13 : 0b10 */
34 EXTAL_MD14_MD13_TYPE_3 /* MD14/MD13 : 0b11 */
35 };
36
37 modemr = mmio_read_32(RCAR_MODEMR);
38 modemr_pll = (modemr & MODEMR_BOOT_PLL_MASK);
39
40 /* Set frequency data in CNTFID0 */
41 reg_cntfid = pll_table[modemr_pll >> MODEMR_BOOT_PLL_SHIFT];
42 reg = mmio_read_32(RCAR_PRR) & (RCAR_PRODUCT_MASK | RCAR_CUT_MASK);
43 switch (modemr_pll) {
44 case MD14_MD13_TYPE_0:
45 #ifdef SALVATORE_XS
46 reg_cntfid = EXTAL_SALVATOR_XS;
47 #endif
48 break;
49 case MD14_MD13_TYPE_3:
50 if (RCAR_PRODUCT_H3_CUT10 == reg) {
51 reg_cntfid = reg_cntfid >> 1U;
52 }
53 break;
54 default:
55 /* none */
56 break;
57 }
58 /* Update memory mapped and register based freqency */
59 __asm__ volatile("msr cntfrq_el0, %0" ::"r"(reg_cntfid));
60 }
61
disable_cntv(void)62 void disable_cntv(void)
63 {
64 uint32_t cntv_ctl;
65 cntv_ctl = 0;
66 __asm__ volatile("msr cntv_ctl_el0, %0" ::"r"(cntv_ctl));
67 }
68 /*-----------------------------------------------------------*/
69
enable_cntv(void)70 void enable_cntv(void)
71 {
72 uint32_t cntv_ctl;
73 cntv_ctl = 1;
74 __asm__ volatile("msr cntv_ctl_el0, %0" ::"r"(cntv_ctl));
75 }
76 /*-----------------------------------------------------------*/
77
write_cntv_tval(uint32_t val)78 void write_cntv_tval(uint32_t val)
79 {
80 __asm__ volatile("msr cntv_tval_el0, %0" ::"r"(val));
81 return;
82 }
83 /*-----------------------------------------------------------*/
84
read_cntfrq(void)85 uint32_t read_cntfrq(void)
86 {
87 uint32_t val;
88 __asm__ volatile("mrs %0, cntfrq_el0" : "=r"(val));
89 return val;
90 }
91 /*-----------------------------------------------------------*/
92
read_cntv_tval(void)93 uint32_t read_cntv_tval(void)
94 {
95 uint32_t val;
96 __asm__ volatile("mrs %0, cntvct_el0" : "=r"(val));
97 return val;
98 }
99 /*-----------------------------------------------------------*/
100
init_timer(void)101 void init_timer(void)
102 {
103 timer_cntfrq = timer_tick = read_cntfrq();
104 /* clear cntv interrupt and set next 1 sec timer. */
105 write_cntv_tval(timer_cntfrq);
106 return;
107 }
108 /*-----------------------------------------------------------*/
109
timer_set_tick_rate_hz(uint32_t rate)110 void timer_set_tick_rate_hz(uint32_t rate)
111 {
112 timer_tick = timer_cntfrq / rate;
113 write_cntv_tval(timer_tick);
114 }
115 /*-----------------------------------------------------------*/
116
vConfigureTickInterrupt(void)117 void vConfigureTickInterrupt(void)
118 {
119 /* disable timer */
120 disable_cntv();
121
122 /* init timer device. */
123 init_generic_timer();
124 init_timer();
125
126 /* set tick rate. */
127 timer_set_tick_rate_hz(configTICK_RATE_HZ);
128
129 /* start & enable interrupts in the timer. */
130 enable_cntv();
131 }
132 /*-----------------------------------------------------------*/
133
vClearTickInterrupt(void)134 void vClearTickInterrupt(void)
135 {
136 /* clear cntv interrupt and set next timer. */
137 write_cntv_tval(timer_tick);
138 return;
139 }
140 /*-----------------------------------------------------------*/
141
vApplicationIRQHandler(void)142 void vApplicationIRQHandler(void)
143 {
144 uint32_t ulInterruptID;
145
146 c_interrupt = mmio_read_32(RCAR_GICC_BASE + GICC_IAR);
147 mmio_write_32(RCAR_GICC_BASE + GICC_EOIR, c_interrupt);
148 ulInterruptID = c_interrupt & 0x00000FFFUL;
149
150 /* call handler function */
151 if (ulInterruptID == VIRTUAL_TIMER_IRQ) {
152 /* Generic Timer */
153 FreeRTOS_Tick_Handler();
154 } else {
155 /* Peripherals */
156 irq_global(ulInterruptID);
157 }
158 c_interrupt = 0;
159 }
160