static void serial_omap_start_tx(struct uart_port *port) { struct uart_omap_port *up = (struct uart_omap_port *)port; struct circ_buf *xmit; unsigned int start; int ret = 0; if (!up->use_dma) { serial_omap_enable_ier_thri(up); return; } if (up->uart_dma.tx_dma_used) return; xmit = &up->port.state->xmit; if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) { ret = omap_request_dma(up->uart_dma.uart_dma_tx, "UART Tx DMA", (void *)uart_tx_dma_callback, up, &(up->uart_dma.tx_dma_channel)); if (ret < 0) { serial_omap_enable_ier_thri(up); return; } } spin_lock(&(up->uart_dma.tx_lock)); up->uart_dma.tx_dma_used = true; spin_unlock(&(up->uart_dma.tx_lock)); start = up->uart_dma.tx_buf_dma_phys + (xmit->tail & (UART_XMIT_SIZE - 1)); up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit); /* * It is a circular buffer. See if the buffer has wounded back. * If yes it will have to be transferred in two separate dma * transfers */ if (start + up->uart_dma.tx_buf_size >= up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) up->uart_dma.tx_buf_size = (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start; omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_CONSTANT, up->uart_dma.uart_base, 0, 0); omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, start, 0, 0); omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel, OMAP_DMA_DATA_TYPE_S8, up->uart_dma.tx_buf_size, 1, OMAP_DMA_SYNC_ELEMENT, up->uart_dma.uart_dma_tx, 0); /* FIXME: Cache maintenance needed here? */ omap_start_dma(up->uart_dma.tx_dma_channel); }
static void serial_omap_start_tx(struct uart_port *port) { struct uart_omap_port *up = to_uart_omap_port(port); int res; pm_runtime_get_sync(up->dev); /* Handle RS-485 */ if (port->rs485.flags & SER_RS485_ENABLED) { /* Fire THR interrupts when FIFO is below trigger level */ up->scr &= ~OMAP_UART_SCR_TX_EMPTY; serial_out(up, UART_OMAP_SCR, up->scr); /* if rts not already enabled */ res = (port->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0; if (gpio_get_value(up->rts_gpio) != res) { gpio_set_value(up->rts_gpio, res); if (port->rs485.delay_rts_before_send > 0) mdelay(port->rs485.delay_rts_before_send); } } if ((port->rs485.flags & SER_RS485_ENABLED) && !(port->rs485.flags & SER_RS485_RX_DURING_TX)) serial_omap_stop_rx(port); serial_omap_enable_ier_thri(up); pm_runtime_mark_last_busy(up->dev); pm_runtime_put_autosuspend(up->dev); }
static void serial_omap_stop_tx(struct uart_port *port) { struct uart_omap_port *up = (struct uart_omap_port *)port; if (up->use_dma && up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) { /* * Check if dma is still active. If yes do nothing, * return. Else stop dma */ if (omap_get_dma_active_status(up->uart_dma.tx_dma_channel)) return; omap_stop_dma(up->uart_dma.tx_dma_channel); omap_free_dma(up->uart_dma.tx_dma_channel); up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE; } if (!(up->rs485.flags & SER_RS485_ENABLED)) { serial_omap_disable_ier_thri(up); return; } up->tx_wait_end = 1; serial_omap_thri_mode(up); serial_omap_enable_ier_thri(up); }
static void serial_omap_start_tx(struct uart_port *port) { struct uart_omap_port *up = to_uart_omap_port(port); pm_runtime_get_sync(up->dev); serial_omap_enable_ier_thri(up); pm_runtime_mark_last_busy(up->dev); pm_runtime_put_autosuspend(up->dev); }
static void serial_omap_start_tx(struct uart_port *port) { struct uart_omap_port *up = (struct uart_omap_port *)port; struct omap_uart_port_info *pdata = up->pdev->dev.platform_data; struct circ_buf *xmit; unsigned int start; int ret = 0; if (!up->use_dma) { pm_runtime_get_sync(&up->pdev->dev); serial_omap_enable_ier_thri(up); if (pdata && pdata->set_noidle) pdata->set_noidle(up->pdev); pm_runtime_mark_last_busy(&up->pdev->dev); pm_runtime_put_autosuspend(&up->pdev->dev); return; } if (up->uart_dma.tx_dma_used) return; xmit = &up->port.state->xmit; if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) { pm_runtime_get_sync(&up->pdev->dev); ret = omap_request_dma(up->uart_dma.uart_dma_tx, "UART Tx DMA", (void *)uart_tx_dma_callback, up, &(up->uart_dma.tx_dma_channel)); if (ret < 0) { serial_omap_enable_ier_thri(up); return; } } spin_lock(&(up->uart_dma.tx_lock)); up->uart_dma.tx_dma_used = true; spin_unlock(&(up->uart_dma.tx_lock)); start = up->uart_dma.tx_buf_dma_phys + (xmit->tail & (UART_XMIT_SIZE - 1)); up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit); if (start + up->uart_dma.tx_buf_size >= up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) up->uart_dma.tx_buf_size = (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start; omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_CONSTANT, up->uart_dma.uart_base, 0, 0); omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0, OMAP_DMA_AMODE_POST_INC, start, 0, 0); omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel, OMAP_DMA_DATA_TYPE_S8, up->uart_dma.tx_buf_size, 1, OMAP_DMA_SYNC_ELEMENT, up->uart_dma.uart_dma_tx, 0); omap_start_dma(up->uart_dma.tx_dma_channel); }