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