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_UART_0_REG_BASE,
117 (sedi_uart_regs_t *)SEDI_UART_1_REG_BASE,
118 (sedi_uart_regs_t *)SEDI_UART_2_REG_BASE};
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 DBG_CHECK(divisor <= (SEDI_UART_MAX_BAUD_DIVISOR), SEDI_DRIVER_ERROR_PARAMETER);
1453
1454 uint32_t dlf = (clk_speed_hz % (baud_rate << 4)) / baud_rate;
1455 uint32_t scaled_dlf =
1456 ((clk_speed_hz % (baud_rate << 4)) * SEDI_UART_DLF_SCALAR) / baud_rate;
1457
1458 dlf = dlf + ((scaled_dlf % SEDI_UART_DLF_SCALAR) >= (SEDI_UART_DLF_SCALAR / 2));
1459
1460 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1461
1462 /* Store LCR before making changes. */
1463 uint32_t lcr_saved = regs->lcr;
1464
1465 /* Set divisor latch registers (integer + fractional part). */
1466 regs->lcr = SEDI_RBFVM(UART, LCR, DLAB, ENABLED);
1467 regs->ier_dlh = SEDI_UART_GET_DLH(divisor);
1468 regs->rbr_thr_dll = SEDI_UART_GET_DLL(divisor);
1469 regs->dlf = dlf;
1470
1471 /* Restore the lcr to its previous value. */
1472 regs->lcr = lcr_saved;
1473 baud_rate_cache[uart] = baud_rate;
1474 clk_speed_cache[uart] = clk_speed_hz;
1475 return SEDI_DRIVER_OK;
1476 }
1477
sedi_uart_get_config(IN sedi_uart_t uart,OUT sedi_uart_config_t * cfg)1478 int sedi_uart_get_config(IN sedi_uart_t uart, OUT sedi_uart_config_t *cfg)
1479 {
1480
1481 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1482 DBG_CHECK(cfg != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1483 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1484 uint32_t fc_setting;
1485
1486 cfg->line_control = regs->lcr;
1487 fc_setting = (regs->mcr &
1488 (SEDI_RBFVM(UART, MCR, AFCE, ENABLED) | SEDI_RBFVM(UART, MCR, RTS, ACTIVE)));
1489 cfg->hw_fc = (fc_setting ==
1490 (SEDI_RBFVM(UART, MCR, AFCE, ENABLED) | SEDI_RBFVM(UART, MCR, RTS, ACTIVE)));
1491 ;
1492 cfg->baud_rate = baud_rate_cache[uart];
1493 cfg->clk_speed_hz = clk_speed_cache[uart];
1494 return SEDI_DRIVER_OK;
1495 }
1496
1497 /* Set the given UART port to loopback mode. */
sedi_uart_set_loopback_mode(IN sedi_uart_t uart)1498 int sedi_uart_set_loopback_mode(IN sedi_uart_t uart)
1499 {
1500 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1501 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1502
1503 /* Setting to loopback. */
1504 regs->mcr |= SEDI_RBFVM(UART, MCR, LoopBack, ENABLED);
1505 return SEDI_DRIVER_OK;
1506 }
1507
1508 /* Clear loopback mode */
sedi_uart_clr_loopback_mode(IN sedi_uart_t uart)1509 int sedi_uart_clr_loopback_mode(IN sedi_uart_t uart)
1510 {
1511 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1512 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1513
1514 /* Clearing loopback. */
1515 regs->mcr &= ~SEDI_RBFVM(UART, MCR, LoopBack, ENABLED);
1516 return SEDI_DRIVER_OK;
1517 }
1518
sedi_uart_get_loopback_mode(IN sedi_uart_t uart,uint32_t * p_mode)1519 int sedi_uart_get_loopback_mode(IN sedi_uart_t uart, uint32_t *p_mode)
1520 {
1521 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1522 DBG_CHECK(p_mode != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1523 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1524
1525 *p_mode = !!(regs->mcr & SEDI_RBFVM(UART, MCR, LoopBack, ENABLED));
1526 return SEDI_DRIVER_OK;
1527 }
1528
1529 /* Generate Break condition */
sedi_uart_set_break_con(IN sedi_uart_t uart)1530 int sedi_uart_set_break_con(IN sedi_uart_t uart)
1531 {
1532 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1533 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1534
1535 regs->lcr |= SEDI_RBFVM(UART, LCR, BC, ENABLED);
1536 return SEDI_DRIVER_OK;
1537 }
1538
1539 /* Clear Break condition */
sedi_uart_clr_break_con(IN sedi_uart_t uart)1540 int sedi_uart_clr_break_con(IN sedi_uart_t uart)
1541 {
1542 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1543 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1544
1545 regs->lcr &= ~SEDI_RBFVM(UART, LCR, BC, ENABLED);
1546 return SEDI_DRIVER_OK;
1547 }
1548
1549 /* Enable auto flow control */
sedi_uart_auto_fc_enable(IN sedi_uart_t uart)1550 int sedi_uart_auto_fc_enable(IN sedi_uart_t uart)
1551 {
1552 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1553 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1554
1555 regs->mcr |= SEDI_RBFVM(UART, MCR, AFCE, ENABLED) | SEDI_RBFVM(UART, MCR, RTS, ACTIVE);
1556 return SEDI_DRIVER_OK;
1557 }
1558
1559 /* Disable auto flow control */
sedi_uart_auto_fc_disable(IN sedi_uart_t uart)1560 int sedi_uart_auto_fc_disable(IN sedi_uart_t uart)
1561 {
1562 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1563 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1564
1565 regs->mcr &= ~(SEDI_RBFVM(UART, MCR, AFCE, ENABLED) | SEDI_RBFVM(UART, MCR, RTS, ACTIVE));
1566 return SEDI_DRIVER_OK;
1567 }
1568
sedi_set_ln_status_report_mask(IN sedi_uart_t uart,IN uint32_t mask)1569 int sedi_set_ln_status_report_mask(IN sedi_uart_t uart, IN uint32_t mask)
1570 {
1571 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1572 status_report_mask[uart] = mask;
1573 return SEDI_DRIVER_OK;
1574 }
1575
sedi_uart_enable_unsol_rx(IN sedi_uart_t uart,IN sedi_uart_unsol_rx_t * const unsol_rx)1576 int sedi_uart_enable_unsol_rx(IN sedi_uart_t uart, IN sedi_uart_unsol_rx_t *const unsol_rx)
1577 {
1578
1579 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1580 DBG_CHECK(unsol_rx != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1581 DBG_CHECK(unsol_rx->buffer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1582 DBG_CHECK(unsol_rx->size != 0, SEDI_DRIVER_ERROR_PARAMETER);
1583 DBG_CHECK(unsol_rx->unsol_rx_callback != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1584
1585 if (is_rx_disabled(uart)) {
1586 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1587 }
1588
1589 /* Report error if there is an ongoing async read. */
1590 if (uart_read_transfer[uart]) {
1591 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1592 }
1593
1594 /* Setting initial conditions for read and write index */
1595 unsol_read_ctxt[uart].read_idx = -1;
1596 unsol_read_ctxt[uart].write_idx = -1;
1597 unsol_read_ctxt[uart].curr_len = 0;
1598 unsol_read_ctxt[uart].unsol_rx = unsol_rx;
1599
1600 unsol_read_ctxt[uart].enable_unsol_rx = true;
1601
1602 /* Enable receive data available interrupt */
1603 SEDI_UART[uart]->ier_dlh |=
1604 SEDI_RBFVM(UART, IER, ERBFI, ENABLE) | SEDI_RBFVM(UART, IER, ELSI, ENABLE);
1605 return SEDI_DRIVER_OK;
1606 }
1607
sedi_uart_disable_unsol_rx(IN sedi_uart_t uart)1608 int sedi_uart_disable_unsol_rx(IN sedi_uart_t uart)
1609 {
1610
1611 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1612 if (uart_read_transfer[uart]) {
1613 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1614 }
1615
1616 if (!unsol_read_ctxt[uart].enable_unsol_rx) {
1617 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1618 }
1619
1620 SEDI_UART[uart]->ier_dlh &=
1621 ~(SEDI_RBFVM(UART, IER, ERBFI, ENABLE) | SEDI_RBFVM(UART, IER, ELSI, ENABLE));
1622
1623 unsol_read_ctxt[uart].enable_unsol_rx = false;
1624 unsol_read_ctxt[uart].unsol_rx = NULL;
1625 return SEDI_DRIVER_OK;
1626 }
1627
sedi_uart_get_unsol_data(IN sedi_uart_t uart,uint8_t * buffer,int len)1628 int sedi_uart_get_unsol_data(IN sedi_uart_t uart, uint8_t *buffer, int len)
1629 {
1630
1631 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1632 DBG_CHECK(buffer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1633 if (!unsol_read_ctxt[uart].enable_unsol_rx) {
1634 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1635 }
1636
1637 int i, count = 0, start_idx, end_idx;
1638 int read_comp = 0;
1639 const sedi_uart_unsol_rx_t *const unsol_rx = unsol_read_ctxt[uart].unsol_rx;
1640
1641 if ((len == 0) || (len > unsol_read_ctxt[uart].curr_len + 1)) {
1642 return SEDI_DRIVER_ERROR_PARAMETER;
1643 }
1644
1645 SEDI_UART[uart]->ier_dlh &=
1646 ~(SEDI_RBFVM(UART, IER, ERBFI, ENABLE) | SEDI_RBFVM(UART, IER, ELSI, ENABLE));
1647
1648 /* read_idx is the last read location so adding 1 for next valid
1649 * location, similarly write_idx is the last written location thus
1650 * adding 1 for getting the end condition.
1651 */
1652 start_idx = unsol_read_ctxt[uart].read_idx + 1;
1653 end_idx = unsol_read_ctxt[uart].write_idx + 1;
1654 if (start_idx < end_idx) {
1655 for (i = start_idx; i < end_idx; i++) {
1656 buffer[count++] = unsol_rx->buffer[i];
1657 if (count == len) {
1658 break;
1659 }
1660 }
1661
1662 } else {
1663 for (i = start_idx; i < unsol_rx->size; i++) {
1664 buffer[count++] = unsol_rx->buffer[i];
1665 if (count == len) {
1666 read_comp = true;
1667 break;
1668 }
1669 }
1670 if (!read_comp) {
1671 for (i = 0; i < end_idx; i++) {
1672 buffer[count++] = unsol_rx->buffer[i];
1673 if (count == len) {
1674 break;
1675 }
1676 }
1677 }
1678 }
1679
1680 /* Update the read idx to last read location. */
1681 unsol_read_ctxt[uart].read_idx = (unsol_read_ctxt[uart].read_idx + len) % unsol_rx->size;
1682 unsol_read_ctxt[uart].curr_len = (unsol_read_ctxt[uart].curr_len - len);
1683
1684 /* Enable receive data available interrupt */
1685 SEDI_UART[uart]->ier_dlh |=
1686 (SEDI_RBFVM(UART, IER, ERBFI, ENABLE) | SEDI_RBFVM(UART, IER, ELSI, ENABLE));
1687
1688 return SEDI_DRIVER_OK;
1689 }
1690
sedi_uart_get_unsol_data_len(sedi_uart_t uart,int * p_len)1691 int sedi_uart_get_unsol_data_len(sedi_uart_t uart, int *p_len)
1692 {
1693 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1694 DBG_CHECK(p_len != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1695
1696 if (!unsol_read_ctxt[uart].enable_unsol_rx) {
1697 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1698 }
1699
1700 *p_len = unsol_read_ctxt[uart].curr_len;
1701 return SEDI_DRIVER_OK;
1702 }
1703
sedi_get_ln_status_report_mask(IN sedi_uart_t uart,OUT uint32_t * p_mask)1704 int sedi_get_ln_status_report_mask(IN sedi_uart_t uart, OUT uint32_t *p_mask)
1705 {
1706 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1707 DBG_CHECK(p_mask != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1708 *p_mask = status_report_mask[uart];
1709 return SEDI_DRIVER_OK;
1710 }
1711
sedi_uart_assert_rts(IN sedi_uart_t uart)1712 int sedi_uart_assert_rts(IN sedi_uart_t uart)
1713 {
1714
1715 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1716 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1717
1718 if (regs->mcr & SEDI_RBFVM(UART, MCR, AFCE, ENABLED)) {
1719 return SEDI_DRIVER_ERROR;
1720 }
1721
1722 regs->mcr |= SEDI_RBFVM(UART, MCR, RTS, ACTIVE);
1723 return SEDI_DRIVER_OK;
1724 }
1725
sedi_uart_de_assert_rts(IN sedi_uart_t uart)1726 int sedi_uart_de_assert_rts(IN sedi_uart_t uart)
1727 {
1728 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1729 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1730
1731 if (regs->mcr & SEDI_RBFVM(UART, MCR, AFCE, ENABLED)) {
1732 return SEDI_DRIVER_ERROR;
1733 }
1734
1735 regs->mcr &= ~SEDI_RBFVM(UART, MCR, AFCE, ENABLED);
1736 return SEDI_DRIVER_OK;
1737 }
1738
sedi_uart_read_rts(IN sedi_uart_t uart,uint32_t * p_rts)1739 int sedi_uart_read_rts(IN sedi_uart_t uart, uint32_t *p_rts)
1740 {
1741 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1742 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1743
1744 *p_rts = !!(regs->mcr & SEDI_RBFVM(UART, MCR, RTS, ACTIVE));
1745 return SEDI_DRIVER_OK;
1746 }
1747
sedi_uart_read_cts(IN sedi_uart_t uart,OUT uint32_t * p_cts)1748 int sedi_uart_read_cts(IN sedi_uart_t uart, OUT uint32_t *p_cts)
1749 {
1750 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1751 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1752 *p_cts = !!(regs->msr & SEDI_RBFVM(UART, MSR, CTS, ASSERTED));
1753 return SEDI_DRIVER_OK;
1754 }
1755
sedi_uart_write_vec_async(IN sedi_uart_t uart,IN sedi_uart_io_vec_xfer_t * const vec_xfer)1756 int sedi_uart_write_vec_async(IN sedi_uart_t uart, IN sedi_uart_io_vec_xfer_t *const vec_xfer)
1757 {
1758
1759 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1760 DBG_CHECK(vec_xfer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1761 DBG_CHECK(vec_xfer->count != 0, SEDI_DRIVER_ERROR_PARAMETER);
1762 DBG_CHECK(uart_write_transfer[uart] == 0, SEDI_DRIVER_ERROR_BUSY);
1763
1764 if (is_tx_disabled(uart)) {
1765 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1766 }
1767
1768 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1769
1770 vec_write_ctxt[uart].vec = vec_xfer;
1771 write_pos[uart] = 0;
1772 vec_write_ctxt[uart].curr_count = 0;
1773 vec_write_ctxt[uart].active = true;
1774
1775 /* Initiate transfer with the first member of the vector. */
1776 vec_write_ctxt[uart].xfer.data = vec_xfer->vec[0].base;
1777 vec_write_ctxt[uart].xfer.data_len = vec_xfer->vec[0].len;
1778 vec_write_ctxt[uart].xfer.callback_data = (void *)uart;
1779 vec_write_ctxt[uart].xfer.callback = io_vec_write_callback;
1780
1781 uart_write_transfer[uart] = &vec_write_ctxt[uart].xfer;
1782
1783 /* Set threshold. */
1784 regs->iir_fcr =
1785 (SEDI_RBFVM(UART, IIR, FIFOE, ENABLE) | SEDI_UART_FCR_TX_0_RX_1_2_THRESHOLD);
1786
1787 /* Enable TX holding reg empty interrupt. */
1788 regs->ier_dlh |= SEDI_RBFVM(UART, IER, ETBEI, ENABLE);
1789
1790 return SEDI_DRIVER_OK;
1791 }
1792
sedi_uart_read_vec_async(IN sedi_uart_t uart,IN sedi_uart_io_vec_xfer_t * const vec_xfer)1793 int sedi_uart_read_vec_async(IN sedi_uart_t uart, IN sedi_uart_io_vec_xfer_t *const vec_xfer)
1794 {
1795
1796 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1797 DBG_CHECK(vec_xfer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1798 DBG_CHECK(vec_xfer->count != 0, SEDI_DRIVER_ERROR_PARAMETER);
1799 DBG_CHECK(uart_read_transfer[uart] == 0, SEDI_DRIVER_ERROR_BUSY);
1800
1801 if (is_rx_disabled(uart)) {
1802 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1803 }
1804 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1805
1806 vec_read_ctxt[uart].vec = vec_xfer;
1807 read_pos[uart] = 0;
1808 vec_read_ctxt[uart].curr_count = 0;
1809 vec_read_ctxt[uart].active = true;
1810
1811 /* Initiate transfer with the first member of the vector. */
1812 vec_read_ctxt[uart].xfer.data = vec_xfer->vec[0].base;
1813 vec_read_ctxt[uart].xfer.data_len = vec_xfer->vec[0].len;
1814 vec_read_ctxt[uart].xfer.callback_data = (void *)uart;
1815 vec_read_ctxt[uart].xfer.callback = io_vec_read_callback;
1816 uart_read_transfer[uart] = &vec_read_ctxt[uart].xfer;
1817
1818 /* Set threshold. */
1819 regs->iir_fcr =
1820 (SEDI_RBFVM(UART, IIR, FIFOE, ENABLE) | SEDI_UART_FCR_TX_0_RX_1_2_THRESHOLD);
1821 /*
1822 * Enable both 'Receiver Data Available' and 'Receiver
1823 * Line Status' interrupts.
1824 */
1825 regs->ier_dlh |= SEDI_RBFVM(UART, IER, ERBFI, ENABLE) | SEDI_RBFVM(UART, IER, ELSI, ENABLE);
1826
1827 return SEDI_DRIVER_OK;
1828 }
1829
1830 /* 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)1831 static int sedi_uart_dma_config(IN sedi_dma_t dma, int32_t channel, IN sedi_dma_event_cb_t cb,
1832 void *param, dma_operation_type_t op)
1833 {
1834 int32_t ret = 0;
1835
1836 PARAM_UNUSED(ret);
1837
1838 ret = sedi_dma_init(dma, channel, cb, param);
1839 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
1840
1841 ret = sedi_dma_set_power(dma, channel, SEDI_POWER_FULL);
1842 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
1843
1844 if (op == READ) {
1845 ret = sedi_dma_control(dma, channel, SEDI_CONFIG_DMA_BURST_LENGTH,
1846 DMA_BURST_TRANS_LENGTH_1);
1847 } else if (op == WRITE) {
1848 ret = sedi_dma_control(dma, channel, SEDI_CONFIG_DMA_BURST_LENGTH,
1849 DMA_BURST_TRANS_LENGTH_32);
1850 } else {
1851 return SEDI_DRIVER_ERROR_PARAMETER;
1852 }
1853
1854 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
1855
1856 ret = sedi_dma_control(dma, channel, SEDI_CONFIG_DMA_SR_TRANS_WIDTH, DMA_TRANS_WIDTH_8);
1857 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
1858
1859 ret = sedi_dma_control(dma, channel, SEDI_CONFIG_DMA_DT_TRANS_WIDTH, DMA_TRANS_WIDTH_8);
1860 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
1861
1862 ret = sedi_dma_control(dma, channel, SEDI_CONFIG_DMA_HS_POLARITY, DMA_HS_POLARITY_HIGH);
1863
1864 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
1865
1866 return SEDI_DRIVER_OK;
1867 }
1868
sedi_uart_dma_io_async(sedi_uart_t uart,const sedi_uart_dma_xfer_t * const xfer,dma_operation_type_t op)1869 static int sedi_uart_dma_io_async(sedi_uart_t uart, const sedi_uart_dma_xfer_t *const xfer,
1870 dma_operation_type_t op)
1871 {
1872 int32_t ret;
1873 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1874 dma_channel_direction_t dma_dir;
1875 dma_hs_per_rtx_t dma_hs_per;
1876 uint32_t src, dst;
1877
1878 if (op == WRITE) {
1879 dma_write_ctxt[uart].dma_xfer = xfer;
1880 ret = sedi_uart_dma_config(xfer->dma_dev, xfer->channel, sedi_dma_event_cb,
1881 (void *)(&dma_write_ctxt[uart]), WRITE);
1882 if (ret != SEDI_DRIVER_OK) {
1883 return ret;
1884 }
1885 dma_dir = DMA_MEMORY_TO_PERIPHERAL;
1886 dma_hs_per = DMA_HS_PER_TX;
1887 src = (uint32_t)xfer->data;
1888 dst = (uint32_t)(®s->rbr_thr_dll);
1889 } else if (op == READ) {
1890 dma_read_ctxt[uart].dma_xfer = xfer;
1891 ret = sedi_uart_dma_config(xfer->dma_dev, xfer->channel, sedi_dma_event_cb,
1892 (void *)(&dma_read_ctxt[uart]), READ);
1893 if (ret != SEDI_DRIVER_OK) {
1894 return ret;
1895 }
1896 dma_dir = DMA_PERIPHERAL_TO_MEMORY;
1897 dma_hs_per = DMA_HS_PER_RX;
1898 dst = (uint32_t)xfer->data;
1899 src = (uint32_t)(®s->rbr_thr_dll);
1900 regs->dmasa |= SEDI_RBFVM(UART, DMASA, DMASA, SOFT_ACK);
1901 } else {
1902 return SEDI_DRIVER_ERROR;
1903 }
1904
1905 ret = sedi_dma_control(xfer->dma_dev, xfer->channel, SEDI_CONFIG_DMA_HS_DEVICE_ID,
1906 uart_dma_hs_id[uart]);
1907 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
1908
1909 ret = sedi_dma_control(xfer->dma_dev, xfer->channel, SEDI_CONFIG_DMA_HS_DEVICE_ID_PER_DIR,
1910 dma_hs_per);
1911 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
1912
1913 ret = sedi_dma_control(xfer->dma_dev, xfer->channel, SEDI_CONFIG_DMA_DIRECTION, dma_dir);
1914 if (ret != SEDI_DRIVER_OK) {
1915 return ret;
1916 }
1917
1918 regs->iir_fcr =
1919 (SEDI_RBFVM(UART, IIR, FIFOE, ENABLE) | SEDI_UART_FCR_DEFAULT_TX_RX_THRESHOLD);
1920 ret = sedi_dma_start_transfer(xfer->dma_dev, xfer->channel, src, dst, xfer->len);
1921 return ret;
1922 }
1923
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)1924 static int sedi_uart_dma_io_polled(sedi_uart_t uart, sedi_dma_t dma_dev, uint32_t channel,
1925 const uint8_t *buff, uint32_t length, dma_operation_type_t op)
1926 {
1927 int ret;
1928 sedi_uart_regs_t *const regs = SEDI_UART[uart];
1929 dma_channel_direction_t dma_dir;
1930 dma_hs_per_rtx_t dma_hs_per;
1931 uint32_t src, dst;
1932
1933 if (op == WRITE) {
1934 dma_dir = DMA_MEMORY_TO_PERIPHERAL;
1935 dma_hs_per = DMA_HS_PER_TX;
1936 src = (uint32_t)buff;
1937 dst = (uint32_t)(®s->rbr_thr_dll);
1938 } else if (op == READ) {
1939 dma_dir = DMA_PERIPHERAL_TO_MEMORY;
1940 dma_hs_per = DMA_HS_PER_RX;
1941 dst = (uint32_t)buff;
1942 src = (uint32_t)(®s->rbr_thr_dll);
1943 regs->dmasa |= SEDI_RBFM(UART, DMASA, DMASA);
1944 } else {
1945 return SEDI_DRIVER_ERROR;
1946 }
1947
1948 ret = sedi_uart_dma_config(dma_dev, channel, sedi_dma_poll_dummy_cb, NULL, op);
1949 if (ret != SEDI_DRIVER_OK) {
1950 return ret;
1951 }
1952 ret = sedi_dma_control(dma_dev, channel, SEDI_CONFIG_DMA_HS_DEVICE_ID,
1953 uart_dma_hs_id[uart]);
1954
1955 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
1956
1957 ret = sedi_dma_control(dma_dev, channel, SEDI_CONFIG_DMA_HS_DEVICE_ID_PER_DIR, dma_hs_per);
1958 DBG_CHECK(0 == ret, SEDI_DRIVER_ERROR);
1959
1960 ret = sedi_dma_control(dma_dev, channel, SEDI_CONFIG_DMA_DIRECTION, dma_dir);
1961 if (ret != SEDI_DRIVER_OK) {
1962 return ret;
1963 }
1964
1965 regs->iir_fcr = (SEDI_RBFM(UART, IIR, FIFOE) | SEDI_UART_FCR_DEFAULT_TX_RX_THRESHOLD);
1966
1967 ret = sedi_dma_start_transfer_polling(dma_dev, channel, src, dst, length);
1968
1969 if (ret != SEDI_DRIVER_OK) {
1970 return ret;
1971 }
1972 /* wait for transfer to complete */
1973 if (op == WRITE) {
1974 while (!(regs->lsr & SEDI_RBFVM(UART, LSR, TEMT, ENABLED))) {
1975 }
1976 }
1977
1978 return SEDI_DRIVER_OK;
1979 }
1980
sedi_uart_dma_write_async(IN sedi_uart_t uart,IN sedi_uart_dma_xfer_t * const xfer)1981 int sedi_uart_dma_write_async(IN sedi_uart_t uart, IN sedi_uart_dma_xfer_t *const xfer)
1982 {
1983
1984 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1985 DBG_CHECK(xfer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1986 DBG_CHECK(xfer->dma_dev < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
1987 DBG_CHECK(xfer->data != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1988 DBG_CHECK(xfer->callback != NULL, SEDI_DRIVER_ERROR_PARAMETER);
1989 if (is_tx_disabled(uart)) {
1990 return SEDI_DRIVER_ERROR_UNSUPPORTED;
1991 }
1992
1993 int32_t ret;
1994
1995 ret = sedi_uart_dma_io_async(uart, xfer, WRITE);
1996 return ret;
1997 }
1998
sedi_uart_dma_write_terminate(IN sedi_uart_t uart)1999 int sedi_uart_dma_write_terminate(IN sedi_uart_t uart)
2000 {
2001 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2002 const sedi_uart_dma_xfer_t *xfer = dma_write_ctxt[uart].dma_xfer;
2003 int ret;
2004
2005 /* No ongoing write transaction to be terminated. */
2006 if (xfer == NULL) {
2007 return SEDI_DRIVER_ERROR;
2008 }
2009
2010 sedi_uart_regs_t *const regs = SEDI_UART[uart];
2011
2012 regs->dmasa |= SEDI_RBFVM(UART, DMASA, DMASA, SOFT_ACK);
2013
2014 ret = sedi_dma_set_power(xfer->dma_dev, xfer->channel, SEDI_POWER_OFF);
2015 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
2016 ret = sedi_dma_uninit(xfer->dma_dev, xfer->channel);
2017 if (xfer->callback && (ret == SEDI_DRIVER_OK)) {
2018 xfer->callback(xfer->cb_param, SEDI_USART_ERROR_CANCELED, 0, 0);
2019 dma_write_ctxt[uart].dma_xfer = NULL;
2020 }
2021
2022 return ret;
2023 }
2024
sedi_uart_dma_read_async(IN sedi_uart_t uart,IN sedi_uart_dma_xfer_t * const xfer)2025 int sedi_uart_dma_read_async(IN sedi_uart_t uart, IN sedi_uart_dma_xfer_t *const xfer)
2026 {
2027 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2028 DBG_CHECK(xfer != NULL, SEDI_DRIVER_ERROR_PARAMETER);
2029 DBG_CHECK(xfer->dma_dev < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2030 DBG_CHECK(xfer->data != NULL, SEDI_DRIVER_ERROR_PARAMETER);
2031 DBG_CHECK(xfer->callback != NULL, SEDI_DRIVER_ERROR_PARAMETER);
2032 if (is_rx_disabled(uart)) {
2033 return SEDI_DRIVER_ERROR_UNSUPPORTED;
2034 }
2035
2036 int32_t ret;
2037
2038 ret = sedi_uart_dma_io_async(uart, xfer, READ);
2039 return ret;
2040 }
2041
sedi_uart_dma_read_terminate(IN sedi_uart_t uart)2042 int sedi_uart_dma_read_terminate(IN sedi_uart_t uart)
2043 {
2044 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2045 const sedi_uart_dma_xfer_t *xfer = dma_read_ctxt[uart].dma_xfer;
2046 int ret;
2047
2048 /* No ongoing read transaction to be terminated. */
2049 if (xfer == NULL) {
2050 return SEDI_DRIVER_ERROR;
2051 }
2052
2053 sedi_uart_regs_t *const regs = SEDI_UART[uart];
2054
2055 regs->dmasa |= SEDI_RBFVM(UART, DMASA, DMASA, SOFT_ACK);
2056
2057 ret = sedi_dma_set_power(xfer->dma_dev, xfer->channel, SEDI_POWER_OFF);
2058 DBG_CHECK(SEDI_DRIVER_OK == ret, SEDI_DRIVER_ERROR);
2059 ret = sedi_dma_uninit(xfer->dma_dev, xfer->channel);
2060 if (xfer->callback && (ret == SEDI_DRIVER_OK)) {
2061 xfer->callback(xfer->cb_param, SEDI_USART_ERROR_CANCELED, 0, 0);
2062 dma_read_ctxt[uart].dma_xfer = NULL;
2063 }
2064
2065 return ret;
2066 }
2067
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)2068 int sedi_uart_dma_write_polled(IN sedi_uart_t uart, IN sedi_dma_t dma_dev, IN uint32_t channel,
2069 IN uint8_t *buff, IN uint32_t length)
2070 {
2071 int ret;
2072
2073 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2074 DBG_CHECK(buff != NULL, SEDI_DRIVER_ERROR_PARAMETER);
2075 DBG_CHECK(length != 0, SEDI_DRIVER_ERROR_PARAMETER);
2076 if (is_tx_disabled(uart)) {
2077 return SEDI_DRIVER_ERROR_UNSUPPORTED;
2078 }
2079
2080 ret = sedi_uart_dma_io_polled(uart, dma_dev, channel, buff, length, WRITE);
2081 return ret;
2082 }
2083
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)2084 int sedi_uart_dma_read_polled(IN sedi_uart_t uart, IN sedi_dma_t dma_dev, IN uint32_t channel,
2085 OUT uint8_t *buff, IN uint32_t length, OUT uint32_t *status)
2086 {
2087 int ret;
2088
2089 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2090 DBG_CHECK(buff != NULL, SEDI_DRIVER_ERROR_PARAMETER);
2091 DBG_CHECK(length != 0, SEDI_DRIVER_ERROR_PARAMETER);
2092 DBG_CHECK(status != 0, SEDI_DRIVER_ERROR_PARAMETER);
2093 if (is_tx_disabled(uart)) {
2094 return SEDI_DRIVER_ERROR_UNSUPPORTED;
2095 }
2096 sedi_uart_regs_t *const regs = SEDI_UART[uart];
2097
2098 ret = sedi_uart_dma_io_polled(uart, dma_dev, channel, buff, length, READ);
2099 *status = regs->lsr & BSETS_UART_LSR_ERROR;
2100 return ret;
2101 }
2102
sedi_uart_set_tx_only_mode(IN sedi_uart_t uart,bool tx_only)2103 int sedi_uart_set_tx_only_mode(IN sedi_uart_t uart, bool tx_only)
2104 {
2105
2106 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2107 #if (HAS_UART_RS485_SUPPORT)
2108 sedi_uart_regs_t *const regs = SEDI_UART[uart];
2109 #endif
2110
2111 if (tx_only) {
2112 uart_xfer_ctrl[uart].tx_disable = false;
2113 uart_xfer_ctrl[uart].rx_disable = true;
2114
2115 #if (HAS_UART_RS485_SUPPORT)
2116 regs->de_en = true;
2117 regs->re_en = false;
2118 #endif
2119 } else {
2120 uart_xfer_ctrl[uart].tx_disable = false;
2121 uart_xfer_ctrl[uart].rx_disable = false;
2122
2123 #if (HAS_UART_RS485_SUPPORT)
2124 regs->de_en = true;
2125 regs->re_en = true;
2126 #endif
2127 }
2128 return SEDI_DRIVER_OK;
2129 }
2130
sedi_uart_set_rx_only_mode(IN sedi_uart_t uart,bool rx_only)2131 int sedi_uart_set_rx_only_mode(IN sedi_uart_t uart, bool rx_only)
2132 {
2133
2134 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2135 #if (HAS_UART_RS485_SUPPORT)
2136 sedi_uart_regs_t *const regs = SEDI_UART[uart];
2137 #endif
2138
2139 if (rx_only) {
2140 uart_xfer_ctrl[uart].tx_disable = true;
2141 uart_xfer_ctrl[uart].rx_disable = false;
2142
2143 #if (HAS_UART_RS485_SUPPORT)
2144 regs->de_en = false;
2145 regs->re_en = true;
2146 #endif
2147 } else {
2148 uart_xfer_ctrl[uart].tx_disable = false;
2149 uart_xfer_ctrl[uart].rx_disable = false;
2150
2151 #if (HAS_UART_RS485_SUPPORT)
2152 regs->de_en = true;
2153 regs->re_en = true;
2154 #endif
2155 }
2156
2157 return SEDI_DRIVER_OK;
2158 }
2159
sedi_uart_disable_tx_rx(IN sedi_uart_t uart)2160 static void sedi_uart_disable_tx_rx(IN sedi_uart_t uart)
2161 {
2162 uart_xfer_ctrl[uart].tx_disable = true;
2163 uart_xfer_ctrl[uart].rx_disable = true;
2164 }
2165
sedi_uart_enable_tx_rx(IN sedi_uart_t uart)2166 static void sedi_uart_enable_tx_rx(IN sedi_uart_t uart)
2167 {
2168 uart_xfer_ctrl[uart].tx_disable = false;
2169 uart_xfer_ctrl[uart].rx_disable = false;
2170 }
2171
sedi_uart_set_power(IN sedi_uart_t uart,IN sedi_power_state_t state)2172 int32_t sedi_uart_set_power(IN sedi_uart_t uart, IN sedi_power_state_t state)
2173 {
2174
2175 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2176
2177 sedi_devid_t id = SEDI_DEVID_UART0 + uart;
2178 int32_t ret = SEDI_DRIVER_OK;
2179
2180 switch (state) {
2181 case SEDI_POWER_FULL:
2182
2183 /* Enable clocks */
2184 sedi_pm_set_device_power(id, state);
2185 sedi_uart_restore_context(uart);
2186 sedi_uart_enable_tx_rx(uart);
2187 break;
2188
2189 case SEDI_POWER_SUSPEND:
2190 /* Disable both tx and rx in configuration. */
2191 sedi_uart_disable_tx_rx(uart);
2192 sedi_uart_save_context(uart);
2193 sedi_pm_set_device_power(id, state);
2194 break;
2195
2196 case SEDI_POWER_FORCE_SUSPEND:
2197 sedi_uart_disable_tx_rx(uart);
2198 sedi_pm_set_device_power(id, state);
2199 break;
2200
2201 case SEDI_POWER_LOW:
2202
2203 sedi_uart_disable_tx_rx(uart);
2204 /* Clock gating for uart */
2205 sedi_pm_set_device_power(id, state);
2206 break;
2207
2208 case SEDI_POWER_OFF:
2209 default:
2210 ret = SEDI_DRIVER_ERROR_UNSUPPORTED;
2211 break;
2212 }
2213 return ret;
2214 }
2215
sedi_uart_init(IN sedi_uart_t uart,void * base)2216 int32_t sedi_uart_init(IN sedi_uart_t uart, void *base)
2217 {
2218 DBG_CHECK(uart < SEDI_UART_NUM, SEDI_DRIVER_ERROR_PARAMETER);
2219
2220 sedi_uart[uart] = (sedi_uart_regs_t *)base;
2221
2222 return SEDI_DRIVER_OK;
2223 }
2224