static void ssauart_rx_chars (struct uart_port *port)
#endif
{
#if 1

   struct tty_struct *tty = port->info->tty;

   while (1)
   {
      if ((UART_GET_LSR(port) & (1 << 0)) == 0)         /* no more chars available */
         break;

      *tty->flip.char_buf_ptr++ = UART_GET_CHAR(port);
      *tty->flip.flag_buf_ptr++ = TTY_NORMAL;           /* Fixme: we should check for overrun, parity, framing errors etc */
      port->icount.rx++;
      tty->flip.count++;

      if (tty->flip.count >= TTY_FLIPBUF_SIZE)
         break;
   }

   tty_flip_buffer_push (tty);

#else

   struct tty_struct *tty = port->info->tty;

   unsigned int ch;
   unsigned int status;
   unsigned int max_count = 256;

   while (1)
   {
      status = UART_GET_LSR(port);

      if (((status & (1 << 0)) == 0) || (--max_count == 0))
         break;

      if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
         tty->flip.tqueue.routine ((void *) tty);
         if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
            printk (KERN_WARNING "TTY_DONT_FLIP set\n");
            return;
         }
      }

      *tty->flip.char_buf_ptr++ = UART_GET_CHAR(port);
      *tty->flip.flag_buf_ptr++ = TTY_NORMAL;           /* Fixme: we should check for overrun, parity, framing errors etc */
      tty->flip.count++;
      port->icount.rx++;
   }

   tty_flip_buffer_push (tty);

#endif
}
Beispiel #2
0
static void s3c2440_rx_int(int irq, void *dev_id, struct pt_regs *regs)
{
	struct uart_info *info = dev_id;
	struct tty_struct *tty = info->tty;
	unsigned int status, ch, max_count = 256;
	struct uart_port *port = info->port;

	status = UART_GET_UTRSTAT(port);
	while ((status & UTRSTAT_RX_RDY) && max_count--) {
		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
			tty->flip.tqueue.routine((void *) tty);
			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
				printk(KERN_WARNING "TTY_DONT_FLIP set\n");
				return;
			}
		}

		ch = UART_GET_CHAR(port);

		*tty->flip.char_buf_ptr = ch;
		*tty->flip.flag_buf_ptr = TTY_NORMAL;
		port->icount.rx++;
		tty->flip.flag_buf_ptr++;
		tty->flip.char_buf_ptr++;
		tty->flip.count++;
		status = UART_GET_UTRSTAT(port);
	}
	tty_flip_buffer_push(tty);
	return;
}
Beispiel #3
0
static void apbuart_flush_fifo(struct uart_port *port)
{
	int i;

	for (i = 0; i < port->fifosize; i++)
		UART_GET_CHAR(port);
}
Beispiel #4
0
static int sa1100_console_wait_key(struct console *co)
{
	struct uart_port *port = sa1100_ports + co->index;
	unsigned long flags;
	u_int old_utcr3, status, ch;

	/*
	 * Save UTCR3 and disable interrupts
	 */
	save_flags(flags);
	cli();
	old_utcr3 = UART_GET_UTCR3(port);
	UART_PUT_UTCR3(port, old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE));
	restore_flags(flags);

	/*
	 * Wait for a character
	 */
	do {
		status = UART_GET_UTSR1(port);
	} while (!(status & UTSR1_RNE));
	ch = UART_GET_CHAR(port);

	/*
	 * Restore UTCR3
	 */
	UART_PUT_UTCR3(port, old_utcr3);

	return ch;
}
static int omahauart_console_wait_key(struct console *co)
{
	struct uart_port *port = omaha_ports + co->index;
	unsigned int status;

	do {
		status = UART_FIFO_STATUS(port);
	} while (!UART_RX_DATA(status));
	return UART_GET_CHAR(port);
}
Beispiel #6
0
/*
 * Characters received (called from interrupt handler)
 */
static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs)
{
	struct tty_struct *tty = port->info->tty;
	unsigned int status, ch, flg;

	status = UART_GET_CSR(port) & port->read_status_mask;
	while (status & (AT91_US_RXRDY)) {
		ch = UART_GET_CHAR(port);

		port->icount.rx++;

		flg = TTY_NORMAL;

		/*
		 * note that the error handling code is
		 * out of the main execution path
		 */
		if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE))) {
			UART_PUT_CR(port, AT91_US_RSTSTA);	/* clear error */
			if (status & (AT91_US_PARE))
				port->icount.parity++;
			if (status & (AT91_US_FRAME))
				port->icount.frame++;
			if (status & (AT91_US_OVRE))
				port->icount.overrun++;

			if (status & AT91_US_PARE)
				flg = TTY_PARITY;
			else if (status & AT91_US_FRAME)
				flg = TTY_FRAME;
			if (status & AT91_US_OVRE) {
				/*
				 * overrun does *not* affect the character
				 * we read from the FIFO
				 */
				tty_insert_flip_char(tty, ch, flg);
				ch = 0;
				flg = TTY_OVERRUN;
			}
#ifdef SUPPORT_SYSRQ
			port->sysrq = 0;
#endif
		}

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

		tty_insert_flip_char(tty, ch, flg);

	ignore_char:
		status = UART_GET_CSR(port) & port->read_status_mask;
	}

	tty_flip_buffer_push(tty);
}
Beispiel #7
0
static irqreturn_t ks8695uart_rx_chars(int irq, void *dev_id)
{
	struct uart_port *port = dev_id;
	struct tty_struct *tty = port->info->port.tty;
	unsigned int status, ch, lsr, flg, max_count = 256;

	status = UART_GET_LSR(port);		/* clears pending LSR interrupts */
	while ((status & URLS_URDR) && max_count--) {
		ch = UART_GET_CHAR(port);
		flg = TTY_NORMAL;

		port->icount.rx++;

		/*
		 * Note that the error handling code is
		 * out of the main execution path
		 */
		lsr = UART_GET_LSR(port) | UART_DUMMY_LSR_RX;
		if (unlikely(lsr & (URLS_URBI | URLS_URPE | URLS_URFE | URLS_URROE))) {
			if (lsr & URLS_URBI) {
				lsr &= ~(URLS_URFE | URLS_URPE);
				port->icount.brk++;
				if (uart_handle_break(port))
					goto ignore_char;
			}
			if (lsr & URLS_URPE)
				port->icount.parity++;
			if (lsr & URLS_URFE)
				port->icount.frame++;
			if (lsr & URLS_URROE)
				port->icount.overrun++;

			lsr &= port->read_status_mask;

			if (lsr & URLS_URBI)
				flg = TTY_BREAK;
			else if (lsr & URLS_URPE)
				flg = TTY_PARITY;
			else if (lsr & URLS_URFE)
				flg = TTY_FRAME;
		}

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

		uart_insert_char(port, lsr, URLS_URROE, ch, flg);

ignore_char:
		status = UART_GET_LSR(port);
	}
	tty_flip_buffer_push(tty);

	return IRQ_HANDLED;
}
Beispiel #8
0
static void bfin_sir_rx_chars(struct net_device *dev)
{
	struct bfin_sir_self *self = netdev_priv(dev);
	struct bfin_sir_port *port = self->sir_port;
	unsigned char ch;

	UART_CLEAR_LSR(port);
	ch = UART_GET_CHAR(port);
	async_unwrap_char(dev, &self->stats, &self->rx_buff, ch);
	dev->last_rx = jiffies;
}
Beispiel #9
0
static void apbuart_rx_chars(struct uart_port *port)
{
	unsigned int status, ch, rsr, flag;
	unsigned int max_chars = port->fifosize;

	status = UART_GET_STATUS(port);

	while (UART_RX_DATA(status) && (max_chars--)) {

		ch = UART_GET_CHAR(port);
		flag = TTY_NORMAL;

		port->icount.rx++;

		rsr = UART_GET_STATUS(port) | UART_DUMMY_RSR_RX;
		UART_PUT_STATUS(port, 0);
		if (rsr & UART_STATUS_ERR) {

			if (rsr & UART_STATUS_BR) {
				rsr &= ~(UART_STATUS_FE | UART_STATUS_PE);
				port->icount.brk++;
				if (uart_handle_break(port))
					goto ignore_char;
			} else if (rsr & UART_STATUS_PE) {
				port->icount.parity++;
			} else if (rsr & UART_STATUS_FE) {
				port->icount.frame++;
			}
			if (rsr & UART_STATUS_OE)
				port->icount.overrun++;

			rsr &= port->read_status_mask;

			if (rsr & UART_STATUS_PE)
				flag = TTY_PARITY;
			else if (rsr & UART_STATUS_FE)
				flag = TTY_FRAME;
		}

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

		uart_insert_char(port, rsr, UART_STATUS_OE, ch, flag);


	      ignore_char:
		status = UART_GET_STATUS(port);
	}

	spin_unlock(&port->lock);
	tty_flip_buffer_push(&port->state->port);
	spin_lock(&port->lock);
}
/*
 * Characters received (called from interrupt handler)
 */
static void atmel_rx_chars(struct uart_port *port)
{
	struct tty_struct *tty = port->info->tty;
	unsigned int status, ch, flg;

	status = UART_GET_CSR(port);
	while (status & ATMEL_US_RXRDY) {
		ch = UART_GET_CHAR(port);

		port->icount.rx++;

		flg = TTY_NORMAL;

		/*
		 * note that the error handling code is
		 * out of the main execution path
		 */
		if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK))) {
			UART_PUT_CR(port, ATMEL_US_RSTSTA);	/* clear error */
			if (status & ATMEL_US_RXBRK) {
				status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);	/* ignore side-effect */
				port->icount.brk++;
				if (uart_handle_break(port))
					goto ignore_char;
			}
			if (status & ATMEL_US_PARE)
				port->icount.parity++;
			if (status & ATMEL_US_FRAME)
				port->icount.frame++;
			if (status & ATMEL_US_OVRE)
				port->icount.overrun++;

			status &= port->read_status_mask;

			if (status & ATMEL_US_RXBRK)
				flg = TTY_BREAK;
			else if (status & ATMEL_US_PARE)
				flg = TTY_PARITY;
			else if (status & ATMEL_US_FRAME)
				flg = TTY_FRAME;
		}

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

		uart_insert_char(port, status, ATMEL_US_OVRE, ch, flg);

	ignore_char:
		status = UART_GET_CSR(port);
	}

	tty_flip_buffer_push(tty);
}
Beispiel #11
0
static void
sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
{
	struct tty_struct *tty = sport->port.info->tty;
	unsigned int status, ch, flg;

	status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
		 UTSR0_TO_SM(UART_GET_UTSR0(sport));
	while (status & UTSR1_TO_SM(UTSR1_RNE)) {
		ch = UART_GET_CHAR(sport);

		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
			goto ignore_char;
		sport->port.icount.rx++;

		flg = TTY_NORMAL;

		/*
		 * note that the error handling code is
		 * out of the main execution path
		 */
		if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR)) {
			if (status & UTSR1_TO_SM(UTSR1_PRE))
				sport->port.icount.parity++;
			else if (status & UTSR1_TO_SM(UTSR1_FRE))
				sport->port.icount.frame++;
			if (status & UTSR1_TO_SM(UTSR1_ROR))
				sport->port.icount.overrun++;

			status &= sport->port.read_status_mask;

			if (status & UTSR1_TO_SM(UTSR1_PRE))
				flg = TTY_PARITY;
			else if (status & UTSR1_TO_SM(UTSR1_FRE))
				flg = TTY_FRAME;

#ifdef SUPPORT_SYSRQ
			sport->port.sysrq = 0;
#endif
		}

		if (uart_handle_sysrq_char(&sport->port, ch, regs))
			goto ignore_char;

		uart_insert_char(&sport->port, status, UTSR1_TO_SM(UTSR1_ROR), ch, flg);

	ignore_char:
		status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
			 UTSR0_TO_SM(UART_GET_UTSR0(sport));
	}
	tty_flip_buffer_push(tty);
}
Beispiel #12
0
pl010_rx_chars(struct uart_port *port)
#endif
{
	struct tty_struct *tty = port->info->tty;
	unsigned int status, ch, flag, rsr, max_count = 256;

	status = UART_GET_FR(port);
	while (UART_RX_DATA(status) && max_count--) {
		ch = UART_GET_CHAR(port);
		flag = TTY_NORMAL;

		port->icount.rx++;

		/*
		 * Note that the error handling code is
		 * out of the main execution path
		 */
		rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
		if (unlikely(rsr & UART01x_RSR_ANY)) {
			if (rsr & UART01x_RSR_BE) {
				rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
				port->icount.brk++;
				if (uart_handle_break(port))
					goto ignore_char;
			} else if (rsr & UART01x_RSR_PE)
				port->icount.parity++;
			else if (rsr & UART01x_RSR_FE)
				port->icount.frame++;
			if (rsr & UART01x_RSR_OE)
				port->icount.overrun++;

			rsr &= port->read_status_mask;

			if (rsr & UART01x_RSR_BE)
				flag = TTY_BREAK;
			else if (rsr & UART01x_RSR_PE)
				flag = TTY_PARITY;
			else if (rsr & UART01x_RSR_FE)
				flag = TTY_FRAME;
		}

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

		uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag);

	ignore_char:
		status = UART_GET_FR(port);
	}
	tty_flip_buffer_push(tty);
	return;
}
Beispiel #13
0
int get_char(char *buf, int i, int len)
{
	int j = 0;
	UART_DIB_RIRQ(i);
	while(UART_GET_RSR(i))
	{
		buf[j++] = UART_GET_CHAR(i);
		if(j == len)
			break;
	}
	UART_ENB_RIRQ(i);
	return j;
}
Beispiel #14
0
static int bfin_serial_poll_get_char(struct uart_port *port)
{
	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
	unsigned char chr;

	while (!(UART_GET_LSR(uart) & DR))
		cpu_relax();

	UART_CLEAR_DLAB(uart);
	chr = UART_GET_CHAR(uart);

	return chr;
}
Beispiel #15
0
static void s3c2440_err_int(int irq, void *dev_id, struct pt_regs *regs)
{
	struct uart_info *info = dev_id;
	struct uart_port *port = info->port;
	struct tty_struct *tty = info->tty;
	unsigned int ch, flg;
	unsigned char err;

	spin_lock(&info->lock);
	
	ch = UART_GET_CHAR (port);
	err = UART_GET_UERSTAT(port) & (UERSTAT_BRK | UERSTAT_FRAME |
			UERSTAT_PARITY | UERSTAT_OVERRUN);
	if (!err) return ;

	if (err & UERSTAT_BRK)
		port->icount.brk++;
	if (err & UERSTAT_FRAME)
		port->icount.frame++;
	if (err & UERSTAT_PARITY)
		port->icount.parity++;
	if (err & UERSTAT_OVERRUN)
		port->icount.overrun++;

	err &= port->read_status_mask;

	if (err & UERSTAT_PARITY)
		flg = TTY_PARITY;
	else if (err & UERSTAT_FRAME)
		flg = TTY_FRAME;
	else
		flg = TTY_NORMAL;

	if (err & UERSTAT_OVERRUN) {
		*tty->flip.char_buf_ptr = ch;
		*tty->flip.flag_buf_ptr = flg;
		tty->flip.flag_buf_ptr++;
		tty->flip.char_buf_ptr++;
		tty->flip.count++;
		if (tty->flip.count < TTY_FLIPBUF_SIZE) {
			ch = 0;
			flg = TTY_OVERRUN;
		}
	}

	*tty->flip.flag_buf_ptr++ = flg;
	*tty->flip.char_buf_ptr++ = ch;
	tty->flip.count++;
	
	spin_unlock(&info->lock);
}
Beispiel #16
0
static void get_buf(struct serial_dev *devp)
{
	UART_DIB_RIRQ(devp->index);//disable recvive irq
	while(devp->recv_full_flag == 0 && UART_GET_RSR(devp->index))
	{
		devp->recv_buf[devp->recv_wr_point++] = UART_GET_CHAR(devp->index);
		if(devp->recv_wr_point >= MAX_BUF_LEN)
			devp->recv_wr_point = 0;
		if(devp->recv_wr_point == devp->recv_rd_point)
			devp->recv_full_flag = 1;			
	}
	UART_ENB_RIRQ(devp->index);
	return ;
}
/*
 * AT91_iso_getchar
 * 
 * Utility to retrieve one char from USART controller
 *
 * by polling UART_CSR register, if ready, get UART_RHR.
 */ 
char AT91_iso_getchar(unsigned int nWait100cycle)
{
	unsigned int CSR_status=0;
	while (!((CSR_status = UART_GET_CSR(base)) & AT91C_US_RXRDY)) {
		if (nWait100cycle>0) {
			udelay(20);	// cycle time??
			nWait100cycle--;
			if (nWait100cycle <= 0) {
				// timeout, break loop
				printk(KERN_INFO "[sam.ko] AT91_iso_getchar(): timeout\n");
				return 0;
			}
		}
	}
	return (UART_GET_CHAR(base) & 0x1FF);
}
Beispiel #18
0
static void
sa1100_rx_chars(struct sa1100_port *sport)
{
	struct tty_struct *tty = sport->port.state->port.tty;
	unsigned int status, ch, flg;

	status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
		 UTSR0_TO_SM(UART_GET_UTSR0(sport));
	while (status & UTSR1_TO_SM(UTSR1_RNE)) {
		ch = UART_GET_CHAR(sport);

		sport->port.icount.rx++;

		flg = TTY_NORMAL;

		
		if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR)) {
			if (status & UTSR1_TO_SM(UTSR1_PRE))
				sport->port.icount.parity++;
			else if (status & UTSR1_TO_SM(UTSR1_FRE))
				sport->port.icount.frame++;
			if (status & UTSR1_TO_SM(UTSR1_ROR))
				sport->port.icount.overrun++;

			status &= sport->port.read_status_mask;

			if (status & UTSR1_TO_SM(UTSR1_PRE))
				flg = TTY_PARITY;
			else if (status & UTSR1_TO_SM(UTSR1_FRE))
				flg = TTY_FRAME;

#ifdef SUPPORT_SYSRQ
			sport->port.sysrq = 0;
#endif
		}

		if (uart_handle_sysrq_char(&sport->port, ch))
			goto ignore_char;

		uart_insert_char(&sport->port, status, UTSR1_TO_SM(UTSR1_ROR), ch, flg);

	ignore_char:
		status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
			 UTSR0_TO_SM(UART_GET_UTSR0(sport));
	}
	tty_flip_buffer_push(tty);
}
static ssize_t sam_read(struct file *file, char *buf, size_t count,
                loff_t *ptr)
{
	unsigned long flags;
	unsigned int CSR_status=0;
	unsigned int i;
	int timeout=0;
	char *tmpBuf = (char *)kmalloc(count, GFP_KERNEL);
	int retval=0;

	if (!tmpBuf)
		return -ENOMEM;

	// SPIN Lock to protect reading from SAM
	spin_lock_irqsave(&sam_spinlock, flags);

	if (DEBUG) {
		printk(KERN_INFO "SAM Read count = %d\n", count);
	}
	for (i=0; i<count; i++) {
		timeout = 10000;
		while (!((CSR_status = UART_GET_CSR(base)) & AT91C_US_RXRDY)) {
			timeout--;
			if (timeout == 0) {
			  printk(KERN_INFO "SAM Read Timeout == 0!\n");
			  break;
			}
		}
		tmpBuf[i] = (UART_GET_CHAR(base) & 0x1FF);
		if (DEBUG)
			printk(KERN_INFO "[%.2X]", tmpBuf[i]);
	}
	if (DEBUG) {
		if (timeout == 0)
			printk(KERN_INFO "SAM Read Timeout == 0!\n");
	}
	
	spin_unlock_irqrestore(&sam_spinlock, flags);
	// SPIN Lock end

	// Move Kernel Space Memory to User Space
	retval = copy_to_user(buf, tmpBuf, i);

	// free kernel memory
	kfree(tmpBuf);
	return 0;
}
static ssize_t sam_write(struct file *file, const char *buf,
                size_t count, loff_t * ppos)
{
	unsigned long flags;
	unsigned int CSR_status=0;
	unsigned int i;
	int data;
	char *tmpBuf = (char *)kmalloc(count, GFP_KERNEL);

	if (!tmpBuf) 
		return -ENOMEM;

	// Move User Space Memory to Kernel Space
	if (copy_from_user(tmpBuf, buf, count)) {
		kfree(tmpBuf);
		return -EFAULT;
	}

	// SPIN Lock to protect writing to SAM
	spin_lock_irqsave(&sam_spinlock, flags);

	// Part 1, clear receive buffer
	while (((CSR_status = UART_GET_CSR(base)) & AT91C_US_RXRDY)) {
		data = (UART_GET_CHAR(base) & 0x1FF);
	}

	// Part 2, write to UART's THR
	for (i=0; i<count; i++) {
		// Wait unit TX ready
		while (!((CSR_status = UART_GET_CSR(base)) & AT91C_US_TXRDY));

		// copy buffer
		UART_PUT_CHAR(base, (tmpBuf[i] & 0xFF));

		// Wait unit TX empty
		while (!((CSR_status = UART_GET_CSR(base)) & AT91C_US_TXEMPTY));
	}

	spin_unlock_irqrestore(&sam_spinlock, flags);
	// SPIN Lock end

	// free kernel memory
	kfree(tmpBuf);
	return 0;
}
ambauart_rx_chars(struct uart_port *port, unsigned short status)
#endif
{
	struct tty_struct *tty = port->info->tty;
	unsigned short ch, lsr, max_count = 256;
	
	while (UART_RX_DATA(status) && max_count--) {
	    lsr = status;
		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
			tty->flip.tqueue.routine((void *)tty);
			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
				printk(KERN_WARNING "TTY_DONT_FLIP set\n");
				return;
			}
		}

		ch = UART_GET_CHAR(port);

		*tty->flip.char_buf_ptr = ch;
		*tty->flip.flag_buf_ptr = TTY_NORMAL;
		port->icount.rx++;

		/*
		 * Note that the error handling code is
		 * out of the main execution path
		 */
		lsr |= UART_DUMMY_LSR_RX;

		if (lsr & KS8695_UART_LINES_ANY) {
			if (lsr & KS8695_UART_LINES_BE) {
				lsr &= ~(KS8695_UART_LINES_FE | KS8695_UART_LINES_PE);
				port->icount.brk++;
				if (uart_handle_break(port))
					goto ignore_char;
			} else if (lsr & KS8695_UART_LINES_PE)
				port->icount.parity++;
			else if (lsr & KS8695_UART_LINES_FE)
				port->icount.frame++;
			if (lsr & KS8695_UART_LINES_OE)
				port->icount.overrun++;

			lsr &= port->read_status_mask;

			if (lsr & KS8695_UART_LINES_BE)
				*tty->flip.flag_buf_ptr = TTY_BREAK;
			else if (lsr & KS8695_UART_LINES_PE)
				*tty->flip.flag_buf_ptr = TTY_PARITY;
			else if (lsr & KS8695_UART_LINES_FE)
				*tty->flip.flag_buf_ptr = TTY_FRAME;
		}

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

		if ((lsr & port->ignore_status_mask) == 0) {
			tty->flip.flag_buf_ptr++;
			tty->flip.char_buf_ptr++;
			tty->flip.count++;
		}
		if ((lsr & KS8695_UART_LINES_OE) &&
		    tty->flip.count < TTY_FLIPBUF_SIZE) {
			/*
			 * Overrun is special, since it's reported
			 * immediately, and doesn't affect the current
			 * character
			 */
			*tty->flip.char_buf_ptr++ = 0;
			*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
			tty->flip.count++;
		}
	ignore_char:
		status = UART_GET_LSR(port);
	}
	tty_flip_buffer_push(tty);
	return;
}
Beispiel #22
0
leonuart_rx_chars(struct uart_port *port)
#endif
{
	struct tty_struct *tty = port->info->tty;
	unsigned int status, ch, flag, rsr, max_count = 256;

	status = UART_GET_STATUS(port);
	while (UART_RX_DATA(status) && max_count--) {

		//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.
			 */
		//}

		ch = UART_GET_CHAR(port);
		flag = TTY_NORMAL;

		port->icount.rx++;

		/*
		 * Note that the error handling code is
		 * out of the main execution path
		 */
		rsr = UART_GET_STATUS(port) | UART_DUMMY_RSR_RX;
		UART_PUT_STATUS(port, 0);
		if (rsr & LEON_USTAT_ERROR) {

			if (rsr & LEON_USTAT_BR) {
				rsr &= ~(LEON_USTAT_FE | LEON_USTAT_PE);
				port->icount.brk++;
				if (uart_handle_break(port))
					goto ignore_char;
			} else if (rsr & LEON_USTAT_PE) {
				port->icount.parity++;
			} else if (rsr & LEON_USTAT_FE) {
				port->icount.frame++;
			}
			if (rsr & LEON_USTAT_OV)
				port->icount.overrun++;

			rsr &= port->read_status_mask;

			if (rsr & LEON_USTAT_BR)
				flag = TTY_BREAK;
			else if (rsr & LEON_USTAT_PE)
				flag = TTY_PARITY;
			else if (rsr & LEON_USTAT_FE)
				flag = TTY_FRAME;
		}

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

		if ((rsr & port->ignore_status_mask) == 0) {
			tty_insert_flip_char(tty, ch, flag);
		}
		if (rsr & LEON_USTAT_OV) {
			/*
			 * 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:
		status = UART_GET_STATUS(port);
	}
	tty_flip_buffer_push(tty);
	return;
}
Beispiel #23
0
static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
{
	struct tty_struct *tty = NULL;
	unsigned int status, ch, flg;
	static struct timeval anomaly_start = { .tv_sec = 0 };

	status = UART_GET_LSR(uart);
	UART_CLEAR_LSR(uart);

 	ch = UART_GET_CHAR(uart);
 	uart->port.icount.rx++;

#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
	defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
	if (kgdb_connected && kgdboc_port_line == uart->port.line)
		if (ch == 0x3) {/* Ctrl + C */
			kgdb_breakpoint();
			return;
		}

	if (!uart->port.info || !uart->port.info->tty)
		return;
#endif
	tty = uart->port.info->tty;

	if (ANOMALY_05000363) {
		/* The BF533 (and BF561) family of processors have a nice anomaly
		 * where they continuously generate characters for a "single" break.
		 * We have to basically ignore this flood until the "next" valid
		 * character comes across.  Due to the nature of the flood, it is
		 * not possible to reliably catch bytes that are sent too quickly
		 * after this break.  So application code talking to the Blackfin
		 * which sends a break signal must allow at least 1.5 character
		 * times after the end of the break for things to stabilize.  This
		 * timeout was picked as it must absolutely be larger than 1
		 * character time +/- some percent.  So 1.5 sounds good.  All other
		 * Blackfin families operate properly.  Woo.
		 */
		if (anomaly_start.tv_sec) {
			struct timeval curr;
			suseconds_t usecs;

			if ((~ch & (~ch + 1)) & 0xff)
				goto known_good_char;

			do_gettimeofday(&curr);
			if (curr.tv_sec - anomaly_start.tv_sec > 1)
				goto known_good_char;

			usecs = 0;
			if (curr.tv_sec != anomaly_start.tv_sec)
				usecs += USEC_PER_SEC;
			usecs += curr.tv_usec - anomaly_start.tv_usec;

			if (usecs > UART_GET_ANOMALY_THRESHOLD(uart))
				goto known_good_char;

			if (ch)
				anomaly_start.tv_sec = 0;
			else
				anomaly_start = curr;

			return;

 known_good_char:
			status &= ~BI;
			anomaly_start.tv_sec = 0;
		}
	}

	if (status & BI) {
		if (ANOMALY_05000363)
			if (bfin_revid() < 5)
				do_gettimeofday(&anomaly_start);
		uart->port.icount.brk++;
		if (uart_handle_break(&uart->port))
			goto ignore_char;
		status &= ~(PE | FE);
	}
	if (status & PE)
		uart->port.icount.parity++;
	if (status & OE)
		uart->port.icount.overrun++;
	if (status & FE)
		uart->port.icount.frame++;

	status &= uart->port.read_status_mask;

	if (status & BI)
		flg = TTY_BREAK;
	else if (status & PE)
		flg = TTY_PARITY;
	else if (status & FE)
		flg = TTY_FRAME;
	else
		flg = TTY_NORMAL;

	if (uart_handle_sysrq_char(&uart->port, ch))
		goto ignore_char;

	uart_insert_char(&uart->port, status, OE, ch, flg);

 ignore_char:
	tty_flip_buffer_push(tty);
}

static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
{
	struct circ_buf *xmit = &uart->port.info->xmit;

	/*
	 * Check the modem control lines before
	 * transmitting anything.
	 */
	bfin_serial_mctrl_check(uart);

	if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
#ifdef CONFIG_BF54x
		/* Clear TFI bit */
		UART_PUT_LSR(uart, TFI);
#endif
		UART_CLEAR_IER(uart, ETBEI);
		return;
	}

	if (uart->port.x_char) {
		UART_PUT_CHAR(uart, uart->port.x_char);
		uart->port.icount.tx++;
		uart->port.x_char = 0;
	}

	while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) {
		UART_PUT_CHAR(uart, xmit->buf[xmit->tail]);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		uart->port.icount.tx++;
		SSYNC();
	}

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(&uart->port);
}

static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id)
{
	struct bfin_serial_port *uart = dev_id;

	spin_lock(&uart->port.lock);
	while (UART_GET_LSR(uart) & DR)
		bfin_serial_rx_chars(uart);
	spin_unlock(&uart->port.lock);

	return IRQ_HANDLED;
}

static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
{
	struct bfin_serial_port *uart = dev_id;

	spin_lock(&uart->port.lock);
	if (UART_GET_LSR(uart) & THRE)
		bfin_serial_tx_chars(uart);
	spin_unlock(&uart->port.lock);

	return IRQ_HANDLED;
}
#endif

#ifdef CONFIG_SERIAL_BFIN_DMA
static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
{
	struct circ_buf *xmit = &uart->port.info->xmit;

	uart->tx_done = 0;

	/*
	 * Check the modem control lines before
	 * transmitting anything.
	 */
	bfin_serial_mctrl_check(uart);

	if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
		uart->tx_count = 0;
		uart->tx_done = 1;
		return;
	}

	if (uart->port.x_char) {
		UART_PUT_CHAR(uart, uart->port.x_char);
		uart->port.icount.tx++;
		uart->port.x_char = 0;
	}

	uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
	if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail))
		uart->tx_count = UART_XMIT_SIZE - xmit->tail;
	blackfin_dcache_flush_range((unsigned long)(xmit->buf+xmit->tail),
					(unsigned long)(xmit->buf+xmit->tail+uart->tx_count));
	set_dma_config(uart->tx_dma_channel,
		set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP,
			INTR_ON_BUF,
			DIMENSION_LINEAR,
			DATA_SIZE_8,
			DMA_SYNC_RESTART));
	set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail));
	set_dma_x_count(uart->tx_dma_channel, uart->tx_count);
	set_dma_x_modify(uart->tx_dma_channel, 1);
	enable_dma(uart->tx_dma_channel);

	UART_SET_IER(uart, ETBEI);
}

static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
{
	struct tty_struct *tty = uart->port.info->port.tty;
	int i, flg, status;

	status = UART_GET_LSR(uart);
	UART_CLEAR_LSR(uart);

	uart->port.icount.rx +=
		CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail,
		UART_XMIT_SIZE);

	if (status & BI) {
		uart->port.icount.brk++;
		if (uart_handle_break(&uart->port))
			goto dma_ignore_char;
		status &= ~(PE | FE);
	}
	if (status & PE)
		uart->port.icount.parity++;
	if (status & OE)
		uart->port.icount.overrun++;
	if (status & FE)
		uart->port.icount.frame++;

	status &= uart->port.read_status_mask;

	if (status & BI)
		flg = TTY_BREAK;
	else if (status & PE)
		flg = TTY_PARITY;
	else if (status & FE)
		flg = TTY_FRAME;
	else
		flg = TTY_NORMAL;

	for (i = uart->rx_dma_buf.tail; i != uart->rx_dma_buf.head; i++) {
		if (i >= UART_XMIT_SIZE)
			i = 0;
		if (!uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i]))
			uart_insert_char(&uart->port, status, OE,
				uart->rx_dma_buf.buf[i], flg);
	}

 dma_ignore_char:
	tty_flip_buffer_push(tty);
}

void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
{
	int x_pos, pos, flags;

	spin_lock_irqsave(&uart->port.lock, flags);

	uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
	x_pos = get_dma_curr_xcount(uart->rx_dma_channel);
	uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows;
	if (uart->rx_dma_nrows == DMA_RX_YCOUNT)
		uart->rx_dma_nrows = 0;
	x_pos = DMA_RX_XCOUNT - x_pos;
	if (x_pos == DMA_RX_XCOUNT)
		x_pos = 0;

	pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos;
	if (pos != uart->rx_dma_buf.tail) {
		uart->rx_dma_buf.head = pos;
		bfin_serial_dma_rx_chars(uart);
		uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
	}

	spin_unlock_irqrestore(&uart->port.lock, flags);

	mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
}
omahauart_rx_chars(struct uart_info *info)
#endif
{
	struct tty_struct *tty = info->tty;
	volatile unsigned int status, data, ch, rsr, max_count = 256;
	struct uart_port *port = info->port;

	status = UART_FIFO_STATUS(port);
	while (UART_RX_DATA(status) && max_count--) {
		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
			tty->flip.tqueue.routine((void *)tty);
			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
				printk(KERN_WARNING "TTY_DONT_FLIP set\n");
				return;
			}
		}

		ch = UART_GET_CHAR(port);

		*tty->flip.char_buf_ptr = ch;
		*tty->flip.flag_buf_ptr = TTY_NORMAL;
		port->icount.rx++;

		/*
		 * Note that the error handling code is
		 * out of the main execution path
		 */
		rsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;
		if (rsr & 0xf) {
			if (rsr & OMAHA_UART_BREAK) {
				rsr &= ~(OMAHA_UART_FRAME | OMAHA_UART_PARITY);
				port->icount.brk++;
				if (uart_handle_break(info, &omaha_console))
					goto ignore_char;
			} else if (rsr & OMAHA_UART_PARITY)
				port->icount.parity++;
			else if (rsr & OMAHA_UART_FRAME)
				port->icount.frame++;
			if (rsr & OMAHA_UART_OVERRUN)
				port->icount.overrun++;

			rsr &= port->read_status_mask;

			if (rsr & OMAHA_UART_BREAK)
				*tty->flip.flag_buf_ptr = TTY_BREAK;
			else if (rsr & OMAHA_UART_PARITY)
				*tty->flip.flag_buf_ptr = TTY_PARITY;
			else if (rsr & OMAHA_UART_FRAME)
				*tty->flip.flag_buf_ptr = TTY_FRAME;
		}

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

		if ((rsr & port->ignore_status_mask) == 0) {
			tty->flip.flag_buf_ptr++;
			tty->flip.char_buf_ptr++;
			tty->flip.count++;
		}
		if ((rsr & OMAHA_UART_OVERRUN) &&
		    tty->flip.count < TTY_FLIPBUF_SIZE) {
			/*
			 * Overrun is special, since it's reported
			 * immediately, and doesn't affect the current
			 * character
			 */
			*tty->flip.char_buf_ptr++ = 0;
			*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
			tty->flip.count++;
		}
	ignore_char:
		status = UART_FIFO_STATUS(port);
	}
	tty_flip_buffer_push(tty);
	return;
}
Beispiel #25
0
static void
uart00_rx_chars(struct uart_port *port, struct pt_regs *regs)
{
	struct tty_struct *tty = port->info->tty;
	unsigned int status, ch, rds, flg, ignored = 0;

	status = UART_GET_RSR(port);
	while (UART_RX_DATA(status)) {
		/* 
		 * We need to read rds before reading the 
		 * character from the fifo
		 */
		rds = UART_GET_RDS(port);
		ch = UART_GET_CHAR(port);
		port->icount.rx++;

		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
			goto ignore_char;

		flg = TTY_NORMAL;

		/*
		 * Note that the error handling code is
		 * out of the main execution path
		 */
		if (rds & (UART_RDS_BI_MSK |UART_RDS_FE_MSK|
			   UART_RDS_PE_MSK |UART_RDS_PE_MSK))
			goto handle_error;
		if (uart_handle_sysrq_char(port, ch, regs))
			goto ignore_char;

	error_return:
		tty_insert_flip_char(tty, ch, flg);

	ignore_char:
		status = UART_GET_RSR(port);
	}
 out:
	tty_flip_buffer_push(tty);
	return;

 handle_error:
	if (rds & UART_RDS_BI_MSK) {
		status &= ~(UART_RDS_FE_MSK | UART_RDS_PE_MSK);
		port->icount.brk++;
		if (uart_handle_break(port))
			goto ignore_char;
	} else if (rds & UART_RDS_PE_MSK)
		port->icount.parity++;
	else if (rds & UART_RDS_FE_MSK)
		port->icount.frame++;
	if (rds & UART_RDS_OE_MSK)
		port->icount.overrun++;

	if (rds & port->ignore_status_mask) {
		if (++ignored > 100)
			goto out;
		goto ignore_char;
	}
	rds &= port->read_status_mask;

	if (rds & UART_RDS_BI_MSK)
		flg = TTY_BREAK;
	else if (rds & UART_RDS_PE_MSK)
		flg = TTY_PARITY;
	else if (rds & UART_RDS_FE_MSK)
		flg = TTY_FRAME;

	if (rds & UART_RDS_OE_MSK) {
		/*
		 * CHECK: does overrun affect the current character?
		 * ASSUMPTION: it does not.
		 */
		tty_insert_flip_char(tty, ch, flg);
		ch = 0;
		flg = TTY_OVERRUN;
	}
#ifdef SUPPORT_SYSRQ
	port->sysrq = 0;
#endif
	goto error_return;
}
Beispiel #26
0
leonuart_rx_chars(struct uart_port *port)
#endif
{
	struct tty_struct *tty = port->info->port.tty;
	unsigned int status, ch, rsr, flag;
	unsigned int max_chars = port->fifosize;

	status = UART_GET_STATUS(port);
	while (UART_RX_DATA(status) && (max_chars--)) {
		/*
		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
			tty->flip.work.func((void *)tty);
			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
				printk(KERN_WARNING "TTY_DONT_FLIP set\n");
				return;
			}
		}
		*/
		ch = UART_GET_CHAR(port);
		flag = TTY_NORMAL;
		
		/**tty->flip.char_buf_ptr = ch;
		*tty->flip.flag_buf_ptr = TTY_NORMAL;*/
		port->icount.rx++;

		/*
		 * Note that the error handling code is
		 * out of the main execution path
		 */
		rsr = UART_GET_STATUS(port) | UART_DUMMY_RSR_RX;
		UART_PUT_STATUS(port, 0);
		if (rsr & LEON_REG_UART_STATUS_ERR) {

			if (rsr & LEON_REG_UART_STATUS_BR) {
				rsr &=
				    ~(LEON_REG_UART_STATUS_FE |
				      LEON_REG_UART_STATUS_PE);
				port->icount.brk++;
				if (uart_handle_break(port))
					goto ignore_char;
			} else if (rsr & LEON_REG_UART_STATUS_PE) {
				port->icount.parity++;
			} else if (rsr & LEON_REG_UART_STATUS_FE) {
				port->icount.frame++;
			}
			if (rsr & LEON_REG_UART_STATUS_OE)
				port->icount.overrun++;

			rsr &= port->read_status_mask;
/*
			if (rsr & LEON_REG_UART_STATUS_PE)
				*tty->flip.flag_buf_ptr = TTY_PARITY;
			else if (rsr & LEON_REG_UART_STATUS_FE)
				*tty->flip.flag_buf_ptr = TTY_FRAME;
				*/
			if (rsr & LEON_REG_UART_STATUS_PE)
				flag = TTY_PARITY;
			else if (rsr & LEON_REG_UART_STATUS_FE)
				flag = TTY_FRAME;
		}

		if (uart_handle_sysrq_char(port, ch))
			goto ignore_char;
/*
		if ((rsr & port->ignore_status_mask) == 0) {
			tty->flip.flag_buf_ptr++;
			tty->flip.char_buf_ptr++;
			tty->flip.count++;
		}
		*/
		if ((rsr & port->ignore_status_mask) == 0) {
			tty_insert_flip_char(tty, ch, flag);
		}
		
		if ( rsr & LEON_REG_UART_STATUS_OE ) {
			/*
			 * 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:
		status = UART_GET_STATUS(port);
	}
	tty_flip_buffer_push(tty);
	return;
}
Beispiel #27
0
/*
 * Characters received (called from interrupt handler)
 */
static void atmel_rx_chars(struct uart_port *port)
{
	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
	struct tty_struct *tty = port->info->tty;
	unsigned int status, ch, flg;

	status = UART_GET_CSR(port);
	while (status & ATMEL_US_RXRDY) {
		ch = UART_GET_CHAR(port);

		port->icount.rx++;

		flg = TTY_NORMAL;

		/*
		 * note that the error handling code is
		 * out of the main execution path
		 */
		if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
				       | ATMEL_US_OVRE | ATMEL_US_RXBRK)
			     || atmel_port->break_active)) {
			UART_PUT_CR(port, ATMEL_US_RSTSTA);	/* clear error */
			if (status & ATMEL_US_RXBRK
			    && !atmel_port->break_active) {
				status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME);	/* ignore side-effect */
				port->icount.brk++;
				atmel_port->break_active = 1;
				UART_PUT_IER(port, ATMEL_US_RXBRK);
				if (uart_handle_break(port))
					goto ignore_char;
			} else {
				/*
				 * This is either the end-of-break
				 * condition or we've received at
				 * least one character without RXBRK
				 * being set. In both cases, the next
				 * RXBRK will indicate start-of-break.
				 */
				UART_PUT_IDR(port, ATMEL_US_RXBRK);
				status &= ~ATMEL_US_RXBRK;
				atmel_port->break_active = 0;
			}
			if (status & ATMEL_US_PARE)
				port->icount.parity++;
			if (status & ATMEL_US_FRAME)
				port->icount.frame++;
			if (status & ATMEL_US_OVRE)
				port->icount.overrun++;

			status &= port->read_status_mask;

			if (status & ATMEL_US_RXBRK)
				flg = TTY_BREAK;
			else if (status & ATMEL_US_PARE)
				flg = TTY_PARITY;
			else if (status & ATMEL_US_FRAME)
				flg = TTY_FRAME;
		}

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

		uart_insert_char(port, status, ATMEL_US_OVRE, ch, flg);

	ignore_char:
		status = UART_GET_CSR(port);
	}

	tty_flip_buffer_push(tty);
}
static void
sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
{
	struct tty_struct *tty = sport->port.info->tty;
	unsigned int status, ch, flg, ignored = 0;

	status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
		 UTSR0_TO_SM(UART_GET_UTSR0(sport));
	while (status & UTSR1_TO_SM(UTSR1_RNE)) {
		ch = UART_GET_CHAR(sport);

		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
			goto ignore_char;
		sport->port.icount.rx++;

		flg = TTY_NORMAL;

		/*
		 * note that the error handling code is
		 * out of the main execution path
		 */
		if (status & UTSR1_TO_SM(UTSR1_PRE | UTSR1_FRE | UTSR1_ROR))
			goto handle_error;

		if (uart_handle_sysrq_char(&sport->port, ch, regs))
			goto ignore_char;

	error_return:
		*tty->flip.flag_buf_ptr++ = flg;
		*tty->flip.char_buf_ptr++ = ch;
		tty->flip.count++;
	ignore_char:
		status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
			 UTSR0_TO_SM(UART_GET_UTSR0(sport));
	}
 out:
	tty_flip_buffer_push(tty);
	return;

 handle_error:
	if (status & UTSR1_TO_SM(UTSR1_PRE))
		sport->port.icount.parity++;
	else if (status & UTSR1_TO_SM(UTSR1_FRE))
		sport->port.icount.frame++;
	if (status & UTSR1_TO_SM(UTSR1_ROR))
		sport->port.icount.overrun++;

	if (status & sport->port.ignore_status_mask) {
		if (++ignored > 100)
			goto out;
		goto ignore_char;
	}

	status &= sport->port.read_status_mask;

	if (status & UTSR1_TO_SM(UTSR1_PRE))
		flg = TTY_PARITY;
	else if (status & UTSR1_TO_SM(UTSR1_FRE))
		flg = TTY_FRAME;

	if (status & UTSR1_TO_SM(UTSR1_ROR)) {
		/*
		 * overrun does *not* affect the character
		 * we read from the FIFO
		 */
		*tty->flip.flag_buf_ptr++ = flg;
		*tty->flip.char_buf_ptr++ = ch;
		tty->flip.count++;
		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
			goto ignore_char;
		ch = 0;
		flg = TTY_OVERRUN;
	}
#ifdef SUPPORT_SYSRQ
	sport->port.sysrq = 0;
#endif
	goto error_return;
}
Beispiel #29
0
static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
{
	struct tty_struct *tty = NULL;
	unsigned int status, ch, flg;
	static struct timeval anomaly_start = { .tv_sec = 0 };

	status = UART_GET_LSR(uart);
	UART_CLEAR_LSR(uart);

 	ch = UART_GET_CHAR(uart);
 	uart->port.icount.rx++;

#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
	defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
	if (kgdb_connected && kgdboc_port_line == uart->port.line
		&& kgdboc_break_enabled)
		if (ch == 0x3) {/* Ctrl + C */
			kgdb_breakpoint();
			return;
		}

	if (!uart->port.state || !uart->port.state->port.tty)
		return;
#endif
	tty = uart->port.state->port.tty;

	if (ANOMALY_05000363) {
		/* The BF533 (and BF561) family of processors have a nice anomaly
		 * where they continuously generate characters for a "single" break.
		 * We have to basically ignore this flood until the "next" valid
		 * character comes across.  Due to the nature of the flood, it is
		 * not possible to reliably catch bytes that are sent too quickly
		 * after this break.  So application code talking to the Blackfin
		 * which sends a break signal must allow at least 1.5 character
		 * times after the end of the break for things to stabilize.  This
		 * timeout was picked as it must absolutely be larger than 1
		 * character time +/- some percent.  So 1.5 sounds good.  All other
		 * Blackfin families operate properly.  Woo.
		 */
		if (anomaly_start.tv_sec) {
			struct timeval curr;
			suseconds_t usecs;

			if ((~ch & (~ch + 1)) & 0xff)
				goto known_good_char;

			do_gettimeofday(&curr);
			if (curr.tv_sec - anomaly_start.tv_sec > 1)
				goto known_good_char;

			usecs = 0;
			if (curr.tv_sec != anomaly_start.tv_sec)
				usecs += USEC_PER_SEC;
			usecs += curr.tv_usec - anomaly_start.tv_usec;

			if (usecs > UART_GET_ANOMALY_THRESHOLD(uart))
				goto known_good_char;

			if (ch)
				anomaly_start.tv_sec = 0;
			else
				anomaly_start = curr;

			return;

 known_good_char:
			status &= ~BI;
			anomaly_start.tv_sec = 0;
		}
	}

	if (status & BI) {
		if (ANOMALY_05000363)
			if (bfin_revid() < 5)
				do_gettimeofday(&anomaly_start);
		uart->port.icount.brk++;
		if (uart_handle_break(&uart->port))
			goto ignore_char;
		status &= ~(PE | FE);
	}
	if (status & PE)
		uart->port.icount.parity++;
	if (status & OE)
		uart->port.icount.overrun++;
	if (status & FE)
		uart->port.icount.frame++;

	status &= uart->port.read_status_mask;

	if (status & BI)
		flg = TTY_BREAK;
	else if (status & PE)
		flg = TTY_PARITY;
	else if (status & FE)
		flg = TTY_FRAME;
	else
		flg = TTY_NORMAL;

	if (uart_handle_sysrq_char(&uart->port, ch))
		goto ignore_char;

	uart_insert_char(&uart->port, status, OE, ch, flg);

 ignore_char:
	tty_flip_buffer_push(tty);
}

static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
{
	struct circ_buf *xmit = &uart->port.state->xmit;

	if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
#ifdef CONFIG_BF54x
		/* Clear TFI bit */
		UART_PUT_LSR(uart, TFI);
#endif
		/* Anomaly notes:
		 *  05000215 -	we always clear ETBEI within last UART TX
		 *		interrupt to end a string. It is always set
		 *		when start a new tx.
		 */
		UART_CLEAR_IER(uart, ETBEI);
		return;
	}

	if (uart->port.x_char) {
		UART_PUT_CHAR(uart, uart->port.x_char);
		uart->port.icount.tx++;
		uart->port.x_char = 0;
	}

	while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) {
		UART_PUT_CHAR(uart, xmit->buf[xmit->tail]);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		uart->port.icount.tx++;
	}

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(&uart->port);
}

static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id)
{
	struct bfin_serial_port *uart = dev_id;

	while (UART_GET_LSR(uart) & DR)
		bfin_serial_rx_chars(uart);

	return IRQ_HANDLED;
}

static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
{
	struct bfin_serial_port *uart = dev_id;

#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
	if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) {
		uart->scts = 0;
		uart_handle_cts_change(&uart->port, uart->scts);
	}
#endif
	spin_lock(&uart->port.lock);
	if (UART_GET_LSR(uart) & THRE)
		bfin_serial_tx_chars(uart);
	spin_unlock(&uart->port.lock);

	return IRQ_HANDLED;
}
#endif

#ifdef CONFIG_SERIAL_BFIN_DMA
static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
{
	struct circ_buf *xmit = &uart->port.state->xmit;

	uart->tx_done = 0;

	if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
		uart->tx_count = 0;
		uart->tx_done = 1;
		return;
	}

	if (uart->port.x_char) {
		UART_PUT_CHAR(uart, uart->port.x_char);
		uart->port.icount.tx++;
		uart->port.x_char = 0;
	}

	uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
	if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail))
		uart->tx_count = UART_XMIT_SIZE - xmit->tail;
	blackfin_dcache_flush_range((unsigned long)(xmit->buf+xmit->tail),
					(unsigned long)(xmit->buf+xmit->tail+uart->tx_count));
	set_dma_config(uart->tx_dma_channel,
		set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP,
			INTR_ON_BUF,
			DIMENSION_LINEAR,
			DATA_SIZE_8,
			DMA_SYNC_RESTART));
	set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail));
	set_dma_x_count(uart->tx_dma_channel, uart->tx_count);
	set_dma_x_modify(uart->tx_dma_channel, 1);
	SSYNC();
	enable_dma(uart->tx_dma_channel);

	UART_SET_IER(uart, ETBEI);
}

static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
{
	struct tty_struct *tty = uart->port.state->port.tty;
	int i, flg, status;

	status = UART_GET_LSR(uart);
	UART_CLEAR_LSR(uart);

	uart->port.icount.rx +=
		CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail,
		UART_XMIT_SIZE);

	if (status & BI) {
		uart->port.icount.brk++;
		if (uart_handle_break(&uart->port))
			goto dma_ignore_char;
		status &= ~(PE | FE);
	}
	if (status & PE)
		uart->port.icount.parity++;
	if (status & OE)
		uart->port.icount.overrun++;
	if (status & FE)
		uart->port.icount.frame++;

	status &= uart->port.read_status_mask;

	if (status & BI)
		flg = TTY_BREAK;
	else if (status & PE)
		flg = TTY_PARITY;
	else if (status & FE)
		flg = TTY_FRAME;
	else
		flg = TTY_NORMAL;

	for (i = uart->rx_dma_buf.tail; ; i++) {
		if (i >= UART_XMIT_SIZE)
			i = 0;
		if (i == uart->rx_dma_buf.head)
			break;
		if (!uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i]))
			uart_insert_char(&uart->port, status, OE,
				uart->rx_dma_buf.buf[i], flg);
	}

 dma_ignore_char:
	tty_flip_buffer_push(tty);
}

void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
{
	int x_pos, pos;

	dma_disable_irq_nosync(uart->rx_dma_channel);
	spin_lock_bh(&uart->rx_lock);

	/* 2D DMA RX buffer ring is used. Because curr_y_count and
	 * curr_x_count can't be read as an atomic operation,
	 * curr_y_count should be read before curr_x_count. When
	 * curr_x_count is read, curr_y_count may already indicate
	 * next buffer line. But, the position calculated here is
	 * still indicate the old line. The wrong position data may
	 * be smaller than current buffer tail, which cause garbages
	 * are received if it is not prohibit.
	 */
	uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
	x_pos = get_dma_curr_xcount(uart->rx_dma_channel);
	uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows;
	if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0)
		uart->rx_dma_nrows = 0;
	x_pos = DMA_RX_XCOUNT - x_pos;
	if (x_pos == DMA_RX_XCOUNT)
		x_pos = 0;

	pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos;
	/* Ignore receiving data if new position is in the same line of
	 * current buffer tail and small.
	 */
	if (pos > uart->rx_dma_buf.tail ||
		uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) {
		uart->rx_dma_buf.head = pos;
		bfin_serial_dma_rx_chars(uart);
		uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
	}

	spin_unlock_bh(&uart->rx_lock);
	dma_enable_irq(uart->rx_dma_channel);

	mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
}