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