1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-3-08 GuEe-GUI the first version
9 */
10
11 #include <rthw.h>
12 #include <rtthread.h>
13 #include <rtdevice.h>
14
15 #include <board.h>
16
17 /*
18 * The Synopsys DesignWare 8250 has an extra feature whereby it detects if the
19 * LCR is written whilst busy. If it is, then a busy detect interrupt is
20 * raised, the LCR needs to be rewritten and the uart status register read.
21 */
22
23 #define UART_RX 0 /* In: Receive buffer */
24 #define UART_TX 0 /* Out: Transmit buffer */
25
26 #define UART_DLL 0 /* Out: Divisor Latch Low */
27 #define UART_DLM 1 /* Out: Divisor Latch High */
28
29 #define UART_IER 1 /* Out: Interrupt Enable Register */
30 #define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
31
32 #define UART_SSR 0x22 /* In: Software Reset Register */
33 #define UART_USR 0x1f /* UART Status Register */
34
35 #define UART_LCR 3 /* Out: Line Control Register */
36 #define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
37 #define UART_LCR_SPAR 0x20 /* Stick parity (?) */
38 #define UART_LCR_PARITY 0x8 /* Parity Enable */
39 #define UART_LCR_STOP 0x4 /* Stop bits: 0=1 bit, 1=2 bits */
40 #define UART_LCR_WLEN8 0x3 /* Wordlength: 8 bits */
41
42 #define UART_MCR 4 /* Out: Modem Control Register */
43 #define UART_MCR_RTS 0x02 /* RTS complement */
44
45 #define UART_LSR 5 /* In: Line Status Register */
46 #define UART_LSR_BI 0x10 /* Break interrupt indicator */
47 #define UART_LSR_DR 0x01 /* Receiver data ready */
48
49 #define UART_IIR 2 /* In: Interrupt ID Register */
50 #define UART_IIR_NO_INT 0x01 /* No interrupts pending */
51 #define UART_IIR_BUSY 0x07 /* DesignWare APB Busy Detect */
52 #define UART_IIR_RX_TIMEOUT 0x0c /* OMAP RX Timeout interrupt */
53
54 #define UART_FCR 2 /* Out: FIFO Control Register */
55 #define UART_FCR_EN_FIFO 0x01 /* Enable the FIFO */
56 #define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
57 #define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
58
59 #define UART_REG_SHIFT 0x2 /* Register Shift*/
60 #define UART_INPUT_CLK 24000000
61
62 struct hw_uart_device
63 {
64 rt_ubase_t hw_base;
65 rt_uint32_t irqno;
66 #ifdef RT_USING_SMP
67 struct rt_spinlock spinlock;
68 #endif
69 };
70
71 #define BSP_DEFINE_UART_DEVICE(no) \
72 static struct hw_uart_device _uart##no##_device = \
73 { \
74 UART##no##_MMIO_BASE, \
75 UART##no##_IRQ \
76 }; \
77 static struct rt_serial_device _serial##no;
78
79 #ifdef RT_USING_UART0
80 BSP_DEFINE_UART_DEVICE(0);
81 #endif
82
83 #ifdef RT_USING_UART1
84 BSP_DEFINE_UART_DEVICE(1);
85 #endif
86
87 #ifdef RT_USING_UART2
88 BSP_DEFINE_UART_DEVICE(2);
89 #endif
90
91 #ifdef RT_USING_UART3
92 BSP_DEFINE_UART_DEVICE(3);
93 #endif
94
95 #ifdef RT_USING_UART4
96 BSP_DEFINE_UART_DEVICE(4);
97 #endif
98
99 #ifdef RT_USING_UART5
100 BSP_DEFINE_UART_DEVICE(5);
101 #endif
102
103 #ifdef RT_USING_UART6
104 BSP_DEFINE_UART_DEVICE(6);
105 #endif
106
107 #ifdef RT_USING_UART7
108 BSP_DEFINE_UART_DEVICE(7);
109 #endif
110
111 #ifdef RT_USING_UART8
112 BSP_DEFINE_UART_DEVICE(8);
113 #endif
114
115 #ifdef RT_USING_UART9
116 BSP_DEFINE_UART_DEVICE(9);
117 #endif
118
dw8250_read32(rt_ubase_t addr,rt_ubase_t offset)119 rt_inline rt_uint32_t dw8250_read32(rt_ubase_t addr, rt_ubase_t offset)
120 {
121 return *((volatile rt_uint32_t *)(addr + (offset << UART_REG_SHIFT)));
122 }
123
dw8250_write32(rt_ubase_t addr,rt_ubase_t offset,rt_uint32_t value)124 rt_inline void dw8250_write32(rt_ubase_t addr, rt_ubase_t offset, rt_uint32_t value)
125 {
126 *((volatile rt_uint32_t *)(addr + (offset << UART_REG_SHIFT))) = value;
127
128 if (offset == UART_LCR)
129 {
130 int tries = 1000;
131
132 /* Make sure LCR write wasn't ignored */
133 while (tries--)
134 {
135 unsigned int lcr = dw8250_read32(addr, UART_LCR);
136
137 if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
138 {
139 return;
140 }
141
142 dw8250_write32(addr, UART_FCR, UART_FCR_EN_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
143 dw8250_read32(addr, UART_RX);
144
145 *((volatile rt_uint32_t *)(addr + (offset << UART_REG_SHIFT))) = value;
146 }
147 }
148 }
149
dw8250_uart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)150 static rt_err_t dw8250_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
151 {
152 rt_base_t base, rate;
153 struct hw_uart_device *uart;
154
155 RT_ASSERT(serial != RT_NULL);
156 uart = (struct hw_uart_device *)serial->parent.user_data;
157 base = uart->hw_base;
158
159 #ifdef RT_USING_SMP
160 rt_spin_lock_init(&uart->spinlock);
161 #endif
162
163 /* Resset UART */
164 dw8250_write32(base, UART_SSR, 1);
165 dw8250_write32(base, UART_SSR, 0);
166
167 dw8250_write32(base, UART_IER, !UART_IER_RDI);
168 dw8250_write32(base, UART_FCR, UART_FCR_EN_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
169
170 /* Disable flow ctrl */
171 dw8250_write32(base, UART_MCR, 0);
172 /* Clear RTS */
173 dw8250_write32(base, UART_MCR, dw8250_read32(base, UART_MCR) | UART_MCR_RTS);
174
175 rate = UART_INPUT_CLK / 16 / serial->config.baud_rate;
176
177 /* Enable access DLL & DLH */
178 dw8250_write32(base, UART_LCR, dw8250_read32(base, UART_LCR) | UART_LCR_DLAB);
179 dw8250_write32(base, UART_DLL, (rate & 0xff));
180 dw8250_write32(base, UART_DLM, (rate & 0xff00) >> 8);
181 /* Clear DLAB bit */
182 dw8250_write32(base, UART_LCR, dw8250_read32(base, UART_LCR) & (~UART_LCR_DLAB));
183
184 dw8250_write32(base, UART_LCR, (dw8250_read32(base, UART_LCR) & (~UART_LCR_WLEN8)) | UART_LCR_WLEN8);
185 dw8250_write32(base, UART_LCR, dw8250_read32(base, UART_LCR) & (~UART_LCR_STOP));
186 dw8250_write32(base, UART_LCR, dw8250_read32(base, UART_LCR) & (~UART_LCR_PARITY));
187
188 dw8250_write32(base, UART_IER, UART_IER_RDI);
189
190 return RT_EOK;
191 }
192
dw8250_uart_control(struct rt_serial_device * serial,int cmd,void * arg)193 static rt_err_t dw8250_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
194 {
195 struct hw_uart_device *uart;
196
197 RT_ASSERT(serial != RT_NULL);
198 uart = (struct hw_uart_device *)serial->parent.user_data;
199
200 switch (cmd)
201 {
202 case RT_DEVICE_CTRL_CLR_INT:
203 /* Disable rx irq */
204 dw8250_write32(uart->hw_base, UART_IER, !UART_IER_RDI);
205 rt_hw_interrupt_mask(uart->irqno);
206 break;
207
208 case RT_DEVICE_CTRL_SET_INT:
209 /* Enable rx irq */
210 dw8250_write32(uart->hw_base, UART_IER, UART_IER_RDI);
211 rt_hw_interrupt_umask(uart->irqno);
212 break;
213 }
214
215 return RT_EOK;
216 }
217
dw8250_uart_putc(struct rt_serial_device * serial,char c)218 static int dw8250_uart_putc(struct rt_serial_device *serial, char c)
219 {
220 rt_base_t base;
221 struct hw_uart_device *uart;
222
223 RT_ASSERT(serial != RT_NULL);
224 uart = (struct hw_uart_device *)serial->parent.user_data;
225 base = uart->hw_base;
226
227 while ((dw8250_read32(base, UART_USR) & 0x2) == 0)
228 {
229 }
230
231 dw8250_write32(base, UART_TX, c);
232
233 return 1;
234 }
235
dw8250_uart_getc(struct rt_serial_device * serial)236 static int dw8250_uart_getc(struct rt_serial_device *serial)
237 {
238 int ch = -1;
239 rt_base_t base;
240 struct hw_uart_device *uart;
241
242 RT_ASSERT(serial != RT_NULL);
243 uart = (struct hw_uart_device *)serial->parent.user_data;
244 base = uart->hw_base;
245
246 if ((dw8250_read32(base, UART_LSR) & 0x1))
247 {
248 ch = dw8250_read32(base, UART_RX) & 0xff;
249 }
250
251 return ch;
252 }
253
254 static const struct rt_uart_ops _uart_ops =
255 {
256 dw8250_uart_configure,
257 dw8250_uart_control,
258 dw8250_uart_putc,
259 dw8250_uart_getc,
260 };
261
rt_hw_uart_isr(int irqno,void * param)262 static void rt_hw_uart_isr(int irqno, void *param)
263 {
264 unsigned int iir, status;
265 struct rt_serial_device *serial = (struct rt_serial_device *)param;
266 struct hw_uart_device *uart = (struct hw_uart_device *)serial->parent.user_data;
267
268 iir = dw8250_read32(uart->hw_base, UART_IIR);
269
270 /* If don't do this in non-DMA mode then the "RX TIMEOUT" interrupt will fire forever. */
271 if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT)
272 {
273 #ifdef RT_USING_SMP
274 rt_base_t level = rt_spin_lock_irqsave(&uart->spinlock);
275 #endif
276
277 status = dw8250_read32(uart->hw_base, UART_LSR);
278
279 if (!(status & (UART_LSR_DR | UART_LSR_BI)))
280 {
281 dw8250_read32(uart->hw_base, UART_RX);
282 }
283
284 #ifdef RT_USING_SMP
285 rt_spin_unlock_irqrestore(&uart->spinlock, level);
286 #endif
287 }
288
289 if (!(iir & UART_IIR_NO_INT))
290 {
291 rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
292 }
293
294 if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY)
295 {
296 /* Clear the USR */
297 dw8250_read32(uart->hw_base, UART_USR);
298
299 return;
300 }
301 }
302
rt_hw_uart_init(void)303 int rt_hw_uart_init(void)
304 {
305 rt_uint32_t value;
306 struct hw_uart_device* uart;
307 struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
308 RT_UNUSED(value);
309
310 config.baud_rate = 1500000;
311
312 #define BSP_INSTALL_UART_DEVICE(no) \
313 uart = &_uart##no##_device; \
314 _serial##no.ops = &_uart_ops; \
315 _serial##no.config = config; \
316 rt_hw_serial_register(&_serial##no, "uart" #no, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); \
317 rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial##no, "uart" #no);
318
319 #ifdef RT_USING_UART0
320 BSP_INSTALL_UART_DEVICE(0);
321 #endif
322
323 #ifdef RT_USING_UART1
324 BSP_INSTALL_UART_DEVICE(1);
325 #endif
326
327 #ifdef RT_USING_UART2
328 BSP_INSTALL_UART_DEVICE(2);
329 #endif
330
331 #ifdef RT_USING_UART3
332 BSP_INSTALL_UART_DEVICE(3);
333 #endif
334
335 #ifdef RT_USING_UART4
336 HWREG32(CRU_BASE + 0x370) = 0xFFFF0000 | (0x600) |(HWREG32(CRU_BASE + 0x370) & 0xF0FF);
337 value = HWREG32(0xFDC60000 + 0x48);
338 value &= ~((7 << 8) | (7 << 4));
339 value |= 0xFFFF0000 | (4 << 8) | (4 << 4);
340 HWREG32(0xFDC60000 + 0x48) = value;
341 HWREG32(0xFDC60000 + 0x30C) = 0xFFFF0000 | (1 << 14) | HWREG32(0xFDC60000 + 0x30C);
342 BSP_INSTALL_UART_DEVICE(4);
343 #endif
344
345 #ifdef RT_USING_UART5
346 BSP_INSTALL_UART_DEVICE(5);
347 #endif
348
349 #ifdef RT_USING_UART6
350 BSP_INSTALL_UART_DEVICE(6);
351 #endif
352
353 #ifdef RT_USING_UART7
354 BSP_INSTALL_UART_DEVICE(7);
355 #endif
356
357 #ifdef RT_USING_UART8
358 BSP_INSTALL_UART_DEVICE(8);
359 #endif
360
361 #ifdef RT_USING_UART9
362 BSP_INSTALL_UART_DEVICE(9);
363 #endif
364
365 return 0;
366 }
367