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