1 /*
2 * Copyright (c) 2022 Nanjing Xiaoxiongpai Intelligent Technology Co., Ltd.
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 "stm32mp1_uart_hw.h"
17
18 #include "los_magickey.h"
19 #include "console.h"
20
21 // offset
22 #define USART_CR1 (0x00)
23 #define USART_CR2 (0x04)
24 #define USART_CR3 (0x08)
25 #define USART_BRR (0x0C)
26 #define USART_GTPR (0x10)
27 #define USART_RTOR (0x14)
28 #define USART_RQR (0x18)
29 #define USART_ISR (0x1C)
30 #define USART_ICR (0x20)
31 #define USART_RDR (0x24)
32 #define USART_TDR (0x28)
33 #define USART_PRESC (0x2C)
34
35 #define USART_CR1_EN BIT(0) // 串口使能
36 #define USART_CR1_RE BIT(2) // 串口接收使能
37 #define USART_CR1_TE BIT(3) // 串口发送使能
38 #define USART_CR1_RXNEIE BIT(5) // 串口接收中断使能
39 #define USART_CR1_FIFOEN BIT(29) // fifo模式使能
40
41 #define USART_ISR_TXE BIT(7) // 该位为 1 表示可以写
42 #define USART_ISR_RXNE BIT(5) // 该位为 1 表示可读
43
44 /* Parity control enable */
45 #define USART_CR1_PCE BIT(10) // 串口校验使能
46 #define USART_CR1_PS BIT(9)
47
48 /* word length */
49 #define USART_CR1_M0 BIT(12)
50 #define USART_CR1_M1 BIT(28)
51 #define USART_CR1_WL_MASK (USART_CR1_M0 | USART_CR1_M1)
52 #define USART_CR1_WL_8B (0)
53 #define USART_CR1_WL_9B (USART_CR1_M0)
54 #define USART_CR1_WL_7B (USART_CR1_M1)
55
56 /* stop bit */
57 #define USART_CR2_STOP_OFFSET (12)
58 #define USART_CR2_STOP_MASK ((0x3) << USART_CR2_STOP_OFFSET)
59 #define USART_CR2_STOP_1P ((0x0) << USART_CR2_STOP_OFFSET)
60 #define USART_CR2_STOP_P5 ((0x1) << USART_CR2_STOP_OFFSET)
61 #define USART_CR2_STOP_2P ((0x2) << USART_CR2_STOP_OFFSET)
62 #define USART_CR2_STOP_1P5 ((0x3) << USART_CR2_STOP_OFFSET)
63
RegRead(void volatile * base,uint32_t reg)64 static inline uint32_t RegRead(void volatile *base, uint32_t reg)
65 {
66 return OSAL_READL((uintptr_t)base + reg);
67 }
68
RegWrite(void volatile * base,uint32_t reg,uint32_t val)69 static inline void RegWrite(void volatile *base, uint32_t reg, uint32_t val)
70 {
71 OSAL_WRITEL(val, (uintptr_t)base + reg);
72 }
73
Mp1xxUartDump(struct Mp1xxUart * uart)74 void Mp1xxUartDump(struct Mp1xxUart *uart)
75 {
76 #ifdef STM32MP1_UART_DEBUG
77 dprintf("-------------------------------------\r\n");
78 dprintf("USART_CR1 : %#x.\r\n", RegRead(uart->base, USART_CR1));
79 dprintf("USART_CR2 : %#x.\r\n", RegRead(uart->base, USART_CR2));
80 dprintf("USART_CR3 : %#x.\r\n", RegRead(uart->base, USART_CR3));
81 dprintf("USART_BRR : %#x.\r\n", RegRead(uart->base, USART_BRR));
82 dprintf("USART_GTPR : %#x.\r\n", RegRead(uart->base, USART_GTPR));
83 dprintf("USART_RTOR : %#x.\r\n", RegRead(uart->base, USART_RTOR));
84 dprintf("USART_ISR : %#x.\r\n", RegRead(uart->base, USART_ISR));
85 dprintf("USART_ICR : %#x.\r\n", RegRead(uart->base, USART_ICR));
86 dprintf("USART_RDR : %#x.\r\n", RegRead(uart->base, USART_RDR));
87 dprintf("USART_TDR : %#x.\r\n", RegRead(uart->base, USART_TDR));
88 dprintf("USART_PRESC : %#x.\r\n", RegRead(uart->base, USART_PRESC));
89 dprintf("-------------------------------------\r\n");
90 #else
91 (void)uart;
92 #endif
93 }
94
Mp1xxUartHwRxEnable(struct Mp1xxUart * uart,int enable)95 int32_t Mp1xxUartHwRxEnable(struct Mp1xxUart *uart, int enable)
96 {
97 uint32_t val;
98
99 val = RegRead(uart->base, USART_CR1);
100
101 if (enable) {
102 val |= USART_CR1_RXNEIE;
103 } else {
104 val &= ~USART_CR1_RXNEIE;
105 }
106
107 RegWrite(uart->base, USART_CR1, val);
108
109 return 0;
110 }
111
Mp1xxUartHwPutc(void * base,char c)112 void Mp1xxUartHwPutc(void *base, char c)
113 {
114 while ((RegRead(base, USART_ISR) & USART_ISR_TXE) == 0) {};
115 RegWrite(base, USART_TDR, c);
116 }
117
Mp1xxUartHwPuts(void * base,char * s,uint32_t len)118 void Mp1xxUartHwPuts(void *base, char *s, uint32_t len)
119 {
120 uint32_t i;
121
122 for (i = 0; i < len; i++) {
123 if (*(s + i) == '\n') {
124 Mp1xxUartHwPutc(base, '\r');
125 }
126 Mp1xxUartHwPutc(base, *(s + i));
127 }
128 }
129
Mp1xxUartHwGetIsr(struct Mp1xxUart * uart)130 uint32_t Mp1xxUartHwGetIsr(struct Mp1xxUart *uart)
131 {
132 return RegRead(uart->base, USART_ISR);
133 }
134
135 // enable uart, and enable tx/rx mode
Mp1xxUartHwEnable(struct Mp1xxUart * uart,int enable)136 int32_t Mp1xxUartHwEnable(struct Mp1xxUart *uart, int enable)
137 {
138 uint32_t val;
139
140 val = RegRead(uart->base, USART_CR1);
141 val &= ~(USART_CR1_EN | USART_CR1_RE | USART_CR1_TE);
142
143 if (enable) {
144 val |= (USART_CR1_EN | USART_CR1_RE | USART_CR1_TE);
145 } else {
146 val &= ~(USART_CR1_EN | USART_CR1_RE | USART_CR1_TE);
147 }
148
149 RegWrite(uart->base, USART_CR1, val);
150
151 return 0;
152 }
153
Mp1xxUartHwFifoEnable(struct Mp1xxUart * uart,int enable)154 int32_t Mp1xxUartHwFifoEnable(struct Mp1xxUart *uart, int enable)
155 {
156 uint32_t val;
157
158 val = RegRead(uart->base, USART_CR1);
159
160 if (enable) {
161 val |= USART_CR1_FIFOEN; // fifo mode enable
162 } else {
163 val &= ~USART_CR1_FIFOEN; // fifo mode disable
164 }
165
166 RegWrite(uart->base, USART_CR1, val);
167
168 return 0;
169 }
170
171 // set data bits
Mp1xxUartHwDataBits(struct Mp1xxUart * uart,uint32_t bits)172 int32_t Mp1xxUartHwDataBits(struct Mp1xxUart *uart, uint32_t bits)
173 {
174 uint32_t val;
175
176 val = RegRead(uart->base, USART_CR1);
177
178 val &= ~USART_CR1_WL_MASK;
179
180 switch (bits) {
181 case UART_HW_DATABIT_8:
182 val |= USART_CR1_WL_8B;
183 break;
184 case UART_HW_DATABIT_7:
185 val |= USART_CR1_WL_7B;
186 break;
187 default:
188 HDF_LOGE("only support 8b.\r\n");
189 break;
190 }
191
192 RegWrite(uart->base, USART_CR1, val);
193
194 return 0;
195 }
196
Mp1xxUartHwStopBits(struct Mp1xxUart * uart,uint32_t bits)197 int32_t Mp1xxUartHwStopBits(struct Mp1xxUart *uart, uint32_t bits)
198 {
199 uint32_t val;
200
201 val = RegRead(uart->base, USART_CR2);
202
203 val &= ~USART_CR2_STOP_MASK;
204
205 if (bits == UART_HW_STOPBIT_1P5) {
206 val |= USART_CR2_STOP_1P5;
207 } else if (bits == UART_HW_STOPBIT_2) {
208 val |= USART_CR2_STOP_2P;
209 }
210
211 RegWrite(uart->base, USART_CR2, val);
212
213 return 0;
214 }
215
Mp1xxUartHwParity(struct Mp1xxUart * uart,uint32_t parity)216 int32_t Mp1xxUartHwParity(struct Mp1xxUart *uart, uint32_t parity)
217 {
218 uint32_t val;
219 val = RegRead(uart->base, USART_CR1);
220
221 val &= ~(USART_CR1_PCE | USART_CR1_PS | USART_CR1_M1 | USART_CR1_M0);
222
223 switch (parity) {
224 case UART_HW_PARITY_NONE:
225 break;
226
227 // if enable parity, use 9 bit mode
228 case UART_HW_PARITY_ODD:
229 val |= (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0);
230 break;
231 case UART_HW_PARITY_EVEN:
232 val |= (USART_CR1_PCE | USART_CR1_M0);
233 break;
234 default:
235 break;
236 }
237
238 RegWrite(uart->base, USART_CR1, val);
239
240 return 0;
241 }
242
Mp1xxUartHwBaudrate(struct Mp1xxUart * uart,uint32_t baudrate)243 int32_t Mp1xxUartHwBaudrate(struct Mp1xxUart *uart, uint32_t baudrate)
244 {
245 uint32_t val;
246 uint32_t sorce_rate = uart->clock_rate;
247
248 val = (sorce_rate + baudrate - 1) / baudrate;
249 RegWrite(uart->base, USART_BRR, val);
250
251 return 0;
252 }
253
254 #define FIFO_SIZE (128)
Mp1xxUartIrqHandler(uint32_t irq,void * data)255 uint32_t Mp1xxUartIrqHandler(uint32_t irq, void *data)
256 {
257 (void)irq;
258
259 unsigned char ch = 0;
260 char buf[FIFO_SIZE];
261 uint32_t count = 0;
262 int max_count = FIFO_SIZE;
263
264 struct Mp1xxUart *uart = (struct Mp1xxUart *)data;
265 struct Mp1xxUartRxCtl *rx_ctl = &(uart->rx_ctl);
266
267 if (Mp1xxUartHwGetIsr(uart) & USART_ISR_RXNE) {
268 do {
269 // read data from RDR
270 ch = RegRead(uart->base, USART_RDR);
271
272 // add data to buffer
273 buf[count++] = (char)ch;
274
275 if (CheckMagicKey(buf[count - 1], CONSOLE_SERIAL)) {
276 goto end;
277 }
278 } while ((Mp1xxUartHwGetIsr(uart) & USART_ISR_RXNE) && (max_count-- > 0));
279
280 if (rx_ctl->stm32mp1_uart_recv_hook) {
281 rx_ctl->stm32mp1_uart_recv_hook(uart, buf, count);
282 }
283 }
284
285 end:
286 return 0;
287 }
288