1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "uart.h"
17 #include "uart_drv.h"
18 #include "hi_isr.h"
19 #include "serial_dw.h"
20 #include "dma.h"
21
22 #define hi_uart_buf_lock(x) hi_int_lock()
23 #define hi_uart_buf_unlock(x, val) hi_int_restore(val)
24 hi_bool g_uart_buf_memcpy_failed = HI_FALSE;
25
uart_circ_buf_empty(const uart_circ_buf * transfer)26 hi_u32 uart_circ_buf_empty(const uart_circ_buf *transfer)
27 {
28 if (transfer->flags & BUF_CIRCLED) {
29 return 0;
30 }
31
32 if (transfer->wp == transfer->rp) {
33 return 1;
34 } else {
35 return 0;
36 }
37 }
38
uart_init_circ_buf(uart_driver_data_t * udd,unsigned int rx_buf_size,unsigned int tx_buf_size)39 hi_u32 uart_init_circ_buf(uart_driver_data_t *udd, unsigned int rx_buf_size, unsigned int tx_buf_size)
40 {
41 if ((!rx_buf_size) || (!tx_buf_size)) {
42 return HI_ERR_UART_INVALID_PARAMETER;
43 }
44
45 udd->rx_transfer = (uart_circ_buf *) hi_malloc(HI_MOD_ID_UART, sizeof(uart_circ_buf));
46 if (udd->rx_transfer == NULL) {
47 goto end;
48 }
49
50 memset_s((hi_void *) udd->rx_transfer, sizeof(uart_circ_buf), 0, sizeof(uart_circ_buf));
51 udd->rx_transfer->data = (char *) hi_malloc(HI_MOD_ID_UART, rx_buf_size);
52 if (udd->rx_transfer->data == NULL) {
53 goto free_rx_transfer;
54 }
55
56 udd->rx_transfer->size = rx_buf_size;
57 udd->tx_transfer = (uart_circ_buf *) hi_malloc(HI_MOD_ID_UART, sizeof(uart_circ_buf));
58 if (udd->tx_transfer == NULL) {
59 goto free_rx_circ_buf;
60 }
61
62 memset_s((hi_void *) udd->tx_transfer, sizeof(uart_circ_buf), 0, sizeof(uart_circ_buf));
63 udd->tx_transfer->data = (char *) hi_malloc(HI_MOD_ID_UART, tx_buf_size);
64 if (udd->tx_transfer->data == NULL) {
65 goto free_tx_circ_buf;
66 }
67
68 udd->tx_transfer->size = tx_buf_size;
69 return HI_ERR_SUCCESS;
70
71 free_tx_circ_buf:
72 hi_free(HI_MOD_ID_UART, udd->tx_transfer);
73 udd->tx_transfer = HI_NULL;
74
75 free_rx_circ_buf:
76 hi_free(HI_MOD_ID_UART, udd->rx_transfer->data);
77 udd->rx_transfer->data = HI_NULL;
78 free_rx_transfer:
79 hi_free(HI_MOD_ID_UART, udd->rx_transfer->data);
80 udd->rx_transfer = HI_NULL;
81 end:
82 return HI_ERR_FAILURE;
83 }
84
uart_deinit_circ_buf(uart_driver_data_t * udd)85 hi_void uart_deinit_circ_buf(uart_driver_data_t *udd)
86 {
87 if (udd->rx_transfer != HI_NULL) {
88 if (udd->rx_transfer->data != HI_NULL) {
89 hi_free(HI_MOD_ID_UART, udd->rx_transfer->data);
90 udd->rx_transfer->data = HI_NULL;
91 }
92
93 hi_free(HI_MOD_ID_UART, udd->rx_transfer);
94 udd->rx_transfer = HI_NULL;
95 }
96
97 if (udd->tx_transfer != HI_NULL) {
98 if (udd->tx_transfer->data != HI_NULL) {
99 hi_free(HI_MOD_ID_UART, udd->tx_transfer->data);
100 udd->tx_transfer->data = HI_NULL;
101 }
102 hi_free(HI_MOD_ID_UART, udd->tx_transfer);
103 udd->tx_transfer = HI_NULL;
104 }
105 }
106
uart_read_circ_buf(uart_circ_buf * transfer,hi_char * buf,hi_u32 count)107 hi_s32 uart_read_circ_buf(uart_circ_buf *transfer, hi_char *buf, hi_u32 count)
108 {
109 uintptr_t data;
110
111 if (transfer == NULL) {
112 return (hi_s32) HI_ERR_FAILURE;
113 }
114
115 hi_u32 last_int_val = hi_uart_buf_lock(transfer);
116 hi_u32 wp = transfer->wp;
117 hi_u32 rp = transfer->rp;
118 hi_u32 flags = transfer->flags;
119 hi_uart_buf_unlock(transfer, last_int_val);
120 data = (uintptr_t) transfer->data;
121 hi_u32 buf_size = transfer->size;
122 if (!(flags & BUF_CIRCLED)) {
123 if (count >= (wp - rp)) {
124 count = wp - rp;
125 }
126
127 if (memcpy_s(buf, count, (hi_void *) (uintptr_t)(data + rp), count) != EOK) {
128 g_uart_buf_memcpy_failed = HI_TRUE;
129 }
130 transfer->rp += count;
131 return (hi_s32) count;
132 }
133 if (count < (buf_size - rp)) {
134 if (memcpy_s(buf, count, (hi_void *) (uintptr_t)(data + rp), count) != EOK) {
135 g_uart_buf_memcpy_failed = HI_TRUE;
136 }
137 transfer->rp += count;
138 return (hi_s32) count;
139 }
140 hi_u32 copy_size = buf_size - rp;
141 hi_u32 left_size = count - copy_size;
142 if (memcpy_s(buf, copy_size, (hi_void *) (uintptr_t)(data + rp), copy_size) != EOK) {
143 g_uart_buf_memcpy_failed = HI_TRUE;
144 }
145 rp = 0;
146 if (left_size > wp) {
147 left_size = wp;
148 }
149
150 if (memcpy_s((hi_void*)(buf + copy_size), left_size, (hi_void *)(uintptr_t)(data + rp), left_size) != EOK) {
151 g_uart_buf_memcpy_failed = HI_TRUE;
152 }
153 last_int_val = hi_uart_buf_lock(transfer);
154 transfer->rp = left_size;
155 transfer->flags &= ~BUF_CIRCLED;
156 hi_uart_buf_unlock(transfer, last_int_val);
157 return (hi_s32) (copy_size + left_size);
158 }
159
uart_write_circ_buf(uart_circ_buf * transfer,const hi_char * buf,hi_u32 count)160 hi_s32 uart_write_circ_buf(uart_circ_buf *transfer, const hi_char *buf, hi_u32 count)
161 {
162 uintptr_t data;
163
164 if (transfer == NULL) {
165 return (hi_s32) HI_ERR_FAILURE;
166 }
167
168 hi_u32 last_int_val = hi_uart_buf_lock(transfer);
169 hi_u32 wp = transfer->wp;
170 hi_u32 rp = transfer->rp;
171 hi_u32 flags = transfer->flags;
172 hi_uart_buf_unlock(transfer, last_int_val);
173
174 data = (uintptr_t) transfer->data;
175 hi_u32 buf_size = transfer->size;
176
177 if (!(flags & BUF_CIRCLED)) {
178 if (count < (buf_size - wp)) {
179 if (memcpy_s((hi_void *)(uintptr_t) (data + wp), count, buf, count) != EOK) {
180 g_uart_buf_memcpy_failed = HI_TRUE;
181 }
182 transfer->wp += count;
183 return (hi_s32) count;
184 }
185 hi_u32 copy_size = buf_size - wp;
186 hi_u32 left_size = count - copy_size;
187 if (memcpy_s((hi_void *)(uintptr_t) (data + wp), copy_size, buf, copy_size) != EOK) {
188 g_uart_buf_memcpy_failed = HI_TRUE;
189 }
190 wp = 0;
191 if (left_size > rp) {
192 /* overflowed. some new data will be discarded */
193 left_size = rp;
194 }
195
196 if (memcpy_s((hi_void*)(uintptr_t)(data + wp), left_size, (hi_void *)(buf + copy_size), left_size) != EOK) {
197 g_uart_buf_memcpy_failed = HI_TRUE;
198 }
199 last_int_val = hi_uart_buf_lock(transfer);
200 transfer->wp = left_size;
201 transfer->flags |= BUF_CIRCLED;
202 hi_uart_buf_unlock(transfer, last_int_val);
203 return (hi_s32) (copy_size + left_size);
204 }
205 if (count > (rp - wp)) {
206 /* overflowed. some new data will be discarded */
207 count = rp - wp;
208 }
209
210 if (memcpy_s((hi_void *)(uintptr_t) (data + wp), count, buf, count) != EOK) {
211 g_uart_buf_memcpy_failed = HI_TRUE;
212 }
213 transfer->wp += count;
214 return (hi_s32) count;
215 }
216
uart_tx_interrupt_disable(uart_driver_data_t * udd)217 hi_void uart_tx_interrupt_disable(uart_driver_data_t *udd)
218 {
219 udd->receive_tx_int = HI_FALSE; /* when disable tx interrupt, set receive_tx_int false */
220 hi_u32 tx_status = hi_reg_read_val32(udd->phys_base + UART_IMSC);
221 hi_reg_write32(udd->phys_base + UART_IMSC, (~UART_TX_INT_BIT) & tx_status);
222 }
223
uart_tx_interrupt_enable(const uart_driver_data_t * udd)224 hi_void uart_tx_interrupt_enable(const uart_driver_data_t *udd)
225 {
226 hi_u32 tx_status = hi_reg_read_val32(udd->phys_base + UART_IMSC);
227 hi_reg_write32(udd->phys_base + UART_IMSC, (unsigned short) (UART_TX_INT_BIT | tx_status));
228 }
229
uart_tx_interrupt_clear(const uart_driver_data_t * udd)230 hi_void uart_tx_interrupt_clear(const uart_driver_data_t *udd)
231 {
232 hi_u32 int_clear_status = hi_reg_read_val32(udd->phys_base + UART_ICR);
233 hi_reg_write32(udd->phys_base + UART_ICR, (unsigned short) (UART_TX_INT_BIT | int_clear_status));
234 }
235
uart_rx_interrupt_disable(const uart_driver_data_t * udd)236 hi_void uart_rx_interrupt_disable(const uart_driver_data_t *udd)
237 {
238 hi_u32 tx_status = hi_reg_read_val32(udd->phys_base + UART_IMSC);
239 hi_reg_write32(udd->phys_base + UART_IMSC, ~(UART_RX_INT_ENABLE) & tx_status);
240 }
241
uart_rx_interrupt_enable(const uart_driver_data_t * udd)242 hi_void uart_rx_interrupt_enable(const uart_driver_data_t *udd)
243 {
244 hi_u32 tx_status = hi_reg_read_val32(udd->phys_base + UART_IMSC);
245 hi_reg_write32(udd->phys_base + UART_IMSC, UART_RX_INT_ENABLE | tx_status);
246 }
247
get_recv_irq_err(unsigned int int_status,uart_drv_stat_info * pst_uart_stat_info)248 hi_void get_recv_irq_err(unsigned int int_status, uart_drv_stat_info *pst_uart_stat_info)
249 {
250 if (int_status & UART_INTMASK_OVERRUN) {
251 (pst_uart_stat_info->recv_irq_err_overrun)++;
252 }
253
254 if (int_status & UART_INTMASK_PARERR) {
255 (pst_uart_stat_info->recv_irq_err_parity)++;
256 }
257
258 if (int_status & UART_INTMASK_FRAMINGERR) {
259 (pst_uart_stat_info->recv_irq_err_frame)++;
260 }
261
262 if (int_status & UART_INTMASK_BREAKERR) {
263 (pst_uart_stat_info->recv_irq_err_break)++;
264 }
265 }
266
uart_get_tx_fifo_available_cnt(const uart_driver_data_t * udd)267 HI_ALWAYS_STAIC_INLINE hi_u32 uart_get_tx_fifo_available_cnt(const uart_driver_data_t *udd)
268 {
269 hi_u32 tx_fifo_line = udd->attr.tx_fifo_line;
270 hi_u32 tx_fifo_used_cnt;
271 switch (tx_fifo_line) {
272 case 0: /* 0 */
273 tx_fifo_used_cnt = 8; /* algorithm: UART_FIFO_TX_SIZE / 8; */
274 break;
275 case 1: /* 1 */
276 tx_fifo_used_cnt = 16; /* algorithm: UART_FIFO_TX_SIZE / 4; 16 */
277 break;
278 case 2: /* 2 */
279 tx_fifo_used_cnt = 32; /* algorithm: UART_FIFO_TX_SIZE / 2; 32 */
280 break;
281 case 3: /* 3 */
282 tx_fifo_used_cnt = 48; /* algorithm: UART_FIFO_TX_SIZE / 4 * 3; 48 */
283 break;
284 case 4: /* 4 */
285 tx_fifo_used_cnt = 56; /* algorithm: UART_FIFO_TX_SIZE / 8 * 7; 56 */
286 break;
287 default:
288 tx_fifo_used_cnt = 32; /* algorithm: UART_FIFO_TX_SIZE / 2; 32 */
289 break;
290 }
291 return (UART_FIFO_TX_SIZE - tx_fifo_used_cnt);
292 }
293
uart_get_rx_fifo_cnt(const uart_driver_data_t * udd)294 HI_ALWAYS_STAIC_INLINE hi_u32 uart_get_rx_fifo_cnt(const uart_driver_data_t *udd)
295 {
296 hi_u32 rx_fifo_line = udd->attr.rx_fifo_line;
297 hi_u32 rx_fifo_cnt;
298 switch (rx_fifo_line) {
299 case 0: /* 0 */
300 rx_fifo_cnt = 8; /* algorithm: UART_FIFO_TX_SIZE / 8 -> 8 */
301 break;
302 case 1: /* 1 */
303 rx_fifo_cnt = 16; /* algorithm: UART_FIFO_TX_SIZE / 4 -> 16 */
304 break;
305 case 2: /* 2 */
306 rx_fifo_cnt = 32; /* algorithm: UART_FIFO_TX_SIZE / 2 -> 32 */
307 break;
308 case 3: /* 3 */
309 rx_fifo_cnt = 48; /* algorithm: UART_FIFO_TX_SIZE / 4 * 3 -> 48 */
310 break;
311 case 4: /* 4 */
312 rx_fifo_cnt = 56; /* algorithm: UART_FIFO_TX_SIZE / 8 * 7 -> 56 */
313 break;
314 default:
315 rx_fifo_cnt = 32; /* algorithm: UART_FIFO_TX_SIZE / 2 -> 32 */
316 break;
317 }
318 return rx_fifo_cnt;
319 }
320
uart_get_tx_fifo_dma_cnt(hi_u32 tx_fifo_available_cnt)321 HI_ALWAYS_STAIC_INLINE hi_u32 uart_get_tx_fifo_dma_cnt(hi_u32 tx_fifo_available_cnt)
322 {
323 if (tx_fifo_available_cnt <= 32) { /* algorithm: UART_FIFO_TX_SIZE / 2 = 32 */
324 return tx_fifo_available_cnt;
325 } else {
326 return 32; /* algorithm: UART_FIFO_TX_SIZE / 2 = 32 */
327 }
328 }
329
uart_get_rx_fifo_dma_cnt(hi_u32 rx_fifo_cnt)330 HI_ALWAYS_STAIC_INLINE hi_u32 uart_get_rx_fifo_dma_cnt(hi_u32 rx_fifo_cnt)
331 {
332 if (rx_fifo_cnt <= 32) { /* algorithm: UART_FIFO_TX_SIZE / 2 = 32 */
333 return rx_fifo_cnt;
334 } else {
335 return 32; /* algorithm: UART_FIFO_TX_SIZE / 2 = 32 */
336 }
337 }
338
uart_get_burst_size_e(hi_u32 burst_size)339 HI_ALWAYS_STAIC_INLINE hi_dma_burst_size uart_get_burst_size_e(hi_u32 burst_size)
340 {
341 if (burst_size == 8) { /* burst_size为8 */
342 return DMA_BURST_MSIZE_8;
343 } else if (burst_size == 16) { /* burst_size为16 */
344 return DMA_BURST_MSIZE_16;
345 } else if (burst_size == 32) { /* burst_size为32 */
346 return DMA_BURST_MSIZE_32;
347 } else {
348 return DMA_BURST_MSIZE_1;
349 }
350 }
351
352 #ifdef CONFIG_UART_DMA_SUPPORT
uart_dma_para_cfg(const uart_driver_data_t * udd,hi_dma_para * dma_para,const hi_char * buf)353 static hi_void uart_dma_para_cfg(const uart_driver_data_t *udd, hi_dma_para *dma_para, const hi_char *buf)
354 {
355 hi_u32 rx_fifo_dma_cnt = uart_get_rx_fifo_dma_cnt(uart_get_rx_fifo_cnt(udd));
356 hi_dma_burst_size burst_size_e = uart_get_burst_size_e(rx_fifo_dma_cnt);
357
358 dma_para->tr_type = DMA_PHL_TO_MEM;
359 if (udd->phys_base == UART0_BASE) {
360 dma_para->src_phl = UART0_RX;
361 } else if (udd->phys_base == UART1_BASE) {
362 dma_para->src_phl = UART1_RX;
363 } else {
364 dma_para->src_phl = UART2_RX;
365 }
366 dma_para->dst_phl = 0;
367 dma_para->src_addr = udd->phys_base;
368 dma_para->dst_addr = (uintptr_t) buf;
369 dma_para->src_burst_size = burst_size_e;
370 dma_para->dst_burst_size = burst_size_e;
371 dma_para->src_width = WIDTH_BIT8;
372 dma_para->dst_width = WIDTH_BIT8;
373 dma_para->transfer_size = rx_fifo_dma_cnt;
374 dma_para->cb = HI_NULL;
375
376 uart_error("rx dma start, rx_fifo_dma_cnt:%d\r\n", rx_fifo_dma_cnt);
377 }
378
uart_dma_recv_irq(uart_driver_data_t * udd,hi_u32 status,hi_char * buf)379 static hi_u32 uart_dma_recv_irq(uart_driver_data_t *udd, hi_u32 status, hi_char *buf)
380 {
381 hi_u32 ret;
382 hi_dma_para dma_para;
383 hi_u32 rx_fifo_dma_cnt;
384
385 uart_error("enter rx dma");
386 #ifdef CONFIG_UART_DEBUG_INFO
387 uart_drv_stat_info *pst_uart_stat_info = &(udd->uart_stat_info);
388 get_recv_irq_err(status, pst_uart_stat_info);
389 #else
390 unused_param(status);
391 #endif
392
393 /* if uart hardware rx fifo is empty, go out of circle */
394 hi_u32 usr = hi_reg_read_val32(udd->phys_base + UART_FR);
395 if ((usr & UARTFR_RXFE_MASK) == UARTFR_RXFE_MASK) {
396 #ifdef CONFIG_UART_DEBUG_INFO
397 (udd->uart_stat_info.recv_irq_err_emptyfifo_cnt)++;
398 #endif
399 return HI_ERR_FAILURE;
400 }
401
402 rx_fifo_dma_cnt = uart_get_rx_fifo_dma_cnt(uart_get_rx_fifo_cnt(udd));
403 uart_dma_para_cfg(udd, &dma_para, buf);
404
405 ret = hi_dma_transfer(&dma_para, HI_TRUE);
406 uart_error("rx dma end, rx_fifo_dma_cnt:%d\r\n", rx_fifo_dma_cnt);
407 if (ret == HI_ERR_SUCCESS) {
408 udd->rx_recv(udd->rx_transfer, buf, rx_fifo_dma_cnt);
409 #ifdef CONFIG_UART_DEBUG_INFO
410 for (hi_u32 i = 0; i < rx_fifo_dma_cnt; i++) {
411 udd->uart_stat_info.recv_last_context.data[udd->uart_stat_info.recv_last_context.num] = buf[i];
412 udd->uart_stat_info.recv_last_context.num++;
413 udd->uart_stat_info.recv_last_context.num &= (HI_UART_LAST_RECORD_BYTE_COUNT - 1);
414 }
415 #endif
416 } else {
417 #ifdef CONFIG_UART_DEBUG_INFO
418 udd->uart_stat_info.recv_dma_err_cnt++;
419 #endif
420 }
421 if (udd->act.rx_block == UART_FLG_RD_BLOCK) {
422 hi_event_send(udd->event_id, UART_RD_EVENT);
423 }
424 #ifdef CONFIG_UART_DEBUG_INFO
425 udd->uart_stat_info.recv_irq_cnt++;
426 udd->uart_stat_info.recv_irq_data_cnt += rx_fifo_dma_cnt;
427 #endif
428 return HI_ERR_SUCCESS;
429 }
430 #endif
431
uart_nodma_recv_irq(uart_driver_data_t * udd,hi_u32 status,hi_char * buf)432 static hi_void uart_nodma_recv_irq(uart_driver_data_t *udd, hi_u32 status, hi_char *buf)
433 {
434 hi_u32 count = 0;
435 uart_error("enter rx not dma");
436
437 #ifdef CONFIG_UART_DEBUG_INFO
438 uart_drv_stat_info *pst_uart_stat_info = &(udd->uart_stat_info);
439 get_recv_irq_err(status, pst_uart_stat_info);
440 #else
441 unused_param(status);
442 #endif
443 do {
444 hi_u32 usr = hi_reg_read_val32(udd->phys_base + UART_FR);
445 /* if uart hardware rx fifo is empty, go out of circle */
446 if ((usr & UARTFR_RXFE_MASK) == UARTFR_RXFE_MASK) {
447 #ifdef CONFIG_UART_DEBUG_INFO
448 if (!count) {
449 (udd->uart_stat_info.recv_irq_err_emptyfifo_cnt)++;
450 }
451 #endif
452 break;
453 }
454
455 if (buf == HI_NULL) {
456 break;
457 }
458 buf[count] = (char) hi_reg_read_val32(udd->phys_base + UART_DR);
459 #ifdef CONFIG_UART_DEBUG_INFO
460 udd->uart_stat_info.recv_last_context.data[udd->uart_stat_info.recv_last_context.num] =
461 (unsigned char) buf[count];
462 udd->uart_stat_info.recv_last_context.num++;
463 udd->uart_stat_info.recv_last_context.num &= (HI_UART_LAST_RECORD_BYTE_COUNT - 1);
464 #endif
465 count++;
466 } while (count < 64); /* 64 */
467
468 if (count >= 1 && udd->rx_recv != HI_NULL) {
469 udd->rx_recv(udd->rx_transfer, buf, count);
470 if (udd->act.rx_block == UART_FLG_RD_BLOCK) {
471 hi_event_send(udd->event_id, UART_RD_EVENT);
472 }
473 }
474 #ifdef CONFIG_UART_DEBUG_INFO
475 udd->uart_stat_info.recv_irq_cnt++;
476 udd->uart_stat_info.recv_irq_data_cnt += count;
477 #endif
478 }
479
uart_send_irq(uart_driver_data_t * udd,hi_char * buf)480 static hi_void uart_send_irq(uart_driver_data_t *udd, hi_char *buf)
481 {
482 #ifdef CONFIG_UART_DEBUG_INFO
483 udd->uart_stat_info.send_irq_cnt++;
484 #endif
485
486 if (udd->receive_tx_int == HI_FALSE) {
487 udd->receive_tx_int = HI_TRUE;
488 return;
489 }
490
491 if (uart_circ_buf_empty(udd->tx_transfer)) {
492 uart_tx_interrupt_disable(udd);
493 } else {
494 hi_u32 count = (unsigned int) udd->tx_send(udd->tx_transfer, buf, uart_get_tx_fifo_available_cnt(udd));
495 if (udd->ops->start_tx) {
496 (void) udd->ops->start_tx(udd, buf, count);
497 }
498 if (udd->act.tx_block == UART_FLG_WD_BLOCK) {
499 (void) hi_event_send(udd->event_id, UART_WD_EVENT);
500 }
501 }
502 }
503
uart_drv_irq(void * data)504 static hi_void uart_drv_irq(void *data)
505 {
506 hi_u32 status;
507 hi_char buf[64] = { 0 }; /* size 64 */
508 uart_driver_data_t *udd = (uart_driver_data_t *) data;
509 char *buff = buf;
510 if (udd == NULL) {
511 return;
512 }
513 status = hi_reg_read_val32(udd->phys_base + UART_MIS);
514 #ifdef CONFIG_UART_DMA_SUPPORT
515 /* recv irq */
516 if ((UART_INTMASK_RX & status) && (udd->act.rx_use_dma == UART_RX_USE_DMA)) {
517 if (uart_dma_recv_irq(udd, status, buff) != HI_ERR_SUCCESS) {
518 /* send irq */
519 if (UART_INTMASK_TX & status) {
520 uart_send_irq(udd, buff);
521 }
522 return;
523 }
524 } else if ((UART_INTMASK_RX & status) || (UART_INTMASK_RECTIMEOUT & status)) {
525 uart_nodma_recv_irq(udd, status, buff);
526 }
527 #else
528 if ((UART_INTMASK_RX & status) || (UART_INTMASK_RECTIMEOUT & status)) {
529 uart_nodma_recv_irq(udd, status, buff);
530 }
531 #endif
532
533 /* send irq */
534 if (UART_INTMASK_TX & status) {
535 uart_send_irq(udd, buff);
536 }
537 }
538
uart_buf_empty(const uart_driver_data_t * udd)539 hi_u32 uart_buf_empty(const uart_driver_data_t *udd)
540 {
541 if ((uart_circ_buf_empty(udd->tx_transfer)) &&
542 (uart_circ_buf_empty(udd->rx_transfer))) {
543 return 1;
544 }
545 return 0;
546 }
547
uart_drv_set_attr(uart_driver_data_t * udd)548 static hi_u32 uart_drv_set_attr(uart_driver_data_t *udd)
549 {
550 hi_u32 ret;
551 hi_u32 int_save;
552 uart_param_stru uart_param;
553 if (memset_s(&uart_param, sizeof(uart_param_stru), 0, sizeof(uart_param_stru)) != EOK) {
554 return HI_ERR_MEMSET_S;
555 }
556 uart_param.baudrate = udd->attr.baud_rate;
557 uart_param.databit = udd->attr.data_bits;
558 uart_param.stopbit = udd->attr.stop_bits;
559 uart_param.parity = udd->attr.parity;
560 uart_param.flow_ctrl = udd->attr.flow_ctrl;
561 uart_param.fifoline_tx_int = udd->attr.tx_fifo_line;
562 uart_param.fifoline_rx_int = udd->attr.rx_fifo_line;
563 uart_param.fifoline_rts = udd->attr.flow_fifo_line;
564
565 int_save = hi_int_lock();
566 ret = set_uart_param(udd->phys_base, uart_param);
567 (hi_void) hi_int_restore(int_save);
568
569 udd->receive_tx_int = HI_FALSE; /* when reset uart module, set receive_tx_int false */
570
571 return ret;
572 }
573
uart_drv_startup(uart_driver_data_t * udd)574 static hi_u32 uart_drv_startup(uart_driver_data_t *udd)
575 {
576 hi_u32 ret;
577
578 /* disable interrupt */
579 hi_reg_write32(udd->phys_base + UART_IMSC, 0);
580
581 /* set baudrate,data_bit,stop_bit,parity */
582 if (uart_drv_set_attr(udd) != HI_ERR_SUCCESS) {
583 return HI_ERR_FAILURE;
584 }
585
586 /* creat interrupt function for uart */
587 ret = hi_irq_request(udd->irq_num, HI_IRQ_FLAG_PRI3, (irq_routine) uart_drv_irq, (uintptr_t) udd);
588 if (ret == HI_ERR_SUCCESS || ret == HI_ERR_ISR_ALREADY_CREATED) {
589 ret = HI_ERR_SUCCESS;
590 uart_rx_interrupt_enable(udd);
591 }
592
593 return ret;
594 }
595
uart_drv_shutdown(struct uart_driver_data * udd)596 static hi_void uart_drv_shutdown(struct uart_driver_data *udd)
597 {
598 uart_tx_interrupt_disable(udd);
599 uart_rx_interrupt_disable(udd);
600 hi_irq_disable((hi_u32) udd->irq_num);
601 if (hi_irq_free(udd->irq_num) != HI_ERR_SUCCESS) {
602 uart_error("uart irq free fail");
603 }
604 }
605
606 #ifdef CONFIG_UART_DMA_SUPPORT
uart_drv_dma_start_tx_cfg(struct uart_driver_data * udd,const hi_char * buf,hi_u32 count)607 hi_u32 uart_drv_dma_start_tx_cfg(struct uart_driver_data *udd, const hi_char *buf, hi_u32 count)
608 {
609 hi_u32 send_cnt = 0;
610 hi_u32 tx_fifo_available_cnt = uart_get_tx_fifo_available_cnt(udd);
611 hi_u32 dma_busrt_size = uart_get_tx_fifo_dma_cnt(tx_fifo_available_cnt);
612 hi_dma_burst_size burst_size_e = uart_get_burst_size_e(dma_busrt_size);
613 hi_u32 ret;
614 hi_dma_para dma_para;
615
616 dma_para.tr_type = DMA_MEM_TO_PHL;
617 dma_para.src_phl = 0;
618 if (udd->phys_base == UART0_BASE) {
619 dma_para.dst_phl = UART0_TX;
620 } else if (udd->phys_base == UART1_BASE) {
621 dma_para.dst_phl = UART1_TX;
622 } else {
623 dma_para.dst_phl = UART2_TX;
624 }
625
626 dma_para.src_addr = (uintptr_t) buf;
627 dma_para.dst_addr = udd->phys_base;
628 dma_para.src_burst_size = burst_size_e;
629 dma_para.dst_burst_size = burst_size_e;
630 dma_para.src_width = WIDTH_BIT8;
631 dma_para.dst_width = WIDTH_BIT8;
632 dma_para.transfer_size = dma_busrt_size;
633 dma_para.cb = HI_NULL;
634 send_cnt += dma_busrt_size;
635 uart_error("tx dma start, dma_busrt_size:%d\r\n", dma_busrt_size);
636 ret = hi_dma_transfer(&dma_para, HI_TRUE);
637 uart_error("tx dma end, dma_busrt_size:%d\r\n", dma_busrt_size);
638 if (ret != HI_ERR_SUCCESS) {
639 #ifdef CONFIG_UART_DEBUG_INFO
640 udd->uart_stat_info.send_dma_err_cnt++;
641 #endif
642 return (hi_u32)ret;
643 }
644
645 for (; send_cnt < count; send_cnt++) {
646 /* Wait until there is space in the FIFO */
647 while ((hi_reg_read_val32(udd->phys_base + UART_FR) & UARTFR_TXFF_MASK) != 0) { }
648 hi_reg_write32(udd->phys_base + UART_DR, (unsigned) (hi_u8) buf[send_cnt]);
649 }
650 return HI_ERR_SUCCESS;
651 }
652
uart_drv_dma_start_tx(struct uart_driver_data * udd,const hi_char * buf,hi_u32 count)653 hi_u32 uart_drv_dma_start_tx(struct uart_driver_data *udd, const hi_char *buf, hi_u32 count)
654 {
655 hi_u32 tx_fifo_available_cnt = uart_get_tx_fifo_available_cnt(udd);
656 hi_u32 dma_busrt_size = uart_get_tx_fifo_dma_cnt(tx_fifo_available_cnt);
657 if (count >= dma_busrt_size) {
658 hi_u32 ret = uart_drv_dma_start_tx_cfg(udd, buf, count);
659 if (ret != HI_ERR_SUCCESS) {
660 #ifdef CONFIG_UART_DEBUG_INFO
661 udd->uart_stat_info.send_dma_err_cnt++;
662 #endif
663 return (hi_s32)ret;
664 }
665 } else {
666 for (hi_u32 i = 0; i < count; i++) {
667 /* Wait until there is space in the FIFO */
668 while ((hi_reg_read_val32(udd->phys_base + UART_FR) & UARTFR_TXFF_MASK) != 0) { }
669 hi_reg_write32(udd->phys_base + UART_DR, (unsigned) (hi_u8) buf[i]);
670 }
671 }
672
673 #ifdef CONFIG_UART_DEBUG_INFO
674 hi_u32 idx;
675 for (idx = 0; idx < count; idx++) {
676 udd->uart_stat_info.send_last_context.data[udd->uart_stat_info.send_last_context.num] = buf[idx];
677 udd->uart_stat_info.send_last_context.num++;
678 udd->uart_stat_info.send_last_context.num &= (HI_UART_LAST_RECORD_BYTE_COUNT - 1);
679 }
680 #endif
681
682 #ifdef CONFIG_UART_DEBUG_INFO
683 udd->uart_stat_info.send_irq_data_cnt += count;
684 #endif
685 return count;
686 }
687 #endif
688
uart_drv_irq_start_tx(struct uart_driver_data * udd,const hi_char * buf,hi_u32 count)689 static hi_u32 uart_drv_irq_start_tx(struct uart_driver_data *udd, const hi_char *buf, hi_u32 count)
690 {
691 hi_u32 tx_fifo_available_cnt = 0;
692 hi_u32 send_cnt = count > tx_fifo_available_cnt ? tx_fifo_available_cnt : count;
693 hi_u32 idx = 0;
694
695 while (idx < send_cnt) {
696 hi_reg_write32(udd->phys_base + UART_DR, (unsigned) (hi_u8) buf[idx]);
697 #ifdef CONFIG_UART_DEBUG_INFO
698 udd->uart_stat_info.send_last_context.data[udd->uart_stat_info.send_last_context.num] = buf[idx];
699 udd->uart_stat_info.send_last_context.num++;
700 udd->uart_stat_info.send_last_context.num &= (HI_UART_LAST_RECORD_BYTE_COUNT - 1);
701 #endif
702 idx++;
703 }
704
705 for (; send_cnt < count; send_cnt++) {
706 /* Wait until there is space in the FIFO */
707 while ((hi_reg_read_val32(udd->phys_base + UART_FR) & UARTFR_TXFF_MASK) != 0) { }
708 hi_reg_write32(udd->phys_base + UART_DR, (unsigned) (hi_u8) buf[send_cnt]);
709 #ifdef CONFIG_UART_DEBUG_INFO
710 udd->uart_stat_info.send_last_context.data[udd->uart_stat_info.send_last_context.num] = buf[send_cnt];
711 udd->uart_stat_info.send_last_context.num++;
712 udd->uart_stat_info.send_last_context.num &= (HI_UART_LAST_RECORD_BYTE_COUNT - 1);
713 #endif
714 }
715
716 #ifdef CONFIG_UART_DEBUG_INFO
717 udd->uart_stat_info.send_irq_data_cnt += count;
718 #endif
719 return count;
720 }
721
uart_drv_start_tx(struct uart_driver_data * udd,const hi_char * buf,hi_u32 count)722 static hi_s32 uart_drv_start_tx(struct uart_driver_data *udd, const hi_char *buf, hi_u32 count)
723 {
724 hi_u32 idx = 0;
725 hi_u32 ret;
726
727 #ifdef CONFIG_UART_DMA_SUPPORT
728 if (udd->tx_use_int == HI_TRUE && udd->receive_tx_int == HI_TRUE && udd->act.tx_use_dma == UART_TX_USE_DMA) {
729 ret = uart_drv_dma_start_tx(udd, buf, count);
730 return (hi_s32)ret;
731 } else if (udd->tx_use_int == HI_TRUE && udd->receive_tx_int == HI_TRUE) {
732 #else
733 if (udd->tx_use_int == HI_TRUE && udd->receive_tx_int == HI_TRUE) {
734 #endif
735 ret = uart_drv_irq_start_tx(udd, buf, count);
736 return (hi_s32)ret;
737 } else {
738 while (idx < count) {
739 /* Wait until there is space in the FIFO */
740 while ((hi_reg_read_val32(udd->phys_base + UART_FR) & UARTFR_TXFF_MASK) != 0) { }
741 hi_reg_write32(udd->phys_base + UART_DR, (unsigned) (hi_u8) buf[idx]);
742 #ifdef CONFIG_UART_DEBUG_INFO
743 udd->uart_stat_info.send_last_context.data[udd->uart_stat_info.send_last_context.num] = buf[idx];
744 udd->uart_stat_info.send_last_context.num++;
745 udd->uart_stat_info.send_last_context.num &= (HI_UART_LAST_RECORD_BYTE_COUNT - 1);
746 #endif
747 idx++;
748 }
749 #ifdef CONFIG_UART_DEBUG_INFO
750 udd->uart_stat_info.send_irq_data_cnt += count;
751 #endif
752 return (hi_s32) count;
753 }
754 }
755
756 static hi_u32 uart_drv_ioctl(uart_driver_data_t *udd)
757 {
758 hi_u32 ret;
759 ret = uart_drv_set_attr(udd);
760 uart_rx_interrupt_enable(udd);
761 return ret;
762 }
763
764 uart_ops g_uart_driver_uops = {
765 .startup = uart_drv_startup,
766 .shutdown = uart_drv_shutdown,
767 .start_tx = uart_drv_start_tx,
768 .ioctl = uart_drv_ioctl,
769 };
770