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  * 2017-05-30     Bernard      the first version
9  * 2018-03-15     flyingcys    add amebaz
10  */
11 #include <rtl8710b.h>
12 #include <serial_api.h>
13 #include "board.h"
14 #include "drv_uart.h"
15 
16 struct device_uart
17 {
18     serial_t serial;
19 
20     rt_uint32_t irqno;
21 };
22 
23 extern int LOGUART_SetBaud(u32 BaudRate);
24 
25 #ifdef BSP_USING_UART0
26 static struct rt_serial_device  serial0;
27 static struct device_uart       uart0;
28 #endif
29 
30 static rt_err_t  ameba_uart_configure    (struct rt_serial_device *serial, struct serial_configure *cfg);
31 static rt_err_t  ameba_uart_control      (struct rt_serial_device *serial, int cmd, void *arg);
32 static int       ameba_uart_putc         (struct rt_serial_device *serial, char c);
33 static int       ameba_uart_getc         (struct rt_serial_device *serial);
34 static rt_ssize_t ameba_uart_dma_transmit (struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction);
35 
36 static void ameba_uart_irq(uint32_t id, SerialIrq event);
37 
38 const struct rt_uart_ops _uart_ops =
39 {
40     ameba_uart_configure,
41     ameba_uart_control,
42     ameba_uart_putc,
43     ameba_uart_getc,
44     ameba_uart_dma_transmit
45 };
46 
47 /*
48  * UART interface
49  */
ameba_uart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)50 static rt_err_t ameba_uart_configure (struct rt_serial_device *serial, struct serial_configure *cfg)
51 {
52      struct device_uart * uart;
53 
54      RT_ASSERT(serial != RT_NULL);
55      serial->config = *cfg;
56 
57      uart = serial->parent.user_data;
58      RT_ASSERT(uart != RT_NULL);
59 
60      /* Set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
61      serial_format(&uart->serial, 8, ParityNone, 1);
62 
63      /* set baudrate */
64      serial_baud(&uart->serial, 115200);
65 
66      return (RT_EOK);
67 }
68 
ameba_uart_control(struct rt_serial_device * serial,int cmd,void * arg)69 static rt_err_t ameba_uart_control (struct rt_serial_device *serial, int cmd, void *arg)
70 {
71     struct device_uart * uart;
72 
73     uart = serial->parent.user_data;
74 
75     RT_ASSERT(uart != RT_NULL);
76 
77     switch (cmd)
78     {
79     case RT_DEVICE_CTRL_CLR_INT:
80         /* Disable the UART Interrupt */
81         serial_irq_set(&uart->serial, RxIrq, 0);
82         serial_irq_handler(&uart->serial, RT_NULL, 0);
83         break;
84 
85     case RT_DEVICE_CTRL_SET_INT:
86         /* install interrupt */
87         serial_irq_handler(&uart->serial, ameba_uart_irq, (uint32_t)serial);
88 
89         /* Enable the UART Interrupt */
90         serial_irq_set(&uart->serial, RxIrq, 1);
91         break;
92     }
93 
94     return (RT_EOK);
95 }
96 
ameba_uart_putc(struct rt_serial_device * serial,char c)97 static int ameba_uart_putc (struct rt_serial_device *serial, char c)
98 {
99     struct device_uart* uart;
100 
101     uart = serial->parent.user_data;
102 
103     /* FIFO status, contain valid data */
104     /* write data */
105     serial_putc(&uart->serial, c);
106 
107     return (1);
108 }
109 
ameba_uart_getc(struct rt_serial_device * serial)110 static int ameba_uart_getc (struct rt_serial_device *serial)
111 {
112     struct device_uart* uart = serial->parent.user_data;
113 
114     if(!serial_readable(&uart->serial))
115         return -1;
116 
117     /* Receive Data Available */
118     return serial_getc(&uart->serial);
119 }
120 
ameba_uart_dma_transmit(struct rt_serial_device * serial,rt_uint8_t * buf,rt_size_t size,int direction)121 static rt_ssize_t ameba_uart_dma_transmit (struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction)
122 {
123     return (0);
124 }
125 
ameba_uart_irq(uint32_t id,SerialIrq event)126 static void ameba_uart_irq(uint32_t id, SerialIrq event)
127 {
128     struct rt_serial_device *serial = (struct rt_serial_device *)id;
129     if(event == RxIrq)
130     {
131         rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
132     }
133     else if(event == TxIrq)
134     {
135     }
136 }
137 
138 static rt_err_t dbg_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
139 static rt_err_t dbg_control(struct rt_serial_device *serial, int cmd, void *arg);
140 static int dbg_putc(struct rt_serial_device *serial, char c);
141 static int dbg_getc(struct rt_serial_device *serial);
142 
143 static struct rt_serial_device ameba_dbg_serial;
144 const struct rt_uart_ops _ambed_dbg_ops =
145 {
146     dbg_configure,
147     dbg_control,
148     dbg_putc,
149     dbg_getc,
150     RT_NULL,
151 };
152 
dbg_configure(struct rt_serial_device * serial,struct serial_configure * cfg)153 static rt_err_t dbg_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
154 {
155     LOGUART_SetBaud(115200);
156     return RT_EOK;
157 }
158 
dbg_uart_irq_handler(void * data)159 void dbg_uart_irq_handler(void * data)
160 {
161     u32 IrqEn = DiagGetIsrEnReg();
162 
163     DiagSetIsrEnReg(0);
164 
165     rt_hw_serial_isr(&ameba_dbg_serial, RT_SERIAL_EVENT_RX_IND);
166 
167     DiagSetIsrEnReg(IrqEn);
168 }
169 
dbg_control(struct rt_serial_device * serial,int cmd,void * arg)170 static rt_err_t dbg_control(struct rt_serial_device *serial, int cmd, void *arg)
171 {
172     switch (cmd)
173     {
174     case RT_DEVICE_CTRL_CLR_INT:
175         /* Disable the UART Interrupt */
176         NVIC_DisableIRQ(UART_LOG_IRQ); /* this is rom_code_patch */
177         break;
178 
179     case RT_DEVICE_CTRL_SET_INT:
180         /* install interrupt */
181         DIAG_UartReInit((IRQ_FUN) dbg_uart_irq_handler);
182         /* Enable the UART Interrupt */
183         NVIC_SetPriority(UART_LOG_IRQ, 10); /* this is rom_code_patch */
184         break;
185     }
186 
187     return (RT_EOK);
188 }
189 
dbg_putc(struct rt_serial_device * serial,char c)190 static int dbg_putc(struct rt_serial_device *serial, char c)
191 {
192     DiagPutChar(c);
193 
194     return 1;
195 };
196 
dbg_getc(struct rt_serial_device * serial)197 static int dbg_getc(struct rt_serial_device *serial)
198 {
199     int c = -1;
200 
201     if(!UART_Readable(UART2_DEV))
202         return -1;
203 
204     c = DiagGetChar(_FALSE);
205 
206     return c;
207 }
208 
209 /*
210  * UART Initiation
211  */
rt_hw_uart_init(void)212 int rt_hw_uart_init(void)
213 {
214     struct rt_serial_device *serial;
215     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
216 
217 #ifdef BSP_USING_UART0
218     {
219         struct device_uart      *uart;
220 
221         serial  = &serial0;
222         uart    = &uart0;
223 
224         /* Init UART Hardware */
225         serial_init(&uart->serial, UART_TX, UART_RX);
226 
227         serial->ops              = &_uart_ops;
228         serial->config           = config;
229         serial->config.baud_rate = 115200;
230 
231         uart->irqno     = UART0_IRQ;
232 
233         rt_hw_serial_register(serial,
234                               "uart0",
235                               RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
236                               uart);
237     }
238 #endif
239 
240     {
241         serial  = &ameba_dbg_serial;
242 
243         serial->ops = &_ambed_dbg_ops;
244         serial->config = config;
245 
246         rt_hw_serial_register(serial,
247                               RT_CONSOLE_DEVICE_NAME,
248                               RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
249                               RT_NULL);
250     }
251     return 0;
252 }
253