[PATCH] ARM: add PrimeCell generic DMA to PL011

Russell King - ARM Linux linux at arm.linux.org.uk
Wed Dec 22 15:34:39 EST 2010


On Wed, Dec 22, 2010 at 06:20:41PM +0000, Russell King - ARM Linux wrote:
> On Wed, Dec 22, 2010 at 06:09:22PM +0100, Linus Walleij wrote:
> > 2010/12/22 Russell King - ARM Linux <linux at arm.linux.org.uk>:
> > > On Wed, Oct 06, 2010 at 11:32:06AM +0200, Linus Walleij wrote:
> > >>       /*
> > >> -      * Finally, enable interrupts
> > >> +      * Finally, enable interrupts, only timeouts when using DMA
> > >> +      * if initial RX DMA job failed, start in interrupt mode
> > >> +      * as well.
> > >>        */
> > >>       spin_lock_irq(&uap->port.lock);
> > >> -     uap->im = UART011_RXIM | UART011_RTIM;
> > >> +     if (uap->enable_dma && uap->rx_dma_running)
> > >> +             uap->im = UART011_RTIM;
> > >> +     else
> > >> +             uap->im = UART011_RXIM | UART011_RTIM;
> > >>       writew(uap->im, uap->port.membase + UART011_IMSC);
> > >
> > > There's a big hole here, using DMA on the receive path.
> > >
> > > | 3.4.4 UARTRTINTR
> > > | The receive timeout interrupt is asserted when the receive FIFO is not
> > > | empty, and no further data is received over a 32-bit period. The receive
> > > | timeout interrupt is cleared either when the FIFO becomes empty through
> > > | reading all the data (or by reading the holding register), or when a 1
> > > | is written to the corresponding bit of the UARTICR register.
> > >
> > > There must be unread data in the FIFO for us to get a RT interrupt.  The
> > > problem is that if we have DMA enabled, then the received characters are
> > > read from the FIFO as soon as they appear, and so the FIFO becomes empty,
> > > which negates the conditions required for the RT interrupt to be
> > > generated.
> > 
> > The DMA on the RX channel will not read single bytes at all,
> > instead it waits until it can retrieve a burst, which is set to half
> > a FIFO: src_maxburst = uap->fifosize >> 1,
> 
> I refer you to section 2.7, which describes the DMA interface.
> 
> UARTRXDMASREQ
> Single character DMA transfer request, asserted by the UART. For
> receive, one character consists of up to 12 bits. This signal is asserted
> when the receive FIFO contains at least one character.
> 
> UARTRXDMABREQ
> Burst DMA transfer request, asserted by the UART. This signal is
> asserted when the receive FIFO contains more characters than the
> programmed watermark level. You can program the watermark level for
> each FIFO through the UARTIFLS register.
> 
> If your DMA controller is using UARTRXDMASREQ, then you'll end up DMAing
> single bytes as long as the FIFO contains any bytes - thereby causing
> it to be emptied completely.  As 3.4.4 says, if the FIFO is empty, you
> don't get the timeout.
> 
> The PB926 doesn't specify whether it connects the burst or single-
> character DMA request signal to the DMA controller - from the behaviour
> I observe, I suspect it's the single character request which is.

And here's what /proc/interrupts reports:

 12:         38         VIC  uart-pl011

Now, I send exactly one 'o' to the port:

 12:         38         VIC  uart-pl011

no interrupt received.  If I extend PL08x's debugfs output to include
a register dump (src, dest, lli, ctrl, conf):

0               uart0rx
                [101f1000 019c4007 0111c011 1a0123f9 0000d01d]

now if I send three characters:

0               uart0rx
                [101f1000 019c400a 0111c011 1a0123f6 0000d01d]

Note that the address has increased by three, and the count has
decremented by three.  This confirms that the DMA is reading the data as
the UART FIFO fills - rather than DMA waiting for the FIFO to partially
fill before starting a request.

This emptying of the RX UART FIFO of all received data prevents the RX
timeout condition being satisfied, which in turn prevents any reasonable
use of the UART port.

I think the answer here is to allow the platform to supply just the TX
DMA channel, so when a UART is wired up to use the single-character
request, RX DMA support can be omitted.



More information about the linux-arm-kernel mailing list