USB HCD driver

Theo Markettos linux-rpi at markettos.org.uk
Tue Jun 5 06:35:22 EDT 2012


On Tue, Jun 05, 2012 at 07:47:48AM +0100, Simon Arlott wrote:
> ARM has a "Fast Interrupt" handler that has priority over the normal
> interrupt handler, and can only handle one interrupt source (which is
> configurable).

FIQ is extra-low-latency because you jump directly into the service routine
to handle your chosen source - that's not even an indirect branch as there
is for the other processor vectors (IRQ, SWI, abort etc).  One way of FIQ
sharing is that you copy a short service routine into the FIQ vector space
(logical address 0x1C to 0x100 or larger, depending on memory map) and only
unmask the FIQ when you need to use it.  The next user copies over their own
routine when they need it.  An alternative is simply to probe the status of
several interrupt sources in the FIQ routine, but that wastes time.  FIQ
also has a set of shadow registers - you get a different R8-R14 from other
modes which means you can preassign them to useful values and don't need to
waste time stacking things.  A good FIQ routine touches RAM as little as
possible.

In the case of DWC USB, this little FIQ routine would check if 'something
interesting is happening', and despatch off to the full handler if so, and
otherwise clear the interrupt and return.

> Unfortunately it would be all or nothing for the USB host so you'd get
> all the non-Start-Of-Frame interrupts too. It could be possible for the
> FIQ to mask itself if the interrupt isn't SOF and then let the normal
> IRQ handler deal with it (and re-enable the FIQ).

There's two ways of dealing with that.  One is that interrupt controllers
have a 'FIQ downgrade', that means you can choose for something wired to the
FIQ interrupt line to cause an IRQ instead.  In BCM2835 any line can be a
FIQ or an IRQ, so you just need to poke the appropriate register to alter
the priority.

That doesn't help you if you're in the middle of an existing interrupt.  But
there's nothing to stop the FIQ handler from switching the CPU from FIQ32
mode to IRQ32 mode and calling the normal IRQ handler.  That handler won't
realise that it hasn't been called directly.  The only thing is you'd have
to fix up the return conditions (your return address/status are in R14_fiq
and SPSR_fiq not R14_irq/SPSR_irq).

Theo

-- 
Computer Laboratory, University of Cambridge



More information about the linux-rpi-kernel mailing list