1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author         Notes
8  * 2019-07-29     zdzn           first version
9  */
10 
11 #include <rthw.h>
12 #include <rtthread.h>
13 
14 #include "board.h"
15 #include "drv_uart.h"
16 #include "drv_timer.h"
17 
18 #include "cp15.h"
19 
20 #ifdef RT_USING_SMP
21 unsigned int cntfrq;
22 #endif
23 
rt_hw_timer_isr(int vector,void * parameter)24 void rt_hw_timer_isr(int vector, void *parameter)
25 {
26     rt_tick_increase();
27 #ifndef RT_USING_SMP
28     ARM_TIMER_IRQCLR = 0;
29 #else
30     mask_cntv();
31     __DSB();
32     write_cntv_tval(cntfrq);
33     __DSB();
34     unmask_cntv();
35     __DSB();
36 #endif
37 }
38 
rt_hw_timer_init()39 int rt_hw_timer_init()
40 {
41 #ifndef RT_USING_SMP
42     /* timer_clock = apb_clock/(pre_divider + 1) */
43     ARM_TIMER_PREDIV = (250 - 1);
44 
45     ARM_TIMER_RELOAD = 0;
46     ARM_TIMER_LOAD   = 0;
47     ARM_TIMER_IRQCLR = 0;
48     ARM_TIMER_CTRL   = 0;
49 
50     ARM_TIMER_RELOAD = 10000;
51     ARM_TIMER_LOAD   = 10000;
52 
53     /* 23-bit counter, enable interrupt, enable timer */
54     ARM_TIMER_CTRL   = (1 << 1) | (1 << 5) | (1 << 7);
55 #else
56     __DSB();
57     cntfrq = 35000;
58     write_cntv_tval(cntfrq);
59     enable_cntv();
60     __DSB();
61     enable_cpu_timer_intr(rt_hw_cpu_id());
62 #endif
63 
64     rt_hw_interrupt_install(IRQ_ARM_TIMER, rt_hw_timer_isr, RT_NULL, "tick");
65     rt_hw_interrupt_umask(IRQ_ARM_TIMER);
66     return 0;
67 }
68 #ifdef RT_USING_SMP
69 extern void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler);
70 
ipi_handler()71 void ipi_handler()
72 {
73     rt_scheduler_ipi_handler(0,RT_NULL);
74 }
75 #endif
76 
idle_wfi(void)77 void idle_wfi(void)
78 {
79     asm volatile ("wfi");
80 }
81 
rt_hw_board_init(void)82 void rt_hw_board_init(void)
83 {
84     /* initialize hardware interrupt */
85     rt_hw_interrupt_init();
86     rt_hw_vector_init();
87     /* initialize uart */
88     rt_hw_uart_init();
89     /* initialize timer for os tick */
90     rt_hw_timer_init();
91     rt_thread_idle_sethook(idle_wfi);
92 #if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
93     /* set console device */
94     rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
95 #endif
96 #ifdef RT_USING_HEAP
97     /* initialize memory system */
98     rt_kprintf("heap: 0x%08x - 0x%08x\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
99     rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
100 #endif
101 
102 #ifdef RT_USING_SMP
103     /* install IPI handle */
104     rt_hw_ipi_handler_install(IRQ_ARM_MAILBOX, ipi_handler);
105     rt_hw_interrupt_umask(IRQ_ARM_MAILBOX);
106     enable_cpu_ipi_intr(0);
107 #endif
108 #ifdef RT_USING_COMPONENTS_INIT
109     rt_components_board_init();
110 #endif
111 
112 }
113 
114 
115 void _reset(void);
116 void secondary_cpu_start(void);
117 
118 #ifdef RT_USING_SMP
rt_hw_secondary_cpu_up(void)119 void rt_hw_secondary_cpu_up(void)
120 {
121     int i;
122     int retry,val;
123     rt_cpu_dcache_clean_flush();
124     rt_cpu_icache_flush();
125     /*TODO maybe, there is some bug */
126     for (i = RT_CPUS_NR - 1; i>0; i-- )
127     {
128         rt_kprintf("boot cpu:%d\n", i);
129         setup_bootstrap_addr(i, (int)_reset);
130         __SEV();
131         __DSB();
132         __ISB();
133         retry = 10;
134         rt_thread_delay(RT_TICK_PER_SECOND/1000);
135         do
136         {
137             val = CORE_MAILBOX3_CLEAR(i);
138             if (val == 0)
139             {
140                 rt_kprintf("start OK: CPU %d \n",i);
141                 break;
142             }
143             rt_thread_delay(RT_TICK_PER_SECOND);
144 
145             retry --;
146             if (retry <= 0)
147             {
148                 rt_kprintf("can't start for CPU %d \n",i);
149                 break;
150             }
151         } while (1);
152     }
153     __DSB();
154     __SEV();
155 }
156 
secondary_cpu_c_start(void)157 void secondary_cpu_c_start(void)
158 {
159     uint32_t id;
160     id = rt_hw_cpu_id();
161     rt_kprintf("cpu = 0x%08x\n",id);
162     rt_hw_timer_init();
163     rt_kprintf("cpu %d startup.\n",id);
164     rt_hw_vector_init();
165     enable_cpu_ipi_intr(id);
166     rt_hw_spin_lock(&_cpus_lock);
167     rt_system_scheduler_start();
168 }
169 
rt_hw_secondary_cpu_idle_exec(void)170 void rt_hw_secondary_cpu_idle_exec(void)
171 {
172     __WFE();
173 }
174 
175 #endif
176 
177 
178