summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2020-04-02 16:34:42 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2020-10-27 06:33:04 +0100
commit2237f4b05334da9a6a450b48a7db38deaff4f1ef (patch)
treec3296e603e5ac71b49fc453f8f2a80e82fd222be
parentif_stmac: Add driver for STM32H7 ethernet module (diff)
downloadrtems-libbsd-2237f4b05334da9a6a450b48a7db38deaff4f1ef.tar.bz2
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.
-rw-r--r--freebsd/sys/dev/usb/controller/dwc_otg.c64
1 files 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 005c7ece..b75b8872 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);