aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2012-09-06 08:45:23 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-06 12:17:01 -0400
commit81b75aef11abfd7b51e719a5388189eefa82e997 (patch)
tree9ce12363f87f0e1924d609a82d4f011cc2912ac1 /drivers/tty
parenta0f38b87de1df05acf2e3cc23ee2f02a18d80c85 (diff)
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>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/omap-serial.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index dd3971fe899f..d5a08cb5213d 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -351,33 +351,58 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
351{ 351{
352 struct uart_omap_port *up = dev_id; 352 struct uart_omap_port *up = dev_id;
353 unsigned int iir, lsr; 353 unsigned int iir, lsr;
354 unsigned int type;
354 unsigned long flags; 355 unsigned long flags;
356 irqreturn_t ret = IRQ_NONE;
355 357
358 spin_lock_irqsave(&up->port.lock, flags);
356 pm_runtime_get_sync(up->dev); 359 pm_runtime_get_sync(up->dev);
357 iir = serial_in(up, UART_IIR); 360 iir = serial_in(up, UART_IIR);
358 if (iir & UART_IIR_NO_INT) { 361again:
359 pm_runtime_mark_last_busy(up->dev); 362 if (iir & UART_IIR_NO_INT)
360 pm_runtime_put_autosuspend(up->dev); 363 goto out;
361 return IRQ_NONE;
362 }
363 364
364 spin_lock_irqsave(&up->port.lock, flags); 365 ret = IRQ_HANDLED;
365 lsr = serial_in(up, UART_LSR); 366 lsr = serial_in(up, UART_LSR);
366 if (iir & UART_IIR_RLSI) { 367
368 /* extract IRQ type from IIR register */
369 type = iir & 0x3e;
370
371 switch (type) {
372 case UART_IIR_MSI:
373 check_modem_status(up);
374 break;
375 case UART_IIR_THRI:
376 if (lsr & UART_LSR_THRE)
377 transmit_chars(up);
378 break;
379 case UART_IIR_RDI:
367 if (lsr & UART_LSR_DR) 380 if (lsr & UART_LSR_DR)
368 receive_chars(up, &lsr); 381 receive_chars(up, &lsr);
382 break;
383 case UART_IIR_RLSI:
384 if (lsr & UART_LSR_BRK_ERROR_BITS)
385 receive_chars(up, &lsr);
386 break;
387 case UART_IIR_RX_TIMEOUT:
388 receive_chars(up, &lsr);
389 break;
390 case UART_IIR_CTS_RTS_DSR:
391 iir = serial_in(up, UART_IIR);
392 goto again;
393 case UART_IIR_XOFF:
394 /* FALLTHROUGH */
395 default:
396 break;
369 } 397 }
370 398
371 check_modem_status(up); 399out:
372 if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI))
373 transmit_chars(up);
374
375 spin_unlock_irqrestore(&up->port.lock, flags); 400 spin_unlock_irqrestore(&up->port.lock, flags);
376 pm_runtime_mark_last_busy(up->dev); 401 pm_runtime_mark_last_busy(up->dev);
377 pm_runtime_put_autosuspend(up->dev); 402 pm_runtime_put_autosuspend(up->dev);
378
379 up->port_activity = jiffies; 403 up->port_activity = jiffies;
380 return IRQ_HANDLED; 404
405 return ret;
381} 406}
382 407
383static unsigned int serial_omap_tx_empty(struct uart_port *port) 408static unsigned int serial_omap_tx_empty(struct uart_port *port)