Unifying External Interrupt System (#51)
[lunaix-os.git] / lunaix-os / hal / char / uart / 16x50.h
1 #ifndef __LUNAIX_16550_H
2 #define __LUNAIX_16550_H
3
4 #include <hal/serial.h>
5 #include <hal/irq.h>
6 #include <lunaix/types.h>
7
8 #define UART_rRxTX 0
9 #define UART_rIE 1
10 #define UART_rII 2
11 #define UART_rFC 2
12 #define UART_rLC 3
13 #define UART_rMC 4
14 #define UART_rLS 5
15 #define UART_rMS 6
16 #define UART_rSC 7
17 #define UART_rDLL 0
18 #define UART_rDLM 1
19
20 #define UART_INTRX 0x1
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_rLC_STOPB (1 << 2)
29 #define UART_rLC_PAREN (1 << 3)
30 #define UART_rLC_PAREVN (1 << 4)
31 #define UART_rLC_SETBRK (1 << 6)
32 #define UART_rLC_DLAB (1 << 7)
33
34 #define UART_rLS_THRE (1 << 5)
35 #define UART_rLS_DR 1
36 #define UART_rLS_BI (1 << 4)
37
38 #define UART_rII_FIFOEN (0b11 << 6)
39 #define UART_rII_ID 0b1111
40
41 #define UART_rFC_EN 1
42 #define UART_rFC_DMA1 (1 << 3)
43 #define UART_rFC_XMIT_RESET (1 << 2)
44 #define UART_rFC_RCVR_RESET (1 << 1)
45
46 #define UART_rMC_DTR 1
47 #define UART_rMC_RTS (1 << 1)
48 #define UART_rMC_IEN (1 << 3)
49
50 #define UART_FIFO1 0b00
51 #define UART_FIFO4 0b01
52 #define UART_FIFO8 0b10
53 #define UART_FIFO14 0b11
54
55 #define UART_NO_INTR 0b0001
56 #define UART_LINE_UDPDATE 0b0110
57 #define UART_DATA_OK 0b0100
58 #define UART_CHR_TIMEOUT 0b1100
59 #define UART_SENT_ALL 0b0010
60 #define UART_MODEM_UPDATE 0b0000
61
62 #define UART_LCR_RESET \
63             (UART_rLC_STOPB | \
64             UART_rLC_PAREN | \
65             UART_rLC_PAREVN | \
66             UART_rLC_DLAB | 0b11)
67
68 struct uart16550
69 {
70     struct llist_header local_ports;
71     struct serial_dev* sdev;
72     ptr_t base_addr;
73     unsigned int base_clk;
74     irq_t irq;
75
76     struct
77     {
78         u8_t rie;
79         u8_t rfc;
80         u8_t rmc;
81         u8_t rlc;
82     } cntl_save;
83
84     u32_t (*read_reg)(struct uart16550* uart, ptr_t regoff);
85     void (*write_reg)(struct uart16550* uart, ptr_t regoff, u32_t val);
86 };
87
88 #define UART16550(sdev) ((struct uart16550*)(sdev)->backend)
89
90 static inline void
91 uart_setup(struct uart16550* uart)
92 {
93     uart->write_reg(uart, UART_rMC, uart->cntl_save.rmc);
94     uart->write_reg(uart, UART_rIE, uart->cntl_save.rie);
95 }
96
97 static inline void
98 uart_clrie(struct uart16550* uart)
99 {
100     uart->cntl_save.rie = uart->read_reg(uart, UART_rIE);
101     uart->write_reg(uart, UART_rIE, 0);
102 }
103
104 static inline void
105 uart_setie(struct uart16550* uart)
106 {
107     uart->write_reg(uart, UART_rIE, uart->cntl_save.rie);
108 }
109
110 static inline void
111 uart_setlc(struct uart16550* uart)
112 {
113     uart->write_reg(uart, UART_rLC, uart->cntl_save.rlc);
114 }
115
116 struct uart16550*
117 uart_alloc(ptr_t base_addr);
118
119 void
120 uart_free(struct uart16550*);
121
122 static inline int
123 uart_baud_divisor(struct uart16550* uart, unsigned int div)
124 {
125     u32_t rlc = uart->read_reg(uart, UART_rLC);
126
127     uart->write_reg(uart, UART_rLC, UART_rLC_DLAB | rlc);
128     u8_t ls = (div & 0x00ff), ms = (div & 0xff00) >> 8;
129
130     uart->write_reg(uart, UART_rLS, ls);
131     uart->write_reg(uart, UART_rMS, ms);
132
133     uart->write_reg(uart, UART_rLC, rlc & ~UART_rLC_DLAB);
134
135     return 0;
136 }
137
138 static inline int
139 uart_testport(struct uart16550* uart, char test_code)
140 {
141     u32_t rmc = uart->cntl_save.rmc;
142     uart->write_reg(uart, UART_rMC, rmc | UART_LOOP);
143
144     uart->write_reg(uart, UART_rRxTX, test_code);
145
146     u32_t result = (char)uart->read_reg(uart, UART_rRxTX) == test_code;
147     uart->write_reg(uart, UART_rMC, rmc & ~UART_LOOP);
148
149     return result;
150 }
151
152 static inline int
153 uart_pending_data(struct uart16550* uart)
154 {
155     return uart->read_reg(uart, UART_rLS) & UART_rLS_DR;
156 }
157
158 static inline int
159 uart_can_transmit(struct uart16550* uart)
160 {
161     return uart->read_reg(uart, UART_rLS) & UART_rLS_THRE;
162 }
163
164 /**
165  * @brief End of receiving
166  *
167  * @param uart
168  * @return int
169  */
170 static inline int
171 uart_eorcv(struct uart16550* uart)
172 {
173     return uart->read_reg(uart, UART_rLS) & UART_rLS_BI;
174 }
175
176 static inline int
177 uart_enable_fifo(struct uart16550* uart, int trig_lvl)
178 {
179     uart->cntl_save.rfc =
180       UART_rFC_EN | ((trig_lvl & 0b11) << 6) | UART_rFC_DMA1;
181     uart->write_reg(uart, UART_rFC, uart->cntl_save.rfc);
182
183     return uart->read_reg(uart, UART_rII) & UART_rII_FIFOEN;
184 }
185
186 static inline void
187 uart_clear_rxfifo(struct uart16550* uart)
188 {
189     uart->write_reg(uart, UART_rFC, uart->cntl_save.rfc | UART_rFC_RCVR_RESET);
190 }
191
192 static inline void
193 uart_clear_txfifo(struct uart16550* uart)
194 {
195     uart->write_reg(uart, UART_rFC, uart->cntl_save.rfc | UART_rFC_XMIT_RESET);
196 }
197
198 static inline void
199 uart_clear_fifo(struct uart16550* uart)
200 {
201     u32_t rfc = uart->cntl_save.rfc | UART_rFC_XMIT_RESET | UART_rFC_RCVR_RESET;
202     uart->write_reg(uart, UART_rFC, rfc);
203 }
204
205 static inline int
206 uart_intr_identify(struct uart16550* uart)
207 {
208     u32_t rii = uart->read_reg(uart, UART_rII);
209     return (rii & UART_rII_ID);
210 }
211
212 static inline u8_t
213 uart_read_byte(struct uart16550* uart)
214 {
215     return (u8_t)uart->read_reg(uart, UART_rRxTX);
216 }
217
218 static inline void
219 uart_write_byte(struct uart16550* uart, u8_t val)
220 {
221     uart->write_reg(uart, UART_rRxTX, val);
222 }
223
224 int
225 uart_general_exec_cmd(struct serial_dev* sdev, u32_t req, va_list args);
226
227 int
228 uart_general_tx(struct serial_dev* sdev, u8_t* data, size_t len);
229
230 void
231 uart_handle_irq_overlap(irq_t irq, struct llist_header* ports);
232
233 void
234 uart_handle_irq(irq_t irq, struct uart16550 *uart);
235
236 static inline struct serial_dev*
237 uart_create_serial(struct uart16550* uart, struct devclass* class, 
238                          struct llist_header* ports, char* if_ident)
239 {
240     llist_append(ports, &uart->local_ports);
241
242     struct serial_dev* sdev = serial_create(class, if_ident);
243     sdev->backend = uart;
244     sdev->write = uart_general_tx;
245     sdev->exec_cmd = uart_general_exec_cmd;
246
247     uart->sdev = sdev;
248
249     uart_setup(uart);
250     uart_setie(uart);
251
252     return sdev;
253 }
254
255 struct uart16550*
256 uart16x50_pmio_create(ptr_t base);
257
258 struct uart16550*
259 uart16x50_mmio_create(ptr_t base, ptr_t size);
260
261 #endif /* __LUNAIX_16550_H */