示例#1
0
static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id, struct pt_regs *regs)
{
	struct s3c24xx_uart_port *ourport = id;
	struct uart_port *port = &ourport->port;
	struct circ_buf *xmit = &port->info->xmit;
	int count = 256;

	if (port->x_char) {
		wr_regb(port, S3C2410_UTXH, port->x_char);
		port->icount.tx++;
		port->x_char = 0;
		goto out;
	}

	/* if there isnt anything more to transmit, or the uart is now
	 * stopped, disable the uart and exit
	*/

	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
		s3c24xx_serial_stop_tx(port, 0);
		goto out;
	}

	/* try and drain the buffer... */

	while (!uart_circ_empty(xmit) && count-- > 0) {
		if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
			break;

		wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		port->icount.tx++;
	}

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);

	if (uart_circ_empty(xmit))
		s3c24xx_serial_stop_tx(port, 0);

 out:
	return IRQ_HANDLED;
}
示例#2
0
static void tegra_uart_tx_dma_complete(void *args)
{
	struct tegra_uart_port *tup = args;
	struct circ_buf *xmit = &tup->uport.state->xmit;
	struct dma_tx_state state;
	unsigned long flags;
	unsigned int count;

	dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state);
	count = tup->tx_bytes_requested - state.residue;
	async_tx_ack(tup->tx_dma_desc);
	spin_lock_irqsave(&tup->uport.lock, flags);
	xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
	tup->tx_in_progress = 0;
	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(&tup->uport);
	tegra_uart_start_next_tx(tup);
	spin_unlock_irqrestore(&tup->uport.lock, flags);
}
示例#3
0
/**
 * xuartps_start_tx -  Start transmitting bytes
 * @port: Handle to the uart port structure
 *
 **/
static void xuartps_start_tx(struct uart_port *port)
{
    unsigned int status, numbytes = port->fifosize;

    if (uart_circ_empty(&port->state->xmit) || uart_tx_stopped(port))
        return;

    status = xuartps_readl(XUARTPS_CR_OFFSET);
    /* Set the TX enable bit and clear the TX disable bit to enable the
     * transmitter.
     */
    xuartps_writel((status & ~XUARTPS_CR_TX_DIS) | XUARTPS_CR_TX_EN,
                   XUARTPS_CR_OFFSET);

    while (numbytes-- && ((xuartps_readl(XUARTPS_SR_OFFSET)
                           & XUARTPS_SR_TXFULL)) != XUARTPS_SR_TXFULL) {

        /* Break if no more data available in the UART buffer */
        if (uart_circ_empty(&port->state->xmit))
            break;

        /* Get the data from the UART circular buffer and
         * write it to the xuartps's TX_FIFO register.
         */
        xuartps_writel(
            port->state->xmit.buf[port->state->xmit.tail],
            XUARTPS_FIFO_OFFSET);
        port->icount.tx++;

        /* Adjust the tail of the UART buffer and wrap
         * the buffer if it reaches limit.
         */
        port->state->xmit.tail = (port->state->xmit.tail + 1) &
                                 (UART_XMIT_SIZE - 1);
    }

    /* Enable the TX Empty interrupt */
    xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_IER_OFFSET);

    if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS)
        uart_write_wakeup(port);
}
示例#4
0
static inline void imx_transmit_buffer(struct imx_port *sport)
{
	struct circ_buf *xmit = &sport->port.state->xmit;

	while (!(readl(sport->port.membase + UTS) & UTS_TXFULL)) {
		/* send xmit->buf[xmit->tail]
		 * out the port here */
		writel(xmit->buf[xmit->tail], sport->port.membase + URTX0);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		sport->port.icount.tx++;
		if (uart_circ_empty(xmit))
			break;
	}

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

	if (uart_circ_empty(xmit))
		imx_stop_tx(&sport->port);
}
示例#5
0
static void sirfsoc_uart_tx_dma_complete_callback(void *param)
{
	struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param;
	struct uart_port *port = &sirfport->port;
	struct circ_buf *xmit = &port->state->xmit;
	unsigned long flags;

	spin_lock_irqsave(&port->lock, flags);
	xmit->tail = (xmit->tail + sirfport->transfer_size) &
				(UART_XMIT_SIZE - 1);
	port->icount.tx += sirfport->transfer_size;
	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);
	if (sirfport->tx_dma_addr)
		dma_unmap_single(port->dev, sirfport->tx_dma_addr,
				sirfport->transfer_size, DMA_TO_DEVICE);
	sirfport->tx_dma_state = TX_DMA_IDLE;
	sirfsoc_uart_tx_with_dma(sirfport);
	spin_unlock_irqrestore(&port->lock, flags);
}
示例#6
0
static void parrot5_serial_tx_chars(struct uart_port *port, u32 status)
{
	int count;
	struct circ_buf *xmit = &port->info->xmit;
	struct uart_parrot5_port *up = (struct uart_parrot5_port *)port;

	if (port->x_char) {
		__raw_writel(port->x_char, port->membase+_UART_TRX);
		port->icount.tx++;
		port->x_char = 0;
		goto out;
	}
	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
		parrot5_serial_stop_tx(port);
		goto out;
	}

	count = up->tx_fifosize;

	/* on Parrot5+ chips TX fifo has a configurable IRQ threshold */
	if (up->tx_threshold && (status & UART_STATUS_TXFILLED)) {
		count -= up->tx_threshold;
	}

	while (!uart_circ_empty(xmit) && (count-- > 0)) {

		__raw_writel(xmit->buf[xmit->tail], port->membase+_UART_TRX);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		port->icount.tx++;
	}

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
		uart_write_wakeup(port);
	}
	if (uart_circ_empty(xmit)) {
		parrot5_serial_stop_tx(port);
	}

out:
	return;
}
示例#7
0
static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
{
	struct s3c24xx_uart_port *ourport = id;
	struct uart_port *port = &ourport->port;
	struct circ_buf *xmit = &port->state->xmit;
	int count = 256;

	if (port->x_char) {
		wr_regb(port, S3C2410_UTXH, port->x_char);
		port->icount.tx++;
		port->x_char = 0;
		goto out;
	}

	

	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
		s3c24xx_serial_stop_tx(port);
		goto out;
	}

	

	while (!uart_circ_empty(xmit) && count-- > 0) {
		if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
			break;

		wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		port->icount.tx++;
	}

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);

	if (uart_circ_empty(xmit))
		s3c24xx_serial_stop_tx(port);

 out:
	return IRQ_HANDLED;
}
示例#8
0
static void transmit_chars(struct uart_omap_port *up)
{
	struct circ_buf *xmit = &up->port.state->xmit;
	int count;

	if (up->port.x_char) {
		serial_out(up, UART_TX, up->port.x_char);
		up->port.icount.tx++;
		up->port.x_char = 0;
		return;
	}
	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
		serial_omap_stop_tx(&up->port);
		return;
	}
	count = up->port.fifosize / 4;
	do {
#if defined(CONFIG_KEYBOARD_P1)
		if(!((up->port.line == 2)&&g_keyboard))
#endif
		{
		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
		}
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		up->port.icount.tx++;
		if (uart_circ_empty(xmit)) {
			/* This wake lock has to moved out to use case drivers
			 * which require these.
			 */
			if (up->plat_hold_wakelock)
				(up->plat_hold_wakelock(up, WAKELK_TX));
			break;
		}
	} while (--count > 0);

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

	if (uart_circ_empty(xmit))
		serial_omap_stop_tx(&up->port);
}
示例#9
0
文件: mfd.c 项目: ANFS/ANFS-kernel
static void transmit_chars(struct uart_hsu_port *up)
{
	struct circ_buf *xmit = &up->port.state->xmit;
	int count;

	if (up->port.x_char) {
		serial_out(up, UART_TX, up->port.x_char);
		up->port.icount.tx++;
		up->port.x_char = 0;
		return;
	}
	if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
		serial_hsu_stop_tx(&up->port);
		return;
	}

#ifndef MFD_HSU_A0_STEPPING
	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);

		up->port.icount.tx++;
		if (uart_circ_empty(xmit))
			break;
	} while (--count > 0);

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

	if (uart_circ_empty(xmit))
		serial_hsu_stop_tx(&up->port);
}
示例#10
0
static void sw_uart_handle_tx(struct sw_uart_port *sw_uport)
{
	struct circ_buf *xmit = &sw_uport->port.state->xmit;
	int count;

	if (sw_uport->port.x_char) {
		serial_out(&sw_uport->port, sw_uport->port.x_char, SW_UART_THR);
		sw_uport->port.icount.tx++;
		sw_uport->port.x_char = 0;
#ifdef CONFIG_SW_UART_DUMP_DATA
		sw_uport->dump_buff[sw_uport->dump_len++] = sw_uport->port.x_char;
		SERIAL_DUMP(sw_uport, "Tx");
#endif
		return;
	}
	if (uart_circ_empty(xmit) || uart_tx_stopped(&sw_uport->port)) {
		sw_uart_stop_tx(&sw_uport->port);
		return;
	}
	count = sw_uport->port.fifosize / 2;
	do {
#ifdef CONFIG_SW_UART_DUMP_DATA
		sw_uport->dump_buff[sw_uport->dump_len++] = xmit->buf[xmit->tail];
#endif
		serial_out(&sw_uport->port, xmit->buf[xmit->tail], SW_UART_THR);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		sw_uport->port.icount.tx++;
		if (uart_circ_empty(xmit)) {
			break;
		}
	} while (--count > 0);

	SERIAL_DUMP(sw_uport, "Tx");
	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
		spin_unlock(&sw_uport->port.lock);
		uart_write_wakeup(&sw_uport->port);
		spin_lock(&sw_uport->port.lock);
	}
	if (uart_circ_empty(xmit))
		sw_uart_stop_tx(&sw_uport->port);
}
static void __dma_tx_complete(void *param)
{
	struct uart_8250_port	*p = param;
	struct uart_8250_dma	*dma = p->dma;
	struct circ_buf		*xmit = &p->port.state->xmit;

	dma->tx_running = 0;

	dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
				UART_XMIT_SIZE, DMA_TO_DEVICE);

	xmit->tail += dma->tx_size;
	xmit->tail &= UART_XMIT_SIZE - 1;
	p->port.icount.tx += dma->tx_size;

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

	if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port))
		serial8250_tx_dma(p);
}
示例#12
0
static void milkymist_uart_tx_char(struct uart_port *port)
{
	struct circ_buf *xmit = &port->state->xmit;

	if (port->x_char) {
		iowrite32be(port->x_char, port->membase + UART_RXTX);
		port->x_char = 0;
		port->icount.tx++;
		return;
	}

	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
		return;

	iowrite32be(xmit->buf[xmit->tail], port->membase + UART_RXTX);
	xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
	port->icount.tx++;

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);
}
示例#13
0
static void tegra_tx_dma_complete_callback(struct tegra_dma_req *req)
{
	struct tegra_uart_port *t = req->dev;
	struct circ_buf *xmit = &t->uport.state->xmit;
	int count = req->bytes_transferred;
	unsigned long flags;

	dev_vdbg(t->uport.dev, "%s: %d\n", __func__, count);

	spin_lock_irqsave(&t->uport.lock, flags);
	xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
	t->tx_in_progress = 0;

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(&t->uport);

	if (req->status != -TEGRA_DMA_REQ_ERROR_ABORTED)
		tegra_start_next_tx(t);

	spin_unlock_irqrestore(&t->uport.lock, flags);
}
示例#14
0
/* 
 * Kick the Tx side.
 * The port lock is held and interrupts are disabled.
 */
static void pmz_start_tx(struct uart_port *port)
{
	struct uart_pmac_port *uap = to_pmz(port);
	unsigned char status;

	pmz_debug("pmz: start_tx()\n");

	uap->flags |= PMACZILOG_FLAG_TX_ACTIVE;
	uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED;

	if (ZS_IS_ASLEEP(uap) || uap->node == NULL)
		return;

	status = read_zsreg(uap, R0);

	/* TX busy?  Just wait for the TX done interrupt.  */
	if (!(status & Tx_BUF_EMP))
		return;

	/* Send the first character to jump-start the TX done
	 * IRQ sending engine.
	 */
	if (port->x_char) {
		write_zsdata(uap, port->x_char);
		zssync(uap);
		port->icount.tx++;
		port->x_char = 0;
	} else {
		struct circ_buf *xmit = &port->info->xmit;

		write_zsdata(uap, xmit->buf[xmit->tail]);
		zssync(uap);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		port->icount.tx++;

		if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
			uart_write_wakeup(&uap->port);
	}
	pmz_debug("pmz: start_tx() done.\n");
}
示例#15
0
static void sa1100_tx_chars(struct sa1100_port *sport)
{
	struct circ_buf *xmit = &sport->port.state->xmit;

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

	/*
	 * Check the modem control lines before
	 * transmitting anything.
	 */
	sa1100_mctrl_check(sport);

	if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
		sa1100_stop_tx(&sport->port);
		return;
	}

	/*
	 * Tried using FIFO (not checking TNF) for fifo fill:
	 * still had the '4 bytes repeated' problem.
	 */
	while (UART_GET_UTSR1(sport) & UTSR1_TNF) {
		UART_PUT_CHAR(sport, xmit->buf[xmit->tail]);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		sport->port.icount.tx++;
		if (uart_circ_empty(xmit))
			break;
	}

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

	if (uart_circ_empty(xmit))
		sa1100_stop_tx(&sport->port);
}
示例#16
0
static void btlinux_start_tx(struct uart_port *port /*, unsigned int tty_start*/)
{
	struct circ_buf *xmit = &port->info->xmit;
	struct uart_btlinux_port *up = (struct uart_btlinux_port *)port;
	int c, count, d;
	unsigned char *buf;
	count = uart_circ_chars_pending(xmit);

	/*    dbg("line %d - buf size = %d", port->line, uart_circ_chars_pending(xmit));*/
	/*    printk("btlinux_start_tx: line %d port %x\n", port->line, up);*/

	if (!up->port_opened) {
		err("start_tx - port is not opened");
		return;
	}

	if (!up->is_open) {
		err("start_tx - bt port is not opened");
		btlinux_stop_tx(port/*, 0*/);
		return;
	}
	if (port->x_char) {
		info("x_char is transmitted");
		port->icount.tx++;
		port->x_char = 0;
		return;
	}

	if (uart_circ_empty(xmit) || uart_tx_stopped(port))  {
		info("tx buffer empty or tx stopped");
		btlinux_stop_tx(port/*, 0*/);
		return;
	}

	send_tx_char(up);

	/* wake up application waiting in a poll */
	wake_up_interruptible(&up->rx_wait_q);

}
static void ip3106_tx_chars(struct ip3106_port *sport)
{
	struct circ_buf *xmit = &sport->port.info->xmit;

	if (sport->port.x_char) {
		serial_out(sport, IP3106_FIFO, sport->port.x_char);
		sport->port.icount.tx++;
		sport->port.x_char = 0;
		return;
	}

	/*
	 * Check the modem control lines before
	 * transmitting anything.
	 */
	ip3106_mctrl_check(sport);

	if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) {
		ip3106_stop_tx(&sport->port, 0);
		return;
	}

	/*
	 * TX while bytes available
	 */
	while (((serial_in(sport, IP3106_FIFO) &
					IP3106_UART_FIFO_TXFIFO) >> 16) < 16) {
		serial_out(sport, IP3106_FIFO, xmit->buf[xmit->tail]);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		sport->port.icount.tx++;
		if (uart_circ_empty(xmit))
			break;
	}

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

	if (uart_circ_empty(xmit))
		ip3106_stop_tx(&sport->port, 0);
}
示例#18
0
static void handle_tx(struct uart_port *port)
{
	struct circ_buf *xmit = &port->state->xmit;
	struct msm_port *msm_port = UART_TO_MSM(port);
	int sent_tx;

	if (port->x_char) {
		if (msm_port->is_uartdm)
			reset_dm_count(port);

		msm_write(port, port->x_char,
			  msm_port->is_uartdm ? UARTDM_TF : UART_TF);
		port->icount.tx++;
		port->x_char = 0;
	}

	if (msm_port->is_uartdm)
		reset_dm_count(port);

	while (msm_read(port, UART_SR) & UART_SR_TX_READY) {
		if (uart_circ_empty(xmit)) {
			/* disable tx interrupts */
			msm_port->imr &= ~UART_IMR_TXLEV;
			msm_write(port, msm_port->imr, UART_IMR);
			break;
		}
		msm_write(port, xmit->buf[xmit->tail],
			  msm_port->is_uartdm ? UARTDM_TF : UART_TF);

		if (msm_port->is_uartdm)
			reset_dm_count(port);

		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		port->icount.tx++;
		sent_tx = 1;
	}

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);
}
示例#19
0
/* The port lock is held and interrupts are disabled.  */
static void ip22zilog_start_tx(struct uart_port *port)
{
	struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port;
	struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port);
	unsigned char status;

	up->flags |= IP22ZILOG_FLAG_TX_ACTIVE;
	up->flags &= ~IP22ZILOG_FLAG_TX_STOPPED;

	status = readb(&channel->control);
	ZSDELAY();

	/* TX busy?  Just wait for the TX done interrupt.  */
	if (!(status & Tx_BUF_EMP))
		return;

	/* Send the first character to jump-start the TX done
	 * IRQ sending engine.
	 */
	if (port->x_char) {
		writeb(port->x_char, &channel->data);
		ZSDELAY();
		ZS_WSYNC(channel);

		port->icount.tx++;
		port->x_char = 0;
	} else {
		struct circ_buf *xmit = &port->state->xmit;

		writeb(xmit->buf[xmit->tail], &channel->data);
		ZSDELAY();
		ZS_WSYNC(channel);

		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		port->icount.tx++;

		if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
			uart_write_wakeup(&up->port);
	}
}
示例#20
0
static bool ntv2_serial_transmit(struct ntv2_serial *ntv2_ser)
{
	struct uart_port *port = &ntv2_ser->uart_port;
	struct circ_buf *xmit  = &port->state->xmit;
	u32 full = NTV2_FLD_MASK(ntv2_kona_fld_serial_tx_full);
	u32 status;

	status = ntv2_reg_read(ntv2_ser->vid_reg, ntv2_kona_reg_serial_status, ntv2_ser->index);
	if (status & full)
		return false;

	/* tx xon/xoff */
	if ((port->x_char) != 0) {
		NTV2_MSG_SERIAL_STREAM("%s: uart tx %02x\n", ntv2_ser->name, (u8)port->x_char);
		ntv2_reg_write(ntv2_ser->vid_reg,
					   ntv2_kona_reg_serial_tx, ntv2_ser->index,
					   (u32)port->x_char);
		port->x_char = 0;
		port->icount.tx++;
		return true;
	}

	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
		return false;

	/* tx data */
	NTV2_MSG_SERIAL_STREAM("%s: uart tx %02x\n", ntv2_ser->name, (u8)xmit->buf[xmit->tail]);
	ntv2_reg_write(ntv2_ser->vid_reg,
				   ntv2_kona_reg_serial_tx, ntv2_ser->index,
				   (u32)xmit->buf[xmit->tail]);
	xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
	port->icount.tx++;

	/* wake up */
	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);

	return true;
}
示例#21
0
static unsigned int
sirfsoc_uart_pio_tx_chars(struct sirfsoc_uart_port *sirfport, int count)
{
	struct uart_port *port = &sirfport->port;
	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
	struct sirfsoc_fifo_status *ufifo_st = &sirfport->uart_reg->fifo_status;
	struct circ_buf *xmit = &port->state->xmit;
	unsigned int num_tx = 0;
	while (!uart_circ_empty(xmit) &&
		!(rd_regl(port, ureg->sirfsoc_tx_fifo_status) &
					ufifo_st->ff_full(port->line)) &&
		count--) {
		wr_regl(port, ureg->sirfsoc_tx_fifo_data,
				xmit->buf[xmit->tail]);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		port->icount.tx++;
		num_tx++;
	}
	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);
	return num_tx;
}
示例#22
0
文件: dz.c 项目: ivucica/linux
/*
 * ------------------------------------------------------------
 * transmit_char ()
 *
 * This routine deals with outputs to any lines.
 * ------------------------------------------------------------
 */
static inline void dz_transmit_chars(struct dz_port *dport_in)
{
	struct dz_port *dport;
	struct circ_buf *xmit;
	unsigned short status;
	unsigned char tmp;

	status = dz_in(dport_in, DZ_CSR);
	dport = &dz_ports[LINE(status)];
	xmit = &dport->port.info->xmit;

	if (dport->port.x_char) {		/* XON/XOFF chars */
		dz_out(dport, DZ_TDR, dport->port.x_char);
		dport->port.icount.tx++;
		dport->port.x_char = 0;
		return;
	}
	/* If nothing to do or stopped or hardware stopped. */
	if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) {
		dz_stop_tx(&dport->port);
		return;
	}

	/*
	 * If something to do... (remember the dz has no output fifo,
	 * so we go one char at a time) :-<
	 */
	tmp = xmit->buf[xmit->tail];
	xmit->tail = (xmit->tail + 1) & (DZ_XMIT_SIZE - 1);
	dz_out(dport, DZ_TDR, tmp);
	dport->port.icount.tx++;

	if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS)
		uart_write_wakeup(&dport->port);

	/* Are we are done. */
	if (uart_circ_empty(xmit))
		dz_stop_tx(&dport->port);
}
示例#23
0
static void l4ser_shm_tx_chars(struct uart_port *port)
{
	struct l4ser_shm_uart_port *l4port = (struct l4ser_shm_uart_port *)port;
	struct circ_buf *xmit = &port->state->xmit;
	int c, do_trigger = 0;

	struct tty_struct *tty = port->state->port.tty;
	tty->hw_stopped = 0;
	tty->stopped = 0;

	if (port->x_char) {
		if (tx_buf(port, &port->x_char, 1)) {
			port->icount.tx++;
			port->x_char = 0;
			L4XV_FN_v(l4shmc_trigger(&l4port->tx_sig));
		}
		return;
	}

	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
		return;
	}

	while (!uart_circ_empty(xmit)) {
		unsigned long r;
		c = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
		if (!(r = tx_buf(port, &xmit->buf[xmit->tail], c)))
			break;
		xmit->tail = (xmit->tail + r) & (UART_XMIT_SIZE - 1);
		port->icount.tx += r;
		do_trigger = 1;
	}

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);

	if (do_trigger)
		L4XV_FN_v(l4shmc_trigger(&l4port->tx_sig));
}
示例#24
0
static void s3c2440_tx_int(int irq, void *dev_id, struct pt_regs *regs)
{
	struct uart_info *info = (struct uart_info*)dev_id;
	struct uart_port *port = info->port;
	struct circ_buf *xmit = &info->xmit;
	int count;

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

	/*
	 * Check the modem control lines before
	 * transmitting anything.
	 */

	if (uart_circ_empty(xmit) || uart_tx_stopped(info)) {
		s3c2440_stop_tx(port, 0);
		return;
	}

	count = port->fifosize >> 1;
	do {
		UART_PUT_CHAR (port, xmit->buf[xmit->tail]);
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		port->icount.tx++;
		if (xmit->head == xmit->tail)
			break;
	} while (--count > 0);

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		tasklet_schedule(&info->tlet);

	if (uart_circ_empty(xmit))
		s3c2440_stop_tx(port, 0);
}
示例#25
0
static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
{
	struct bfin_serial_port *uart = dev_id;
	struct circ_buf *xmit = &uart->port.info->xmit;

	spin_lock(&uart->port.lock);
	if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
		disable_dma(uart->tx_dma_channel);
		clear_dma_irqstat(uart->tx_dma_channel);
		UART_CLEAR_IER(uart, ETBEI);
		xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1);
		uart->port.icount.tx += uart->tx_count;

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

		bfin_serial_dma_tx_chars(uart);
	}

	spin_unlock(&uart->port.lock);
	return IRQ_HANDLED;
}
示例#26
0
static void transmit_chars(struct am_uart_port *info)
{
    am_uart_t *uart = uart_addr[info->line];
    struct uart_port * up = &info->port;
    unsigned int ch;
    struct circ_buf *xmit = &up->state->xmit;
    int count = 256;

    if (up->x_char) {
        writel(up->x_char, &uart->wdata);
        up->x_char = 0;
        goto clear_and_return;
    }

    if (uart_circ_empty(xmit) || uart_tx_stopped(up))
        goto clear_and_return;

    spin_lock(&info->wr_lock);
    while(!uart_circ_empty(xmit) && count-- > 0)
    {
        if((readl(&uart->status) & UART_TXFULL) ==0) {
            ch = xmit->buf[xmit->tail];
            writel(ch, &uart->wdata);
            xmit->tail = (xmit->tail+1) & (SERIAL_XMIT_SIZE - 1);
        }
	 else
	 {
		break;
	 }
    }
    spin_unlock(&info->wr_lock);
clear_and_return:

    if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(up);

    return;
}
示例#27
0
static void handle_tx(struct uart_port *port)
{
	struct circ_buf *xmit = &port->info->xmit;
	struct msm_port *msm_port = UART_TO_MSM(port);
	int sent_tx;

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

	while (msm_read(port, UART_SR) & UART_SR_TX_READY) {
		if (uart_circ_empty(xmit)) {
			/* disable tx interrupts */
			msm_port->imr &= ~UART_IMR_TXLEV;
			msm_write(port, msm_port->imr, UART_IMR);
			break;
		}

		msm_write(port, xmit->buf[xmit->tail], UART_TF);

		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		port->icount.tx++;
		sent_tx = 1;
	}

#ifdef CONFIG_SERIAL_MSM_CLOCK_CONTROL
	if (sent_tx && msm_port->clk_state == MSM_CLK_REQUEST_OFF)
		/* new TX - restart the timer */
		if (hrtimer_try_to_cancel(&msm_port->clk_off_timer) == 1)
			hrtimer_start(&msm_port->clk_off_timer,
				msm_port->clk_off_delay, HRTIMER_MODE_REL);
#endif

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);
}
示例#28
0
/**
 * cdns_uart_handle_tx - Handle the bytes to be Txed.
 * @dev_id: Id of the UART port
 * Return: None
 */
static void cdns_uart_handle_tx(void *dev_id)
{
	struct uart_port *port = (struct uart_port *)dev_id;
	unsigned int numbytes;

	if (uart_circ_empty(&port->state->xmit)) {
		cdns_uart_writel(CDNS_UART_IXR_TXEMPTY, CDNS_UART_IDR_OFFSET);
	} else {
		numbytes = port->fifosize;
		/* Break if no more data available in the UART buffer */
		while (numbytes--) {
			if (uart_circ_empty(&port->state->xmit))
				break;
			/*
			 * Get the data from the UART circular buffer
			 * and write it to the cdns_uart's TX_FIFO
			 * register.
			 */
			cdns_uart_writel(
				port->state->xmit.buf[port->state->xmit.
				tail], CDNS_UART_FIFO_OFFSET);

			port->icount.tx++;

			/*
			 * Adjust the tail of the UART buffer and wrap
			 * the buffer if it reaches limit.
			 */
			port->state->xmit.tail =
				(port->state->xmit.tail + 1) &
					(UART_XMIT_SIZE - 1);
		}

		if (uart_circ_chars_pending(
				&port->state->xmit) < WAKEUP_CHARS)
			uart_write_wakeup(port);
	}
}
示例#29
0
文件: tilegx.c 项目: 020gzh/linux
/*
 * Send chars to UART Write FIFO; called by interrupt handler.
 */
static void handle_transmit(struct tile_uart_port *tile_uart)
{
	unsigned char ch;
	struct uart_port *port;
	struct circ_buf *xmit;
	gxio_uart_context_t *context = &tile_uart->context;

	/* First reset WFIFO_RE interrupt. */
	gxio_uart_write(context, UART_INTERRUPT_STATUS,
			UART_INTERRUPT_MASK__WFIFO_RE_MASK);

	port = &tile_uart->uart;
	xmit = &port->state->xmit;
	if (port->x_char) {
		if (tilegx_putchar(context, port->x_char))
			return;
		port->x_char = 0;
		port->icount.tx++;
	}

	if (uart_circ_empty(xmit) || uart_tx_stopped(port))
		return;

	while (!uart_circ_empty(xmit)) {
		ch = xmit->buf[xmit->tail];
		if (tilegx_putchar(context, ch))
			break;
		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		port->icount.tx++;
	}

	/* Reset WFIFO_RE interrupt. */
	gxio_uart_write(context, UART_INTERRUPT_STATUS,
			UART_INTERRUPT_MASK__WFIFO_RE_MASK);

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);
}
示例#30
0
static void stm32_transmit_chars(struct uart_port *port)
{
	struct stm32_port *stm32_port = to_stm32_port(port);
	struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
	struct circ_buf *xmit = &port->state->xmit;

	if (port->x_char) {
		if (stm32_port->tx_dma_busy)
			stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
		writel_relaxed(port->x_char, port->membase + ofs->tdr);
		port->x_char = 0;
		port->icount.tx++;
		if (stm32_port->tx_dma_busy)
			stm32_set_bits(port, ofs->cr3, USART_CR3_DMAT);
		return;
	}

	if (uart_tx_stopped(port)) {
		stm32_stop_tx(port);
		return;
	}

	if (uart_circ_empty(xmit)) {
		stm32_stop_tx(port);
		return;
	}

	if (stm32_port->tx_ch)
		stm32_transmit_chars_dma(port);
	else
		stm32_transmit_chars_pio(port);

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);

	if (uart_circ_empty(xmit))
		stm32_stop_tx(port);
}