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