forked from luck/tmp_suning_uos_patched
serial: tegra: Add PIO mode support
Add PIO mode support in receive and transmit path with RX interrupt trigger of 16 bytes for Tegra194 and older chips. Signed-off-by: Shardar Shariff Md <smohammed@nvidia.com> Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com> Link: https://lore.kernel.org/r/1567572187-29820-13-git-send-email-kyarlagadda@nvidia.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d781ec21ba
commit
1dce2df3ee
|
@ -139,6 +139,8 @@ struct tegra_uart_port {
|
|||
int n_adjustable_baud_rates;
|
||||
int required_rate;
|
||||
int configured_rate;
|
||||
bool use_rx_pio;
|
||||
bool use_tx_pio;
|
||||
};
|
||||
|
||||
static void tegra_uart_start_next_tx(struct tegra_uart_port *tup);
|
||||
|
@ -567,7 +569,7 @@ static void tegra_uart_start_next_tx(struct tegra_uart_port *tup)
|
|||
if (!count)
|
||||
return;
|
||||
|
||||
if (count < TEGRA_UART_MIN_DMA)
|
||||
if (tup->use_tx_pio || count < TEGRA_UART_MIN_DMA)
|
||||
tegra_uart_start_pio_tx(tup, count);
|
||||
else if (BYTES_TO_ALIGN(tail) > 0)
|
||||
tegra_uart_start_pio_tx(tup, BYTES_TO_ALIGN(tail));
|
||||
|
@ -800,6 +802,18 @@ static void tegra_uart_handle_modem_signal_change(struct uart_port *u)
|
|||
uart_handle_cts_change(&tup->uport, msr & UART_MSR_CTS);
|
||||
}
|
||||
|
||||
static void do_handle_rx_pio(struct tegra_uart_port *tup)
|
||||
{
|
||||
struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
|
||||
struct tty_port *port = &tup->uport.state->port;
|
||||
|
||||
tegra_uart_handle_rx_pio(tup, port);
|
||||
if (tty) {
|
||||
tty_flip_buffer_push(port);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t tegra_uart_isr(int irq, void *data)
|
||||
{
|
||||
struct tegra_uart_port *tup = data;
|
||||
|
@ -813,7 +827,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data)
|
|||
while (1) {
|
||||
iir = tegra_uart_read(tup, UART_IIR);
|
||||
if (iir & UART_IIR_NO_INT) {
|
||||
if (is_rx_int) {
|
||||
if (!tup->use_rx_pio && is_rx_int) {
|
||||
tegra_uart_handle_rx_dma(tup);
|
||||
if (tup->rx_in_progress) {
|
||||
ier = tup->ier_shadow;
|
||||
|
@ -841,7 +855,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data)
|
|||
case 4: /* End of data */
|
||||
case 6: /* Rx timeout */
|
||||
case 2: /* Receive */
|
||||
if (!is_rx_int) {
|
||||
if (!tup->use_rx_pio && !is_rx_int) {
|
||||
is_rx_int = true;
|
||||
/* Disable Rx interrupts */
|
||||
ier = tup->ier_shadow;
|
||||
|
@ -851,6 +865,8 @@ static irqreturn_t tegra_uart_isr(int irq, void *data)
|
|||
UART_IER_RTOIE | TEGRA_UART_IER_EORD);
|
||||
tup->ier_shadow = ier;
|
||||
tegra_uart_write(tup, ier, UART_IER);
|
||||
} else {
|
||||
do_handle_rx_pio(tup);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -869,6 +885,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data)
|
|||
static void tegra_uart_stop_rx(struct uart_port *u)
|
||||
{
|
||||
struct tegra_uart_port *tup = to_tegra_uport(u);
|
||||
struct tty_port *port = &tup->uport.state->port;
|
||||
struct dma_tx_state state;
|
||||
unsigned long ier;
|
||||
|
||||
|
@ -886,9 +903,13 @@ static void tegra_uart_stop_rx(struct uart_port *u)
|
|||
tup->ier_shadow = ier;
|
||||
tegra_uart_write(tup, ier, UART_IER);
|
||||
tup->rx_in_progress = 0;
|
||||
if (tup->rx_dma_chan && !tup->use_rx_pio) {
|
||||
dmaengine_terminate_all(tup->rx_dma_chan);
|
||||
dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
|
||||
tegra_uart_rx_buffer_push(tup, state.residue);
|
||||
} else {
|
||||
tegra_uart_handle_rx_pio(tup, port);
|
||||
}
|
||||
}
|
||||
|
||||
static void tegra_uart_hw_deinit(struct tegra_uart_port *tup)
|
||||
|
@ -939,7 +960,9 @@ static void tegra_uart_hw_deinit(struct tegra_uart_port *tup)
|
|||
tup->rx_in_progress = 0;
|
||||
tup->tx_in_progress = 0;
|
||||
|
||||
if (!tup->use_rx_pio)
|
||||
tegra_uart_dma_channel_free(tup, true);
|
||||
if (!tup->use_tx_pio)
|
||||
tegra_uart_dma_channel_free(tup, false);
|
||||
|
||||
clk_disable_unprepare(tup->uart_clk);
|
||||
|
@ -985,10 +1008,14 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup)
|
|||
*/
|
||||
tup->fcr_shadow = UART_FCR_ENABLE_FIFO;
|
||||
|
||||
if (tup->use_rx_pio) {
|
||||
tup->fcr_shadow |= UART_FCR_R_TRIG_11;
|
||||
} else {
|
||||
if (tup->cdata->max_dma_burst_bytes == 8)
|
||||
tup->fcr_shadow |= UART_FCR_R_TRIG_10;
|
||||
else
|
||||
tup->fcr_shadow |= UART_FCR_R_TRIG_01;
|
||||
}
|
||||
|
||||
tup->fcr_shadow |= TEGRA_UART_TX_TRIG_16B;
|
||||
tegra_uart_write(tup, tup->fcr_shadow, UART_FCR);
|
||||
|
@ -1016,12 +1043,13 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup)
|
|||
* (115200, N, 8, 1) so that the receive DMA buffer may be
|
||||
* enqueued
|
||||
*/
|
||||
tup->lcr_shadow = TEGRA_UART_DEFAULT_LSR;
|
||||
ret = tegra_set_baudrate(tup, TEGRA_UART_DEFAULT_BAUD);
|
||||
if (ret < 0) {
|
||||
dev_err(tup->uport.dev, "Failed to set baud rate\n");
|
||||
return ret;
|
||||
}
|
||||
if (!tup->use_rx_pio) {
|
||||
tup->lcr_shadow = TEGRA_UART_DEFAULT_LSR;
|
||||
tup->fcr_shadow |= UART_FCR_DMA_SELECT;
|
||||
tegra_uart_write(tup, tup->fcr_shadow, UART_FCR);
|
||||
|
||||
|
@ -1030,6 +1058,9 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup)
|
|||
dev_err(tup->uport.dev, "Not able to start Rx DMA\n");
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
tegra_uart_write(tup, tup->fcr_shadow, UART_FCR);
|
||||
}
|
||||
tup->rx_in_progress = 1;
|
||||
|
||||
/*
|
||||
|
@ -1050,7 +1081,12 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup)
|
|||
* both the EORD as well as RX_TIMEOUT - SW sees RX_TIMEOUT first
|
||||
* then the EORD.
|
||||
*/
|
||||
tup->ier_shadow = UART_IER_RLSI | UART_IER_RTOIE | TEGRA_UART_IER_EORD;
|
||||
if (!tup->use_rx_pio)
|
||||
tup->ier_shadow = UART_IER_RLSI | UART_IER_RTOIE |
|
||||
TEGRA_UART_IER_EORD;
|
||||
else
|
||||
tup->ier_shadow = UART_IER_RLSI | UART_IER_RTOIE | UART_IER_RDI;
|
||||
|
||||
tegra_uart_write(tup, tup->ier_shadow, UART_IER);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1145,17 +1181,23 @@ static int tegra_uart_startup(struct uart_port *u)
|
|||
struct tegra_uart_port *tup = to_tegra_uport(u);
|
||||
int ret;
|
||||
|
||||
if (!tup->use_tx_pio) {
|
||||
ret = tegra_uart_dma_channel_allocate(tup, false);
|
||||
if (ret < 0) {
|
||||
dev_err(u->dev, "Tx Dma allocation failed, err = %d\n", ret);
|
||||
dev_err(u->dev, "Tx Dma allocation failed, err = %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tup->use_rx_pio) {
|
||||
ret = tegra_uart_dma_channel_allocate(tup, true);
|
||||
if (ret < 0) {
|
||||
dev_err(u->dev, "Rx Dma allocation failed, err = %d\n", ret);
|
||||
dev_err(u->dev, "Rx Dma allocation failed, err = %d\n",
|
||||
ret);
|
||||
goto fail_rx_dma;
|
||||
}
|
||||
}
|
||||
|
||||
ret = tegra_uart_hw_init(tup);
|
||||
if (ret < 0) {
|
||||
|
@ -1172,8 +1214,10 @@ static int tegra_uart_startup(struct uart_port *u)
|
|||
return 0;
|
||||
|
||||
fail_hw_init:
|
||||
if (!tup->use_rx_pio)
|
||||
tegra_uart_dma_channel_free(tup, true);
|
||||
fail_rx_dma:
|
||||
if (!tup->use_tx_pio)
|
||||
tegra_uart_dma_channel_free(tup, false);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1378,7 +1422,6 @@ static int tegra_uart_parse_dt(struct platform_device *pdev,
|
|||
int count;
|
||||
int n_entries;
|
||||
|
||||
|
||||
port = of_alias_get_id(np, "serial");
|
||||
if (port < 0) {
|
||||
dev_err(&pdev->dev, "failed to get alias id, errno %d\n", port);
|
||||
|
@ -1388,6 +1431,18 @@ static int tegra_uart_parse_dt(struct platform_device *pdev,
|
|||
|
||||
tup->enable_modem_interrupt = of_property_read_bool(np,
|
||||
"nvidia,enable-modem-interrupt");
|
||||
|
||||
index = of_property_match_string(np, "dma-names", "rx");
|
||||
if (index < 0) {
|
||||
tup->use_rx_pio = true;
|
||||
dev_info(&pdev->dev, "RX in PIO mode\n");
|
||||
}
|
||||
index = of_property_match_string(np, "dma-names", "tx");
|
||||
if (index < 0) {
|
||||
tup->use_tx_pio = true;
|
||||
dev_info(&pdev->dev, "TX in PIO mode\n");
|
||||
}
|
||||
|
||||
n_entries = of_property_count_u32_elems(np, "nvidia,adjust-baud-rates");
|
||||
if (n_entries > 0) {
|
||||
tup->n_adjustable_baud_rates = n_entries / 3;
|
||||
|
|
Loading…
Reference in New Issue
Block a user