1 /*
2  * Copyright (C) 2020-2021 Alibaba Group Holding Limited
3  */
4 
5 #define BES_HAL_DEBUG 0
6 #include <aos/kernel.h>
7 #include <aos/tty_core.h>
8 #include <ulog/ulog.h>
9 #include <hal_uart.h>
10 #include <hal_iomux.h>
11 #include <hal_trace.h>
12 #include <plat_types.h>
13 
14 #define UART_DMA_RING_BUFFER_SIZE 256 /* mast be 2^n */
15 
16 static __SRAMBSS unsigned char _hal_uart0_buf[UART_DMA_RING_BUFFER_SIZE];
17 static __SRAMBSS unsigned char _hal_uart1_buf[UART_DMA_RING_BUFFER_SIZE];
18 static __SRAMBSS unsigned char _hal_uart2_buf[UART_DMA_RING_BUFFER_SIZE];
19 
20 typedef struct {
21     aos_tty_t tty;
22     unsigned char *rx_buf;
23     unsigned char tx_buf[UART_DMA_RING_BUFFER_SIZE];
24     void (*rx_handler)(uint32_t, int, union HAL_UART_IRQ_T);
25     void (*tx_handler)(uint32_t, int);
26     bool rx_busy;
27     bool tx_busy;
28 } tty_uart_t;
29 
hal_set_uart_iomux(uint32_t uart_id)30 static void hal_set_uart_iomux(uint32_t uart_id)
31 {
32     if (uart_id == HAL_UART_ID_0)
33         hal_iomux_set_uart0();
34     else if (uart_id == HAL_UART_ID_1)
35         hal_iomux_set_uart1();
36     else
37         hal_iomux_set_uart2();
38 }
39 
tty_uart_unregister(aos_tty_t * tty)40 static void tty_uart_unregister(aos_tty_t *tty)
41 {
42 }
43 
tty_uart_startup(aos_tty_t * tty)44 static aos_status_t tty_uart_startup(aos_tty_t *tty)
45 {
46     tty_uart_t *uart = aos_container_of(tty, tty_uart_t, tty);
47     uint32_t id = tty->dev.id;
48     struct HAL_UART_CFG_T cfg;
49 
50     switch (tty->termios.c_cflag & CBAUD) {
51     case B50:
52         cfg.baud = 50;
53         break;
54     case B75:
55         cfg.baud = 75;
56         break;
57     case B110:
58         cfg.baud = 110;
59         break;
60     case B134:
61         cfg.baud = 134;
62         break;
63     case B150:
64         cfg.baud = 150;
65         break;
66     case B200:
67         cfg.baud = 200;
68         break;
69     case B300:
70         cfg.baud = 300;
71         break;
72     case B600:
73         cfg.baud = 600;
74         break;
75     case B1200:
76         cfg.baud = 1200;
77         break;
78     case B1800:
79         cfg.baud = 1800;
80         break;
81     case B2400:
82         cfg.baud = 2400;
83         break;
84     case B4800:
85         cfg.baud = 4800;
86         break;
87     case B9600:
88         cfg.baud = 9600;
89         break;
90     case B19200:
91         cfg.baud = 19200;
92         break;
93     case B38400:
94         cfg.baud = 38400;
95         break;
96     case B57600:
97         cfg.baud = 57600;
98         break;
99     case B115200:
100         cfg.baud = 115200;
101         break;
102     case B230400:
103         cfg.baud = 230400;
104         break;
105     case B460800:
106         cfg.baud = 460800;
107         break;
108     case B500000:
109         cfg.baud = 500000;
110         break;
111     case B576000:
112         cfg.baud = 576000;
113         break;
114     case B921600:
115         cfg.baud = 921600;
116         break;
117     case B1000000:
118         cfg.baud = 1000000;
119         break;
120     case B1152000:
121         cfg.baud = 1152000;
122         break;
123     case B1500000:
124         cfg.baud = 1500000;
125         break;
126     case B2000000:
127         cfg.baud = 2000000;
128         break;
129     case B2500000:
130         cfg.baud = 2500000;
131         break;
132     case B3000000:
133         cfg.baud = 3000000;
134         break;
135     case B3500000:
136         cfg.baud = 3500000;
137         break;
138     case B4000000:
139         cfg.baud = 4000000;
140         break;
141     default:
142         cfg.baud = 9600;
143         break;
144     }
145 
146     if (tty->termios.c_cflag & PARENB) {
147         if (tty->termios.c_cflag & PARODD)
148             cfg.parity = HAL_UART_PARITY_ODD;
149         else
150             cfg.parity = HAL_UART_PARITY_EVEN;
151     } else {
152         cfg.parity = HAL_UART_PARITY_NONE;
153     }
154 
155     if (tty->termios.c_cflag & CSTOPB)
156         cfg.stop = HAL_UART_STOP_BITS_2;
157     else
158         cfg.stop = HAL_UART_STOP_BITS_1;
159 
160     switch (tty->termios.c_cflag & CSIZE) {
161     case CS5:
162         cfg.data = HAL_UART_DATA_BITS_5;
163         break;
164     case CS6:
165         cfg.data = HAL_UART_DATA_BITS_6;
166         break;
167     case CS7:
168         cfg.data = HAL_UART_DATA_BITS_7;
169         break;
170     case CS8:
171         cfg.data = HAL_UART_DATA_BITS_8;
172         break;
173     default:
174         cfg.data = HAL_UART_DATA_BITS_8;
175         break;
176     }
177 
178     switch (tty->termios.c_cflag & CRTSCTS) {
179     case RTSFLOW:
180         cfg.flow = HAL_UART_FLOW_CONTROL_RTS;
181         break;
182     case CTSFLOW:
183         cfg.flow = HAL_UART_FLOW_CONTROL_CTS;
184         break;
185     case CRTSCTS:
186         cfg.flow = HAL_UART_FLOW_CONTROL_RTSCTS;
187         break;
188     default:
189         cfg.flow = HAL_UART_FLOW_CONTROL_NONE;
190         break;
191     }
192 
193     cfg.tx_level = HAL_UART_FIFO_LEVEL_1_2;
194     cfg.rx_level = HAL_UART_FIFO_LEVEL_1_2;
195     cfg.dma_rx = true;
196     cfg.dma_tx = true;
197     cfg.dma_rx_stop_on_err = false;
198 
199     if (hal_uart_open(id, &cfg))
200         return -EIO;
201 
202     hal_set_uart_iomux(id);
203     hal_uart_irq_set_dma_handler(id, uart->rx_handler, uart->tx_handler, NULL);
204 
205     return 0;
206 }
207 
tty_uart_shutdown(aos_tty_t * tty)208 static void tty_uart_shutdown(aos_tty_t *tty)
209 {
210     tty_uart_t *uart = aos_container_of(tty, tty_uart_t, tty);
211     uint32_t id = tty->dev.id;
212 
213     hal_uart_close(id);
214 }
215 
tty_uart_set_attr(aos_tty_t * tty)216 static aos_status_t tty_uart_set_attr(aos_tty_t *tty)
217 {
218     tty_uart_shutdown(tty);
219 
220     return tty_uart_startup(tty);
221 }
222 
start_rx_dma(tty_uart_t * uart)223 static void start_rx_dma(tty_uart_t *uart)
224 {
225     uint32_t id = uart->tty.dev.id;
226     struct HAL_DMA_DESC_T desc;
227     uint32_t desc_count = 1;
228     union HAL_UART_IRQ_T mask;
229 
230     mask.reg = 0;
231     mask.BE = 0;
232     mask.FE = 0;
233     mask.OE = 0;
234     mask.PE = 0;
235     mask.RT = 1;
236     hal_uart_dma_recv_mask(id, uart->rx_buf, UART_DMA_RING_BUFFER_SIZE, &desc, &desc_count, &mask);
237 }
238 
tty_uart_enable_rx(aos_tty_t * tty)239 static void tty_uart_enable_rx(aos_tty_t *tty)
240 {
241     tty_uart_t *uart = aos_container_of(tty, tty_uart_t, tty);
242     aos_irqsave_t flags;
243 
244     flags = aos_spin_lock_irqsave(&tty->lock);
245     uart->rx_busy = true;
246     start_rx_dma(uart);
247     aos_spin_unlock_irqrestore(&tty->lock, flags);
248 }
249 
tty_uart_disable_rx(aos_tty_t * tty)250 static void tty_uart_disable_rx(aos_tty_t *tty)
251 {
252     tty_uart_t *uart = aos_container_of(tty, tty_uart_t, tty);
253     uint32_t id = tty->dev.id;
254     aos_irqsave_t flags;
255 
256     flags = aos_spin_lock_irqsave(&tty->lock);
257     uart->rx_busy = false;
258     hal_uart_stop_dma_recv(id);
259     aos_spin_unlock_irqrestore(&tty->lock, flags);
260 }
261 
tty_uart_start_tx(aos_tty_t * tty)262 static void tty_uart_start_tx(aos_tty_t *tty)
263 {
264     tty_uart_t *uart = aos_container_of(tty, tty_uart_t, tty);
265     uint32_t id = tty->dev.id;
266     size_t count;
267 
268     if (uart->tx_busy)
269         return;
270 
271     uart->tx_busy = true;
272     count = aos_tty_tx_buffer_consume(tty, uart->tx_buf, sizeof(uart->tx_buf));
273     hal_uart_dma_send_sync_cache(id, uart->tx_buf, count, NULL, NULL);
274 }
275 
tty_uart_stop_tx(aos_tty_t * tty)276 static void tty_uart_stop_tx(aos_tty_t *tty)
277 {
278     tty_uart_t *uart = aos_container_of(tty, tty_uart_t, tty);
279     uint32_t id = tty->dev.id;
280     aos_irqsave_t flags;
281 
282     flags = aos_spin_lock_irqsave(&tty->lock);
283 
284     if (uart->tx_busy) {
285         uart->tx_busy = false;
286         hal_uart_stop_dma_send(id);
287     }
288 
289     aos_spin_unlock_irqrestore(&tty->lock, flags);
290 }
291 
292 static const aos_tty_ops_t tty_uart_ops = {
293     .unregister = tty_uart_unregister,
294     .startup    = tty_uart_startup,
295     .shutdown   = tty_uart_shutdown,
296     .set_attr   = tty_uart_set_attr,
297     .enable_rx  = tty_uart_enable_rx,
298     .disable_rx = tty_uart_disable_rx,
299     .start_tx   = tty_uart_start_tx,
300     .stop_tx    = tty_uart_stop_tx,
301 };
302 
303 static tty_uart_t tty_uarts[3];
304 
tty_uart_rx_handler(tty_uart_t * uart,size_t rx_count)305 static void tty_uart_rx_handler(tty_uart_t *uart, size_t rx_count)
306 {
307     aos_tty_t *tty = &uart->tty;
308     uint32_t id = tty->dev.id;
309     aos_irqsave_t flags;
310 
311     flags = aos_spin_lock_irqsave(&tty->lock);
312 
313     if (!uart->rx_busy) {
314         aos_spin_unlock_irqrestore(&tty->lock, flags);
315         return;
316     }
317 
318     (void)aos_tty_rx_buffer_produce(tty, uart->rx_buf, rx_count);
319     start_rx_dma(uart);
320     aos_spin_unlock_irqrestore(&tty->lock, flags);
321 }
322 
tty_uart1_rx_handler(uint32_t xfer_size,int dma_error,union HAL_UART_IRQ_T status)323 static void tty_uart1_rx_handler(uint32_t xfer_size, int dma_error, union HAL_UART_IRQ_T status)
324 {
325     tty_uart_rx_handler(&tty_uarts[1], xfer_size);
326 }
327 
tty_uart2_rx_handler(uint32_t xfer_size,int dma_error,union HAL_UART_IRQ_T status)328 static void tty_uart2_rx_handler(uint32_t xfer_size, int dma_error, union HAL_UART_IRQ_T status)
329 {
330     tty_uart_rx_handler(&tty_uarts[2], xfer_size);
331 }
332 
tty_uart_tx_handler(tty_uart_t * uart)333 static void tty_uart_tx_handler(tty_uart_t *uart)
334 {
335     aos_tty_t *tty = &uart->tty;
336     uint32_t id = tty->dev.id;
337     size_t count;
338     aos_irqsave_t flags;
339 
340     flags = aos_spin_lock_irqsave(&tty->lock);
341 
342     if (!uart->tx_busy) {
343         aos_spin_unlock_irqrestore(&tty->lock, flags);
344         return;
345     }
346 
347     count = aos_tty_tx_buffer_consume(tty, uart->tx_buf, sizeof(uart->tx_buf));
348     if (count == 0) {
349         uart->tx_busy = false;
350         aos_spin_unlock_irqrestore(&tty->lock, flags);
351         return;
352     }
353 
354     hal_uart_dma_send_sync_cache(id, uart->tx_buf, count, NULL, NULL);
355     aos_spin_unlock_irqrestore(&tty->lock, flags);
356 }
357 
tty_uart1_tx_handler(uint32_t xfer_size,int dma_error)358 static void tty_uart1_tx_handler(uint32_t xfer_size, int dma_error)
359 {
360     tty_uart_tx_handler(&tty_uarts[1]);
361 }
362 
tty_uart2_tx_handler(uint32_t xfer_size,int dma_error)363 static void tty_uart2_tx_handler(uint32_t xfer_size, int dma_error)
364 {
365     tty_uart_tx_handler(&tty_uarts[2]);
366 }
367 
tty_uart_init(void)368 static int tty_uart_init(void)
369 {
370     int ret;
371 
372     tty_uarts[1].tty.dev.id = 1;
373     tty_uarts[1].tty.ops = &tty_uart_ops;
374     tty_uarts[1].tty.flags = 0;
375     tty_uarts[1].rx_buf = _hal_uart1_buf;
376     tty_uarts[1].rx_handler = tty_uart1_rx_handler;
377     tty_uarts[1].tx_handler = tty_uart1_tx_handler;
378     tty_uarts[1].rx_busy = false;
379     tty_uarts[1].tx_busy = false;
380     ret = (int)aos_tty_register(&tty_uarts[1].tty);
381     if (ret)
382         return ret;
383 
384     tty_uarts[2].tty.dev.id = 2;
385     tty_uarts[2].tty.ops = &tty_uart_ops;
386     tty_uarts[2].tty.flags = 0;
387     tty_uarts[2].rx_buf = _hal_uart2_buf;
388     tty_uarts[2].rx_handler = tty_uart2_rx_handler;
389     tty_uarts[2].tx_handler = tty_uart2_tx_handler;
390     tty_uarts[2].rx_busy = false;
391     tty_uarts[2].tx_busy = false;
392     ret = (int)aos_tty_register(&tty_uarts[2].tty);
393     if (ret) {
394         (void)aos_tty_unregister(1);
395         return ret;
396     }
397 
398     return 0;
399 }
400 
401 LEVEL1_DRIVER_ENTRY(tty_uart_init)
402