1 /*
2 * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2009-12-22
13 * Description: UniProton hi3093 demo
14 */
15 #include "uart_core.h"
16 #include "common.h"
17
18 #define UART_REG_READ(addr) (*(volatile U32 *)(((uintptr_t)addr)))
19 #define UART_REG_WRITE(value, addr) (*(volatile U32 *)((uintptr_t)addr) = (U32)value)
20
21 /* Get UART register base address */
uart_core_base_addr(S32 uartno,U32 * reg_base)22 static S32 uart_core_base_addr(S32 uartno, U32 *reg_base)
23 {
24 unsigned long reg_bases[] = {
25 UART0_REG_BASE,
26 UART1_REG_BASE,
27 UART2_REG_BASE,
28 UART3_REG_BASE,
29 UART4_REG_BASE
30 };
31
32 if (uartno >= MAX_UART_NUM || uartno < 0) {
33 return -1;
34 }
35
36 *reg_base = reg_bases[uartno];
37
38 return OS_OK;
39 }
40
uart_reg_read(S32 uartno,U32 offset,U32 * val)41 S32 uart_reg_read(S32 uartno, U32 offset, U32 *val)
42 {
43 S32 ret;
44 U32 reg_base = 0x0;
45
46 ret = uart_core_base_addr(uartno, ®_base);
47 if (ret) {
48 return ret;
49 }
50
51 *val = UART_REG_READ((unsigned long)(reg_base + offset));
52 return OS_OK;
53 }
54
uart_reg_write(S32 uartno,U32 offset,U32 val)55 void uart_reg_write(S32 uartno, U32 offset, U32 val)
56 {
57 S32 ret;
58 U32 reg_base = 0x0;
59
60 ret = uart_core_base_addr(uartno, ®_base);
61 if (ret) {
62 return;
63 }
64
65 UART_REG_WRITE(val, (unsigned long)(reg_base + offset));
66 return;
67 }
68
uart_set_lcr_dlab(S32 uartno,S32 dlab_sel)69 void uart_set_lcr_dlab(S32 uartno, S32 dlab_sel)
70 {
71 S32 ret;
72 U32 lcr = 0;
73
74 ret = uart_reg_read(uartno, DW_UART_LCR, &lcr);
75 if (ret) {
76 return;
77 }
78
79 if (dlab_sel) {
80 lcr |= DW_UART_DLAB;
81 } else {
82 lcr &= ~DW_UART_DLAB;
83 }
84
85 uart_reg_write(uartno, DW_UART_LCR, lcr);
86 return;
87 }
88
uart_set_dll_dlh(S32 uartno,U32 dll,U32 dlh)89 void uart_set_dll_dlh(S32 uartno, U32 dll, U32 dlh)
90 {
91 /* Enable DLL/DLH/FCR access */
92 uart_set_lcr_dlab(uartno, 1);
93 uart_reg_write(uartno, DW_UART_DLL, dll);
94 uart_reg_write(uartno, DW_UART_DLH, dlh);
95 uart_set_lcr_dlab(uartno, 0);
96 return;
97 }
98
uart_get_dll_dlh(S32 uartno,U32 * dll,U32 * dlh)99 void uart_get_dll_dlh(S32 uartno, U32 *dll, U32 *dlh)
100 {
101 /* Enable DLL/DLH/FCR access */
102 uart_set_lcr_dlab(uartno, 1);
103 uart_reg_read(uartno, DW_UART_DLL, dll);
104 uart_reg_read(uartno, DW_UART_DLH, dlh);
105 uart_set_lcr_dlab(uartno, 0);
106 return;
107 }
108
uart_set_fifo_ctrl(S32 uartno,U32 fifo_ctrl)109 void uart_set_fifo_ctrl(S32 uartno, U32 fifo_ctrl)
110 {
111 /* Enable DLL/DLH/FCR access */
112 uart_set_lcr_dlab(uartno, 1);
113 uart_reg_write(uartno, DW_UART_FCR, fifo_ctrl);
114 uart_set_lcr_dlab(uartno, 0);
115 return;
116 }
117
uart_set_lcr(S32 uartno,U32 lcr)118 void uart_set_lcr(S32 uartno, U32 lcr)
119 {
120 uart_reg_write(uartno, DW_UART_LCR, lcr);
121 return;
122 }
123
124 /* value: 0:禁止;1:使能 */
uart_set_irq_enable(S32 uartno,U32 value)125 void uart_set_irq_enable(S32 uartno, U32 value)
126 {
127 uart_reg_write(uartno, ELSI, value);
128 return;
129 }
130
uart_is_txfifo_full(S32 uartno)131 S32 uart_is_txfifo_full(S32 uartno)
132 {
133 S32 ret;
134 U32 usr = 0;
135
136 ret = uart_reg_read(uartno, DW_UART_USR, &usr);
137 if (ret) {
138 return OS_OK;
139 }
140
141 return (usr & DW_XFIFO_NOT_FULL) ? 0 : 1;
142 }
143
uart_is_rx_ready(S32 uartno)144 S32 uart_is_rx_ready(S32 uartno)
145 {
146 U32 lsr = 0;
147
148 (void)uart_reg_read(uartno, DW_UART_LSR, &lsr);
149 return (lsr & DW_UART_LSR_DDR) ? 1 : 0;
150 }
151
uart_tx_char(S32 uartno,const S8 c)152 void uart_tx_char(S32 uartno, const S8 c)
153 {
154 uart_reg_write(uartno, DW_UART_THR, (U32)(U8)c);
155 return;
156 }
157
uart_rx_char(S32 uartno,S8 * c)158 void uart_rx_char(S32 uartno, S8 *c)
159 {
160 U32 rbr = 0;
161
162 (void)uart_reg_read(uartno, DW_UART_RBR, &rbr);
163 *c = (S8)(rbr & 0xFF);
164
165 return;
166 }
167
uart_wait4idle(S32 uartno,U32 timeout)168 S32 uart_wait4idle(S32 uartno, U32 timeout)
169 {
170 U32 usr = 0;
171
172 while (timeout) {
173 (void)uart_reg_read(uartno, DW_UART_USR, &usr);
174 if ((usr & (DW_UART_BUSY)) == 0) {
175 return OS_OK;
176 }
177
178 timeout--;
179 }
180
181 return -1;
182 }
183