@@ -158,6 +158,8 @@ struct uart_xlnx_ps_dev_data_t {
158158 uint32_t flowctrl ;
159159
160160#ifdef CONFIG_UART_INTERRUPT_DRIVEN
161+ const struct device * dev ;
162+ struct k_timer timer ;
161163 uart_irq_callback_user_data_t user_cb ;
162164 void * user_data ;
163165#endif
@@ -270,6 +272,25 @@ static void set_baudrate(const struct device *dev, uint32_t baud_rate)
270272 }
271273}
272274
275+ #ifdef CONFIG_UART_INTERRUPT_DRIVEN
276+
277+ /**
278+ * @brief Trigger a UART callback based on a timer.
279+ *
280+ * @param timer Timer that triggered the callback
281+ */
282+ static void uart_xlnx_ps_soft_isr (struct k_timer * timer )
283+ {
284+ struct uart_xlnx_ps_dev_data_t * data =
285+ CONTAINER_OF (timer , struct uart_xlnx_ps_dev_data_t , timer );
286+
287+ if (data -> user_cb ) {
288+ data -> user_cb (data -> dev , data -> user_data );
289+ }
290+ }
291+
292+ #endif
293+
273294/**
274295 * @brief Initialize individual UART port
275296 *
@@ -290,16 +311,18 @@ static int uart_xlnx_ps_init(const struct device *dev)
290311 DEVICE_MMIO_MAP (dev , K_MEM_CACHE_NONE );
291312 uintptr_t reg_base = DEVICE_MMIO_GET (dev );
292313
293- /* Disable RX/TX before changing any configuration data */
294- xlnx_ps_disable_uart (reg_base );
295-
296314#ifdef CONFIG_PINCTRL
297315 err = pinctrl_apply_state (dev_cfg -> pincfg , PINCTRL_STATE_DEFAULT );
298316 if (err < 0 ) {
299317 return err ;
300318 }
301319#endif
302320
321+ /* Set RX/TX reset and disable RX/TX */
322+ sys_write32 (XUARTPS_CR_STOPBRK | XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS | XUARTPS_CR_TXRST |
323+ XUARTPS_CR_RXRST ,
324+ reg_base + XUARTPS_CR_OFFSET );
325+
303326 /* Set initial character length / start/stop bit / parity configuration */
304327 reg_val = sys_read32 (reg_base + XUARTPS_MR_OFFSET );
305328 reg_val &= (~(XUARTPS_MR_CHARLEN_MASK | XUARTPS_MR_STOPMODE_MASK | XUARTPS_MR_PARITY_MASK ));
@@ -316,10 +339,14 @@ static int uart_xlnx_ps_init(const struct device *dev)
316339 set_baudrate (dev , dev_cfg -> baud_rate );
317340
318341#ifdef CONFIG_UART_INTERRUPT_DRIVEN
342+ struct uart_xlnx_ps_dev_data_t * dev_data = dev -> data ;
319343
320344 /* Clear any pending interrupt flags */
321345 sys_write32 (XUARTPS_IXR_MASK , reg_base + XUARTPS_ISR_OFFSET );
322346
347+ dev_data -> dev = dev ;
348+ k_timer_init (& dev_data -> timer , & uart_xlnx_ps_soft_isr , NULL );
349+
323350 /* Attach to & unmask the corresponding interrupt vector */
324351 dev_cfg -> irq_config_func (dev );
325352
@@ -354,7 +381,7 @@ static int uart_xlnx_ps_poll_in(const struct device *dev, unsigned char *c)
354381/**
355382 * @brief Output a character in polled mode.
356383 *
357- * Checks if the transmitter is empty . If empty , a character is written to
384+ * Checks if the transmitter has available TX FIFO space . If so , a character is written to
358385 * the data register.
359386 *
360387 * If the hardware flow control is enabled then the handshake signal CTS has to
@@ -368,18 +395,54 @@ static int uart_xlnx_ps_poll_in(const struct device *dev, unsigned char *c)
368395static void uart_xlnx_ps_poll_out (const struct device * dev , unsigned char c )
369396{
370397 uintptr_t reg_base = DEVICE_MMIO_GET (dev );
371- uint32_t reg_val ;
372398
373- /* wait for transmitter to ready to accept a character */
374- do {
375- reg_val = sys_read32 (reg_base + XUARTPS_SR_OFFSET );
376- } while ((reg_val & XUARTPS_SR_TXEMPTY ) == 0 );
399+ /* wait for transmitter to be ready to accept a character */
400+ while ((sys_read32 (reg_base + XUARTPS_SR_OFFSET ) & XUARTPS_SR_TXFULL ) != 0 ) {
401+ }
377402
378403 sys_write32 ((uint32_t )(c & 0xFF ), reg_base + XUARTPS_FIFO_OFFSET );
404+ }
405+
406+ /**
407+ * Check for pending TX/TX errors on the port.
408+ *
409+ * @param dev UART device struct
410+ * @return 0 if no errors, UART_ERROR_* flags otherwise
411+ */
412+ static int uart_xlnx_ps_err_check (const struct device * dev )
413+ {
414+ uintptr_t reg_base = DEVICE_MMIO_GET (dev );
415+ uint32_t reg_val = sys_read32 (reg_base + XUARTPS_ISR_OFFSET );
416+ int err = 0 ;
417+
418+ if (reg_val & XUARTPS_IXR_RBRK ) {
419+ err |= UART_BREAK ;
420+ }
379421
380- do {
381- reg_val = sys_read32 (reg_base + XUARTPS_SR_OFFSET );
382- } while ((reg_val & XUARTPS_SR_TXEMPTY ) == 0 );
422+ if (reg_val & XUARTPS_IXR_TOVR ) {
423+ err |= UART_ERROR_OVERRUN ;
424+ }
425+
426+ if (reg_val & XUARTPS_IXR_TOUT ) {
427+ err |= UART_ERROR_NOISE ;
428+ }
429+
430+ if (reg_val & XUARTPS_IXR_PARITY ) {
431+ err |= UART_ERROR_PARITY ;
432+ }
433+
434+ if (reg_val & XUARTPS_IXR_FRAMING ) {
435+ err |= UART_ERROR_FRAMING ;
436+ }
437+
438+ if (reg_val & XUARTPS_IXR_RXOVR ) {
439+ err |= UART_ERROR_OVERRUN ;
440+ }
441+ sys_write32 (reg_val & (XUARTPS_IXR_RBRK | XUARTPS_IXR_TOVR | XUARTPS_IXR_TOUT |
442+ XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING | XUARTPS_IXR_RXOVR ),
443+ reg_base + XUARTPS_ISR_OFFSET );
444+
445+ return err ;
383446}
384447
385448/**
@@ -826,17 +889,14 @@ static int uart_xlnx_ps_config_get(const struct device *dev, struct uart_config
826889static int uart_xlnx_ps_fifo_fill (const struct device * dev , const uint8_t * tx_data , int size )
827890{
828891 uintptr_t reg_base = DEVICE_MMIO_GET (dev );
829- uint32_t data_iter = 0 ;
892+ int count = 0 ;
830893
831- sys_write32 (XUARTPS_IXR_TXEMPTY , reg_base + XUARTPS_IDR_OFFSET );
832- while (size -- ) {
833- while ((sys_read32 (reg_base + XUARTPS_SR_OFFSET ) & XUARTPS_SR_TXFULL ) != 0 ) {
834- }
835- sys_write32 ((uint32_t )tx_data [data_iter ++ ], reg_base + XUARTPS_FIFO_OFFSET );
894+ while (count < size &&
895+ (sys_read32 (reg_base + XUARTPS_SR_OFFSET ) & XUARTPS_SR_TXFULL ) == 0 ) {
896+ sys_write32 ((uint32_t )tx_data [count ++ ], reg_base + XUARTPS_FIFO_OFFSET );
836897 }
837- sys_write32 (XUARTPS_IXR_TXEMPTY , reg_base + XUARTPS_IER_OFFSET );
838898
839- return data_iter ;
899+ return count ;
840900}
841901
842902/**
@@ -851,16 +911,14 @@ static int uart_xlnx_ps_fifo_fill(const struct device *dev, const uint8_t *tx_da
851911static int uart_xlnx_ps_fifo_read (const struct device * dev , uint8_t * rx_data , const int size )
852912{
853913 uintptr_t reg_base = DEVICE_MMIO_GET (dev );
854- uint32_t reg_val = sys_read32 (reg_base + XUARTPS_SR_OFFSET );
855- int inum = 0 ;
914+ int count = 0 ;
856915
857- while (inum < size && (reg_val & XUARTPS_SR_RXEMPTY ) == 0 ) {
858- rx_data [inum ] = (uint8_t )sys_read32 (reg_base + XUARTPS_FIFO_OFFSET );
859- inum ++ ;
860- reg_val = sys_read32 (reg_base + XUARTPS_SR_OFFSET );
916+ while (count < size &&
917+ (sys_read32 (reg_base + XUARTPS_SR_OFFSET ) & XUARTPS_SR_RXEMPTY ) == 0 ) {
918+ rx_data [count ++ ] = (uint8_t )sys_read32 (reg_base + XUARTPS_FIFO_OFFSET );
861919 }
862920
863- return inum ;
921+ return count ;
864922}
865923
866924/**
@@ -870,9 +928,20 @@ static int uart_xlnx_ps_fifo_read(const struct device *dev, uint8_t *rx_data, co
870928 */
871929static void uart_xlnx_ps_irq_tx_enable (const struct device * dev )
872930{
931+ struct uart_xlnx_ps_dev_data_t * dev_data = dev -> data ;
873932 uintptr_t reg_base = DEVICE_MMIO_GET (dev );
874933
875934 sys_write32 ((XUARTPS_IXR_TTRIG | XUARTPS_IXR_TXEMPTY ), reg_base + XUARTPS_IER_OFFSET );
935+ if ((sys_read32 (reg_base + XUARTPS_SR_OFFSET ) & (XUARTPS_SR_TTRIG | XUARTPS_SR_TXEMPTY )) !=
936+ 0 ) {
937+ /*
938+ * Enabling TX empty interrupts does not cause an interrupt
939+ * if the FIFO is already empty.
940+ * Generate a soft interrupt and have it call the
941+ * callback function in timer isr context.
942+ */
943+ k_timer_start (& dev_data -> timer , K_NO_WAIT , K_NO_WAIT );
944+ }
876945}
877946
878947/**
@@ -918,11 +987,7 @@ static int uart_xlnx_ps_irq_tx_complete(const struct device *dev)
918987 uintptr_t reg_base = DEVICE_MMIO_GET (dev );
919988 uint32_t reg_val = sys_read32 (reg_base + XUARTPS_SR_OFFSET );
920989
921- if ((reg_val & XUARTPS_SR_TXEMPTY ) == 0 ) {
922- return 0 ;
923- } else {
924- return 1 ;
925- }
990+ return (reg_val & XUARTPS_SR_TXEMPTY ) != 0 ;
926991}
927992
928993/**
@@ -932,9 +997,19 @@ static int uart_xlnx_ps_irq_tx_complete(const struct device *dev)
932997 */
933998static void uart_xlnx_ps_irq_rx_enable (const struct device * dev )
934999{
1000+ struct uart_xlnx_ps_dev_data_t * dev_data = dev -> data ;
9351001 uintptr_t reg_base = DEVICE_MMIO_GET (dev );
9361002
9371003 sys_write32 (XUARTPS_IXR_RTRIG , reg_base + XUARTPS_IER_OFFSET );
1004+ if ((sys_read32 (reg_base + XUARTPS_SR_OFFSET ) & XUARTPS_SR_RXEMPTY ) == 0 ) {
1005+ /*
1006+ * Enabling RX trigger interrupts does not cause an interrupt
1007+ * if the FIFO already contains RX data.
1008+ * Generate a soft interrupt and have it call the
1009+ * callback function in timer isr context.
1010+ */
1011+ k_timer_start (& dev_data -> timer , K_NO_WAIT , K_NO_WAIT );
1012+ }
9381013}
9391014
9401015/**
@@ -959,14 +1034,9 @@ static void uart_xlnx_ps_irq_rx_disable(const struct device *dev)
9591034static int uart_xlnx_ps_irq_rx_ready (const struct device * dev )
9601035{
9611036 uintptr_t reg_base = DEVICE_MMIO_GET (dev );
962- uint32_t reg_val = sys_read32 (reg_base + XUARTPS_ISR_OFFSET );
1037+ uint32_t reg_val = sys_read32 (reg_base + XUARTPS_SR_OFFSET );
9631038
964- if ((reg_val & XUARTPS_IXR_RTRIG ) == 0 ) {
965- return 0 ;
966- } else {
967- sys_write32 (XUARTPS_IXR_RTRIG , reg_base + XUARTPS_ISR_OFFSET );
968- return 1 ;
969- }
1039+ return (reg_val & XUARTPS_SR_RXEMPTY ) == 0 ;
9701040}
9711041
9721042/**
@@ -978,7 +1048,8 @@ static void uart_xlnx_ps_irq_err_enable(const struct device *dev)
9781048{
9791049 uintptr_t reg_base = DEVICE_MMIO_GET (dev );
9801050
981- sys_write32 (XUARTPS_IXR_TOVR /* [12] Transmitter FIFO Overflow */
1051+ sys_write32 (XUARTPS_IXR_RBRK /* [13] Receiver Break */
1052+ | XUARTPS_IXR_TOVR /* [12] Transmitter FIFO Overflow */
9821053 | XUARTPS_IXR_TOUT /* [8] Receiver Timerout */
9831054 | XUARTPS_IXR_PARITY /* [7] Parity Error */
9841055 | XUARTPS_IXR_FRAMING /* [6] Receiver Framing Error */
@@ -997,7 +1068,8 @@ static void uart_xlnx_ps_irq_err_disable(const struct device *dev)
9971068{
9981069 uintptr_t reg_base = DEVICE_MMIO_GET (dev );
9991070
1000- sys_write32 (XUARTPS_IXR_TOVR /* [12] Transmitter FIFO Overflow */
1071+ sys_write32 (XUARTPS_IXR_RBRK /* [13] Receiver Break */
1072+ | XUARTPS_IXR_TOVR /* [12] Transmitter FIFO Overflow */
10011073 | XUARTPS_IXR_TOUT /* [8] Receiver Timerout */
10021074 | XUARTPS_IXR_PARITY /* [7] Parity Error */
10031075 | XUARTPS_IXR_FRAMING /* [6] Receiver Framing Error */
@@ -1034,7 +1106,11 @@ static int uart_xlnx_ps_irq_is_pending(const struct device *dev)
10341106 */
10351107static int uart_xlnx_ps_irq_update (const struct device * dev )
10361108{
1037- ARG_UNUSED (dev );
1109+ uintptr_t reg_base = DEVICE_MMIO_GET (dev );
1110+
1111+ /* Clear RX/TX interrupts */
1112+ sys_write32 (XUARTPS_IXR_TTRIG | XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RTRIG ,
1113+ reg_base + XUARTPS_ISR_OFFSET );
10381114 return 1 ;
10391115}
10401116
@@ -1073,6 +1149,7 @@ static void uart_xlnx_ps_isr(const struct device *dev)
10731149static DEVICE_API (uart , uart_xlnx_ps_driver_api ) = {
10741150 .poll_in = uart_xlnx_ps_poll_in ,
10751151 .poll_out = uart_xlnx_ps_poll_out ,
1152+ .err_check = uart_xlnx_ps_err_check ,
10761153#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
10771154 .configure = uart_xlnx_ps_configure ,
10781155 .config_get = uart_xlnx_ps_config_get ,
0 commit comments