feat: serial device interfacing
[lunaix-os.git] / lunaix-os / hal / char / uart / 16550.h
1 #ifndef __LUNAIX_16550_H
2 #define __LUNAIX_16550_H
3
4 #include <hal/serial.h>
5 #include <lunaix/types.h>
6
7 #define UART_rRxTX 0
8 #define UART_rIE 1
9 #define UART_rII 2
10 #define UART_rFC 2
11 #define UART_rLC 3
12 #define UART_rMC 4
13 #define UART_rLS 5
14 #define UART_rMS 6
15 #define UART_rSC 7
16 #define UART_rDLL 0
17 #define UART_rDLM 1
18
19 #define UART_INTRX 0x1
20 #define UART_DLAB (1 << 7)
21 #define UART_LOOP (1 << 4)
22
23 #define UART_rIE_ERBFI 1
24 #define UART_rIE_ETBEI (1 << 1)
25 #define UART_rIE_ELSI (1 << 2)
26 #define UART_rIE_EDSSI (1 << 3)
27
28 #define UART_rLS_THRE (1 << 5)
29 #define UART_rLS_DR 1
30 #define UART_rLS_BI (1 << 4)
31
32 #define UART_rII_FIFOEN (0b11 << 6)
33 #define UART_rII_ID 0b1110
34
35 #define UART_rFC_EN 1
36 #define UART_rFC_XMIT_RESET (1 << 2)
37 #define UART_rFC_RCVR_RESET (1 << 1)
38
39 #define UART_rMC_DTR 1
40 #define UART_rMC_RTS (1 << 1)
41 #define UART_rMC_IEN (1 << 3)
42
43 #define UART_FIFO1 0b00
44 #define UART_FIFO4 0b01
45 #define UART_FIFO8 0b10
46 #define UART_FIFO14 0b11
47
48 #define UART_NO_INTR 0b0001
49 #define UART_LINE_UDPDATE 0b0110
50 #define UART_DATA_OK 0b0100
51 #define UART_CHR_TIMEOUT 0b1100
52 #define UART_SENT_ALL 0b0010
53 #define UART_MODEM_UPDATE 0b0000
54
55 struct uart16550
56 {
57     struct llist_header local_ports;
58     struct serial_dev* sdev;
59     ptr_t base_addr;
60     int iv;
61
62     struct
63     {
64         u8_t rie;
65         u8_t rfc;
66         u8_t rmc;
67     } cntl_save;
68
69     u32_t (*read_reg)(struct uart16550* uart, ptr_t regoff);
70     void (*write_reg)(struct uart16550* uart, ptr_t regoff, u32_t val);
71 };
72
73 #define UART16550(sdev) ((struct uart16550*)(sdev)->backend)
74
75 static inline void
76 uart_setup(struct uart16550* uart)
77 {
78     uart->write_reg(uart, UART_rMC, uart->cntl_save.rmc);
79     uart->write_reg(uart, UART_rIE, uart->cntl_save.rie);
80 }
81
82 static inline void
83 uart_setie(struct uart16550* uart)
84 {
85     uart->cntl_save.rie = uart->read_reg(uart, UART_rIE);
86     uart->write_reg(uart, UART_rIE, 0);
87 }
88
89 static inline void
90 uart_clrie(struct uart16550* uart)
91 {
92     uart->write_reg(uart, UART_rIE, uart->cntl_save.rie | 1);
93 }
94
95 struct uart16550*
96 uart_alloc(ptr_t base_addr);
97
98 void
99 uart_free(struct uart16550*);
100
101 static inline int
102 uart_baud_divisor(struct uart16550* uart, int div)
103 {
104     u32_t rlc = uart->read_reg(uart, UART_rLC);
105
106     uart->write_reg(uart, UART_rLC, UART_DLAB | rlc);
107     u8_t ls = (div & 0xff), ms = (div & 0xff00) >> 8;
108
109     uart->write_reg(uart, UART_rLS, ls);
110     uart->write_reg(uart, UART_rMS, ms);
111
112     uart->write_reg(uart, UART_rLC, rlc & ~UART_DLAB);
113
114     return 0;
115 }
116
117 static inline int
118 uart_testport(struct uart16550* uart, char test_code)
119 {
120     u32_t rmc = uart->cntl_save.rmc;
121     uart->write_reg(uart, UART_rMC, rmc | UART_LOOP);
122
123     uart->write_reg(uart, UART_rRxTX, test_code);
124
125     u32_t result = (char)uart->read_reg(uart, UART_rRxTX) == test_code;
126     uart->write_reg(uart, UART_rMC, rmc & ~UART_LOOP);
127
128     return result;
129 }
130
131 static inline int
132 uart_pending_data(struct uart16550* uart)
133 {
134     return uart->read_reg(uart, UART_rLS) & UART_rLS_DR;
135 }
136
137 static inline int
138 uart_can_transmit(struct uart16550* uart)
139 {
140     return uart->read_reg(uart, UART_rLS) & UART_rLS_THRE;
141 }
142
143 /**
144  * @brief End of receiving
145  *
146  * @param uart
147  * @return int
148  */
149 static inline int
150 uart_eorcv(struct uart16550* uart)
151 {
152     return uart->read_reg(uart, UART_rLS) & UART_rLS_BI;
153 }
154
155 static inline int
156 uart_enable_fifo(struct uart16550* uart, int trig_lvl)
157 {
158     uart->cntl_save.rfc = UART_rFC_EN | (trig_lvl & 0b11);
159     uart->write_reg(uart, UART_rFC, uart->cntl_save.rfc);
160
161     return uart->read_reg(uart, UART_rII) & UART_rII_FIFOEN;
162 }
163
164 static inline void
165 uart_clear_rxfifo(struct uart16550* uart)
166 {
167     uart->write_reg(uart, UART_rFC, uart->cntl_save.rfc | UART_rFC_RCVR_RESET);
168 }
169
170 static inline void
171 uart_clear_txfifo(struct uart16550* uart)
172 {
173     uart->write_reg(uart, UART_rFC, uart->cntl_save.rfc | UART_rFC_XMIT_RESET);
174 }
175
176 static inline void
177 uart_clear_fifo(struct uart16550* uart)
178 {
179     u32_t rfc = uart->cntl_save.rfc | UART_rFC_XMIT_RESET | UART_rFC_RCVR_RESET;
180     uart->write_reg(uart, UART_rFC, rfc);
181 }
182
183 static inline int
184 uart_intr_identify(struct uart16550* uart)
185 {
186     u32_t rii = uart->read_reg(uart, UART_rII);
187     return (!!(rii & UART_rII_FIFOEN) << 3) | ((rii & UART_rII_ID) >> 1);
188 }
189
190 static inline u8_t
191 uart_read_byte(struct uart16550* uart)
192 {
193     return (u8_t)uart->read_reg(uart, UART_rRxTX);
194 }
195
196 static inline void
197 uart_write_byte(struct uart16550* uart, u8_t val)
198 {
199     uart->write_reg(uart, UART_rRxTX, val);
200 }
201
202 int
203 uart_general_exec_cmd(struct serial_dev* sdev, u32_t req, va_list args);
204
205 int
206 uart_general_tx(struct serial_dev* sdev, u8_t* data, size_t len);
207
208 void
209 uart_general_irq_handler(int iv, struct llist_header* ports);
210
211 #endif /* __LUNAIX_16550_H */