Merged in david_s5/nuttx/master_kinetis_usb_fixes (pull request #634)

kinetis usb device fixes

* kinetis:usb device use correct CONFIG OTG control

* kinetis:usb device fix interrupt storm when cable is disconnected

      The DM, DP state were incorrect because the pulldowns were not
      enabled.

      Also the pending asynchronous resume interrupt needed to be
      re-armed after the suspend is in effect. This is now done in
      the isr.

Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
David Sidrane 2018-04-28 11:27:48 +00:00 committed by Gregory Nutt
parent efed1b6aa1
commit 7e756e413d

View File

@ -74,7 +74,7 @@
#include "chip/kinetis_sim.h"
#include "chip/kinetis_fmc.h"
#if defined(CONFIG_USBDEV) && defined(CONFIG_KINETIS_USBOTG)
#if defined(CONFIG_USBDEV)
/****************************************************************************
* Pre-processor Definitions
@ -2116,7 +2116,7 @@ static void khci_ep0setup(struct khci_usbdev_s *priv)
{
/* Disable B device from performing HNP */
#ifdef CONFIG_USBOTG
#ifdef CONFIG_KINETIS_USBOTG
if (value.w == USBOTG_FEATURE_B_HNP_ENABLE)
{
/* Disable HNP */
@ -2195,7 +2195,7 @@ static void khci_ep0setup(struct khci_usbdev_s *priv)
{
/* Enable B device to perform HNP */
#ifdef CONFIG_USBOTG
#ifdef CONFIG_KINETIS_USBOTG
if (value.w == USBOTG_FEATURE_B_HNP_ENABLE)
{
/* Enable HNP */
@ -2729,7 +2729,7 @@ static int khci_interrupt(int irq, void *context, FAR void *arg)
uint16_t usbir;
uint32_t regval;
int i;
#ifdef CONFIG_USBOTG
#ifdef CONFIG_KINETIS_USBOTG
uint16_t otgir;
#endif
@ -2739,7 +2739,7 @@ static int khci_interrupt(int irq, void *context, FAR void *arg)
usbir = khci_getreg(KINETIS_USB0_ISTAT) & khci_getreg(KINETIS_USB0_INTEN);
#if !defined(CONFIG_USBOTG)
#if !defined(CONFIG_KINETIS_USBOTG)
usbtrace(TRACE_INTENTRY(KHCI_TRACEINTID_INTERRUPT), usbir);
#else
otgir = khci_getreg(KINETIS_USB0_OTGISTAT) & khci_getreg(KINETIS_USB0_OTGICR);
@ -2753,7 +2753,7 @@ static int khci_interrupt(int irq, void *context, FAR void *arg)
{
/* Check if the 1 millisecond timer has expired */
if ((otgir & USBOTG_INT_T1MSEC) != 0)
if ((otgir & USB_OTGISTAT_ONEMSEC) != 0)
{
usbtrace(TRACE_INTDECODE(KHCI_TRACEINTID_T1MSEC), otgir);
@ -2766,7 +2766,7 @@ static int khci_interrupt(int irq, void *context, FAR void *arg)
/* Clear Interrupt 1 msec timer Flag */
khci_putreg(USBOTG_INT_T1MSEC, KINETIS_USB0_ISTAT);
khci_putreg(USB_OTGISTAT_ONEMSEC, KINETIS_USB0_OTGISTAT);
}
}
#endif
@ -2820,7 +2820,7 @@ static int khci_interrupt(int irq, void *context, FAR void *arg)
khci_ep0configure(priv);
priv->devstate = DEVSTATE_DEFAULT;
#ifdef CONFIG_USBOTG
#ifdef CONFIG_KINETIS_USBOTG
/* Disable and deactivate HNP */
#warning Missing Logic
#endif
@ -2830,17 +2830,17 @@ static int khci_interrupt(int irq, void *context, FAR void *arg)
goto interrupt_exit;
}
#ifdef CONFIG_USBOTG
#ifdef CONFIG_KINETIS_USBOTG
/* Check if the ID Pin Changed State */
if ((otgir & USBOTG_INT_ID) != 0)
if ((otgir & USB_OTGISTAT_IDCHG) != 0)
{
usbtrace(TRACE_INTDECODE(KHCI_TRACEINTID_OTGID), otgir);
/* Re-detect and re-initialize */
#warning "Missing logic"
khci_putreg(USBOTG_INT_ID, KINETIS_USB0_ISTAT);
khci_putreg(USB_OTGISTAT_IDCHG, KINETIS_USB0_OTGISTAT);
}
#endif
@ -2895,7 +2895,7 @@ static int khci_interrupt(int irq, void *context, FAR void *arg)
{
usbtrace(TRACE_INTDECODE(KHCI_TRACEINTID_IDLE), usbir);
#ifdef CONFIG_USBOTG
#ifdef CONFIG_KINETIS_USBOTG
/* If Suspended, Try to switch to Host */
#warning "Missing logic"
#else
@ -2905,11 +2905,26 @@ static int khci_interrupt(int irq, void *context, FAR void *arg)
khci_putreg(USB_INT_SLEEP, KINETIS_USB0_ISTAT);
}
/* Check for asynchronous resume interrupt */
if ((khci_getreg(KINETIS_USB0_USBTRC0) & USB_USBTRC0_RESUME_INT) != 0)
{
/* Just clear the asynchronous resume interrupt enable */
regval = khci_getreg(KINETIS_USB0_USBTRC0);
regval &= ~USB_USBTRC0_USBRESMEN;
khci_putreg(regval, KINETIS_USB0_USBTRC0);
}
/* It is pointless to continue servicing if the device is in suspend mode. */
if ((khci_getreg(KINETIS_USB0_USBCTRL) & USB_USBCTRL_SUSP) != 0)
{
/* Just clear the interrupt and return */
/* If we are still suspended then re-enable asynchronous resume interrupt */
regval = khci_getreg(KINETIS_USB0_USBTRC0);
regval |= USB_USBTRC0_USBRESMEN;
khci_putreg(regval, KINETIS_USB0_USBTRC0);
usbtrace(TRACE_INTDECODE(KHCI_TRACEINTID_SUSPENDED), khci_getreg(KINETIS_USB0_CTL));
goto interrupt_exit;
@ -2947,7 +2962,7 @@ static int khci_interrupt(int irq, void *context, FAR void *arg)
interrupt_exit:
kinetis_clrpend(KINETIS_IRQ_USBOTG);
#ifdef CONFIG_USBOTG
#ifdef CONFIG_KINETIS_USBOTG
usbtrace(TRACE_INTEXIT(KHCI_TRACEINTID_INTERRUPT), usbir | otgir);
#else
usbtrace(TRACE_INTEXIT(KHCI_TRACEINTID_INTERRUPT), usbir);
@ -2984,6 +2999,10 @@ static void khci_suspend(struct khci_usbdev_s *priv)
regval |= USB_INT_RESUME;
khci_putreg(regval, KINETIS_USB0_INTEN);
regval = khci_getreg(KINETIS_USB0_USBCTRL);
regval |= USB_USBCTRL_SUSP | USB_USBCTRL_PDE;
khci_putreg(regval, KINETIS_USB0_USBCTRL);
regval = khci_getreg(KINETIS_USB0_USBTRC0);
regval |= USB_USBTRC0_USBRESMEN;
khci_putreg(regval, KINETIS_USB0_USBTRC0);
@ -2994,9 +3013,6 @@ static void khci_suspend(struct khci_usbdev_s *priv)
kinetis_usbsuspend((struct usbdev_s *)priv, false);
regval = khci_getreg(KINETIS_USB0_USBCTRL);
regval |= USB_USBCTRL_SUSP;
khci_putreg(regval, KINETIS_USB0_USBCTRL);
}
/****************************************************************************
@ -3042,7 +3058,7 @@ static void khci_resume(struct khci_usbdev_s *priv)
/* Unsuspend */
regval = khci_getreg(KINETIS_USB0_USBCTRL);
regval &= ~USB_USBCTRL_SUSP;
regval &= ~(USB_USBCTRL_SUSP | USB_USBCTRL_PDE);
khci_putreg(regval, KINETIS_USB0_USBCTRL);
/* Enable the IDLE interrupt */
@ -4035,9 +4051,9 @@ static void khci_attach(struct khci_usbdev_s *priv)
/* Enable OTG */
#ifdef CONFIG_USBOTG
#ifdef CONFIG_KINETIS_USBOTG
regval = khci_getreg(KINETIS_USB0_OTGCTL);
regval |= (USBOTG_CON_DPPULUP | USBOTG_CON_OTGEN);
regval |= (USB_OTGCTL_DPHIGH | USB_OTGCTL_OTGEN);
khci_putreg(regval, KINETIS_USB0_OTGCTL);
#endif
@ -4568,4 +4584,4 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
leave_critical_section(flags);
return OK;
}
#endif /* CONFIG_USBDEV && CONFIG_KHCI_USB */
#endif /* CONFIG_USBDEV */