aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-02-17 13:34:37 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-02-17 13:34:37 +0000
commit24f6e5ca625bca50d593429ac7fc420f2658adc6 (patch)
treed0891ec8caf158219af4e462c054d71d4279cb53 /os
parent777fa5d5684ef62c7241e43a457acfb69965e4a3 (diff)
downloadChibiOS-24f6e5ca625bca50d593429ac7fc420f2658adc6.tar.gz
ChibiOS-24f6e5ca625bca50d593429ac7fc420f2658adc6.tar.bz2
ChibiOS-24f6e5ca625bca50d593429ac7fc420f2658adc6.zip
Fixed bug 3603362.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5220 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r--os/hal/platforms/STM32/OTGv1/stm32_otg.h2
-rw-r--r--os/hal/platforms/STM32/OTGv1/usb_lld.c87
-rw-r--r--os/hal/platforms/STM32/OTGv1/usb_lld.h7
3 files changed, 80 insertions, 16 deletions
diff --git a/os/hal/platforms/STM32/OTGv1/stm32_otg.h b/os/hal/platforms/STM32/OTGv1/stm32_otg.h
index 842ec80ea..9a28c7f08 100644
--- a/os/hal/platforms/STM32/OTGv1/stm32_otg.h
+++ b/os/hal/platforms/STM32/OTGv1/stm32_otg.h
@@ -238,6 +238,7 @@ typedef struct {
#define GUSBCFG_CTXPKT (1U<<31) /**< Corrupt Tx packet. */
#define GUSBCFG_FDMOD (1U<<30) /**< Force Device Mode. */
#define GUSBCFG_FHMOD (1U<<29) /**< Force Host Mode. */
+#define GUSBCFG_ULPIEVBUSD (1U<<20) /**< ULPI External VBUS Drive */
#define GUSBCFG_TRDT_MASK (15U<<10) /**< USB Turnaround time field
mask. */
#define GUSBCFG_TRDT(n) ((n)<<10) /**< USB Turnaround time field
@@ -679,6 +680,7 @@ typedef struct {
#define DSTS_ENUMSPD_MASK (3U<<1) /**< Enumerated speed mask. */
#define DSTS_ENUMSPD_FS_48 (3U<<1) /**< Full speed (PHY clock is
running at 48 MHz). */
+#define DSTS_ENUMSPD_HS_480 (0U<<1) /**< High speed */
#define DSTS_SUSPSTS (1U<<0) /**< Suspend status. */
/** @} */
diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.c b/os/hal/platforms/STM32/OTGv1/usb_lld.c
index 1bb29beae..119b5b610 100644
--- a/os/hal/platforms/STM32/OTGv1/usb_lld.c
+++ b/os/hal/platforms/STM32/OTGv1/usb_lld.c
@@ -37,7 +37,8 @@
/* Driver local definitions. */
/*===========================================================================*/
-#define TRDT_VALUE 5
+#define TRDT_VALUE 5
+#define TRDT_HS_VALUE 9
/*===========================================================================*/
/* Driver exported variables. */
@@ -605,11 +606,28 @@ static void otg_epout_handler(USBDriver *usbp, usbep_t ep) {
*/
static void usb_lld_serve_interrupt(USBDriver *usbp) {
stm32_otg_t *otgp = usbp->otg;
- uint32_t sts, src;
+ uint32_t sts, src, dsts_enumspd;
sts = otgp->GINTSTS & otgp->GINTMSK;
+ /* Writing 1's to this register clears those respective interrupt flags.*/
otgp->GINTSTS = sts;
+ if (sts & GINTSTS_WKUPINT) {
+ /* If clocks are gated off, turn them back on (may be the case if coming out
+ of suspend mode).*/
+ if (otgp->PCGCCTL & (PCGCCTL_STPPCLK | PCGCCTL_GATEHCLK)) {
+ /* Set to zero to un-gate the USB core clocks.*/
+ otgp->PCGCCTL &= ~(PCGCCTL_STPPCLK | PCGCCTL_GATEHCLK);
+ }
+
+ /* Clear the Remote Wake-up Signaling */
+ otgp->DCTL |= DCTL_RWUSIG;
+ }
+
+ if (sts & GINTSTS_USBSUSP) {
+ /* Implement suspend mode.*/
+ }
+
/* Reset interrupt handling.*/
if (sts & GINTSTS_USBRST) {
_usb_reset(usbp);
@@ -618,7 +636,13 @@ static void usb_lld_serve_interrupt(USBDriver *usbp) {
/* Enumeration done.*/
if (sts & GINTSTS_ENUMDNE) {
- (void)otgp->DSTS;
+ /* Full or High speed timing selection */
+ dsts_enumspd = (otgp->DSTS & DSTS_ENUMSPD_MASK);
+ if( dsts_enumspd == DSTS_ENUMSPD_HS_480 ) {
+ otgp->GUSBCFG = (otgp->GUSBCFG & ~(GUSBCFG_TRDT_MASK)) | GUSBCFG_TRDT(TRDT_HS_VALUE);
+ } else {
+ otgp->GUSBCFG = (otgp->GUSBCFG & ~(GUSBCFG_TRDT_MASK)) | GUSBCFG_TRDT(TRDT_VALUE);
+ }
}
/* SOF interrupt handling.*/
@@ -858,6 +882,12 @@ void usb_lld_start(USBDriver *usbp) {
#if STM32_USB_USE_OTG2
if (&USBD2 == usbp) {
/* OTG HS clock enable and reset.*/
+#if STM32_USE_USB_OTG2_ULPI
+ rccEnableAHB1((RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN |
+ RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIOHEN | RCC_AHB1ENR_GPIOIEN),
+ FALSE);
+ rccEnableAHB1(RCC_AHB1ENR_OTGHSULPIEN, FALSE);
+#endif
rccEnableOTG_HS(FALSE);
rccResetOTG_HS();
@@ -878,18 +908,39 @@ void usb_lld_start(USBDriver *usbp) {
usbp);
/* - Forced device mode.
- - USB turn-around time = TRDT_VALUE.
- - Full Speed 1.1 PHY.*/
+ - USB turn-around time = TRDT_VALUE. */
+#if STM32_USE_USB_OTG2_ULPI
+ /* High speed ULPI PHY */
+ otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE) | GUSBCFG_SRPCAP | GUSBCFG_HNPCAP;
+#else
+ /* - Full Speed 1.1 PHY.*/
otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE) | GUSBCFG_PHYSEL;
+#endif
+
+#if STM32_USE_USB_OTG2_HS
+ /* USB 2.0 High Speed PHY.*/
+ otgp->DCFG = 0x02200000 | DCFG_DSPD_HS;
+#else
/* 48MHz 1.1 PHY.*/
otgp->DCFG = 0x02200000 | DCFG_DSPD_FS11;
+#endif
/* PHY enabled.*/
otgp->PCGCCTL = 0;
- /* Internal FS PHY activation.*/
- otgp->GCCFG = GCCFG_VBUSASEN | GCCFG_VBUSBSEN | GCCFG_PWRDWN;
+ if (&USBD2 == usbp) {
+#if STM32_USE_USB_OTG2_ULPI
+ otgp->GCCFG = 0;
+#else
+ otgp->GCCFG = GCCFG_VBUSASEN | GCCFG_VBUSBSEN | GCCFG_PWRDWN;
+#endif
+ } else {
+ /* Internal FS PHY activation.*/
+ otgp->GCCFG = GCCFG_VBUSASEN | GCCFG_VBUSBSEN | GCCFG_PWRDWN;
+ }
+
+
/* Soft core reset.*/
otg_core_reset(usbp);
@@ -905,12 +956,13 @@ void usb_lld_start(USBDriver *usbp) {
otgp->DIEPMSK = 0;
otgp->DOEPMSK = 0;
otgp->DAINTMSK = 0;
- if (usbp->config->sof_cb == NULL)
- otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM /*| GINTMSK_USBSUSPM |
- GINTMSK_ESUSPM |*/;
- else
- otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM /*| GINTMSK_USBSUSPM |
- GINTMSK_ESUSPM */ | GINTMSK_SOFM;
+ if (usbp->config->sof_cb == NULL) {
+ otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM |
+ GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM;
+ } else {
+ otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM | GINTMSK_USBSUSPM |
+ GINTMSK_ESUSPM | GINTMSK_SRQM | GINTMSK_WKUM | GINTMSK_SOFM;
+ }
otgp->GINTSTS = 0xFFFFFFFF; /* Clears all pending IRQs, if any. */
/* Global interrupts enable.*/
@@ -937,17 +989,20 @@ void usb_lld_stop(USBDriver *usbp) {
otgp->GAHBCFG = 0;
otgp->GCCFG = 0;
-#if STM32_USB_USE_USB1
+#if STM32_USB_USE_OTG1
if (&USBD1 == usbp) {
nvicDisableVector(STM32_OTG1_NUMBER);
rccDisableOTG1(FALSE);
}
#endif
-#if STM32_USB_USE_USB2
+#if STM32_USB_USE_OTG2
if (&USBD2 == usbp) {
nvicDisableVector(STM32_OTG2_NUMBER);
- rccDisableOTG2(FALSE);
+ rccDisableOTG_HS(FALSE);
+#if STM32_USE_USB_OTG2_ULPI
+ rccDisableAHB1(RCC_AHB1ENR_OTGHSULPIEN, FALSE);
+#endif
}
#endif
}
diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.h b/os/hal/platforms/STM32/OTGv1/usb_lld.h
index 1ab3c0f0c..a95f45842 100644
--- a/os/hal/platforms/STM32/OTGv1/usb_lld.h
+++ b/os/hal/platforms/STM32/OTGv1/usb_lld.h
@@ -74,6 +74,13 @@
#endif
/**
+ * @brief ULPI support for OTH-HS.
+ */
+#if !defined(STM32_USE_USB_OTG2_ULPI) || defined(__DOXYGEN__)
+#define STM32_USE_USB_OTG2_ULPI FALSE
+#endif
+
+/**
* @brief OTG1 interrupt priority level setting.
*/
#if !defined(STM32_USB_OTG1_IRQ_PRIORITY) || defined(__DOXYGEN__)