diff options
Diffstat (limited to 'drivers/tty/serial/mfd.c')
| -rw-r--r-- | drivers/tty/serial/mfd.c | 73 | 
1 files changed, 15 insertions, 58 deletions
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index d40010a22ec..c111f36f5d2 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c @@ -16,9 +16,7 @@   *    2/3 chan to port 1, 4/5 chan to port 3. Even number chans   *    are used for RX, odd chans for TX   * - * 2. In A0 stepping, UART will not support TX half empty flag - * - * 3. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always + * 2. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always   *    asserted, only when the HW is reset the DDCD and DDSR will   *    be triggered   */ @@ -41,8 +39,6 @@  #include <linux/io.h>  #include <linux/debugfs.h> -#define  MFD_HSU_A0_STEPPING	1 -  #define HSU_DMA_BUF_SIZE	2048  #define chan_readl(chan, offset)	readl(chan->reg + offset) @@ -51,7 +47,10 @@  #define mfd_readl(obj, offset)		readl(obj->reg + offset)  #define mfd_writel(obj, offset, val)	writel(val, obj->reg + offset) -#define HSU_DMA_TIMEOUT_CHECK_FREQ	(HZ/10) +static int hsu_dma_enable; +module_param(hsu_dma_enable, int, 0); +MODULE_PARM_DESC(hsu_dma_enable, "It is a bitmap to set working mode, if \ +bit[x] is 1, then port[x] will work in DMA mode, otherwise in PIO mode.");  struct hsu_dma_buffer {  	u8		*buf; @@ -65,7 +64,6 @@ struct hsu_dma_chan {  	enum dma_data_direction	dirt;  	struct uart_hsu_port	*uport;  	void __iomem		*reg; -	struct timer_list	rx_timer; /* only needed by RX channel */  };  struct uart_hsu_port { @@ -355,8 +353,6 @@ void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf  					 | (0x1 << 24)	/* timeout bit, see HSU Errata 1 */  					 );  	chan_writel(rxc, HSU_CH_CR, 0x3); - -	mod_timer(&rxc->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ);  }  /* Protected by spin_lock_irqsave(port->lock) */ @@ -420,7 +416,6 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts)  		chan_writel(chan, HSU_CH_CR, 0x3);  		return;  	} -	del_timer(&chan->rx_timer);  	dma_sync_single_for_cpu(port->dev, dbuf->dma_addr,  			dbuf->dma_size, DMA_FROM_DEVICE); @@ -448,8 +443,6 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts)  	tty_flip_buffer_push(tty);  	chan_writel(chan, HSU_CH_CR, 0x3); -	chan->rx_timer.expires = jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ; -	add_timer(&chan->rx_timer);  } @@ -551,16 +544,9 @@ static void transmit_chars(struct uart_hsu_port *up)  		return;  	} -#ifndef MFD_HSU_A0_STEPPING +	/* The IRQ is for TX FIFO half-empty */  	count = up->port.fifosize / 2; -#else -	/* -	 * A0 only supports fully empty IRQ, and the first char written -	 * into it won't clear the EMPT bit, so we may need be cautious -	 * by useing a shorter buffer -	 */ -	count = up->port.fifosize - 4; -#endif +  	do {  		serial_out(up, UART_TX, xmit->buf[xmit->tail]);  		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); @@ -769,9 +755,8 @@ static void serial_hsu_break_ctl(struct uart_port *port, int break_state)  /*   * What special to do:   * 1. chose the 64B fifo mode - * 2. make sure not to select half empty mode for A0 stepping - * 3. start dma or pio depends on configuration - * 4. we only allocate dma memory when needed + * 2. start dma or pio depends on configuration + * 3. we only allocate dma memory when needed   */  static int serial_hsu_startup(struct uart_port *port)  { @@ -870,8 +855,6 @@ static void serial_hsu_shutdown(struct uart_port *port)  		container_of(port, struct uart_hsu_port, port);  	unsigned long flags; -	del_timer_sync(&up->rxc->rx_timer); -  	/* Disable interrupts from this port */  	up->ier = 0;  	serial_out(up, UART_IER, 0); @@ -977,10 +960,6 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,  		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B;  	fcr |= UART_FCR_HSU_64B_FIFO; -#ifdef MFD_HSU_A0_STEPPING -	/* A0 doesn't support half empty IRQ */ -	fcr |= UART_FCR_FULL_EMPT_TXI; -#endif  	/*  	 * Ok, we're now changing the port state.  Do it with @@ -1343,28 +1322,6 @@ err_disable:  	return ret;  } -static void hsu_dma_rx_timeout(unsigned long data) -{ -	struct hsu_dma_chan *chan = (void *)data; -	struct uart_hsu_port *up = chan->uport; -	struct hsu_dma_buffer *dbuf = &up->rxbuf; -	int count = 0; -	unsigned long flags; - -	spin_lock_irqsave(&up->port.lock, flags); - -	count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr; - -	if (!count) { -		mod_timer(&chan->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ); -		goto exit; -	} - -	hsu_dma_rx(up, 0); -exit: -	spin_unlock_irqrestore(&up->port.lock, flags); -} -  static void hsu_global_init(void)  {  	struct hsu_port *hsu; @@ -1415,6 +1372,12 @@ static void hsu_global_init(void)  		serial_hsu_ports[i] = uport;  		uport->index = i; + +		if (hsu_dma_enable & (1<<i)) +			uport->use_dma = 1; +		else +			uport->use_dma = 0; +  		uport++;  	} @@ -1427,12 +1390,6 @@ static void hsu_global_init(void)  		dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET +  				i * HSU_DMA_CHANS_REG_LENGTH; -		/* Work around for RX */ -		if (dchan->dirt == DMA_FROM_DEVICE) { -			init_timer(&dchan->rx_timer); -			dchan->rx_timer.function = hsu_dma_rx_timeout; -			dchan->rx_timer.data = (unsigned long)dchan; -		}  		dchan++;  	}  |