1 /*
2 * Copyright (c) 2023 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <errno.h>
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/uart.h>
10 #include <zephyr/pm/device.h>
11 #include <zephyr/pm/device_runtime.h>
12 #include "sedi_driver_uart.h"
13
14 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
15 static void uart_sedi_isr(void *arg);
16 static void uart_sedi_cb(struct device *port);
17 #endif
18
19 #define DT_DRV_COMPAT intel_sedi_uart
20
21 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
22 /* UART IRQ handler declaration. */
23 #define UART_IRQ_HANDLER_DECL(n) \
24 static void irq_config_uart_##n(const struct device *dev)
25
26 /* Setting configuration function. */
27 #define UART_CONFIG_IRQ_HANDLER_SET(n) \
28 .uart_irq_config_func = irq_config_uart_##n
29 #define UART_IRQ_HANDLER_DEFINE(n) \
30 static void irq_config_uart_##n(const struct device *dev) \
31 { \
32 ARG_UNUSED(dev); \
33 IRQ_CONNECT(DT_INST_IRQN(n), \
34 DT_INST_IRQ(n, priority), uart_sedi_isr, \
35 DEVICE_DT_GET(DT_NODELABEL(uart##n)), \
36 DT_INST_IRQ(n, sense)); \
37 irq_enable(DT_INST_IRQN(n)); \
38 }
39 #else /*CONFIG_UART_INTERRUPT_DRIVEN */
40 #define UART_IRQ_HANDLER_DECL(n)
41 #define UART_CONFIG_IRQ_HANDLER_SET(n) (0)
42
43 #define UART_IRQ_HANDLER_DEFINE(n)
44 #endif /* !CONFIG_UART_INTERRUPT_DRIVEN */
45
46 /* Device init macro for UART instance. As multiple uart instances follow a
47 * similar definition of data structures differing only in the instance
48 * number.This macro makes adding instances simpler.
49 */
50 #define UART_SEDI_DEVICE_INIT(n) \
51 UART_IRQ_HANDLER_DECL(n); \
52 static K_MUTEX_DEFINE(uart_##n##_mutex); \
53 static K_SEM_DEFINE(uart_##n##_tx_sem, 1, 1); \
54 static K_SEM_DEFINE(uart_##n##_rx_sem, 1, 1); \
55 static K_SEM_DEFINE(uart_##n##_sync_read_sem, 0, 1); \
56 static const struct uart_sedi_config_info config_info_##n = { \
57 DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \
58 .instance = DT_INST_PROP(n, peripheral_id), \
59 .baud_rate = DT_INST_PROP(n, current_speed), \
60 .hw_fc = DT_INST_PROP(n, hw_flow_control), \
61 .line_ctrl = SEDI_UART_LC_8N1, \
62 .mutex = &uart_##n##_mutex, \
63 UART_CONFIG_IRQ_HANDLER_SET(n) \
64 }; \
65 \
66 static struct uart_sedi_drv_data drv_data_##n; \
67 PM_DEVICE_DT_INST_DEFINE(n, \
68 uart_sedi_pm_action); \
69 DEVICE_DT_INST_DEFINE(n, \
70 &uart_sedi_init, \
71 PM_DEVICE_DT_INST_GET(n), \
72 &drv_data_##n, &config_info_##n, \
73 PRE_KERNEL_1, \
74 CONFIG_SERIAL_INIT_PRIORITY, &api); \
75 UART_IRQ_HANDLER_DEFINE(n)
76
77
78
79 /* Convenient macro to get the controller instance. */
80 #define GET_CONTROLLER_INSTANCE(dev) \
81 (((const struct uart_sedi_config_info *) \
82 dev->config)->instance)
83
84 #define GET_MUTEX(dev) \
85 (((const struct uart_sedi_config_info *) \
86 dev->config)->mutex)
87
88 struct uart_sedi_config_info {
89 DEVICE_MMIO_ROM;
90 /* Specifies the uart instance for configuration. */
91 sedi_uart_t instance;
92
93 /* Specifies the baudrate for the uart instance. */
94 uint32_t baud_rate;
95
96 /* Specifies the port line control settings */
97 sedi_uart_lc_t line_ctrl;
98
99 struct k_mutex *mutex;
100
101 /* Enable / disable hardware flow control for UART. */
102 bool hw_fc;
103
104 /* UART irq configuration function when supporting interrupt
105 * mode.
106 */
107 uart_irq_config_func_t uart_irq_config_func;
108 };
109
110
111 static int uart_sedi_init(const struct device *dev);
112
113 struct uart_sedi_drv_data {
114 DEVICE_MMIO_RAM;
115 uart_irq_callback_user_data_t user_cb;
116 void *unsol_rx_usr_cb_param;
117 uint32_t sync_rx_len;
118 uint32_t sync_rx_status;
119 void *user_data;
120 void *usr_rx_buff;
121 uint32_t usr_rx_size;
122 uint8_t iir_cache;
123 uint8_t busy_count;
124 };
125
126 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_busy_set(const struct device * dev)127 static void uart_busy_set(const struct device *dev)
128 {
129
130 struct uart_sedi_drv_data *context = dev->data;
131
132 context->busy_count++;
133
134 if (context->busy_count == 1) {
135 pm_device_busy_set(dev);
136 }
137 }
138
uart_busy_clear(const struct device * dev)139 static void uart_busy_clear(const struct device *dev)
140 {
141
142 struct uart_sedi_drv_data *context = dev->data;
143
144 context->busy_count--;
145
146 if (context->busy_count == 0) {
147 pm_device_busy_clear(dev);
148 }
149 }
150 #endif
151
152 #ifdef CONFIG_PM_DEVICE
153
154 #ifndef CONFIG_UART_CONSOLE
155
uart_suspend_device(const struct device * dev)156 static int uart_suspend_device(const struct device *dev)
157 {
158 const struct uart_sedi_config_info *config = dev->config;
159
160 if (pm_device_is_busy(dev)) {
161 return -EBUSY;
162 }
163
164 int ret = sedi_uart_set_power(config->instance, SEDI_POWER_SUSPEND);
165
166 if (ret != SEDI_DRIVER_OK) {
167 return -EIO;
168 }
169
170 return 0;
171 }
172
uart_resume_device_from_suspend(const struct device * dev)173 static int uart_resume_device_from_suspend(const struct device *dev)
174 {
175 const struct uart_sedi_config_info *config = dev->config;
176 int ret;
177
178 ret = sedi_uart_set_power(config->instance, SEDI_POWER_FULL);
179 if (ret != SEDI_DRIVER_OK) {
180 return -EIO;
181 }
182
183 return 0;
184 }
185
uart_sedi_pm_action(const struct device * dev,enum pm_device_action action)186 static int uart_sedi_pm_action(const struct device *dev,
187 enum pm_device_action action)
188 {
189 int ret = 0;
190
191 switch (action) {
192 case PM_DEVICE_ACTION_SUSPEND:
193 ret = uart_suspend_device(dev);
194 break;
195 case PM_DEVICE_ACTION_RESUME:
196 ret = uart_resume_device_from_suspend(dev);
197 break;
198
199 default:
200 ret = -ENOTSUP;
201 }
202 return ret;
203 }
204
205 #else
206
uart_sedi_pm_action(const struct device * dev,enum pm_device_action action)207 static int uart_sedi_pm_action(const struct device *dev,
208 enum pm_device_action action)
209 {
210 /* do nothing if using UART print log to avoid clock gating
211 * pm driver already handled power management for uart.
212 */
213 return 0;
214 }
215
216 #endif /* CONFIG_UART_CONSOLE */
217
218 #endif /* CONFIG_PM_DEVICE */
219
uart_sedi_poll_in(const struct device * dev,unsigned char * data)220 static int uart_sedi_poll_in(const struct device *dev, unsigned char *data)
221 {
222 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
223 uint32_t status;
224 int ret = 0;
225
226 (void)pm_device_runtime_get(dev);
227
228 sedi_uart_get_status(instance, (uint32_t *) &status);
229
230 /* In order to check if there is any data to read from UART
231 * controller we should check if the SEDI_UART_RX_BUSY bit from
232 * 'status' is not set. This bit is set only if there is any
233 * pending character to read.
234 */
235 if (!(status & SEDI_UART_RX_BUSY)) {
236 ret = -1;
237 } else {
238 if (sedi_uart_read(instance, data, (uint32_t *)&status)) {
239 ret = -1;
240 }
241 }
242
243 pm_device_runtime_put(dev);
244
245 return ret;
246 }
247
uart_sedi_poll_out(const struct device * dev,unsigned char data)248 static void uart_sedi_poll_out(const struct device *dev,
249 unsigned char data)
250 {
251 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
252
253 (void)pm_device_runtime_get(dev);
254
255 sedi_uart_write(instance, data);
256
257 pm_device_runtime_put(dev);
258 }
259
260 #ifdef CONFIG_UART_LINE_CTRL
get_xfer_error(int bsp_err)261 static int get_xfer_error(int bsp_err)
262 {
263 int err;
264
265 switch (bsp_err) {
266 case SEDI_DRIVER_OK:
267 err = 0;
268 break;
269 case SEDI_USART_ERROR_CANCELED:
270 err = -ECANCELED;
271 break;
272 case SEDI_DRIVER_ERROR:
273 err = -EIO;
274 break;
275 case SEDI_DRIVER_ERROR_PARAMETER:
276 err = -EINVAL;
277 break;
278 case SEDI_DRIVER_ERROR_UNSUPPORTED:
279 err = -ENOTSUP;
280 break;
281 default:
282 err = -EFAULT;
283 }
284 return err;
285 }
286 #endif /* CONFIG_UART_LINE_CTRL */
287
uart_sedi_err_check(const struct device * dev)288 static int uart_sedi_err_check(const struct device *dev)
289 {
290 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
291 uint32_t status;
292 int ret_status = 0;
293
294 (void)pm_device_runtime_get(dev);
295
296 sedi_uart_get_status(instance, (uint32_t *const)&status);
297 if (status & SEDI_UART_RX_OE) {
298 ret_status = UART_ERROR_OVERRUN;
299 }
300
301 if (status & SEDI_UART_RX_PE) {
302 ret_status = UART_ERROR_PARITY;
303 }
304
305 if (status & SEDI_UART_RX_FE) {
306 ret_status = UART_ERROR_FRAMING;
307 }
308
309 if (status & SEDI_UART_RX_BI) {
310 ret_status = UART_BREAK;
311 }
312
313 pm_device_runtime_put(dev);
314
315 return ret_status;
316 }
317
318
319 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
320
uart_sedi_fifo_fill(const struct device * dev,const uint8_t * tx_data,int size)321 static int uart_sedi_fifo_fill(const struct device *dev, const uint8_t *tx_data,
322 int size)
323 {
324 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
325 int ret = 0;
326
327 pm_device_runtime_get(dev);
328
329 ret = sedi_uart_fifo_fill(instance, tx_data, size);
330
331 pm_device_runtime_put(dev);
332
333 return ret;
334 }
335
uart_sedi_fifo_read(const struct device * dev,uint8_t * rx_data,const int size)336 static int uart_sedi_fifo_read(const struct device *dev, uint8_t *rx_data,
337 const int size)
338 {
339 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
340 int ret = 0;
341
342 pm_device_runtime_get(dev);
343
344 ret = sedi_uart_fifo_read(instance, rx_data, size);
345
346 pm_device_runtime_put(dev);
347
348 return ret;
349 }
350
uart_sedi_irq_tx_enable(const struct device * dev)351 static void uart_sedi_irq_tx_enable(const struct device *dev)
352 {
353 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
354
355 pm_device_runtime_get(dev);
356
357 sedi_uart_irq_tx_enable(instance);
358
359 pm_device_runtime_put(dev);
360 }
361
uart_sedi_irq_tx_disable(const struct device * dev)362 static void uart_sedi_irq_tx_disable(const struct device *dev)
363 {
364 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
365
366 pm_device_runtime_get(dev);
367
368 sedi_uart_irq_tx_disable(instance);
369
370 pm_device_runtime_put(dev);
371 }
372
uart_sedi_irq_tx_ready(const struct device * dev)373 static int uart_sedi_irq_tx_ready(const struct device *dev)
374 {
375 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
376
377 return sedi_uart_irq_tx_ready(instance);
378 }
379
uart_sedi_irq_tx_complete(const struct device * dev)380 static int uart_sedi_irq_tx_complete(const struct device *dev)
381 {
382 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
383 int ret = 0;
384
385 pm_device_runtime_get(dev);
386
387 ret = sedi_uart_is_tx_complete(instance);
388
389 pm_device_runtime_put(dev);
390
391 return ret;
392 }
393
uart_sedi_irq_rx_enable(const struct device * dev)394 static void uart_sedi_irq_rx_enable(const struct device *dev)
395 {
396 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
397
398 #ifdef CONFIG_PM_DEVICE_RUNTIME
399 pm_device_runtime_get(dev);
400 #else
401 uart_busy_set(dev);
402 #endif
403 sedi_uart_irq_rx_enable(instance);
404 }
405
uart_sedi_irq_rx_disable(const struct device * dev)406 static void uart_sedi_irq_rx_disable(const struct device *dev)
407 {
408 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
409
410 sedi_uart_irq_rx_disable(instance);
411 #ifdef CONFIG_PM_DEVICE_RUNTIME
412 pm_device_runtime_put(dev);
413 #else
414 uart_busy_clear(dev);
415 #endif
416 }
417
uart_sedi_irq_rx_ready(const struct device * dev)418 static int uart_sedi_irq_rx_ready(const struct device *dev)
419 {
420 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
421
422 return sedi_uart_is_irq_rx_ready(instance);
423 }
424
uart_sedi_irq_err_enable(const struct device * dev)425 static void uart_sedi_irq_err_enable(const struct device *dev)
426 {
427 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
428
429 pm_device_runtime_get(dev);
430
431 sedi_uart_irq_err_enable(instance);
432
433 pm_device_runtime_put(dev);
434 }
435
uart_sedi_irq_err_disable(const struct device * dev)436 static void uart_sedi_irq_err_disable(const struct device *dev)
437 {
438 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
439
440 pm_device_runtime_get(dev);
441
442 sedi_uart_irq_err_disable(instance);
443
444 pm_device_runtime_put(dev);
445 }
446
uart_sedi_irq_is_pending(const struct device * dev)447 static int uart_sedi_irq_is_pending(const struct device *dev)
448 {
449
450 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
451
452 return sedi_uart_is_irq_pending(instance);
453 }
454
uart_sedi_irq_update(const struct device * dev)455 static int uart_sedi_irq_update(const struct device *dev)
456 {
457 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
458
459 pm_device_runtime_get(dev);
460
461 sedi_uart_update_irq_cache(instance);
462
463 pm_device_runtime_put(dev);
464
465 return 1;
466 }
467
uart_sedi_irq_callback_set(const struct device * dev,uart_irq_callback_user_data_t cb,void * user_data)468 static void uart_sedi_irq_callback_set(const struct device *dev,
469 uart_irq_callback_user_data_t cb,
470 void *user_data)
471 {
472 struct uart_sedi_drv_data *drv_data = dev->data;
473
474 drv_data->user_cb = cb;
475 drv_data->user_data = user_data;
476
477 }
478
uart_sedi_isr(void * arg)479 static void uart_sedi_isr(void *arg)
480 {
481 struct device *dev = arg;
482 struct uart_sedi_drv_data *drv_data = dev->data;
483
484 if (drv_data->user_cb) {
485 drv_data->user_cb(dev, drv_data->user_data);
486 } else {
487 uart_sedi_cb(dev);
488 }
489 }
490
491 /* Called from generic callback of zephyr , set by set_cb. */
uart_sedi_cb(struct device * port)492 static void uart_sedi_cb(struct device *port)
493 {
494 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(port);
495
496 sedi_uart_isr_handler(instance);
497 }
498
499 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
500
501 #ifdef CONFIG_UART_LINE_CTRL
uart_sedi_line_ctrl_set(struct device * dev,uint32_t ctrl,uint32_t val)502 static int uart_sedi_line_ctrl_set(struct device *dev,
503 uint32_t ctrl, uint32_t val)
504 {
505 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
506 sedi_uart_config_t cfg;
507 uint32_t mask;
508 int ret;
509
510 k_mutex_lock(GET_MUTEX(dev), K_FOREVER);
511
512 pm_device_runtime_get(dev);
513
514 switch (ctrl) {
515 case UART_LINE_CTRL_BAUD_RATE:
516 sedi_uart_get_config(instance, &cfg);
517 cfg.baud_rate = val;
518 ret = sedi_uart_set_config(instance, &cfg);
519 break;
520
521 default:
522 ret = -ENODEV;
523 }
524
525 pm_device_runtime_put(dev);
526
527 k_mutex_unlock(GET_MUTEX(dev));
528 ret = get_xfer_error(ret);
529 return ret;
530 }
531
uart_sedi_line_ctrl_get(struct device * dev,uint32_t ctrl,uint32_t * val)532 static int uart_sedi_line_ctrl_get(struct device *dev,
533 uint32_t ctrl, uint32_t *val)
534 {
535 sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
536 sedi_uart_config_t cfg;
537 uint32_t mask;
538 int ret;
539
540 k_mutex_lock(GET_MUTEX(dev), K_FOREVER);
541
542 pm_device_runtime_get(dev);
543
544 switch (ctrl) {
545 case UART_LINE_CTRL_BAUD_RATE:
546 ret = sedi_uart_get_config(instance, &cfg);
547 *val = cfg.baud_rate;
548 break;
549
550 case UART_LINE_CTRL_LOOPBACK:
551 ret = sedi_uart_get_loopback_mode(instance, (uint32_t *)val);
552 break;
553
554 case UART_LINE_CTRL_AFCE:
555 ret = sedi_uart_get_config(instance, &cfg);
556 *val = cfg.hw_fc;
557 break;
558
559 case UART_LINE_CTRL_LINE_STATUS_REPORT_MASK:
560 mask = 0;
561 *val = 0;
562 ret = sedi_get_ln_status_report_mask(instance,
563 (uint32_t *)&mask);
564 *val |= ((mask & SEDI_UART_RX_OE) ? UART_ERROR_OVERRUN : 0);
565 *val |= ((mask & SEDI_UART_RX_PE) ? UART_ERROR_PARITY : 0);
566 *val |= ((mask & SEDI_UART_RX_FE) ? UART_ERROR_FRAMING : 0);
567 *val |= ((mask & SEDI_UART_RX_BI) ? UART_BREAK : 0);
568 break;
569
570 case UART_LINE_CTRL_RTS:
571 ret = sedi_uart_read_rts(instance, (uint32_t *)val);
572 break;
573
574 case UART_LINE_CTRL_CTS:
575 ret = sedi_uart_read_cts(instance, (uint32_t *)val);
576 break;
577
578
579 default:
580 ret = -ENODEV;
581 }
582
583 pm_device_runtime_put(dev);
584
585 k_mutex_unlock(GET_MUTEX(dev));
586 ret = get_xfer_error(ret);
587 return ret;
588 }
589
590 #endif /* CONFIG_UART_LINE_CTRL */
591
592 static DEVICE_API(uart, api) = {
593 .poll_in = uart_sedi_poll_in,
594 .poll_out = uart_sedi_poll_out,
595 .err_check = uart_sedi_err_check,
596 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
597 .fifo_fill = uart_sedi_fifo_fill,
598 .fifo_read = uart_sedi_fifo_read,
599 .irq_tx_enable = uart_sedi_irq_tx_enable,
600 .irq_tx_disable = uart_sedi_irq_tx_disable,
601 .irq_tx_ready = uart_sedi_irq_tx_ready,
602 .irq_tx_complete = uart_sedi_irq_tx_complete,
603 .irq_rx_enable = uart_sedi_irq_rx_enable,
604 .irq_rx_disable = uart_sedi_irq_rx_disable,
605 .irq_rx_ready = uart_sedi_irq_rx_ready,
606 .irq_err_enable = uart_sedi_irq_err_enable,
607 .irq_err_disable = uart_sedi_irq_err_disable,
608 .irq_is_pending = uart_sedi_irq_is_pending,
609 .irq_update = uart_sedi_irq_update,
610 .irq_callback_set = uart_sedi_irq_callback_set,
611 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
612 #ifdef CONFIG_UART_LINE_CTRL
613 .line_ctrl_set = uart_sedi_line_ctrl_set,
614 .line_ctrl_get = uart_sedi_line_ctrl_get,
615 #endif /* CONFIG_UART_LINE_CTRL */
616
617 };
618
uart_sedi_init(const struct device * dev)619 static int uart_sedi_init(const struct device *dev)
620 {
621
622 const struct uart_sedi_config_info *config = dev->config;
623 sedi_uart_config_t cfg;
624
625 DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
626 sedi_uart_init(config->instance, (void *)DEVICE_MMIO_GET(dev));
627
628 cfg.line_control = config->line_ctrl;
629 cfg.baud_rate = config->baud_rate;
630 cfg.hw_fc = config->hw_fc;
631
632 /* Setting to full power and enabling clk. */
633 sedi_uart_set_power(config->instance, SEDI_POWER_FULL);
634
635 sedi_uart_set_config(config->instance, &cfg);
636
637 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
638 config->uart_irq_config_func(dev);
639 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
640
641 pm_device_runtime_enable(dev);
642
643 return 0;
644 }
645
646 DT_INST_FOREACH_STATUS_OKAY(UART_SEDI_DEVICE_INIT)
647