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