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