1 /*
2 * Copyright (c) 2006-2020, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 */
9
10 #include <rthw.h>
11 #include <rtdevice.h>
12 #include <rtthread.h>
13
14 #include "board.h"
15 #include "drv_uart.h"
16
17 #include <stdio.h>
18 #ifdef RT_USING_SMART
19 #include <ioremap.h>
20 #endif
21 #include "sbi.h"
22
23 struct device_uart
24 {
25 rt_ubase_t hw_base;
26 rt_uint32_t irqno;
27 };
28
29 void *uart0_base = (void*)0x10000000;
30 struct rt_serial_device serial0;
31 struct device_uart uart0;
32
uart_init(void)33 void uart_init(void)
34 {
35 rt_uint32_t div = UART_REFERENCE_CLOCK / (UART_DEFAULT_BAUDRATE * 16);
36
37 write8_uart0(UART_IER, 0x00);
38 write8_uart0(UART_LCR, UART_LCR_BAUD_LATCH);
39
40 // LSB
41 write8_uart0(0, div & 0xff);
42 // MSB
43 write8_uart0(1, (div >> 8) & 0xff);
44
45 // set word length to 8 bits, no parity
46 write8_uart0(UART_LCR, UART_LCR_EIGHT_BITS);
47
48 write8_uart0(UART_FCR, UART_FCR_FIFO_ENABLE | UART_FCR_FIFO_CLEAR);
49
50 return;
51 }
52
_uart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)53 static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
54 {
55 return (RT_EOK);
56 }
57
_uart_control(struct rt_serial_device * serial,int cmd,void * arg)58 static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *arg)
59 {
60 struct device_uart *uart = (struct device_uart*)serial->parent.user_data;
61
62 switch (cmd)
63 {
64 case RT_DEVICE_CTRL_CLR_INT:
65 if ((size_t)arg == RT_DEVICE_FLAG_INT_RX)
66 {
67 rt_uint8_t value = read8_uart0(UART_IER);
68 write8_uart0(UART_IER, value & ~UART_IER_RX_ENABLE);
69 }
70 break;
71
72 case RT_DEVICE_CTRL_SET_INT:
73 if ((size_t)arg == RT_DEVICE_FLAG_INT_RX)
74 {
75 rt_uint8_t value = read8_uart0(UART_IER);
76 write8_uart0(UART_IER, value | UART_IER_RX_ENABLE);
77 }
78 break;
79 }
80
81 return (RT_EOK);
82 }
83
_uart_putc(struct rt_serial_device * serial,char c)84 static int _uart_putc(struct rt_serial_device *serial, char c)
85 {
86 struct device_uart *uart;
87 uart = (struct device_uart*)serial->parent.user_data;
88
89 // wait for Transmit Holding Empty to be set in LSR.
90 while((read8_uart0(UART_LSR) & UART_LSR_TX_IDLE) == 0)
91 ;
92 write8_uart0(UART_THR, c);
93
94 return (1);
95 }
96
_uart_getc(struct rt_serial_device * serial)97 static int _uart_getc(struct rt_serial_device *serial)
98 {
99 struct device_uart *uart;
100 volatile rt_uint32_t lsr;
101 int ch = -1;
102
103 uart = (struct device_uart*)serial->parent.user_data;
104 lsr = read8_uart0(UART_LSR);
105
106 if (lsr & UART_LSR_RX_READY)
107 {
108 ch = read8_uart0(UART_RHR);
109 }
110 return ch;
111 }
112
113 const struct rt_uart_ops _uart_ops = {
114 _uart_configure,
115 _uart_control,
116 _uart_putc,
117 _uart_getc,
118 // TODO: add DMA support
119 RT_NULL};
120
rt_hw_uart_isr(int irqno,void * param)121 static void rt_hw_uart_isr(int irqno, void *param)
122 {
123 rt_ubase_t level = rt_hw_interrupt_disable();
124
125 struct rt_serial_device *serial = (struct rt_serial_device *)param;
126
127 rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
128
129 rt_hw_interrupt_enable(level);
130 }
131
132 /*
133 * UART Initiation
134 */
rt_hw_uart_init(void)135 int rt_hw_uart_init(void)
136 {
137 struct rt_serial_device *serial;
138 struct device_uart *uart;
139 struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
140 #ifdef RT_USING_SMART
141 uart0_base = rt_ioremap(uart0_base, 4096);
142 #endif
143 // register device
144 serial = &serial0;
145 uart = &uart0;
146
147 serial->ops = &_uart_ops;
148 serial->config = config;
149 serial->config.baud_rate = UART_DEFAULT_BAUDRATE;
150 uart->hw_base = (rt_ubase_t)uart0_base;
151 uart->irqno = 0x0a;
152
153 rt_hw_serial_register(serial,
154 RT_CONSOLE_DEVICE_NAME,
155 RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
156 uart);
157 rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, serial, RT_CONSOLE_DEVICE_NAME);
158 rt_hw_interrupt_umask(uart->irqno);
159 return 0;
160 }
161
162 /* WEAK for SDK 0.5.6 */
uart_debug_init(int uart_channel)163 rt_weak void uart_debug_init(int uart_channel)
164 {
165 }
166