• 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 
18 static uart_driver_data_t g_uart_0 = {
19     .num = UART0,
20     .phys_base = HI_UART0_REG_BASE,
21     .irq_num = UART_0_IRQ,
22     .rx_transfer = HI_NULL,
23     .tx_transfer = HI_NULL,
24     .rx_recv = uart_write_circ_buf,
25     .tx_send = uart_read_circ_buf,
26     .count = 0,
27     .state = UART_STATE_NOT_OPENED,
28     .receive_tx_int = HI_FALSE,
29     .ops = &g_uart_driver_uops,
30     .tx_use_int = HI_FALSE,
31     .attr = UART_ATTR_DEFAULT,
32     .act = UART_ACT_DEFAULT,
33 };
34 
35 static uart_driver_data_t g_uart_1 = {
36     .num = UART1,
37     .phys_base = HI_UART1_REG_BASE,
38     .irq_num = UART_1_IRQ,
39     .rx_transfer = HI_NULL,
40     .tx_transfer = HI_NULL,
41     .rx_recv = uart_write_circ_buf,
42     .tx_send = uart_read_circ_buf,
43     .count = 0,
44     .state = UART_STATE_NOT_OPENED,
45     .receive_tx_int = HI_FALSE,
46     .ops = &g_uart_driver_uops,
47     .tx_use_int = HI_FALSE,
48     .attr = UART_ATTR_DEFAULT,
49     .act = UART_ACT_DEFAULT,
50 };
51 
52 static uart_driver_data_t g_uart_2 = {
53     .num = UART2,
54     .phys_base = HI_UART2_REG_BASE,
55     .irq_num = UART_2_IRQ,
56     .rx_transfer = HI_NULL,
57     .tx_transfer = HI_NULL,
58     .rx_recv = uart_write_circ_buf,
59     .tx_send = uart_read_circ_buf,
60     .count = 0,
61     .state = UART_STATE_NOT_OPENED,
62     .receive_tx_int = HI_FALSE,
63     .ops = &g_uart_driver_uops,
64     .tx_use_int = HI_FALSE,
65     .attr = UART_ATTR_DEFAULT,
66     .act = UART_ACT_DEFAULT,
67 };
68 
69 uart_driver_data_t *g_udd_g[UART_NUM] = { &g_uart_0, &g_uart_1, &g_uart_2 };
70 
uart_open(hi_u32 uart_index,uart_mode mode)71 uart_driver_data_t *uart_open(hi_u32 uart_index, uart_mode mode)
72 {
73     hi_u32 ret;
74     uart_driver_data_t *udd = HI_NULL;
75 
76     if (uart_index >= UART_NUM || mode != UART_232) {
77         return HI_NULL;
78     }
79 
80     udd = (uart_driver_data_t *) g_udd_g[uart_index];
81 
82     if (udd->state == UART_STATE_NOT_OPENED) {
83         ret = uart_init_circ_buf(udd, udd->act.tx_buffer_size, udd->act.rx_buffer_size);
84         if (ret != HI_ERR_SUCCESS) {
85             uart_set_errno(UART_ERR_INIT_CIRC_FAILED);
86             return HI_NULL;
87         }
88         ret = hi_event_create(&udd->event_id);
89         if (ret != HI_ERR_SUCCESS) {
90             uart_deinit_circ_buf(udd);
91             return HI_NULL;
92         }
93         udd->type = mode;
94 
95         if (!udd->ops->startup || udd->ops->startup(udd)) {
96             uart_deinit_circ_buf(udd);
97             hi_event_delete(udd->event_id);
98             uart_set_errno(UART_ERR_START_FAILED);
99             return HI_NULL;
100         }
101         udd->state = UART_STATE_USEABLE;
102     } else {
103         if (mode != udd->type) {
104             if (udd->ops->startup != HI_NULL) {
105                 udd->type = mode;
106                 udd->ops->startup(udd);
107             }
108         }
109     }
110 
111     return udd;
112 }
113 
114 
uart_read(uart_driver_data_t * udd,hi_char * buf,hi_u32 count)115 hi_s32 uart_read(uart_driver_data_t *udd, hi_char *buf, hi_u32 count)
116 {
117     hi_s32 len;
118     hi_u32 event_val = 0;
119 
120     if (udd == HI_NULL) {
121         return (hi_s32)HI_ERR_FAILURE;
122     }
123     if ((buf == HI_NULL) || (count == 0)) {
124         uart_set_errno(UART_ERR_PARA_INVALID);
125         return (hi_s32)HI_ERR_FAILURE;
126     }
127     if (udd->state != UART_STATE_USEABLE) {
128         uart_set_errno(UART_ERR_NOT_OPENED);
129         return (hi_s32)HI_ERR_FAILURE;
130     }
131 
132     do {
133         len = uart_read_circ_buf(udd->rx_transfer, buf, count);
134 #ifdef UART_DEBUG_INFO
135         udd->uart_stat_info.read_circ_cnt += (unsigned int) len;
136 #endif
137         if ((len == 0) && (udd->act.rx_block == UART_FLG_RD_BLOCK)) {
138             hi_event_wait(udd->event_id, UART_RD_EVENT | UART_RD_QUIT_EVENT, &event_val,
139                           HI_SYS_WAIT_FOREVER, HI_EVENT_WAITMODE_OR | HI_EVENT_WAITMODE_CLR);
140             if (event_val == UART_RD_QUIT_EVENT) {
141                 break;
142             }
143         } else {
144             break;
145         }
146     } while (len == 0);
147 
148     return len;
149 }
150 
uart_write(uart_driver_data_t * udd,const hi_char * buf,hi_u32 send_count)151 hi_s32 uart_write(uart_driver_data_t *udd, const hi_char *buf, hi_u32 send_count)
152 {
153     hi_s32 len = 0;
154     hi_s32 count = (hi_s32)send_count;
155     hi_u32 left;
156     hi_u32 event_val = 0;
157     /* if uart is not in useable, report error */
158     if (udd == HI_NULL) {
159         return (hi_s32)HI_ERR_FAILURE;
160     }
161 
162     if ((buf == HI_NULL) || (count == 0)) {
163         uart_set_errno(UART_ERR_PARA_INVALID);
164         return (hi_s32)HI_ERR_FAILURE;
165     }
166     left = (hi_u32)count;
167     if (udd->state != UART_STATE_USEABLE) {
168         uart_set_errno(UART_ERR_NOT_OPENED);
169         return (hi_s32)HI_ERR_FAILURE;
170     }
171 
172     if (udd->receive_tx_int == HI_TRUE) {
173         do {
174             len += uart_write_circ_buf(udd->tx_transfer, (hi_char *)&buf[len], left);
175             if (len >= count) {
176                 break;
177             }
178             left = (hi_u32)count - (hi_u32)len;
179             if (udd->act.tx_block != UART_FLG_WD_BLOCK) {
180                 break;
181             }
182             uart_tx_interrupt_enable(udd);
183             (void) hi_event_wait(udd->event_id, UART_WD_EVENT, &event_val,
184                                  HI_SYS_WAIT_FOREVER, HI_EVENT_WAITMODE_OR | HI_EVENT_WAITMODE_CLR);
185         } while (left > 0);
186         uart_tx_interrupt_enable(udd);
187     } else {
188         uart_tx_interrupt_enable(udd);
189         if (udd->ops != HI_NULL &&
190             udd->ops->start_tx) {
191             len = udd->ops->start_tx(udd, buf, (hi_u32)count);
192         }
193     }
194 
195 #ifdef UART_DEBUG_INFO
196     udd->uart_stat_info.write_circ_cnt += (unsigned int) len;
197 #endif
198 
199     return len;
200 }
201 
uart_write_immediately(uart_driver_data_t * udd,const hi_char * buf,hi_u32 send_count)202 hi_s32 uart_write_immediately(uart_driver_data_t *udd, const hi_char *buf, hi_u32 send_count)
203 {
204     hi_s32 len = 0;
205     hi_s32 count = (hi_s32)send_count;
206 
207     /* if uart is not in useable, report error */
208     if (udd == HI_NULL) {
209         return (hi_s32)HI_ERR_FAILURE;
210     }
211 
212     if ((buf == HI_NULL) || (count == 0)) {
213         uart_set_errno(UART_ERR_PARA_INVALID);
214         return (hi_s32)HI_ERR_FAILURE;
215     }
216 
217     if (udd->state != UART_STATE_USEABLE) {
218         uart_set_errno(UART_ERR_NOT_OPENED);
219         return (hi_s32)HI_ERR_FAILURE;
220     }
221 
222     if (udd->ops->start_tx) {
223         len = udd->ops->start_tx(udd, buf, (hi_u32)count);
224     }
225 
226 #ifdef UART_DEBUG_INFO
227     udd->uart_stat_info.write_circ_cnt += (unsigned int) len;
228 #endif
229 
230     return len;
231 }
232 
uart_check_ioctrl_param(const uart_attr_t * attr)233 hi_bool uart_check_ioctrl_param(const uart_attr_t *attr)
234 {
235     if (attr == HI_NULL) {
236         return HI_FALSE;
237     }
238 
239     if (attr->baud_rate > 0
240         && attr->data_bits <= 8 && attr->data_bits >= 5   /* bits>=5 bits<=8 */
241         && (attr->parity == 0 || attr->parity == 1 || attr->parity == 2)  /* stop_bits:1 2 */
242         && (attr->stop_bits == 1 || attr->stop_bits == 2) /* stop_bits:1 2 */
243         && attr->tx_fifo_line <= 4 && attr->rx_fifo_line <= 4 && attr->flow_fifo_line <= 4) { /* 4 */
244         return HI_TRUE;
245     }
246 
247     return HI_FALSE;
248 }
249 
uart_ioctl(uart_driver_data_t * udd,hi_u32 cmd,uintptr_t arg)250 hi_u32 uart_ioctl(uart_driver_data_t *udd, hi_u32 cmd, uintptr_t arg)
251 {
252     hi_u32 ret = HI_ERR_SUCCESS;
253     uart_attr_t *attr = HI_NULL;
254 
255     if (udd == HI_NULL) {
256         return HI_ERR_UART_INVALID_PARAMETER;
257     }
258 
259     if (udd->state != UART_STATE_USEABLE) {
260         uart_set_errno(UART_ERR_NOT_OPENED);
261         return HI_ERR_FAILURE;
262     }
263 
264     switch (cmd) {
265         case UART_CFG_SET_ATTR:
266             attr = (uart_attr_t *) arg;
267             if (uart_check_ioctrl_param(attr) == HI_TRUE) {
268                 if (memcpy_s(&udd->attr, sizeof(uart_attr_t), attr, sizeof(uart_attr_t)) != EOK) {
269                     return HI_ERR_FAILURE;
270                 }
271                 if (udd->ops->ioctl && udd->ops->ioctl(udd)) {
272                     uart_set_errno(UART_ERR_IOCTL_FAILED);
273                     ret = HI_ERR_FAILURE;
274                 }
275             } else {
276                 uart_set_errno(UART_ERR_PARA_INVALID);
277                 ret = HI_ERR_FAILURE;
278             }
279             break;
280         case UART_CFG_GET_ATTR:
281             attr = (uart_attr_t *) arg;
282             if (memcpy_s(attr, sizeof(uart_attr_t), &udd->attr, sizeof(uart_attr_t)) != EOK) {
283                 return HI_ERR_FAILURE;
284             }
285             break;
286         case UART_CFG_GET_BUF_EMPTY: {
287             hi_u32 *is_empty = (hi_u32 *) arg;
288             *is_empty = uart_buf_empty(udd);
289             break;
290         }
291         default:
292             uart_set_errno(UART_ERR_PARA_INVALID);
293             ret = HI_ERR_FAILURE;
294             break;
295     }
296 
297     return ret;
298 }
299 
uart_close(uart_driver_data_t * udd)300 hi_u32 uart_close(uart_driver_data_t *udd)
301 {
302     if (udd == HI_NULL) {
303         return HI_ERR_UART_INVALID_PARAMETER;
304     }
305     if (udd->state != UART_STATE_USEABLE) {
306         return HI_ERR_SUCCESS;
307     }
308     if (udd->ops != HI_NULL && udd->ops->shutdown) {
309         udd->ops->shutdown(udd);
310     }
311 
312     uart_deinit_circ_buf(udd);
313     udd->state = UART_STATE_NOT_OPENED;
314 
315     if (udd->receive_tx_int != HI_FALSE) {
316         udd->receive_tx_int = HI_FALSE;
317     }
318     if (udd->count != 0) {
319         udd->count = 0;
320     }
321 
322     udd->attr = (uart_attr_t) UART_ATTR_DEFAULT;
323     udd->act = (uart_act_t) UART_ACT_DEFAULT;
324 
325     if (hi_event_delete(udd->event_id) != HI_ERR_SUCCESS) {
326         return HI_ERR_FAILURE;
327     }
328     return HI_ERR_SUCCESS;
329 }
330