From 7e756e413d14859f57304b83d11f6c8c10db47cd Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Sat, 28 Apr 2018 11:27:48 +0000 Subject: [PATCH] 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 --- arch/arm/src/kinetis/kinetis_usbdev.c | 58 +++++++++++++++++---------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/arch/arm/src/kinetis/kinetis_usbdev.c b/arch/arm/src/kinetis/kinetis_usbdev.c index 9fd71b3e784..cb8f1ec6a47 100644 --- a/arch/arm/src/kinetis/kinetis_usbdev.c +++ b/arch/arm/src/kinetis/kinetis_usbdev.c @@ -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 */