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  * 2012-02-13   mojingxian  first version
9  */
10 
11 #include "board.h"
12 #include "rtconfig.h"
13 #include "rtdef.h"
14 #include "rthw.h"
15 #include "drivers/dev_serial.h"
16 
17 #include <signal.h>
18 #include <sys/platform.h>
19 #include <ccblkfn.h>
20 #include <sysreg.h>
21 #include <string.h>
22 #include <sys\exception.h>
23 #include <stdio.h>
24 
25 #define IVG_CLR(index)     (index > 0 ? ((0xFFFFFFF0 << (index * 0x04)) | \
26                            (0xFFFFFFF0 >> ((0x08 - index) * 0x04))):0xFFFFFFF0)
27 #define IVG_SET(index,ivg) ((((ivg) - 0x07) & 0x0F) << (index * 0x04))
28 
29 #define UART0   ((struct uartport *)pUART_THR)
30 struct serial_int_rx uart0_int_rx;
31 struct serial_device uart0 =
32 {
33     UART0,
34     &uart0_int_rx,
35     RT_NULL
36 };
37 struct rt_device uart0_device;
38 
39 /**
40  * This function is to set the EBIU(EXTERNAL BUS INTERFACE UNIT).
41  */
rt_hw_ebiu_init(void)42 static void rt_hw_ebiu_init(void)
43 {
44     *pEBIU_AMBCTL0  = 0xffc2ffc2;
45 
46     *pEBIU_AMBCTL1  = 0xffc2ffc3;
47 
48     *pEBIU_AMGCTL   = 0x010f;
49 }
50 
51 /**
52  * This is the timer interrupt service routine.
53  */
EX_INTERRUPT_HANDLER(rt_hw_timer_handler)54 EX_INTERRUPT_HANDLER(rt_hw_timer_handler)
55 {
56     /* enter interrupt */
57     rt_interrupt_enter();
58 
59     rt_tick_increase();
60 
61     /* leave interrupt */
62     rt_interrupt_leave();
63 }
64 
65 /**
66  * This function is called to initialize system tick source (typically a
67  * timer generating interrupts every 1 to 100 mS).
68  * We decided to use Core Timer as the tick interrupt source.
69  */
rt_hw_core_timer_init(void)70 void rt_hw_core_timer_init(void)
71 {
72     *pTCNTL   = 1;     // Turn on timer, TMPWR
73     *pTSCALE  = 0x00;
74     *pTCOUNT  = CCLKSPEED / RT_TICK_PER_SECOND;
75     *pTPERIOD = CCLKSPEED / RT_TICK_PER_SECOND;
76     register_handler(ik_timer,rt_hw_timer_handler);
77     *pTCNTL    = 0x07; // Start Timer and set Auto-reload
78 }
79 
rt_hw_interrupt_init(void)80 void rt_hw_interrupt_init(void)
81 {
82     extern rt_uint32_t rt_interrupt_from_thread;
83     extern rt_uint32_t rt_interrupt_to_thread;
84     extern rt_uint32_t rt_thread_switch_interrupt_flag;
85     extern rt_uint8_t  rt_interrupt_nest;
86     extern void interrupt_thread_switch(void);
87 
88     register_handler(ik_ivg14,interrupt_thread_switch); //context_vdsp.S
89 
90     /* init interrupt nest, and context in thread sp */
91     rt_interrupt_nest               = 0;
92     rt_interrupt_from_thread        = 0;
93     rt_interrupt_to_thread          = 0;
94     rt_thread_switch_interrupt_flag = 0;
95 }
96 
rt_hw_pll_init(void)97 static void rt_hw_pll_init(void)
98 {
99     unsigned long imask;
100 
101     sysreg_write(reg_SYSCFG, 0x32);
102 
103     *pSIC_IWR = 0x01;
104 
105     *pPLL_CTL = SET_MSEL(SPEED_MULTIPLE);
106 
107     // PLL Re-programming Sequence.
108     // Core is idle'ed to allow the PPL to re-lock.
109     imask = cli();
110     idle();
111     sti(imask);
112     *pVR_CTL = 0x00FB;
113 
114     // PLL Re-programming Sequence.
115     // Core is idle'ed to allow the PPL to re-lock.
116     imask = cli();
117     idle();
118     sti(imask);
119 
120     *pPLL_DIV = BUS_DIVISOR;
121 }
122 
123 /**
124  * This function is called to initialize external sdram.
125  */
rt_hw_exdram_init(void)126 static void rt_hw_exdram_init(void)
127 {
128     // Initalize EBIU control registers to enable all banks
129     *pEBIU_AMBCTL1 = 0xFFFFFF02;
130     ssync();
131 
132     *pEBIU_AMGCTL = 0x00FF;
133     ssync();
134 
135     // Check if already enabled
136     if (SDRS != ((*pEBIU_SDSTAT) & SDRS))
137     {
138         return;
139     }
140 
141     //SDRAM Refresh Rate Control Register
142     *pEBIU_SDRRC = 0x01A0;
143 
144     //SDRAM Memory Bank Control Register
145     *pEBIU_SDBCTL = 0x0025; //1.7   64 MB
146 
147     //SDRAM Memory Global Control Register
148     *pEBIU_SDGCTL = 0x0091998D;//0x998D0491
149 
150     ssync();
151 }
152 
uart_set_bitrate(unsigned long bit_rate)153 short uart_set_bitrate(unsigned long bit_rate)
154 {
155     unsigned short int divisor;
156 
157     switch (bit_rate)
158     {
159         case 1200:
160         case 2400:
161         case 4800:
162         case 9600:
163         case 19200:
164         case 28800:
165         case 38400:
166         case 57600:
167         case 115200:
168         case 125000:
169             divisor = (unsigned short int) ((float) SCLKSPEED / ((float) bit_rate * 16.0f) + 0.5f);
170 
171             *(pUART_LCR) |= DLAB;            // Enable access to DLL and DLH registers
172             *(pUART_DLL) = divisor & 0xFF;
173             *(pUART_DLH) = divisor >> 8;
174             *(pUART_LCR) &= ~DLAB;           // clear DLAB bit
175 
176             break;
177 
178         default: // baud rate not supported
179             break;
180     }
181 
182     return 0;
183 }
184 
rt_hw_uart_init(void)185 void rt_hw_uart_init(void)
186 {
187     // Apply UART configuration 8 bit data, No parity, 1 stop bit
188     *pUART_LCR = 0x0000; // Reset value
189     *pUART_LCR = WLS(8);
190 
191      // Ensure that Loopback mode is disabled by clearing LOOP_ENA bit
192     *pUART_MCR = 0x0000; //Reset value
193 
194     uart_set_bitrate(19200);// Set communication baudrate 115200
195 
196     *pUART_IER = ERBFI;
197 
198     // Enable UART clock
199     *pUART_GCTL = UCEN;
200 }
201 
uart_put_char(const char c)202 int uart_put_char(const char c)
203 {
204     while (!(*pUART_LSR & THRE))
205     {
206         /* wait */
207     }
208 
209     *pUART_THR = c;
210 
211     return c;
212 }
213 
rt_hw_console_output(const char * str)214 void rt_hw_console_output(const char *str)
215 {
216     while (*str != '\0')
217     {
218         if (*str == '\n')
219             uart_put_char('\r');
220         uart_put_char(*str++);
221     }
222 }
223 
EX_INTERRUPT_HANDLER(uart_rx_isr)224 EX_INTERRUPT_HANDLER(uart_rx_isr)
225 {
226     rt_interrupt_enter();
227 
228     rt_hw_serial_isr(&uart0_device);
229 
230     rt_interrupt_leave();
231 }
232 
rt_hw_isr_install(void)233 void rt_hw_isr_install(void)
234 {
235     *pSIC_IWR   = 0xFFFFFFFF;
236     *pSIC_IMASK = 0x00000000;
237 
238     *pSIC_IAR1 &= IVG_CLR(IAR1_DMA6_UARTRX_IVG);
239     *pSIC_IAR1 |= IVG_SET(IAR1_DMA6_UARTRX_IVG,ik_ivg9);
240     register_handler(ik_ivg9,uart_rx_isr);
241     *pSIC_IMASK |= DMA6_UART_RX_INT_MASK;/*  开中断      */
242 }
243 
rt_hw_board_init(void)244 void rt_hw_board_init(void)
245 {
246     rt_hw_pll_init();
247 
248     rt_hw_ebiu_init();
249 
250     rt_hw_exdram_init();
251 
252     rt_hw_uart_init();
253 }
254