[rtems-libbsd commit] dwc_otg: Update host frame interval

Sebastian Huber sebh at rtems.org
Tue Oct 27 05:32:36 UTC 2020


Module:    rtems-libbsd
Branch:    6-freebsd-12
Commit:    8c4c7807f52636fa2b6ed6f867f966a9cf7455be
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=8c4c7807f52636fa2b6ed6f867f966a9cf7455be

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Thu Apr  2 16:34:42 2020 +0200

dwc_otg: Update host frame interval

Update the host frame interval after a device connection.  Select also
the FS/LS PHY clock.  It is not clear if this works on all platforms.

Update #3910.

---

 freebsd/sys/dev/usb/controller/dwc_otg.c | 64 ++++++++++++--------------------
 1 file changed, 24 insertions(+), 40 deletions(-)

diff --git a/freebsd/sys/dev/usb/controller/dwc_otg.c b/freebsd/sys/dev/usb/controller/dwc_otg.c
index 005c7ec..b75b887 100644
--- a/freebsd/sys/dev/usb/controller/dwc_otg.c
+++ b/freebsd/sys/dev/usb/controller/dwc_otg.c
@@ -470,38 +470,31 @@ dwc_otg_uses_split(struct usb_device *udev)
 static void
 dwc_otg_update_host_frame_interval(struct dwc_otg_softc *sc)
 {
-
-  /*
-   * Disabled until further. Assuming that the register is already
-   * programmed correctly by the boot loader.
-   */
-#if 0
+	uint32_t fslpclksel;
+	uint32_t frint;
 	uint32_t temp;
 
-	/* setup HOST frame interval register, based on existing value */
-	temp = DWC_OTG_READ_4(sc, DOTG_HFIR) & HFIR_FRINT_MASK;
-	if (temp >= 10000)
-		temp /= 1000;
-	else
-		temp /= 125;
-
-	/* figure out nearest X-tal value */
-	if (temp >= 54)
-		temp = 60;	/* MHz */
-	else if (temp >= 39)
-		temp = 48;	/* MHz */
-	else
-		temp = 30;	/* MHz */
-
-	if (sc->sc_flags.status_high_speed)
-		temp *= 125;
-	else
-		temp *= 1000;
-
-	DPRINTF("HFIR=0x%08x\n", temp);
+	if (sc->sc_flags.status_high_speed ||
+	    sc->sc_phy_type != DWC_OTG_PHY_INTERNAL) {
+		fslpclksel = 0;
+		frint = 60000;
+	} else if (sc->sc_flags.status_low_speed) {
+		fslpclksel = 2;
+		frint = 6000;
+	} else {
+		fslpclksel = 1;
+		frint = 48000;
+	}
 
+	temp = DWC_OTG_READ_4(sc, DOTG_HFIR);
+	temp &= ~HFIR_FRINT_MASK;
+	temp |= frint;
 	DWC_OTG_WRITE_4(sc, DOTG_HFIR, temp);
-#endif
+
+	temp = DWC_OTG_READ_4(sc, DOTG_HCFG);
+	temp &= ~(HCFG_FSLSSUPP | HCFG_FSLSPCLKSEL_MASK);
+	temp |= (fslpclksel << HCFG_FSLSPCLKSEL_SHIFT);
+	DWC_OTG_WRITE_4(sc, DOTG_HCFG, temp);
 }
 
 static void
@@ -3049,8 +3042,10 @@ dwc_otg_interrupt(void *arg)
 		else
 			sc->sc_flags.status_high_speed = 0;
 
-		if (hprt & HPRT_PRTCONNDET)
+		if (hprt & HPRT_PRTCONNDET) {
 			sc->sc_flags.change_connect = 1;
+			dwc_otg_update_host_frame_interval(sc);
+		}
 
 		if (hprt & HPRT_PRTSUSP)
 			dwc_otg_suspend_irq(sc);
@@ -3059,9 +3054,6 @@ dwc_otg_interrupt(void *arg)
 
 		/* complete root HUB interrupt endpoint */
 		dwc_otg_root_intr(sc);
-
-		/* update host frame interval */
-		dwc_otg_update_host_frame_interval(sc);
 	}
 
 	/*
@@ -4049,14 +4041,6 @@ dwc_otg_init(struct dwc_otg_softc *sc)
 		DWC_OTG_WRITE_4(sc, DOTG_DAINTMSK, 0xFFFF);
 	}
 
-	if (sc->sc_mode == DWC_MODE_OTG || sc->sc_mode == DWC_MODE_HOST) {
-		/* setup clocks */
-		temp = DWC_OTG_READ_4(sc, DOTG_HCFG);
-		temp &= ~(HCFG_FSLSSUPP | HCFG_FSLSPCLKSEL_MASK);
-		temp |= (1 << HCFG_FSLSPCLKSEL_SHIFT);
-		DWC_OTG_WRITE_4(sc, DOTG_HCFG, temp);
-	}
-
 	/* only enable global IRQ */
 	DWC_OTG_WRITE_4(sc, DOTG_GAHBCFG,
 	    GAHBCFG_GLBLINTRMSK);



More information about the vc mailing list