Beispiel #1
0
static void bfin_sir_send_work(struct work_struct *work)
{
	struct bfin_sir_self  *self = container_of(work, struct bfin_sir_self, work);
	struct net_device *dev = self->sir_port->dev;
	struct bfin_sir_port *port = self->sir_port;
	unsigned short val;
	int tx_cnt = 10;

	while (bfin_sir_is_receiving(dev) && --tx_cnt)
		turnaround_delay(dev->last_rx, self->mtt);

	bfin_sir_stop_rx(port);

	/* To avoid losting RX interrupt, we reset IR function before
	 * sending data. We also can set the speed, which will
	 * reset all the UART.
	 */
	val = UART_GET_GCTL(port);
	val &= ~(IREN | RPOLC);
	UART_PUT_GCTL(port, val);
	SSYNC();
	val |= IREN | RPOLC;
	UART_PUT_GCTL(port, val);
	SSYNC();
	/* bfin_sir_set_speed(port, self->speed); */

#ifdef CONFIG_SIR_BFIN_DMA
	bfin_sir_dma_tx_chars(dev);
#endif
	bfin_sir_enable_tx(port);
	dev->trans_start = jiffies;
}
Beispiel #2
0
/*
 * Enable the IrDA function if tty->ldisc.num is N_IRDA.
 * In other cases, disable IrDA function.
 */
static void bfin_serial_set_ldisc(struct uart_port *port, int ld)
{
	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
	unsigned short val;

	switch (ld) {
	case N_IRDA:
		val = UART_GET_GCTL(uart);
		val |= (IREN | RPOLC);
		UART_PUT_GCTL(uart, val);
		break;
	default:
		val = UART_GET_GCTL(uart);
		val &= ~(IREN | RPOLC);
		UART_PUT_GCTL(uart, val);
	}
}
Beispiel #3
0
/*
 * Enable the IrDA function if tty->ldisc.num is N_IRDA.
 * In other cases, disable IrDA function.
 */
static void bfin_serial_set_ldisc(struct uart_port *port)
{
	int line = port->line;
	unsigned short val;

	if (line >= port->info->port.tty->driver->num)
		return;

	switch (port->info->port.tty->termios->c_line) {
	case N_IRDA:
		val = UART_GET_GCTL(&bfin_serial_ports[line]);
		val |= (IREN | RPOLC);
		UART_PUT_GCTL(&bfin_serial_ports[line], val);
		break;
	default:
		val = UART_GET_GCTL(&bfin_serial_ports[line]);
		val &= ~(IREN | RPOLC);
		UART_PUT_GCTL(&bfin_serial_ports[line], val);
	}
}
Beispiel #4
0
static void bfin_serial_reset_irda(struct uart_port *port)
{
	int line = port->line;
	unsigned short val;

	val = UART_GET_GCTL(&bfin_serial_ports[line]);
	val &= ~(IREN | RPOLC);
	UART_PUT_GCTL(&bfin_serial_ports[line], val);
	SSYNC();
	val |= (IREN | RPOLC);
	UART_PUT_GCTL(&bfin_serial_ports[line], val);
	SSYNC();
}
Beispiel #5
0
static void bfin_serial_reset_irda(struct uart_port *port)
{
	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
	unsigned short val;

	val = UART_GET_GCTL(uart);
	val &= ~(IREN | RPOLC);
	UART_PUT_GCTL(uart, val);
	SSYNC();
	val |= (IREN | RPOLC);
	UART_PUT_GCTL(uart, val);
	SSYNC();
}
Beispiel #6
0
static void bfin_sir_shutdown(struct bfin_sir_port *port, struct net_device *dev)
{
	unsigned short val;

	bfin_sir_stop_rx(port);

	val = UART_GET_GCTL(port);
	val &= ~(UCEN | IREN | RPOLC);
	UART_PUT_GCTL(port, val);

#ifdef CONFIG_SIR_BFIN_DMA
	disable_dma(port->tx_dma_channel);
	disable_dma(port->rx_dma_channel);
	del_timer(&(port->rx_dma_timer));
	dma_free_coherent(NULL, PAGE_SIZE, port->rx_dma_buf.buf, 0);
#else
	free_irq(port->irq+1, dev);
	free_irq(port->irq, dev);
#endif
	free_dma(port->tx_dma_channel);
	free_dma(port->rx_dma_channel);
}
Beispiel #7
0
static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed)
{
	int ret = -EINVAL;
	unsigned int quot;
	unsigned short val, lsr, lcr;
	static int utime;
	int count = 10;

	lcr = WLS(8);

	switch (speed) {
	case 9600:
	case 19200:
	case 38400:
	case 57600:
	case 115200:

		/*
		 * IRDA is not affected by anomaly 05000230, so there is no
		 * need to tweak the divisor like he UART driver (which will
		 * slightly speed up the baud rate on us).
		 */
		quot = (port->clk + (8 * speed)) / (16 * speed);

		do {
			udelay(utime);
			lsr = UART_GET_LSR(port);
		} while (!(lsr & TEMT) && count--);

		/* The useconds for 1 bits to transmit */
		utime = 1000000 / speed + 1;

		/* Clear UCEN bit to reset the UART state machine
		 * and control registers
		 */
		val = UART_GET_GCTL(port);
		val &= ~UCEN;
		UART_PUT_GCTL(port, val);

		/* Set DLAB in LCR to Access THR RBR IER */
		UART_SET_DLAB(port);
		SSYNC();

		UART_PUT_DLL(port, quot & 0xFF);
		UART_PUT_DLH(port, (quot >> 8) & 0xFF);
		SSYNC();

		/* Clear DLAB in LCR */
		UART_CLEAR_DLAB(port);
		SSYNC();

		UART_PUT_LCR(port, lcr);

		val = UART_GET_GCTL(port);
		val |= UCEN;
		UART_PUT_GCTL(port, val);

		ret = 0;
		break;
	default:
		printk(KERN_WARNING "bfin_sir: Invalid speed %d\n", speed);
		break;
	}

	val = UART_GET_GCTL(port);
	/* If not add the 'RPOLC', we can't catch the receive interrupt.
	 * It's related with the HW layout and the IR transiver.
	 */
	val |= IREN | RPOLC;
	UART_PUT_GCTL(port, val);
	return ret;
}
Beispiel #8
0
static void
bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
		   struct ktermios *old)
{
	struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
	unsigned long flags;
	unsigned int baud, quot;
	unsigned short val, ier, lcr = 0;

	switch (termios->c_cflag & CSIZE) {
	case CS8:
		lcr = WLS(8);
		break;
	case CS7:
		lcr = WLS(7);
		break;
	case CS6:
		lcr = WLS(6);
		break;
	case CS5:
		lcr = WLS(5);
		break;
	default:
		printk(KERN_ERR "%s: word lengh not supported\n",
			__func__);
	}

	if (termios->c_cflag & CSTOPB)
		lcr |= STB;
	if (termios->c_cflag & PARENB)
		lcr |= PEN;
	if (!(termios->c_cflag & PARODD))
		lcr |= EPS;
	if (termios->c_cflag & CMSPAR)
		lcr |= STP;

	port->read_status_mask = OE;
	if (termios->c_iflag & INPCK)
		port->read_status_mask |= (FE | PE);
	if (termios->c_iflag & (BRKINT | PARMRK))
		port->read_status_mask |= BI;

	/*
	 * Characters to ignore
	 */
	port->ignore_status_mask = 0;
	if (termios->c_iflag & IGNPAR)
		port->ignore_status_mask |= FE | PE;
	if (termios->c_iflag & IGNBRK) {
		port->ignore_status_mask |= BI;
		/*
		 * If we're ignoring parity and break indicators,
		 * ignore overruns too (for real raw support).
		 */
		if (termios->c_iflag & IGNPAR)
			port->ignore_status_mask |= OE;
	}

	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
	quot = uart_get_divisor(port, baud);
	spin_lock_irqsave(&uart->port.lock, flags);

	UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);

	/* Disable UART */
	ier = UART_GET_IER(uart);
	UART_DISABLE_INTS(uart);

	/* Set DLAB in LCR to Access DLL and DLH */
	UART_SET_DLAB(uart);

	UART_PUT_DLL(uart, quot & 0xFF);
	UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
	SSYNC();

	/* Clear DLAB in LCR to Access THR RBR IER */
	UART_CLEAR_DLAB(uart);

	UART_PUT_LCR(uart, lcr);

	/* Enable UART */
	UART_ENABLE_INTS(uart, ier);

	val = UART_GET_GCTL(uart);
	val |= UCEN;
	UART_PUT_GCTL(uart, val);

	/* Port speed changed, update the per-port timeout. */
	uart_update_timeout(port, termios->c_cflag, baud);

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