drivers: serial: xlnx_xuartps: Fix interrupt-driven operation

Fixes interrupt-driven operation. With the previous way of
handling the TX FIFO and the interrupt flags, the operation
of the UART was prone to stalling when using it as the
console I/O device.

Signed-off-by: Immo Birnbaum <Immo.Birnbaum@weidmueller.com>
This commit is contained in:
Immo Birnbaum 2021-07-15 14:26:11 +02:00 committed by Carles Cufí
parent fe33a24721
commit 811d77a88a

View file

@ -303,9 +303,6 @@ static int uart_xlnx_ps_init(const struct device *dev)
/* Set RX FIFO trigger at 1 data bytes. */
sys_write32(0x01U, reg_base + XUARTPS_RXWM_OFFSET);
/* Set RX timeout to 1, which will be 4 character time */
sys_write32(0x1U, reg_base + XUARTPS_RXTOUT_OFFSET);
/* Disable all interrupts, polling mode is default */
sys_write32(XUARTPS_IXR_MASK, reg_base + XUARTPS_IDR_OFFSET);
@ -845,20 +842,18 @@ static int uart_xlnx_ps_fifo_fill(const struct device *dev,
int size)
{
const struct uart_xlnx_ps_dev_config *dev_cfg = DEV_CFG(dev);
uint32_t reg_val;
uint32_t reg_base;
int onum = 0;
uint32_t reg_base = dev_cfg->uconf.regs;
uint32_t data_iter = 0;
reg_base = dev_cfg->uconf.regs;
reg_val = sys_read32(reg_base + XUARTPS_SR_OFFSET);
while (onum < size && (reg_val & XUARTPS_SR_TXFULL) == 0) {
sys_write32((uint32_t)(tx_data[onum] & 0xFF),
reg_base + XUARTPS_FIFO_OFFSET);
onum++;
reg_val = sys_read32(reg_base + XUARTPS_SR_OFFSET);
sys_write32(XUARTPS_IXR_TXEMPTY, reg_base + XUARTPS_IDR_OFFSET);
while (size--) {
while ((sys_read32(reg_base + XUARTPS_SR_OFFSET) & XUARTPS_SR_TXFULL) != 0) {
}
sys_write32((uint32_t)tx_data[data_iter++], reg_base + XUARTPS_FIFO_OFFSET);
}
sys_write32(XUARTPS_IXR_TXEMPTY, reg_base + XUARTPS_IER_OFFSET);
return onum;
return data_iter;
}
/**
@ -937,17 +932,12 @@ static void uart_xlnx_ps_irq_tx_disable(const struct device *dev)
static int uart_xlnx_ps_irq_tx_ready(const struct device *dev)
{
const struct uart_xlnx_ps_dev_config *dev_cfg = DEV_CFG(dev);
uint32_t reg_base;
uint32_t reg_val;
uint32_t reg_base = dev_cfg->uconf.regs;
uint32_t reg_val = sys_read32(reg_base + XUARTPS_SR_OFFSET);
reg_base = dev_cfg->uconf.regs;
reg_val = sys_read32(reg_base + XUARTPS_ISR_OFFSET);
if ((reg_val & (XUARTPS_IXR_TTRIG | XUARTPS_IXR_TXEMPTY)) == 0) {
if ((reg_val & (XUARTPS_SR_TTRIG | XUARTPS_SR_TXEMPTY)) == 0) {
return 0;
} else {
sys_write32(
(XUARTPS_IXR_TTRIG | XUARTPS_IXR_TXEMPTY),
reg_base + XUARTPS_ISR_OFFSET);
return 1;
}
}
@ -1016,11 +1006,9 @@ static void uart_xlnx_ps_irq_rx_disable(const struct device *dev)
static int uart_xlnx_ps_irq_rx_ready(const struct device *dev)
{
const struct uart_xlnx_ps_dev_config *dev_cfg = DEV_CFG(dev);
uint32_t reg_base;
uint32_t reg_val;
uint32_t reg_base = dev_cfg->uconf.regs;
uint32_t reg_val = sys_read32(reg_base + XUARTPS_ISR_OFFSET);
reg_base = dev_cfg->uconf.regs;
reg_val = sys_read32(reg_base + XUARTPS_ISR_OFFSET);
if ((reg_val & XUARTPS_IXR_RTRIG) == 0) {
return 0;
} else {
@ -1107,7 +1095,7 @@ static int uart_xlnx_ps_irq_is_pending(const struct device *dev)
*/
static int uart_xlnx_ps_irq_update(const struct device *dev)
{
(void)dev;
ARG_UNUSED(dev);
return 1;
}