diff --git a/src/device/dcd.h b/src/device/dcd.h index 8efbc90ef6..d14a94696b 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -132,6 +132,9 @@ void dcd_connect(uint8_t rhport) TU_ATTR_WEAK; // Disconnect by disabling internal pull-up resistor on D+/D- void dcd_disconnect(uint8_t rhport) TU_ATTR_WEAK; +// Set new (max) intended bus speed +void dcd_speed_set(tusb_speed_t speed) TU_ATTR_WEAK; + //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ diff --git a/src/device/usbd.c b/src/device/usbd.c index 167a053e21..7d2387c10e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -334,6 +334,15 @@ tusb_speed_t tud_speed_get(void) return (tusb_speed_t) _usbd_dev.speed; } +bool tud_speed_set(tusb_speed_t speed) +{ + TU_VERIFY(dcd_speed_set); + + dcd_speed_set(speed); + + return true; +} + bool tud_connected(void) { return _usbd_dev.connected; diff --git a/src/device/usbd.h b/src/device/usbd.h index 5839626114..86fa207f03 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -65,6 +65,10 @@ extern void dcd_int_handler(uint8_t rhport); // Get current bus speed tusb_speed_t tud_speed_get(void); +// Set new (max) intended bus speed +// Return false if not supported +bool tud_speed_set(tusb_speed_t speed); + // Check if device is connected (may not mounted/configured yet) // True if just got out of Bus Reset and received the very first data from host bool tud_connected(void); diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 3a9cca8086..1c5cb6cf47 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -95,6 +95,8 @@ static uint16_t ep0_pending[2]; // Index determines direction static uint16_t _allocated_fifo_words_tx; // TX FIFO size in words (IN EPs) static bool _out_ep_closed; // Flag to check if RX FIFO size needs an update (reduce its size) +static tusb_speed_t _usb_max_speed = TUSB_SPEED_INVALID; // Value to indicate the intended (max) USB speed + // Flush the TX-FIFO and wait until we have confirmed it cleared static void dcd_flush_tx_endpoint(dwc2_regs_t * dwc2, uint8_t epnum) { @@ -493,7 +495,20 @@ static void phy_hs_init(dwc2_regs_t * dwc2) // Set max speed uint32_t dcfg = dwc2->dcfg; dcfg &= ~DCFG_DSPD_Msk; - dcfg |= DCFG_DSPD_HS << DCFG_DSPD_Pos; + + // Handle the intended (max) speed + switch (_usb_max_speed) + { + // Limit to Full-Speed + case TUSB_SPEED_FULL: + dcfg |= DCFG_DSPD_FS_HSPHY << DCFG_DSPD_Pos; + break; + + // Default to Hi-Speed if speed is not Full-Speed + default: + dcfg |= DCFG_DSPD_HS << DCFG_DSPD_Pos; + break; + } // XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required // when using with some PHYs such as USB334x (USB3341, USB3343, USB3346, USB3347) @@ -1366,4 +1381,9 @@ void dcd_int_handler(uint8_t rhport) // } } +void dcd_speed_set(tusb_speed_t speed) +{ + _usb_max_speed = speed; +} + #endif