1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author         Notes
8  * 2020-04-16     bigmagic       first version
9  * 2020-05-26     bigmagic       add other uart
10  */
11 
12 #include <rthw.h>
13 #include <rtthread.h>
14 #include <rtdevice.h>
15 
16 #include "board.h"
17 #include "drv_uart.h"
18 #include "drv_gpio.h"
19 #include <mmu.h>
20 
21 size_t uart0_addr = 0;
22 size_t uart3_addr = 0;
23 size_t uart4_addr = 0;
24 size_t uart5_addr = 0;
25 
26 #ifdef RT_USING_UART0
27 static struct rt_serial_device _serial0;
28 #endif
29 
30 #ifdef RT_USING_UART1
31 static struct rt_serial_device _serial1;
32 #endif
33 
34 #ifdef RT_USING_UART3
35 static struct rt_serial_device _serial3;
36 #endif
37 
38 #ifdef RT_USING_UART4
39 static struct rt_serial_device _serial4;
40 #endif
41 
42 #ifdef RT_USING_UART5
43 static struct rt_serial_device _serial5;
44 #endif
45 
46 struct hw_uart_device
47 {
48     rt_ubase_t hw_base;
49     rt_uint32_t irqno;
50 };
51 
uart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)52 static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
53 {
54     struct hw_uart_device *uart;
55     uint32_t bauddiv = (UART_REFERENCE_CLOCK / cfg->baud_rate)* 1000 / 16;
56     uint32_t ibrd = bauddiv / 1000;
57 
58     RT_ASSERT(serial != RT_NULL);
59     uart = (struct hw_uart_device *)serial->parent.user_data;
60 
61     if(uart->hw_base == AUX_BASE)
62     {
63         prev_raspi_pin_mode(GPIO_PIN_14, ALT5);
64         prev_raspi_pin_mode(GPIO_PIN_15, ALT5);
65 
66         AUX_ENABLES(uart->hw_base)      = 1;    /* Enable UART1 */
67         AUX_MU_IER_REG(uart->hw_base)   = 0;    /* Disable interrupt */
68         AUX_MU_CNTL_REG(uart->hw_base)  = 0;    /* Disable Transmitter and Receiver */
69         AUX_MU_LCR_REG(uart->hw_base)   = 3;    /* Works in 8-bit mode */
70         AUX_MU_MCR_REG(uart->hw_base)   = 0;    /* Disable RTS */
71         AUX_MU_IIR_REG(uart->hw_base)   = 0xC6; /* Enable FIFO, Clear FIFO */
72         AUX_MU_BAUD_REG(uart->hw_base)  = 270;  /* 115200 = system clock 250MHz / (8 * (baud + 1)), baud = 270 */
73         AUX_MU_CNTL_REG(uart->hw_base)  = 3;    /* Enable Transmitter and Receiver */
74         return RT_EOK;
75     }
76 
77     if(uart->hw_base == uart0_addr)
78     {
79         prev_raspi_pin_mode(GPIO_PIN_14, ALT0);
80         prev_raspi_pin_mode(GPIO_PIN_15, ALT0);
81     }
82 
83     if(uart->hw_base == uart3_addr)
84     {
85         prev_raspi_pin_mode(GPIO_PIN_4, ALT4);
86         prev_raspi_pin_mode(GPIO_PIN_5, ALT4);
87     }
88 
89     if(uart->hw_base == uart4_addr)
90     {
91         prev_raspi_pin_mode(GPIO_PIN_8, ALT4);
92         prev_raspi_pin_mode(GPIO_PIN_9, ALT4);
93     }
94 
95     if(uart->hw_base == uart5_addr)
96     {
97         prev_raspi_pin_mode(GPIO_PIN_12, ALT4);
98         prev_raspi_pin_mode(GPIO_PIN_13, ALT4);
99     }
100 
101     PL011_REG_CR(uart->hw_base) = 0;/*Clear UART setting*/
102     PL011_REG_LCRH(uart->hw_base) = 0;/*disable FIFO*/
103     PL011_REG_IBRD(uart->hw_base) = ibrd;
104     PL011_REG_FBRD(uart->hw_base) = (((bauddiv - ibrd * 1000) * 64 + 500) / 1000);
105     PL011_REG_LCRH(uart->hw_base) = PL011_LCRH_WLEN_8;/*FIFO*/
106     PL011_REG_CR(uart->hw_base) = PL011_CR_UARTEN | PL011_CR_TXE | PL011_CR_RXE;/*art enable, TX/RX enable*/
107 
108     return RT_EOK;
109 }
110 
uart_control(struct rt_serial_device * serial,int cmd,void * arg)111 static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
112 {
113     struct hw_uart_device *uart;
114 
115     RT_ASSERT(serial != RT_NULL);
116     uart = (struct hw_uart_device *)serial->parent.user_data;
117     switch (cmd)
118     {
119     case RT_DEVICE_CTRL_CLR_INT:
120         break;
121 
122     case RT_DEVICE_CTRL_SET_INT:
123         /* enable rx irq */
124         if(uart->hw_base == AUX_BASE)
125         {
126             AUX_MU_IER_REG(uart->hw_base) = 0x1;
127         }
128         else
129         {
130             PL011_REG_IMSC(uart->hw_base) |= PL011_IMSC_RXIM;
131         }
132         rt_hw_interrupt_umask(uart->irqno);
133         break;
134     }
135     return RT_EOK;
136 }
137 
uart_putc(struct rt_serial_device * serial,char c)138 static int uart_putc(struct rt_serial_device *serial, char c)
139 {
140     struct hw_uart_device *uart;
141     RT_ASSERT(serial != RT_NULL);
142     uart = (struct hw_uart_device *)serial->parent.user_data;
143     if(uart->hw_base == AUX_BASE)
144     {
145         while (!(AUX_MU_LSR_REG(uart->hw_base) & 0x20));
146         AUX_MU_IO_REG(uart->hw_base) = c;
147     }
148     else
149     {
150         while ((PL011_REG_FR(uart->hw_base) & PL011_FR_TXFF));
151         PL011_REG_DR(uart->hw_base) = (uint8_t)c;
152     }
153     return 1;
154 }
155 
uart_getc(struct rt_serial_device * serial)156 static int uart_getc(struct rt_serial_device *serial)
157 {
158     int ch = -1;
159     struct hw_uart_device *uart;
160 
161     RT_ASSERT(serial != RT_NULL);
162     uart = (struct hw_uart_device *)serial->parent.user_data;
163 
164     if(uart->hw_base == AUX_BASE)
165     {
166         if ((AUX_MU_LSR_REG(uart->hw_base) & 0x01))
167         {
168             ch = AUX_MU_IO_REG(uart->hw_base) & 0xff;
169         }
170     }
171     else
172     {
173         if((PL011_REG_FR(uart->hw_base) & PL011_FR_RXFE) == 0)
174         {
175             ch = PL011_REG_DR(uart->hw_base) & 0xff;
176         }
177     }
178 
179     return ch;
180 }
181 
182 static const struct rt_uart_ops _uart_ops =
183 {
184     uart_configure,
185     uart_control,
186     uart_putc,
187     uart_getc,
188 };
189 
190 volatile void *earlycon_base = 0;
191 const size_t earlycon_size = 0x1000;
192 
early_putc(int c)193 extern void early_putc(int c)
194 {
195     if (c == '\n')
196     {
197         early_putc('\r');
198     }
199     while (!(AUX_MU_LSR_REG(earlycon_base) & 0x20));
200     AUX_MU_IO_REG(earlycon_base) = c;
201 }
202 
rt_hw_earlycon_ioremap_early(void)203 void rt_hw_earlycon_ioremap_early(void)
204 {
205     earlycon_base = rt_ioremap_early((void *)AUX_BASE, earlycon_size);
206 }
207 
rt_hw_console_output(const char * str)208 void rt_hw_console_output(const char *str)
209 {
210     if (earlycon_base)
211     {
212         while (*str)
213         {
214             early_putc(*str++);
215         }
216     }
217 }
218 
early_printhex(rt_ubase_t number)219 void early_printhex(rt_ubase_t number)
220 {
221     char str[sizeof("0123456789abcdef")];
222 
223     str[16] = 0;
224 
225     for (int i = 15; i >= 0; --i)
226     {
227         str[i] = "0123456789abcdef"[(number & 0xf)];
228 
229         number >>= 4;
230     }
231 
232     rt_kputs(str);
233 }
234 
235 #ifdef RT_USING_UART1
rt_hw_aux_uart_isr(int irqno,void * param)236 static void rt_hw_aux_uart_isr(int irqno, void *param)
237 {
238     struct rt_serial_device *serial = (struct rt_serial_device*)param;
239     rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
240 }
241 #endif
242 
rt_hw_uart_isr(int irqno,void * param)243 static void rt_hw_uart_isr(int irqno, void *param)
244 {
245 #ifdef RT_USING_UART0
246     if((PACTL_CS & IRQ_UART0) == IRQ_UART0)
247     {
248         PACTL_CS &=  ~(IRQ_UART0);
249         rt_hw_serial_isr(&_serial0, RT_SERIAL_EVENT_RX_IND);
250         PL011_REG_ICR(uart0_addr) = PL011_INTERRUPT_RECEIVE;
251     }
252 #endif
253 
254 #ifdef RT_USING_UART3
255     if((PACTL_CS & IRQ_UART3) == IRQ_UART3)
256     {
257         PACTL_CS &=  ~(IRQ_UART3);
258         rt_hw_serial_isr(&_serial3, RT_SERIAL_EVENT_RX_IND);
259         PL011_REG_ICR(uart3_addr) = PL011_INTERRUPT_RECEIVE;
260     }
261 #endif
262 
263 #ifdef RT_USING_UART4
264     if((PACTL_CS & IRQ_UART4) == IRQ_UART4)
265     {
266         PACTL_CS &=  ~(IRQ_UART4);
267         rt_hw_serial_isr(&_serial4, RT_SERIAL_EVENT_RX_IND);
268         PL011_REG_ICR(uart4_addr) = PL011_INTERRUPT_RECEIVE;
269     }
270 #endif
271 
272 #ifdef RT_USING_UART5
273     if((PACTL_CS & IRQ_UART5) == IRQ_UART5)
274     {
275         PACTL_CS &=  ~(IRQ_UART5);
276         rt_hw_serial_isr(&_serial5, RT_SERIAL_EVENT_RX_IND);
277         PL011_REG_ICR(uart5_addr) = PL011_INTERRUPT_RECEIVE;
278     }
279 #endif
280 }
281 
282 #ifdef RT_USING_UART0
283 /* UART device driver structure */
284 static struct hw_uart_device _uart0_device =
285 {
286     UART0_BASE,
287     IRQ_PL011,
288 };
289 #endif
290 
291 #ifdef RT_USING_UART1
292 /* UART device driver structure */
293 static struct hw_uart_device _uart1_device =
294 {
295     AUX_BASE,
296     IRQ_AUX_UART,
297 };
298 #endif
299 
300 #ifdef RT_USING_UART3
301 static struct hw_uart_device _uart3_device =
302 {
303     UART3_BASE,
304     IRQ_PL011,
305 };
306 #endif
307 
308 #ifdef RT_USING_UART4
309 static struct hw_uart_device _uart4_device =
310 {
311     UART4_BASE,
312     IRQ_PL011,
313 };
314 #endif
315 
316 #ifdef RT_USING_UART5
317 static struct hw_uart_device _uart5_device =
318 {
319     UART5_BASE,
320     IRQ_PL011,
321 };
322 #endif
323 
rt_hw_uart_init(void)324 int rt_hw_uart_init(void)
325 {
326     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
327 #ifdef RT_USING_UART0
328     struct hw_uart_device *uart0;
329     uart0 = &_uart0_device;
330 
331     _serial0.ops    = &_uart_ops;
332     _serial0.config = config;
333 
334     uart0_addr = UART0_BASE;
335 #ifdef RT_USING_SMART
336     uart0_addr = (size_t)rt_ioremap((void*)UART0_BASE, 0x1000);
337 #endif
338     earlycon_base = (void *)uart0_addr;
339     uart0->hw_base = uart0_addr;
340 
341 
342     /* register UART0 device */
343     rt_hw_serial_register(&_serial0, "uart0",
344                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
345                           uart0);
346     rt_hw_interrupt_install(uart0->irqno, rt_hw_uart_isr, &_serial0, "uart0");
347 
348 #endif
349 
350 #ifdef RT_USING_UART1
351     struct hw_uart_device *uart1;
352     uart1 = &_uart1_device;
353 
354     _serial1.ops    = &_uart_ops;
355     _serial1.config = config;
356 
357     uart1->hw_base = (size_t)rt_ioremap((void*)AUX_BASE, 0x1000);
358 
359     /* register UART1 device */
360     rt_hw_serial_register(&_serial1, "uart1",
361                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
362                           uart1);
363     rt_hw_interrupt_install(uart1->irqno, rt_hw_aux_uart_isr, &_serial1, "uart1");
364 #endif
365 
366 #ifdef RT_USING_UART3
367     struct hw_uart_device *uart3;
368     uart3 = &_uart3_device;
369 
370     _serial3.ops    = &_uart_ops;
371     _serial3.config = config;
372 
373     uart3_addr = (size_t)rt_ioremap((void*)UART3_BASE, 0x1000);
374     uart3->hw_base = uart3_addr;
375 
376     /* register UART3 device */
377     rt_hw_serial_register(&_serial3, "uart3",
378                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
379                           uart3);
380     rt_hw_interrupt_install(uart3->irqno, rt_hw_uart_isr, &_serial3, "uart3");
381 #endif
382 
383 #ifdef RT_USING_UART4
384     struct hw_uart_device *uart4;
385     uart4 = &_uart4_device;
386 
387     _serial4.ops    = &_uart_ops;
388     _serial4.config = config;
389 
390     uart4_addr = (size_t)rt_ioremap((void*)UART4_BASE, 0x1000);
391     uart4->hw_base = uart4_addr;
392 
393     /* register UART4 device */
394     rt_hw_serial_register(&_serial4, "uart4",
395                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
396                           uart4);
397     rt_hw_interrupt_install(uart4->irqno, rt_hw_uart_isr, &_serial4, "uart4");
398 #endif
399 
400 #ifdef RT_USING_UART5
401     struct hw_uart_device *uart5;
402     uart5 = &_uart5_device;
403 
404     _serial5.ops    = &_uart_ops;
405     _serial5.config = config;
406 
407     uart5_addr = (size_t)rt_ioremap((void*)UART5_BASE, 0x1000);
408     uart5->hw_base = uart5_addr;
409 
410     /* register UART5 device */
411     rt_hw_serial_register(&_serial5, "uart5",
412                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
413                           uart5);
414     rt_hw_interrupt_install(uart5->irqno, rt_hw_uart_isr, &_serial5, "uart5");
415 #endif
416     return 0;
417 }
418 
419