1 /*******************************************************************************
2 * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * PolarFire SoC Microprocessor Subsystem MMUART bare metal software driver
7 * implementation.
8 *
9 */
10 #include "mpfs_hal/mss_hal.h"
11 #include "mss_uart_regs.h"
12 #include "mss_uart.h"
13
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17
18 #define MSS_UART0_LO_BASE (MSS_UART_TypeDef*)0x20000000UL
19 #define MSS_UART1_LO_BASE (MSS_UART_TypeDef*)0x20100000UL
20 #define MSS_UART2_LO_BASE (MSS_UART_TypeDef*)0x20102000UL
21 #define MSS_UART3_LO_BASE (MSS_UART_TypeDef*)0x20104000UL
22 #define MSS_UART4_LO_BASE (MSS_UART_TypeDef*)0x20106000UL
23
24 #define MSS_UART0_HI_BASE (MSS_UART_TypeDef*)0x28000000UL
25 #define MSS_UART1_HI_BASE (MSS_UART_TypeDef*)0x28100000UL
26 #define MSS_UART2_HI_BASE (MSS_UART_TypeDef*)0x28102000UL
27 #define MSS_UART3_HI_BASE (MSS_UART_TypeDef*)0x28104000UL
28 #define MSS_UART4_HI_BASE (MSS_UART_TypeDef*)0x28106000UL
29
30
31 mss_uart_instance_t g_mss_uart0_lo;
32 mss_uart_instance_t g_mss_uart1_lo;
33 mss_uart_instance_t g_mss_uart2_lo;
34 mss_uart_instance_t g_mss_uart3_lo;
35 mss_uart_instance_t g_mss_uart4_lo;
36
37 mss_uart_instance_t g_mss_uart0_hi;
38 mss_uart_instance_t g_mss_uart1_hi;
39 mss_uart_instance_t g_mss_uart2_hi;
40 mss_uart_instance_t g_mss_uart3_hi;
41 mss_uart_instance_t g_mss_uart4_hi;
42
43 /* This variable tracks if the UART peripheral is located on S5 or S6 on AXI
44 * switch. This will be used to determine which UART instance to be passed to
45 * UART interrupt handler. value 0 = S5(low). value 1 = S6(high)
46 * Bit positions:
47 * 0 ==> MMUART0
48 * 1 ==> MMUART1
49 * 2 ==> MMUART2
50 * 3 ==> MMUART3
51 * 4 ==> MMUART4
52
53 */
54 static uint32_t g_uart_axi_pos = 0x0u;
55
56 /*******************************************************************************
57 * Defines
58 */
59 #define TX_COMPLETE 0u
60 #define TX_FIFO_SIZE 16u
61
62 #define FCR_TRIG_LEVEL_MASK 0xC0u
63
64 #define IIRF_MASK 0x0Fu
65
66 #define INVALID_INTERRUPT 0u
67 #define INVALID_IRQ_HANDLER ((mss_uart_irq_handler_t) 0)
68 #define NULL_HANDLER ((mss_uart_irq_handler_t) 0)
69
70 #define MSS_UART_DATA_READY ((uint8_t) 0x01)
71
72 #define SYNC_ASYNC_MODE_MASK (0x7u)
73
74 #define UART0_POSITION_MASK 0x01u
75 #define UART1_POSITION_MASK 0x02u
76 #define UART2_POSITION_MASK 0x04u
77 #define UART3_POSITION_MASK 0x08u
78 #define UART4_POSITION_MASK 0x10u
79
80 /*******************************************************************************
81 * Possible values for Interrupt Identification Register Field.
82 */
83 #define IIRF_MODEM_STATUS 0x00u
84 #define IIRF_THRE 0x02u
85 #define IIRF_MMI 0x03u
86 #define IIRF_RX_DATA 0x04u
87 #define IIRF_RX_LINE_STATUS 0x06u
88 #define IIRF_DATA_TIMEOUT 0x0Cu
89
90 /*******************************************************************************
91 * Receiver error status mask.
92 */
93 #define STATUS_ERROR_MASK ( MSS_UART_OVERUN_ERROR | MSS_UART_PARITY_ERROR | \
94 MSS_UART_FRAMING_ERROR | MSS_UART_BREAK_ERROR | \
95 MSS_UART_FIFO_ERROR)
96
97 /*******************************************************************************
98 * Local functions.
99 */
100 static void global_init(mss_uart_instance_t * this_uart, uint32_t baud_rate,
101 uint8_t line_config);
102 static void uart_isr(mss_uart_instance_t * this_uart);
103 static void default_tx_handler(mss_uart_instance_t * this_uart);
104 static void enable_irq(const mss_uart_instance_t * this_uart);
105 static void disable_irq(const mss_uart_instance_t * this_uart);
106 static void config_baud_divisors
107 (
108 mss_uart_instance_t * this_uart,
109 uint32_t baudrate
110 );
111
112 /*******************************************************************************
113 * Public Functions
114 *******************************************************************************/
115 /***************************************************************************//**
116 * See mss_uart.h for details of how to use this function.
117 */
118 void
MSS_UART_init(mss_uart_instance_t * this_uart,uint32_t baud_rate,uint8_t line_config)119 MSS_UART_init
120 (
121 mss_uart_instance_t* this_uart,
122 uint32_t baud_rate,
123 uint8_t line_config
124 )
125 {
126 /* Perform generic initialization */
127 global_init(this_uart, baud_rate, line_config);
128
129 /* Disable LIN mode */
130 this_uart->hw_reg->MM0 &= ~ELIN_MASK;
131
132 /* Disable IrDA mode */
133 this_uart->hw_reg->MM1 &= ~EIRD_MASK;
134
135 /* Disable SmartCard Mode */
136 this_uart->hw_reg->MM2 &= ~EERR_MASK;
137
138 /* set default tx handler for automated TX using interrupt in USART mode */
139 this_uart->tx_handler = default_tx_handler;
140 }
141
142 /***************************************************************************//**
143 * See mss_uart.h for details of how to use this function.
144 */
MSS_UART_lin_init(mss_uart_instance_t * this_uart,uint32_t baud_rate,uint8_t line_config)145 void MSS_UART_lin_init
146 (
147 mss_uart_instance_t* this_uart,
148 uint32_t baud_rate,
149 uint8_t line_config
150 )
151 {
152 /* Perform generic initialization */
153 global_init(this_uart, baud_rate, line_config);
154
155 /* Enable LIN mode */
156 this_uart->hw_reg->MM0 |= ELIN_MASK;
157
158 /* Disable IrDA mode */
159 this_uart->hw_reg->MM1 &= ~EIRD_MASK;
160
161 /* Disable SmartCard Mode */
162 this_uart->hw_reg->MM2 &= ~EERR_MASK;
163 }
164
165 /***************************************************************************//**
166 * See mss_uart.h for details of how to use this function.
167 */
168 void
MSS_UART_irda_init(mss_uart_instance_t * this_uart,uint32_t baud_rate,uint8_t line_config,mss_uart_rzi_polarity_t rxpol,mss_uart_rzi_polarity_t txpol,mss_uart_rzi_pulsewidth_t pw)169 MSS_UART_irda_init
170 (
171 mss_uart_instance_t* this_uart,
172 uint32_t baud_rate,
173 uint8_t line_config,
174 mss_uart_rzi_polarity_t rxpol,
175 mss_uart_rzi_polarity_t txpol,
176 mss_uart_rzi_pulsewidth_t pw
177 )
178 {
179 /* Perform generic initialization */
180 global_init(this_uart, baud_rate, line_config);
181
182 /* Enable LIN mode */
183 this_uart->hw_reg->MM0 &= ~ELIN_MASK;
184
185 /* Disable IrDA mode */
186 this_uart->hw_reg->MM1 |= EIRD_MASK;
187
188 ((rxpol == MSS_UART_ACTIVE_LOW) ? (this_uart->hw_reg->MM1 &= ~EIRX_MASK) :
189 (this_uart->hw_reg->MM1 |= EIRX_MASK));
190
191 ((txpol == MSS_UART_ACTIVE_LOW) ? (this_uart->hw_reg->MM1 &= ~EITX_MASK) :
192 (this_uart->hw_reg->MM1 |= EITX_MASK));
193
194 ((pw == MSS_UART_3_BY_16) ? (this_uart->hw_reg->MM1 &= ~EITP_MASK) :
195 (this_uart->hw_reg->MM1 |= EITP_MASK));
196 /* Disable SmartCard Mode */
197 this_uart->hw_reg->MM2 &= ~EERR_MASK;
198 }
199
200 /***************************************************************************//**
201 * See mss_uart.h for details of how to use this function.
202 */
203 void
MSS_UART_smartcard_init(mss_uart_instance_t * this_uart,uint32_t baud_rate,uint8_t line_config)204 MSS_UART_smartcard_init
205 (
206 mss_uart_instance_t* this_uart,
207 uint32_t baud_rate,
208 uint8_t line_config
209 )
210 {
211 /* Perform generic initialization */
212 global_init(this_uart, baud_rate, line_config);
213
214 /* Disable LIN mode */
215 this_uart->hw_reg->MM0 &= ~ELIN_MASK;
216
217 /* Disable IrDA mode */
218 this_uart->hw_reg->MM1 &= ~EIRD_MASK;
219
220 /* Enable SmartCard Mode : Only when data is 8-bit and 2 stop bits */
221 if ((MSS_UART_DATA_8_BITS | MSS_UART_TWO_STOP_BITS) ==
222 (line_config & (MSS_UART_DATA_8_BITS | MSS_UART_TWO_STOP_BITS)))
223 {
224 this_uart->hw_reg->MM2 |= EERR_MASK;
225
226 /* Enable single wire half-duplex mode */
227 this_uart->hw_reg->MM2 |= ESWM_MASK;
228 }
229 }
230
231 /***************************************************************************//**
232 * See mss_uart.h for details of how to use this function.
233 */
234 void
MSS_UART_polled_tx(mss_uart_instance_t * this_uart,const uint8_t * pbuff,uint32_t tx_size)235 MSS_UART_polled_tx
236 (
237 mss_uart_instance_t * this_uart,
238 const uint8_t * pbuff,
239 uint32_t tx_size
240 )
241 {
242 uint32_t char_idx = 0u;
243 uint32_t size_sent;
244 uint8_t status;
245 uint32_t temp_tx_size = tx_size;
246
247 ASSERT(pbuff != ( (uint8_t*)0));
248 ASSERT(tx_size > 0u);
249
250 if ((pbuff != ((uint8_t*)0)) && (temp_tx_size > 0u))
251 {
252 /* Remain in this loop until the entire input buffer
253 * has been transferred to the UART.
254 */
255 do
256 {
257 /* Read the Line Status Register and update the sticky record */
258 status = this_uart->hw_reg->LSR;
259 this_uart->status |= status;
260
261 /* Check if TX FIFO is empty. */
262 if (status & MSS_UART_THRE)
263 {
264 uint32_t fill_size = TX_FIFO_SIZE;
265
266 /* Calculate the number of bytes to transmit. */
267 if (temp_tx_size < TX_FIFO_SIZE)
268 {
269 fill_size = temp_tx_size;
270 }
271
272 /* Fill the TX FIFO with the calculated the number of bytes. */
273 for (size_sent = 0u; size_sent < fill_size; ++size_sent)
274 {
275 /* Send next character in the buffer. */
276 this_uart->hw_reg->THR = pbuff[char_idx];
277 char_idx++;
278 }
279
280 /* find the number of bytes remaining(not transmitted yet) */
281 temp_tx_size -= size_sent;
282 }
283 }while (temp_tx_size);
284 }
285 }
286
287 /***************************************************************************//**
288 * See mss_uart.h for details of how to use this function.
289 */
290 void
MSS_UART_polled_tx_string(mss_uart_instance_t * this_uart,const uint8_t * p_sz_string)291 MSS_UART_polled_tx_string
292 (
293 mss_uart_instance_t * this_uart,
294 const uint8_t * p_sz_string
295 )
296 {
297 uint32_t char_idx = 0u;
298 uint32_t fill_size;
299 uint8_t data_byte;
300 uint8_t status;
301
302 ASSERT(p_sz_string != ((uint8_t*)0));
303
304 if (p_sz_string != ((uint8_t*)0))
305 {
306 /* Get the first data byte from the input buffer */
307 data_byte = p_sz_string[char_idx];
308
309 /* First check for the NULL terminator byte.
310 * Then remain in this loop until the entire string in the input buffer
311 * has been transferred to the UART.
312 */
313 while (0u != data_byte)
314 {
315 /* Wait until TX FIFO is empty. */
316 do
317 {
318 status = this_uart->hw_reg->LSR;
319 this_uart->status |= status;
320 }while (0u == (status & MSS_UART_THRE));
321
322 /* Send bytes from the input buffer until the TX FIFO is full
323 * or we reach the NULL terminator byte.
324 */
325 fill_size = 0u;
326
327 while ((0u != data_byte) && (fill_size < TX_FIFO_SIZE))
328 {
329 /* Send the data byte */
330 this_uart->hw_reg->THR = data_byte;
331 ++fill_size;
332 char_idx++;
333 /* Get the next data byte from the input buffer */
334 data_byte = p_sz_string[char_idx];
335 }
336 }
337 }
338 }
339
340 /***************************************************************************//**
341 * See mss_uart.h for details of how to use this function.
342 */
343 void
MSS_UART_irq_tx(mss_uart_instance_t * this_uart,const uint8_t * pbuff,uint32_t tx_size)344 MSS_UART_irq_tx
345 (
346 mss_uart_instance_t * this_uart,
347 const uint8_t * pbuff,
348 uint32_t tx_size
349 )
350 {
351 ASSERT(pbuff != ((uint8_t*)0));
352 ASSERT(tx_size > 0u);
353
354 if ((tx_size > 0u) && (pbuff != ((uint8_t*)0)))
355 {
356 /* Initialize the transmit info for the UART instance with the
357 * arguments */
358 this_uart->tx_buffer = pbuff;
359 this_uart->tx_buff_size = tx_size;
360 this_uart->tx_idx = 0u;
361
362 /* assign default handler for data transfer */
363 this_uart->tx_handler = default_tx_handler;
364
365 /* enables TX interrupt */
366 this_uart->hw_reg->IER |= ETBEI_MASK;
367 enable_irq(this_uart);
368 }
369 }
370
371 /***************************************************************************//**
372 * See mss_uart.h for details of how to use this function.
373 */
374 int8_t
MSS_UART_tx_complete(mss_uart_instance_t * this_uart)375 MSS_UART_tx_complete
376 (
377 mss_uart_instance_t * this_uart
378 )
379 {
380 int8_t ret_value = 0;
381 uint8_t status = 0u;
382
383 /* Read the Line Status Register and update the sticky record. */
384 status = this_uart->hw_reg->LSR;
385 this_uart->status |= status;
386
387 if ((TX_COMPLETE == this_uart->tx_buff_size) &&
388 ((status & MSS_UART_TEMT) != 0u))
389 {
390 ret_value = (int8_t)1;
391 }
392
393 return ret_value;
394 }
395
396 /***************************************************************************//**
397 * See mss_uart.h for details of how to use this function.
398 */
399 size_t
MSS_UART_get_rx(mss_uart_instance_t * this_uart,uint8_t * rx_buff,size_t buff_size)400 MSS_UART_get_rx
401 (
402 mss_uart_instance_t * this_uart,
403 uint8_t * rx_buff,
404 size_t buff_size
405 )
406 {
407 size_t rx_size = 0u;
408 uint8_t status = 0u;
409
410 ASSERT(rx_buff != ((uint8_t*)0));
411 ASSERT(buff_size > 0u);
412
413 if ((rx_buff != (uint8_t*)0) && (buff_size > 0u))
414 {
415 status = this_uart->hw_reg->LSR;
416 this_uart->status |= status;
417
418 while (((status & MSS_UART_DATA_READY) != 0u) && (rx_size < buff_size))
419 {
420 rx_buff[rx_size] = this_uart->hw_reg->RBR;
421 ++rx_size;
422 status = this_uart->hw_reg->LSR;
423 this_uart->status |= status;
424 }
425 }
426
427 return rx_size;
428 }
429
430 /***************************************************************************//**
431 * See mss_uart.h for details of how to use this function.
432 */
433 void
MSS_UART_enable_irq(mss_uart_instance_t * this_uart,mss_uart_irq_t irq_mask)434 MSS_UART_enable_irq
435 (
436 mss_uart_instance_t * this_uart,
437 mss_uart_irq_t irq_mask
438 )
439 {
440 ASSERT(MSS_UART_INVALID_IRQ > irq_mask);
441
442 enable_irq(this_uart);
443
444 if (MSS_UART_INVALID_IRQ > irq_mask)
445 {
446 /* irq_mask encoding: 1- enable
447 * bit 0 - Receive Data Available Interrupt
448 * bit 1 - Transmitter Holding Register Empty Interrupt
449 * bit 2 - Receiver Line Status Interrupt
450 * bit 3 - Modem Status Interrupt
451 */
452 this_uart->hw_reg->IER |= ((uint8_t)(((uint32_t)irq_mask &
453 (uint32_t)IIRF_MASK)));
454
455
456 /*
457 * bit 4 - Receiver time-out interrupt
458 * bit 5 - NACK / ERR signal interrupt
459 * bit 6 - PID parity error interrupt
460 * bit 7 - LIN break detection interrupt
461 * bit 8 - LIN Sync detection interrupt
462 */
463 this_uart->hw_reg->IEM |= (uint8_t)(((uint32_t)irq_mask >> 4u) &
464 ((uint32_t)IIRF_MASK));
465 }
466 }
467
468 /***************************************************************************//**
469 * See mss_uart.h for details of how to use this function.
470 */
471 void
MSS_UART_disable_irq(mss_uart_instance_t * this_uart,mss_uart_irq_t irq_mask)472 MSS_UART_disable_irq
473 (
474 mss_uart_instance_t * this_uart,
475 mss_uart_irq_t irq_mask
476 )
477 {
478 /* irq_mask encoding: 1 - disable
479 * bit 0 - Receive Data Available Interrupt
480 * bit 1 - Transmitter Holding Register Empty Interrupt
481 * bit 2 - Receiver Line Status Interrupt
482 * bit 3 - Modem Status Interrupt
483 */
484 this_uart->hw_reg->IER &= ((uint8_t)(~((uint32_t)irq_mask &
485 (uint32_t)IIRF_MASK)));
486
487 /*
488 * bit 4 - Receiver time-out interrupt
489 * bit 5 - NACK / ERR signal interrupt
490 * bit 6 - PID parity error interrupt
491 * bit 7 - LIN break detection interrupt
492 * bit 8 - LIN Sync detection interrupt
493 */
494 this_uart->hw_reg->IEM &= (uint8_t)(~(((uint32_t)irq_mask >> 4u) &
495 ((uint32_t)IIRF_MASK)));
496
497 if(1 == this_uart->local_irq_enabled)
498 {
499 __disable_local_irq((int8_t)MMUART0_E51_INT);
500 }
501 else
502 {
503 disable_irq(this_uart);
504 }
505 }
506
507 /***************************************************************************//**
508 * See mss_uart.h for details of how to use this function.
509 */
510 void
MSS_UART_set_rx_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler,mss_uart_rx_trig_level_t trigger_level)511 MSS_UART_set_rx_handler
512 (
513 mss_uart_instance_t * this_uart,
514 mss_uart_irq_handler_t handler,
515 mss_uart_rx_trig_level_t trigger_level
516 )
517 {
518 ASSERT(handler != INVALID_IRQ_HANDLER );
519 ASSERT(trigger_level < MSS_UART_FIFO_INVALID_TRIG_LEVEL);
520
521 if ((handler != INVALID_IRQ_HANDLER) &&
522 (trigger_level < MSS_UART_FIFO_INVALID_TRIG_LEVEL))
523 {
524 this_uart->rx_handler = handler;
525
526 /* Set the receive interrupt trigger level. */
527 this_uart->hw_reg->FCR = (this_uart->hw_reg->FCR &
528 (uint8_t)(~((uint8_t)FCR_TRIG_LEVEL_MASK))) |
529 (uint8_t)trigger_level;
530
531 /* Enable receive interrupt. */
532 this_uart->hw_reg->IER |= ERBFI_MASK;
533
534 enable_irq(this_uart);
535 }
536 }
537
538 /***************************************************************************//**
539 * See mss_uart.h for details of how to use this function.
540 */
541 void
MSS_UART_set_loopback(mss_uart_instance_t * this_uart,mss_uart_loopback_t loopback)542 MSS_UART_set_loopback
543 (
544 mss_uart_instance_t * this_uart,
545 mss_uart_loopback_t loopback
546 )
547 {
548 ASSERT(MSS_UART_INVALID_LOOPBACK > loopback);
549
550 if (MSS_UART_INVALID_LOOPBACK > loopback)
551 {
552 switch (loopback)
553 {
554 case MSS_UART_LOCAL_LOOPBACK_OFF:
555 /* Disable local loopback */
556 this_uart->hw_reg->MCR &= ~LOOP_MASK;
557 break;
558
559 case MSS_UART_LOCAL_LOOPBACK_ON:
560 /* Enable local loopback */
561 this_uart->hw_reg->MCR |= LOOP_MASK;
562 break;
563
564 case MSS_UART_REMOTE_LOOPBACK_OFF:
565 case MSS_UART_AUTO_ECHO_OFF:
566 /* Disable remote loopback & automatic echo */
567 this_uart->hw_reg->MCR &= ~(RLOOP_MASK|ECHO_MASK);
568 break;
569
570 case MSS_UART_REMOTE_LOOPBACK_ON:
571 /* Enable remote loopback */
572 this_uart->hw_reg->MCR |= (1u << RLOOP);
573 break;
574
575 case MSS_UART_AUTO_ECHO_ON:
576 /* Enable automatic echo */
577 this_uart->hw_reg->MCR |= (1u << ECHO);
578 break;
579
580 case MSS_UART_INVALID_LOOPBACK:
581 /* Fall through to default. */
582 default:
583 ASSERT(0);
584 break;
585 }
586 }
587 }
588
589 /***************************************************************************//**
590 * interrupt service routine.
591 */
mmuart0_plic_77_IRQHandler(void)592 uint8_t mmuart0_plic_77_IRQHandler(void)
593 {
594 if (g_uart_axi_pos & UART0_POSITION_MASK)
595 {
596 uart_isr(&g_mss_uart0_hi);
597 }
598 else
599 {
600 uart_isr(&g_mss_uart0_lo);
601 }
602
603 return EXT_IRQ_KEEP_ENABLED;
604 }
605
mmuart1_plic_IRQHandler(void)606 uint8_t mmuart1_plic_IRQHandler(void)
607 {
608 if (g_uart_axi_pos & UART1_POSITION_MASK)
609 {
610 uart_isr(&g_mss_uart1_hi);
611 }
612 else
613 {
614 uart_isr(&g_mss_uart1_lo);
615 }
616
617 return EXT_IRQ_KEEP_ENABLED;
618 }
619
mmuart2_plic_IRQHandler(void)620 uint8_t mmuart2_plic_IRQHandler(void)
621 {
622 if (g_uart_axi_pos & UART2_POSITION_MASK)
623 {
624 uart_isr(&g_mss_uart2_hi);
625 }
626 else
627 {
628 uart_isr(&g_mss_uart2_lo);
629 }
630
631 return EXT_IRQ_KEEP_ENABLED;
632 }
633
mmuart3_plic_IRQHandler(void)634 uint8_t mmuart3_plic_IRQHandler(void)
635 {
636 if (g_uart_axi_pos & UART3_POSITION_MASK)
637 {
638 uart_isr(&g_mss_uart3_hi);
639 }
640 else
641 {
642 uart_isr(&g_mss_uart3_lo);
643 }
644
645 return EXT_IRQ_KEEP_ENABLED;
646 }
647
mmuart4_plic_IRQHandler(void)648 uint8_t mmuart4_plic_IRQHandler(void)
649 {
650 if (g_uart_axi_pos & UART4_POSITION_MASK)
651 {
652 uart_isr(&g_mss_uart4_hi);
653 }
654 else
655 {
656 uart_isr(&g_mss_uart4_lo);
657 }
658
659 return EXT_IRQ_KEEP_ENABLED;
660 }
661
mmuart0_e51_local_IRQHandler_11(void)662 void mmuart0_e51_local_IRQHandler_11(void)
663 {
664 if (g_uart_axi_pos & UART0_POSITION_MASK)
665 {
666 uart_isr(&g_mss_uart0_hi);
667 }
668 else
669 {
670 uart_isr(&g_mss_uart0_lo);
671 }
672 }
673
mmuart_u54_h1_local_IRQHandler_11(void)674 void mmuart_u54_h1_local_IRQHandler_11(void)
675 {
676 if (g_uart_axi_pos & UART1_POSITION_MASK)
677 {
678 uart_isr(&g_mss_uart1_hi);
679 }
680 else
681 {
682 uart_isr(&g_mss_uart1_lo);
683 }
684 }
685
mmuart_u54_h2_local_IRQHandler_11(void)686 void mmuart_u54_h2_local_IRQHandler_11(void)
687 {
688 if (g_uart_axi_pos & UART2_POSITION_MASK)
689 {
690 uart_isr(&g_mss_uart2_hi);
691 }
692 else
693 {
694 uart_isr(&g_mss_uart2_lo);
695 }
696 }
697
mmuart_u54_h3_local_IRQHandler_11(void)698 void mmuart_u54_h3_local_IRQHandler_11(void)
699 {
700 if (g_uart_axi_pos & UART3_POSITION_MASK)
701 {
702 uart_isr(&g_mss_uart3_hi);
703 }
704 else
705 {
706 uart_isr(&g_mss_uart3_lo);
707 }
708 }
709
mmuart_u54_h4_local_IRQHandler_11(void)710 void mmuart_u54_h4_local_IRQHandler_11(void)
711 {
712 if (g_uart_axi_pos & UART4_POSITION_MASK)
713 {
714 uart_isr(&g_mss_uart4_hi);
715 }
716 else
717 {
718 uart_isr(&g_mss_uart4_lo);
719 }
720 }
721
722 /***************************************************************************//**
723 * See mss_uart.h for details of how to use this function.
724 */
725 void
MSS_UART_set_rxstatus_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)726 MSS_UART_set_rxstatus_handler
727 (
728 mss_uart_instance_t * this_uart,
729 mss_uart_irq_handler_t handler
730 )
731 {
732 ASSERT(handler != INVALID_IRQ_HANDLER);
733
734 if (handler != INVALID_IRQ_HANDLER)
735 {
736 this_uart->linests_handler = handler;
737
738 /* Enable receiver line status interrupt. */
739 this_uart->hw_reg->IER |= ELSI_MASK;
740
741 enable_irq(this_uart);
742 }
743 }
744
745 /***************************************************************************//**
746 * See mss_uart.h for details of how to use this function.
747 */
748 void
MSS_UART_set_tx_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)749 MSS_UART_set_tx_handler
750 (
751 mss_uart_instance_t * this_uart,
752 mss_uart_irq_handler_t handler
753 )
754 {
755 ASSERT(handler != INVALID_IRQ_HANDLER);
756
757 if (handler != INVALID_IRQ_HANDLER)
758 {
759 this_uart->tx_handler = handler;
760
761 /* Make TX buffer info invalid */
762 this_uart->tx_buffer = (const uint8_t*)0;
763 this_uart->tx_buff_size = 0u;
764
765 /* Enable transmitter holding register Empty interrupt. */
766 this_uart->hw_reg->IER |= ETBEI_MASK;
767 enable_irq(this_uart);
768 }
769 }
770
771 /***************************************************************************//**
772 * See mss_uart.h for details of how to use this function.
773 */
774 void
MSS_UART_set_modemstatus_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)775 MSS_UART_set_modemstatus_handler
776 (
777 mss_uart_instance_t * this_uart,
778 mss_uart_irq_handler_t handler
779 )
780 {
781 ASSERT(handler != INVALID_IRQ_HANDLER);
782
783 if (handler != INVALID_IRQ_HANDLER)
784 {
785 this_uart->modemsts_handler = handler;
786
787 /* Enable modem status interrupt. */
788 this_uart->hw_reg->IER |= EDSSI_MASK;
789 enable_irq(this_uart);
790 }
791 }
792
793 /***************************************************************************//**
794 * See mss_uart.h for details of how to use this function.
795 */
796 size_t
MSS_UART_fill_tx_fifo(mss_uart_instance_t * this_uart,const uint8_t * tx_buffer,size_t tx_size)797 MSS_UART_fill_tx_fifo
798 (
799 mss_uart_instance_t * this_uart,
800 const uint8_t * tx_buffer,
801 size_t tx_size
802 )
803 {
804 uint8_t status = 0u;
805 uint32_t size_sent = 0u;
806
807 ASSERT(tx_buffer != ( (uint8_t*)0));
808 ASSERT(tx_size > 0);
809
810 /* Fill the UART's Tx FIFO until the FIFO is full or the complete input
811 * buffer has been written. */
812 if ((tx_buffer != ((uint8_t*)0)) && (tx_size > 0u))
813 {
814 status = this_uart->hw_reg->LSR;
815 this_uart->status |= status;
816
817 if (status & MSS_UART_THRE)
818 {
819 uint32_t fill_size = TX_FIFO_SIZE;
820
821 if (tx_size < TX_FIFO_SIZE)
822 {
823 fill_size = tx_size;
824 }
825
826 /* Fill up FIFO */
827 for (size_sent = 0u; size_sent < fill_size; size_sent++)
828 {
829 /* Send next character in the buffer. */
830 this_uart->hw_reg->THR = tx_buffer[size_sent];
831 }
832 }
833 }
834
835 return size_sent;
836 }
837
838 /***************************************************************************//**
839 * See mss_uart.h for details of how to use this function.
840 */
841 uint8_t
MSS_UART_get_rx_status(mss_uart_instance_t * this_uart)842 MSS_UART_get_rx_status
843 (
844 mss_uart_instance_t * this_uart
845 )
846 {
847 uint8_t status = MSS_UART_INVALID_PARAM;
848
849 /*
850 * Extract UART receive error status.
851 * Bit 1 - Overflow error status
852 * Bit 2 - Parity error status
853 * Bit 3 - Frame error status
854 * Bit 4 - Break interrupt indicator
855 * Bit 7 - FIFO data error status
856 */
857 this_uart->status |= (this_uart->hw_reg->LSR);
858 status = (this_uart->status & STATUS_ERROR_MASK);
859 /* Clear the sticky status after reading */
860 this_uart->status = 0u;
861
862 return status;
863 }
864
865 /***************************************************************************//**
866 * See mss_uart.h for details of how to use this function.
867 */
868 uint8_t
MSS_UART_get_modem_status(const mss_uart_instance_t * this_uart)869 MSS_UART_get_modem_status
870 (
871 const mss_uart_instance_t * this_uart
872 )
873 {
874 uint8_t status = MSS_UART_INVALID_PARAM;
875
876 /*
877 * Extract UART modem status and place in lower bits of "status".
878 * Bit 0 - Delta Clear to Send Indicator
879 * Bit 1 - Delta Clear to Receive Indicator
880 * Bit 2 - Trailing edge of Ring Indicator detector
881 * Bit 3 - Delta Data Carrier Detect indicator
882 * Bit 4 - Clear To Send
883 * Bit 5 - Data Set Ready
884 * Bit 6 - Ring Indicator
885 * Bit 7 - Data Carrier Detect
886 */
887 status = this_uart->hw_reg->MSR;
888
889 return status;
890 }
891
892 /***************************************************************************//**
893 * MSS_UART_get_tx_status.
894 * See mss_uart.h for details of how to use this function.
895 */
896 uint8_t
MSS_UART_get_tx_status(mss_uart_instance_t * this_uart)897 MSS_UART_get_tx_status
898 (
899 mss_uart_instance_t * this_uart
900 )
901 {
902 uint8_t status = MSS_UART_TX_BUSY;
903
904 /* Read the Line Status Register and update the sticky record. */
905 status = this_uart->hw_reg->LSR;
906 this_uart->status |= status;
907
908 /*
909 * Extract the transmit status bits from the UART's Line Status Register.
910 * Bit 5 - Transmitter Holding Register/FIFO Empty (THRE) status.
911 (If = 1, TX FIFO is empty)
912 * Bit 6 - Transmitter Empty (TEMT) status.
913 (If = 1, both TX FIFO and shift register are empty)
914 */
915 status &= (MSS_UART_THRE | MSS_UART_TEMT);
916
917 return status;
918 }
919
920 /***************************************************************************//**
921 * See mss_uart.h for details of how to use this function.
922 */
923 void
MSS_UART_set_break(mss_uart_instance_t * this_uart)924 MSS_UART_set_break
925 (
926 mss_uart_instance_t * this_uart
927 )
928 {
929 /* set break character on Tx line */
930 this_uart->hw_reg->LCR |= SB_MASK;
931 }
932
933 /***************************************************************************//**
934 * See mss_uart.h for details of how to use this function.
935 */
936 void
MSS_UART_clear_break(mss_uart_instance_t * this_uart)937 MSS_UART_clear_break
938 (
939 mss_uart_instance_t * this_uart
940 )
941 {
942 /* remove break character from Tx line */
943 this_uart->hw_reg->LCR &= ~SB_MASK;
944 }
945
946 /***************************************************************************//**
947 * See mss_uart.h for details of how to use this function.
948 */
949 void
MSS_UART_set_pidpei_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)950 MSS_UART_set_pidpei_handler
951 (
952 mss_uart_instance_t * this_uart,
953 mss_uart_irq_handler_t handler
954 )
955 {
956 ASSERT(handler != INVALID_IRQ_HANDLER);
957
958 if (handler != INVALID_IRQ_HANDLER)
959 {
960 this_uart->pid_pei_handler = handler;
961
962 /* Enable PID parity error interrupt. */
963 this_uart->hw_reg->IEM |= EPID_PEI_MASK;
964 enable_irq(this_uart);
965 }
966 }
967
968 /***************************************************************************//**
969 * See mss_uart.h for details of how to use this function.
970 */
971 void
MSS_UART_set_linbreak_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)972 MSS_UART_set_linbreak_handler
973 (
974 mss_uart_instance_t * this_uart,
975 mss_uart_irq_handler_t handler
976 )
977 {
978 ASSERT(handler != INVALID_IRQ_HANDLER);
979
980 if (handler != INVALID_IRQ_HANDLER)
981 {
982 this_uart->break_handler = handler;
983
984 /* Enable LIN break detection interrupt. */
985 this_uart->hw_reg->IEM |= ELINBI_MASK;
986 enable_irq(this_uart);
987 }
988 }
989
990 /***************************************************************************//**
991 * See mss_uart.h for details of how to use this function.
992 */
993 void
MSS_UART_set_linsync_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)994 MSS_UART_set_linsync_handler
995 (
996 mss_uart_instance_t * this_uart,
997 mss_uart_irq_handler_t handler
998 )
999 {
1000 ASSERT(handler != INVALID_IRQ_HANDLER);
1001
1002 if (handler != INVALID_IRQ_HANDLER)
1003 {
1004 this_uart->sync_handler = handler;
1005
1006 /* Enable LIN sync detection interrupt. */
1007 this_uart->hw_reg->IEM |= ELINSI_MASK;
1008 enable_irq(this_uart);
1009 }
1010 }
1011
1012 /***************************************************************************//**
1013 * See mss_uart.h for details of how to use this function.
1014 */
1015 void
MSS_UART_set_nack_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)1016 MSS_UART_set_nack_handler
1017 (
1018 mss_uart_instance_t * this_uart,
1019 mss_uart_irq_handler_t handler
1020 )
1021 {
1022 ASSERT(handler != INVALID_IRQ_HANDLER);
1023
1024 if (handler != INVALID_IRQ_HANDLER)
1025 {
1026 this_uart->nack_handler = handler;
1027
1028 /* Enable LIN sync detection interrupt. */
1029 this_uart->hw_reg->IEM |= ENACKI_MASK;
1030 enable_irq(this_uart);
1031 }
1032 }
1033
1034 /***************************************************************************//**
1035 * See mss_uart.h for details of how to use this function.
1036 */
1037 void
MSS_UART_set_rx_timeout_handler(mss_uart_instance_t * this_uart,mss_uart_irq_handler_t handler)1038 MSS_UART_set_rx_timeout_handler
1039 (
1040 mss_uart_instance_t * this_uart,
1041 mss_uart_irq_handler_t handler
1042 )
1043 {
1044 ASSERT(handler != INVALID_IRQ_HANDLER);
1045
1046 if (handler != INVALID_IRQ_HANDLER)
1047 {
1048 this_uart->rto_handler = handler;
1049
1050 /* Enable receiver timeout interrupt. */
1051 this_uart->hw_reg->IEM |= ERTOI_MASK;
1052 enable_irq(this_uart);
1053 }
1054 }
1055
1056 /***************************************************************************//**
1057 * See mss_uart.h for details of how to use this function.
1058 */
1059 void
MSS_UART_enable_half_duplex(mss_uart_instance_t * this_uart)1060 MSS_UART_enable_half_duplex
1061 (
1062 mss_uart_instance_t * this_uart
1063 )
1064 {
1065 /* enable single wire half-duplex mode */
1066 this_uart->hw_reg->MM2 |= ESWM_MASK;
1067 }
1068
1069 /***************************************************************************//**
1070 * See mss_uart.h for details of how to use this function.
1071 */
1072 void
MSS_UART_disable_half_duplex(mss_uart_instance_t * this_uart)1073 MSS_UART_disable_half_duplex
1074 (
1075 mss_uart_instance_t * this_uart
1076 )
1077 {
1078 /* enable single wire half-duplex mode */
1079 this_uart->hw_reg->MM2 &= ~ESWM_MASK;
1080 }
1081
1082 /***************************************************************************//**
1083 * See mss_uart.h for details of how to use this function.
1084 */
1085 void
MSS_UART_set_rx_endian(mss_uart_instance_t * this_uart,mss_uart_endian_t endian)1086 MSS_UART_set_rx_endian
1087 (
1088 mss_uart_instance_t * this_uart,
1089 mss_uart_endian_t endian
1090 )
1091 {
1092 ASSERT(MSS_UART_INVALID_ENDIAN > endian);
1093
1094 if (MSS_UART_INVALID_ENDIAN > endian)
1095 {
1096 /* Configure MSB first / LSB first for receiver */
1097 ((MSS_UART_LITTLEEND == endian) ? (this_uart->hw_reg->MM1 &= ~E_MSB_RX_MASK) :
1098 (this_uart->hw_reg->MM1 |= E_MSB_RX_MASK));
1099 }
1100 }
1101
1102 /***************************************************************************//**
1103 * See mss_uart.h for details of how to use this function.
1104 */
1105 void
MSS_UART_set_tx_endian(mss_uart_instance_t * this_uart,mss_uart_endian_t endian)1106 MSS_UART_set_tx_endian
1107 (
1108 mss_uart_instance_t * this_uart,
1109 mss_uart_endian_t endian
1110 )
1111 {
1112 ASSERT(MSS_UART_INVALID_ENDIAN > endian);
1113
1114 if (MSS_UART_INVALID_ENDIAN > endian)
1115 {
1116 /* Configure MSB first / LSB first for transmitter */
1117 ((MSS_UART_LITTLEEND == endian) ? (this_uart->hw_reg->MM1 &= ~E_MSB_TX_MASK) :
1118 (this_uart->hw_reg->MM1 |= E_MSB_TX_MASK));
1119 }
1120 }
1121
1122 /***************************************************************************//**
1123 * See mss_uart.h for details of how to use this function.
1124 */
1125 void
MSS_UART_set_filter_length(mss_uart_instance_t * this_uart,mss_uart_filter_length_t length)1126 MSS_UART_set_filter_length
1127 (
1128 mss_uart_instance_t * this_uart,
1129 mss_uart_filter_length_t length
1130 )
1131 {
1132 ASSERT(MSS_UART_INVALID_FILTER_LENGTH > length);
1133
1134 if (MSS_UART_INVALID_FILTER_LENGTH > length)
1135 {
1136 /* Configure glitch filter length */
1137 this_uart->hw_reg->GFR = (uint8_t)length;
1138 }
1139 }
1140
1141 /***************************************************************************//**
1142 * See mss_uart.h for details of how to use this function.
1143 */
1144 void
MSS_UART_enable_afm(mss_uart_instance_t * this_uart)1145 MSS_UART_enable_afm
1146 (
1147 mss_uart_instance_t * this_uart
1148 )
1149 {
1150 /* Disable RX FIFO till address flag with correct address is received */
1151 this_uart->hw_reg->MM2 |= EAFM_MASK;
1152 }
1153
1154 /***************************************************************************//**
1155 * See mss_uart.h for details of how to use this function.
1156 */
1157 void
MSS_UART_disable_afm(mss_uart_instance_t * this_uart)1158 MSS_UART_disable_afm
1159 (
1160 mss_uart_instance_t * this_uart
1161 )
1162 {
1163 /* Enable RX FIFO irrespective of address flag and
1164 correct address is received */
1165 this_uart->hw_reg->MM2 &= ~EAFM_MASK;
1166 }
1167
1168 /***************************************************************************//**
1169 * See mss_uart.h for details of how to use this function.
1170 */
1171 void
MSS_UART_enable_afclear(mss_uart_instance_t * this_uart)1172 MSS_UART_enable_afclear
1173 (
1174 mss_uart_instance_t * this_uart
1175 )
1176 {
1177 /* Enable address flag clearing */
1178 /* Disable RX FIFO till another address flag with
1179 correct address is received */
1180 this_uart->hw_reg->MM2 |= EAFC_MASK;
1181 }
1182
1183 /***************************************************************************//**
1184 * See mss_uart.h for details of how to use this function.
1185 */
1186 void
MSS_UART_disable_afclear(mss_uart_instance_t * this_uart)1187 MSS_UART_disable_afclear
1188 (
1189 mss_uart_instance_t * this_uart
1190 )
1191 {
1192 /* Disable address flag clearing */
1193 this_uart->hw_reg->MM2 &= ~EAFC_MASK;
1194 }
1195
1196 /***************************************************************************//**
1197 * See mss_uart.h for details of how to use this function.
1198 */
1199 void
MSS_UART_enable_rx_timeout(mss_uart_instance_t * this_uart,uint8_t timeout)1200 MSS_UART_enable_rx_timeout
1201 (
1202 mss_uart_instance_t * this_uart,
1203 uint8_t timeout
1204 )
1205 {
1206 /* Load the receive timeout value */
1207 this_uart->hw_reg->RTO = timeout;
1208
1209 /*Enable receiver time-out */
1210 this_uart->hw_reg->MM0 |= ERTO_MASK;
1211 }
1212
1213 /***************************************************************************//**
1214 * See mss_uart.h for details of how to use this function.
1215 */
1216 void
MSS_UART_disable_rx_timeout(mss_uart_instance_t * this_uart)1217 MSS_UART_disable_rx_timeout
1218 (
1219 mss_uart_instance_t * this_uart
1220 )
1221 {
1222 /* Disable receiver time-out */
1223 this_uart->hw_reg->MM0 &= ~ERTO_MASK;
1224 }
1225
1226 /***************************************************************************//**
1227 * See mss_uart.h for details of how to use this function.
1228 */
1229 void
MSS_UART_enable_tx_time_guard(mss_uart_instance_t * this_uart,uint8_t timeguard)1230 MSS_UART_enable_tx_time_guard
1231 (
1232 mss_uart_instance_t * this_uart,
1233 uint8_t timeguard
1234 )
1235 {
1236 /* Load the transmitter time guard value */
1237 this_uart->hw_reg->TTG = timeguard;
1238
1239 /* Enable transmitter time guard */
1240 this_uart->hw_reg->MM0 |= ETTG_MASK;
1241 }
1242
1243 /***************************************************************************//**
1244 * See mss_uart.h for details of how to use this function.
1245 */
1246 void
MSS_UART_disable_tx_time_guard(mss_uart_instance_t * this_uart)1247 MSS_UART_disable_tx_time_guard
1248 (
1249 mss_uart_instance_t * this_uart
1250 )
1251 {
1252 /* Disable transmitter time guard */
1253 this_uart->hw_reg->MM0 &= ~ETTG_MASK;
1254 }
1255
1256 /***************************************************************************//**
1257 * See mss_uart.h for details of how to use this function.
1258 */
1259 void
MSS_UART_set_address(mss_uart_instance_t * this_uart,uint8_t address)1260 MSS_UART_set_address
1261 (
1262 mss_uart_instance_t * this_uart,
1263 uint8_t address
1264 )
1265 {
1266 this_uart->hw_reg->ADR = address;
1267 }
1268
1269 /***************************************************************************//**
1270 * See mss_uart.h for details of how to use this function.
1271 */
1272 void
MSS_UART_set_ready_mode(mss_uart_instance_t * this_uart,mss_uart_ready_mode_t mode)1273 MSS_UART_set_ready_mode
1274 (
1275 mss_uart_instance_t * this_uart,
1276 mss_uart_ready_mode_t mode
1277 )
1278 {
1279 ASSERT(MSS_UART_INVALID_READY_MODE > mode);
1280
1281 if (MSS_UART_INVALID_READY_MODE > mode )
1282 {
1283 /* Configure mode 0 or mode 1 for TXRDY and RXRDY */
1284 ((MSS_UART_READY_MODE0 == mode) ? (this_uart->hw_reg->FCR &= ~RDYMODE_MASK) :
1285 (this_uart->hw_reg->FCR |= RDYMODE_MASK) );
1286 }
1287 }
1288
1289 /***************************************************************************//**
1290 * See mss_uart.h for details of how to use this function.
1291 */
1292 void
MSS_UART_set_usart_mode(mss_uart_instance_t * this_uart,mss_uart_usart_mode_t mode)1293 MSS_UART_set_usart_mode
1294 (
1295 mss_uart_instance_t * this_uart,
1296 mss_uart_usart_mode_t mode
1297 )
1298 {
1299 ASSERT(MSS_UART_INVALID_SYNC_MODE > mode);
1300
1301 if (MSS_UART_INVALID_SYNC_MODE > mode)
1302 {
1303 /* Nothing to do for the baudrate:
1304 operates at PCLK / 2 + glitch filter length */
1305 /* Clear the ESYN bits 2:0 */
1306 this_uart->hw_reg->MM0 &= ~SYNC_ASYNC_MODE_MASK;
1307 this_uart->hw_reg->MM0 |= (uint8_t)mode;
1308 }
1309 }
1310
1311 /***************************************************************************//**
1312 * See mss_uart.h for details of how to use this function.
1313 */
1314 void
MSS_UART_enable_local_irq(mss_uart_instance_t * this_uart)1315 MSS_UART_enable_local_irq
1316 (
1317 mss_uart_instance_t * this_uart
1318 )
1319 {
1320 /* Make sure to disable interrupt on PLIC as it might have been enabled
1321 * when application registered an interrupt handler function or
1322 * used MSS_UART_enable_irq() to enable PLIC interrupt */
1323 disable_irq(this_uart);
1324
1325 this_uart->local_irq_enabled = 1u;
1326
1327 /* Enable local interrupt UART instance.
1328 * Local interrupt will be enabled on the HART on which the application
1329 * calling this API is being executed*/
1330 __enable_local_irq((int8_t)MMUART0_E51_INT);
1331 }
1332
1333 /*******************************************************************************
1334 * Local Functions
1335 ******************************************************************************/
1336 /*******************************************************************************
1337 * Global initialization for all modes
1338 */
global_init(mss_uart_instance_t * this_uart,uint32_t baud_rate,uint8_t line_config)1339 static void global_init
1340 (
1341 mss_uart_instance_t * this_uart,
1342 uint32_t baud_rate,
1343 uint8_t line_config
1344 )
1345 {
1346 if ((&g_mss_uart0_lo == this_uart))
1347 {
1348 this_uart->hw_reg = MSS_UART0_LO_BASE;
1349 g_uart_axi_pos &= ~0x01u;
1350 }
1351
1352 else if (&g_mss_uart1_lo == this_uart)
1353 {
1354
1355 this_uart->hw_reg = MSS_UART1_LO_BASE;
1356 g_uart_axi_pos &= ~0x02u;
1357 }
1358
1359 else if (&g_mss_uart2_lo == this_uart)
1360 {
1361 this_uart->hw_reg = MSS_UART2_LO_BASE;
1362 g_uart_axi_pos &= ~0x04u;
1363 }
1364
1365 else if (&g_mss_uart3_lo == this_uart)
1366 {
1367 this_uart->hw_reg = MSS_UART3_LO_BASE;
1368 g_uart_axi_pos &= ~0x08u;
1369 }
1370
1371 else if (&g_mss_uart4_lo == this_uart)
1372 {
1373 this_uart->hw_reg = MSS_UART4_LO_BASE;
1374 g_uart_axi_pos &= ~0x10u;
1375 }
1376
1377 else if ((&g_mss_uart0_hi == this_uart))
1378 {
1379 this_uart->hw_reg = MSS_UART0_HI_BASE;
1380 g_uart_axi_pos |= 0x01u;
1381 }
1382
1383 else if (&g_mss_uart1_hi == this_uart)
1384 {
1385 this_uart->hw_reg = MSS_UART1_HI_BASE;
1386 g_uart_axi_pos |= 0x02u;
1387 }
1388
1389 else if (&g_mss_uart2_hi == this_uart)
1390 {
1391 this_uart->hw_reg = MSS_UART2_HI_BASE;
1392 g_uart_axi_pos |= 0x04u;
1393 }
1394
1395 else if (&g_mss_uart3_hi == this_uart)
1396 {
1397 this_uart->hw_reg = MSS_UART3_HI_BASE;
1398 g_uart_axi_pos |= 0x08u;
1399 }
1400
1401 else if (&g_mss_uart4_hi == this_uart)
1402 {
1403 this_uart->hw_reg = MSS_UART4_HI_BASE;
1404 g_uart_axi_pos |= 0x10u;
1405 }
1406 else
1407 {
1408 ASSERT(0); /* Comment to avoid LDRA warning */
1409 }
1410
1411 /* disable interrupts */
1412 this_uart->hw_reg->IER = 0u;
1413
1414 /* FIFO configuration */
1415 this_uart->hw_reg->FCR = 0u;
1416
1417 /* clear receiver FIFO */
1418 this_uart->hw_reg->FCR |= CLEAR_RX_FIFO_MASK;
1419
1420 /* clear transmitter FIFO */
1421 this_uart->hw_reg->FCR |= CLEAR_TX_FIFO_MASK;
1422
1423 /* set default READY mode : Mode 0*/
1424 /* enable RXRDYN and TXRDYN pins. The earlier FCR write to set the TX FIFO
1425 * trigger level inadvertently disabled the FCR_RXRDY_TXRDYN_EN bit. */
1426 this_uart->hw_reg->FCR |= RXRDY_TXRDYN_EN_MASK;
1427
1428 /* disable loopback : local * remote */
1429 this_uart->hw_reg->MCR &= ~LOOP_MASK;
1430
1431 this_uart->hw_reg->MCR &= ~RLOOP_MASK;
1432
1433 /* set default TX endian */
1434 this_uart->hw_reg->MM1 &= ~E_MSB_TX_MASK;
1435
1436 /* set default RX endian */
1437 this_uart->hw_reg->MM1 &= ~E_MSB_RX_MASK;
1438
1439 /* default AFM : disabled */
1440 this_uart->hw_reg->MM2 &= ~EAFM_MASK;
1441
1442 /* disable TX time guard */
1443 this_uart->hw_reg->MM0 &= ~ETTG_MASK;
1444
1445 /* set default RX timeout */
1446 this_uart->hw_reg->MM0 &= ~ERTO_MASK;
1447
1448 /* disable fractional baud-rate */
1449 this_uart->hw_reg->MM0 &= ~EFBR_MASK;
1450
1451 /* disable single wire mode */
1452 this_uart->hw_reg->MM2 &= ~ESWM_MASK;
1453
1454 /* set filter to minimum value */
1455 this_uart->hw_reg->GFR = 0u;
1456
1457 /* set default TX time guard */
1458 this_uart->hw_reg->TTG = 0u;
1459
1460 /* set default RX timeout */
1461 this_uart->hw_reg->RTO = 0u;
1462
1463 /*
1464 * Configure baud rate divisors. This uses the fractional baud rate divisor
1465 * where possible to provide the most accurate baud rat possible.
1466 */
1467 config_baud_divisors(this_uart, baud_rate);
1468
1469 /* set the line control register (bit length, stop bits, parity) */
1470 this_uart->hw_reg->LCR = line_config;
1471
1472 /* Instance setup */
1473 this_uart->baudrate = baud_rate;
1474 this_uart->lineconfig = line_config;
1475 this_uart->tx_buff_size = TX_COMPLETE;
1476 this_uart->tx_buffer = (const uint8_t*)0;
1477 this_uart->tx_idx = 0u;
1478
1479 /* Default handlers for MSS UART interrupts */
1480 this_uart->rx_handler = NULL_HANDLER;
1481 this_uart->tx_handler = NULL_HANDLER;
1482 this_uart->linests_handler = NULL_HANDLER;
1483 this_uart->modemsts_handler = NULL_HANDLER;
1484 this_uart->rto_handler = NULL_HANDLER;
1485 this_uart->nack_handler = NULL_HANDLER;
1486 this_uart->pid_pei_handler = NULL_HANDLER;
1487 this_uart->break_handler = NULL_HANDLER;
1488 this_uart->sync_handler = NULL_HANDLER;
1489
1490 this_uart->local_irq_enabled = 0u;
1491
1492 /* Initialize the sticky status */
1493 this_uart->status = 0u;
1494 }
1495
1496 /***************************************************************************//**
1497 * Configure baud divisors using fractional baud rate if possible.
1498 */
1499 static void
config_baud_divisors(mss_uart_instance_t * this_uart,uint32_t baudrate)1500 config_baud_divisors
1501 (
1502 mss_uart_instance_t * this_uart,
1503 uint32_t baudrate
1504 )
1505 {
1506 uint32_t baud_value;
1507 uint32_t baud_value_by_64;
1508 uint32_t baud_value_by_128;
1509 uint32_t fractional_baud_value;
1510 uint64_t pclk_freq;
1511
1512 this_uart->baudrate = baudrate;
1513
1514 pclk_freq = LIBERO_SETTING_MSS_APB_AHB_CLK;
1515
1516 /*
1517 * Compute baud value based on requested baud rate and PCLK frequency.
1518 * The baud value is computed using the following equation:
1519 * baud_value = PCLK_Frequency / (baud_rate * 16)
1520 */
1521 baud_value_by_128 = (uint32_t)((8UL * pclk_freq) / baudrate);
1522 baud_value_by_64 = baud_value_by_128 / 2u;
1523 baud_value = baud_value_by_64 / 64u;
1524 fractional_baud_value = baud_value_by_64 - (baud_value * 64u);
1525 fractional_baud_value += (baud_value_by_128 - (baud_value * 128u))
1526 - (fractional_baud_value * 2u);
1527
1528 /* Assert if integer baud value fits in 16-bit. */
1529 ASSERT(baud_value <= UINT16_MAX);
1530
1531 if (baud_value <= (uint32_t)UINT16_MAX)
1532 {
1533 if (baud_value > 1u)
1534 {
1535 /* Use Fractional baud rate divisors */
1536 /* set divisor latch */
1537 this_uart->hw_reg->LCR |= DLAB_MASK;
1538
1539 /* MSB of baud value */
1540 this_uart->hw_reg->DMR = (uint8_t)(baud_value >> 8);
1541
1542 /* LSB of baud value */
1543 this_uart->hw_reg->DLR = (uint8_t)baud_value;
1544
1545 /* reset divisor latch */
1546 this_uart->hw_reg->LCR &= ~DLAB_MASK;
1547
1548 /* Enable Fractional baud rate */
1549 this_uart->hw_reg->MM0 |= EFBR_MASK;
1550
1551 /* Load the fractional baud rate register */
1552 ASSERT(fractional_baud_value <= (uint32_t)UINT8_MAX);
1553 this_uart->hw_reg->DFR = (uint8_t)fractional_baud_value;
1554 }
1555 else
1556 {
1557 /* Do NOT use Fractional baud rate divisors. */
1558 /* set divisor latch */
1559 this_uart->hw_reg->LCR |= DLAB_MASK;
1560
1561 /* MSB of baud value */
1562 this_uart->hw_reg->DMR = (uint8_t)(baud_value >> 8u);
1563
1564 /* LSB of baud value */
1565 this_uart->hw_reg->DLR = (uint8_t)baud_value;
1566
1567 /* reset divisor latch */
1568 this_uart->hw_reg->LCR &= ~DLAB_MASK;
1569
1570 /* Disable Fractional baud rate */
1571 this_uart->hw_reg->MM0 &= ~EFBR_MASK;
1572 }
1573 }
1574 }
1575
1576 /***************************************************************************//**
1577 * Interrupt service routine triggered by any MSS UART interrupt. This routine
1578 * will call the handler function appropriate to the interrupt from the
1579 * handlers previously registered with the driver through calls to the
1580 * MSS_UART_set_*_handler() functions, or it will call the default_tx_handler()
1581 * function in response to transmit interrupts if MSS_UART_irq_tx() is used to
1582 * transmit data.
1583 */
1584 static void
uart_isr(mss_uart_instance_t * this_uart)1585 uart_isr
1586 (
1587 mss_uart_instance_t * this_uart
1588 )
1589 {
1590 uint8_t iirf;
1591
1592 iirf = this_uart->hw_reg->IIR & IIRF_MASK;
1593
1594 switch (iirf)
1595 {
1596 case IIRF_MODEM_STATUS: /* Modem status interrupt */
1597 {
1598 ASSERT(NULL_HANDLER != this_uart->modemsts_handler);
1599 if (NULL_HANDLER != this_uart->modemsts_handler)
1600 {
1601 (*(this_uart->modemsts_handler))(this_uart);
1602 }
1603 }
1604 break;
1605
1606 case IIRF_THRE: /* Transmitter Holding Register Empty */
1607 {
1608 ASSERT(NULL_HANDLER != this_uart->tx_handler);
1609 if (NULL_HANDLER != this_uart->tx_handler)
1610 {
1611 (*(this_uart->tx_handler))(this_uart);
1612 }
1613 }
1614 break;
1615
1616 case IIRF_RX_DATA: /* Received Data Available */
1617 case IIRF_DATA_TIMEOUT: /* Received Data Timed-out */
1618 {
1619 ASSERT(NULL_HANDLER != this_uart->rx_handler);
1620 if (NULL_HANDLER != this_uart->rx_handler)
1621 {
1622 (*(this_uart->rx_handler))(this_uart);
1623 }
1624 }
1625 break;
1626
1627 case IIRF_RX_LINE_STATUS: /* Line Status Interrupt */
1628 {
1629 ASSERT(NULL_HANDLER != this_uart->linests_handler);
1630 if (NULL_HANDLER != this_uart->linests_handler)
1631 {
1632 (*(this_uart->linests_handler))(this_uart);
1633 }
1634 }
1635 break;
1636
1637 case IIRF_MMI:
1638 {
1639 /* Identify multi-mode interrupts and handle */
1640
1641 /* Receiver time-out interrupt */
1642 if (this_uart->hw_reg->IIM & ERTOI_MASK)
1643 {
1644 ASSERT(NULL_HANDLER != this_uart->rto_handler);
1645
1646 if (NULL_HANDLER != this_uart->rto_handler)
1647 {
1648 (*(this_uart->rto_handler))(this_uart);
1649 }
1650 }
1651
1652 /* NACK interrupt */
1653 if (this_uart->hw_reg->IIM &ENACKI)
1654 {
1655 ASSERT(NULL_HANDLER != this_uart->nack_handler);
1656
1657 if (NULL_HANDLER != this_uart->nack_handler)
1658 {
1659 (*(this_uart->nack_handler))(this_uart);
1660 }
1661 }
1662
1663 /* PID parity error interrupt */
1664 if (this_uart->hw_reg->IIM & EPID_PEI)
1665 {
1666 ASSERT(NULL_HANDLER != this_uart->pid_pei_handler);
1667
1668 if (NULL_HANDLER != this_uart->pid_pei_handler)
1669 {
1670 (*(this_uart->pid_pei_handler))(this_uart);
1671 }
1672 }
1673
1674 /* LIN break detection interrupt */
1675 if (this_uart->hw_reg->IIM & ELINBI)
1676 {
1677 ASSERT(NULL_HANDLER != this_uart->break_handler);
1678
1679 if (NULL_HANDLER != this_uart->break_handler)
1680 {
1681 (*(this_uart->break_handler))(this_uart);
1682 }
1683 }
1684
1685 /* LIN Sync detection interrupt */
1686 if (this_uart->hw_reg->IIM & ELINSI)
1687 {
1688 ASSERT(NULL_HANDLER != this_uart->sync_handler);
1689
1690 if (NULL_HANDLER != this_uart->sync_handler)
1691 {
1692 (*(this_uart->sync_handler))(this_uart);
1693 }
1694 }
1695 break;
1696 }
1697 default:
1698 {
1699 ASSERT(INVALID_INTERRUPT); /* Comment to avoid LDRA warning */
1700 }
1701 break;
1702 }
1703 }
1704
1705 /***************************************************************************//**
1706 * See mss_uart.h for details of how to use this function.
1707 */
1708 static void
default_tx_handler(mss_uart_instance_t * this_uart)1709 default_tx_handler
1710 (
1711 mss_uart_instance_t * this_uart
1712 )
1713 {
1714 uint8_t status;
1715
1716 ASSERT(( (uint8_t*)0 ) != this_uart->tx_buffer);
1717 ASSERT(0u < this_uart->tx_buff_size);
1718
1719 if ((((uint8_t*)0 ) != this_uart->tx_buffer) &&
1720 (0u < this_uart->tx_buff_size))
1721 {
1722 /* Read the Line Status Register and update the sticky record. */
1723 status = this_uart->hw_reg->LSR;
1724 this_uart->status |= status;
1725
1726 /*
1727 * This function should only be called as a result of a THRE interrupt.
1728 * Verify that this is true before proceeding to transmit data.
1729 */
1730 if (status & MSS_UART_THRE)
1731 {
1732 uint32_t cnt;
1733 uint32_t fill_size = TX_FIFO_SIZE;
1734 uint32_t tx_remain = this_uart->tx_buff_size - this_uart->tx_idx;
1735
1736 /* Calculate the number of bytes to transmit. */
1737 if (tx_remain < TX_FIFO_SIZE)
1738 {
1739 fill_size = tx_remain;
1740 }
1741
1742 /* Fill the TX FIFO with the calculated the number of bytes. */
1743 for (cnt = 0u; cnt < fill_size; ++cnt)
1744 {
1745 /* Send next character in the buffer. */
1746 this_uart->hw_reg->THR = this_uart->tx_buffer[this_uart->tx_idx];
1747 ++this_uart->tx_idx;
1748 }
1749 }
1750
1751 /* Flag Tx as complete if all data has been pushed into the Tx FIFO. */
1752 if (this_uart->tx_idx == this_uart->tx_buff_size)
1753 {
1754 this_uart->tx_buff_size = TX_COMPLETE;
1755
1756 /* disables TX interrupt */
1757 this_uart->hw_reg->IER &= ~ETBEI_MASK;
1758 }
1759 }
1760 }
1761
1762 static void
enable_irq(const mss_uart_instance_t * this_uart)1763 enable_irq
1764 (
1765 const mss_uart_instance_t * this_uart
1766 )
1767 {
1768 PLIC_IRQn_Type plic_num = 0;
1769
1770 if(0u == this_uart->local_irq_enabled)
1771 {
1772 if (((&g_mss_uart0_lo == this_uart)) || ((&g_mss_uart0_hi == this_uart)))
1773 {
1774 plic_num = MMUART0_PLIC_77;
1775 }
1776 else if (((&g_mss_uart1_lo == this_uart)) || ((&g_mss_uart1_hi == this_uart)))
1777 {
1778 plic_num = MMUART1_PLIC;
1779 }
1780 else if (((&g_mss_uart2_lo == this_uart)) || ((&g_mss_uart2_hi == this_uart)))
1781 {
1782 plic_num = MMUART2_PLIC;
1783 }
1784 else if (((&g_mss_uart3_lo == this_uart)) || ((&g_mss_uart3_hi == this_uart)))
1785 {
1786 plic_num = MMUART3_PLIC;
1787 }
1788 else if (((&g_mss_uart4_lo == this_uart)) || ((&g_mss_uart4_hi == this_uart)))
1789 {
1790 plic_num = MMUART4_PLIC;
1791 }
1792 else
1793 {
1794 ASSERT(0); /* Comment to avoid LDRA warning */
1795 }
1796
1797 /* Enable UART instance interrupt in PLIC. */
1798 PLIC_EnableIRQ(plic_num);
1799 }
1800 }
1801
1802 static void
disable_irq(const mss_uart_instance_t * this_uart)1803 disable_irq
1804 (
1805 const mss_uart_instance_t * this_uart
1806 )
1807 {
1808 PLIC_IRQn_Type plic_num = 0;
1809
1810 if (((&g_mss_uart0_lo == this_uart)) || ((&g_mss_uart0_hi == this_uart)))
1811 {
1812 plic_num = MMUART0_PLIC_77;
1813 }
1814 else if (((&g_mss_uart1_lo == this_uart)) || ((&g_mss_uart1_hi == this_uart)))
1815 {
1816 plic_num = MMUART1_PLIC;
1817 }
1818 else if (((&g_mss_uart2_lo == this_uart)) || ((&g_mss_uart2_hi == this_uart)))
1819 {
1820 plic_num = MMUART2_PLIC;
1821 }
1822 else if (((&g_mss_uart3_lo == this_uart)) || ((&g_mss_uart3_hi == this_uart)))
1823 {
1824 plic_num = MMUART3_PLIC;
1825 }
1826 else if (((&g_mss_uart4_lo == this_uart)) || ((&g_mss_uart4_hi == this_uart)))
1827 {
1828 plic_num = MMUART4_PLIC;
1829 }
1830 else
1831 {
1832 ASSERT(0); /* Comment to avoid LDRA warning */
1833 }
1834
1835 /* Disable UART instance interrupt in PLIC. */
1836 PLIC_DisableIRQ(plic_num);
1837 }
1838
1839 #ifdef __cplusplus
1840 }
1841 #endif
1842