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 * Description: Provides uart port template \n
16 *
17 * History: \n
18 * 2022-06-06, Create file. \n
19 */
20 #include "uart_porting.h"
21 #include "hal_uart_v151.h"
22 #ifdef SUPPORT_HAL_PINCTRL
23 #include "pinctrl_porting.h"
24 #include "pinctrl.h"
25 #endif
26 #include "uart.h"
27 #include "platform_core.h"
28 #include "securec.h"
29 #include "osal_interrupt.h"
30 #include "soc_osal.h"
31 #if defined(CONFIG_UART_SUPPORT_DMA)
32 #include "dma_porting.h"
33 #endif
34
35 #ifdef CONFIG_UART_SUPPORT_PORTTING_IRQ
36 #include "interrupt_porting.h"
37 #endif
38 #ifdef LOG_SUPPORT
39 #include "log_oam_msg.h"
40 #endif
41
42 #if !defined(BUILD_NOOSAL)
43 #if defined(USE_ALIOS)
44 #include "cmsis_os2.h"
45 #else
46 #include "cmsis_os.h"
47 #endif
48 #endif
49
50 #define UART_BUS_0_BASE_ADDR (UART0_BASE - 4)
51 #define UART_BUS_1_BASE_ADDR (UART1_BASE - 4)
52 #define UART_BUS_2_BASE_ADDR (UART2_BASE - 4)
53 #define GPIO12_PAD_CTRL_GROUP_ADDR 0x4400D030
54 #define GPIO13_PAD_CTRL_GROUP_ADDR 0x4400D034
55
56 #define UART_TRANS_LEN_MAX 128
57
58 const uintptr_t g_uart_base_addrs[UART_BUS_MAX_NUM] = {
59 (uintptr_t)UART_BUS_0_BASE_ADDR,
60 (uintptr_t)UART_BUS_1_BASE_ADDR,
61 (uintptr_t)UART_BUS_2_BASE_ADDR
62 };
63 #if !defined(BUILD_NOOSAL)
64 static osal_mutex g_uart_tx_mutex[UART_BUS_MAX_NUMBER] = {0};
65 const bool g_uart_support_mutex[UART_BUS_MAX_NUMBER] = {
66 CONFIG_UART0_SUPPORT_WRITE_MUTEX,
67 CONFIG_UART1_SUPPORT_WRITE_MUTEX,
68 CONFIG_UART2_SUPPORT_WRITE_MUTEX,
69 };
70 #endif
uart_porting_base_addr_get(uart_bus_t bus)71 uintptr_t uart_porting_base_addr_get(uart_bus_t bus)
72 {
73 return g_uart_base_addrs[bus];
74 }
75
76 typedef struct uart_interrupt {
77 core_irq_t irq_num;
78 osal_irq_handler irq_func;
79 } hal_uart_interrupt_t;
80
81 #ifdef CONFIG_UART_SUPPORT_PORTTING_IRQ
82 static const hal_uart_interrupt_t g_uart_interrupt_lines[UART_BUS_MAX_NUMBER] = {
83 #if UART_BUS_MAX_NUMBER > 0
84 { UART_0_IRQN, (osal_irq_handler)irq_uart0_handler },
85 #endif
86 #if UART_BUS_MAX_NUMBER > 1
87 { UART_1_IRQN, (osal_irq_handler)irq_uart1_handler },
88 #endif
89 #if UART_BUS_MAX_NUMBER > 2
90 { UART_2_IRQN, (osal_irq_handler)irq_uart2_handler },
91 #endif
92 #if UART_BUS_MAX_NUMBER > 3
93 { UART_3_IRQN, (osal_irq_handler)irq_uart3_handler },
94 #endif
95 };
96 #endif
97
uart_port_register_hal_funcs(uart_bus_t bus)98 void uart_port_register_hal_funcs(uart_bus_t bus)
99 {
100 hal_uart_register_funcs(bus, hal_uart_v151_funcs_get());
101 }
102
103 #ifdef SUPPORT_CLOCKS_CORE
104 #include "clocks_core_common.h"
105 #endif
106 #include "debug_print.h"
107
108 static uint32_t g_uart_clock_value = UART_CLOCK_FRQ;
109
uart_port_set_clock_value(uart_bus_t bus,uint32_t clock)110 void uart_port_set_clock_value(uart_bus_t bus, uint32_t clock)
111 {
112 unused(bus);
113 g_uart_clock_value = clock;
114 }
115
uart_port_get_clock_value(uart_bus_t bus)116 uint32_t uart_port_get_clock_value(uart_bus_t bus)
117 {
118 #ifdef SUPPORT_CLOCKS_CORE
119 return uart_get_clock_value(bus);
120 #else
121 UNUSED(bus);
122 return g_uart_clock_value;
123 #endif
124 }
125
126 #define GPIO_05_SEL 0x4400d014
127 #define GPIO_06_SEL 0x4400d018
128 #define GPIO_07_SEL 0x4400d01c
129 #define GPIO_08_SEL 0x4400d020
130 #define UART_2_MODE 2
131 #define GPIO_13_SEL 0x4400d034
132 #define GPIO_14_SEL 0x4400d038
133 #define UART1_TXD_SEL 0x4400d03c
134 #define UART1_RXD_SEL 0x4400d040
135 #define UART_1_MODE 1
136 #define UART0_TXD_SEL 0x4400d044
137 #define UART0_RXD_SEL 0x4400d048
138 #define UART_0_MODE 1
uart_port_config_pinmux(uart_bus_t bus)139 void uart_port_config_pinmux(uart_bus_t bus)
140 {
141 #ifndef BOARD_ASIC
142 // uart2需要配管脚复用
143 if (bus == UART_BUS_2) {
144 uapi_reg_write32(GPIO12_PAD_CTRL_GROUP_ADDR, 0x1);
145 uapi_reg_write32(GPIO13_PAD_CTRL_GROUP_ADDR, 0x1);
146 }
147 return;
148 #else
149 if (bus == UART_BUS_2) {
150 writel(GPIO_05_SEL, UART_2_MODE);
151 writel(GPIO_06_SEL, UART_2_MODE);
152 writel(GPIO_07_SEL, UART_2_MODE);
153 writel(GPIO_08_SEL, UART_2_MODE);
154 } else if (bus == UART_BUS_1) {
155 writel(GPIO_13_SEL, UART_1_MODE);
156 writel(GPIO_14_SEL, UART_1_MODE);
157 writel(UART1_TXD_SEL, UART_1_MODE);
158 writel(UART1_RXD_SEL, UART_1_MODE);
159 } else if (bus == UART_BUS_0) {
160 writel(UART0_TXD_SEL, UART_0_MODE);
161 writel(UART0_RXD_SEL, UART_0_MODE);
162 }
163 #endif
164 #if !defined(BUILD_NOOSAL)
165 if (bus < UART_BUS_MAX_NUMBER && g_uart_support_mutex[bus] == true && g_uart_tx_mutex[bus].mutex == NULL) {
166 osal_mutex_init(&g_uart_tx_mutex[bus]);
167 }
168 #endif
169 }
170
171 #ifdef CONFIG_UART_SUPPORT_PORTTING_IRQ
uart_port_register_irq(uart_bus_t bus)172 void uart_port_register_irq(uart_bus_t bus)
173 {
174 osal_irq_request(g_uart_interrupt_lines[bus].irq_num, g_uart_interrupt_lines[bus].irq_func, NULL, NULL, NULL);
175 osal_irq_set_priority(g_uart_interrupt_lines[bus].irq_num, irq_prio(g_uart_interrupt_lines[bus].irq_num));
176 osal_irq_enable(g_uart_interrupt_lines[bus].irq_num);
177 }
178
irq_uart0_handler(void)179 void irq_uart0_handler(void)
180 {
181 hal_uart_irq_handler(UART_BUS_0);
182 osal_irq_clear(UART_0_IRQN);
183 }
184
irq_uart1_handler(void)185 void irq_uart1_handler(void)
186 {
187 hal_uart_irq_handler(UART_BUS_1);
188 osal_irq_clear(UART_1_IRQN);
189 }
190
irq_uart2_handler(void)191 void irq_uart2_handler(void)
192 {
193 hal_uart_irq_handler(UART_BUS_2);
194 osal_irq_clear(UART_2_IRQN);
195 }
196
uart_port_unregister_irq(uart_bus_t bus)197 void uart_port_unregister_irq(uart_bus_t bus)
198 {
199 osal_irq_disable(g_uart_interrupt_lines[bus].irq_num);
200 }
201
uart_port_set_pending_irq(uart_bus_t uart)202 void uart_port_set_pending_irq(uart_bus_t uart)
203 {
204 int_set_pendind_irq(g_uart_interrupt_lines[uart].irq_num);
205 }
206 #else
uart_port_register_irq(uart_bus_t bus)207 void uart_port_register_irq(uart_bus_t bus)
208 {
209 unused(bus);
210 }
211
uart_port_unregister_irq(uart_bus_t bus)212 void uart_port_unregister_irq(uart_bus_t bus)
213 {
214 unused(bus);
215 }
216 #endif
217
218 #ifdef SW_UART_DEBUG
219 #define DEBUG_UART_RX_BUFFER_SIZE 1
220 STATIC uart_bus_t g_sw_debug_uart;
221 static bool g_sw_debug_uart_enabled = false;
222 STATIC uint8_t g_uart_rx_buffer[DEBUG_UART_RX_BUFFER_SIZE];
223
224 static void uart_rx_callback(const void *buf, uint16_t buf_len, bool remaining);
225
uart_rx_callback(const void * buf,uint16_t buf_len,bool remaining)226 void uart_rx_callback(const void *buf, uint16_t buf_len, bool remaining)
227 {
228 UNUSED(remaining);
229 if (!g_sw_debug_uart_enabled) {
230 return;
231 }
232 uapi_uart_write(SW_DEBUG_UART_BUS, (const void *)buf, buf_len, 0);
233 }
234
sw_debug_uart_init(uint32_t baud_rate)235 void sw_debug_uart_init(uint32_t baud_rate)
236 {
237 uart_pin_config_t uart_pins;
238 uart_attr_t uart_line_config;
239 uart_buffer_config_t uart_buffer_config;
240
241 g_sw_debug_uart = SW_DEBUG_UART_BUS;
242 // TX configuration
243 uart_pins.tx_pin = CHIP_FIXED_TX_PIN;
244 uart_pins.rts_pin = PIN_NONE;
245
246 // RX configuration
247 uart_pins.rx_pin = CHIP_FIXED_RX_PIN;
248 uart_pins.cts_pin = PIN_NONE;
249
250 uart_line_config.baud_rate = baud_rate;
251 uart_line_config.data_bits = UART_DATA_BIT_8;
252 uart_line_config.parity = UART_PARITY_NONE;
253 uart_line_config.stop_bits = UART_STOP_BIT_1;
254
255 uart_buffer_config.rx_buffer_size = DEBUG_UART_RX_BUFFER_SIZE;
256 uart_buffer_config.rx_buffer = g_uart_rx_buffer;
257
258 (void)uapi_uart_init(SW_DEBUG_UART_BUS, &uart_pins, &uart_line_config, NULL, &uart_buffer_config);
259 uapi_uart_register_rx_callback(SW_DEBUG_UART_BUS, UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE,
260 DEBUG_UART_RX_BUFFER_SIZE, uart_rx_callback);
261
262 g_sw_debug_uart_enabled = true;
263 }
264 #ifdef ASIC_SMOKE_TEST
265 STATIC uart_bus_t g_uart2;
266 static bool g_uart2_enabled = false;
267 STATIC uint8_t g_uart2_rx_buffer[DEBUG_UART_RX_BUFFER_SIZE];
268 #define DEBUG_UART2_RX_BUFFER_SIZE 1
uart2_rx_callback(const void * buf,uint16_t buf_len,bool remaining)269 void uart2_rx_callback(const void *buf, uint16_t buf_len, bool remaining)
270 {
271 UNUSED(remaining);
272 if (!g_uart2_enabled) {
273 return;
274 }
275 uapi_uart_write(CHIP_FIXED_UART_BUS, (const void *)buf, buf_len, 0);
276 }
uart2_init(uint32_t baud_rate)277 void uart2_init(uint32_t baud_rate)
278 {
279 uart_pin_config_t uart_pins;
280 uart_attr_t uart_line_config;
281 uart_buffer_config_t uart_buffer_config;
282
283 g_uart2 = CHIP_FIXED_UART_BUS;
284 // TX configuration
285 uart_pins.tx_pin = CHIP_FIXED_TX_PIN;
286 uart_pins.rts_pin = PIN_NONE;
287
288 // RX configuration
289 uart_pins.rx_pin = CHIP_FIXED_RX_PIN;
290 uart_pins.cts_pin = PIN_NONE;
291
292 uart_line_config.baud_rate = baud_rate;
293 uart_line_config.data_bits = UART_DATA_BIT_8;
294 uart_line_config.parity = UART_PARITY_NONE;
295 uart_line_config.stop_bits = UART_STOP_BIT_1;
296
297 uart_buffer_config.rx_buffer_size = DEBUG_UART2_RX_BUFFER_SIZE;
298 uart_buffer_config.rx_buffer = g_uart2_rx_buffer;
299
300 (void)uapi_uart_init(CHIP_FIXED_UART_BUS, &uart_pins, &uart_line_config, NULL, &uart_buffer_config);
301 uapi_uart_register_rx_callback(CHIP_FIXED_UART_BUS, UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE,
302 DEBUG_UART2_RX_BUFFER_SIZE, uart2_rx_callback);
303
304 g_uart2_enabled = true;
305 }
306 #endif
307
308 #ifdef SW_UART_CHIP_DEFINE
UartPuts(const char * s,uint32_t len,bool is_lock)309 void UartPuts(const char *s, uint32_t len, bool is_lock)
310 {
311 if ((s == NULL) || (strlen(s) == 0)) {
312 return;
313 }
314
315 UNUSED(is_lock);
316 #ifdef SW_UART_DEBUG
317 uapi_uart_write(SW_DEBUG_UART_BUS, (const void *)s, len, 0);
318 #elif defined(TEST_SUITE)
319 test_suite_uart_send(s);
320 #elif defined(SW_RTT_DEBUG)
321 SEGGER_RTT_Write(0, (const char *)s, len);
322 #else
323 UNUSED(s);
324 UNUSED(len);
325 #endif
326 }
327 #endif
328
print_str_inner(const char * fmt,va_list ap)329 static void print_str_inner(const char *fmt, va_list ap)
330 {
331 int32_t len;
332 static char str_buf[UART_TRANS_LEN_MAX] = {0};
333 char *tmp_buf = NULL;
334 uint32_t buflen = UART_TRANS_LEN_MAX;
335
336 tmp_buf = str_buf;
337 len = vsnprintf_s(tmp_buf, buflen, buflen - 1, fmt, ap);
338 if ((len == -1) && (*tmp_buf == '\0')) {
339 /* parameter is illegal or some features in fmt dont support */
340 return;
341 }
342 #ifdef CONFIG_PRINTF_BUFFER_DYNAMIC
343 const char *errmsgmalloc = "print long str, malloc failed!\n";
344 while (len == -1) {
345 /* tmp_buf is not enough */
346 if (buflen != UART_TRANS_LEN_MAX) {
347 osal_kfree(tmp_buf);
348 }
349
350 buflen = buflen << 1;
351 tmp_buf = (char *)osal_kmalloc(buflen, OSAL_GFP_KERNEL);
352 if (tmp_buf == NULL) {
353 uapi_uart_write(SW_DEBUG_UART_BUS, (const uint8_t *)errmsgmalloc, (uint32_t)strlen(errmsgmalloc), 0);
354 return;
355 }
356 len = vsnprintf_s(tmp_buf, buflen, buflen - 1, fmt, ap);
357 if (*tmp_buf == '\0') {
358 /* parameter is illegal or some features in fmt dont support */
359 osal_kfree(tmp_buf);
360 return;
361 }
362 }
363 #endif
364 *(tmp_buf + len) = '\0';
365 uapi_uart_write(SW_DEBUG_UART_BUS, (const uint8_t *)tmp_buf, len, 0);
366 #ifdef CONFIG_PRINTF_BUFFER_DYNAMIC
367 if (buflen != UART_TRANS_LEN_MAX) {
368 osal_kfree(tmp_buf);
369 }
370 #endif
371 }
372
print_str(const char * str,...)373 void print_str(const char *str, ...)
374 {
375 va_list args;
376 if ((str == NULL) || (strlen(str) == 0)) {
377 return;
378 }
379 va_start(args, str);
380 print_str_inner(str, args);
381 va_end(args);
382 }
383
384 #endif
385
386 #ifdef LOG_SUPPORT
387 /** UART Settings. Define these in the C file to avoid pulling in the UART header in the header file. */
388 #define LOG_UART_RX_MAX_BUFFER_SIZE 16
389 static uint8_t g_uart_log_rx_buffer[LOG_UART_RX_MAX_BUFFER_SIZE];
log_uart_port_init(void)390 void log_uart_port_init(void)
391 {
392 uart_pin_config_t log_uart_pins = {
393 .tx_pin = CODELOADER_UART_TX_PIN,
394 .rx_pin = CODELOADER_UART_RX_PIN,
395 .cts_pin = PIN_NONE,
396 .rts_pin = PIN_NONE
397 };
398
399 uart_attr_t uart_line_config = {
400 .baud_rate = CONFIG_LOG_UART_BAUDRATE,
401 .data_bits = UART_DATA_BIT_8,
402 .stop_bits = UART_STOP_BIT_1,
403 .parity = UART_PARITY_NONE
404 };
405 uart_buffer_config_t uart_buffer_config;
406
407 uart_buffer_config.rx_buffer_size = LOG_UART_RX_MAX_BUFFER_SIZE;
408 uart_buffer_config.rx_buffer = g_uart_log_rx_buffer;
409
410 (void)uapi_uart_init(LOG_UART_BUS, &log_uart_pins, &uart_line_config, NULL, &uart_buffer_config);
411
412 #if SYS_DEBUG_MODE_ENABLE == YES
413 uapi_uart_register_rx_callback(LOG_UART_BUS, UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE,
414 LOG_UART_RX_MAX_BUFFER_SIZE, log_uart_rx_callback);
415 #endif
416 }
417 #endif
418
419 #ifdef CONFIG_UART_SUPPORT_PORTTING_IRQ
hal_uart_clear_pending(uart_bus_t uart)420 void hal_uart_clear_pending(uart_bus_t uart)
421 {
422 switch (uart) {
423 #if UART_BUS_MAX_NUMBER > 0
424 case UART_BUS_0:
425 osal_irq_clear(UART_0_IRQN);
426 break;
427 #endif
428 #if UART_BUS_MAX_NUMBER > 1
429 case UART_BUS_1:
430 osal_irq_clear(UART_1_IRQN);
431 break;
432 #endif
433 #if UART_BUS_MAX_NUMBER > 2
434 case UART_BUS_2:
435 osal_irq_clear(UART_2_IRQN);
436 break;
437 #endif
438 #if UART_BUS_MAX_NUMBER > 3
439 case UART_BUS_3:
440 int_clear_pending_irq(UART_3_IRQN);
441 break;
442 #endif
443 default:
444 break;
445 }
446 }
447 #endif
448
449 #if defined(CONFIG_UART_SUPPORT_DMA)
uart_port_get_dma_trans_dest_handshaking(uart_bus_t bus)450 uint8_t uart_port_get_dma_trans_dest_handshaking(uart_bus_t bus)
451 {
452 switch (bus) {
453 case UART_BUS_0:
454 return (uint8_t)HAL_DMA_HANDSHAKING_UART_L_TX;
455 case UART_BUS_1:
456 return (uint8_t)HAL_DMA_HANDSHAKING_UART_H0_TX;
457 case UART_BUS_2:
458 return (uint8_t)HAL_DMA_HANDSHAKING_UART_H1_TX;
459 default:
460 return (uint8_t)HAL_DMA_HANDSHAKING_MAX_NUM;
461 }
462 return 0;
463 }
464
uart_port_get_dma_trans_src_handshaking(uart_bus_t bus)465 uint8_t uart_port_get_dma_trans_src_handshaking(uart_bus_t bus)
466 {
467 switch (bus) {
468 case UART_BUS_0:
469 return (uint8_t)HAL_DMA_HANDSHAKING_UART_L_TX;
470 case UART_BUS_1:
471 return (uint8_t)HAL_DMA_HANDSHAKING_UART_H0_RX;
472 case UART_BUS_2:
473 return (uint8_t)HAL_DMA_HANDSHAKING_UART_H1_RX;
474 default:
475 return (uint8_t)HAL_DMA_HANDSHAKING_MAX_NUM;
476 }
477 return 0;
478 }
479 #endif /* CONFIG_UART_SUPPORT_DMA */
480
uart_porting_lock(uart_bus_t bus)481 uint32_t uart_porting_lock(uart_bus_t bus)
482 {
483 #if !defined(BUILD_NOOSAL)
484 if ((g_uart_support_mutex[bus] == true) && (osKernelGetState() == osKernelRunning) &&
485 (osal_in_interrupt() == 0)) {
486 return (uint32_t)osal_mutex_lock_timeout(&g_uart_tx_mutex[bus], OSAL_MUTEX_WAIT_FOREVER);
487 } else {
488 return 0;
489 }
490 #else
491 unused(bus);
492 return osal_irq_lock();
493 #endif
494 }
495
uart_porting_unlock(uart_bus_t bus,uint32_t irq_sts)496 void uart_porting_unlock(uart_bus_t bus, uint32_t irq_sts)
497 {
498 #if !defined(BUILD_NOOSAL)
499 unused(irq_sts);
500 if ((g_uart_support_mutex[bus] == true) && (osKernelGetState() == osKernelRunning) &&
501 (osal_in_interrupt() == 0)) {
502 osal_mutex_unlock(&g_uart_tx_mutex[bus]);
503 }
504 #else
505 unused(bus);
506 osal_irq_restore(irq_sts);
507 #endif
508 }
509