1 /*
2  * Copyright (c) 2006-2025 RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date         Author      Notes
8  * 2013-03-30   Bernard     the first version
9  * 2025-04-08   Hydevcode   second version
10  *
11  */
12 #include <rtthread.h>
13 #include <rtdevice.h>
14 #include <rtdbg.h>
15 
16 #include "drv_uart.h"
17 #include "board.h"
18 #include "mmu.h"
19 
20 
21 #ifdef RT_USING_SERIAL_V1
22 
23 struct hw_uart_device
24 {
25     rt_uint32_t hw_base;
26     rt_uint32_t irqno;
27     struct rt_serial_device *serial;
28     char *device_name;
29 };
30 
31 #define UART_DR(base)   __REG32(base + 0x00)
32 #define UART_FR(base)   __REG32(base + 0x18)
33 #define UART_CR(base)   __REG32(base + 0x30)
34 #define UART_IMSC(base) __REG32(base + 0x38)
35 #define UART_ICR(base)  __REG32(base + 0x44)
36 
37 #define UARTFR_RXFE     0x10
38 #define UARTFR_TXFF     0x20
39 #define UARTIMSC_RXIM   0x10
40 #define UARTIMSC_TXIM   0x20
41 #define UARTICR_RXIC    0x10
42 #define UARTICR_TXIC    0x20
43 
44 #if defined(BSP_USING_UART0)
45 struct rt_serial_device serial0;
46 #endif
47 
48 #if defined(BSP_USING_UART1)
49 struct rt_serial_device serial1;
50 #endif
51 
52 #if defined(BSP_USING_UART2)
53 struct rt_serial_device serial2;
54 #endif
55 
56 
57 #if defined(BSP_USING_UART3)
58 struct rt_serial_device serial3;
59 #endif
60 
61 static struct hw_uart_device _uart_device[] = {
62 #if defined(BSP_USING_UART0)
63 {
64     REALVIEW_UART0_BASE,
65     IRQ_PBA8_UART0,
66     &serial0,
67     "uart0",
68 },
69 #endif
70 
71 #if defined(BSP_USING_UART1)
72 {
73     REALVIEW_UART1_BASE,
74     IRQ_PBA8_UART1,
75     &serial1,
76     "uart1",
77 },
78 #endif
79 
80 #if defined(BSP_USING_UART2)
81 {
82     REALVIEW_UART2_BASE,
83     IRQ_PBA8_UART2,
84     &serial2,
85     "uart2",
86 },
87 #endif
88 
89 #if defined(BSP_USING_UART3)
90 {
91     REALVIEW_UART3_BASE,
92     IRQ_PBA8_UART3,
93     &serial3,
94     "uart3",
95 },
96 #endif
97 
98 };
99 
100 /**
101  * @brief UART common interrupt process. This
102  *
103  * @param serial Serial device
104  */
rt_hw_uart_isr(int irqno,void * param)105 static void rt_hw_uart_isr(int irqno, void *param)
106 {
107     struct rt_serial_device *serial = (struct rt_serial_device *)param;
108     rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
109 }
110 
uart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)111 static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
112 {
113     return RT_EOK;
114 }
115 
uart_control(struct rt_serial_device * serial,int cmd,void * arg)116 static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
117 {
118     struct hw_uart_device *uart;
119 
120     RT_ASSERT(serial != RT_NULL);
121 
122     uart = (struct hw_uart_device *)serial->parent.user_data;
123 
124     switch (cmd)
125     {
126         case RT_DEVICE_CTRL_CLR_INT:
127             /* disable rx irq */
128         UART_IMSC(uart->hw_base) &= ~UARTIMSC_RXIM;
129             break;
130 
131         case RT_DEVICE_CTRL_SET_INT:
132             /* enable rx irq */
133             UART_IMSC(uart->hw_base) |= UARTIMSC_RXIM;
134             rt_hw_interrupt_umask(uart->irqno);
135             break;
136     }
137 
138     return RT_EOK;
139 }
140 
uart_putc(struct rt_serial_device * serial,char ch)141 static int uart_putc(struct rt_serial_device *serial, char ch)
142 {
143     struct hw_uart_device *uart;
144 
145     RT_ASSERT(serial != RT_NULL);
146     uart = (struct hw_uart_device *)serial->parent.user_data;
147 
148     while (UART_FR(uart->hw_base) & UARTFR_TXFF);
149     UART_DR(uart->hw_base) = ch;
150 
151     return 1;
152 }
153 
uart_getc(struct rt_serial_device * serial)154 static int uart_getc(struct rt_serial_device *serial)
155 {
156     int ch;
157     struct hw_uart_device *uart;
158 
159     RT_ASSERT(serial != RT_NULL);
160     uart = (struct hw_uart_device *)serial->parent.user_data;
161 
162     ch = -1;
163     if (!(UART_FR(uart->hw_base) & UARTFR_RXFE))
164     {
165         ch = UART_DR(uart->hw_base) & 0xff;
166     }
167 
168     return ch;
169 }
170 
171 static const struct rt_uart_ops _uart_ops = {
172     uart_configure,
173     uart_control,
174     uart_putc,
175     uart_getc,
176 };
177 
rt_hw_uart_init(void)178 int rt_hw_uart_init(void)
179 {
180 
181     rt_err_t err = RT_EOK;
182 
183     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
184 
185     for (uint32_t i = 0; i < sizeof(_uart_device) / sizeof(_uart_device[0]); i++)
186     {
187 
188         #ifdef RT_USING_SMART
189             _uart_device[i].hw_base = (uint32_t)rt_ioremap((void*)_uart_device[i].hw_base, 0x1000);
190         #endif
191 
192         _uart_device[i].serial->ops = &_uart_ops;
193         _uart_device[i].serial->config = config;
194 
195         /* register UART device */
196         err = rt_hw_serial_register(_uart_device[i].serial,
197                             _uart_device[i].device_name,
198                             RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
199                             (void*)&_uart_device[i]);
200         rt_hw_interrupt_install(_uart_device[i].irqno, rt_hw_uart_isr, _uart_device[i].serial, _uart_device[i].device_name);
201         /* enable Rx and Tx of UART */
202         UART_CR(_uart_device[i].hw_base) = (1 << 0) | (1 << 8) | (1 << 9);
203     }
204 
205     return err;
206 }
207 
208 INIT_BOARD_EXPORT(rt_hw_uart_init);
209 
210 #endif /* RT_USING_SERIAL */