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)(&regs->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)(&regs->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)(&regs->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)(&regs->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