1 /**
2 * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 ******************************************************************************
6 * @file drv_uart.c
7 * @author Huibin Hong
8 * @version V0.5
9 * @date 10-Dec-2018
10 * @brief serial driver
11 *
12 ******************************************************************************
13 */
14
15 #include <rthw.h>
16 #include <rtdevice.h>
17 #include <rtthread.h>
18
19 #ifdef RT_USING_UART
20
21 #include "hal_base.h"
22 #include "hal_bsp.h"
23 #include "drv_uart.h"
24 #include "drv_clock.h"
25 #ifdef RK_BSP_TEMP
26 #include "drv_pm.h"
27 #endif
28 #include "board.h"
29
30 /****************************************************************************
31 * Private Types
32 ****************************************************************************/
33 struct rockchip_uart
34 {
35 const struct uart_board *uart_board;
36 /* HAL */
37 const struct HAL_UART_DEV *dev;
38
39 /* irq handler */
40 rt_isr_handler_t irq_handler;
41 };
42
43 static int rockchip_uart_irq(rt_serial_t *serial);
44
45 #define DEFINE_ROCKCHIP_UART(ID) \
46 static void rockchip_uart##ID##_irq(int irq, void *param); \
47 static struct rt_serial_device serial##ID; \
48 static struct rockchip_uart rk_uart##ID = \
49 { \
50 .uart_board = &g_uart##ID##_board, \
51 .dev = &g_uart##ID##Dev, \
52 .irq_handler = rockchip_uart##ID##_irq, \
53 }; \
54 static void rockchip_uart##ID##_irq(int irq, void *param) \
55 { \
56 rockchip_uart_irq(&serial##ID); \
57 } \
58
59 #if defined(RT_USING_UART0)
60 DEFINE_ROCKCHIP_UART(0);
61 #endif /* RT_USING_UART0 */
62
63 #if defined(RT_USING_UART1)
64 DEFINE_ROCKCHIP_UART(1);
65 #endif /* RT_USING_UART1 */
66
67 #if defined(RT_USING_UART2)
68 DEFINE_ROCKCHIP_UART(2);
69 #endif /* RT_USING_UART2 */
70
71 #if defined(RT_USING_UART3)
72 DEFINE_ROCKCHIP_UART(3);
73 #endif /* RT_USING_UART3 */
74
75 #if defined(RT_USING_UART4)
76 DEFINE_ROCKCHIP_UART(4);
77 #endif /* RT_USING_UART4 */
78
79 #if defined(RT_USING_UART5)
80 DEFINE_ROCKCHIP_UART(5);
81 #endif /* RT_USING_UART5 */
82
83 #if defined(RT_USING_UART6)
84 DEFINE_ROCKCHIP_UART(6);
85 #endif /* RT_USING_UART6 */
86
87 #if defined(RT_USING_UART7)
88 DEFINE_ROCKCHIP_UART(7);
89 #endif /* RT_USING_UART7 */
90
91 #if defined(RT_USING_UART8)
92 DEFINE_ROCKCHIP_UART(8);
93 #endif /* RT_USING_UART8 */
94
95 #if defined(RT_USING_UART9)
96 DEFINE_ROCKCHIP_UART(9);
97 #endif /* RT_USING_UART9 */
98
99 static struct rockchip_uart *rk_uart_table[] =
100 {
101 #if defined(RT_USING_UART0)
102 &rk_uart0,
103 #endif
104 #if defined(RT_USING_UART1)
105 &rk_uart1,
106 #endif
107 #if defined(RT_USING_UART2)
108 &rk_uart2,
109 #endif
110 #if defined(RT_USING_UART3)
111 &rk_uart3,
112 #endif
113 #if defined(RT_USING_UART4)
114 &rk_uart4,
115 #endif
116 #if defined(RT_USING_UART5)
117 &rk_uart5,
118 #endif
119 #if defined(RT_USING_UART6)
120 &rk_uart6,
121 #endif
122 #if defined(RT_USING_UART7)
123 &rk_uart7,
124 #endif
125 #if defined(RT_USING_UART8)
126 &rk_uart8,
127 #endif
128 #if defined(RT_USING_UART9)
129 &rk_uart9,
130 #endif
131 };
132
133 static struct rt_serial_device *rt_serial_table[] =
134 {
135 #if defined(RT_USING_UART0)
136 &serial0,
137 #endif
138 #if defined(RT_USING_UART1)
139 &serial1,
140 #endif
141 #if defined(RT_USING_UART2)
142 &serial2,
143 #endif
144 #if defined(RT_USING_UART3)
145 &serial3,
146 #endif
147 #if defined(RT_USING_UART4)
148 &serial4,
149 #endif
150 #if defined(RT_USING_UART5)
151 &serial5,
152 #endif
153 #if defined(RT_USING_UART6)
154 &serial6,
155 #endif
156 #if defined(RT_USING_UART7)
157 &serial7,
158 #endif
159 #if defined(RT_USING_UART8)
160 &serial8,
161 #endif
162 #if defined(RT_USING_UART9)
163 &serial9,
164 #endif
165 };
166
rockchip_uart_putc(rt_serial_t * serial,char c)167 static int rockchip_uart_putc(rt_serial_t *serial, char c)
168 {
169 struct rockchip_uart *uart = RT_NULL;
170
171 RT_ASSERT(serial != RT_NULL);
172 uart = (struct rockchip_uart *)serial->parent.user_data;
173
174 HAL_UART_SerialOutChar(uart->dev->pReg, c);
175 return 1;
176 }
177
rockchip_uart_getc(rt_serial_t * serial)178 static int rockchip_uart_getc(rt_serial_t *serial)
179 {
180 rt_uint8_t c = 0;
181 int ret = -1;
182
183 struct rockchip_uart *uart = RT_NULL;
184
185 RT_ASSERT(serial != RT_NULL);
186 uart = (struct rockchip_uart *)serial->parent.user_data;
187
188 ret = HAL_UART_SerialIn(uart->dev->pReg, &c, 1);
189
190 if (ret <= 0)
191 {
192 return -1;
193 }
194 else
195 {
196 ret = c;
197 return ret;
198 }
199 }
200
rt_hw_console_channel(void)201 int rt_hw_console_channel(void)
202 {
203 #if defined(RT_CONSOLE_DEVICE_NAME)
204 #if defined(RT_USING_UART0)
205 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart0"))
206 return 0;
207 #endif
208 #if defined(RT_USING_UART1)
209 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart1"))
210 return 1;
211 #endif
212 #if defined(RT_USING_UART2)
213 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart2"))
214 return 2;
215 #endif
216 #if defined(RT_USING_UART3)
217 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart3"))
218 return 3;
219 #endif
220 #if defined(RT_USING_UART4)
221 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart4"))
222 return 4;
223 #endif
224 #if defined(RT_USING_UART5)
225 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart5"))
226 return 5;
227 #endif
228 #if defined(RT_USING_UART6)
229 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart6"))
230 return 6;
231 #endif
232 #if defined(RT_USING_UART7)
233 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart7"))
234 return 7;
235 #endif
236 #if defined(RT_USING_UART8)
237 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart8"))
238 return 8;
239 #endif
240 #if defined(RT_USING_UART9)
241 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart9"))
242 return 9;
243 #endif
244 #endif
245
246 return -RT_EINVAL;
247 }
248
rt_hw_console_output(const char * str)249 void rt_hw_console_output(const char *str)
250 {
251 struct rockchip_uart *uart = RT_NULL;
252
253 #if defined(RT_CONSOLE_DEVICE_NAME)
254 #if defined(RT_USING_UART0)
255 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart0"))
256 uart = &rk_uart0;
257 #endif
258 #if defined(RT_USING_UART1)
259 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart1"))
260 uart = &rk_uart1;
261 #endif
262 #if defined(RT_USING_UART2)
263 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart2"))
264 uart = &rk_uart2;
265 #endif
266 #if defined(RT_USING_UART3)
267 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart3"))
268 uart = &rk_uart3;
269 #endif
270 #if defined(RT_USING_UART4)
271 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart4"))
272 uart = &rk_uart4;
273 #endif
274 #if defined(RT_USING_UART5)
275 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart5"))
276 uart = &rk_uart5;
277 #endif
278 #if defined(RT_USING_UART6)
279 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart6"))
280 uart = &rk_uart6;
281 #endif
282 #if defined(RT_USING_UART7)
283 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart7"))
284 uart = &rk_uart7;
285 #endif
286 #if defined(RT_USING_UART8)
287 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart8"))
288 uart = &rk_uart8;
289 #endif
290 #if defined(RT_USING_UART9)
291 if (!strcmp(RT_CONSOLE_DEVICE_NAME, "uart9"))
292 uart = &rk_uart9;
293 #endif
294 #endif
295
296 if (!uart)
297 return;
298
299 while (*str)
300 {
301 if (*str == '\n')
302 HAL_UART_SerialOutChar(uart->dev->pReg, '\r');
303
304 HAL_UART_SerialOutChar(uart->dev->pReg, *str);
305 str++;
306 }
307 }
308
rockchip_uart_configure(rt_serial_t * serial,struct serial_configure * cfg)309 static rt_err_t rockchip_uart_configure(rt_serial_t *serial, struct serial_configure *cfg)
310 {
311 struct rockchip_uart *uart = RT_NULL;
312 struct HAL_UART_CONFIG hal_uart_config;
313 const struct HAL_UART_DEV *dev;
314
315 RT_ASSERT(serial != RT_NULL);
316 uart = (struct rockchip_uart *)serial->parent.user_data;
317 dev = uart->dev;
318
319 if (cfg->stop_bits == STOP_BITS_1)
320 hal_uart_config.stopBit = UART_ONE_STOPBIT;
321 else if (cfg->stop_bits == STOP_BITS_2)
322 hal_uart_config.stopBit = UART_ONE_AND_HALF_OR_TWO_STOPBIT;
323 else
324 rt_kprintf("STOP_BITS_3 and STOP_BITS_4 are not supported\n");
325
326 if (cfg->parity == PARITY_ODD)
327 hal_uart_config.parity = UART_ODD_PARITY;
328 else if (cfg->parity == PARITY_EVEN)
329 hal_uart_config.parity = UART_EVEN_PARITY;
330 else
331 hal_uart_config.parity = UART_PARITY_DISABLE;
332
333 hal_uart_config.baudRate = cfg->baud_rate;
334 hal_uart_config.dataBit = cfg->data_bits;
335
336 HAL_UART_Init(dev, &hal_uart_config);
337 #ifdef RK_BSP_TEMP
338 if (dev->isAutoFlow && (cfg->flow_ctrl == RT_SERIAL_AUTO_FLOW_ENABLE))
339 HAL_UART_EnableAutoFlowControl(dev->pReg);
340 else
341 HAL_UART_DisableAutoFlowControl(dev->pReg);
342 #endif
343 rt_hw_interrupt_umask(dev->irqNum);
344
345 return RT_EOK;
346 }
347
rockchip_uart_control(rt_serial_t * serial,int cmd,void * arg)348 static rt_err_t rockchip_uart_control(rt_serial_t *serial, int cmd, void *arg)
349 {
350 struct rockchip_uart *uart = RT_NULL;
351 struct UART_REG *hw_base = RT_NULL;
352 const struct HAL_UART_DEV *dev;
353 rt_uint32_t flag = (rt_uint32_t)arg;
354
355 RT_ASSERT(serial != RT_NULL);
356 uart = (struct rockchip_uart *)serial->parent.user_data;
357 hw_base = uart->dev->pReg;
358 dev = uart->dev;
359
360 switch (cmd)
361 {
362 case RT_DEVICE_CTRL_CLR_INT:
363 if (flag == RT_DEVICE_FLAG_INT_RX)
364 HAL_UART_DisableIrq(hw_base, UART_IER_RDI);
365 else if (flag == RT_DEVICE_FLAG_INT_TX)
366 HAL_UART_DisableIrq(hw_base, UART_IER_THRI);
367 break;
368
369 case RT_DEVICE_CTRL_SET_INT:
370 if (flag == RT_DEVICE_FLAG_INT_RX)
371 HAL_UART_EnableIrq(hw_base, UART_IER_RDI);
372 else if (flag == RT_DEVICE_FLAG_INT_TX)
373 HAL_UART_EnableIrq(hw_base, UART_IER_THRI);
374 break;
375 case RT_DEVICE_CTRL_CONFIG:
376 if (flag == RT_DEVICE_FLAG_DMA_RX)
377 HAL_UART_EnableIrq(hw_base, UART_IER_RDI);
378 break;
379 #ifdef RK_BSP_TEMP
380 case RT_DEVICE_CTRL_HW_OPEN:
381 clk_enable_by_id(dev->sclkGateID);
382 break;
383 case RT_DEVICE_CTRL_HW_CLOSE:
384 clk_disable_by_id(dev->sclkGateID);
385 break;
386 #endif
387 }
388
389 return RT_EOK;
390 }
391
rockchip_uart_irq(rt_serial_t * serial)392 static int rockchip_uart_irq(rt_serial_t *serial)
393 {
394 rt_uint32_t iir = 0;
395 struct rockchip_uart *uart = RT_NULL;
396 struct UART_REG *hw_base = RT_NULL;
397
398 RT_ASSERT(serial != RT_NULL);
399 uart = (struct rockchip_uart *)serial->parent.user_data;
400 hw_base = uart->dev->pReg;
401
402 rt_interrupt_enter();
403
404 iir = HAL_UART_GetIrqID(hw_base);
405
406 switch (iir)
407 {
408 case UART_IIR_RDI:
409 case UART_IIR_RX_TIMEOUT:
410 rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
411 break;
412
413 case UART_IIR_THRI:
414 rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE);
415 break;
416
417 default:
418 HAL_UART_HandleIrq(hw_base);
419 break;
420 }
421
422 rt_interrupt_leave();
423 return 0;
424 }
425
426 static const struct rt_uart_ops rockchip_uart_ops =
427 {
428 rockchip_uart_configure,
429 rockchip_uart_control,
430 rockchip_uart_putc,
431 rockchip_uart_getc,
432 };
433
434 #ifdef RT_USING_PM
435
436 static struct UART_SAVE_CONFIG pUartSave;
437
rockchip_uart_suspend(const struct rt_device * device)438 static int rockchip_uart_suspend(const struct rt_device *device)
439 {
440 struct rockchip_uart *uart = RT_NULL;
441 const struct HAL_UART_DEV *dev;
442
443 RT_ASSERT(device != RT_NULL);
444 uart = (struct rockchip_uart *)device->user_data;
445 dev = uart->dev;
446
447 rt_hw_interrupt_mask(dev->irqNum);
448 HAL_UART_Suspend(dev->pReg, &pUartSave);
449 clk_disable_by_id(dev->pclkGateID);
450 clk_disable_by_id(dev->sclkGateID);
451 return RT_EOK;
452 }
453
rockchip_uart_resume(const struct rt_device * device)454 static void rockchip_uart_resume(const struct rt_device *device)
455 {
456 struct rockchip_uart *uart = RT_NULL;
457 const struct HAL_UART_DEV *dev;
458
459 RT_ASSERT(device != RT_NULL);
460 uart = (struct rockchip_uart *)device->user_data;
461 dev = uart->dev;
462
463 clk_enable_by_id(dev->pclkGateID);
464 clk_enable_by_id(dev->sclkGateID);
465 HAL_UART_Reset(dev->pReg);
466 HAL_UART_Resume(dev->pReg, &pUartSave);
467 rt_hw_interrupt_umask(dev->irqNum);
468 }
469
470 static const struct rt_device_pm_ops rockchip_uart_pm_ops =
471 {
472 .suspend = rockchip_uart_suspend,
473 .resume = rockchip_uart_resume,
474 };
475
rockchip_rt_hw_uart_pm_register(void)476 int rockchip_rt_hw_uart_pm_register(void)
477 {
478 int i = 0;
479 struct rockchip_uart *uart;
480 struct rt_serial_device *serial;
481 const struct uart_board *uart_board;
482
483 for (i = 0; i < HAL_ARRAY_SIZE(rk_uart_table); i++)
484 {
485 uart = rk_uart_table[i];
486 if (uart)
487 {
488 rt_bool_t is_console;
489 uart_board = uart->uart_board;
490
491 #ifdef RT_CONSOLE_DEVICE_NAME
492 if (!strcmp(RT_CONSOLE_DEVICE_NAME, uart_board->name))
493 is_console = true;
494 else
495 is_console = false;
496 #else
497 is_console = false;
498 #endif
499
500 serial = rt_serial_table[i];
501 serial->ops = &rockchip_uart_ops;
502 #ifdef RK_BSP_TEMP
503 if (!is_console && !uart_board->en_irq_wake)
504 rt_pm_register_device(&serial->parent, &rockchip_uart_pm_ops);
505 #endif
506 }
507 }
508
509 return 0;
510 }
511 INIT_PREV_EXPORT(rockchip_rt_hw_uart_pm_register);
512
513 #endif
514
rt_hw_usart_init(void)515 void rt_hw_usart_init(void)
516 {
517 int i = 0;
518 struct rockchip_uart *uart;
519 struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
520 struct rt_serial_device *serial;
521 const struct HAL_UART_DEV *dev;
522 const struct uart_board *uart_board;
523
524 for (i = 0; i < HAL_ARRAY_SIZE(rk_uart_table); i++)
525 {
526 uart = rk_uart_table[i];
527 if (uart)
528 {
529 rt_bool_t is_console; /* uart is used for console */
530
531 dev = uart->dev;
532 uart_board = uart->uart_board;
533
534 if (uart_board->baud_rate)
535 {
536 config.baud_rate = uart_board->baud_rate;
537 }
538
539 #ifdef RT_CONSOLE_DEVICE_NAME
540 if (!strcmp(RT_CONSOLE_DEVICE_NAME, uart_board->name))
541 {
542 is_console = true;
543 }
544 else
545 {
546 is_console = false;
547 }
548 #else
549 is_console = false;
550 #endif
551
552 config.bufsz = uart_board->bufer_size;
553 serial = rt_serial_table[i];
554 serial->ops = &rockchip_uart_ops;
555 serial->config = config;
556
557 /* enable uart clk here */
558 clk_enable_by_id(dev->pclkGateID);
559 clk_enable_by_id(dev->sclkGateID);
560
561 if (!is_console)
562 HAL_UART_Reset(dev->pReg);
563
564 /* register UARTx device */
565 rt_hw_serial_register(serial, uart_board->name,
566 uart_board->dev_flag, (void *)uart);
567
568 /* enable interrupt */
569 rt_hw_interrupt_install(dev->irqNum, uart->irq_handler,
570 RT_NULL, uart_board->name);
571 rt_hw_interrupt_mask(dev->irqNum);
572 }
573 }
574 }
575 #endif
576