1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author            Notes
8  * 2022-07-15     Emuzit            first version
9  */
10 #ifndef __CH56X_UART_H__
11 #define __CH56X_UART_H__
12 
13 #include "soc.h"
14 #include "ch56x_gpio.h"
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 #define UART_RXD0_ALT       GET_PIN(A, 5)
21 #define UART_TXD0_ALT       GET_PIN(A, 6)
22 
23 #define UART_RXD0_PIN       GET_PIN(B, 5)
24 #define UART_TXD0_PIN       GET_PIN(B, 6)
25 #define UART_RXD1_PIN       GET_PIN(A, 7)
26 #define UART_TXD1_PIN       GET_PIN(A, 8)
27 #define UART_RXD2_PIN       GET_PIN(A, 2)
28 #define UART_TXD2_PIN       GET_PIN(A, 3)
29 #define UART_RXD3_PIN       GET_PIN(B, 3)
30 #define UART_TXD3_PIN       GET_PIN(B, 4)
31 
32 #ifndef UART_FIFO_SIZE
33 #define UART_FIFO_SIZE      8
34 #endif
35 
36 #ifndef UART_RECV_RDY_SZ
37 #define UART_RECV_RDY_SZ    7    // FIFO trigger level for rx data available
38 #endif
39 
40 union _uart_mcr
41 {
42     uint8_t reg;
43     struct
44     {
45         uint8_t dtr         : 1;  // B.0 : RW, DTR output (UART0 only)
46         uint8_t rts         : 1;  // B.1 : RW, RTS output (UART0 only)
47         uint8_t out1        : 1;  // B.2 : RW, user defined modem control (UART0 only)
48         uint8_t int_oe      : 1;  // B.3 : RW, interrupt output enable / OUT2
49         uint8_t loop        : 1;  // B.4 : RW, enable internal loop test (UART0 only)
50         uint8_t au_flow_en  : 1;  // B.5 : RW, enable CTS/RTS autoflow control
51         uint8_t tnow        : 1;  // B.6 : RW, enable DTR TNOW output (UART0 only)
52         uint8_t half        : 1;  // B.7 : RW, enable half-duplex mode (UART0 only)
53     };
54 };
55 #define RB_MCR_DTR          0x01
56 #define RB_MCR_RTS          0x02
57 #define RB_MCR_OUT1         0x04
58 #define RB_MCR_OUT2         0x08
59 #define RB_MCR_INT_OE       0x08
60 #define RB_MCR_LOOP         0x10
61 #define RB_MCR_AU_FLOW_EN   0x20
62 #define RB_MCR_TNOW         0x40
63 #define RB_MCR_HALF         0x80
64 
65 union _uart_ier
66 {
67     uint8_t reg;
68     struct
69     {
70         uint8_t recv_rdy    : 1;  // B.0 : RW, enable rx data ready intr
71         uint8_t thr_empty   : 1;  // B.1 : RW, enable THR empty intr
72         uint8_t line_stat   : 1;  // B.2 : RW, enable rx line status intr
73         uint8_t modem_chg   : 1;  // B.3 : RW, enable modem status change intr (UART0 only)
74         uint8_t dtr_en      : 1;  // B.4 : RW, DTR/TNOW output pin enable (UART0 only)
75         uint8_t rts_en      : 1;  // B.5 : RW, RTS output pin enable (UART0 only)
76         uint8_t txd_en      : 1;  // B.6 : RW, TXD pin enable
77         uint8_t reset       : 1;  // B.7 : WZ, software reset control, active high, auto clear
78     };
79 };
80 #define RB_IER_RECV_RDY     0x01
81 #define RB_IER_THR_EMPTY    0x02
82 #define RB_IER_LINE_STAT    0x04
83 #define RB_IER_MODEM_CHG    0x08
84 #define RB_IER_DTR_EN       0x10
85 #define RB_IER_RTS_EN       0x20
86 #define RB_IER_TXD_EN       0x40
87 #define RB_IER_RESET        0x80
88 
89 union _uart_fcr
90 {
91     uint8_t reg;
92     struct
93     {
94         uint8_t fifo_en     : 1;  // B.0   : RW, FIFO enable
95         uint8_t rx_fifo_clr : 1;  // B.1   : WZ, write 1 to clear rx FIFO, auto clear
96         uint8_t tx_fifo_clr : 1;  // B.2   : WZ, write 1 to clear tx FIFO, auto clear
97         uint8_t resv_3      : 3;
98         uint8_t fifo_trig   : 2;  // B.7-6 : RW, rx FIFO trigger level, 1/2/4/7 bytes
99     };
100 };
101 #define RB_FCR_FIFO_EN      0x01
102 #define RB_FCR_RX_FIFO_CLR  0x02
103 #define RB_FCR_TX_FIFO_CLR  0x04
104 #define RB_FCR_FIFO_TRIG    0xc0
105 
106 #define UART_1BYTE_TRIG     0
107 #define UART_2BYTE_TRIG     1
108 #define UART_4BYTE_TRIG     2
109 #define UART_7BYTE_TRIG     3
110 
111 union _uart_lcr
112 {
113     uint8_t reg;
114     struct
115     {
116         uint8_t word_sz     : 2;  // B.1-0 : RW, word bit length, 5/6/7/8 bits
117         uint8_t stop_bit    : 1;  // B.2   : RW, stop bit length, 1/2 bits
118         uint8_t par_en      : 1;  // B.3   : RW, parity enable
119         uint8_t par_mod     : 2;  // B.5-4 : RW, parity mode, odd/even/mark/space
120         uint8_t break_en    : 1;  // B.6   : RW, force BREAK line condition
121         uint8_t dlab        : 1;  // B.7   : RW, user defined general purpose bit
122     };
123 };
124 #define RB_LCR_WORD_SZ      0x03
125 #define RB_LCR_STOP_BIT     0x04
126 #define RB_LCR_PAR_EN       0x08
127 #define RB_LCR_PAR_MOD      0x30
128 #define RB_LCR_BREAK_EN     0x40
129 #define RB_LCR_DLAB         0x80
130 #define RB_LCR_GP_BIT       0x80
131 
132 #define LCR_DATA_BITS_5     0
133 #define LCR_DATA_BITS_6     1
134 #define LCR_DATA_BITS_7     2
135 #define LCR_DATA_BITS_8     3
136 
137 #define LCR_STOP_BITS_1     0
138 #define LCR_STOP_BITS_2     1
139 
140 #define LCR_PARITY_ODD      0
141 #define LCR_PARITY_EVEN     1
142 #define LCR_PARITY_MARK     2
143 #define LCR_PARITY_SPACE    3
144 
145 union _uart_iir
146 {
147     uint8_t reg;
148     struct
149     {
150         uint8_t int_mask    : 4;  // B.3-0 : RO, interrupt mask (intr if B.0 is 0)
151         uint8_t resv_4      : 2;
152         uint8_t fifo_id     : 2;  // B.7-6 : RO, FIFO enabled flag
153     };
154 };
155 #define RB_IIR_NO_INT       0x01
156 #define RB_IIR_INT_MASK     0x0f
157 #define RB_IIR_FIFO_ID      0xc0
158 
159 /* RB_IIR_INT_MASK (IIR bits 3:0) definition
160 */
161 #define UART_II_SLV_ADDR    0x0e  // UART0 slave address match interrupt
162 #define UART_II_LINE_STAT   0x06  // rx line status interrupt
163 #define UART_II_RECV_RDY    0x04  // rx data available interrupt
164 #define UART_II_RECV_TOUT   0x0c  // rx fifo timeout interrupt
165 #define UART_II_THR_EMPTY   0x02  // THR empty interrupt
166 #define UART_II_MODEM_CHG   0x00  // UART0 modem status change interrupt
167 #define UART_II_NO_INTER    0x01  // no interrupt pending
168 
169 union _uart_lsr
170 {
171     uint8_t reg;
172     struct
173     {
174         uint8_t data_rdy    : 1;  // B.0 : RO, rx FIFO data ready
175         uint8_t over_err    : 1;  // B.1 : RZ, rx FIFO data overrun
176         uint8_t par_err     : 1;  // B.2 : RZ, rx parity error
177         uint8_t frame_err   : 1;  // B.3 : RZ, rx frame error
178         uint8_t break_err   : 1;  // B.4 : RZ, rx BREAK detected
179         uint8_t tx_fifo_emp : 1;  // B.5 : RO, tx FIFO empty
180         uint8_t tx_all_emp  : 1;  // B.6 : RO, THR/TSR all empty
181         uint8_t err_rx_fifo : 1;  // B.7 : RO, PAR/FRAME/BREAK ERR in rx FIFO
182     };
183 };
184 #define RB_LSR_DATA_RDY     0x01
185 #define RB_LSR_OVER_ERR     0x02
186 #define RB_LSR_PAR_ERR      0x04
187 #define RB_LSR_FRAME_ERR    0x08
188 #define RB_LSR_BREAK_ERR    0x10
189 #define RB_LSR_TX_FIFO_EMP  0x20
190 #define RB_LSR_TX_ALL_EMP   0x40
191 #define RB_LSR_ERR_RX_FIFO  0x80
192 
193 union _uart_msr
194 {
195     uint8_t reg;
196     struct
197     {
198         uint8_t cts_chg     : 1;  // B.0 : RZ, CTS input changed
199         uint8_t dsr_chg     : 1;  // B.1 : RZ, DSR input changed
200         uint8_t ri_chg      : 1;  // B.2 : RZ, RI  input changed
201         uint8_t dcd_chg     : 1;  // B.3 : RZ, DCD input changed
202         uint8_t cts         : 1;  // B.4 : RO, CTS action status
203         uint8_t dsr         : 1;  // B.5 : RO, DSR action status
204         uint8_t ri          : 1;  // B.6 : RO, RI  action status
205         uint8_t dcd         : 1;  // B.7 : RO, DCD action status
206     };
207 };
208 #define RB_MSR_CTS_CHG      0x01
209 #define RB_MSR_DSR_CHG      0x02
210 #define RB_MSR_RI_CHG       0x04
211 #define RB_MSR_DCD_CHG      0x08
212 #define RB_MSR_CTS          0x10
213 #define RB_MSR_DSR          0x20
214 #define RB_MSR_RI           0x40
215 #define RB_MSR_DCD          0x80
216 
217 /*
218  * 0x00  R8_UARTx_MCR:  Modem Control Register
219  * 0x01  R8_UARTx_IER:  Interrupt Enable Register
220  * 0x02  R8_UARTx_FCR:  FIFO Control Register
221  * 0x03  R8_UARTx_LCR:  Line Control Register
222  * 0x04  R8_UARTx_IIR:  Interrupt Identification Register
223  * 0x05  R8_UARTx_LSR:  Line Status Register
224  * 0x06  R8_UARTx_MSR:  Modem Status Register (UART0 only)
225  * 0x08  R8_UARTx_RBR:  Rx Buffer Register
226  * 0x08  R8_UARTx_THR:  Tx Hold Register
227  * 0x0a  R8_UARTx_RFC:  Rx FIFO count register
228  * 0x0b  R8_UARTx_TFC:  Tx FIFO count register
229  * 0x0c  R16_UARTx_DL:  Divisor Latch
230  * 0x0e  R8_UARTx_DIV:  frequency pre divider
231  * 0x0f  R8_UARTx_ADR:  Address Register (UART0 only)
232  *
233  * CAVEAT: gcc (as of 8.2.0) tends to read 32-bit word for bit field test.
234  * Be careful for those with side effect for read (e.g. RBR, IIR).
235  */
236 struct uart_registers
237 {
238     union _uart_mcr MCR;
239     union _uart_ier IER;
240     union _uart_fcr FCR;
241     union _uart_lcr LCR;
242     union _uart_iir IIR;
243     union _uart_lsr LSR;
244     union _uart_lsr MSR;
245     uint8_t         resv_7;
246     union
247     {
248         uint8_t     RBR;
249         uint8_t     THR;
250     };
251     uint8_t         resv_9;
252     uint8_t         RFC;
253     uint8_t         TFC;
254     uint16_t        DL;
255     uint8_t         DIV;
256     uint8_t         ADR;
257 } __packed;
258 
259 CHECK_STRUCT_SIZE(struct uart_registers, 0x10);
260 
261 int rt_hw_uart_init(void);
262 
263 #ifdef __cplusplus
264 }
265 #endif
266 
267 #endif
268