SAMA5: OHCI various bugfixes for interrupt handling

This commit is contained in:
Gregory Nutt 2013-08-24 13:03:15 -06:00
parent cd84d1bec4
commit 5f78f6998f

View File

@ -1995,6 +1995,7 @@ static void sam_ohci_bottomhalf(void *arg)
/* Now re-enable interrupts */ /* Now re-enable interrupts */
sam_putreg(OHCI_INT_MIE, SAM_USBHOST_INTEN); sam_putreg(OHCI_INT_MIE, SAM_USBHOST_INTEN);
sam_givesem(&g_ohci.exclsem);
} }
/******************************************************************************* /*******************************************************************************
@ -3264,41 +3265,53 @@ FAR struct usbhost_connection_s *sam_ohci_initialize(int controller)
int sam_ohci_tophalf(int irq, FAR void *context) int sam_ohci_tophalf(int irq, FAR void *context)
{ {
uint32_t intst; uint32_t intst;
uint32_t regval; uint32_t inten;
uint32_t pending; uint32_t pending;
/* Read Interrupt Status and mask out interrupts that are not enabled. */ /* Read Interrupt Status and mask out interrupts that are not enabled. */
intst = sam_getreg(SAM_USBHOST_INTST); intst = sam_getreg(SAM_USBHOST_INTST);
regval = sam_getreg(SAM_USBHOST_INTEN); inten = sam_getreg(SAM_USBHOST_INTEN);
ullvdbg("INST: %08x INTEN: %08x\n", intst, regval); ullvdbg("INST: %08x INTEN: %08x\n", intst, inten);
pending = intst & regval; #ifdef CONFIG_SAMA5_EHCI
if (pending != 0) /* Check the Master Interrupt Enable bit (MIE). It this function is called
* from the common UHPHS interrupt handler, there might be pending interrupts
* but with the overall interstate disabled. This could never happen if only
* OHCI were enabled because we would never get here.
*/
if ((inten & OHCI_INT_MIE) != 0)
#endif
{ {
/* Schedule interrupt handling work for the high priority worker thread /* Mask out the interrupts that are not enabled */
* so that we are not pressed for time and so that we can interrupt with pending = intst & inten;
* other USB threads gracefully. if (pending != 0)
* {
* The worker should be available now because we implement a handshake /* Schedule interrupt handling work for the high priority worker
* by controlling the OHCI interrupts. * thread so that we are not pressed for time and so that we can
*/ * interrupt with other USB threads gracefully.
*
* The worker should be available now because we implement a
* handshake by controlling the OHCI interrupts.
*/
DEBUGASSERT(work_available(&g_ohci.work)); DEBUGASSERT(work_available(&g_ohci.work));
DEBUGVERIFY(work_queue(HPWORK, &g_ohci.work, sam_ohci_bottomhalf, DEBUGVERIFY(work_queue(HPWORK, &g_ohci.work, sam_ohci_bottomhalf,
(FAR void *)pending, 0)); (FAR void *)pending, 0));
/* Disable further OHCI interrupts so that we do not overrun the work /* Disable further OHCI interrupts so that we do not overrun the
* queue. * work queue.
*/ */
sam_putreg(OHCI_INT_MIE, SAM_USBHOST_INTDIS); sam_putreg(OHCI_INT_MIE, SAM_USBHOST_INTDIS);
/* Clear all pending status bits by writing the value of the pending /* Clear all pending status bits by writing the value of the
* interrupt bits back to the status register. * pending interrupt bits back to the status register.
*/ */
sam_putreg(intst, SAM_USBHOST_INTST); sam_putreg(intst, SAM_USBHOST_INTST);
}
} }
return OK; return OK;