Skip to content

Commit

Permalink
serial: imx: don't use idle condition detect for DMA transfers
Browse files Browse the repository at this point in the history
The reference manual states that idle condition detect should not be used
with DMA transfers, as the ROM SDMA scripts don't check those conditions.

The RAM SDMA scripts worked around this, but the change broke compatibility
with the ROM scripts.

The previous commits fixed the DMA burst sizes, so that the aging timer is
now working as described in the reference manual. With this fixed we can
remove the hack of using the idle condition detect to stop the DMA transfer
if there are no new characters incoming.

This should work with both the ROM and RAM SDMA scripts.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Acked-by: Jiada Wang <jiada_wang@mentor.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Lucas Stach authored and Greg Kroah-Hartman committed Oct 4, 2015
1 parent 184bd70 commit 905c0de
Showing 1 changed file with 5 additions and 26 deletions.
31 changes: 5 additions & 26 deletions drivers/tty/serial/imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -884,14 +884,12 @@ static void imx_rx_dma_done(struct imx_port *sport)
}

/*
* There are three kinds of RX DMA interrupts(such as in the MX6Q):
* There are two kinds of RX DMA interrupts(such as in the MX6Q):
* [1] the RX DMA buffer is full.
* [2] the Aging timer expires(wait for 8 bytes long)
* [3] the Idle Condition Detect(enabled the UCR4_IDDMAEN).
* [2] the aging timer expires
*
* The [2] is trigger when a character was been sitting in the FIFO
* meanwhile [3] can wait for 32 bytes long when the RX line is
* on IDLE state and RxFIFO is empty.
* Condition [2] is triggered when a character has been sitting in the FIFO
* for at least 8 byte durations.
*/
static void dma_rx_callback(void *data)
{
Expand All @@ -909,13 +907,6 @@ static void dma_rx_callback(void *data)
status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
count = RX_BUF_SIZE - state.residue;

if (readl(sport->port.membase + USR2) & USR2_IDLE) {
/* In condition [3] the SDMA counted up too early */
count--;

writel(USR2_IDLE, sport->port.membase + USR2);
}

dev_dbg(sport->port.dev, "We get %d bytes.\n", count);

if (count) {
Expand Down Expand Up @@ -1072,20 +1063,13 @@ static void imx_enable_dma(struct imx_port *sport)

/* set UCR1 */
temp = readl(sport->port.membase + UCR1);
temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN |
/* wait for 32 idle frames for IDDMA interrupt */
UCR1_ICD_REG(3);
temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN;
writel(temp, sport->port.membase + UCR1);

temp = readl(sport->port.membase + UCR2);
temp |= UCR2_ATEN;
writel(temp, sport->port.membase + UCR2);

/* set UCR4 */
temp = readl(sport->port.membase + UCR4);
temp |= UCR4_IDDMAEN;
writel(temp, sport->port.membase + UCR4);

imx_setup_ufcr(sport, TXTL_DMA, RXTL_DMA);

sport->dma_is_enabled = 1;
Expand All @@ -1105,11 +1089,6 @@ static void imx_disable_dma(struct imx_port *sport)
temp &= ~(UCR2_CTSC | UCR2_CTS | UCR2_ATEN);
writel(temp, sport->port.membase + UCR2);

/* clear UCR4 */
temp = readl(sport->port.membase + UCR4);
temp &= ~UCR4_IDDMAEN;
writel(temp, sport->port.membase + UCR4);

imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);

sport->dma_is_enabled = 0;
Expand Down

0 comments on commit 905c0de

Please sign in to comment.