@@ -65,6 +65,7 @@ struct pl011_data {
65
65
uint32_t baud_rate ; /* Baud rate */
66
66
bool sbsa ; /* SBSA mode */
67
67
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
68
+ volatile bool sw_call_txdrdy ;
68
69
uart_irq_callback_user_data_t irq_cb ;
69
70
void * irq_cb_data ;
70
71
#endif
@@ -134,10 +135,10 @@ struct pl011_data {
134
135
#define PL011_CR_CTSEn BIT(15) /* CTS hw flow control enable */
135
136
136
137
/* PL011 Interrupt Fifo Level Select Register */
137
- #define PL011_IFLS_TXIFLSEL_SHIFT 0 /* bits 2:0 */
138
- #define PL011_IFLS_TXIFLSEL_WIDTH 3
139
- #define PL011_IFLS_RXIFLSEL_SHIFT 3 /* bits 5:3 */
140
- #define PL011_IFLS_RXIFLSEL_WIDTH 3
138
+ #define PL011_IFLS_RXIFLSEL_M GENMASK(5, 3)
139
+ #define RXIFLSEL_1_2_FULL 2UL
140
+ #define PL011_IFLS_TXIFLSEL_M GENMASK(2, 0)
141
+ #define TXIFLSEL_1_8_FULL 0UL
141
142
142
143
/* PL011 Interrupt Mask Set/Clear Register */
143
144
#define PL011_IMSC_RIMIM BIT(0) /* RTR modem interrupt mask */
@@ -163,6 +164,9 @@ struct pl011_data {
163
164
PL011_IMSC_RXIM | PL011_IMSC_TXIM | \
164
165
PL011_IMSC_RTIM)
165
166
167
+ /* PL011 Raw Interrupt Status Register */
168
+ #define PL011_RIS_TXRIS BIT(5) /* Transmit interrupt status */
169
+
166
170
static inline
167
171
volatile struct pl011_regs * const get_uart (const struct device * dev )
168
172
{
@@ -281,7 +285,28 @@ static int pl011_fifo_read(const struct device *dev,
281
285
282
286
static void pl011_irq_tx_enable (const struct device * dev )
283
287
{
288
+ struct pl011_data * data = dev -> data ;
289
+
284
290
get_uart (dev )-> imsc |= PL011_IMSC_TXIM ;
291
+ if (data -> sw_call_txdrdy ) {
292
+ /* Verify if the callback has been registered */
293
+ if (data -> irq_cb ) {
294
+ /*
295
+ * Due to HW limitation, the first TX interrupt should
296
+ * be triggered by the software.
297
+ *
298
+ * PL011 TX interrupt is based on a transition through
299
+ * a level, rather than on the level itself[1]. So that,
300
+ * enable TX interrupt can not trigger TX interrupt if
301
+ * no data was filled to TX FIFO at the beginning.
302
+ *
303
+ * [1]: PrimeCell UART (PL011) Technical Reference Manual
304
+ * functional-overview/interrupts
305
+ */
306
+ data -> irq_cb (dev , data -> irq_cb_data );
307
+ }
308
+ data -> sw_call_txdrdy = false;
309
+ }
285
310
}
286
311
287
312
static void pl011_irq_tx_disable (const struct device * dev )
@@ -291,8 +316,8 @@ static void pl011_irq_tx_disable(const struct device *dev)
291
316
292
317
static int pl011_irq_tx_complete (const struct device * dev )
293
318
{
294
- /* check for TX FIFO empty */
295
- return get_uart (dev )-> fr & PL011_FR_TXFE ;
319
+ /* Check for UART is busy transmitting data. */
320
+ return (( get_uart (dev )-> fr & PL011_FR_BUSY ) == 0 ) ;
296
321
}
297
322
298
323
static int pl011_irq_tx_ready (const struct device * dev )
@@ -303,7 +328,8 @@ static int pl011_irq_tx_ready(const struct device *dev)
303
328
return false;
304
329
305
330
return ((get_uart (dev )-> imsc & PL011_IMSC_TXIM ) &&
306
- pl011_irq_tx_complete (dev ));
331
+ /* Check for TX interrupt status is set or TX FIFO is empty. */
332
+ (get_uart (dev )-> ris & PL011_RIS_TXRIS || get_uart (dev )-> fr & PL011_FR_TXFE ));
307
333
}
308
334
309
335
static void pl011_irq_rx_enable (const struct device * dev )
@@ -418,6 +444,10 @@ static int pl011_init(const struct device *dev)
418
444
lcrh |= PL011_LCRH_WLEN_SIZE (8 ) << PL011_LCRH_WLEN_SHIFT ;
419
445
get_uart (dev )-> lcr_h = lcrh ;
420
446
447
+ /* Setting transmit and receive interrupt FIFO level */
448
+ get_uart (dev )-> ifls = FIELD_PREP (PL011_IFLS_TXIFLSEL_M , TXIFLSEL_1_8_FULL )
449
+ | FIELD_PREP (PL011_IFLS_RXIFLSEL_M , RXIFLSEL_1_2_FULL );
450
+
421
451
/* Enabling the FIFOs */
422
452
pl011_enable_fifo (dev );
423
453
}
@@ -434,6 +464,7 @@ static int pl011_init(const struct device *dev)
434
464
}
435
465
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
436
466
config -> irq_config_func (dev );
467
+ data -> sw_call_txdrdy = true;
437
468
#endif
438
469
if (!data -> sbsa ) {
439
470
pl011_enable (dev );
0 commit comments