@@ -158,6 +158,8 @@ struct uart_xlnx_ps_dev_data_t {
158
158
uint32_t flowctrl ;
159
159
160
160
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
161
+ const struct device * dev ;
162
+ struct k_timer timer ;
161
163
uart_irq_callback_user_data_t user_cb ;
162
164
void * user_data ;
163
165
#endif
@@ -270,6 +272,25 @@ static void set_baudrate(const struct device *dev, uint32_t baud_rate)
270
272
}
271
273
}
272
274
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
+
273
294
/**
274
295
* @brief Initialize individual UART port
275
296
*
@@ -290,16 +311,18 @@ static int uart_xlnx_ps_init(const struct device *dev)
290
311
DEVICE_MMIO_MAP (dev , K_MEM_CACHE_NONE );
291
312
uintptr_t reg_base = DEVICE_MMIO_GET (dev );
292
313
293
- /* Disable RX/TX before changing any configuration data */
294
- xlnx_ps_disable_uart (reg_base );
295
-
296
314
#ifdef CONFIG_PINCTRL
297
315
err = pinctrl_apply_state (dev_cfg -> pincfg , PINCTRL_STATE_DEFAULT );
298
316
if (err < 0 ) {
299
317
return err ;
300
318
}
301
319
#endif
302
320
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
+
303
326
/* Set initial character length / start/stop bit / parity configuration */
304
327
reg_val = sys_read32 (reg_base + XUARTPS_MR_OFFSET );
305
328
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)
316
339
set_baudrate (dev , dev_cfg -> baud_rate );
317
340
318
341
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
342
+ struct uart_xlnx_ps_dev_data_t * dev_data = dev -> data ;
319
343
320
344
/* Clear any pending interrupt flags */
321
345
sys_write32 (XUARTPS_IXR_MASK , reg_base + XUARTPS_ISR_OFFSET );
322
346
347
+ dev_data -> dev = dev ;
348
+ k_timer_init (& dev_data -> timer , & uart_xlnx_ps_soft_isr , NULL );
349
+
323
350
/* Attach to & unmask the corresponding interrupt vector */
324
351
dev_cfg -> irq_config_func (dev );
325
352
@@ -354,7 +381,7 @@ static int uart_xlnx_ps_poll_in(const struct device *dev, unsigned char *c)
354
381
/**
355
382
* @brief Output a character in polled mode.
356
383
*
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
358
385
* the data register.
359
386
*
360
387
* 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)
368
395
static void uart_xlnx_ps_poll_out (const struct device * dev , unsigned char c )
369
396
{
370
397
uintptr_t reg_base = DEVICE_MMIO_GET (dev );
371
- uint32_t reg_val ;
372
398
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
+ }
377
402
378
403
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
+ }
379
421
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 ;
383
446
}
384
447
385
448
/**
@@ -826,17 +889,14 @@ static int uart_xlnx_ps_config_get(const struct device *dev, struct uart_config
826
889
static int uart_xlnx_ps_fifo_fill (const struct device * dev , const uint8_t * tx_data , int size )
827
890
{
828
891
uintptr_t reg_base = DEVICE_MMIO_GET (dev );
829
- uint32_t data_iter = 0 ;
892
+ int count = 0 ;
830
893
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 );
836
897
}
837
- sys_write32 (XUARTPS_IXR_TXEMPTY , reg_base + XUARTPS_IER_OFFSET );
838
898
839
- return data_iter ;
899
+ return count ;
840
900
}
841
901
842
902
/**
@@ -851,16 +911,14 @@ static int uart_xlnx_ps_fifo_fill(const struct device *dev, const uint8_t *tx_da
851
911
static int uart_xlnx_ps_fifo_read (const struct device * dev , uint8_t * rx_data , const int size )
852
912
{
853
913
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 ;
856
915
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 );
861
919
}
862
920
863
- return inum ;
921
+ return count ;
864
922
}
865
923
866
924
/**
@@ -870,9 +928,20 @@ static int uart_xlnx_ps_fifo_read(const struct device *dev, uint8_t *rx_data, co
870
928
*/
871
929
static void uart_xlnx_ps_irq_tx_enable (const struct device * dev )
872
930
{
931
+ struct uart_xlnx_ps_dev_data_t * dev_data = dev -> data ;
873
932
uintptr_t reg_base = DEVICE_MMIO_GET (dev );
874
933
875
934
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
+ }
876
945
}
877
946
878
947
/**
@@ -918,11 +987,7 @@ static int uart_xlnx_ps_irq_tx_complete(const struct device *dev)
918
987
uintptr_t reg_base = DEVICE_MMIO_GET (dev );
919
988
uint32_t reg_val = sys_read32 (reg_base + XUARTPS_SR_OFFSET );
920
989
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 ;
926
991
}
927
992
928
993
/**
@@ -932,9 +997,19 @@ static int uart_xlnx_ps_irq_tx_complete(const struct device *dev)
932
997
*/
933
998
static void uart_xlnx_ps_irq_rx_enable (const struct device * dev )
934
999
{
1000
+ struct uart_xlnx_ps_dev_data_t * dev_data = dev -> data ;
935
1001
uintptr_t reg_base = DEVICE_MMIO_GET (dev );
936
1002
937
1003
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
+ }
938
1013
}
939
1014
940
1015
/**
@@ -959,14 +1034,9 @@ static void uart_xlnx_ps_irq_rx_disable(const struct device *dev)
959
1034
static int uart_xlnx_ps_irq_rx_ready (const struct device * dev )
960
1035
{
961
1036
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 );
963
1038
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 ;
970
1040
}
971
1041
972
1042
/**
@@ -978,7 +1048,8 @@ static void uart_xlnx_ps_irq_err_enable(const struct device *dev)
978
1048
{
979
1049
uintptr_t reg_base = DEVICE_MMIO_GET (dev );
980
1050
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 */
982
1053
| XUARTPS_IXR_TOUT /* [8] Receiver Timerout */
983
1054
| XUARTPS_IXR_PARITY /* [7] Parity Error */
984
1055
| XUARTPS_IXR_FRAMING /* [6] Receiver Framing Error */
@@ -997,7 +1068,8 @@ static void uart_xlnx_ps_irq_err_disable(const struct device *dev)
997
1068
{
998
1069
uintptr_t reg_base = DEVICE_MMIO_GET (dev );
999
1070
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 */
1001
1073
| XUARTPS_IXR_TOUT /* [8] Receiver Timerout */
1002
1074
| XUARTPS_IXR_PARITY /* [7] Parity Error */
1003
1075
| XUARTPS_IXR_FRAMING /* [6] Receiver Framing Error */
@@ -1034,7 +1106,11 @@ static int uart_xlnx_ps_irq_is_pending(const struct device *dev)
1034
1106
*/
1035
1107
static int uart_xlnx_ps_irq_update (const struct device * dev )
1036
1108
{
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 );
1038
1114
return 1 ;
1039
1115
}
1040
1116
@@ -1073,6 +1149,7 @@ static void uart_xlnx_ps_isr(const struct device *dev)
1073
1149
static DEVICE_API (uart , uart_xlnx_ps_driver_api ) = {
1074
1150
.poll_in = uart_xlnx_ps_poll_in ,
1075
1151
.poll_out = uart_xlnx_ps_poll_out ,
1152
+ .err_check = uart_xlnx_ps_err_check ,
1076
1153
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
1077
1154
.configure = uart_xlnx_ps_configure ,
1078
1155
.config_get = uart_xlnx_ps_config_get ,
0 commit comments