root/drivers/tty/serial/8250/8250_fsl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fsl8250_handle_irq

   1 // SPDX-License-Identifier: GPL-2.0
   2 #if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
   3 #define SUPPORT_SYSRQ
   4 #endif
   5 
   6 #include <linux/serial_reg.h>
   7 #include <linux/serial_8250.h>
   8 
   9 #include "8250.h"
  10 
  11 /*
  12  * Freescale 16550 UART "driver", Copyright (C) 2011 Paul Gortmaker.
  13  *
  14  * This isn't a full driver; it just provides an alternate IRQ
  15  * handler to deal with an errata.  Everything else is just
  16  * using the bog standard 8250 support.
  17  *
  18  * We follow code flow of serial8250_default_handle_irq() but add
  19  * a check for a break and insert a dummy read on the Rx for the
  20  * immediately following IRQ event.
  21  *
  22  * We re-use the already existing "bug handling" lsr_saved_flags
  23  * field to carry the "what we just did" information from the one
  24  * IRQ event to the next one.
  25  */
  26 
  27 int fsl8250_handle_irq(struct uart_port *port)
  28 {
  29         unsigned char lsr, orig_lsr;
  30         unsigned long flags;
  31         unsigned int iir;
  32         struct uart_8250_port *up = up_to_u8250p(port);
  33 
  34         spin_lock_irqsave(&up->port.lock, flags);
  35 
  36         iir = port->serial_in(port, UART_IIR);
  37         if (iir & UART_IIR_NO_INT) {
  38                 spin_unlock_irqrestore(&up->port.lock, flags);
  39                 return 0;
  40         }
  41 
  42         /* This is the WAR; if last event was BRK, then read and return */
  43         if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) {
  44                 up->lsr_saved_flags &= ~UART_LSR_BI;
  45                 port->serial_in(port, UART_RX);
  46                 spin_unlock_irqrestore(&up->port.lock, flags);
  47                 return 1;
  48         }
  49 
  50         lsr = orig_lsr = up->port.serial_in(&up->port, UART_LSR);
  51 
  52         /* Process incoming characters first */
  53         if ((lsr & (UART_LSR_DR | UART_LSR_BI)) &&
  54             (up->ier & (UART_IER_RLSI | UART_IER_RDI))) {
  55                 lsr = serial8250_rx_chars(up, lsr);
  56         }
  57 
  58         /* Stop processing interrupts on input overrun */
  59         if ((orig_lsr & UART_LSR_OE) && (up->overrun_backoff_time_ms > 0)) {
  60                 unsigned long delay;
  61 
  62                 up->ier = port->serial_in(port, UART_IER);
  63                 if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) {
  64                         port->ops->stop_rx(port);
  65                 } else {
  66                         /* Keep restarting the timer until
  67                          * the input overrun subsides.
  68                          */
  69                         cancel_delayed_work(&up->overrun_backoff);
  70                 }
  71 
  72                 delay = msecs_to_jiffies(up->overrun_backoff_time_ms);
  73                 schedule_delayed_work(&up->overrun_backoff, delay);
  74         }
  75 
  76         serial8250_modem_status(up);
  77 
  78         if (lsr & UART_LSR_THRE)
  79                 serial8250_tx_chars(up);
  80 
  81         up->lsr_saved_flags = orig_lsr;
  82         uart_unlock_and_check_sysrq(&up->port, flags);
  83         return 1;
  84 }
  85 EXPORT_SYMBOL_GPL(fsl8250_handle_irq);

/* [<][>][^][v][top][bottom][index][help] */