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 * 2025-05-28 ZhangJing Porting to ultrarisc dp1000
9 */
10
11 #include <rthw.h>
12 #include <rtdevice.h>
13 #include <rtthread.h>
14
15 #include "board.h"
16 #include "drv_uart.h"
17
18 #include <stdio.h>
19 #ifdef RT_USING_SMART
20 #include <ioremap.h>
21 #endif
22 #include "sbi.h"
23
24 struct device_uart
25 {
26 rt_ubase_t hw_base;
27 rt_uint32_t irqno;
28 };
29
30 #ifdef BSP_USING_UART0
31 void *uart0_base = (void *)UART0_BASE_ADDR;
32 struct rt_serial_device serial0;
33 struct device_uart uart0;
34
35 #define UART0_CLK (UART0_REFERENCE_CLOCK)
36 #define UART0_BAUDRATE (UART0_DEFAULT_BAUDRATE)
37 #endif
38
39 #define UART_REFERENCE_CLOCK (UART0_CLK)
40 #define REG_SHIFT (1 << UART0_REG_SHIFT)
41 #define write8_uart(base,idx, value) __raw_writeb(((rt_uint8_t)value), (void*)((size_t)base + (idx*REG_SHIFT)))
42 #define read8_uart(base,idx) __raw_readb((void*)((size_t)base + (idx*REG_SHIFT)))
43
_uart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)44 static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
45 {
46 struct device_uart *uart = (struct device_uart *)serial->parent.user_data;
47 rt_uint32_t div = UART_REFERENCE_CLOCK / (cfg->baud_rate * 16);
48 rt_uint32_t ier = read8_uart(uart->hw_base, UART_IER);
49
50 write8_uart(uart->hw_base, UART_IER, 0x00);
51 write8_uart(uart->hw_base, UART_LCR, UART_LCR_BAUD_LATCH);
52
53 /* LSB */
54 write8_uart(uart->hw_base, 0, div & 0xff);
55 /* MSB */
56 write8_uart(uart->hw_base, 1, (div >> 8) & 0xff);
57
58 /* set word length to 8 bits, no parity */
59 write8_uart(uart->hw_base, UART_LCR, UART_LCR_EIGHT_BITS);
60
61 write8_uart(uart->hw_base, UART_FCR, UART_FCR_FIFO_ENABLE | UART_FCR_FIFO_CLEAR);
62 write8_uart(uart->hw_base, UART_IER, ier);
63 return (RT_EOK);
64 }
65
_uart_control(struct rt_serial_device * serial,int cmd,void * arg)66 static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *arg)
67 {
68 struct device_uart *uart = (struct device_uart *)serial->parent.user_data;
69
70 switch (cmd)
71 {
72 case RT_DEVICE_CTRL_CLR_INT:
73 if ((size_t)arg == RT_DEVICE_FLAG_INT_RX)
74 {
75 rt_uint8_t value = read8_uart(uart->hw_base, UART_IER);
76 write8_uart(uart->hw_base, UART_IER, value & ~UART_IER_RX_ENABLE);
77 }
78 break;
79
80 case RT_DEVICE_CTRL_SET_INT:
81 if ((size_t)arg == RT_DEVICE_FLAG_INT_RX)
82 {
83 rt_uint8_t value = read8_uart(uart->hw_base, UART_IER);
84 write8_uart(uart->hw_base, UART_IER, value | UART_IER_RX_ENABLE);
85 }
86 break;
87 }
88
89 return (RT_EOK);
90 }
91
_uart_putc(struct rt_serial_device * serial,char c)92 static int _uart_putc(struct rt_serial_device *serial, char c)
93 {
94 struct device_uart *uart;
95 uart = (struct device_uart *)serial->parent.user_data;
96
97 /* wait for Transmit Holding Empty to be set in LSR. */
98 while ((read8_uart(uart->hw_base, UART_LSR) & UART_LSR_TX_IDLE) == 0)
99 ;
100 write8_uart(uart->hw_base, UART_THR, c);
101
102 return (1);
103 }
104
_uart_getc(struct rt_serial_device * serial)105 static int _uart_getc(struct rt_serial_device *serial)
106 {
107 struct device_uart *uart;
108 volatile rt_uint32_t lsr;
109 int ch = -1;
110
111 uart = (struct device_uart *)serial->parent.user_data;
112 lsr = read8_uart(uart->hw_base, UART_LSR);
113
114 if (lsr & UART_LSR_RX_READY)
115 {
116 ch = read8_uart(uart->hw_base, UART_RHR);
117 }
118 return ch;
119 }
120
121 const struct rt_uart_ops _uart_ops =
122 {
123 _uart_configure,
124 _uart_control,
125 _uart_putc,
126 _uart_getc,
127 /* TODO: add DMA support */
128 RT_NULL
129 };
130
rt_hw_uart_isr(int irqno,void * param)131 static void rt_hw_uart_isr(int irqno, void *param)
132 {
133 rt_ubase_t level = rt_hw_interrupt_disable();
134
135 struct rt_serial_device *serial = (struct rt_serial_device *)param;
136 struct device_uart *uart = (struct device_uart *)serial->parent.user_data;
137
138 if ((read8_uart(uart->hw_base, UART_LSR) & UART_LSR_RX_READY) != 0)
139 {
140 rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
141 }
142
143 rt_hw_interrupt_enable(level);
144 return;
145 }
146
147 /*
148 * UART Initiation
149 */
rt_hw_uart_init(void)150 int rt_hw_uart_init(void)
151 {
152 struct rt_serial_device *serial;
153 struct device_uart *uart;
154 struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
155 char ch;
156 #ifdef BSP_USING_UART0
157 /* register device */
158 serial = &serial0;
159 uart = &uart0;
160
161 serial->ops = &_uart_ops;
162 serial->config = config;
163 serial->config.baud_rate = UART0_BAUDRATE;
164 uart->hw_base = (rt_ubase_t)uart0_base;
165 #ifdef RT_USING_SMART
166 uart->hw_base = (rt_ubase_t)rt_ioremap((void *)uart0_base, 0x1000);
167 #endif
168 uart->irqno = UART0_IRQ_BASE;
169 /* disable all uart irqs */
170 write8_uart(uart->hw_base, UART_IER, 0);
171 /* wait for Transmit Holding Empty to be set in LSR. */
172 while ((read8_uart(uart->hw_base, UART_LSR) & UART_LSR_TX_IDLE) == 0)
173 ;
174
175 while ((read8_uart(uart->hw_base, UART_LSR) & UART_LSR_RX_READY) != 0)
176 {
177 ch = read8_uart(uart->hw_base, UART_RHR);
178 }
179
180 rt_hw_serial_register(serial,
181 RT_CONSOLE_DEVICE_NAME,
182 RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
183 uart);
184 rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, serial, RT_CONSOLE_DEVICE_NAME);
185 rt_hw_interrupt_umask(uart->irqno);
186 #endif
187 }