Beispiel #1
0
static void s3c_serial_shutdown(struct uart_port *port)
{
	struct s3c_uart_port *ourport = to_ourport(port);

#ifdef UART_HAS_INTMSK
	if (ourport->tx_claimed || ourport->rx_claimed) {
		free_irq(UART_IRQ(port), ourport);

		ourport->tx_claimed = 0;
		ourport->rx_claimed = 0;
		tx_enabled(port) = 0;
		rx_enabled(port) = 0;
	}
#else
	if (ourport->tx_claimed) {
		free_irq(TX_IRQ(port), ourport);
		tx_enabled(port) = 0;
		ourport->tx_claimed = 0;
	}

	if (ourport->rx_claimed) {
		free_irq(RX_IRQ(port), ourport);
		ourport->rx_claimed = 0;
		rx_enabled(port) = 0;
	}
#endif
}
Beispiel #2
0
static void s3c24xx_serial_stop_rx(struct uart_port *port)
{
	struct s3c24xx_uart_port *ourport = to_ourport(port);
	struct s3c24xx_uart_dma *dma = ourport->dma;
	struct tty_port *t = &port->state->port;
	struct dma_tx_state state;
	enum dma_status dma_status;
	unsigned int received;

	if (rx_enabled(port)) {
		dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
		if (s3c24xx_serial_has_interrupt_mask(port))
			s3c24xx_set_bit(port, S3C64XX_UINTM_RXD,
					S3C64XX_UINTM);
		else
			disable_irq_nosync(ourport->rx_irq);
		rx_enabled(port) = 0;
	}
	if (dma && dma->rx_chan) {
		dmaengine_pause(dma->tx_chan);
		dma_status = dmaengine_tx_status(dma->rx_chan,
				dma->rx_cookie, &state);
		if (dma_status == DMA_IN_PROGRESS ||
			dma_status == DMA_PAUSED) {
			received = dma->rx_bytes_requested - state.residue;
			dmaengine_terminate_all(dma->rx_chan);
			s3c24xx_uart_copy_rx_to_tty(ourport, t, received);
		}
	}
}
static void s3c24xx_serial_stop_rx(struct uart_port *port)
{
	if (rx_enabled(port)) {
		dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
		disable_irq(RX_IRQ(port));
		rx_enabled(port) = 0;
	}
}
Beispiel #4
0
static void s3c24xx_serial_stop_rx(struct uart_port *port)
{
    struct s3c24xx_uart_port *ourport = to_ourport(port);

    if (rx_enabled(port)) {
        dbg("s3c24xx_serial_stop_rx: port=%p\n", port);
        disable_irq_nosync(ourport->rx_irq);
        rx_enabled(port) = 0;
    }
}
Beispiel #5
0
static void s3c_serial_stop_rx(struct uart_port *port)
{
	if (rx_enabled(port)) {
#ifdef UART_HAS_INTMSK
		uart_disable_irq(port, UART_RX_INT);
#else
		disable_irq(RX_IRQ(port));
#endif
		rx_enabled(port) = 0;
	}
}
Beispiel #6
0
static void imapx200_serial_stop_rx(struct uart_port *port)
{
	struct imapx200_uart_port *ourport = to_ourport(port);

	if (rx_enabled(port))
	{
		dbg("imapx200_serial_stop_rx: port=%p\n", port);
		disable_irq_nosync(ourport->rx_irq);
#if 1
		uart_disable_irq(port, UART_RX_INT);
		uart_disable_irq(port, UART_ERR_INT);
#endif	
		rx_enabled(port) = 0;
	}
}
Beispiel #7
0
static void ks8695uart_stop_rx(struct uart_port *port)
{
	if (rx_enabled(port)) {
		disable_irq(KS8695_IRQ_UART_RX);
		rx_enable(port, 0);
	}
}
Beispiel #8
0
static void imapx200_serial_rx_disable(struct uart_port *port)
{
	unsigned long flags;

	spin_lock_irqsave(&port->lock, flags);

	rx_enabled(port) = 0;
	
	spin_unlock_irqrestore(&port->lock, flags);
}
Beispiel #9
0
static int s3c24xx_serial_startup(struct uart_port *port)
{
	struct s3c24xx_uart_port *ourport = to_ourport(port);
	int ret;

	dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n",
	    port->mapbase, port->membase);

        if (port->line == 2) {
       	    s3c2410_gpio_cfgpin(S3C2410_GPH6, S3C2410_GPH6_TXD2);
    	    s3c2410_gpio_pullup(S3C2410_GPH6, 1); 

    	    s3c2410_gpio_cfgpin(S3C2410_GPH7, S3C2410_GPH7_RXD2);
    	    s3c2410_gpio_pullup(S3C2410_GPH7, 1); 
        }

	rx_enabled(port) = 1;

	ret = request_irq(RX_IRQ(port),
			  s3c24xx_serial_rx_chars, 0,
			  s3c24xx_serial_portname(port), ourport);

	if (ret != 0) {
		printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port));
		return ret;
	}

	ourport->rx_claimed = 1;

	dbg("requesting tx irq...\n");

	tx_enabled(port) = 1;

	ret = request_irq(TX_IRQ(port),
			  s3c24xx_serial_tx_chars, 0,
			  s3c24xx_serial_portname(port), ourport);

	if (ret) {
		printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port));
		goto err;
	}

	ourport->tx_claimed = 1;

	dbg("s3c24xx_serial_startup ok\n");

	/* the port reset code should have done the correct
	 * register setup for the port controls */

	return ret;

 err:
	s3c24xx_serial_shutdown(port);
	return ret;
}
Beispiel #10
0
static int s3c_serial_startup(struct uart_port *port)
{
	struct s3c_uart_port *ourport = to_ourport(port);
	unsigned long flags;
	int ret;

	dbg("s3c_serial_startup: port=%p (%08lx,%p)\n",
	    port->mapbase, port->membase);

	local_irq_save(flags);

	rx_enabled(port) = 1;
	tx_enabled(port) = 1;
	
#ifdef UART_HAS_INTMSK
	uart_enable_irq(port, UART_TX_INT | UART_RX_INT);
	ret = request_irq(UART_IRQ(port), s3c_serial_interrupt, 0,
			  s3c_serial_portname(port), ourport);
	if (ret != 0) {
		printk(KERN_ERR "cannot get irq %d\n", UART_IRQ(port));
		return ret;
	}
#else
	ret = request_irq(RX_IRQ(port),
			  s3c_serial_rx_chars, 0,
			  s3c_serial_portname(port), ourport);
	if (ret != 0) {
		printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port));
		return ret;
	}

	ret = request_irq(TX_IRQ(port),
			  s3c_serial_tx_chars, 0,
			  s3c_serial_portname(port), ourport);
	if (ret) {
		printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port));
		s3c_serial_shutdown(port);
		local_irq_restore(flags);
		return ret;
	}
#endif

	ourport->rx_claimed = 1;
	ourport->tx_claimed = 1;

	dbg("s3c_serial_startup ok\n");

	/* the port reset code should have done the correct
	 * register setup for the port controls */
	local_irq_restore(flags);
	return ret;
}
Beispiel #11
0
static int s3c24xx_serial_startup(struct uart_port *port)
{
	struct s3c24xx_uart_port *ourport = to_ourport(port);
	unsigned long flags;
	int ret;

	dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n",
	    port->mapbase, port->membase);

	local_irq_save(flags);

	rx_enabled(port) = 1;

	ret = request_irq(RX_IRQ(port),
			  s3c24xx_serial_rx_chars, 0,
			  s3c24xx_serial_portname(port), ourport);

	if (ret != 0) {
		printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port));
		return ret;
	}

	ourport->rx_claimed = 1;

	dbg("requesting tx irq...\n");

	tx_enabled(port) = 1;

	ret = request_irq(TX_IRQ(port),
			  s3c24xx_serial_tx_chars, 0,
			  s3c24xx_serial_portname(port), ourport);

	if (ret) {
		printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port));
		goto err;
	}

	ourport->tx_claimed = 1;

	dbg("s3c24xx_serial_startup ok\n");

	/* the port reset code should have done the correct
	 * register setup for the port controls */

	local_irq_restore(flags);
	return ret;

 err:
	s3c24xx_serial_shutdown(port);
	local_irq_restore(flags);
	return ret;
}
Beispiel #12
0
static void imapx200_serial_shutdown(struct uart_port *port)
{
	struct imapx200_uart_port *ourport = to_ourport(port);
	if (ourport->tx_claimed || ourport->rx_claimed)
	{
		free_irq(UART_IRQ(port), ourport);

		ourport->tx_claimed = 0;
		ourport->rx_claimed = 0;
		tx_enabled(port) = 0;
		rx_enabled(port) = 0;
	}
}
Beispiel #13
0
static void s3c24xx_serial_rx_disable(struct uart_port *port)
{
	unsigned long flags;
	unsigned int ucon;

	spin_lock_irqsave(&port->lock, flags);

	ucon = rd_regl(port, S3C2410_UCON);
	ucon &= ~S3C2410_UCON_RXIRQMODE;
	wr_regl(port, S3C2410_UCON, ucon);

	rx_enabled(port) = 0;
	spin_unlock_irqrestore(&port->lock, flags);
}
Beispiel #14
0
static int s3c24xx_serial_startup(struct uart_port *port)
{
	struct s3c24xx_uart_port *ourport = to_ourport(port);
	struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
	int ret;

	dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n",
	    port->mapbase, port->membase);

	/* runstate should be 1 before request_irq is called */
	if (cfg->set_runstate)
		cfg->set_runstate(1);

	rx_enabled(port) = 1;

	ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0,
			  s3c24xx_serial_portname(port), ourport);

	if (ret != 0) {
		printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq);
		goto err;
	}

	ourport->rx_claimed = 1;

	dbg("requesting tx irq...\n");

	tx_enabled(port) = 1;

	ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0,
			  s3c24xx_serial_portname(port), ourport);

	if (ret) {
		printk(KERN_ERR "cannot get irq %d\n", ourport->tx_irq);
		goto err;
	}

	ourport->tx_claimed = 1;

	dbg("s3c24xx_serial_startup ok\n");

	/* the port reset code should have done the correct
	 * register setup for the port controls */

	return ret;

 err:
	s3c24xx_serial_shutdown(port);
	return ret;
}
Beispiel #15
0
static void s3c24xx_serial_shutdown(struct uart_port *port)
{
    struct s3c24xx_uart_port *ourport = to_ourport(port);

    if (ourport->tx_claimed) {
        free_irq(ourport->tx_irq, ourport);
        tx_enabled(port) = 0;
        ourport->tx_claimed = 0;
    }

    if (ourport->rx_claimed) {
        free_irq(ourport->rx_irq, ourport);
        ourport->rx_claimed = 0;
        rx_enabled(port) = 0;
    }
}
Beispiel #16
0
static void imapx200_serial_rx_enable(struct uart_port *port)
{
	unsigned long flags;
	unsigned int fcr;
	int count = 10000;

	spin_lock_irqsave(&port->lock, flags);

	while (--count && !imapx200_serial_txempty_nofifo(port))
		udelay(100);

	fcr |= IMAPX200_FCR_RFIFOR_RX_FIFO_RESET | IMAPX200_FCR_FIFOE_FIFO_ENABLE;
	wr_regl(port, IMAPX200_FCR, fcr);

	rx_enabled(port) = 1;
	
	spin_unlock_irqrestore(&port->lock, flags);
}
Beispiel #17
0
static int s3c24xx_serial_startup(struct uart_port *port)
{
	struct s3c24xx_uart_port *ourport = to_ourport(port);
	int ret;

	dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n",
	    port->mapbase, port->membase);

	rx_enabled(port) = 1;

	ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0,
			  s3c24xx_serial_portname(port), ourport);

	if (ret != 0) {
		printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq);
		return ret;
	}

	ourport->rx_claimed = 1;

	dbg("requesting tx irq...\n");

	tx_enabled(port) = 1;

	ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0,
			  s3c24xx_serial_portname(port), ourport);

	if (ret) {
		printk(KERN_ERR "cannot get irq %d\n", ourport->tx_irq);
		goto err;
	}

	ourport->tx_claimed = 1;

	dbg("s3c24xx_serial_startup ok\n");

	

	return ret;

 err:
	s3c24xx_serial_shutdown(port);
	return ret;
}
Beispiel #18
0
static int imapx200_serial_startup(struct uart_port *port)
{
	struct imapx200_uart_port *ourport = to_ourport(port);
	int ret;
	unsigned long flags;
	
	dbg("imapx200_serial_startup: port=%p (%08lx,%p)\n",
		port->mapbase, port->membase);

//	local_irq_save(flags);

	rx_enabled(port) = 1;
//	tx_enabled(port) = 1;

	uart_enable_irq(port, UART_RX_INT);
	uart_enable_irq(port, UART_ERR_INT);
//	uart_enable_irq(port, UART_THRE_INT);
	ret = request_irq(UART_IRQ(port), imapx200_serial_interrupt, IRQF_DISABLED,
	imapx200_serial_portname(port), ourport);
	if (ret != 0)
	{
		printk(KERN_ERR "cannot get irq %d\n", UART_IRQ(port));
		goto err;
	}

	ourport->tx_claimed = 1;
	ourport->rx_claimed = 1;

	dbg("imapx200_serial_startup ok\n");

	/* the port reset code should have done the correct
	 * register setup for the port controls */
//	local_irq_restore(flags);
	return ret;

 err:
	imapx200_serial_shutdown(port);
	
	return ret;
}
Beispiel #19
0
static void s3c24xx_serial_rx_enable(struct uart_port *port)
{
	unsigned long flags;
	unsigned int ucon, ufcon;
	int count = 10000;

	spin_lock_irqsave(&port->lock, flags);

	while (--count && !s3c24xx_serial_txempty_nofifo(port))
		udelay(100);

	ufcon = rd_regl(port, S3C2410_UFCON);
	ufcon |= S3C2410_UFCON_RESETRX;
	wr_regl(port, S3C2410_UFCON, ufcon);

	ucon = rd_regl(port, S3C2410_UCON);
	ucon |= S3C2410_UCON_RXIRQMODE;
	wr_regl(port, S3C2410_UCON, ucon);

	rx_enabled(port) = 1;
	spin_unlock_irqrestore(&port->lock, flags);
}
Beispiel #20
0
static void s3c24xx_serial_shutdown(struct uart_port *port)
{
	struct s3c24xx_uart_port *ourport = to_ourport(port);
	struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);

	if (ourport->tx_claimed) {
		disable_irq(ourport->tx_irq);
		free_irq(ourport->tx_irq, ourport);
		tx_enabled(port) = 0;
		ourport->tx_claimed = 0;
	}

	if (ourport->rx_claimed) {
		disable_irq(ourport->rx_irq);
		free_irq(ourport->rx_irq, ourport);
		ourport->rx_claimed = 0;
		rx_enabled(port) = 0;
	}

	if (cfg->set_runstate)
		cfg->set_runstate(0);
}
Beispiel #21
0
static irqreturn_t
s3c24xx_serial_rx_chars(int irq, void *dev_id)
{
    struct s3c24xx_uart_port *ourport = dev_id;
    struct uart_port *port = &ourport->port;
    struct tty_struct *tty = port->state->port.tty;
    unsigned int ufcon, ch, flag, ufstat, uerstat;
    int max_count = 64;

    while (max_count-- > 0) {
        ufcon = rd_regl(port, S3C2410_UFCON);
        ufstat = rd_regl(port, S3C2410_UFSTAT);

        if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
            break;

        uerstat = rd_regl(port, S3C2410_UERSTAT);
        ch = rd_regb(port, S3C2410_URXH);

        if (port->flags & UPF_CONS_FLOW) {
            int txe = s3c24xx_serial_txempty_nofifo(port);

            if (rx_enabled(port)) {
                if (!txe) {
                    rx_enabled(port) = 0;
                    continue;
                }
            } else {
                if (txe) {
                    ufcon |= S3C2410_UFCON_RESETRX;
                    wr_regl(port, S3C2410_UFCON, ufcon);
                    rx_enabled(port) = 1;
                    goto out;
                }
                continue;
            }
        }

        /* insert the character into the buffer */

        flag = TTY_NORMAL;
        port->icount.rx++;

        if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) {
            dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
                ch, uerstat);

            /* check for break */
            if (uerstat & S3C2410_UERSTAT_BREAK) {
                dbg("break!\n");
                port->icount.brk++;
                if (uart_handle_break(port))
                    goto ignore_char;
            }

            if (uerstat & S3C2410_UERSTAT_FRAME)
                port->icount.frame++;
            if (uerstat & S3C2410_UERSTAT_OVERRUN)
                port->icount.overrun++;

            uerstat &= port->read_status_mask;

            if (uerstat & S3C2410_UERSTAT_BREAK)
                flag = TTY_BREAK;
            else if (uerstat & S3C2410_UERSTAT_PARITY)
                flag = TTY_PARITY;
            else if (uerstat & (S3C2410_UERSTAT_FRAME |
                                S3C2410_UERSTAT_OVERRUN))
                flag = TTY_FRAME;
        }

        if (uart_handle_sysrq_char(port, ch))
            goto ignore_char;

        uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
                         ch, flag);

ignore_char:
        continue;
    }
    tty_flip_buffer_push(tty);

out:
    return IRQ_HANDLED;
}
Beispiel #22
0
static irqreturn_t
s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
{
	struct s3c24xx_uart_port *ourport = dev_id;
	struct uart_port *port = &ourport->port;
	struct tty_struct *tty = port->info->tty;
	unsigned int ufcon, ch, flag, ufstat, uerstat;
	int max_count = 64;

	while (max_count-- > 0) {
		ufcon = rd_regl(port, S3C2410_UFCON);
		ufstat = rd_regl(port, S3C2410_UFSTAT);

		if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
			break;

		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
			if (tty->low_latency)
				tty_flip_buffer_push(tty);

			/*
			 * If this failed then we will throw away the
			 * bytes but must do so to clear interrupts
			 */
		}

		uerstat = rd_regl(port, S3C2410_UERSTAT);
		ch = rd_regb(port, S3C2410_URXH);

		if (port->flags & UPF_CONS_FLOW) {
			int txe = s3c24xx_serial_txempty_nofifo(port);

			if (rx_enabled(port)) {
				if (!txe) {
					rx_enabled(port) = 0;
					continue;
				}
			} else {
				if (txe) {
					ufcon |= S3C2410_UFCON_RESETRX;
					wr_regl(port, S3C2410_UFCON, ufcon);
					rx_enabled(port) = 1;
					goto out;
				}
				continue;
			}
		}

		/* insert the character into the buffer */

		flag = TTY_NORMAL;
		port->icount.rx++;

		if (uerstat & S3C2410_UERSTAT_ANY) {
			dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
			    ch, uerstat);

			/* check for break */
			if (uerstat & S3C2410_UERSTAT_BREAK) {
				dbg("break!\n");
				port->icount.brk++;
				if (uart_handle_break(port))
				    goto ignore_char;
			}

			if (uerstat & S3C2410_UERSTAT_FRAME)
				port->icount.frame++;
			if (uerstat & S3C2410_UERSTAT_OVERRUN)
				port->icount.overrun++;

			uerstat &= port->read_status_mask;

			if (uerstat & S3C2410_UERSTAT_BREAK)
				flag = TTY_BREAK;
			else if (uerstat & S3C2410_UERSTAT_PARITY)
				flag = TTY_PARITY;
			else if (uerstat & ( S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_OVERRUN))
				flag = TTY_FRAME;
		}

		if (uart_handle_sysrq_char(port, ch, regs))
			goto ignore_char;

		if ((uerstat & port->ignore_status_mask) == 0) {
			tty_insert_flip_char(tty, ch, flag);
		}

		if ((uerstat & S3C2410_UERSTAT_OVERRUN) &&
		    tty->flip.count < TTY_FLIPBUF_SIZE) {
			/*
			 * Overrun is special, since it's reported
			 * immediately, and doesn't affect the current
			 * character.
			 */

			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
		}

	ignore_char:
		continue;
	}
	tty_flip_buffer_push(tty);

 out:
	return IRQ_HANDLED;
}
Beispiel #23
0
static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
{
	struct uart_port *port = &ourport->port;
	unsigned int ufcon, ch, flag, ufstat, uerstat;
	unsigned int fifocnt = 0;
	int max_count = port->fifosize;

	while (max_count-- > 0) {
		/*
		 * Receive all characters known to be in FIFO
		 * before reading FIFO level again
		 */
		if (fifocnt == 0) {
			ufstat = rd_regl(port, S3C2410_UFSTAT);
			fifocnt = s3c24xx_serial_rx_fifocnt(ourport, ufstat);
			if (fifocnt == 0)
				break;
		}
		fifocnt--;

		uerstat = rd_regl(port, S3C2410_UERSTAT);
		ch = rd_regb(port, S3C2410_URXH);

		if (port->flags & UPF_CONS_FLOW) {
			int txe = s3c24xx_serial_txempty_nofifo(port);

			if (rx_enabled(port)) {
				if (!txe) {
					rx_enabled(port) = 0;
					continue;
				}
			} else {
				if (txe) {
					ufcon = rd_regl(port, S3C2410_UFCON);
					ufcon |= S3C2410_UFCON_RESETRX;
					wr_regl(port, S3C2410_UFCON, ufcon);
					rx_enabled(port) = 1;
					return;
				}
				continue;
			}
		}

		/* insert the character into the buffer */

		flag = TTY_NORMAL;
		port->icount.rx++;

		if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) {
			dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
			    ch, uerstat);

			/* check for break */
			if (uerstat & S3C2410_UERSTAT_BREAK) {
				dbg("break!\n");
				port->icount.brk++;
				if (uart_handle_break(port))
					continue; /* Ignore character */
			}

			if (uerstat & S3C2410_UERSTAT_FRAME)
				port->icount.frame++;
			if (uerstat & S3C2410_UERSTAT_OVERRUN)
				port->icount.overrun++;

			uerstat &= port->read_status_mask;

			if (uerstat & S3C2410_UERSTAT_BREAK)
				flag = TTY_BREAK;
			else if (uerstat & S3C2410_UERSTAT_PARITY)
				flag = TTY_PARITY;
			else if (uerstat & (S3C2410_UERSTAT_FRAME |
					    S3C2410_UERSTAT_OVERRUN))
				flag = TTY_FRAME;
		}

		if (uart_handle_sysrq_char(port, ch))
			continue; /* Ignore character */

		uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
				 ch, flag);
	}

	tty_flip_buffer_push(&port->state->port);
}
Beispiel #24
0
static irqreturn_t imapx200_serial_rx_chars(int irq, void *dev_id)
{
	struct imapx200_uart_port *ourport = dev_id;
	struct uart_port *port = &ourport->port;
	struct tty_struct *tty = port->state->port.tty;
	unsigned int ch, flag;
	unsigned int usr, rfl, lsr, fcr;
	int max_count = 64;

	while (max_count-- > 0)
	{
		usr = rd_regl(port, IMAPX200_USR);
		rfl = rd_regl(port, IMAPX200_RFL);
		if (imapx200_serial_rx_fifocnt(ourport, usr, rfl) == 0)
			break;

		lsr = rd_regl(port, IMAPX200_LSR);
		ch = rd_regl(port, IMAPX200_RBR);

		if (port->flags & UPF_CONS_FLOW)
		{
			int txe = imapx200_serial_txempty_nofifo(port);

			if (rx_enabled(port))
			{
				if (!txe)
				{
					rx_enabled(port) = 0;
					continue;
				}
			}
			else
			{
				if (txe)
				{
					fcr |= IMAPX200_FCR_RFIFOR_RX_FIFO_RESET | IMAPX200_FCR_FIFOE_FIFO_ENABLE;
					wr_regl(port, IMAPX200_FCR, fcr);
					rx_enabled(port) = 1;
					goto out;
				}
				continue;
			}
		}

		/* insert the character into the buffer */
		flag = TTY_NORMAL;
		port->icount.rx++;

		if (unlikely(lsr & IMAPX200_LSR_ANY))
		{
			dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n", ch, lsr);
			
			/* check for break */
			if (lsr & IMAPX200_LSR_BI_Break_INT)
			{
				dbg("break!\n");
				port->icount.brk++;
				if (uart_handle_break(port))
				    goto ignore_char;
			}

			if (lsr & IMAPX200_LSR_FE_FRAME_ERR)
				port->icount.frame++;
			if (lsr & IMAPX200_LSR_OE_OVERRUN_ERR)
				port->icount.overrun++;

			lsr &= port->read_status_mask;

			if (lsr & IMAPX200_LSR_BI_Break_INT)
				flag = TTY_BREAK;
			else if (lsr & IMAPX200_LSR_PE_PARITY_ERR)
				flag = TTY_PARITY;
			else if (lsr & (IMAPX200_LSR_FE_FRAME_ERR | IMAPX200_LSR_OE_OVERRUN_ERR))
				flag = TTY_FRAME;
		}

		if (uart_handle_sysrq_char(port, ch))
			goto ignore_char;

		uart_insert_char(port, lsr, IMAPX200_LSR_OE_OVERRUN_ERR, ch, flag);

 ignore_char:
		continue;
	}
	tty_flip_buffer_push(tty);

 out:
	return IRQ_HANDLED;
}