1  /*
2  * Copyright (C) 2017-2024 Alibaba Group Holding Limited
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 /******************************************************************************
20  * @file     uart.c
21  * @brief    CSI Source File for uart Driver
22  * @version  V2.01
23  * @date     2020-04-09
24  ******************************************************************************/
25 
26 #include <drv/uart.h>
27 #include <drv/dma.h>
28 #include <drv/irq.h>
29 #include <drv/pin.h>
30 #include <drv/porting.h>
31 #include <soc.h>
32 #include <dw_uart_ll.h>
33 #include <drv/tick.h>
34 
35 #define UART_TIMEOUT    0x10000000U
36 #define UART_MAX_FIFO   0x10U
37 
38 extern uint16_t uart_tx_hs_num[];
39 extern uint16_t uart_rx_hs_num[];
40 extern const csi_pinmap_t uart_pinmap[];
41 
find_max_prime_num(uint32_t num)42 static uint8_t find_max_prime_num(uint32_t num)
43 {
44     uint8_t ret;
45 
46     if (!(num % 8U)) {
47         ret = 8U;
48     } else if (!(num % 4U)) {
49         ret = 4U;
50     } else {
51         ret = 1U;
52     }
53 
54     return ret;
55 }
56 
dw_uart_intr_recv_data(csi_uart_t * uart)57 static void dw_uart_intr_recv_data(csi_uart_t *uart)
58 {
59     dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
60     uint32_t rxfifo_num = 1;///<dw_uart_get_receive_fifo_waiting_data(uart_base);
61     uint32_t rxdata_num = (rxfifo_num > uart->rx_size) ? uart->rx_size : rxfifo_num;
62 
63     if ((uart->rx_data == NULL) || (uart->rx_size == 0U)) {
64         if (uart->callback) {
65             uart->callback(uart, UART_EVENT_RECEIVE_FIFO_READABLE, uart->arg);
66         } else {
67             do {
68                 dw_uart_getchar(uart_base);
69             } while (--rxfifo_num);
70         }
71     } else {
72         do {
73             *uart->rx_data = dw_uart_getchar(uart_base);
74             uart->rx_size--;
75             uart->rx_data++;
76         } while (--rxdata_num);
77 
78         if (uart->rx_size == 0U) {
79             uart->state.readable = 1U;
80 
81             if (uart->callback) {
82                 uart->callback(uart, UART_EVENT_RECEIVE_COMPLETE, uart->arg);
83             }
84         }
85     }
86 }
87 
uart_intr_send_data(csi_uart_t * uart)88 static void uart_intr_send_data(csi_uart_t *uart)
89 {
90     uint32_t i = 0U, trans_num = 0U;
91     dw_uart_regs_t *uart_base = (dw_uart_regs_t *)uart->dev.reg_base;
92 
93     if (uart->tx_size > UART_MAX_FIFO) {
94         trans_num = UART_MAX_FIFO;
95     } else {
96         trans_num = uart->tx_size;
97     }
98 
99     for (i = 0U; i < trans_num; i++) {
100         //dw_uart_putchar(uart_base, *uart->tx_data);
101         csi_uart_putc(uart, *uart->tx_data);
102         uart->tx_size--;
103         uart->tx_data++;
104     }
105 
106     if (uart->tx_size == 0U) {
107         dw_uart_disable_trans_irq(uart_base);
108         uart->state.writeable = 1U;
109 
110         if (uart->callback) {
111             uart->callback(uart, UART_EVENT_SEND_COMPLETE, uart->arg);
112         }
113     }
114 }
115 
uart_intr_line_error(csi_uart_t * uart)116 static void uart_intr_line_error(csi_uart_t *uart)
117 {
118     uint32_t uart_status;
119     dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
120 
121     uart->state.readable = 1U;
122     uart->state.writeable = 1U;
123     uart_status = dw_uart_get_line_status(uart_base);
124 
125     if (uart->callback) {
126         if (uart_status & DW_UART_LSR_OE_ERROR) {
127             uart->callback(uart, UART_EVENT_ERROR_OVERFLOW, uart->arg);
128         }
129 
130         if (uart_status & DW_UART_LSR_PE_ERROR) {
131             uart->callback(uart, UART_EVENT_ERROR_PARITY, uart->arg);
132         }
133 
134         if (uart_status & DW_UART_LSR_FE_ERROR) {
135             uart->callback(uart, UART_EVENT_ERROR_FRAMING, uart->arg);
136         }
137 
138         if (uart_status & DW_UART_LSR_BI_SET) {
139             uart->callback(uart, UART_ENENT_BREAK_INTR, uart->arg);
140         }
141     }
142 }
143 
dw_uart_irq_handler(void * arg)144 void dw_uart_irq_handler(void *arg)
145 {
146     csi_uart_t *uart = (csi_uart_t *)arg;
147     dw_uart_regs_t *uart_base = (dw_uart_regs_t *)uart->dev.reg_base;
148 
149     uint8_t intr_state;
150 
151     intr_state = (uint8_t)(uart_base->IIR & 0xfU);
152 
153     switch (intr_state) {
154     case DW_UART_IIR_IID_RECV_LINE_STATUS:  /* interrupt source: Overrun/parity/framing errors or break interrupt */
155         uart_intr_line_error(uart);
156         break;
157 
158     case DW_UART_IIR_IID_THR_EMPTY:         /* interrupt source:sendter holding register empty */
159         uart_intr_send_data(uart);
160         break;
161 
162     case DW_UART_IIR_IID_RECV_DATA_AVAIL:   /* interrupt source:receiver data available or receiver fifo trigger level reached */
163     case DW_UART_IIR_IID_CHARACTER_TIMEOUT:
164         dw_uart_intr_recv_data(uart);
165         break;
166 
167     default:
168         break;
169     }
170 }
171 
csi_uart_init(csi_uart_t * uart,uint32_t idx)172 csi_error_t csi_uart_init(csi_uart_t *uart, uint32_t idx)
173 {
174     CSI_PARAM_CHK(uart, CSI_ERROR);
175 
176     csi_error_t ret = CSI_OK;
177     dw_uart_regs_t *uart_base;
178 
179     ret = target_get(DEV_DW_UART_TAG, idx, &uart->dev);
180 
181     if (ret == CSI_OK) {
182         uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
183 
184         dw_uart_fifo_init(uart_base);
185 
186         uart->rx_size = 0U;
187         uart->tx_size = 0U;
188         uart->rx_data = NULL;
189         uart->tx_data = NULL;
190         uart->tx_dma  = NULL;
191         uart->rx_dma  = NULL;
192         dw_uart_disable_trans_irq(uart_base);
193         dw_uart_disable_recv_irq(uart_base);
194         dw_uart_disable_auto_flow_control(uart_base);
195     }
196 
197     return ret;
198 }
199 
csi_uart_uninit(csi_uart_t * uart)200 void csi_uart_uninit(csi_uart_t *uart)
201 {
202     CSI_PARAM_CHK_NORETVAL(uart);
203 
204     dw_uart_regs_t *uart_base;
205     uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
206 
207     uart->rx_size = 0U;
208     uart->tx_size = 0U;
209     uart->rx_data = NULL;
210     uart->tx_data = NULL;
211 
212     dw_uart_disable_trans_irq(uart_base);
213     dw_uart_disable_recv_irq(uart_base);
214     csi_irq_disable((uint32_t)(uart->dev.irq_num));
215     csi_irq_detach((uint32_t)(uart->dev.irq_num));
216 }
217 
csi_uart_baud(csi_uart_t * uart,uint32_t baud)218 ATTRIBUTE_DATA csi_error_t csi_uart_baud(csi_uart_t *uart, uint32_t baud)
219 {
220     CSI_PARAM_CHK(uart, CSI_ERROR);
221 
222     int32_t ret = 0;
223     csi_error_t csi_ret = CSI_OK;
224     dw_uart_regs_t *uart_base;
225     uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
226 
227     ret = dw_uart_config_baudrate(uart_base, baud, soc_get_uart_freq((uint32_t)(uart->dev.idx)));
228 
229     if (ret == 0) {
230         csi_ret = CSI_OK;
231     } else {
232         csi_ret = CSI_ERROR;
233     }
234 
235     return csi_ret;
236 }
237 
csi_uart_format(csi_uart_t * uart,csi_uart_data_bits_t data_bits,csi_uart_parity_t parity,csi_uart_stop_bits_t stop_bits)238 csi_error_t csi_uart_format(csi_uart_t *uart,  csi_uart_data_bits_t data_bits,
239                             csi_uart_parity_t parity, csi_uart_stop_bits_t stop_bits)
240 {
241     CSI_PARAM_CHK(uart, CSI_ERROR);
242 
243     int32_t ret = 0;
244     csi_error_t csi_ret = CSI_OK;
245     dw_uart_regs_t *uart_base;
246     uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
247 
248     switch (data_bits) {
249     case UART_DATA_BITS_5:
250         ret = dw_uart_config_data_bits(uart_base, 5U);
251         break;
252 
253     case UART_DATA_BITS_6:
254         ret = dw_uart_config_data_bits(uart_base, 6U);
255         break;
256 
257     case UART_DATA_BITS_7:
258         ret = dw_uart_config_data_bits(uart_base, 7U);
259         break;
260 
261     case UART_DATA_BITS_8:
262         ret = dw_uart_config_data_bits(uart_base, 8U);
263         break;
264 
265     default:
266         ret = -1;
267         break;
268     }
269 
270     if (ret == 0) {
271         switch (parity) {
272         case UART_PARITY_NONE:
273             ret = dw_uart_config_parity_none(uart_base);
274             break;
275 
276         case UART_PARITY_ODD:
277             ret = dw_uart_config_parity_odd(uart_base);
278             break;
279 
280         case UART_PARITY_EVEN:
281             ret = dw_uart_config_parity_even(uart_base);
282             break;
283 
284         default:
285             ret = -1;
286             break;
287         }
288 
289         if (ret == 0) {
290             switch (stop_bits) {
291             case UART_STOP_BITS_1:
292                 ret = dw_uart_config_stop_bits(uart_base, 1U);
293                 break;
294 
295             case UART_STOP_BITS_2:
296                 ret = dw_uart_config_stop_bits(uart_base, 2U);
297                 break;
298 
299             case UART_STOP_BITS_1_5:
300                 if (data_bits == UART_DATA_BITS_5) {
301                     ret = dw_uart_config_stop_bits(uart_base, 2U);
302                     break;
303                 }
304 
305             default:
306                 ret = -1;
307                 break;
308             }
309 
310             if (ret != 0) {
311                 csi_ret = CSI_ERROR;
312             }
313 
314         } else {
315             csi_ret = CSI_ERROR;
316         }
317 
318     } else {
319         csi_ret = CSI_ERROR;
320     }
321 
322     return csi_ret;
323 }
324 
csi_uart_flowctrl(csi_uart_t * uart,csi_uart_flowctrl_t flowctrl)325 csi_error_t csi_uart_flowctrl(csi_uart_t *uart,  csi_uart_flowctrl_t flowctrl)
326 {
327     CSI_PARAM_CHK(uart, CSI_ERROR);
328     csi_error_t csi_ret = CSI_OK;
329     dw_uart_regs_t *uart_base;
330     uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
331 
332     switch (flowctrl) {
333     case UART_FLOWCTRL_CTS:
334         dw_uart_wait_idle(uart_base);
335         dw_uart_enable_auto_flow_control(uart_base);
336         break;
337 
338     case UART_FLOWCTRL_RTS_CTS:
339         dw_uart_wait_idle(uart_base);
340         dw_uart_enable_auto_flow_control(uart_base);
341         break;
342 
343     case UART_FLOWCTRL_NONE:
344         dw_uart_wait_idle(uart_base);
345         break;
346 
347     case UART_FLOWCTRL_RTS:
348     default:
349         csi_ret = CSI_UNSUPPORTED;
350         break;
351     }
352 
353     return csi_ret;
354 }
355 
csi_uart_putc(csi_uart_t * uart,uint8_t ch)356 void csi_uart_putc(csi_uart_t *uart, uint8_t ch)
357 {
358     CSI_PARAM_CHK_NORETVAL(uart);
359 
360     volatile int i = 10;
361     uint32_t timeout = UART_TIMEOUT;
362     dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
363 
364     while (!dw_uart_putready(uart_base) && timeout--);
365 
366     if (timeout) {
367         //FIXME: fix print luanma on irq-mode sometimes. maybe hw bug
368         while (i--);
369         dw_uart_putchar(uart_base, ch);
370     }
371 }
372 
csi_uart_getc(csi_uart_t * uart)373 ATTRIBUTE_DATA uint8_t csi_uart_getc(csi_uart_t *uart)
374 {
375     CSI_PARAM_CHK(uart, 0U);
376 
377     dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
378 
379     while (!dw_uart_getready(uart_base));
380 
381     return dw_uart_getchar(uart_base);
382 }
383 
csi_uart_receive(csi_uart_t * uart,void * data,uint32_t size,uint32_t timeout)384 int32_t csi_uart_receive(csi_uart_t *uart, void *data, uint32_t size, uint32_t timeout)
385 {
386     CSI_PARAM_CHK(uart, CSI_ERROR);
387     CSI_PARAM_CHK(data, CSI_ERROR);
388 
389     uint8_t *temp_data = (uint8_t *)data;
390     int32_t recv_num = 0;
391     uint32_t recv_start, timeout_flag = 0U;
392     uint32_t intr_en_status;
393 
394     recv_start = csi_tick_get_ms();
395     dw_uart_regs_t *uart_base = (dw_uart_regs_t *)uart->dev.reg_base;
396     intr_en_status = dw_uart_get_intr_en_status(uart_base);
397     dw_uart_disable_recv_irq(uart_base);
398 
399     while (recv_num < (int32_t)size) {
400         while (!dw_uart_getready(uart_base)) {
401             if ((csi_tick_get_ms() - recv_start) >= timeout) {
402                 timeout_flag = 1U;
403                 break;
404             }
405         };
406 
407         if (timeout_flag == 0U) {
408             *temp_data = dw_uart_getchar(uart_base);
409             temp_data++;
410             recv_num++;
411             recv_start = csi_tick_get_ms();
412         } else {
413             break;
414         }
415     }
416 
417     dw_uart_set_intr_en_status(uart_base, intr_en_status);
418 
419     return recv_num;
420 }
421 
dw_uart_receive_intr(csi_uart_t * uart,void * data,uint32_t num)422 csi_error_t dw_uart_receive_intr(csi_uart_t *uart, void *data, uint32_t num)
423 {
424     dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
425     uart->rx_data = (uint8_t *)data;
426     uart->rx_size = num;
427 
428     dw_uart_enable_recv_irq(uart_base);
429 
430     return CSI_OK;
431 }
432 
csi_uart_receive_async(csi_uart_t * uart,void * data,uint32_t size)433 csi_error_t csi_uart_receive_async(csi_uart_t *uart, void *data, uint32_t size)
434 {
435     CSI_PARAM_CHK(uart, CSI_ERROR);
436     CSI_PARAM_CHK(data, CSI_ERROR);
437     CSI_PARAM_CHK(uart->callback, CSI_ERROR);
438     CSI_PARAM_CHK(uart->receive, CSI_ERROR);
439 
440     csi_error_t ret;
441 
442     ret = uart->receive(uart, data, size);
443 
444     if (ret == CSI_OK) {
445         uart->state.readable = 0U;
446     }
447 
448     return ret;
449 }
450 
csi_uart_send(csi_uart_t * uart,const void * data,uint32_t size,uint32_t timeout)451 int32_t csi_uart_send(csi_uart_t *uart, const void *data, uint32_t size, uint32_t timeout)
452 {
453     /* check data and uart */
454     CSI_PARAM_CHK(uart, CSI_ERROR);
455     CSI_PARAM_CHK(data, CSI_ERROR);
456     CSI_PARAM_CHK(size, CSI_ERROR);
457 
458     dw_uart_regs_t *uart_base;
459     uint8_t *ch = (uint8_t *)data;
460     int32_t trans_num = 0;
461     uint32_t send_start, timeout_flag = 0U;
462     uint32_t intr_en_status;
463 
464     uart_base = (dw_uart_regs_t *)uart->dev.reg_base; // 串口地址 0x1900d000
465     /* store the status of intr */
466     intr_en_status = dw_uart_get_intr_en_status(uart_base);
467     dw_uart_disable_trans_irq(uart_base);
468 
469     send_start = csi_tick_get_ms();
470 
471     while (trans_num < (int32_t)size) {
472         while (!dw_uart_putready(uart_base)) {
473             if ((csi_tick_get_ms() - send_start) >= timeout) {
474                 timeout_flag = 1U;
475                 break;
476             }
477         };
478 
479         if (timeout_flag == 0U) {
480             dw_uart_putchar(uart_base, *ch++);
481             /* update the timeout */
482             send_start = csi_tick_get_ms();
483             trans_num++;
484         } else {
485             break;
486         }
487     }
488 
489     dw_uart_set_intr_en_status(uart_base, intr_en_status);
490 
491     return trans_num;
492 }
493 
dw_uart_send_intr(csi_uart_t * uart,const void * data,uint32_t size)494 csi_error_t dw_uart_send_intr(csi_uart_t *uart, const void *data, uint32_t size)
495 {
496     dw_uart_regs_t *uart_base = (dw_uart_regs_t *)uart->dev.reg_base;
497 
498     uart->tx_data = (uint8_t *)data;
499     uart->tx_size = size;
500     dw_uart_enable_trans_irq(uart_base);
501 
502     return CSI_OK;
503 }
504 
csi_uart_send_async(csi_uart_t * uart,const void * data,uint32_t size)505 csi_error_t csi_uart_send_async(csi_uart_t *uart, const void *data, uint32_t size)
506 {
507     CSI_PARAM_CHK(uart, CSI_ERROR);
508     CSI_PARAM_CHK(data, CSI_ERROR);
509     CSI_PARAM_CHK(uart->callback, CSI_ERROR);
510     CSI_PARAM_CHK(uart->send, CSI_ERROR);
511 
512     csi_error_t ret;
513     ret = uart->send(uart, data, size);
514 
515     if (ret == CSI_OK) {
516         uart->state.writeable = 0U;
517     }
518 
519     return ret;
520 }
521 
csi_uart_attach_callback(csi_uart_t * uart,void * callback,void * arg)522 csi_error_t csi_uart_attach_callback(csi_uart_t *uart, void  *callback, void *arg)
523 {
524     CSI_PARAM_CHK(uart, CSI_ERROR);
525 
526     dw_uart_regs_t *uart_base;
527     uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
528 
529     uart->callback = callback;
530     uart->arg = arg;
531     uart->send = dw_uart_send_intr;
532     uart->receive = dw_uart_receive_intr;
533     csi_irq_attach((uint32_t)(uart->dev.irq_num), &dw_uart_irq_handler, &uart->dev);
534     csi_irq_enable((uint32_t)(uart->dev.irq_num));
535     dw_uart_enable_recv_irq(uart_base);
536 
537     return CSI_OK;
538 }
539 
csi_uart_detach_callback(csi_uart_t * uart)540 void csi_uart_detach_callback(csi_uart_t *uart)
541 {
542     CSI_PARAM_CHK_NORETVAL(uart);
543 
544     dw_uart_regs_t *uart_base;
545     uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
546 
547     uart->callback  = NULL;
548     uart->arg = NULL;
549     uart->send = NULL;
550     uart->receive = NULL;
551     dw_uart_disable_recv_irq(uart_base);
552     csi_irq_disable((uint32_t)(uart->dev.irq_num));
553     csi_irq_detach((uint32_t)(uart->dev.irq_num));
554 }
555 
csi_uart_get_state(csi_uart_t * uart,csi_state_t * state)556 csi_error_t csi_uart_get_state(csi_uart_t *uart, csi_state_t *state)
557 {
558     CSI_PARAM_CHK(uart, CSI_ERROR);
559     CSI_PARAM_CHK(state, CSI_ERROR);
560 
561     *state = uart->state;
562 
563     return CSI_OK;
564 }
565 
dw_uart_dma_event_cb(csi_dma_ch_t * dma,csi_dma_event_t event,void * arg)566 static void dw_uart_dma_event_cb(csi_dma_ch_t *dma, csi_dma_event_t event, void *arg)
567 {
568     csi_uart_t *uart = (csi_uart_t *)dma->parent;
569     dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
570 
571     if (event == DMA_EVENT_TRANSFER_ERROR) {/* DMA transfer ERROR */
572         if ((uart->tx_dma != NULL) && (uart->tx_dma->ch_id == dma->ch_id)) {
573             csi_dma_ch_stop(dma);
574             dw_uart_fifo_init(uart_base);
575 
576             uart->state.writeable = 1U;
577 
578             if (uart->callback) {
579                 uart->callback(uart, UART_EVENT_ERROR_OVERFLOW, uart->arg);
580             }
581         } else {
582             csi_dma_ch_stop(dma);
583             dw_uart_fifo_init(uart_base);
584             /* enable received data available */
585             dw_uart_enable_recv_irq(uart_base);
586 
587             uart->state.readable = 1U;
588 
589             if (uart->callback) {
590                 uart->callback(uart, UART_EVENT_ERROR_FRAMING, uart->arg);
591             }
592         }
593     } else if (event == DMA_EVENT_TRANSFER_DONE) {/* DMA transfer complete */
594         if ((uart->tx_dma != NULL) && (uart->tx_dma->ch_id == dma->ch_id)) {
595 
596             csi_dma_ch_stop(dma);
597             dw_uart_fifo_init(uart_base);
598 
599             uart->state.writeable = 1U;
600 
601             if (uart->callback) {
602                 uart->callback(uart, UART_EVENT_SEND_COMPLETE, uart->arg);
603             }
604         } else {
605             csi_dma_ch_stop(dma);
606             dw_uart_fifo_init(uart_base);
607             /* enable received data available */
608             dw_uart_enable_recv_irq(uart_base);
609 
610             uart->state.readable = 1U;
611 
612             if (uart->callback) {
613                 uart->callback(uart, UART_EVENT_RECEIVE_COMPLETE, uart->arg);
614             }
615         }
616     }
617 }
618 
dw_uart_send_dma(csi_uart_t * uart,const void * data,uint32_t num)619 csi_error_t dw_uart_send_dma(csi_uart_t *uart, const void *data, uint32_t num)
620 {
621     csi_dma_ch_config_t config;
622     memset(&config, 0, sizeof(csi_dma_ch_config_t));
623     uint32_t fcr_reg = UART_FIFO_INIT_CONFIG;
624     dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
625     csi_dma_ch_t *dma_ch = (csi_dma_ch_t *)uart->tx_dma;
626 
627     uart->tx_data = (uint8_t *)data;
628     uart->tx_size = num;
629     dw_uart_disable_recv_irq(uart_base);
630     dw_uart_disable_trans_irq(uart_base);
631     config.src_inc = DMA_ADDR_INC;
632     config.dst_inc = DMA_ADDR_CONSTANT;
633     config.src_tw = DMA_DATA_WIDTH_8_BITS;
634     config.dst_tw = DMA_DATA_WIDTH_8_BITS;
635 
636     /* config for wj_dma */
637     config.group_len = find_max_prime_num(num);
638     config.trans_dir = DMA_MEM2PERH;
639 
640     /* config for etb */
641     config.handshake = uart_tx_hs_num[uart->dev.idx];
642 
643     csi_dma_ch_config(dma_ch, &config);
644 
645     fcr_reg &= ~(DW_UART_FCR_TET_Msk);
646 
647     if (config.group_len >= (UART_MAX_FIFO / 2U)) {
648         fcr_reg |= DW_UART_FCR_TET_FIFO_1_2_FULL;
649     } else if (config.group_len >= (UART_MAX_FIFO / 4U)) {
650         fcr_reg |= DW_UART_FCR_TET_FIFO_1_4_FULL;
651     } else if (config.group_len >= (UART_MAX_FIFO / 8U)) {
652         fcr_reg |= DW_UART_FCR_TET_FIFO_2_CHAR;
653     } else {
654         fcr_reg |= DW_UART_FCR_TET_FIFO_EMTPY;
655     }
656 
657     soc_dcache_clean_invalid_range((unsigned long)uart->tx_data, uart->tx_size);
658     dw_uart_set_fcr_reg(uart_base, fcr_reg);
659     csi_dma_ch_start(uart->tx_dma, (void *)uart->tx_data, (uint8_t *) & (uart_base->THR), uart->tx_size);
660 
661     return CSI_OK;
662 }
663 
dw_uart_receive_dma(csi_uart_t * uart,void * data,uint32_t num)664 csi_error_t dw_uart_receive_dma(csi_uart_t *uart, void *data, uint32_t num)
665 {
666     csi_dma_ch_config_t config;
667     memset(&config, 0, sizeof(csi_dma_ch_config_t));
668     csi_error_t ret = CSI_OK;
669     uint32_t fcr_reg = UART_FIFO_INIT_CONFIG;
670     dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE(uart);
671     csi_dma_ch_t *dma = (csi_dma_ch_t *)uart->rx_dma;
672 
673     dw_uart_disable_trans_irq(uart_base);
674     dw_uart_disable_recv_irq(uart_base);
675     uart->rx_data = (uint8_t *)data;
676     uart->rx_size = num;
677     config.src_inc = DMA_ADDR_CONSTANT;
678     config.dst_inc = DMA_ADDR_INC;
679     config.src_tw = DMA_DATA_WIDTH_8_BITS;
680     config.dst_tw = DMA_DATA_WIDTH_8_BITS;
681     config.group_len = find_max_prime_num(num);
682     config.trans_dir = DMA_PERH2MEM;
683     config.handshake = uart_rx_hs_num[uart->dev.idx];
684 
685     ret = csi_dma_ch_config(dma, &config);
686 
687     if (ret == CSI_OK) {
688 
689         fcr_reg &= ~(DW_UART_FCR_RT_Msk);
690 
691         if (config.group_len >= (UART_MAX_FIFO / 2U)) {
692             fcr_reg |= DW_UART_FCR_RT_FIFO_1_2_FULL;
693         } else if (config.group_len >= (UART_MAX_FIFO / 4U)) {
694             fcr_reg |= DW_UART_FCR_RT_FIFO_1_4_FULL;
695         } else {
696             fcr_reg |= DW_UART_FCR_RT_FIFO_1_CHAR;
697         }
698 
699         soc_dcache_clean_invalid_range((unsigned long)uart->rx_data, uart->rx_size);
700         dw_uart_set_fcr_reg(uart_base, fcr_reg | DW_UART_FCR_RFIFOR_RESET);
701         csi_dma_ch_start(uart->rx_dma, (uint8_t *) & (uart_base->RBR), (void *)uart->rx_data, uart->rx_size);
702     }
703 
704     return ret;
705 }
706 
csi_uart_link_dma(csi_uart_t * uart,csi_dma_ch_t * tx_dma,csi_dma_ch_t * rx_dma)707 csi_error_t csi_uart_link_dma(csi_uart_t *uart, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma)
708 {
709     CSI_PARAM_CHK(uart, CSI_ERROR);
710     CSI_PARAM_CHK(uart->callback, CSI_ERROR);
711     csi_error_t ret = CSI_OK;
712 
713     if (tx_dma != NULL) {
714         tx_dma->parent = uart;
715         ret = csi_dma_ch_alloc(tx_dma, -1, -1);
716 
717         if (ret == CSI_OK) {
718             csi_dma_ch_attach_callback(tx_dma, dw_uart_dma_event_cb, NULL);
719             uart->tx_dma = tx_dma;
720             uart->send = dw_uart_send_dma;
721         } else {
722             tx_dma->parent = NULL;
723         }
724     } else {
725         if (uart->tx_dma) {
726             csi_dma_ch_detach_callback(uart->tx_dma);
727             csi_dma_ch_free(uart->tx_dma);
728             uart->tx_dma = NULL;
729         }
730 
731         uart->send = dw_uart_send_intr;
732     }
733 
734     if (ret != CSI_ERROR) {
735         if (rx_dma != NULL) {
736             rx_dma->parent = uart;
737             ret = csi_dma_ch_alloc(rx_dma, -1, -1);
738 
739             if (ret == CSI_OK) {
740                 csi_dma_ch_attach_callback(rx_dma, dw_uart_dma_event_cb, NULL);
741                 uart->rx_dma = rx_dma;
742                 uart->receive = dw_uart_receive_dma;
743             } else {
744                 rx_dma->parent = NULL;
745             }
746         } else {
747             if (uart->rx_dma) {
748                 csi_dma_ch_detach_callback(uart->rx_dma);
749                 csi_dma_ch_free(uart->rx_dma);
750                 uart->rx_dma = NULL;
751             }
752 
753             uart->receive = dw_uart_receive_intr;
754         }
755     }
756     return ret;
757 }
758 
759 #ifdef CONFIG_PM
dw_uart_pm_action(csi_dev_t * dev,csi_pm_dev_action_t action)760 csi_error_t dw_uart_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action)
761 {
762     CSI_PARAM_CHK(dev, CSI_ERROR);
763 
764     csi_error_t ret = CSI_OK;
765     csi_pm_dev_t *pm_dev = &dev->pm_dev;
766     dw_uart_regs_t *uart_base = (dw_uart_regs_t *)dev->reg_base;
767 
768     switch (action) {
769     case PM_DEV_SUSPEND:
770         dw_uart_fifo_disable(uart_base);
771         dw_uart_fifo_enable(uart_base);
772         dw_uart_wait_idle(uart_base);
773         uart_base->LCR |= DW_UART_LCR_DLAB_EN;
774         csi_pm_dev_save_regs(pm_dev->reten_mem, (uint32_t *)dev->reg_base, 2U);
775         uart_base->LCR &= (~DW_UART_LCR_DLAB_EN);
776         csi_pm_dev_save_regs(pm_dev->reten_mem + 2, (uint32_t *)(dev->reg_base + 4U), 1U);
777         csi_pm_dev_save_regs(pm_dev->reten_mem + 2 + 1, (uint32_t *)(dev->reg_base + 12U), 2U);
778         break;
779 
780     case PM_DEV_RESUME:
781         dw_uart_fifo_disable(uart_base);
782         dw_uart_fifo_enable(uart_base);
783         dw_uart_wait_idle(uart_base);
784         uart_base->LCR |= DW_UART_LCR_DLAB_EN;
785         csi_pm_dev_restore_regs(pm_dev->reten_mem, (uint32_t *)dev->reg_base, 2U);
786         uart_base->LCR &= (~DW_UART_LCR_DLAB_EN);
787         csi_pm_dev_restore_regs(pm_dev->reten_mem + 2, (uint32_t *)(dev->reg_base + 4U), 1U);
788         csi_pm_dev_restore_regs(pm_dev->reten_mem + 2 + 1, (uint32_t *)(dev->reg_base + 12U), 2U);
789         break;
790 
791     default:
792         ret = CSI_ERROR;
793         break;
794     }
795 
796     return ret;
797 }
798 
csi_uart_enable_pm(csi_uart_t * uart)799 csi_error_t csi_uart_enable_pm(csi_uart_t *uart)
800 {
801     return csi_pm_dev_register(&uart->dev, dw_uart_pm_action, 20U, 0U);
802 }
803 
csi_uart_disable_pm(csi_uart_t * uart)804 void csi_uart_disable_pm(csi_uart_t *uart)
805 {
806     csi_pm_dev_unregister(&uart->dev);
807 }
808 #endif
809 
810