1 /*
2 * Copyright (c) 2023 Intel Corporation
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include "sedi_driver_uart.h"
8 #include "sedi_driver_pm.h"
9 #include <sedi_uart_regs.h>
10
11 #define HAS_ADVANCED_UART_CONFIGURATION (0)
12 #define HAS_UART_RS485_SUPPORT (0)
13 #define HAS_UART_9BIT_SUPPORT (0)
14 #define HAS_UART_SOFT_RST (0)
15
16 /* No interrupt pending */
17 #define SEDI_UART_IIR_NO_INTERRUPT_PENDING (0x01)
18 /* Transmit Holding Register Empty. */
19 #define SEDI_UART_IIR_THR_EMPTY (0x02)
20 /* Received Data Available. */
21 #define SEDI_UART_IIR_RECV_DATA_AVAIL (0x04)
22 /* Receiver Line Status. */
23 #define SEDI_UART_IIR_RECV_LINE_STATUS (0x06)
24 /* Character Timeout. */
25 #define SEDI_UART_IIR_CHAR_TIMEOUT (0x0C)
26 /* Interrupt ID Mask. */
27 #define SEDI_UART_IIR_IID_MASK (0x0F)
28
29 /* Default FIFO RX & TX Thresholds, half full for both. */
30 #define SEDI_UART_FCR_DEFAULT_TX_RX_THRESHOLD (0xB0)
31 /* Change TX Threshold to empty, keep RX Threshold to default. */
32 #define SEDI_UART_FCR_TX_0_RX_1_2_THRESHOLD (0x80)
33
34 #define BSETS_UART_LSR_ERROR \
35 (SEDI_RBFVM(UART, LSR, OE, OVER_RUN_ERROR) | SEDI_RBFVM(UART, LSR, PE, PARITY_ERROR) | \
36 SEDI_RBFVM(UART, LSR, FE, FRAMING_ERROR) | SEDI_RBFVM(UART, LSR, BI, BREAK))
37
38 /* SCR bit to indicate updated status for LSR. */
39 #define SEDI_UART_SCR_STATUS_UPDATE (0x1)
40
41 /* FIFO Depth. */
42 #define SEDI_UART_FIFO_DEPTH (64)
43 /* FIFO Half Depth. */
44 #define SEDI_UART_FIFO_HALF_DEPTH (SEDI_UART_FIFO_DEPTH / 2)
45
46 /* At 100Mhz clock. */
47 /* Serial clock period in NS. */
48 #define SEDI_UART_SERIAL_CLK_PERIOD_NS (10)
49 /* Max DE signal assertion , deassertion time in NS. */
50 #define SEDI_UART_DE_AT_DT_NS_MAX (2550)
51 /* Max Turnaround time in NS. */
52 #define SEDI_UART_TAT_NS_MAX (655350)
53
54 /** Full Duplex mode. */
55 #define SEDI_UART_XFER_MODE_FULL_DUPLEX (0)
56
57 /** Software Controlled Half Duplex mode. */
58 #define SEDI_UART_XFER_MODE_SW_HALF_DUPLEX (1)
59
60 /** Hardware Controlled Half Duplex mode. */
61 #define SEDI_UART_XFER_MODE_HW_HALF_DUPLEX (2)
62
63 /* Multiplier for improving rounding accuracy in uart DLF */
64 #define SEDI_UART_DLF_SCALAR (100)
65
66 /* Get the lower byte from the divisor.*/
67 #define SEDI_UART_GET_DLL(divisor) ((divisor) & 0xFF)
68
69 /* Get the higher byte from the divisor. */
70 #define SEDI_UART_GET_DLH(divisor) (((divisor) & 0xFF00) >> 8)
71
72 /* Packs the assertion and deassertion time to a uint32_t. */
73 #define SEDI_UART_DET_AT_DT_PACK(assertion_time, de_assertion_time) \
74 ((uint32_t)(((uint32_t)(assertion_time)) << SEDI_RBFO(UART, DET, DE_Assertion_Time) | \
75 ((uint32_t)(de_assertion_time)) \
76 << SEDI_RBFO(UART, DET, DE_De_assertion_Time)))
77
78 /* Packs the de to re and re to de times to a uint32_t. */
79 #define SEDI_UART_TAT_PACK(de_to_re, re_to_de) \
80 ((uint32_t)(((uint32_t)(de_to_re)) << SEDI_RBFO(UART, TAT, DE_to_RE) | \
81 ((uint32_t)(re_to_de)) << SEDI_RBFO(UART, TAT, RE_to_DE)))
82
83 /**
84 * UART context to be saved between sleep/resume.
85 *
86 * Application should not modify the content.
87 * This structure is only intended to be used by the sedi_uart_save_context and
88 * sedi_uart_restore_context functions.
89 */
90 typedef struct {
91 uint32_t ier; /**< Interrupt Enable Register. */
92 uint32_t dlh; /**< Divisor Latch High. */
93 uint32_t dll; /**< Divisor Latch Low. */
94 uint32_t lcr; /**< Line Control. */
95 uint32_t mcr; /**< Modem Control. */
96 uint32_t scr; /**< Scratchpad. */
97 uint32_t htx; /**< Halt Transmission. */
98 uint32_t dlf; /**< Divisor Latch Fraction. */
99 #if (HAS_UART_RS485_SUPPORT)
100 uint32_t tcr; /**< Transmission Control Register. */
101 uint32_t de_en; /**< Driver Enable. */
102 uint32_t re_en; /**< Receiver Enable. */
103 uint32_t det; /**< Driver-output Enable Timing. */
104 uint32_t tat; /**< Turn Around Timing. */
105 #endif
106 #if (HAS_UART_9BIT_SUPPORT)
107 uint32_t rar; /**< Receive Address Register. */
108 uint32_t tar; /**< Transmit Address Register. */
109 uint32_t lcr_ext; /**< Line extended Control Register. */
110 #endif
111 bool context_valid; /**< Indicates whether saved context is valid. */
112 } sedi_uart_context_t;
113
114 static sedi_uart_context_t uart_context[SEDI_UART_NUM];
115
116 static sedi_uart_regs_t *sedi_uart[SEDI_UART_NUM] = {(sedi_uart_regs_t *)SEDI_IREG_BASE(UART, 0),
117 (sedi_uart_regs_t *)SEDI_IREG_BASE(UART, 1),
118 (sedi_uart_regs_t *)SEDI_IREG_BASE(UART, 2)};
119
120 #define SEDI_UART sedi_uart
121
122 /* Transmit & Receive control. */
123 typedef struct {
124 uint8_t tx_disable: 1;
125 uint8_t rx_disable: 1;
126 } uart_xfer_ctrl_t;
127
128 static uart_xfer_ctrl_t uart_xfer_ctrl[SEDI_UART_NUM];
129
130 /* Buffer pointers to store transmit / receive data for UART. */
131 static uint32_t write_pos[SEDI_UART_NUM];
132 static uint32_t read_pos[SEDI_UART_NUM];
133 static const sedi_uart_transfer_t *uart_read_transfer[SEDI_UART_NUM];
134 static const sedi_uart_transfer_t *uart_write_transfer[SEDI_UART_NUM];
135 static uint32_t iir_cache[SEDI_UART_NUM];
136 static uint32_t baud_rate_cache[SEDI_UART_NUM];
137 static uint32_t clk_speed_cache[SEDI_UART_NUM];
138 static uint32_t status_report_mask[SEDI_UART_NUM] = {BSETS_UART_LSR_ERROR, BSETS_UART_LSR_ERROR,
139 BSETS_UART_LSR_ERROR};
140
141 typedef struct {
142 uint32_t enable_unsol_rx;
143 int32_t read_idx;
144 int32_t write_idx;
145 int32_t curr_len;
146 const sedi_uart_unsol_rx_t *unsol_rx;
147 } unsol_read_context_t;
148
149 unsol_read_context_t unsol_read_ctxt[SEDI_UART_NUM];
150
151 typedef struct {
152 sedi_uart_transfer_t xfer;
153 const sedi_uart_io_vec_xfer_t *vec;
154 uint32_t curr_count;
155 uint8_t active;
156 } io_vec_cntxt_t;
157
158 static io_vec_cntxt_t vec_read_ctxt[SEDI_UART_NUM];
159 static io_vec_cntxt_t vec_write_ctxt[SEDI_UART_NUM];
160
161 typedef enum {
162 WRITE,
163 READ
164 } dma_operation_type_t;
165
166 typedef struct {
167 const sedi_uart_dma_xfer_t *dma_xfer;
168 sedi_uart_t uart;
169 dma_operation_type_t operation; /* READ/WRITE */
170 } uart_dma_ctxt_t;
171
172 static uint32_t uart_dma_hs_id[SEDI_UART_NUM];
173
174 static uart_dma_ctxt_t dma_write_ctxt[SEDI_UART_NUM] = {
175 {.dma_xfer = NULL, .uart = SEDI_UART_0, .operation = WRITE},
176 {.dma_xfer = NULL, .uart = SEDI_UART_1, .operation = WRITE},
177 {.dma_xfer = NULL, .uart = SEDI_UART_2, .operation = WRITE}
178 };
179
180 static uart_dma_ctxt_t dma_read_ctxt[SEDI_UART_NUM] = {
181 {.dma_xfer = NULL, .uart = SEDI_UART_0, .operation = READ},
182 {.dma_xfer = NULL, .uart = SEDI_UART_1, .operation = READ},
183 {.dma_xfer = NULL, .uart = SEDI_UART_2, .operation = READ}
184 };
185
186 /* DMA driver requires to have a callback to be provided during init even
187 * when in polled mode. Adding a dummy callback for this.
188 */
sedi_dma_poll_dummy_cb(IN sedi_dma_t dma_dev,IN int channel,IN int event,INOUT void * param)189 static void sedi_dma_poll_dummy_cb(IN sedi_dma_t dma_dev, IN int channel, IN int event,
190 INOUT void *param)
191 {
192 PARAM_UNUSED(event);
193 PARAM_UNUSED(param);
194 PARAM_UNUSED(dma_dev);
195 PARAM_UNUSED(channel);
196 }
197
sedi_dma_event_cb(IN sedi_dma_t dma_device,IN int channel_id,IN int event,INOUT void * param)198 static void sedi_dma_event_cb(IN sedi_dma_t dma_device, IN int channel_id, IN int event,
199 INOUT void *param)
200 {
201 (void)dma_device;
202 (void)channel_id;
203 uart_dma_ctxt_t *ctxt = (uart_dma_ctxt_t *)(param);
204 sedi_uart_dma_xfer_t *xfer = (sedi_uart_dma_xfer_t *)(ctxt->dma_xfer);
205
206 /* Program next transfer. */
207 sedi_uart_regs_t *const regs = SEDI_UART[ctxt->uart];
208 uint32_t line_err_status = (regs->lsr & BSETS_UART_LSR_ERROR);
209
210 if (ctxt->operation == READ) {
211 if (event == SEDI_DMA_EVENT_TRANSFER_DONE) {
212 if (xfer->callback) {
213 xfer->callback(xfer->cb_param, SEDI_DRIVER_OK, line_err_status,
214 xfer->len);
215 }
216 } else {
217 if (xfer->callback) {
218 xfer->callback(xfer->cb_param, SEDI_DRIVER_ERROR, line_err_status,
219 xfer->len);
220 }
221 }
222 } else if (ctxt->operation == WRITE) {
223 if (event == SEDI_DMA_EVENT_TRANSFER_DONE) {
224 /* wait for transfer to complete as data may
225 * still be in the fifo/ tx shift regs.
226 */
227 while (!(regs->lsr & SEDI_RBFVM(UART, LSR, TEMT, ENABLED))) {
228 }
229 if (xfer->callback) {
230 xfer->callback(xfer->cb_param, SEDI_DRIVER_OK, line_err_status,
231 xfer->len);
232 }
233 } else {
234 if (xfer->callback) {
235 xfer->callback(xfer->cb_param, SEDI_DRIVER_ERROR, line_err_status,
236 xfer->len);
237 }
238 }
239 }
240
241 ctxt->dma_xfer = NULL;
242 }
243
244 #if HAS_UART_SOFT_RST
245 /* Soft reset all instances if not done before */
uart_soft_rst(void)246 static void uart_soft_rst(void)
247 {
248 static bool uart_rst_done;
249 volatile uint32_t *rst_reg = (uint32_t *)(SEDI_UART_SFT_RST_REG);
250
251 if (!uart_rst_done) {
252 *rst_reg = SEDI_UART_SFT_RST_MASK;
253 *rst_reg = 0;
254 uart_rst_done = true;
255 }
256 }
257
uart_soft_rst_instance(sedi_uart_t uart)258 static void uart_soft_rst_instance(sedi_uart_t uart)
259 {
260 volatile uint32_t *rst_reg = (uint32_t *)(SEDI_UART_SFT_RST_REG);
261
262 *rst_reg |= (1 << uart);
263 *rst_reg &= (~(1 << uart));
264
265 /* Wait till reset bit is cleared */
266 while (*rst_reg & (1 << uart)) {
267 __asm volatile("nop");
268 }
269 }
270 #endif
271
io_vec_write_callback(void * data,int error,uint32_t status,uint32_t len)272 static void io_vec_write_callback(void *data, int error, uint32_t status, uint32_t len)
273 {
274
275 sedi_uart_t uart = (sedi_uart_t)(data);
276 const sedi_uart_io_vec_xfer_t *const vec_xfer = vec_write_ctxt[uart].vec;
277
278 uint32_t current_count;
279
280 /* Increment the next count */
281 current_count = ++vec_write_ctxt[uart].curr_count;
282 PARAM_UNUSED(len);
283
284 /* Error in write or transfer completed , call user callback.*/
285 if (status || (current_count == vec_xfer->count)) {
286 if (vec_xfer->callback) {
287
288 /* Call callback with error. */
289 vec_xfer->callback(vec_xfer->cb_data, error, status, current_count);
290 }
291 /* Set active xfer to false. */
292 vec_write_ctxt[uart].active = false;
293 return;
294 }
295
296 /* Program next transfer. */
297 sedi_uart_regs_t *const regs = SEDI_UART[uart];
298
299 vec_write_ctxt[uart].xfer.data = vec_xfer->vec[current_count].base;
300 vec_write_ctxt[uart].xfer.data_len = vec_xfer->vec[current_count].len;
301 write_pos[uart] = 0;
302 uart_write_transfer[uart] = &vec_write_ctxt[uart].xfer;
303
304 /* Wait for last write transfer to finish completely. */
305 while (!(regs->lsr & SEDI_RBFVM(UART, LSR, TEMT, ENABLED))) {
306 }
307
308 regs->iir_fcr = (SEDI_RBFM(UART, IIR, FIFOE) | SEDI_UART_FCR_TX_0_RX_1_2_THRESHOLD);
309
310 /* Enable TX holding reg empty interrupt. */
311 regs->ier_dlh |= SEDI_RBFVM(UART, IER, ETBEI, ENABLE);
312 }
313
io_vec_read_callback(void * data,int error,uint32_t status,uint32_t len)314 static void io_vec_read_callback(void *data, int error, uint32_t status, uint32_t len)
315 {
316 sedi_uart_t uart = (sedi_uart_t)(data);
317 const sedi_uart_io_vec_xfer_t *const vec_xfer = vec_read_ctxt[uart].vec;
318 uint32_t current_count;
319
320 PARAM_UNUSED(len);
321
322 /* Increment the next count */
323 current_count = ++vec_read_ctxt[uart].curr_count;
324
325 /* Error in read or read completes, call user callback.*/
326 if (status || (current_count == vec_xfer->count)) {
327 if (vec_xfer->callback) {
328 /* Call callback with error. */
329 vec_xfer->callback(vec_xfer->cb_data, error, status, current_count);
330 }
331 /* Set active xfer to false. */
332 vec_read_ctxt[uart].active = false;
333 return;
334 }
335
336 /* Program next transfer */
337 sedi_uart_regs_t *const regs = SEDI_UART[uart];
338
339 vec_read_ctxt[uart].xfer.data = vec_xfer->vec[current_count].base;
340 vec_read_ctxt[uart].xfer.data_len = vec_xfer->vec[current_count].len;
341 read_pos[uart] = 0;
342 uart_read_transfer[uart] = &vec_read_ctxt[uart].xfer;
343
344 /* Set threshold. */
345 regs->iir_fcr =
346 (SEDI_RBFVM(UART, IIR, FIFOE, ENABLE) | SEDI_UART_FCR_TX_0_RX_1_2_THRESHOLD);
347
348 /*
349 * Enable both 'Receiver Data Available' and 'Receiver
350 * Line Status' interrupts.
351 */
352 regs->ier_dlh |= SEDI_RBFVM(UART, IER, ERBFI, ENABLE) | SEDI_RBFVM(UART, IER, ELSI, ENABLE);
353 }
354
is_read_xfer_complete(const sedi_uart_t uart)355 static bool is_read_xfer_complete(const sedi_uart_t uart)
356 {
357 const sedi_uart_transfer_t *const transfer = uart_read_transfer[uart];
358
359 return read_pos[uart] >= transfer->data_len;
360 }
361
is_write_xfer_complete(const sedi_uart_t uart)362 static bool is_write_xfer_complete(const sedi_uart_t uart)
363 {
364 const sedi_uart_transfer_t *const transfer = uart_write_transfer[uart];
365
366 return write_pos[uart] >= transfer->data_len;
367 }
368
handle_unsol_rx_data(const sedi_uart_t uart)369 static void handle_unsol_rx_data(const sedi_uart_t uart)
370 {
371 sedi_uart_regs_t *const regs = SEDI_UART[uart];
372 uint32_t lsr = regs->lsr;
373 const sedi_uart_unsol_rx_t *const unsol_rx = unsol_read_ctxt[uart].unsol_rx;
374 int32_t write_idx = unsol_read_ctxt[uart].write_idx;
375 int32_t read_idx = unsol_read_ctxt[uart].read_idx;
376
377 while (lsr & SEDI_RBFVM(UART, LSR, DR, READY)) {
378 write_idx++;
379 if (write_idx == unsol_rx->size) {
380 write_idx = 0;
381 }
382 unsol_rx->buffer[write_idx] = regs->rbr_thr_dll;
383 lsr = regs->lsr;
384 }
385 unsol_read_ctxt[uart].write_idx = write_idx;
386 if (read_idx < write_idx) {
387 unsol_read_ctxt[uart].curr_len = write_idx - read_idx;
388 } else {
389 unsol_read_ctxt[uart].curr_len = unsol_rx->size - read_idx + write_idx;
390 }
391 unsol_rx->unsol_rx_callback(unsol_rx->cb_data, SEDI_DRIVER_OK, SEDI_UART_IDLE,
392 unsol_read_ctxt[uart].curr_len);
393 }
394
handle_unsol_rx_error(const sedi_uart_t uart,uint32_t line_status)395 static void handle_unsol_rx_error(const sedi_uart_t uart, uint32_t line_status)
396 {
397 const sedi_uart_unsol_rx_t *const unsol_rx = unsol_read_ctxt[uart].unsol_rx;
398
399 unsol_rx->unsol_rx_callback(unsol_rx->cb_data, SEDI_DRIVER_ERROR, line_status,
400 unsol_read_ctxt[uart].curr_len);
401 }
402
is_tx_disabled(const sedi_uart_t uart)403 static bool is_tx_disabled(const sedi_uart_t uart)
404 {
405 return uart_xfer_ctrl[uart].tx_disable;
406 }
407
is_rx_disabled(const sedi_uart_t uart)408 static bool is_rx_disabled(const sedi_uart_t uart)
409 {
410 return uart_xfer_ctrl[uart].rx_disable;
411 }
412
sedi_uart_isr_handler(const sedi_uart_t uart)413 void sedi_uart_isr_handler(const sedi_uart_t uart)
414 {
415 sedi_uart_regs_t *const regs = SEDI_UART[uart];
416 uint8_t interrupt_id = regs->iir_fcr & SEDI_UART_IIR_IID_MASK;
417 const sedi_uart_transfer_t *const read_transfer = uart_read_transfer[uart];
418 const sedi_uart_transfer_t *const write_transfer = uart_write_transfer[uart];
419 uint32_t line_status;
420
421 /*
422 * Interrupt ID priority levels (from highest to lowest):
423 * 1: SEDI_UART_IIR_RECV_LINE_STATUS
424 * 2: SEDI_UART_IIR_RECV_DATA_AVAIL and SEDI_UART_IIR_CHAR_TIMEOUT
425 * 3: SEDI_UART_IIR_THR_EMPTY
426 */
427 switch (interrupt_id) {
428 /* Spurious interrupt */
429 case SEDI_UART_IIR_NO_INTERRUPT_PENDING:
430 break;
431
432 case SEDI_UART_IIR_THR_EMPTY:
433 if (write_transfer) {
434 if (is_write_xfer_complete(uart)) {
435 regs->ier_dlh &= ~SEDI_RBFVM(UART, IER, ETBEI, ENABLE);
436
437 /*
438 * At this point the FIFOs are empty, but the
439 * shift
440 * register still is transmitting the last 8
441 * bits. So if
442 * we were to read LSR, it would say the device
443 * is still
444 * busy. Use the SCR Bit 0 to indicate an irq tx
445 * is
446 * complete.
447 */
448 regs->scr |= SEDI_UART_SCR_STATUS_UPDATE;
449 if (write_transfer->callback) {
450 write_transfer->callback(write_transfer->callback_data, 0,
451 SEDI_UART_IDLE, write_pos[uart]);
452 }
453
454 if (vec_write_ctxt[uart].active == false) {
455 uart_write_transfer[uart] = NULL;
456 }
457 return;
458 }
459 /*
460 * If we are starting the transfer then the TX FIFO is
461 * empty.
462 * In that case we set 'count' variable to
463 * SEDI_UART_FIFO_DEPTH
464 * in order to take advantage of the whole FIFO
465 * capacity.
466 */
467 int count = (write_pos[uart] == 0) ? SEDI_UART_FIFO_DEPTH
468 : SEDI_UART_FIFO_HALF_DEPTH;
469 while (count-- && !is_write_xfer_complete(uart)) {
470 regs->rbr_thr_dll = write_transfer->data[write_pos[uart]++];
471 }
472
473 /*
474 * Change the threshold level to trigger an interrupt
475 * when the
476 * TX buffer is empty.
477 */
478 if (is_write_xfer_complete(uart)) {
479 regs->iir_fcr = SEDI_UART_FCR_TX_0_RX_1_2_THRESHOLD |
480 SEDI_RBFVM(UART, IIR, FIFOE, ENABLE);
481 }
482 }
483 break;
484
485 case SEDI_UART_IIR_CHAR_TIMEOUT:
486 case SEDI_UART_IIR_RECV_DATA_AVAIL:
487 if (read_transfer) {
488 /*
489 * Copy data from RX FIFO to xfer buffer as long as the
490 * xfer
491 * has not completed and we have data in the RX FIFO.
492 */
493 while (!is_read_xfer_complete(uart)) {
494 uint32_t lsr = regs->lsr;
495 /*
496 * A break condition may cause a line status
497 * interrupt to follow very closely after a
498 * char timeout interrupt, but reading the lsr
499 * effectively clears the pending interrupts so
500 * we issue here the callback
501 * instead, otherwise we would miss it.
502 * NOTE: Returned len is 0 for now, this might
503 * change in the future.
504 */
505 if (lsr & status_report_mask[uart]) {
506 regs->ier_dlh &= ~(SEDI_RBFVM(UART, IER, ERBFI, ENABLE) |
507 SEDI_RBFVM(UART, IER, ELSI, ENABLE));
508
509 if (read_transfer->callback) {
510 read_transfer->callback(
511 read_transfer->callback_data,
512 SEDI_DRIVER_ERROR,
513 lsr & BSETS_UART_LSR_ERROR, 0);
514 }
515 uart_read_transfer[uart] = NULL;
516 return;
517 }
518 if (lsr & SEDI_RBFVM(UART, LSR, DR, READY)) {
519 read_transfer->data[read_pos[uart]++] = regs->rbr_thr_dll;
520 } else {
521 /* No more data in the RX FIFO. */
522 break;
523 }
524 }
525
526 if (is_read_xfer_complete(uart)) {
527 /*
528 * Disable both 'Receiver Data Available' and
529 * 'Receiver Line Status' interrupts.
530 */
531 regs->ier_dlh &= ~(SEDI_RBFVM(UART, IER, ERBFI, ENABLE) |
532 SEDI_RBFVM(UART, IER, ELSI, ENABLE));
533 if (read_transfer->callback) {
534 read_transfer->callback(read_transfer->callback_data, 0,
535 SEDI_UART_IDLE, read_pos[uart]);
536 }
537
538 if (vec_read_ctxt[uart].active == false) {
539 uart_read_transfer[uart] = NULL;
540 }
541 }
542 } else {
543 if (unsol_read_ctxt[uart].enable_unsol_rx) {
544 handle_unsol_rx_data(uart);
545 }
546 }
547 break;
548
549 case SEDI_UART_IIR_RECV_LINE_STATUS:
550
551 line_status =
552 regs->lsr & (SEDI_RBFVM(UART, LSR, ADDR_RCVD, 1) | BSETS_UART_LSR_ERROR);
553
554 if (status_report_mask[uart] & line_status) {
555 if (read_transfer) {
556 regs->ier_dlh &= ~(SEDI_RBFVM(UART, IER, ERBFI, ENABLE) |
557 SEDI_RBFVM(UART, IER, ELSI, ENABLE));
558 if (read_transfer->callback) {
559 /*
560 * Return the number of bytes read
561 * a zero as a line status error
562 * was detected.
563 */
564 read_transfer->callback(read_transfer->callback_data,
565 SEDI_DRIVER_ERROR,
566 (status_report_mask[uart] & line_status), 0);
567 uart_read_transfer[uart] = NULL;
568 }
569 } else {
570 if (unsol_read_ctxt[uart].enable_unsol_rx) {
571 handle_unsol_rx_error(uart, line_status);
572 }
573 }
574 }
575 if (line_status & SEDI_RBFVM(UART, LSR, ADDR_RCVD, 1)) {
576 /* Remove the address from FIFO as address match is
577 * confirmed with hardware address match.
578 */
579 regs->rbr_thr_dll;
580 }
581 break;
582
583 default:
584 /* Unhandled interrupt occurred, disable uart interrupts.
585 * and report error.
586 */
587 if (read_transfer && read_transfer->callback) {
588 regs->ier_dlh &= ~(SEDI_RBFVM(UART, IER, ERBFI, ENABLE) |
589 SEDI_RBFVM(UART, IER, ELSI, ENABLE));
590 read_transfer->callback(read_transfer->callback_data, SEDI_DRIVER_ERROR,
591 SEDI_UART_UNHANDLED_INT, 0);
592 uart_read_transfer[uart] = NULL;
593 }
594 if (write_transfer && write_transfer->callback) {
595 regs->ier_dlh &= ~SEDI_RBFVM(UART, IER, ETBEI, ENABLE);
596 write_transfer->callback(write_transfer->callback_data, SEDI_DRIVER_ERROR,
597 SEDI_UART_UNHANDLED_INT, 0);
598 uart_write_transfer[uart] = NULL;
599 }
600 }
601 }
602
sedi_uart_set_config(IN sedi_uart_t uart,IN sedi_uart_config_t * cfg)603 int sedi_uart_set_config(IN sedi_uart_t uart, IN sedi_uart_config_t *cfg)
604 {
605 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
606 DBG_CHECK(cfg != NULL, SEDI_DRIVER_ERROR_PARAMETER);
607 int32_t ret;
608
609 #if HAS_UART_SOFT_RST
610 uart_soft_rst();
611 #endif
612
613 sedi_uart_regs_t *const regs = SEDI_UART[uart];
614
615 volatile uint32_t unused_lsr __attribute__((unused));
616
617 ret = sedi_uart_set_baud_rate(uart, cfg->baud_rate, sedi_pm_get_hbw_clock());
618 if (ret != SEDI_DRIVER_OK) {
619 return SEDI_DRIVER_ERROR_PARAMETER;
620 }
621
622 /* Set line parameters. This also unsets the DLAB. */
623 regs->lcr = cfg->line_control;
624
625 /* Hardware automatic flow control. */
626 regs->mcr = 0;
627 if (true == cfg->hw_fc) {
628 regs->mcr |=
629 SEDI_RBFVM(UART, MCR, AFCE, ENABLED) | SEDI_RBFVM(UART, MCR, RTS, ACTIVE);
630 }
631
632 /* FIFO's enable and reset, set interrupt threshold. */
633 regs->iir_fcr =
634 (SEDI_RBFVM(UART, IIR, FIFOE, ENABLE) | SEDI_RBFVM(UART, IIR, RFIFOR, ENABLE) |
635 SEDI_RBFVM(UART, IIR, XFIFOR, ENABLE) | SEDI_UART_FCR_TX_0_RX_1_2_THRESHOLD);
636
637 /* Clear interrupt settings set by bootloader uart init.*/
638 regs->ier_dlh = 0;
639
640 /* Enable the programmable fifo threshold interrupt.
641 * NOTE: This changes the interpretation of the THRE bit in LSR.
642 * It indicates FIFO Full status instead of THR Empty.
643 */
644 regs->ier_dlh |= SEDI_RBFVM(UART, IER, PTIME, ENABLE);
645
646 /* Clear LSR. */
647 unused_lsr = regs->lsr;
648
649 /* Enable both tx and rx in default configuration. */
650 uart_xfer_ctrl[uart].tx_disable = false;
651 uart_xfer_ctrl[uart].rx_disable = false;
652
653 return SEDI_DRIVER_OK;
654 }
655
sedi_uart_get_status(IN sedi_uart_t uart,OUT uint32_t * const status)656 int sedi_uart_get_status(IN sedi_uart_t uart, OUT uint32_t *const status)
657 {
658 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
659 DBG_CHECK(status != NULL, SEDI_DRIVER_ERROR_PARAMETER);
660 sedi_uart_regs_t *const regs = SEDI_UART[uart];
661 uint32_t lsr = regs->lsr;
662
663 *status =
664 lsr & (SEDI_RBFVM(UART, LSR, OE, OVER_RUN_ERROR) |
665 SEDI_RBFVM(UART, LSR, PE, PARITY_ERROR) |
666 SEDI_RBFVM(UART, LSR, FE, FRAMING_ERROR) | SEDI_RBFVM(UART, LSR, BI, BREAK));
667
668 /*
669 * Check as an IRQ TX completed, if so, the Shift register may still be
670 * busy.An IRQ TX might have completed after we read the lsr.
671 * This will be reflected in the scr.
672 */
673 if (regs->scr & SEDI_UART_SCR_STATUS_UPDATE) {
674 regs->scr &= ~SEDI_UART_SCR_STATUS_UPDATE;
675 } else if (!(lsr & (SEDI_RBFVM(UART, LSR, TEMT, ENABLED)))) {
676 *status |= SEDI_UART_TX_BUSY;
677 }
678
679 if (lsr & SEDI_RBFVM(UART, LSR, DR, READY)) {
680 *status |= SEDI_UART_RX_BUSY;
681 }
682
683 return SEDI_DRIVER_OK;
684 }
685
sedi_uart_write(IN sedi_uart_t uart,IN uint8_t data)686 int sedi_uart_write(IN sedi_uart_t uart, IN uint8_t data)
687 {
688 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
689
690 if (is_tx_disabled(uart)) {
691 return SEDI_DRIVER_ERROR_UNSUPPORTED;
692 }
693
694 sedi_uart_regs_t *const regs = SEDI_UART[uart];
695
696 while (!(regs->lsr & SEDI_RBFVM(UART, LSR, TEMT, ENABLED))) {
697 }
698
699 regs->rbr_thr_dll = data;
700 /* Wait for transaction to complete. */
701 while (!(regs->lsr & SEDI_RBFVM(UART, LSR, TEMT, ENABLED))) {
702 }
703 return SEDI_DRIVER_OK;
704 }
705
sedi_uart_read(IN sedi_uart_t uart,OUT uint8_t * const data,OUT uint32_t * status)706 int sedi_uart_read(IN sedi_uart_t uart, OUT uint8_t *const data, OUT uint32_t *status)
707 {
708 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
709 DBG_CHECK(data != NULL, SEDI_DRIVER_ERROR_PARAMETER);
710 DBG_CHECK(unsol_read_ctxt[uart].enable_unsol_rx == false, SEDI_DRIVER_ERROR_UNSUPPORTED);
711
712 if (is_rx_disabled(uart)) {
713 return SEDI_DRIVER_ERROR_UNSUPPORTED;
714 }
715
716 sedi_uart_regs_t *const regs = SEDI_UART[uart];
717
718 uint32_t lsr = regs->lsr;
719
720 while (!(lsr & SEDI_RBFVM(UART, LSR, DR, READY))) {
721 lsr = regs->lsr;
722 }
723 /* Check if there are any errors on the line. */
724 if (lsr & status_report_mask[uart]) {
725 if (status) {
726 *status = (lsr & BSETS_UART_LSR_ERROR);
727 }
728 return SEDI_DRIVER_ERROR;
729 }
730 *data = regs->rbr_thr_dll;
731
732 return SEDI_DRIVER_OK;
733 }
734
sedi_uart_write_non_block(IN sedi_uart_t uart,IN uint8_t data)735 int sedi_uart_write_non_block(IN sedi_uart_t uart, IN uint8_t data)
736 {
737 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
738
739 if (is_tx_disabled(uart)) {
740 return SEDI_DRIVER_ERROR_UNSUPPORTED;
741 }
742
743 sedi_uart_regs_t *const regs = SEDI_UART[uart];
744
745 regs->rbr_thr_dll = data;
746
747 return SEDI_DRIVER_OK;
748 }
749
sedi_uart_read_non_block(IN sedi_uart_t uart,OUT uint8_t * const data)750 int sedi_uart_read_non_block(IN sedi_uart_t uart, OUT uint8_t *const data)
751 {
752 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
753 DBG_CHECK(data != NULL, SEDI_DRIVER_ERROR_PARAMETER);
754
755 if (is_rx_disabled(uart)) {
756 return SEDI_DRIVER_ERROR_UNSUPPORTED;
757 }
758
759 sedi_uart_regs_t *const regs = SEDI_UART[uart];
760
761 *data = regs->rbr_thr_dll;
762
763 return SEDI_DRIVER_OK;
764 }
765
sedi_uart_write_buffer(IN sedi_uart_t uart,IN uint8_t * const data,IN uint32_t len)766 int sedi_uart_write_buffer(IN sedi_uart_t uart, IN uint8_t *const data, IN uint32_t len)
767 {
768 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
769 DBG_CHECK(data != NULL, SEDI_DRIVER_ERROR_PARAMETER);
770
771 if (is_tx_disabled(uart)) {
772 return SEDI_DRIVER_ERROR_UNSUPPORTED;
773 }
774
775 uint32_t write_length = len;
776 sedi_uart_regs_t *const regs = SEDI_UART[uart];
777
778 uint8_t *d = (uint8_t *)data;
779
780 while (write_length--) {
781 /*
782 * Because FCR_FIFOE and IER_PTIME are enabled, LSR_THRE
783 * behaves as a TX FIFO full indicator.
784 */
785 while (regs->lsr & SEDI_RBFVM(UART, LSR, THRE, ENABLED)) {
786 }
787 regs->rbr_thr_dll = *d;
788 d++;
789 }
790 /* Wait for transaction to complete. */
791 while (!(regs->lsr & SEDI_RBFVM(UART, LSR, TEMT, ENABLED))) {
792 }
793 return SEDI_DRIVER_OK;
794 }
795
sedi_uart_read_buffer(IN sedi_uart_t uart,OUT uint8_t * const data,IN uint32_t req_len,OUT uint32_t * comp_len,OUT uint32_t * status)796 int sedi_uart_read_buffer(IN sedi_uart_t uart, OUT uint8_t *const data, IN uint32_t req_len,
797 OUT uint32_t *comp_len, OUT uint32_t *status)
798 {
799 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
800 DBG_CHECK(data != NULL, SEDI_DRIVER_ERROR_PARAMETER);
801 DBG_CHECK(status != NULL, SEDI_DRIVER_ERROR_PARAMETER);
802 DBG_CHECK(comp_len != NULL, SEDI_DRIVER_ERROR_PARAMETER);
803 DBG_CHECK(unsol_read_ctxt[uart].enable_unsol_rx == false, SEDI_DRIVER_ERROR_UNSUPPORTED);
804
805 if (is_rx_disabled(uart)) {
806 return SEDI_DRIVER_ERROR_UNSUPPORTED;
807 }
808
809 sedi_uart_regs_t *const regs = SEDI_UART[uart];
810 uint8_t *d = data;
811 uint32_t read_len = req_len;
812 uint32_t lsr = 0;
813 *comp_len = 0;
814 while (read_len--) {
815 while (!(lsr & SEDI_RBFVM(UART, LSR, DR, READY))) {
816 lsr = regs->lsr;
817 }
818
819 *status = (lsr & status_report_mask[uart]);
820
821 if (*status) {
822 return SEDI_DRIVER_ERROR;
823 }
824 *d = regs->rbr_thr_dll;
825 (*comp_len)++;
826 d++;
827 lsr = 0;
828 }
829 return SEDI_DRIVER_OK;
830 }
831
sedi_uart_write_async(IN sedi_uart_t uart,IN sedi_uart_transfer_t * const xfer)832 int sedi_uart_write_async(IN sedi_uart_t uart, IN sedi_uart_transfer_t *const xfer)
833 {
834 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
835 DBG_CHECK(xfer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
836 DBG_CHECK(uart_write_transfer[uart] == 0, SEDI_DRIVER_ERROR_BUSY);
837
838 if (is_tx_disabled(uart)) {
839 return SEDI_DRIVER_ERROR_UNSUPPORTED;
840 }
841
842 sedi_uart_regs_t *const regs = SEDI_UART[uart];
843
844 write_pos[uart] = 0;
845 uart_write_transfer[uart] = xfer;
846
847 /* Set threshold. */
848 regs->iir_fcr = SEDI_RBFVM(UART, IIR, FIFOE, ENABLE) | SEDI_UART_FCR_TX_0_RX_1_2_THRESHOLD;
849
850 /* Enable TX holding reg empty interrupt. */
851 regs->ier_dlh |= SEDI_RBFVM(UART, IER, ETBEI, ENABLE);
852 return SEDI_DRIVER_OK;
853 }
854
sedi_uart_read_async(IN sedi_uart_t uart,IN sedi_uart_transfer_t * const xfer)855 int sedi_uart_read_async(IN sedi_uart_t uart, IN sedi_uart_transfer_t *const xfer)
856 {
857 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
858 DBG_CHECK(xfer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
859 DBG_CHECK(uart_read_transfer[uart] == 0, SEDI_DRIVER_ERROR_BUSY);
860
861 DBG_CHECK(unsol_read_ctxt[uart].enable_unsol_rx == false, SEDI_DRIVER_ERROR_UNSUPPORTED);
862
863 if (is_rx_disabled(uart)) {
864 return SEDI_DRIVER_ERROR_UNSUPPORTED;
865 }
866
867 sedi_uart_regs_t *const regs = SEDI_UART[uart];
868
869 read_pos[uart] = 0;
870 uart_read_transfer[uart] = xfer;
871
872 /* Set threshold. */
873 regs->iir_fcr =
874 (SEDI_RBFVM(UART, IIR, FIFOE, ENABLE) | SEDI_UART_FCR_TX_0_RX_1_2_THRESHOLD);
875
876 /*
877 * Enable both 'Receiver Data Available' and 'Receiver
878 * Line Status' interrupts.
879 */
880 regs->ier_dlh |= SEDI_RBFVM(UART, IER, ERBFI, ENABLE) | SEDI_RBFVM(UART, IER, ELSI, ENABLE);
881
882 return SEDI_DRIVER_OK;
883 }
884
sedi_uart_async_write_terminate(IN sedi_uart_t uart)885 int sedi_uart_async_write_terminate(IN sedi_uart_t uart)
886 {
887 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
888
889 sedi_uart_regs_t *const regs = SEDI_UART[uart];
890 const sedi_uart_transfer_t *const transfer = uart_write_transfer[uart];
891
892 /* No ongoing write transaction to be terminated. */
893 if (transfer == NULL) {
894 return SEDI_DRIVER_ERROR;
895 }
896
897 /* Disable TX holding reg empty interrupt. */
898 regs->ier_dlh &= ~SEDI_RBFVM(UART, IER, ETBEI, ENABLE);
899 if (transfer) {
900 if (transfer->callback) {
901 transfer->callback(transfer->callback_data, SEDI_USART_ERROR_CANCELED,
902 SEDI_UART_IDLE, write_pos[uart]);
903 }
904 uart_write_transfer[uart] = NULL;
905 write_pos[uart] = 0;
906 }
907
908 return SEDI_DRIVER_OK;
909 }
910
sedi_uart_async_read_terminate(IN sedi_uart_t uart)911 int sedi_uart_async_read_terminate(IN sedi_uart_t uart)
912 {
913 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
914
915 sedi_uart_regs_t *const regs = SEDI_UART[uart];
916 const sedi_uart_transfer_t *const transfer = uart_read_transfer[uart];
917
918 /* No ongoing read transaction to be terminated. */
919 if (transfer == NULL) {
920 return SEDI_DRIVER_ERROR;
921 }
922
923 /*
924 * Disable both 'Receiver Data Available' and 'Receiver Line Status'
925 * interrupts.
926 */
927 regs->ier_dlh &=
928 ~(SEDI_RBFVM(UART, IER, ERBFI, ENABLE) | SEDI_RBFVM(UART, IER, ELSI, ENABLE));
929
930 if (transfer) {
931 if (transfer->callback) {
932 transfer->callback(transfer->callback_data, SEDI_USART_ERROR_CANCELED,
933 SEDI_UART_IDLE, read_pos[uart]);
934 }
935 uart_read_transfer[uart] = NULL;
936 read_pos[uart] = 0;
937 }
938 return SEDI_DRIVER_OK;
939 }
940
941 #if (HAS_UART_RS485_SUPPORT)
942
sedi_uart_rs485_set_config(IN sedi_uart_t uart,IN sedi_uart_rs485_config_t * cfg)943 int sedi_uart_rs485_set_config(IN sedi_uart_t uart, IN sedi_uart_rs485_config_t *cfg)
944 {
945
946 uint32_t de_assertion_cycles;
947 uint32_t de_deassertion_cycles;
948 uint32_t de_re_tat_cycles;
949 uint32_t re_de_tat_cycles;
950
951 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
952 sedi_uart_regs_t *const regs = SEDI_UART[uart];
953
954 DBG_CHECK(cfg != NULL, SEDI_DRIVER_ERROR_PARAMETER);
955 DBG_CHECK(cfg->de_assertion_time < SEDI_UART_DE_AT_DT_NS_MAX, SEDI_DRIVER_ERROR_PARAMETER);
956 DBG_CHECK(cfg->de_deassertion_time < SEDI_UART_DE_AT_DT_NS_MAX,
957 SEDI_DRIVER_ERROR_PARAMETER);
958 DBG_CHECK(cfg->de_re_tat < SEDI_UART_TAT_NS_MAX, SEDI_DRIVER_ERROR_PARAMETER);
959 DBG_CHECK(cfg->re_de_tat < SEDI_UART_TAT_NS_MAX, SEDI_DRIVER_ERROR_PARAMETER);
960
961 /* Setting configuration for supporting RS-485 extension. */
962
963 /* Setting the bit enable writes to RS485 registers. */
964 regs->tcr |= SEDI_RBFVM(UART, TCR, RS485_EN, 1);
965
966 de_assertion_cycles = (cfg->de_assertion_time / SEDI_UART_SERIAL_CLK_PERIOD_NS);
967 de_deassertion_cycles = (cfg->de_deassertion_time / SEDI_UART_SERIAL_CLK_PERIOD_NS);
968
969 /* Set the values of assertion and de-assertion time. */
970 regs->det = SEDI_UART_DET_AT_DT_PACK(de_assertion_cycles, de_deassertion_cycles);
971
972 /* Clearing previous values of transfer mode in TCR. */
973 regs->tcr &= ~(SEDI_RBFM(UART, TCR, XFER_MODE));
974
975 /* The TAT values are valid only in half duplex mode. */
976 if (cfg->transfer_mode == SEDI_UART_RS485_XFER_MODE_HALF_DUPLEX) {
977 /* Setting the transfer mode in TCR. */
978 regs->tcr |= (uint32_t)(SEDI_UART_XFER_MODE_HW_HALF_DUPLEX
979 << (SEDI_RBFO(UART, TCR, XFER_MODE)));
980
981 /* Set the values of de-re and re-de tat.*/
982 de_re_tat_cycles = cfg->de_re_tat / SEDI_UART_SERIAL_CLK_PERIOD_NS;
983 re_de_tat_cycles = cfg->re_de_tat / SEDI_UART_SERIAL_CLK_PERIOD_NS;
984 regs->tat = SEDI_UART_TAT_PACK(de_re_tat_cycles, re_de_tat_cycles);
985 } else {
986 regs->tcr |= (uint32_t)(SEDI_UART_XFER_MODE_FULL_DUPLEX
987 << (SEDI_RBFO(UART, TCR, XFER_MODE)));
988 }
989
990 /* Clearing previous values of DE & RE polarity in TCR. */
991 regs->tcr &= ~(SEDI_RBFVM(UART, TCR, RE_POL, 1) | SEDI_RBFVM(UART, TCR, DE_POL, 1));
992 regs->tcr |= (((cfg->re_polarity) << SEDI_RBFO(UART, TCR, RE_POL)) |
993 ((cfg->de_polarity) << SEDI_RBFO(UART, TCR, DE_POL)));
994
995 /* Enable or disable the driver based on config. */
996 regs->de_en = cfg->de_en;
997
998 /* Enable or disable the receiver based on config. */
999 regs->re_en = cfg->re_en;
1000
1001 regs->tcr &= ~(SEDI_RBFVM(UART, TCR, RS485_EN, 1));
1002 return SEDI_DRIVER_OK;
1003 }
1004
sedi_uart_rs485_disable(IN sedi_uart_t uart)1005 int sedi_uart_rs485_disable(IN sedi_uart_t uart)
1006 {
1007 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1008
1009 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1010
1011 regs->tcr &= ~(SEDI_RBFVM(UART, TCR, RS485_EN, 1));
1012 return SEDI_DRIVER_OK;
1013 }
1014
sedi_uart_rs485_enable(IN sedi_uart_t uart)1015 int sedi_uart_rs485_enable(IN sedi_uart_t uart)
1016 {
1017 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1018
1019 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1020
1021 regs->tcr |= SEDI_RBFVM(UART, TCR, RS485_EN, 1);
1022
1023 /* Reset rx_fifo right after enable to clear any error conditions
1024 * generated as rx line held low when rs485 is not enabled.
1025 */
1026 regs->iir_fcr |= SEDI_RBFVM(UART, IIR, RFIFOR, ENABLE);
1027 regs->lsr;
1028 return SEDI_DRIVER_OK;
1029 }
1030
sedi_uart_rs485_get_config(IN sedi_uart_t uart,sedi_uart_rs485_config_t * cfg)1031 int sedi_uart_rs485_get_config(IN sedi_uart_t uart, sedi_uart_rs485_config_t *cfg)
1032 {
1033
1034 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1035 DBG_CHECK(cfg != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1036 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1037
1038 cfg->de_assertion_time =
1039 (uint32_t)(((regs->det & SEDI_RBFM(UART, DET, DE_Assertion_Time)) >>
1040 SEDI_RBFO(UART, DET, DE_Assertion_Time)) *
1041 SEDI_UART_SERIAL_CLK_PERIOD_NS);
1042
1043 cfg->de_deassertion_time =
1044 (uint32_t)(((regs->det & SEDI_RBFM(UART, DET, DE_De_assertion_Time)) >>
1045 SEDI_RBFO(UART, DET, DE_De_assertion_Time)) *
1046 SEDI_UART_SERIAL_CLK_PERIOD_NS);
1047
1048 cfg->de_re_tat = (uint32_t)(((regs->tat & SEDI_RBFM(UART, TAT, DE_to_RE)) >>
1049 SEDI_RBFO(UART, TAT, DE_to_RE)) *
1050 SEDI_UART_SERIAL_CLK_PERIOD_NS);
1051
1052 cfg->re_de_tat = (uint32_t)(((regs->tat & SEDI_RBFM(UART, TAT, RE_to_DE)) >>
1053 SEDI_RBFO(UART, TAT, RE_to_DE)) *
1054 SEDI_UART_SERIAL_CLK_PERIOD_NS);
1055
1056 cfg->transfer_mode =
1057 (regs->tcr & SEDI_RBFM(UART, TCR, XFER_MODE)) >> SEDI_RBFO(UART, TCR, XFER_MODE);
1058
1059 if (regs->tcr & (SEDI_RBFO(UART, TCR, DE_POL))) {
1060 cfg->de_polarity = SEDI_UART_RS485_POL_ACTIVE_HIGH;
1061 } else {
1062 cfg->de_polarity = SEDI_UART_RS485_POL_ACTIVE_LOW;
1063 }
1064
1065 if (regs->tcr & (SEDI_RBFO(UART, TCR, RE_POL))) {
1066 cfg->re_polarity = SEDI_UART_RS485_POL_ACTIVE_HIGH;
1067 } else {
1068 cfg->re_polarity = SEDI_UART_RS485_POL_ACTIVE_LOW;
1069 }
1070
1071 cfg->de_en = regs->de_en;
1072 cfg->re_en = regs->re_en;
1073 return SEDI_DRIVER_OK;
1074 }
1075
1076 /* Clear the RS485 configuration registers. */
sedi_uart_rs485_clear_config(IN sedi_uart_t uart)1077 int sedi_uart_rs485_clear_config(IN sedi_uart_t uart)
1078 {
1079 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1080
1081 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1082
1083 regs->tcr |= SEDI_RBFVM(UART, TCR, RS485_EN, 1);
1084 regs->det = 0;
1085 regs->tat = 0;
1086 regs->de_en = 0;
1087 regs->re_en = 0;
1088 regs->tcr = 0;
1089
1090 return SEDI_DRIVER_OK;
1091 }
1092
1093 #endif /* HAS_UART_RS485_SUPPORT */
1094
1095 #if (HAS_UART_9BIT_SUPPORT)
sedi_uart_9bit_set_config(IN sedi_uart_t uart,IN sedi_uart_9bit_config_t * cfg)1096 int sedi_uart_9bit_set_config(IN sedi_uart_t uart, IN sedi_uart_9bit_config_t *cfg)
1097 {
1098
1099 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1100 DBG_CHECK(cfg != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1101
1102 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1103
1104 regs->lcr_ext = SEDI_RBFVM(UART, LCR_EXT, DLS_E, 1);
1105
1106 if (cfg->addr_ctrl == SEDI_UART_9BIT_HW_ADDR_CTRL) {
1107 regs->lcr_ext &= ~SEDI_RBFVM(UART, LCR_EXT, TRANSMIT_MODE, 1);
1108 regs->rar = cfg->receive_address & (SEDI_RBFM(UART, RAR, RAR));
1109 regs->lcr_ext |= SEDI_RBFVM(UART, LCR_EXT, ADDR_MATCH, 1);
1110 } else {
1111 regs->lcr_ext |= SEDI_RBFV(UART, LCR_EXT, ADDR_MATCH, 1);
1112 regs->lcr_ext &= ~SEDI_RBFVM(UART, LCR_EXT, ADDR_MATCH, 1);
1113 }
1114
1115 regs->lcr_ext &= ~(SEDI_RBFVM(UART, LCR_EXT, DLS_E, 1));
1116
1117 return SEDI_DRIVER_OK;
1118 }
1119
sedi_uart_9bit_disable(IN sedi_uart_t uart)1120 int sedi_uart_9bit_disable(IN sedi_uart_t uart)
1121 {
1122 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1123
1124 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1125
1126 regs->lcr_ext &= ~(SEDI_RBFVM(UART, LCR_EXT, DLS_E, 1));
1127 return SEDI_DRIVER_OK;
1128 }
1129
sedi_uart_9bit_enable(IN sedi_uart_t uart)1130 int sedi_uart_9bit_enable(IN sedi_uart_t uart)
1131 {
1132 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1133 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1134
1135 regs->lcr_ext |= SEDI_RBFVM(UART, LCR_EXT, DLS_E, 1);
1136 return SEDI_DRIVER_OK;
1137 }
1138
sedi_uart_9bit_send_address(IN sedi_uart_t uart,uint8_t address)1139 int sedi_uart_9bit_send_address(IN sedi_uart_t uart, uint8_t address)
1140 {
1141
1142 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1143 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1144
1145 if (is_tx_disabled(uart)) {
1146 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1147 }
1148
1149 if (regs->lcr_ext & SEDI_RBFVM(UART, LCR_EXT, DLS_E, 1)) {
1150
1151 if ((regs->lcr_ext & SEDI_RBFVM(UART, LCR_EXT, TRANSMIT_MODE, 1))) {
1152 regs->rbr_thr_dll = (BIT(8) | (uint32_t)address);
1153
1154 /* Wait for address to be sent. */
1155 while (!(regs->lsr & SEDI_RBFVM(UART, LSR, TEMT, ENABLED))) {
1156 }
1157 } else {
1158 regs->tar = address;
1159 /* Sending the address. */
1160 regs->lcr_ext |= SEDI_RBFVM(UART, LCR_EXT, SEND_ADDR, 1);
1161 /* Wait for address to be sent. */
1162 while (regs->lcr_ext & SEDI_RBFVM(UART, LCR_EXT, SEND_ADDR, 1))
1163 ;
1164 }
1165 } else {
1166 /* UART not configured for 9 bit operation. */
1167 return SEDI_DRIVER_ERROR;
1168 }
1169
1170 return SEDI_DRIVER_OK;
1171 }
1172
sedi_uart_9bit_get_config(IN sedi_uart_t uart,sedi_uart_9bit_config_t * cfg)1173 int sedi_uart_9bit_get_config(IN sedi_uart_t uart, sedi_uart_9bit_config_t *cfg)
1174 {
1175 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1176 DBG_CHECK(cfg != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1177 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1178
1179 /* Address of this node when hardware address match enabled. */
1180 cfg->receive_address = regs->rar & SEDI_RBFM(UART, RAR, RAR);
1181
1182 /* Transmit Addr Ctrl s/w or h/w enabled address transmit. */
1183 if (regs->lcr_ext & SEDI_RBFVM(UART, LCR_EXT, TRANSMIT_MODE, 1)) {
1184 cfg->addr_ctrl = SEDI_UART_9BIT_SW_ADDR_CTRL;
1185 } else {
1186 cfg->addr_ctrl = SEDI_UART_9BIT_HW_ADDR_CTRL;
1187 }
1188
1189 return SEDI_DRIVER_OK;
1190 }
1191
sedi_uart_read_rx_fifo(IN sedi_uart_t uart,uint16_t * rx_buff,uint16_t * length_read)1192 int sedi_uart_read_rx_fifo(IN sedi_uart_t uart, uint16_t *rx_buff, uint16_t *length_read)
1193 {
1194 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1195 DBG_CHECK(rx_buff != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1196 DBG_CHECK(length_read != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1197
1198 if (is_rx_disabled(uart)) {
1199 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1200 }
1201
1202 uint16_t data;
1203 uint16_t i = 0;
1204 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1205 uint32_t lsr = regs->lsr;
1206 *length_read = 0;
1207
1208 if (!(lsr & SEDI_RBFVM(UART, LSR, DR, READY))) {
1209 return SEDI_DRIVER_ERROR;
1210 }
1211
1212 while (lsr & SEDI_RBFVM(UART, LSR, DR, READY)) {
1213 if (lsr & status_report_mask[uart]) {
1214 return SEDI_DRIVER_ERROR;
1215 }
1216 data = regs->rbr_thr_dll;
1217 rx_buff[i] = data;
1218 lsr = regs->lsr;
1219 ++i;
1220 }
1221
1222 *length_read = i;
1223 return SEDI_DRIVER_OK;
1224 }
1225
sedi_uart_9bit_clear_config(IN sedi_uart_t uart)1226 int sedi_uart_9bit_clear_config(IN sedi_uart_t uart)
1227 {
1228
1229 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1230 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1231
1232 regs->rar = 0;
1233 regs->tar = 0;
1234 regs->lcr_ext = 0;
1235 return SEDI_DRIVER_OK;
1236 }
1237 #endif /* HAS_UART_9BIT_SUPPORT */
1238
sedi_uart_save_context(IN sedi_uart_t uart)1239 static void sedi_uart_save_context(IN sedi_uart_t uart)
1240 {
1241
1242 sedi_uart_regs_t *IN regs = SEDI_UART[uart];
1243 sedi_uart_context_t *ctx = &uart_context[uart];
1244
1245 ctx->ier = regs->ier_dlh;
1246 ctx->lcr = regs->lcr;
1247 ctx->mcr = regs->mcr;
1248 ctx->scr = regs->scr;
1249 ctx->htx = regs->htx;
1250 ctx->dlf = regs->dlf;
1251 regs->lcr |= SEDI_RBFVM(UART, LCR, DLAB, ENABLED);
1252 ctx->dlh = regs->ier_dlh;
1253 ctx->dll = regs->rbr_thr_dll;
1254 regs->lcr &= ~SEDI_RBFVM(UART, LCR, DLAB, ENABLED);
1255
1256 #if (HAS_UART_RS485_SUPPORT)
1257 /* Save registers for RS485 operation. */
1258 ctx->tcr = regs->tcr;
1259 ctx->de_en = regs->de_en;
1260 ctx->re_en = regs->re_en;
1261 ctx->det = regs->det;
1262 ctx->tat = regs->tat;
1263 #endif
1264
1265 #if (HAS_UART_9BIT_SUPPORT)
1266 /* Save registers for 9-bit operation. */
1267 ctx->rar = regs->rar;
1268 ctx->tar = regs->tar;
1269 ctx->lcr_ext = regs->lcr_ext;
1270 #endif
1271 ctx->context_valid = true;
1272 }
1273
sedi_uart_restore_context(IN sedi_uart_t uart)1274 static void sedi_uart_restore_context(IN sedi_uart_t uart)
1275 {
1276 sedi_uart_context_t *ctx = &uart_context[uart];
1277 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1278
1279 if (ctx->context_valid == true) {
1280 uint32_t clk_speed;
1281
1282 #if HAS_UART_SOFT_RST
1283 uart_soft_rst_instance(uart);
1284 #endif
1285 clk_speed = sedi_pm_get_hbw_clock();
1286 sedi_uart_set_baud_rate(uart, baud_rate_cache[uart], clk_speed);
1287
1288 /* When DLAB is set, DLL and DLH registers can be accessed. */
1289 regs->ier_dlh = ctx->ier;
1290 regs->lcr = ctx->lcr;
1291 regs->mcr = ctx->mcr;
1292 regs->scr = ctx->scr;
1293 regs->htx = ctx->htx;
1294
1295 #if (HAS_UART_RS485_SUPPORT)
1296 /* Restore registers for RS485 operation. */
1297 regs->tcr |= SEDI_RBFVM(UART, TCR, RS485_EN, 1);
1298 regs->de_en = ctx->de_en;
1299 regs->re_en = ctx->re_en;
1300 regs->det = ctx->det;
1301 regs->tat = ctx->tat;
1302 regs->tcr = ctx->tcr;
1303 #endif
1304
1305 #if (HAS_UART_9BIT_SUPPORT)
1306 /* Restore registers for 9-bit operation. */
1307 regs->rar = ctx->rar;
1308 regs->tar = ctx->tar;
1309 regs->lcr_ext = ctx->lcr_ext;
1310 #endif
1311
1312 /*
1313 * FIFO control register cannot be read back,
1314 * default config is applied for this register.
1315 * Application will need to restore its own parameters.
1316 */
1317 regs->iir_fcr = (SEDI_RBFVM(UART, IIR, FIFOE, ENABLE) |
1318 SEDI_RBFVM(UART, IIR, RFIFOR, ENABLE) |
1319 SEDI_RBFVM(UART, IIR, XFIFOR, ENABLE) |
1320 SEDI_UART_FCR_TX_0_RX_1_2_THRESHOLD);
1321 ctx->context_valid = false;
1322 }
1323 }
1324
is_tx_fifo_full(sedi_uart_t uart)1325 static bool is_tx_fifo_full(sedi_uart_t uart)
1326 {
1327 /* As fifos are enabled and ptime is enabled the thre bit
1328 * acts as a fifo full indicator.
1329 */
1330 return !!(SEDI_UART[uart]->lsr & SEDI_RBFVM(UART, LSR, THRE, ENABLED));
1331 }
1332
sedi_uart_irq_tx_ready(IN sedi_uart_t uart)1333 bool sedi_uart_irq_tx_ready(IN sedi_uart_t uart)
1334 {
1335 uint32_t id;
1336
1337 id = iir_cache[uart] & SEDI_UART_IIR_IID_MASK;
1338 return id == SEDI_UART_IIR_THR_EMPTY;
1339 }
1340
sedi_is_rx_data_available(sedi_uart_t uart)1341 static bool sedi_is_rx_data_available(sedi_uart_t uart)
1342 {
1343 return SEDI_UART[uart]->lsr & SEDI_RBFVM(UART, LSR, DR, READY);
1344 }
1345
sedi_uart_is_irq_rx_ready(IN sedi_uart_t uart)1346 bool sedi_uart_is_irq_rx_ready(IN sedi_uart_t uart)
1347 {
1348 uint32_t id = (iir_cache[uart] & SEDI_UART_IIR_IID_MASK);
1349
1350 return (id == SEDI_UART_IIR_RECV_DATA_AVAIL) || (id == SEDI_UART_IIR_CHAR_TIMEOUT);
1351 }
1352
sedi_uart_is_irq_pending(IN sedi_uart_t uart)1353 bool sedi_uart_is_irq_pending(IN sedi_uart_t uart)
1354 {
1355 return !(iir_cache[uart] & SEDI_UART_IIR_NO_INTERRUPT_PENDING);
1356 }
1357
sedi_uart_fifo_fill(IN sedi_uart_t uart,IN uint8_t * data,IN uint32_t size)1358 int sedi_uart_fifo_fill(IN sedi_uart_t uart, IN uint8_t *data, IN uint32_t size)
1359 {
1360 uint32_t i;
1361
1362 if (is_tx_disabled(uart)) {
1363 return 0;
1364 }
1365
1366 for (i = 0; ((i < size) && (!is_tx_fifo_full(uart))); i++) {
1367 SEDI_UART[uart]->rbr_thr_dll = data[i];
1368 }
1369 return i;
1370 }
1371
sedi_uart_fifo_read(IN sedi_uart_t uart,OUT uint8_t * data,IN uint32_t size)1372 int sedi_uart_fifo_read(IN sedi_uart_t uart, OUT uint8_t *data, IN uint32_t size)
1373 {
1374 int i;
1375
1376 if (is_rx_disabled(uart)) {
1377 return 0;
1378 }
1379
1380 for (i = 0; i < size && sedi_is_rx_data_available(uart); i++) {
1381 data[i] = SEDI_UART[uart]->rbr_thr_dll;
1382 }
1383 return i;
1384 }
1385
sedi_uart_irq_tx_enable(IN sedi_uart_t uart)1386 int sedi_uart_irq_tx_enable(IN sedi_uart_t uart)
1387 {
1388 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1389 SEDI_UART[uart]->ier_dlh |= SEDI_RBFVM(UART, IER, ETBEI, ENABLE);
1390 return SEDI_DRIVER_OK;
1391 }
1392
sedi_uart_irq_tx_disable(IN sedi_uart_t uart)1393 int sedi_uart_irq_tx_disable(IN sedi_uart_t uart)
1394 {
1395 SEDI_UART[uart]->ier_dlh &= ~SEDI_RBFVM(UART, IER, ETBEI, ENABLE);
1396 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1397 return SEDI_DRIVER_OK;
1398 }
1399
sedi_uart_is_tx_complete(IN sedi_uart_t uart)1400 bool sedi_uart_is_tx_complete(IN sedi_uart_t uart)
1401 {
1402 return !!(SEDI_UART[uart]->lsr & SEDI_RBFVM(UART, LSR, TEMT, ENABLED));
1403 }
1404
sedi_uart_irq_rx_enable(IN sedi_uart_t uart)1405 int sedi_uart_irq_rx_enable(IN sedi_uart_t uart)
1406 {
1407
1408 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1409 SEDI_UART[uart]->ier_dlh |= SEDI_RBFVM(UART, IER, ERBFI, ENABLE);
1410
1411 return SEDI_DRIVER_OK;
1412 }
1413
sedi_uart_irq_rx_disable(IN sedi_uart_t uart)1414 int sedi_uart_irq_rx_disable(IN sedi_uart_t uart)
1415 {
1416
1417 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1418 SEDI_UART[uart]->ier_dlh &= ~SEDI_RBFVM(UART, IER, ERBFI, ENABLE);
1419 return SEDI_DRIVER_OK;
1420 }
1421
sedi_uart_update_irq_cache(IN sedi_uart_t uart)1422 int sedi_uart_update_irq_cache(IN sedi_uart_t uart)
1423 {
1424
1425 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1426 iir_cache[uart] = SEDI_UART[uart]->iir_fcr;
1427 return SEDI_DRIVER_OK;
1428 }
1429
sedi_uart_irq_err_enable(IN sedi_uart_t uart)1430 int sedi_uart_irq_err_enable(IN sedi_uart_t uart)
1431 {
1432 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1433 SEDI_UART[uart]->ier_dlh |= SEDI_RBFVM(UART, IER, ELSI, ENABLE);
1434 return SEDI_DRIVER_OK;
1435 }
1436
sedi_uart_irq_err_disable(IN sedi_uart_t uart)1437 int sedi_uart_irq_err_disable(IN sedi_uart_t uart)
1438 {
1439
1440 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1441 SEDI_UART[uart]->ier_dlh &= ~SEDI_RBFVM(UART, IER, ELSI, ENABLE);
1442 return SEDI_DRIVER_OK;
1443 }
1444
sedi_uart_set_baud_rate(IN sedi_uart_t uart,IN uint32_t baud_rate,IN uint32_t clk_speed_hz)1445 int sedi_uart_set_baud_rate(IN sedi_uart_t uart, IN uint32_t baud_rate, IN uint32_t clk_speed_hz)
1446 {
1447 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1448
1449 /* Divisor = clock_speed_hz /(16* baudrate) */
1450 uint32_t divisor = clk_speed_hz / (baud_rate << 4);
1451
1452 uint32_t dlf = (clk_speed_hz % (baud_rate << 4)) / baud_rate;
1453 uint32_t scaled_dlf =
1454 ((clk_speed_hz % (baud_rate << 4)) * SEDI_UART_DLF_SCALAR) / baud_rate;
1455
1456 dlf = dlf + ((scaled_dlf % SEDI_UART_DLF_SCALAR) >= (SEDI_UART_DLF_SCALAR / 2));
1457
1458 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1459
1460 /* Store LCR before making changes. */
1461 uint32_t lcr_saved = regs->lcr;
1462
1463 /* Set divisor latch registers (integer + fractional part). */
1464 regs->lcr = SEDI_RBFVM(UART, LCR, DLAB, ENABLED);
1465 regs->ier_dlh = SEDI_UART_GET_DLH(divisor);
1466 regs->rbr_thr_dll = SEDI_UART_GET_DLL(divisor);
1467 regs->dlf = dlf;
1468
1469 /* Restore the lcr to its previous value. */
1470 regs->lcr = lcr_saved;
1471 baud_rate_cache[uart] = baud_rate;
1472 clk_speed_cache[uart] = clk_speed_hz;
1473 return SEDI_DRIVER_OK;
1474 }
1475
sedi_uart_get_config(IN sedi_uart_t uart,OUT sedi_uart_config_t * cfg)1476 int sedi_uart_get_config(IN sedi_uart_t uart, OUT sedi_uart_config_t *cfg)
1477 {
1478
1479 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1480 DBG_CHECK(cfg != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1481 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1482 uint32_t fc_setting;
1483
1484 cfg->line_control = regs->lcr;
1485 fc_setting = (regs->mcr &
1486 (SEDI_RBFVM(UART, MCR, AFCE, ENABLED) | SEDI_RBFVM(UART, MCR, RTS, ACTIVE)));
1487 cfg->hw_fc = (fc_setting ==
1488 (SEDI_RBFVM(UART, MCR, AFCE, ENABLED) | SEDI_RBFVM(UART, MCR, RTS, ACTIVE)));
1489 ;
1490 cfg->baud_rate = baud_rate_cache[uart];
1491 cfg->clk_speed_hz = clk_speed_cache[uart];
1492 return SEDI_DRIVER_OK;
1493 }
1494
1495 /* Set the given UART port to loopback mode. */
sedi_uart_set_loopback_mode(IN sedi_uart_t uart)1496 int sedi_uart_set_loopback_mode(IN sedi_uart_t uart)
1497 {
1498 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1499 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1500
1501 /* Setting to loopback. */
1502 regs->mcr |= SEDI_RBFVM(UART, MCR, LoopBack, ENABLED);
1503 return SEDI_DRIVER_OK;
1504 }
1505
1506 /* Clear loopback mode */
sedi_uart_clr_loopback_mode(IN sedi_uart_t uart)1507 int sedi_uart_clr_loopback_mode(IN sedi_uart_t uart)
1508 {
1509 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1510 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1511
1512 /* Clearing loopback. */
1513 regs->mcr &= ~SEDI_RBFVM(UART, MCR, LoopBack, ENABLED);
1514 return SEDI_DRIVER_OK;
1515 }
1516
sedi_uart_get_loopback_mode(IN sedi_uart_t uart,uint32_t * p_mode)1517 int sedi_uart_get_loopback_mode(IN sedi_uart_t uart, uint32_t *p_mode)
1518 {
1519 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1520 DBG_CHECK(p_mode != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1521 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1522
1523 *p_mode = !!(regs->mcr & SEDI_RBFVM(UART, MCR, LoopBack, ENABLED));
1524 return SEDI_DRIVER_OK;
1525 }
1526
1527 /* Generate Break condition */
sedi_uart_set_break_con(IN sedi_uart_t uart)1528 int sedi_uart_set_break_con(IN sedi_uart_t uart)
1529 {
1530 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1531 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1532
1533 regs->lcr |= SEDI_RBFVM(UART, LCR, BC, ENABLED);
1534 return SEDI_DRIVER_OK;
1535 }
1536
1537 /* Clear Break condition */
sedi_uart_clr_break_con(IN sedi_uart_t uart)1538 int sedi_uart_clr_break_con(IN sedi_uart_t uart)
1539 {
1540 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1541 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1542
1543 regs->lcr &= ~SEDI_RBFVM(UART, LCR, BC, ENABLED);
1544 return SEDI_DRIVER_OK;
1545 }
1546
1547 /* Enable auto flow control */
sedi_uart_auto_fc_enable(IN sedi_uart_t uart)1548 int sedi_uart_auto_fc_enable(IN sedi_uart_t uart)
1549 {
1550 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1551 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1552
1553 regs->mcr |= SEDI_RBFVM(UART, MCR, AFCE, ENABLED) | SEDI_RBFVM(UART, MCR, RTS, ACTIVE);
1554 return SEDI_DRIVER_OK;
1555 }
1556
1557 /* Disable auto flow control */
sedi_uart_auto_fc_disable(IN sedi_uart_t uart)1558 int sedi_uart_auto_fc_disable(IN sedi_uart_t uart)
1559 {
1560 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1561 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1562
1563 regs->mcr &= ~(SEDI_RBFVM(UART, MCR, AFCE, ENABLED) | SEDI_RBFVM(UART, MCR, RTS, ACTIVE));
1564 return SEDI_DRIVER_OK;
1565 }
1566
sedi_set_ln_status_report_mask(IN sedi_uart_t uart,IN uint32_t mask)1567 int sedi_set_ln_status_report_mask(IN sedi_uart_t uart, IN uint32_t mask)
1568 {
1569 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1570 status_report_mask[uart] = mask;
1571 return SEDI_DRIVER_OK;
1572 }
1573
sedi_uart_enable_unsol_rx(IN sedi_uart_t uart,IN sedi_uart_unsol_rx_t * const unsol_rx)1574 int sedi_uart_enable_unsol_rx(IN sedi_uart_t uart, IN sedi_uart_unsol_rx_t *const unsol_rx)
1575 {
1576
1577 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1578 DBG_CHECK(unsol_rx != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1579 DBG_CHECK(unsol_rx->buffer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1580 DBG_CHECK(unsol_rx->size != 0, SEDI_DRIVER_ERROR_PARAMETER);
1581 DBG_CHECK(unsol_rx->unsol_rx_callback != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1582
1583 if (is_rx_disabled(uart)) {
1584 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1585 }
1586
1587 /* Report error if there is an ongoing async read. */
1588 if (uart_read_transfer[uart]) {
1589 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1590 }
1591
1592 /* Setting initial conditions for read and write index */
1593 unsol_read_ctxt[uart].read_idx = -1;
1594 unsol_read_ctxt[uart].write_idx = -1;
1595 unsol_read_ctxt[uart].curr_len = 0;
1596 unsol_read_ctxt[uart].unsol_rx = unsol_rx;
1597
1598 unsol_read_ctxt[uart].enable_unsol_rx = true;
1599
1600 /* Enable receive data available interrupt */
1601 SEDI_UART[uart]->ier_dlh |=
1602 SEDI_RBFVM(UART, IER, ERBFI, ENABLE) | SEDI_RBFVM(UART, IER, ELSI, ENABLE);
1603 return SEDI_DRIVER_OK;
1604 }
1605
sedi_uart_disable_unsol_rx(IN sedi_uart_t uart)1606 int sedi_uart_disable_unsol_rx(IN sedi_uart_t uart)
1607 {
1608
1609 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1610 if (uart_read_transfer[uart]) {
1611 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1612 }
1613
1614 if (!unsol_read_ctxt[uart].enable_unsol_rx) {
1615 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1616 }
1617
1618 SEDI_UART[uart]->ier_dlh &=
1619 ~(SEDI_RBFVM(UART, IER, ERBFI, ENABLE) | SEDI_RBFVM(UART, IER, ELSI, ENABLE));
1620
1621 unsol_read_ctxt[uart].enable_unsol_rx = false;
1622 unsol_read_ctxt[uart].unsol_rx = NULL;
1623 return SEDI_DRIVER_OK;
1624 }
1625
sedi_uart_get_unsol_data(IN sedi_uart_t uart,uint8_t * buffer,int len)1626 int sedi_uart_get_unsol_data(IN sedi_uart_t uart, uint8_t *buffer, int len)
1627 {
1628
1629 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1630 DBG_CHECK(buffer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1631 if (!unsol_read_ctxt[uart].enable_unsol_rx) {
1632 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1633 }
1634
1635 int i, count = 0, start_idx, end_idx;
1636 int read_comp = 0;
1637 const sedi_uart_unsol_rx_t *const unsol_rx = unsol_read_ctxt[uart].unsol_rx;
1638
1639 if ((len == 0) || (len > unsol_read_ctxt[uart].curr_len + 1)) {
1640 return SEDI_DRIVER_ERROR_PARAMETER;
1641 }
1642
1643 SEDI_UART[uart]->ier_dlh &=
1644 ~(SEDI_RBFVM(UART, IER, ERBFI, ENABLE) | SEDI_RBFVM(UART, IER, ELSI, ENABLE));
1645
1646 /* read_idx is the last read location so adding 1 for next valid
1647 * location, similarly write_idx is the last written location thus
1648 * adding 1 for getting the end condition.
1649 */
1650 start_idx = unsol_read_ctxt[uart].read_idx + 1;
1651 end_idx = unsol_read_ctxt[uart].write_idx + 1;
1652 if (start_idx < end_idx) {
1653 for (i = start_idx; i < end_idx; i++) {
1654 buffer[count++] = unsol_rx->buffer[i];
1655 if (count == len) {
1656 break;
1657 }
1658 }
1659
1660 } else {
1661 for (i = start_idx; i < unsol_rx->size; i++) {
1662 buffer[count++] = unsol_rx->buffer[i];
1663 if (count == len) {
1664 read_comp = true;
1665 break;
1666 }
1667 }
1668 if (!read_comp) {
1669 for (i = 0; i < end_idx; i++) {
1670 buffer[count++] = unsol_rx->buffer[i];
1671 if (count == len) {
1672 break;
1673 }
1674 }
1675 }
1676 }
1677
1678 /* Update the read idx to last read location. */
1679 unsol_read_ctxt[uart].read_idx = (unsol_read_ctxt[uart].read_idx + len) % unsol_rx->size;
1680 unsol_read_ctxt[uart].curr_len = (unsol_read_ctxt[uart].curr_len - len);
1681
1682 /* Enable receive data available interrupt */
1683 SEDI_UART[uart]->ier_dlh |=
1684 (SEDI_RBFVM(UART, IER, ERBFI, ENABLE) | SEDI_RBFVM(UART, IER, ELSI, ENABLE));
1685
1686 return SEDI_DRIVER_OK;
1687 }
1688
sedi_uart_get_unsol_data_len(sedi_uart_t uart,int * p_len)1689 int sedi_uart_get_unsol_data_len(sedi_uart_t uart, int *p_len)
1690 {
1691 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1692 DBG_CHECK(p_len != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1693
1694 if (!unsol_read_ctxt[uart].enable_unsol_rx) {
1695 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1696 }
1697
1698 *p_len = unsol_read_ctxt[uart].curr_len;
1699 return SEDI_DRIVER_OK;
1700 }
1701
sedi_get_ln_status_report_mask(IN sedi_uart_t uart,OUT uint32_t * p_mask)1702 int sedi_get_ln_status_report_mask(IN sedi_uart_t uart, OUT uint32_t *p_mask)
1703 {
1704 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1705 DBG_CHECK(p_mask != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1706 *p_mask = status_report_mask[uart];
1707 return SEDI_DRIVER_OK;
1708 }
1709
sedi_uart_assert_rts(IN sedi_uart_t uart)1710 int sedi_uart_assert_rts(IN sedi_uart_t uart)
1711 {
1712
1713 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1714 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1715
1716 if (regs->mcr & SEDI_RBFVM(UART, MCR, AFCE, ENABLED)) {
1717 return SEDI_DRIVER_ERROR;
1718 }
1719
1720 regs->mcr |= SEDI_RBFVM(UART, MCR, RTS, ACTIVE);
1721 return SEDI_DRIVER_OK;
1722 }
1723
sedi_uart_de_assert_rts(IN sedi_uart_t uart)1724 int sedi_uart_de_assert_rts(IN sedi_uart_t uart)
1725 {
1726 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1727 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1728
1729 if (regs->mcr & SEDI_RBFVM(UART, MCR, AFCE, ENABLED)) {
1730 return SEDI_DRIVER_ERROR;
1731 }
1732
1733 regs->mcr &= ~SEDI_RBFVM(UART, MCR, AFCE, ENABLED);
1734 return SEDI_DRIVER_OK;
1735 }
1736
sedi_uart_read_rts(IN sedi_uart_t uart,uint32_t * p_rts)1737 int sedi_uart_read_rts(IN sedi_uart_t uart, uint32_t *p_rts)
1738 {
1739 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1740 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1741
1742 *p_rts = !!(regs->mcr & SEDI_RBFVM(UART, MCR, RTS, ACTIVE));
1743 return SEDI_DRIVER_OK;
1744 }
1745
sedi_uart_read_cts(IN sedi_uart_t uart,OUT uint32_t * p_cts)1746 int sedi_uart_read_cts(IN sedi_uart_t uart, OUT uint32_t *p_cts)
1747 {
1748 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1749 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1750 *p_cts = !!(regs->msr & SEDI_RBFVM(UART, MSR, CTS, ASSERTED));
1751 return SEDI_DRIVER_OK;
1752 }
1753
sedi_uart_write_vec_async(IN sedi_uart_t uart,IN sedi_uart_io_vec_xfer_t * const vec_xfer)1754 int sedi_uart_write_vec_async(IN sedi_uart_t uart, IN sedi_uart_io_vec_xfer_t *const vec_xfer)
1755 {
1756
1757 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1758 DBG_CHECK(vec_xfer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1759 DBG_CHECK(vec_xfer->count != 0, SEDI_DRIVER_ERROR_PARAMETER);
1760 DBG_CHECK(uart_write_transfer[uart] == 0, SEDI_DRIVER_ERROR_BUSY);
1761
1762 if (is_tx_disabled(uart)) {
1763 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1764 }
1765
1766 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1767
1768 vec_write_ctxt[uart].vec = vec_xfer;
1769 write_pos[uart] = 0;
1770 vec_write_ctxt[uart].curr_count = 0;
1771 vec_write_ctxt[uart].active = true;
1772
1773 /* Initiate transfer with the first member of the vector. */
1774 vec_write_ctxt[uart].xfer.data = vec_xfer->vec[0].base;
1775 vec_write_ctxt[uart].xfer.data_len = vec_xfer->vec[0].len;
1776 vec_write_ctxt[uart].xfer.callback_data = (void *)uart;
1777 vec_write_ctxt[uart].xfer.callback = io_vec_write_callback;
1778
1779 uart_write_transfer[uart] = &vec_write_ctxt[uart].xfer;
1780
1781 /* Set threshold. */
1782 regs->iir_fcr =
1783 (SEDI_RBFVM(UART, IIR, FIFOE, ENABLE) | SEDI_UART_FCR_TX_0_RX_1_2_THRESHOLD);
1784
1785 /* Enable TX holding reg empty interrupt. */
1786 regs->ier_dlh |= SEDI_RBFVM(UART, IER, ETBEI, ENABLE);
1787
1788 return SEDI_DRIVER_OK;
1789 }
1790
sedi_uart_read_vec_async(IN sedi_uart_t uart,IN sedi_uart_io_vec_xfer_t * const vec_xfer)1791 int sedi_uart_read_vec_async(IN sedi_uart_t uart, IN sedi_uart_io_vec_xfer_t *const vec_xfer)
1792 {
1793
1794 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1795 DBG_CHECK(vec_xfer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1796 DBG_CHECK(vec_xfer->count != 0, SEDI_DRIVER_ERROR_PARAMETER);
1797 DBG_CHECK(uart_read_transfer[uart] == 0, SEDI_DRIVER_ERROR_BUSY);
1798
1799 if (is_rx_disabled(uart)) {
1800 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1801 }
1802 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1803
1804 vec_read_ctxt[uart].vec = vec_xfer;
1805 read_pos[uart] = 0;
1806 vec_read_ctxt[uart].curr_count = 0;
1807 vec_read_ctxt[uart].active = true;
1808
1809 /* Initiate transfer with the first member of the vector. */
1810 vec_read_ctxt[uart].xfer.data = vec_xfer->vec[0].base;
1811 vec_read_ctxt[uart].xfer.data_len = vec_xfer->vec[0].len;
1812 vec_read_ctxt[uart].xfer.callback_data = (void *)uart;
1813 vec_read_ctxt[uart].xfer.callback = io_vec_read_callback;
1814 uart_read_transfer[uart] = &vec_read_ctxt[uart].xfer;
1815
1816 /* Set threshold. */
1817 regs->iir_fcr =
1818 (SEDI_RBFVM(UART, IIR, FIFOE, ENABLE) | SEDI_UART_FCR_TX_0_RX_1_2_THRESHOLD);
1819 /*
1820 * Enable both 'Receiver Data Available' and 'Receiver
1821 * Line Status' interrupts.
1822 */
1823 regs->ier_dlh |= SEDI_RBFVM(UART, IER, ERBFI, ENABLE) | SEDI_RBFVM(UART, IER, ELSI, ENABLE);
1824
1825 return SEDI_DRIVER_OK;
1826 }
1827
1828 /* UART DMA functions. */
sedi_uart_dma_config(IN sedi_dma_t dma,int32_t channel,IN sedi_dma_event_cb_t cb,void * param,dma_operation_type_t op)1829 static int sedi_uart_dma_config(IN sedi_dma_t dma, int32_t channel, IN sedi_dma_event_cb_t cb,
1830 void *param, dma_operation_type_t op)
1831 {
1832 int32_t ret = 0;
1833
1834 PARAM_UNUSED(ret);
1835
1836 ret = sedi_dma_init(dma, channel, cb, param);
1837 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
1838
1839 ret = sedi_dma_set_power(dma, channel, SEDI_POWER_FULL);
1840 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
1841
1842 if (op == READ) {
1843 ret = sedi_dma_control(dma, channel, SEDI_CONFIG_DMA_BURST_LENGTH,
1844 DMA_BURST_TRANS_LENGTH_1);
1845 } else if (op == WRITE) {
1846 ret = sedi_dma_control(dma, channel, SEDI_CONFIG_DMA_BURST_LENGTH,
1847 DMA_BURST_TRANS_LENGTH_32);
1848 } else {
1849 return SEDI_DRIVER_ERROR_PARAMETER;
1850 }
1851
1852 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
1853
1854 ret = sedi_dma_control(dma, channel, SEDI_CONFIG_DMA_SR_TRANS_WIDTH, DMA_TRANS_WIDTH_8);
1855 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
1856
1857 ret = sedi_dma_control(dma, channel, SEDI_CONFIG_DMA_DT_TRANS_WIDTH, DMA_TRANS_WIDTH_8);
1858 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
1859
1860 ret = sedi_dma_control(dma, channel, SEDI_CONFIG_DMA_HS_POLARITY, DMA_HS_POLARITY_HIGH);
1861
1862 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
1863
1864 return SEDI_DRIVER_OK;
1865 }
1866
sedi_uart_dma_io_async(sedi_uart_t uart,const sedi_uart_dma_xfer_t * const xfer,dma_operation_type_t op)1867 static int sedi_uart_dma_io_async(sedi_uart_t uart, const sedi_uart_dma_xfer_t *const xfer,
1868 dma_operation_type_t op)
1869 {
1870 int32_t ret;
1871 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1872 dma_channel_direction_t dma_dir;
1873 dma_hs_per_rtx_t dma_hs_per;
1874 uint32_t src, dst;
1875
1876 if (op == WRITE) {
1877 dma_write_ctxt[uart].dma_xfer = xfer;
1878 ret = sedi_uart_dma_config(xfer->dma_dev, xfer->channel, sedi_dma_event_cb,
1879 (void *)(&dma_write_ctxt[uart]), WRITE);
1880 if (ret != SEDI_DRIVER_OK) {
1881 return ret;
1882 }
1883 dma_dir = DMA_MEMORY_TO_PERIPHERAL;
1884 dma_hs_per = DMA_HS_PER_TX;
1885 src = (uint32_t)xfer->data;
1886 dst = (uint32_t)(®s->rbr_thr_dll);
1887 } else if (op == READ) {
1888 dma_read_ctxt[uart].dma_xfer = xfer;
1889 ret = sedi_uart_dma_config(xfer->dma_dev, xfer->channel, sedi_dma_event_cb,
1890 (void *)(&dma_read_ctxt[uart]), READ);
1891 if (ret != SEDI_DRIVER_OK) {
1892 return ret;
1893 }
1894 dma_dir = DMA_PERIPHERAL_TO_MEMORY;
1895 dma_hs_per = DMA_HS_PER_RX;
1896 dst = (uint32_t)xfer->data;
1897 src = (uint32_t)(®s->rbr_thr_dll);
1898 regs->dmasa |= SEDI_RBFVM(UART, DMASA, DMASA, SOFT_ACK);
1899 } else {
1900 return SEDI_DRIVER_ERROR;
1901 }
1902
1903 ret = sedi_dma_control(xfer->dma_dev, xfer->channel, SEDI_CONFIG_DMA_HS_DEVICE_ID,
1904 uart_dma_hs_id[uart]);
1905 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
1906
1907 ret = sedi_dma_control(xfer->dma_dev, xfer->channel, SEDI_CONFIG_DMA_HS_DEVICE_ID_PER_DIR,
1908 dma_hs_per);
1909 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
1910
1911 ret = sedi_dma_control(xfer->dma_dev, xfer->channel, SEDI_CONFIG_DMA_DIRECTION, dma_dir);
1912 if (ret != SEDI_DRIVER_OK) {
1913 return ret;
1914 }
1915
1916 regs->iir_fcr =
1917 (SEDI_RBFVM(UART, IIR, FIFOE, ENABLE) | SEDI_UART_FCR_DEFAULT_TX_RX_THRESHOLD);
1918 ret = sedi_dma_start_transfer(xfer->dma_dev, xfer->channel, src, dst, xfer->len);
1919 return ret;
1920 }
1921
sedi_uart_dma_io_polled(sedi_uart_t uart,sedi_dma_t dma_dev,uint32_t channel,const uint8_t * buff,uint32_t length,dma_operation_type_t op)1922 static int sedi_uart_dma_io_polled(sedi_uart_t uart, sedi_dma_t dma_dev, uint32_t channel,
1923 const uint8_t *buff, uint32_t length, dma_operation_type_t op)
1924 {
1925 int ret;
1926 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1927 dma_channel_direction_t dma_dir;
1928 dma_hs_per_rtx_t dma_hs_per;
1929 uint32_t src, dst;
1930
1931 if (op == WRITE) {
1932 dma_dir = DMA_MEMORY_TO_PERIPHERAL;
1933 dma_hs_per = DMA_HS_PER_TX;
1934 src = (uint32_t)buff;
1935 dst = (uint32_t)(®s->rbr_thr_dll);
1936 } else if (op == READ) {
1937 dma_dir = DMA_PERIPHERAL_TO_MEMORY;
1938 dma_hs_per = DMA_HS_PER_RX;
1939 dst = (uint32_t)buff;
1940 src = (uint32_t)(®s->rbr_thr_dll);
1941 regs->dmasa |= SEDI_RBFM(UART, DMASA, DMASA);
1942 } else {
1943 return SEDI_DRIVER_ERROR;
1944 }
1945
1946 ret = sedi_uart_dma_config(dma_dev, channel, sedi_dma_poll_dummy_cb, NULL, op);
1947 if (ret != SEDI_DRIVER_OK) {
1948 return ret;
1949 }
1950 ret = sedi_dma_control(dma_dev, channel, SEDI_CONFIG_DMA_HS_DEVICE_ID,
1951 uart_dma_hs_id[uart]);
1952
1953 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
1954
1955 ret = sedi_dma_control(dma_dev, channel, SEDI_CONFIG_DMA_HS_DEVICE_ID_PER_DIR, dma_hs_per);
1956 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
1957
1958 ret = sedi_dma_control(dma_dev, channel, SEDI_CONFIG_DMA_DIRECTION, dma_dir);
1959 if (ret != SEDI_DRIVER_OK) {
1960 return ret;
1961 }
1962
1963 regs->iir_fcr = (SEDI_RBFM(UART, IIR, FIFOE) | SEDI_UART_FCR_DEFAULT_TX_RX_THRESHOLD);
1964
1965 ret = sedi_dma_start_transfer_polling(dma_dev, channel, src, dst, length);
1966
1967 if (ret != SEDI_DRIVER_OK) {
1968 return ret;
1969 }
1970 /* wait for transfer to complete */
1971 if (op == WRITE) {
1972 while (!(regs->lsr & SEDI_RBFVM(UART, LSR, TEMT, ENABLED))) {
1973 }
1974 }
1975
1976 return SEDI_DRIVER_OK;
1977 }
1978
sedi_uart_dma_write_async(IN sedi_uart_t uart,IN sedi_uart_dma_xfer_t * const xfer)1979 int sedi_uart_dma_write_async(IN sedi_uart_t uart, IN sedi_uart_dma_xfer_t *const xfer)
1980 {
1981
1982 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1983 DBG_CHECK(xfer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1984 DBG_CHECK(xfer->dma_dev < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1985 DBG_CHECK(xfer->data != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1986 DBG_CHECK(xfer->callback != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1987 if (is_tx_disabled(uart)) {
1988 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1989 }
1990
1991 int32_t ret;
1992
1993 ret = sedi_uart_dma_io_async(uart, xfer, WRITE);
1994 return ret;
1995 }
1996
sedi_uart_dma_write_terminate(IN sedi_uart_t uart)1997 int sedi_uart_dma_write_terminate(IN sedi_uart_t uart)
1998 {
1999 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2000 const sedi_uart_dma_xfer_t *xfer = dma_write_ctxt[uart].dma_xfer;
2001 int ret;
2002
2003 /* No ongoing write transaction to be terminated. */
2004 if (xfer == NULL) {
2005 return SEDI_DRIVER_ERROR;
2006 }
2007
2008 sedi_uart_regs_t *const regs = SEDI_UART[uart];
2009
2010 regs->dmasa |= SEDI_RBFVM(UART, DMASA, DMASA, SOFT_ACK);
2011
2012 ret = sedi_dma_set_power(xfer->dma_dev, xfer->channel, SEDI_POWER_OFF);
2013 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
2014 ret = sedi_dma_uninit(xfer->dma_dev, xfer->channel);
2015 if (xfer->callback && (ret == SEDI_DRIVER_OK)) {
2016 xfer->callback(xfer->cb_param, SEDI_USART_ERROR_CANCELED, 0, 0);
2017 dma_write_ctxt[uart].dma_xfer = NULL;
2018 }
2019
2020 return ret;
2021 }
2022
sedi_uart_dma_read_async(IN sedi_uart_t uart,IN sedi_uart_dma_xfer_t * const xfer)2023 int sedi_uart_dma_read_async(IN sedi_uart_t uart, IN sedi_uart_dma_xfer_t *const xfer)
2024 {
2025 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2026 DBG_CHECK(xfer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
2027 DBG_CHECK(xfer->dma_dev < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2028 DBG_CHECK(xfer->data != NULL, SEDI_DRIVER_ERROR_PARAMETER);
2029 DBG_CHECK(xfer->callback != NULL, SEDI_DRIVER_ERROR_PARAMETER);
2030 if (is_rx_disabled(uart)) {
2031 return SEDI_DRIVER_ERROR_UNSUPPORTED;
2032 }
2033
2034 int32_t ret;
2035
2036 ret = sedi_uart_dma_io_async(uart, xfer, READ);
2037 return ret;
2038 }
2039
sedi_uart_dma_read_terminate(IN sedi_uart_t uart)2040 int sedi_uart_dma_read_terminate(IN sedi_uart_t uart)
2041 {
2042 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2043 const sedi_uart_dma_xfer_t *xfer = dma_read_ctxt[uart].dma_xfer;
2044 int ret;
2045
2046 /* No ongoing read transaction to be terminated. */
2047 if (xfer == NULL) {
2048 return SEDI_DRIVER_ERROR;
2049 }
2050
2051 sedi_uart_regs_t *const regs = SEDI_UART[uart];
2052
2053 regs->dmasa |= SEDI_RBFVM(UART, DMASA, DMASA, SOFT_ACK);
2054
2055 ret = sedi_dma_set_power(xfer->dma_dev, xfer->channel, SEDI_POWER_OFF);
2056 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
2057 ret = sedi_dma_uninit(xfer->dma_dev, xfer->channel);
2058 if (xfer->callback && (ret == SEDI_DRIVER_OK)) {
2059 xfer->callback(xfer->cb_param, SEDI_USART_ERROR_CANCELED, 0, 0);
2060 dma_read_ctxt[uart].dma_xfer = NULL;
2061 }
2062
2063 return ret;
2064 }
2065
sedi_uart_dma_write_polled(IN sedi_uart_t uart,IN sedi_dma_t dma_dev,IN uint32_t channel,IN uint8_t * buff,IN uint32_t length)2066 int sedi_uart_dma_write_polled(IN sedi_uart_t uart, IN sedi_dma_t dma_dev, IN uint32_t channel,
2067 IN uint8_t *buff, IN uint32_t length)
2068 {
2069 int ret;
2070
2071 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2072 DBG_CHECK(buff != NULL, SEDI_DRIVER_ERROR_PARAMETER);
2073 DBG_CHECK(length != 0, SEDI_DRIVER_ERROR_PARAMETER);
2074 if (is_tx_disabled(uart)) {
2075 return SEDI_DRIVER_ERROR_UNSUPPORTED;
2076 }
2077
2078 ret = sedi_uart_dma_io_polled(uart, dma_dev, channel, buff, length, WRITE);
2079 return ret;
2080 }
2081
sedi_uart_dma_read_polled(IN sedi_uart_t uart,IN sedi_dma_t dma_dev,IN uint32_t channel,OUT uint8_t * buff,IN uint32_t length,OUT uint32_t * status)2082 int sedi_uart_dma_read_polled(IN sedi_uart_t uart, IN sedi_dma_t dma_dev, IN uint32_t channel,
2083 OUT uint8_t *buff, IN uint32_t length, OUT uint32_t *status)
2084 {
2085 int ret;
2086
2087 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2088 DBG_CHECK(buff != NULL, SEDI_DRIVER_ERROR_PARAMETER);
2089 DBG_CHECK(length != 0, SEDI_DRIVER_ERROR_PARAMETER);
2090 DBG_CHECK(status != 0, SEDI_DRIVER_ERROR_PARAMETER);
2091 if (is_tx_disabled(uart)) {
2092 return SEDI_DRIVER_ERROR_UNSUPPORTED;
2093 }
2094 sedi_uart_regs_t *const regs = SEDI_UART[uart];
2095
2096 ret = sedi_uart_dma_io_polled(uart, dma_dev, channel, buff, length, READ);
2097 *status = regs->lsr & BSETS_UART_LSR_ERROR;
2098 return ret;
2099 }
2100
sedi_uart_set_tx_only_mode(IN sedi_uart_t uart,bool tx_only)2101 int sedi_uart_set_tx_only_mode(IN sedi_uart_t uart, bool tx_only)
2102 {
2103
2104 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2105 #if (HAS_UART_RS485_SUPPORT)
2106 sedi_uart_regs_t *const regs = SEDI_UART[uart];
2107 #endif
2108
2109 if (tx_only) {
2110 uart_xfer_ctrl[uart].tx_disable = false;
2111 uart_xfer_ctrl[uart].rx_disable = true;
2112
2113 #if (HAS_UART_RS485_SUPPORT)
2114 regs->de_en = true;
2115 regs->re_en = false;
2116 #endif
2117 } else {
2118 uart_xfer_ctrl[uart].tx_disable = false;
2119 uart_xfer_ctrl[uart].rx_disable = false;
2120
2121 #if (HAS_UART_RS485_SUPPORT)
2122 regs->de_en = true;
2123 regs->re_en = true;
2124 #endif
2125 }
2126 return SEDI_DRIVER_OK;
2127 }
2128
sedi_uart_set_rx_only_mode(IN sedi_uart_t uart,bool rx_only)2129 int sedi_uart_set_rx_only_mode(IN sedi_uart_t uart, bool rx_only)
2130 {
2131
2132 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2133 #if (HAS_UART_RS485_SUPPORT)
2134 sedi_uart_regs_t *const regs = SEDI_UART[uart];
2135 #endif
2136
2137 if (rx_only) {
2138 uart_xfer_ctrl[uart].tx_disable = true;
2139 uart_xfer_ctrl[uart].rx_disable = false;
2140
2141 #if (HAS_UART_RS485_SUPPORT)
2142 regs->de_en = false;
2143 regs->re_en = true;
2144 #endif
2145 } else {
2146 uart_xfer_ctrl[uart].tx_disable = false;
2147 uart_xfer_ctrl[uart].rx_disable = false;
2148
2149 #if (HAS_UART_RS485_SUPPORT)
2150 regs->de_en = true;
2151 regs->re_en = true;
2152 #endif
2153 }
2154
2155 return SEDI_DRIVER_OK;
2156 }
2157
sedi_uart_disable_tx_rx(IN sedi_uart_t uart)2158 static void sedi_uart_disable_tx_rx(IN sedi_uart_t uart)
2159 {
2160 uart_xfer_ctrl[uart].tx_disable = true;
2161 uart_xfer_ctrl[uart].rx_disable = true;
2162 }
2163
sedi_uart_enable_tx_rx(IN sedi_uart_t uart)2164 static void sedi_uart_enable_tx_rx(IN sedi_uart_t uart)
2165 {
2166 uart_xfer_ctrl[uart].tx_disable = false;
2167 uart_xfer_ctrl[uart].rx_disable = false;
2168 }
2169
sedi_uart_set_power(IN sedi_uart_t uart,IN sedi_power_state_t state)2170 int32_t sedi_uart_set_power(IN sedi_uart_t uart, IN sedi_power_state_t state)
2171 {
2172
2173 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2174
2175 sedi_devid_t id = SEDI_DEVID_UART0 + uart;
2176 int32_t ret = SEDI_DRIVER_OK;
2177
2178 switch (state) {
2179 case SEDI_POWER_FULL:
2180
2181 /* Enable clocks */
2182 sedi_pm_set_device_power(id, state);
2183 sedi_uart_restore_context(uart);
2184 sedi_uart_enable_tx_rx(uart);
2185 break;
2186
2187 case SEDI_POWER_SUSPEND:
2188 /* Disable both tx and rx in configuration. */
2189 sedi_uart_disable_tx_rx(uart);
2190 sedi_uart_save_context(uart);
2191 sedi_pm_set_device_power(id, state);
2192 break;
2193
2194 case SEDI_POWER_FORCE_SUSPEND:
2195 sedi_uart_disable_tx_rx(uart);
2196 sedi_pm_set_device_power(id, state);
2197 break;
2198
2199 case SEDI_POWER_LOW:
2200
2201 sedi_uart_disable_tx_rx(uart);
2202 /* Clock gating for uart */
2203 sedi_pm_set_device_power(id, state);
2204 break;
2205
2206 case SEDI_POWER_OFF:
2207 default:
2208 ret = SEDI_DRIVER_ERROR_UNSUPPORTED;
2209 break;
2210 }
2211 return ret;
2212 }
2213
sedi_uart_init(IN sedi_uart_t uart,void * base)2214 int32_t sedi_uart_init(IN sedi_uart_t uart, void *base)
2215 {
2216 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2217
2218 sedi_uart[uart] = (sedi_uart_regs_t *)base;
2219
2220 return SEDI_DRIVER_OK;
2221 }
2222