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