• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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