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