1 /*
2 * Copyright (C) 2017-2024 Alibaba Group Holding Limited
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 /******************************************************************************
20 * @file dw_uart_ll.c
21 * @brief dw uart ll driver
22 * @version V1.0
23 * @date 18. December 2024
24 ******************************************************************************/
25 #include <dw_uart_ll.h>
26
dw_uart_wait_idle(dw_uart_regs_t * uart_base)27 int32_t dw_uart_wait_idle(dw_uart_regs_t *uart_base)
28 {
29 uint32_t timecount = 0U;
30 int32_t ret = 0;
31
32 while ((uart_base->USR & DW_UART_USR_BUSY_SET) && (timecount < UART_BUSY_TIMEOUT)) {
33 timecount++;
34 }
35
36 if (timecount >= UART_BUSY_TIMEOUT) {
37 ret = -1;
38 }
39
40 return ret;
41 }
42
dw_uart_wait_timeout(dw_uart_regs_t * uart_base)43 int32_t dw_uart_wait_timeout(dw_uart_regs_t *uart_base)
44 {
45 uint32_t timecount = 0U;
46 int32_t ret = 0;
47
48 while ((uart_base->LSR & 0x81U) || (uart_base->USR & 0x1U)) {
49 uart_base->LSR;
50 uart_base->RBR;
51 timecount++;
52
53 if (timecount >= UART_BUSY_TIMEOUT) {
54 ret = -1;
55 break;
56 }
57 }
58
59 if (ret == 0) {
60 ret = dw_uart_wait_idle(uart_base);
61 }
62
63 return ret;
64 }
65
dw_uart_config_baudrate(dw_uart_regs_t * uart_base,uint32_t baud,uint32_t uart_freq)66 int32_t dw_uart_config_baudrate(dw_uart_regs_t *uart_base, uint32_t baud, uint32_t uart_freq)
67 {
68 uint32_t divisor;
69 int32_t ret = 0;
70 ret = dw_uart_wait_timeout(uart_base);
71
72 if (ret == 0) {
73 if ((uart_freq / 16) % baud >= (baud / 2))
74 divisor = (uart_freq / 16) / baud + 1;
75 else
76 divisor = (uart_freq / 16) / baud;
77
78 uart_base->LCR |= DW_UART_LCR_DLAB_EN;
79
80 /* DLL and DLH is lower 8-bits and higher 8-bits of divisor.*/
81 uart_base->DLH = (divisor >> 8U) & 0xFFU;
82 uart_base->DLL = divisor & 0xFFU;
83 /*
84 * The DLAB must be cleared after the baudrate is setted
85 * to access other registers.
86 */
87 uart_base->LCR &= (~DW_UART_LCR_DLAB_EN);
88 }
89
90 return ret;
91 }
92
dw_uart_config_stop_bits(dw_uart_regs_t * uart_base,uint32_t stop_bits)93 int32_t dw_uart_config_stop_bits(dw_uart_regs_t *uart_base, uint32_t stop_bits)
94 {
95 int32_t ret;
96 ret = dw_uart_wait_timeout(uart_base);
97
98 if (ret == 0) {
99
100 //when data length is 5 bits, use dw_uart_config_stop_bits_2 will be 1.5 stop bits
101 if (stop_bits == 1U) {
102 dw_uart_config_stop_bits_1(uart_base);
103 } else if (stop_bits == 2U) {
104 dw_uart_config_stop_bits_2(uart_base);
105 }
106 }
107
108 //FIXME: no console output sometimes
109 mdelay(1);
110
111 return ret;
112 }
113
dw_uart_config_parity_none(dw_uart_regs_t * uart_base)114 int32_t dw_uart_config_parity_none(dw_uart_regs_t *uart_base)
115 {
116 int32_t ret;
117 ret = dw_uart_wait_timeout(uart_base);
118
119 if (ret == 0) {
120 uart_base->LCR &= (~DW_UART_LCR_PEN_EN);
121 }
122
123 return ret;
124 }
125
dw_uart_config_parity_odd(dw_uart_regs_t * uart_base)126 int32_t dw_uart_config_parity_odd(dw_uart_regs_t *uart_base)
127 {
128 int32_t ret;
129
130 ret = dw_uart_wait_timeout(uart_base);
131
132 if (ret == 0) {
133 uart_base->LCR |= DW_UART_LCR_PEN_EN;
134 uart_base->LCR &= ~(DW_UART_LCR_EPS_EN);
135 }
136
137 return ret;
138 }
139
dw_uart_config_parity_even(dw_uart_regs_t * uart_base)140 int32_t dw_uart_config_parity_even(dw_uart_regs_t *uart_base)
141 {
142 int32_t ret;
143
144 ret = dw_uart_wait_timeout(uart_base);
145
146 if (ret == 0) {
147 uart_base->LCR |= DW_UART_LCR_PEN_EN;
148 uart_base->LCR |= DW_UART_LCR_EPS_EN;
149 }
150
151 return ret;
152 }
153
dw_uart_config_data_bits(dw_uart_regs_t * uart_base,uint32_t data_bits)154 int32_t dw_uart_config_data_bits(dw_uart_regs_t *uart_base, uint32_t data_bits)
155 {
156 int32_t ret;
157
158 ret = dw_uart_wait_timeout(uart_base);
159
160 uart_base->LCR &= 0xFCU;
161 uart_base->LCR |= (data_bits - 5U);
162
163 return ret;
164 }
165