static void timbuart_tx_chars(struct uart_port *port) { struct circ_buf *xmit = &port->state->xmit; while (!(ioread32(port->membase + TIMBUART_ISR) & TXBF) && !uart_circ_empty(xmit)) { iowrite8(xmit->buf[xmit->tail], port->membase + TIMBUART_TXFIFO); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; } dev_dbg(port->dev, "%s - total written %d bytes, CTL: %x, RTS: %x, baud: %x\n", __func__, port->icount.tx, ioread8(port->membase + TIMBUART_CTRL), port->mctrl & TIOCM_RTS, ioread8(port->membase + TIMBUART_BAUDRATE)); }
static void fill_tx_fifo(struct tegra_uart_port *t, int max_bytes) { int i; struct circ_buf *xmit = &t->uport.state->xmit; #ifndef CONFIG_ARCH_TEGRA_2x_SOC unsigned long lsr; #endif for (i = 0; i < max_bytes; i++) { BUG_ON(uart_circ_empty(xmit)); #ifndef CONFIG_ARCH_TEGRA_2x_SOC lsr = uart_readl(t, UART_LSR); if ((lsr & UART_LSR_TXFIFO_FULL)) break; #endif uart_writeb(t, xmit->buf[xmit->tail], UART_TX); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); t->uport.icount.tx++; } }
int omap_uart_active(int num, u32 timeout) { struct uart_omap_port *up = ui[num]; struct circ_buf *xmit; unsigned int status; /* Though when UART's initialised this can never happen, * but during initialisation, it can happen the "ui" * structure is not initialized and the timer kicks * in. This would result in a NULL value, resulting * in crash. */ if (up == NULL) return 0; /* Check for recent driver activity. If time delta from now * to last activty < "uart idle timeout" second keep clocks on. */ if (((jiffies - up->port_activity) < timeout)) return 1; xmit = &up->port.state->xmit; if (!(uart_circ_empty(xmit) || uart_tx_stopped(&up->port))) return 1; status = serial_in(up, UART_LSR); /* TX hardware not empty */ if (!(status & (UART_LSR_TEMT | UART_LSR_THRE))) return 1; /* Any rx activity? */ if (status & UART_LSR_DR) return 1; /* Check if DMA channels are active */ if (up->use_dma && (up->uart_dma.rx_dma_channel != OMAP_UART_DMA_CH_FREE || up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE)) return 1; return 0; }
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); }
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); }
static void sc16is7xx_stop_tx(struct uart_port* port) { struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); struct circ_buf *xmit = &one->port.state->xmit; /* handle rs485 */ if (one->rs485.flags & SER_RS485_ENABLED) { /* do nothing if current tx not yet completed */ int lsr = sc16is7xx_port_read(port, SC16IS7XX_LSR_REG); if (!(lsr & SC16IS7XX_LSR_TEMT_BIT)) return; if (uart_circ_empty(xmit) && (one->rs485.delay_rts_after_send > 0)) mdelay(one->rs485.delay_rts_after_send); } sc16is7xx_port_update(port, SC16IS7XX_IER_REG, SC16IS7XX_IER_THRI_BIT, 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 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); }
static unsigned int sdp_serial_tx_chars(struct uart_port *port) { struct circ_buf *xmit = &port->info->xmit; int count = 0; if (port->x_char) { UART_PUT_CHAR(port, port->x_char); port->icount.tx++; port->x_char = 0; return 0; } if (uart_circ_empty(xmit) || uart_tx_stopped(port)){ sdp_serial_stop_tx(port); return 0; } if (port->fifosize > 1) count = (port->fifosize - (((UART_GET_UFSTAT(port) >> 4) & 0xF) + 1)); // avoid to overflow , fifo size else
static void sc16is7xx_handle_tx(struct uart_port *port) { struct sc16is7xx_port *s = dev_get_drvdata(port->dev); struct circ_buf *xmit = &port->state->xmit; unsigned int txlen, to_send, i; if (unlikely(port->x_char)) { sc16is7xx_port_write(port, SC16IS7XX_THR_REG, port->x_char); port->icount.tx++; port->x_char = 0; return; } if (uart_circ_empty(xmit) || uart_tx_stopped(port)) return; /* Get length of data pending in circular buffer */ to_send = uart_circ_chars_pending(xmit); if (likely(to_send)) { /* Limit to size of TX FIFO */ txlen = sc16is7xx_port_read(port, SC16IS7XX_TXLVL_REG); to_send = (to_send > txlen) ? txlen : to_send; /* Add data to send */ port->icount.tx += to_send; /* Convert to linear buffer */ for (i = 0; i < to_send; ++i) { s->buf[i] = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); } regcache_cache_bypass(s->regmap, true); regmap_raw_write(s->regmap, SC16IS7XX_THR_REG, s->buf, to_send); regcache_cache_bypass(s->regmap, false); } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); }
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; }
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; }
/********************************************************************************************************** * Description: This function is used to start transfer data. * * Arguments : port is the uart port * * Returns : **********************************************************************************************************/ void tls_uart_tx_chars_start(struct tls_uart_port *port) { struct tls_uart_circ_buf *xmit = &port->xmit; int tx_count; u32 cpu_sr; /* send some chars */ tx_count = 32; cpu_sr = tls_os_set_critical(); while (!uart_circ_empty(xmit) && tx_count-- > 0) { /* 检查tx fifo是否已满 */ if ((port->regs->UR_FIFOS & UFS_TX_FIFO_CNT_MASK) == port->tx_fifofull) break; port->regs->UR_TXW = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (TLS_UART_TX_BUF_SIZE - 1); port->icount.tx++; } tls_os_release_critical(cpu_sr); return; }
static void am_uart_start_tx(struct uart_port *port) { unsigned int ch; struct meson_uart_port * mup = &am_ports[port->line]; am_uart_t *uart = mup->uart; struct uart_port * up = &mup->port; struct circ_buf *xmit = &up->state->xmit; unsigned long flags; spin_lock_irqsave(&mup->wr_lock, flags); while(!uart_circ_empty(xmit)){ 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; } //mutex_unlock(&info->info_mutex); spin_unlock_irqrestore(&mup->wr_lock, flags); }
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); }
static void uart_tx_dma_callback(int lch, u16 ch_status, void *data) { struct uart_omap_port *up = (struct uart_omap_port *)data; struct circ_buf *xmit = &up->port.state->xmit; xmit->tail = (xmit->tail + up->uart_dma.tx_buf_size) & \ (UART_XMIT_SIZE - 1); up->port.icount.tx += up->uart_dma.tx_buf_size; if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&up->port); if (uart_circ_empty(xmit)) { spin_lock(&(up->uart_dma.tx_lock)); serial_omap_stop_tx(&up->port); up->uart_dma.tx_dma_used = false; spin_unlock(&(up->uart_dma.tx_lock)); if (up->plat_hold_wakelock) (up->plat_hold_wakelock(up, WAKELK_TX)); } else { #ifdef CONFIG_PM /* * This will enable the clock for some reason if the * clocks get disabled. This would enable the ICK also * in case if the Idle state is set and the PRCM modul * just shutdown the ICK because of inactivity. */ omap_uart_enable_clock_from_irq(up->pdev->id); #endif omap_stop_dma(up->uart_dma.tx_dma_channel); serial_omap_continue_tx(up); } up->port_activity = jiffies; return; }
static inline void send_circ_buf(struct uart_max3110 *max, struct circ_buf *xmit) { int len, left = 0; u16 obuf[WORDS_PER_XFER], ibuf[WORDS_PER_XFER]; u8 valid_str[WORDS_PER_XFER]; int i, j; while (!uart_circ_empty(xmit)) { left = uart_circ_chars_pending(xmit); while (left) { len = (left >= WORDS_PER_XFER) ? WORDS_PER_XFER : left; memset(obuf, 0, len * 2); memset(ibuf, 0, len * 2); for (i = 0; i < len; i++) { obuf[i] = (u8)xmit->buf[xmit->tail] | WD_TAG; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); } max3110_write_then_read(max, (u8 *)obuf, (u8 *)ibuf, len * 2, 0); for (i = 0, j = 0; i < len; i++) { if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE) valid_str[j++] = (u8)(ibuf[i] & 0xff); } if (j) receive_chars(max, valid_str, j); max->port.icount.tx += len; left -= len; } } }
static void fm3_transmit(struct uart_port *port) { struct circ_buf *xmit; volatile struct fm3_uart_regs *uart_regs = uart_regs_by_port(port); if (port->x_char) { fm3_tx_char(uart_regs, port->x_char); port->x_char = 0; port->icount.tx++; return; } xmit = &port->state->xmit; if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { fm3_port_stop_tx(port); return; } fm3_tx_char(uart_regs, 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); return; }
static void sprd_complete_tx_dma(void *data) { struct uart_port *port = (struct uart_port *)data; struct sprd_uart_port *sp = container_of(port, struct sprd_uart_port, port); struct circ_buf *xmit = &port->state->xmit; unsigned long flags; spin_lock_irqsave(&port->lock, flags); dma_unmap_single(port->dev, sp->tx_dma.phys_addr, sp->tx_dma.trans_len, DMA_TO_DEVICE); xmit->tail = (xmit->tail + sp->tx_dma.trans_len) & (UART_XMIT_SIZE - 1); port->icount.tx += sp->tx_dma.trans_len; if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); if (uart_circ_empty(xmit) || sprd_tx_buf_remap(port) || sprd_tx_dma_config(port)) sp->tx_dma.trans_len = 0; spin_unlock_irqrestore(&port->lock, flags); }
static unsigned int sdp_serial_tx_chars(struct uart_port *port) { SDP_UART_REG_T * reg = (SDP_UART_REG_T*) port->membase; struct circ_buf *xmit = &port->state->xmit; // unsigned long flags; int count = 0; #if defined(CONFIG_SERIAL_SDP_CONSOLE) && defined(SDP_CONSOLE_IRQ) SDP_UART_PRIV_T * p_uart_priv; if(!DEBUG_PORT(port)) { p_uart_priv = (SDP_UART_PRIV_T *) UART_PRIV(port); if(p_uart_priv->console) { if(sdp_cons_print(port)) { return 0; } } } #endif // spin_lock_irqsave(&port->lock, flags); if (port->x_char) { reg->utxh = port->x_char; port->icount.tx++; port->x_char = 0; goto __exit_tx_chars; } if (uart_circ_empty(xmit) || uart_tx_stopped(port)){ goto __exit_tx_chars; } if (port->fifosize > 1) count = (port->fifosize - (((reg->ufstat >> 4) & 0xF) + 1)); // avoid to overflow , fifo size else
static void genode_serial_tx_chars(struct uart_port *port) { struct genode_uart_port *l4port = (struct genode_uart_port *)port; struct circ_buf *xmit = &port->state->xmit; unsigned long flags; unsigned c; if (port->x_char) { local_irq_save(flags); genode_terminal_writechar(l4port->idx, &port->x_char, sizeof(char)); local_irq_restore(flags); port->icount.tx++; port->x_char = 0; return; } while (!uart_circ_empty(xmit)) { c = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); local_irq_save(flags); genode_terminal_writechar(l4port->idx, &xmit->buf[xmit->tail], c); local_irq_restore(flags); xmit->tail = (xmit->tail + c) & (UART_XMIT_SIZE - 1); port->icount.tx += c; } }
static void uart_tx_dma_callback(int lch, u16 ch_status, void *data) { struct uart_omap_port *up = (struct uart_omap_port *)data; struct circ_buf *xmit = &up->port.state->xmit; xmit->tail = (xmit->tail + up->uart_dma.tx_buf_size) & \ (UART_XMIT_SIZE - 1); up->port.icount.tx += up->uart_dma.tx_buf_size; if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&up->port); if (uart_circ_empty(xmit)) { spin_lock(&(up->uart_dma.tx_lock)); serial_omap_stop_tx(&up->port); up->uart_dma.tx_dma_used = false; spin_unlock(&(up->uart_dma.tx_lock)); } else { omap_stop_dma(up->uart_dma.tx_dma_channel); serial_omap_continue_tx(up); } up->port_activity = jiffies; return; }
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; unsigned long flags; int count, dma_count = 0; spin_lock_irqsave(&port->lock, flags); count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); if (ourport->dma && ourport->dma->tx_chan && count >= ourport->min_dma_size) { int align = dma_get_cache_alignment() - (xmit->tail & (dma_get_cache_alignment() - 1)); if (count-align >= ourport->min_dma_size) { dma_count = count-align; count = align; } } if (port->x_char) { wr_regb(port, S3C2410_UTXH, port->x_char); port->icount.tx++; port->x_char = 0; goto out; } /* if there isn't 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); goto out; } /* try and drain the buffer... */ if (count > port->fifosize) { count = port->fifosize; dma_count = 0; } 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++; count--; } if (!count && dma_count) { s3c24xx_serial_start_tx_dma(ourport, dma_count); goto out; } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) { spin_unlock(&port->lock); uart_write_wakeup(port); spin_lock(&port->lock); } if (uart_circ_empty(xmit)) s3c24xx_serial_stop_tx(port); out: spin_unlock_irqrestore(&port->lock, flags); return IRQ_HANDLED; }
/* * Transmit characters, refill buffer descriptor, if possible */ static int cpm_uart_tx_pump(struct uart_port *port) { volatile cbd_t *bdp; unsigned char *p; int count; struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; struct circ_buf *xmit = &port->info->xmit; /* Handle xon/xoff */ if (port->x_char) { /* Pick next descriptor and fill from buffer */ bdp = pinfo->tx_cur; p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); *p++ = port->x_char; bdp->cbd_datlen = 1; bdp->cbd_sc |= BD_SC_READY; /* Get next BD. */ if (bdp->cbd_sc & BD_SC_WRAP) bdp = pinfo->tx_bd_base; else bdp++; pinfo->tx_cur = bdp; port->icount.tx++; port->x_char = 0; return 1; } if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { cpm_uart_stop_tx(port); return 0; } /* Pick next descriptor and fill from buffer */ bdp = pinfo->tx_cur; while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) { count = 0; p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo); while (count < pinfo->tx_fifosize) { *p++ = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; count++; if (xmit->head == xmit->tail) break; } bdp->cbd_datlen = count; bdp->cbd_sc |= BD_SC_READY; __asm__("eieio"); /* Get next BD. */ if (bdp->cbd_sc & BD_SC_WRAP) bdp = pinfo->tx_bd_base; else bdp++; } pinfo->tx_cur = bdp; if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); if (uart_circ_empty(xmit)) { cpm_uart_stop_tx(port); return 0; } return 1; }
static void handle_tx(struct uart_port *port) { struct circ_buf *xmit = &port->state->xmit; int sent_tx; int tx_count; int x; unsigned int tf_pointer = 0; tx_count = uart_circ_chars_pending(xmit); if (tx_count > (UART_XMIT_SIZE - xmit->tail)) tx_count = UART_XMIT_SIZE - xmit->tail; if (tx_count >= port->fifosize) tx_count = port->fifosize; /* Handle x_char */ if (port->x_char) { wait_for_xmitr(port, UARTDM_ISR_TX_READY_BMSK); msm_hsl_write(port, tx_count + 1, UARTDM_NCF_TX_ADDR); msm_hsl_write(port, port->x_char, UARTDM_TF_ADDR); port->icount.tx++; port->x_char = 0; } else if (tx_count) { wait_for_xmitr(port, UARTDM_ISR_TX_READY_BMSK); msm_hsl_write(port, tx_count, UARTDM_NCF_TX_ADDR); } if (!tx_count) { msm_hsl_stop_tx(port); return; } #ifdef FELICA_DEBUG if (port->line == 3) pr_info("%s: count=%d\n", __func__, tx_count); #endif while (tf_pointer < tx_count) { if (unlikely(!(msm_hsl_read(port, UARTDM_SR_ADDR) & UARTDM_SR_TXRDY_BMSK))) continue; switch (tx_count - tf_pointer) { case 1: { x = xmit->buf[xmit->tail]; port->icount.tx++; break; } case 2: { x = xmit->buf[xmit->tail] | xmit->buf[xmit->tail+1] << 8; port->icount.tx += 2; break; } case 3: { x = xmit->buf[xmit->tail] | xmit->buf[xmit->tail+1] << 8 | xmit->buf[xmit->tail + 2] << 16; port->icount.tx += 3; break; } default: { x = *((int *)&(xmit->buf[xmit->tail])); port->icount.tx += 4; break; } } #ifdef FELICA_DEBUG if (port->line == 3) pr_info("%s: 0x%08X\n", __func__, x); #endif msm_hsl_write(port, x, UARTDM_TF_ADDR); xmit->tail = ((tx_count - tf_pointer < 4) ? (tx_count - tf_pointer + xmit->tail) : (xmit->tail + 4)) & (UART_XMIT_SIZE - 1); tf_pointer += 4; sent_tx = 1; } if (uart_circ_empty(xmit)) msm_hsl_stop_tx(port); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); }
/** * xuartps_isr - Interrupt handler * @irq: Irq number * @dev_id: Id of the port * * Returns IRQHANDLED **/ static irqreturn_t xuartps_isr(int irq, void *dev_id) { struct uart_port *port = (struct uart_port *)dev_id; unsigned long flags; unsigned int isrstatus, numbytes; unsigned int data; char status = TTY_NORMAL; spin_lock_irqsave(&port->lock, flags); /* Read the interrupt status register to determine which * interrupt(s) is/are active. */ isrstatus = xuartps_readl(XUARTPS_ISR_OFFSET); /* drop byte with parity error if IGNPAR specified */ if (isrstatus & port->ignore_status_mask & XUARTPS_IXR_PARITY) isrstatus &= ~(XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT); isrstatus &= port->read_status_mask; isrstatus &= ~port->ignore_status_mask; if ((isrstatus & XUARTPS_IXR_TOUT) || (isrstatus & XUARTPS_IXR_RXTRIG)) { /* Receive Timeout Interrupt */ while ((xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) { data = xuartps_readl(XUARTPS_FIFO_OFFSET); port->icount.rx++; if (isrstatus & XUARTPS_IXR_PARITY) { port->icount.parity++; status = TTY_PARITY; } else if (isrstatus & XUARTPS_IXR_FRAMING) { port->icount.frame++; status = TTY_FRAME; } else if (isrstatus & XUARTPS_IXR_OVERRUN) port->icount.overrun++; uart_insert_char(port, isrstatus, XUARTPS_IXR_OVERRUN, data, status); } spin_unlock(&port->lock); tty_flip_buffer_push(&port->state->port); spin_lock(&port->lock); } /* Dispatch an appropriate handler */ if ((isrstatus & XUARTPS_IXR_TXEMPTY) == XUARTPS_IXR_TXEMPTY) { if (uart_circ_empty(&port->state->xmit)) { xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_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 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); } if (uart_circ_chars_pending( &port->state->xmit) < WAKEUP_CHARS) uart_write_wakeup(port); } } xuartps_writel(isrstatus, XUARTPS_ISR_OFFSET); /* be sure to release the lock and tty before leaving */ spin_unlock_irqrestore(&port->lock, flags); return IRQ_HANDLED; }
/* * Transmit characters, refill buffer descriptor, if possible */ static int cpm_uart_tx_pump(struct uart_port *port) { cbd_t __iomem *bdp; u8 *p; int count; struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; struct circ_buf *xmit = &port->info->xmit; /* Handle xon/xoff */ if (port->x_char) { /* Pick next descriptor and fill from buffer */ bdp = pinfo->tx_cur; p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo); *p++ = port->x_char; out_be16(&bdp->cbd_datlen, 1); setbits16(&bdp->cbd_sc, BD_SC_READY); /* Get next BD. */ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) bdp = pinfo->tx_bd_base; else bdp++; pinfo->tx_cur = bdp; port->icount.tx++; port->x_char = 0; return 1; } if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { cpm_uart_stop_tx(port); return 0; } /* Pick next descriptor and fill from buffer */ bdp = pinfo->tx_cur; while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) && xmit->tail != xmit->head) { count = 0; p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo); while (count < pinfo->tx_fifosize) { *p++ = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; count++; if (xmit->head == xmit->tail) break; } out_be16(&bdp->cbd_datlen, count); setbits16(&bdp->cbd_sc, BD_SC_READY); /* Get next BD. */ if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) bdp = pinfo->tx_bd_base; else bdp++; } pinfo->tx_cur = bdp; if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); if (uart_circ_empty(xmit)) { cpm_uart_stop_tx(port); return 0; } return 1; }
static void ip22zilog_transmit_chars(struct uart_ip22zilog_port *up, struct zilog_channel *channel) { struct circ_buf *xmit; if (ZS_IS_CONS(up)) { unsigned char status = readb(&channel->control); ZSDELAY(); /* TX still busy? Just wait for the next TX done interrupt. * * It can occur because of how we do serial console writes. It would * be nice to transmit console writes just like we normally would for * a TTY line. (ie. buffered and TX interrupt driven). That is not * easy because console writes cannot sleep. One solution might be * to poll on enough port->xmit space becoming free. -DaveM */ if (!(status & Tx_BUF_EMP)) return; } up->flags &= ~IP22ZILOG_FLAG_TX_ACTIVE; if (ZS_REGS_HELD(up)) { __load_zsregs(channel, up->curregs); up->flags &= ~IP22ZILOG_FLAG_REGS_HELD; } if (ZS_TX_STOPPED(up)) { up->flags &= ~IP22ZILOG_FLAG_TX_STOPPED; goto ack_tx_int; } if (up->port.x_char) { up->flags |= IP22ZILOG_FLAG_TX_ACTIVE; writeb(up->port.x_char, &channel->data); ZSDELAY(); ZS_WSYNC(channel); up->port.icount.tx++; up->port.x_char = 0; return; } if (up->port.state == NULL) goto ack_tx_int; xmit = &up->port.state->xmit; if (uart_circ_empty(xmit)) goto ack_tx_int; if (uart_tx_stopped(&up->port)) goto ack_tx_int; up->flags |= IP22ZILOG_FLAG_TX_ACTIVE; writeb(xmit->buf[xmit->tail], &channel->data); ZSDELAY(); ZS_WSYNC(channel); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); up->port.icount.tx++; if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&up->port); return; ack_tx_int: writeb(RES_Tx_P, &channel->control); ZSDELAY(); ZS_WSYNC(channel); }
static void transmit_chars_no_dma(struct uart_cris_port *up) { int max_count; struct circ_buf *xmit = &up->port.state->xmit; void __iomem *regi_ser = up->regi_ser; reg_ser_r_stat_din rstat; reg_ser_rw_ack_intr ack_intr = { .tr_rdy = regk_ser_yes }; if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { /* No more to send, so disable the interrupt. */ reg_ser_rw_intr_mask intr_mask; intr_mask = REG_RD(ser, regi_ser, rw_intr_mask); intr_mask.tr_rdy = 0; intr_mask.tr_empty = 0; REG_WR(ser, regi_ser, rw_intr_mask, intr_mask); up->write_ongoing = 0; return; } /* If the serport is fast, we send up to max_count bytes before exiting the loop. */ max_count = 64; do { reg_ser_rw_dout dout = { .data = xmit->buf[xmit->tail] }; REG_WR(ser, regi_ser, rw_dout, dout); REG_WR(ser, regi_ser, rw_ack_intr, ack_intr); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1); up->port.icount.tx++; if (xmit->head == xmit->tail) break; rstat = REG_RD(ser, regi_ser, r_stat_din); } while ((--max_count > 0) && rstat.tr_rdy); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&up->port); } static void receive_chars_no_dma(struct uart_cris_port *up) { reg_ser_rs_stat_din stat_din; reg_ser_r_stat_din rstat; struct tty_port *port; struct uart_icount *icount; int max_count = 16; char flag; reg_ser_rw_ack_intr ack_intr = { 0 }; rstat = REG_RD(ser, up->regi_ser, r_stat_din); icount = &up->port.icount; port = &up->port.state->port; do { stat_din = REG_RD(ser, up->regi_ser, rs_stat_din); flag = TTY_NORMAL; ack_intr.dav = 1; REG_WR(ser, up->regi_ser, rw_ack_intr, ack_intr); icount->rx++; if (stat_din.framing_err | stat_din.par_err | stat_din.orun) { if (stat_din.data == 0x00 && stat_din.framing_err) { /* Most likely a break. */ flag = TTY_BREAK; icount->brk++; } else if (stat_din.par_err) { flag = TTY_PARITY; icount->parity++; } else if (stat_din.orun) { flag = TTY_OVERRUN; icount->overrun++; } else if (stat_din.framing_err) { flag = TTY_FRAME; icount->frame++; } } /* * If this becomes important, we probably *could* handle this * gracefully by keeping track of the unhandled character. */ if (!tty_insert_flip_char(port, stat_din.data, flag)) panic("%s: No tty buffer space", __func__); rstat = REG_RD(ser, up->regi_ser, r_stat_din); } while (rstat.dav && (max_count-- > 0)); spin_unlock(&up->port.lock); tty_flip_buffer_push(port); spin_lock(&up->port.lock); }
static void pmz_transmit_chars(struct uart_pmac_port *uap) { struct circ_buf *xmit; if (ZS_IS_ASLEEP(uap)) return; if (ZS_IS_CONS(uap)) { unsigned char status = read_zsreg(uap, R0); /* TX still busy? Just wait for the next TX done interrupt. * * It can occur because of how we do serial console writes. It would * be nice to transmit console writes just like we normally would for * a TTY line. (ie. buffered and TX interrupt driven). That is not * easy because console writes cannot sleep. One solution might be * to poll on enough port->xmit space becomming free. -DaveM */ if (!(status & Tx_BUF_EMP)) return; } uap->flags &= ~PMACZILOG_FLAG_TX_ACTIVE; if (ZS_REGS_HELD(uap)) { pmz_load_zsregs(uap, uap->curregs); uap->flags &= ~PMACZILOG_FLAG_REGS_HELD; } if (ZS_TX_STOPPED(uap)) { uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED; goto ack_tx_int; } if (uap->port.x_char) { uap->flags |= PMACZILOG_FLAG_TX_ACTIVE; write_zsdata(uap, uap->port.x_char); zssync(uap); uap->port.icount.tx++; uap->port.x_char = 0; return; } if (uap->port.info == NULL) goto ack_tx_int; xmit = &uap->port.info->xmit; if (uart_circ_empty(xmit)) { uart_write_wakeup(&uap->port); goto ack_tx_int; } if (uart_tx_stopped(&uap->port)) goto ack_tx_int; uap->flags |= PMACZILOG_FLAG_TX_ACTIVE; write_zsdata(uap, xmit->buf[xmit->tail]); zssync(uap); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); uap->port.icount.tx++; if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&uap->port); return; ack_tx_int: write_zsreg(uap, R0, RES_Tx_P); zssync(uap); }