#define UART_BUG_NOMSR BIT(2) /* UART has buggy MSR status bits (Au1x00) */
#define UART_BUG_THRE BIT(3) /* UART has buggy THRE reassertion */
#define UART_BUG_TXRACE BIT(5) /* UART Tx fails to set remote DR */
+#define UART_BUG_NOMSI BIT(6) /* UART has no modem status interrupt */
#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
UPF_SKIP_TEST | UPF_IOREMAP;
up.port.rs485_config = serial8250_em485_config;
up.port.rs485_supported = serial8250_em485_supported;
+ up.bugs |= UART_BUG_NOMSI;
up.rs485_start_tx = bcm2835aux_rs485_start_tx;
up.rs485_stop_tx = bcm2835aux_rs485_stop_tx;
mod_timer(&up->timer, jiffies + uart_poll_timeout(&up->port));
}
+static void serial8250_cts_poll_timeout(struct timer_list *t)
+{
+ struct uart_8250_port *up = from_timer(up, t, timer);
+ unsigned long flags;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ serial8250_modem_status(up);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ if (up->port.hw_stopped)
+ mod_timer(&up->timer, jiffies + 1);
+}
+
static void serial8250_backup_timeout(struct timer_list *t)
{
struct uart_8250_port *up = from_timer(up, t, timer);
uart_poll_timeout(port) + HZ / 5);
}
+ if (up->bugs & UART_BUG_NOMSI)
+ up->timer.function = serial8250_cts_poll_timeout;
+
/*
* If the "interrupt" for this port doesn't correspond with any
* hardware interrupt, we use a timer-based system. The original
serial_icr_write(up, UART_ACR, up->acr);
}
serial8250_rpm_put(up);
+
+ if (port->hw_stopped && (up->bugs & UART_BUG_NOMSI))
+ mod_timer(&up->timer, jiffies + 1);
}
static inline void __start_tx(struct uart_port *port)
/* Port locked to synchronize UART_IER access against the console. */
lockdep_assert_held_once(&port->lock);
+ if (up->bugs & UART_BUG_NOMSI)
+ del_timer(&up->timer);
+
if (!port->x_char && uart_circ_empty(&port->state->xmit))
return;
uart_handle_cts_change(port, status & UART_MSR_CTS);
wake_up_interruptible(&port->state->port.delta_msr_wait);
+ } else if (up->bugs & UART_BUG_NOMSI && port->hw_stopped &&
+ status & UART_MSR_CTS) {
+ uart_handle_cts_change(port, status & UART_MSR_CTS);
}
return status;