1 /*
2 * Copyright (c) 2017 Jean-Paul Etienne <fractalclone@gmail.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @brief UART driver for the SiFive Freedom Processor
9 */
10
11 #define DT_DRV_COMPAT sifive_uart0
12
13 #include <zephyr/kernel.h>
14 #include <zephyr/arch/cpu.h>
15 #include <zephyr/drivers/uart.h>
16 #include <zephyr/drivers/pinctrl.h>
17 #include <soc.h>
18 #include <zephyr/irq.h>
19
20 #define RXDATA_EMPTY (1 << 31) /* Receive FIFO Empty */
21 #define RXDATA_MASK 0xFF /* Receive Data Mask */
22
23 #define TXDATA_FULL (1 << 31) /* Transmit FIFO Full */
24
25 #define TXCTRL_TXEN (1 << 0) /* Activate Tx Channel */
26
27 #define RXCTRL_RXEN (1 << 0) /* Activate Rx Channel */
28
29 #define IE_TXWM (1 << 0) /* TX Interrupt Enable/Pending */
30 #define IE_RXWM (1 << 1) /* RX Interrupt Enable/Pending */
31
32 /*
33 * RX/TX Threshold count to generate TX/RX Interrupts.
34 * Used by txctrl and rxctrl registers
35 */
36 #define CTRL_CNT(x) (((x) & 0x07) << 16)
37
38 struct uart_sifive_regs_t {
39 uint32_t tx;
40 uint32_t rx;
41 uint32_t txctrl;
42 uint32_t rxctrl;
43 uint32_t ie;
44 uint32_t ip;
45 uint32_t div;
46 };
47
48 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
49 typedef void (*irq_cfg_func_t)(void);
50 #endif
51
52 struct uart_sifive_device_config {
53 uintptr_t port;
54 uint32_t sys_clk_freq;
55 uint32_t baud_rate;
56 uint32_t rxcnt_irq;
57 uint32_t txcnt_irq;
58 const struct pinctrl_dev_config *pcfg;
59 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
60 irq_cfg_func_t cfg_func;
61 #endif
62 };
63
64 struct uart_sifive_data {
65 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
66 uart_irq_callback_user_data_t callback;
67 void *cb_data;
68 #endif
69 };
70
71 #define DEV_UART(dev) \
72 ((struct uart_sifive_regs_t *) \
73 ((const struct uart_sifive_device_config * const)(dev)->config)->port)
74
75 /**
76 * @brief Output a character in polled mode.
77 *
78 * Writes data to tx register if transmitter is not full.
79 *
80 * @param dev UART device struct
81 * @param c Character to send
82 */
uart_sifive_poll_out(const struct device * dev,unsigned char c)83 static void uart_sifive_poll_out(const struct device *dev,
84 unsigned char c)
85 {
86 volatile struct uart_sifive_regs_t *uart = DEV_UART(dev);
87
88 /* Wait while TX FIFO is full */
89 while (uart->tx & TXDATA_FULL) {
90 }
91
92 uart->tx = (int)c;
93 }
94
95 /**
96 * @brief Poll the device for input.
97 *
98 * @param dev UART device struct
99 * @param c Pointer to character
100 *
101 * @return 0 if a character arrived, -1 if the input buffer if empty.
102 */
uart_sifive_poll_in(const struct device * dev,unsigned char * c)103 static int uart_sifive_poll_in(const struct device *dev, unsigned char *c)
104 {
105 volatile struct uart_sifive_regs_t *uart = DEV_UART(dev);
106 uint32_t val = uart->rx;
107
108 if (val & RXDATA_EMPTY) {
109 return -1;
110 }
111
112 *c = (unsigned char)(val & RXDATA_MASK);
113
114 return 0;
115 }
116
117 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
118
119 /**
120 * @brief Fill FIFO with data
121 *
122 * @param dev UART device struct
123 * @param tx_data Data to transmit
124 * @param size Number of bytes to send
125 *
126 * @return Number of bytes sent
127 */
uart_sifive_fifo_fill(const struct device * dev,const uint8_t * tx_data,int size)128 static int uart_sifive_fifo_fill(const struct device *dev,
129 const uint8_t *tx_data,
130 int size)
131 {
132 volatile struct uart_sifive_regs_t *uart = DEV_UART(dev);
133 int i;
134
135 for (i = 0; i < size && !(uart->tx & TXDATA_FULL); i++) {
136 uart->tx = (int)tx_data[i];
137 }
138
139 return i;
140 }
141
142 /**
143 * @brief Read data from FIFO
144 *
145 * @param dev UART device struct
146 * @param rxData Data container
147 * @param size Container size
148 *
149 * @return Number of bytes read
150 */
uart_sifive_fifo_read(const struct device * dev,uint8_t * rx_data,const int size)151 static int uart_sifive_fifo_read(const struct device *dev,
152 uint8_t *rx_data,
153 const int size)
154 {
155 volatile struct uart_sifive_regs_t *uart = DEV_UART(dev);
156 int i;
157 uint32_t val;
158
159 for (i = 0; i < size; i++) {
160 val = uart->rx;
161
162 if (val & RXDATA_EMPTY) {
163 break;
164 }
165
166 rx_data[i] = (uint8_t)(val & RXDATA_MASK);
167 }
168
169 return i;
170 }
171
172 /**
173 * @brief Enable TX interrupt in ie register
174 *
175 * @param dev UART device struct
176 */
uart_sifive_irq_tx_enable(const struct device * dev)177 static void uart_sifive_irq_tx_enable(const struct device *dev)
178 {
179 volatile struct uart_sifive_regs_t *uart = DEV_UART(dev);
180
181 uart->ie |= IE_TXWM;
182 }
183
184 /**
185 * @brief Disable TX interrupt in ie register
186 *
187 * @param dev UART device struct
188 */
uart_sifive_irq_tx_disable(const struct device * dev)189 static void uart_sifive_irq_tx_disable(const struct device *dev)
190 {
191 volatile struct uart_sifive_regs_t *uart = DEV_UART(dev);
192
193 uart->ie &= ~IE_TXWM;
194 }
195
196 /**
197 * @brief Check if Tx IRQ has been raised
198 *
199 * @param dev UART device struct
200 *
201 * @return 1 if an IRQ is ready, 0 otherwise
202 */
uart_sifive_irq_tx_ready(const struct device * dev)203 static int uart_sifive_irq_tx_ready(const struct device *dev)
204 {
205 volatile struct uart_sifive_regs_t *uart = DEV_UART(dev);
206
207 return !!(uart->ip & IE_TXWM);
208 }
209
210 /**
211 * @brief Check if nothing remains to be transmitted
212 *
213 * @param dev UART device struct
214 *
215 * @return 1 if nothing remains to be transmitted, 0 otherwise
216 */
uart_sifive_irq_tx_complete(const struct device * dev)217 static int uart_sifive_irq_tx_complete(const struct device *dev)
218 {
219 volatile struct uart_sifive_regs_t *uart = DEV_UART(dev);
220
221 /*
222 * No TX EMPTY flag for this controller,
223 * just check if TX FIFO is not full
224 */
225 return !(uart->tx & TXDATA_FULL);
226 }
227
228 /**
229 * @brief Enable RX interrupt in ie register
230 *
231 * @param dev UART device struct
232 */
uart_sifive_irq_rx_enable(const struct device * dev)233 static void uart_sifive_irq_rx_enable(const struct device *dev)
234 {
235 volatile struct uart_sifive_regs_t *uart = DEV_UART(dev);
236
237 uart->ie |= IE_RXWM;
238 }
239
240 /**
241 * @brief Disable RX interrupt in ie register
242 *
243 * @param dev UART device struct
244 */
uart_sifive_irq_rx_disable(const struct device * dev)245 static void uart_sifive_irq_rx_disable(const struct device *dev)
246 {
247 volatile struct uart_sifive_regs_t *uart = DEV_UART(dev);
248
249 uart->ie &= ~IE_RXWM;
250 }
251
252 /**
253 * @brief Check if Rx IRQ has been raised
254 *
255 * @param dev UART device struct
256 *
257 * @return 1 if an IRQ is ready, 0 otherwise
258 */
uart_sifive_irq_rx_ready(const struct device * dev)259 static int uart_sifive_irq_rx_ready(const struct device *dev)
260 {
261 volatile struct uart_sifive_regs_t *uart = DEV_UART(dev);
262
263 return !!(uart->ip & IE_RXWM);
264 }
265
266 /* No error interrupt for this controller */
uart_sifive_irq_err_enable(const struct device * dev)267 static void uart_sifive_irq_err_enable(const struct device *dev)
268 {
269 ARG_UNUSED(dev);
270 }
271
uart_sifive_irq_err_disable(const struct device * dev)272 static void uart_sifive_irq_err_disable(const struct device *dev)
273 {
274 ARG_UNUSED(dev);
275 }
276
277 /**
278 * @brief Check if any IRQ is pending
279 *
280 * @param dev UART device struct
281 *
282 * @return 1 if an IRQ is pending, 0 otherwise
283 */
uart_sifive_irq_is_pending(const struct device * dev)284 static int uart_sifive_irq_is_pending(const struct device *dev)
285 {
286 volatile struct uart_sifive_regs_t *uart = DEV_UART(dev);
287
288 return !!(uart->ip & (IE_RXWM | IE_TXWM));
289 }
290
uart_sifive_irq_update(const struct device * dev)291 static int uart_sifive_irq_update(const struct device *dev)
292 {
293 return 1;
294 }
295
296 /**
297 * @brief Set the callback function pointer for IRQ.
298 *
299 * @param dev UART device struct
300 * @param cb Callback function pointer.
301 */
uart_sifive_irq_callback_set(const struct device * dev,uart_irq_callback_user_data_t cb,void * cb_data)302 static void uart_sifive_irq_callback_set(const struct device *dev,
303 uart_irq_callback_user_data_t cb,
304 void *cb_data)
305 {
306 struct uart_sifive_data *data = dev->data;
307
308 data->callback = cb;
309 data->cb_data = cb_data;
310 }
311
uart_sifive_irq_handler(const struct device * dev)312 static void uart_sifive_irq_handler(const struct device *dev)
313 {
314 struct uart_sifive_data *data = dev->data;
315
316 if (data->callback) {
317 data->callback(dev, data->cb_data);
318 }
319 }
320
321 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
322
323
uart_sifive_init(const struct device * dev)324 static int uart_sifive_init(const struct device *dev)
325 {
326 const struct uart_sifive_device_config * const cfg = dev->config;
327 volatile struct uart_sifive_regs_t *uart = DEV_UART(dev);
328 #ifdef CONFIG_PINCTRL
329 int ret;
330 #endif
331
332 /* Enable TX and RX channels */
333 uart->txctrl = TXCTRL_TXEN | CTRL_CNT(cfg->txcnt_irq);
334 uart->rxctrl = RXCTRL_RXEN | CTRL_CNT(cfg->rxcnt_irq);
335
336 /* Set baud rate */
337 uart->div = cfg->sys_clk_freq / cfg->baud_rate - 1;
338
339 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
340 /* Ensure that uart IRQ is disabled initially */
341 uart->ie = 0U;
342
343 /* Setup IRQ handler */
344 cfg->cfg_func();
345 #endif
346
347 #ifdef CONFIG_PINCTRL
348 ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
349 if (ret < 0) {
350 return ret;
351 }
352 #endif
353
354 return 0;
355 }
356
357 static DEVICE_API(uart, uart_sifive_driver_api) = {
358 .poll_in = uart_sifive_poll_in,
359 .poll_out = uart_sifive_poll_out,
360 .err_check = NULL,
361 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
362 .fifo_fill = uart_sifive_fifo_fill,
363 .fifo_read = uart_sifive_fifo_read,
364 .irq_tx_enable = uart_sifive_irq_tx_enable,
365 .irq_tx_disable = uart_sifive_irq_tx_disable,
366 .irq_tx_ready = uart_sifive_irq_tx_ready,
367 .irq_tx_complete = uart_sifive_irq_tx_complete,
368 .irq_rx_enable = uart_sifive_irq_rx_enable,
369 .irq_rx_disable = uart_sifive_irq_rx_disable,
370 .irq_rx_ready = uart_sifive_irq_rx_ready,
371 .irq_err_enable = uart_sifive_irq_err_enable,
372 .irq_err_disable = uart_sifive_irq_err_disable,
373 .irq_is_pending = uart_sifive_irq_is_pending,
374 .irq_update = uart_sifive_irq_update,
375 .irq_callback_set = uart_sifive_irq_callback_set,
376 #endif
377 };
378
379 #ifdef CONFIG_UART_SIFIVE_PORT_0
380
381 static struct uart_sifive_data uart_sifive_data_0;
382
383 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
384 static void uart_sifive_irq_cfg_func_0(void);
385 #endif
386
387 PINCTRL_DT_INST_DEFINE(0);
388
389 static const struct uart_sifive_device_config uart_sifive_dev_cfg_0 = {
390 .port = DT_INST_REG_ADDR(0),
391 .sys_clk_freq = SIFIVE_PERIPHERAL_CLOCK_FREQUENCY,
392 .baud_rate = DT_INST_PROP(0, current_speed),
393 .rxcnt_irq = CONFIG_UART_SIFIVE_PORT_0_RXCNT_IRQ,
394 .txcnt_irq = CONFIG_UART_SIFIVE_PORT_0_TXCNT_IRQ,
395 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
396 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
397 .cfg_func = uart_sifive_irq_cfg_func_0,
398 #endif
399 };
400
401 DEVICE_DT_INST_DEFINE(0,
402 uart_sifive_init,
403 NULL,
404 &uart_sifive_data_0, &uart_sifive_dev_cfg_0,
405 PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY,
406 (void *)&uart_sifive_driver_api);
407
408
409 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_sifive_irq_cfg_func_0(void)410 static void uart_sifive_irq_cfg_func_0(void)
411 {
412 IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority),
413 uart_sifive_irq_handler, DEVICE_DT_INST_GET(0),
414 0);
415
416 irq_enable(DT_INST_IRQN(0));
417 }
418 #endif
419
420 #endif /* CONFIG_UART_SIFIVE_PORT_0 */
421
422 #ifdef CONFIG_UART_SIFIVE_PORT_1
423
424 static struct uart_sifive_data uart_sifive_data_1;
425
426 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
427 static void uart_sifive_irq_cfg_func_1(void);
428 #endif
429
430 PINCTRL_DT_INST_DEFINE(1);
431
432 static const struct uart_sifive_device_config uart_sifive_dev_cfg_1 = {
433 .port = DT_INST_REG_ADDR(1),
434 .sys_clk_freq = SIFIVE_PERIPHERAL_CLOCK_FREQUENCY,
435 .baud_rate = DT_INST_PROP(1, current_speed),
436 .rxcnt_irq = CONFIG_UART_SIFIVE_PORT_1_RXCNT_IRQ,
437 .txcnt_irq = CONFIG_UART_SIFIVE_PORT_1_TXCNT_IRQ,
438 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(1),
439 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
440 .cfg_func = uart_sifive_irq_cfg_func_1,
441 #endif
442 };
443
444 DEVICE_DT_INST_DEFINE(1,
445 uart_sifive_init,
446 NULL,
447 &uart_sifive_data_1, &uart_sifive_dev_cfg_1,
448 PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY,
449 (void *)&uart_sifive_driver_api);
450
451 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_sifive_irq_cfg_func_1(void)452 static void uart_sifive_irq_cfg_func_1(void)
453 {
454 IRQ_CONNECT(DT_INST_IRQN(1), DT_INST_IRQ(1, priority),
455 uart_sifive_irq_handler, DEVICE_DT_INST_GET(1),
456 0);
457
458 irq_enable(DT_INST_IRQN(1));
459 }
460 #endif
461
462 #endif /* CONFIG_UART_SIFIVE_PORT_1 */
463