[PATCH v2 2/2] serial: mxs-auart: wait for FIFO to flush before shutdown
Hector Palacios
hector.palacios at digi.com
Wed Oct 2 10:01:47 EDT 2013
Hello Uwe,
On 10/02/2013 02:22 PM, Uwe Kleine-König wrote:
> Hello Hector,
>
> On Wed, Oct 02, 2013 at 02:02:44PM +0200, Hector Palacios wrote:
>> The shutdown function was not waiting for the FIFO (which may be the
>> real 16 byte FIFO or the DMA buffer, if DMA is enabled) to flush
>> before disabling the AUART.
>> This lead to many bytes not being transferred (specially at low
>> baudrates), as they were still in the DMA buffer when the AUART was
>> shutdown.
>> This patch also adds the check for the BUSY flag before disabling
>> the AUART.
>>
>> Signed-off-by: Hector Palacios <hector.palacios at digi.com>
>> ---
>> drivers/tty/serial/mxs-auart.c | 13 +++++++++++++
>> 1 file changed, 13 insertions(+)
>>
>> diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
>> index 9f046177..589b595 100644
>> --- a/drivers/tty/serial/mxs-auart.c
>> +++ b/drivers/tty/serial/mxs-auart.c
>> @@ -757,9 +757,22 @@ static int mxs_auart_startup(struct uart_port *u)
>> return 0;
>> }
>>
>> +static unsigned int mxs_auart_tx_empty(struct uart_port *u);
>> +
>> static void mxs_auart_shutdown(struct uart_port *u)
>> {
>> struct mxs_auart_port *s = to_auart_port(u);
>> + unsigned int to;
>> +
>> + /* Wait for the FIFO to flush */
>> + to = u->timeout;
>> + while (!mxs_auart_tx_empty(u) && to--)
>> + mdelay(1);
>> +
>> + /* Wait for UART to become idle ... */
>> + to = u->timeout;
>> + while ((readl(u->membase + AUART_STAT) & AUART_STAT_BUSY) && to--)
>> + mdelay(1);
> If the 2nd loop is needed the tx_empty callback is buggy. According to
> Documentation/serial/driver tx_empty "tests whether the transmitter fifo
> and shifter for the port [...] is empty". I guess it only tests for the
> fifo part? Time for another fix ...
Do you mean the tx_empty should check both for TX_FIFO and !BUSY, right?
I did it so because I thought the BUSY was also set during rx, but it is really only
used to signal tx operation.
That would turn this patch into this:
@@ -755,13 +755,21 @@ static int mxs_auart_startup(struct uart_port *u)
writel(AUART_LINECTRL_FEN, u->membase + AUART_LINECTRL_SET);
return 0;
}
+static unsigned int mxs_auart_tx_empty(struct uart_port *u);
+
static void mxs_auart_shutdown(struct uart_port *u)
{
struct mxs_auart_port *s = to_auart_port(u);
+ unsigned int to;
+
+ /* Wait for the FIFO to flush */
+ to = u->timeout;
+ while (!mxs_auart_tx_empty(u) && to--)
+ mdelay(1);
if (auart_dma_enabled(s))
mxs_auart_dma_exit(s);
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
@@ -774,14 +782,15 @@ static void mxs_auart_shutdown(struct uart_port *u)
clk_disable_unprepare(s->clk);
}
static unsigned int mxs_auart_tx_empty(struct uart_port *u)
{
- if (readl(u->membase + AUART_STAT) & AUART_STAT_TXFE)
- return TIOCSER_TEMT;
- else
- return 0;
+ if (!((readl(u->membase + AUART_STAT) & AUART_STAT_BUSY)))
+ if (readl(u->membase + AUART_STAT) & AUART_STAT_TXFE)
+ return TIOCSER_TEMT;
+
+ return 0;
}
static void mxs_auart_start_tx(struct uart_port *u)
{
struct mxs_auart_port *s = to_auart_port(u);
Do you agree?
Best regards,
--
Hector Palacios
More information about the linux-arm-kernel
mailing list