1 /*
2 * Copyright (c) 2018 - 2019 Antmicro <www.antmicro.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT litex_uart0
8
9 #include <kernel.h>
10 #include <arch/cpu.h>
11 #include <init.h>
12 #include <irq.h>
13 #include <device.h>
14 #include <drivers/uart.h>
15 #include <zephyr/types.h>
16
17 #define UART_EV_TX (1 << 0)
18 #define UART_EV_RX (1 << 1)
19 #define UART_BASE_ADDR DT_INST_REG_ADDR(0)
20 #define UART_RXTX ((UART_BASE_ADDR) + 0x00)
21 #define UART_TXFULL ((UART_BASE_ADDR) + 0x04)
22 #define UART_RXEMPTY ((UART_BASE_ADDR) + 0x08)
23 #define UART_EV_STATUS ((UART_BASE_ADDR) + 0x0c)
24 #define UART_EV_PENDING ((UART_BASE_ADDR) + 0x10)
25 #define UART_EV_ENABLE ((UART_BASE_ADDR) + 0x14)
26 #define UART_IRQ DT_INST_IRQN(0)
27
28 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
29 typedef void (*irq_cfg_func_t)(void);
30 #endif
31
32 struct uart_liteuart_device_config {
33 uint32_t port;
34 uint32_t sys_clk_freq;
35 uint32_t baud_rate;
36 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
37 irq_cfg_func_t cfg_func;
38 #endif
39 };
40
41 struct uart_liteuart_data {
42 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
43 uart_irq_callback_user_data_t callback;
44 void *cb_data;
45 #endif
46 };
47
48 /**
49 * @brief Output a character in polled mode.
50 *
51 * Writes data to tx register. Waits for space if transmitter is full.
52 *
53 * @param dev UART device struct
54 * @param c Character to send
55 */
uart_liteuart_poll_out(const struct device * dev,unsigned char c)56 static void uart_liteuart_poll_out(const struct device *dev, unsigned char c)
57 {
58 /* wait for space */
59 while (sys_read8(UART_TXFULL)) {
60 }
61
62 sys_write8(c, UART_RXTX);
63 }
64
65 /**
66 * @brief Poll the device for input.
67 *
68 * @param dev UART device struct
69 * @param c Pointer to character
70 *
71 * @return 0 if a character arrived, -1 if the input buffer if empty.
72 */
uart_liteuart_poll_in(const struct device * dev,unsigned char * c)73 static int uart_liteuart_poll_in(const struct device *dev, unsigned char *c)
74 {
75 if (!sys_read8(UART_RXEMPTY)) {
76 *c = sys_read8(UART_RXTX);
77
78 /* refresh UART_RXEMPTY by writing UART_EV_RX
79 * to UART_EV_PENDING
80 */
81 sys_write8(UART_EV_RX, UART_EV_PENDING);
82 return 0;
83 } else {
84 return -1;
85 }
86 }
87
88 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
89 /**
90 * @brief Enable TX interrupt in event register
91 *
92 * @param dev UART device struct
93 *
94 * @return N/A
95 */
uart_liteuart_irq_tx_enable(const struct device * dev)96 static void uart_liteuart_irq_tx_enable(const struct device *dev)
97 {
98 uint8_t enable = sys_read8(UART_EV_ENABLE);
99
100 sys_write8(enable | UART_EV_TX, UART_EV_ENABLE);
101 }
102
103 /**
104 * @brief Disable TX interrupt in event register
105 *
106 * @param dev UART device struct
107 *
108 * @return N/A
109 */
uart_liteuart_irq_tx_disable(const struct device * dev)110 static void uart_liteuart_irq_tx_disable(const struct device *dev)
111 {
112 uint8_t enable = sys_read8(UART_EV_ENABLE);
113
114 sys_write8(enable & ~(UART_EV_TX), UART_EV_ENABLE);
115 }
116
117 /**
118 * @brief Enable RX interrupt in event register
119 *
120 * @param dev UART device struct
121 *
122 * @return N/A
123 */
uart_liteuart_irq_rx_enable(const struct device * dev)124 static void uart_liteuart_irq_rx_enable(const struct device *dev)
125 {
126 uint8_t enable = sys_read8(UART_EV_ENABLE);
127
128 sys_write8(enable | UART_EV_RX, UART_EV_ENABLE);
129 }
130
131 /**
132 * @brief Disable RX interrupt in event register
133 *
134 * @param dev UART device struct
135 *
136 * @return N/A
137 */
uart_liteuart_irq_rx_disable(const struct device * dev)138 static void uart_liteuart_irq_rx_disable(const struct device *dev)
139 {
140 uint8_t enable = sys_read8(UART_EV_ENABLE);
141
142 sys_write8(enable & ~(UART_EV_RX), UART_EV_ENABLE);
143 }
144
145 /**
146 * @brief Check if Tx IRQ has been raised and UART is ready to accept new data
147 *
148 * @param dev UART device struct
149 *
150 * @return 1 if an IRQ has been raised, 0 otherwise
151 */
uart_liteuart_irq_tx_ready(const struct device * dev)152 static int uart_liteuart_irq_tx_ready(const struct device *dev)
153 {
154 uint8_t val = sys_read8(UART_TXFULL);
155
156 return !val;
157 }
158
159 /**
160 * @brief Check if Rx IRQ has been raised and there's data to be read from UART
161 *
162 * @param dev UART device struct
163 *
164 * @return 1 if an IRQ has been raised, 0 otherwise
165 */
uart_liteuart_irq_rx_ready(const struct device * dev)166 static int uart_liteuart_irq_rx_ready(const struct device *dev)
167 {
168 uint8_t pending;
169
170 pending = sys_read8(UART_EV_PENDING);
171
172 if (pending & UART_EV_RX) {
173 return 1;
174 } else {
175 return 0;
176 }
177 }
178
179 /**
180 * @brief Fill FIFO with data
181 *
182 * @param dev UART device struct
183 * @param tx_data Data to transmit
184 * @param size Number of bytes to send
185 *
186 * @return Number of bytes sent
187 */
uart_liteuart_fifo_fill(const struct device * dev,const uint8_t * tx_data,int size)188 static int uart_liteuart_fifo_fill(const struct device *dev,
189 const uint8_t *tx_data, int size)
190 {
191 int i;
192
193 for (i = 0; i < size && !sys_read8(UART_TXFULL); i++) {
194 sys_write8(tx_data[i], UART_RXTX);
195 }
196
197 return i;
198 }
199
200 /**
201 * @brief Read data from FIFO
202 *
203 * @param dev UART device struct
204 * @param rxData Data container
205 * @param size Container size
206 *
207 * @return Number of bytes read
208 */
uart_liteuart_fifo_read(const struct device * dev,uint8_t * rx_data,const int size)209 static int uart_liteuart_fifo_read(const struct device *dev,
210 uint8_t *rx_data, const int size)
211 {
212 int i;
213
214 for (i = 0; i < size && !sys_read8(UART_RXEMPTY); i++) {
215 rx_data[i] = sys_read8(UART_RXTX);
216
217 /* refresh UART_RXEMPTY by writing UART_EV_RX
218 * to UART_EV_PENDING
219 */
220 sys_write8(UART_EV_RX, UART_EV_PENDING);
221 }
222
223 return i;
224 }
225
uart_liteuart_irq_err(const struct device * dev)226 static void uart_liteuart_irq_err(const struct device *dev)
227 {
228 ARG_UNUSED(dev);
229 }
230
231 /**
232 * @brief Check if any IRQ is pending
233 *
234 * @param dev UART device struct
235 *
236 * @return 1 if an IRQ is pending, 0 otherwise
237 */
uart_liteuart_irq_is_pending(const struct device * dev)238 static int uart_liteuart_irq_is_pending(const struct device *dev)
239 {
240 uint8_t pending;
241
242 pending = sys_read8(UART_EV_PENDING);
243
244 if (pending & (UART_EV_TX | UART_EV_RX)) {
245 return 1;
246 } else {
247 return 0;
248 }
249 }
250
uart_liteuart_irq_update(const struct device * dev)251 static int uart_liteuart_irq_update(const struct device *dev)
252 {
253 return 1;
254 }
255
256 /**
257 * @brief Set the callback function pointer for IRQ.
258 *
259 * @param dev UART device struct
260 * @param cb Callback function pointer.
261 *
262 * @return N/A
263 */
uart_liteuart_irq_callback_set(const struct device * dev,uart_irq_callback_user_data_t cb,void * cb_data)264 static void uart_liteuart_irq_callback_set(const struct device *dev,
265 uart_irq_callback_user_data_t cb,
266 void *cb_data)
267 {
268 struct uart_liteuart_data *data;
269
270 data = (struct uart_liteuart_data *)dev->data;
271 data->callback = cb;
272 data->cb_data = cb_data;
273 }
274
liteuart_uart_irq_handler(const struct device * dev)275 static void liteuart_uart_irq_handler(const struct device *dev)
276 {
277 struct uart_liteuart_data *data = DEV_DATA(dev);
278 int key = irq_lock();
279
280 if (data->callback) {
281 data->callback(dev, data->cb_data);
282 }
283
284 /* clear events */
285 sys_write8(UART_EV_TX | UART_EV_RX, UART_EV_PENDING);
286
287 irq_unlock(key);
288 }
289 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
290
291 static const struct uart_driver_api uart_liteuart_driver_api = {
292 .poll_in = uart_liteuart_poll_in,
293 .poll_out = uart_liteuart_poll_out,
294 .err_check = NULL,
295 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
296 .fifo_fill = uart_liteuart_fifo_fill,
297 .fifo_read = uart_liteuart_fifo_read,
298 .irq_tx_enable = uart_liteuart_irq_tx_enable,
299 .irq_tx_disable = uart_liteuart_irq_tx_disable,
300 .irq_tx_ready = uart_liteuart_irq_tx_ready,
301 .irq_rx_enable = uart_liteuart_irq_rx_enable,
302 .irq_rx_disable = uart_liteuart_irq_rx_disable,
303 .irq_rx_ready = uart_liteuart_irq_rx_ready,
304 .irq_err_enable = uart_liteuart_irq_err,
305 .irq_err_disable = uart_liteuart_irq_err,
306 .irq_is_pending = uart_liteuart_irq_is_pending,
307 .irq_update = uart_liteuart_irq_update,
308 .irq_callback_set = uart_liteuart_irq_callback_set
309 #endif
310 };
311
312 static struct uart_liteuart_data uart_liteuart_data_0;
313 static int uart_liteuart_init(const struct device *dev);
314
315 static const struct uart_liteuart_device_config uart_liteuart_dev_cfg_0 = {
316 .port = UART_BASE_ADDR,
317 .baud_rate = DT_INST_PROP(0, current_speed)
318 };
319
320 DEVICE_DT_INST_DEFINE(0,
321 uart_liteuart_init,
322 NULL,
323 &uart_liteuart_data_0, &uart_liteuart_dev_cfg_0,
324 PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY,
325 (void *)&uart_liteuart_driver_api);
326
uart_liteuart_init(const struct device * dev)327 static int uart_liteuart_init(const struct device *dev)
328 {
329 sys_write8(UART_EV_TX | UART_EV_RX, UART_EV_PENDING);
330
331 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
332 IRQ_CONNECT(UART_IRQ, DT_INST_IRQ(0, priority),
333 liteuart_uart_irq_handler, DEVICE_DT_INST_GET(0),
334 0);
335 irq_enable(UART_IRQ);
336 #endif
337
338 return 0;
339 }
340