serial: omap: simplify IRQ handling
quite a few changes here, though they are pretty obvious. In summary we're making sure to detect which interrupt type we need to handle before calling the underlying interrupt handling procedure. Tested-by: Shubhrajyoti D <shubhrajyoti@ti.com> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Signed-off-by: Felipe Balbi <balbi@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
a0f38b87de
commit
81b75aef11
@ -351,33 +351,58 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
|
|||||||
{
|
{
|
||||||
struct uart_omap_port *up = dev_id;
|
struct uart_omap_port *up = dev_id;
|
||||||
unsigned int iir, lsr;
|
unsigned int iir, lsr;
|
||||||
|
unsigned int type;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
irqreturn_t ret = IRQ_NONE;
|
||||||
pm_runtime_get_sync(up->dev);
|
|
||||||
iir = serial_in(up, UART_IIR);
|
|
||||||
if (iir & UART_IIR_NO_INT) {
|
|
||||||
pm_runtime_mark_last_busy(up->dev);
|
|
||||||
pm_runtime_put_autosuspend(up->dev);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_irqsave(&up->port.lock, flags);
|
spin_lock_irqsave(&up->port.lock, flags);
|
||||||
|
pm_runtime_get_sync(up->dev);
|
||||||
|
iir = serial_in(up, UART_IIR);
|
||||||
|
again:
|
||||||
|
if (iir & UART_IIR_NO_INT)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = IRQ_HANDLED;
|
||||||
lsr = serial_in(up, UART_LSR);
|
lsr = serial_in(up, UART_LSR);
|
||||||
if (iir & UART_IIR_RLSI) {
|
|
||||||
|
/* extract IRQ type from IIR register */
|
||||||
|
type = iir & 0x3e;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case UART_IIR_MSI:
|
||||||
|
check_modem_status(up);
|
||||||
|
break;
|
||||||
|
case UART_IIR_THRI:
|
||||||
|
if (lsr & UART_LSR_THRE)
|
||||||
|
transmit_chars(up);
|
||||||
|
break;
|
||||||
|
case UART_IIR_RDI:
|
||||||
if (lsr & UART_LSR_DR)
|
if (lsr & UART_LSR_DR)
|
||||||
receive_chars(up, &lsr);
|
receive_chars(up, &lsr);
|
||||||
|
break;
|
||||||
|
case UART_IIR_RLSI:
|
||||||
|
if (lsr & UART_LSR_BRK_ERROR_BITS)
|
||||||
|
receive_chars(up, &lsr);
|
||||||
|
break;
|
||||||
|
case UART_IIR_RX_TIMEOUT:
|
||||||
|
receive_chars(up, &lsr);
|
||||||
|
break;
|
||||||
|
case UART_IIR_CTS_RTS_DSR:
|
||||||
|
iir = serial_in(up, UART_IIR);
|
||||||
|
goto again;
|
||||||
|
case UART_IIR_XOFF:
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_modem_status(up);
|
out:
|
||||||
if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI))
|
|
||||||
transmit_chars(up);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&up->port.lock, flags);
|
spin_unlock_irqrestore(&up->port.lock, flags);
|
||||||
pm_runtime_mark_last_busy(up->dev);
|
pm_runtime_mark_last_busy(up->dev);
|
||||||
pm_runtime_put_autosuspend(up->dev);
|
pm_runtime_put_autosuspend(up->dev);
|
||||||
|
|
||||||
up->port_activity = jiffies;
|
up->port_activity = jiffies;
|
||||||
return IRQ_HANDLED;
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int serial_omap_tx_empty(struct uart_port *port)
|
static unsigned int serial_omap_tx_empty(struct uart_port *port)
|
||||||
|
Loading…
Reference in New Issue
Block a user