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