SAMA5: OHCI various bugfixes for interrupt handling
This commit is contained in:
parent
cd84d1bec4
commit
5f78f6998f
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user