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