diff --git a/components/hal/esp32p4/include/hal/usb_dwc_ll.h b/components/hal/esp32p4/include/hal/usb_dwc_ll.h index f93db6623c..fd0685a50d 100644 --- a/components/hal/esp32p4/include/hal/usb_dwc_ll.h +++ b/components/hal/esp32p4/include/hal/usb_dwc_ll.h @@ -9,7 +9,6 @@ #include #include #include "soc/usb_dwc_struct.h" -#include "soc/usb_dwc_cfg.h" #include "hal/usb_dwc_types.h" #include "hal/misc.h" @@ -20,8 +19,7 @@ extern "C" { /* ----------------------------- Helper Macros ------------------------------ */ // Get USB hardware instance -// TODO: extend this macros when we have support for both FS and HS hardware on P4 -#define USB_DWC_LL_GET_HW(num) (&USB_DWC_HS) +#define USB_DWC_LL_GET_HW(num) (((num) == 1) ? &USB_DWC_FS : &USB_DWC_HS) /* ----------------------------------------------------------------------------- --------------------------------- DWC Constants -------------------------------- @@ -221,11 +219,9 @@ static inline void usb_dwc_ll_gusbcfg_set_timeout_cal(usb_dwc_dev_t *hw, uint8_t static inline void usb_dwc_ll_gusbcfg_set_utmi_phy(usb_dwc_dev_t *hw) { -#if (OTG_HSPHY_INTERFACE != 0) hw->gusbcfg_reg.phyif = 1; // 16 bits interface hw->gusbcfg_reg.ulpiutmisel = 0; // UTMI+ hw->gusbcfg_reg.physel = 0; // HS PHY -#endif // (OTG_HSPHY_INTERFACE != 0) } // --------------------------- GRSTCTL Register -------------------------------- @@ -352,24 +348,19 @@ static inline uint32_t usb_dwc_ll_gsnpsid_get_id(usb_dwc_dev_t *hw) // --------------------------- GHWCFGx Register -------------------------------- -/** - * @brief Get the hardware configuration registers of the DWC_OTG controller - * - * The hardware configuration regitsers are read only and indicate the various - * features of the DWC_OTG core. - * - * @param hw Start address of the DWC_OTG registers - * @param[out] ghwcfg1 Hardware configuration registesr 1 - * @param[out] ghwcfg2 Hardware configuration registesr 2 - * @param[out] ghwcfg3 Hardware configuration registesr 3 - * @param[out] ghwcfg4 Hardware configuration registesr 4 - */ -static inline void usb_dwc_ll_ghwcfg_get_hw_config(usb_dwc_dev_t *hw, uint32_t *ghwcfg1, uint32_t *ghwcfg2, uint32_t *ghwcfg3, uint32_t *ghwcfg4) +static inline unsigned usb_dwc_ll_ghwcfg_get_fifo_depth(usb_dwc_dev_t *hw) { - *ghwcfg1 = hw->ghwcfg1_reg.val; - *ghwcfg2 = hw->ghwcfg2_reg.val; - *ghwcfg3 = hw->ghwcfg3_reg.val; - *ghwcfg4 = hw->ghwcfg4_reg.val; + return hw->ghwcfg3_reg.dfifodepth; +} + +static inline unsigned usb_dwc_ll_ghwcfg_get_hsphy_type(usb_dwc_dev_t *hw) +{ + return hw->ghwcfg2_reg.hsphytype; +} + +static inline unsigned usb_dwc_ll_ghwcfg_get_channel_num(usb_dwc_dev_t *hw) +{ + return hw->ghwcfg2_reg.numhstchnl; } // --------------------------- HPTXFSIZ Register ------------------------------- @@ -434,47 +425,44 @@ static inline void usb_dwc_ll_hcfg_set_fsls_supp_only(usb_dwc_dev_t *hw) hw->hcfg_reg.fslssupp = 1; } -static inline void usb_dwc_ll_hcfg_set_fsls_pclk_sel(usb_dwc_dev_t *hw) -{ - hw->hcfg_reg.fslspclksel = 1; -} - /** - * @brief Sets some default values to HCFG to operate in Host mode with scatter/gather DMA + * @brief Set FSLS PHY clock * + * @attention This function should only be called if FSLS PHY is selected * @param[in] hw Start address of the DWC_OTG registers - * @param[in] speed Speed to initialize the host port at */ -static inline void usb_dwc_ll_hcfg_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed) +static inline void usb_dwc_ll_hcfg_set_fsls_phy_clock(usb_dwc_dev_t *hw) { - hw->hcfg_reg.descdma = 1; //Enable scatt/gatt -#if (OTG_HSPHY_INTERFACE == 0) /* Indicate to the OTG core what speed the PHY clock is at - Note: It seems like S2/S3 PHY has an implicit 8 divider applied when in LS mode, + Note: FSLS PHY has an implicit 8 divider applied when in LS mode, so the values of FSLSPclkSel and FrInt have to be adjusted accordingly. */ - hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2; //PHY clock on esp32-sx for FS/LS-only -#endif // (OTG_HSPHY_INTERFACE == 0) - hw->hcfg_reg.perschedena = 0; //Disable perio sched + usb_dwc_speed_t speed = (usb_dwc_speed_t)hw->hprt_reg.prtspd; + hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2; } // ----------------------------- HFIR Register --------------------------------- -static inline void usb_dwc_ll_hfir_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed) +/** + * @brief Set Frame Interval + * + * @attention This function should only be called if FSLS PHY is selected + * @param[in] hw Start address of the DWC_OTG registers + */ +static inline void usb_dwc_ll_hfir_set_frame_interval(usb_dwc_dev_t *hw) { -#if (OTG_HSPHY_INTERFACE == 0) usb_dwc_hfir_reg_t hfir; hfir.val = hw->hfir_reg.val; - hfir.hfirrldctrl = 0; //Disable dynamic loading + hfir.hfirrldctrl = 0; // Disable dynamic loading /* Set frame interval to be equal to 1ms - Note: It seems like our PHY has an implicit 8 divider applied when in LS mode, + Note: FSLS PHY has an implicit 8 divider applied when in LS mode, so the values of FSLSPclkSel and FrInt have to be adjusted accordingly. */ - hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000; //esp32-sx targets only support FS or LS + usb_dwc_speed_t speed = (usb_dwc_speed_t)hw->hprt_reg.prtspd; + hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000; hw->hfir_reg.val = hfir.val; -#endif // (OTG_HSPHY_INTERFACE == 0) } // ----------------------------- HFNUM Register -------------------------------- diff --git a/components/hal/esp32s2/include/hal/usb_dwc_ll.h b/components/hal/esp32s2/include/hal/usb_dwc_ll.h index 954a54bf80..7426be2efa 100644 --- a/components/hal/esp32s2/include/hal/usb_dwc_ll.h +++ b/components/hal/esp32s2/include/hal/usb_dwc_ll.h @@ -220,11 +220,9 @@ static inline void usb_dwc_ll_gusbcfg_set_timeout_cal(usb_dwc_dev_t *hw, uint8_t static inline void usb_dwc_ll_gusbcfg_set_utmi_phy(usb_dwc_dev_t *hw) { -#if (OTG_HSPHY_INTERFACE != 0) hw->gusbcfg_reg.phyif = 1; // 16 bits interface hw->gusbcfg_reg.ulpiutmisel = 0; // UTMI+ hw->gusbcfg_reg.physel = 0; // HS PHY -#endif // (OTG_HSPHY_INTERFACE != 0) } // --------------------------- GRSTCTL Register -------------------------------- @@ -351,24 +349,19 @@ static inline uint32_t usb_dwc_ll_gsnpsid_get_id(usb_dwc_dev_t *hw) // --------------------------- GHWCFGx Register -------------------------------- -/** - * @brief Get the hardware configuration registers of the DWC_OTG controller - * - * The hardware configuration regitsers are read only and indicate the various - * features of the DWC_OTG core. - * - * @param hw Start address of the DWC_OTG registers - * @param[out] ghwcfg1 Hardware configuration registesr 1 - * @param[out] ghwcfg2 Hardware configuration registesr 2 - * @param[out] ghwcfg3 Hardware configuration registesr 3 - * @param[out] ghwcfg4 Hardware configuration registesr 4 - */ -static inline void usb_dwc_ll_ghwcfg_get_hw_config(usb_dwc_dev_t *hw, uint32_t *ghwcfg1, uint32_t *ghwcfg2, uint32_t *ghwcfg3, uint32_t *ghwcfg4) +static inline unsigned usb_dwc_ll_ghwcfg_get_fifo_depth(usb_dwc_dev_t *hw) { - *ghwcfg1 = hw->ghwcfg1_reg.val; - *ghwcfg2 = hw->ghwcfg2_reg.val; - *ghwcfg3 = hw->ghwcfg3_reg.val; - *ghwcfg4 = hw->ghwcfg4_reg.val; + return hw->ghwcfg3_reg.dfifodepth; +} + +static inline unsigned usb_dwc_ll_ghwcfg_get_hsphy_type(usb_dwc_dev_t *hw) +{ + return hw->ghwcfg2_reg.hsphytype; +} + +static inline unsigned usb_dwc_ll_ghwcfg_get_channel_num(usb_dwc_dev_t *hw) +{ + return hw->ghwcfg2_reg.numhstchnl; } // --------------------------- HPTXFSIZ Register ------------------------------- @@ -433,47 +426,44 @@ static inline void usb_dwc_ll_hcfg_set_fsls_supp_only(usb_dwc_dev_t *hw) hw->hcfg_reg.fslssupp = 1; } -static inline void usb_dwc_ll_hcfg_set_fsls_pclk_sel(usb_dwc_dev_t *hw) -{ - hw->hcfg_reg.fslspclksel = 1; -} - /** - * @brief Sets some default values to HCFG to operate in Host mode with scatter/gather DMA + * @brief Set FSLS PHY clock * + * @attention This function should only be called if FSLS PHY is selected * @param[in] hw Start address of the DWC_OTG registers - * @param[in] speed Speed to initialize the host port at */ -static inline void usb_dwc_ll_hcfg_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed) +static inline void usb_dwc_ll_hcfg_set_fsls_phy_clock(usb_dwc_dev_t *hw) { - hw->hcfg_reg.descdma = 1; //Enable scatt/gatt -#if (OTG_HSPHY_INTERFACE == 0) /* Indicate to the OTG core what speed the PHY clock is at - Note: It seems like S2/S3 PHY has an implicit 8 divider applied when in LS mode, + Note: FSLS PHY has an implicit 8 divider applied when in LS mode, so the values of FSLSPclkSel and FrInt have to be adjusted accordingly. */ - hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2; //PHY clock on esp32-sx for FS/LS-only -#endif // (OTG_HSPHY_INTERFACE == 0) - hw->hcfg_reg.perschedena = 0; //Disable perio sched + usb_dwc_speed_t speed = (usb_dwc_speed_t)hw->hprt_reg.prtspd; + hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2; } // ----------------------------- HFIR Register --------------------------------- -static inline void usb_dwc_ll_hfir_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed) +/** + * @brief Set Frame Interval + * + * @attention This function should only be called if FSLS PHY is selected + * @param[in] hw Start address of the DWC_OTG registers + */ +static inline void usb_dwc_ll_hfir_set_frame_interval(usb_dwc_dev_t *hw) { -#if (OTG_HSPHY_INTERFACE == 0) usb_dwc_hfir_reg_t hfir; hfir.val = hw->hfir_reg.val; - hfir.hfirrldctrl = 0; //Disable dynamic loading + hfir.hfirrldctrl = 0; // Disable dynamic loading /* Set frame interval to be equal to 1ms - Note: It seems like our PHY has an implicit 8 divider applied when in LS mode, + Note: FSLS PHY has an implicit 8 divider applied when in LS mode, so the values of FSLSPclkSel and FrInt have to be adjusted accordingly. */ - hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000; //esp32-sx targets only support FS or LS + usb_dwc_speed_t speed = (usb_dwc_speed_t)hw->hprt_reg.prtspd; + hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000; hw->hfir_reg.val = hfir.val; -#endif // (OTG_HSPHY_INTERFACE == 0) } // ----------------------------- HFNUM Register -------------------------------- diff --git a/components/hal/esp32s3/include/hal/usb_dwc_ll.h b/components/hal/esp32s3/include/hal/usb_dwc_ll.h index 954a54bf80..7426be2efa 100644 --- a/components/hal/esp32s3/include/hal/usb_dwc_ll.h +++ b/components/hal/esp32s3/include/hal/usb_dwc_ll.h @@ -220,11 +220,9 @@ static inline void usb_dwc_ll_gusbcfg_set_timeout_cal(usb_dwc_dev_t *hw, uint8_t static inline void usb_dwc_ll_gusbcfg_set_utmi_phy(usb_dwc_dev_t *hw) { -#if (OTG_HSPHY_INTERFACE != 0) hw->gusbcfg_reg.phyif = 1; // 16 bits interface hw->gusbcfg_reg.ulpiutmisel = 0; // UTMI+ hw->gusbcfg_reg.physel = 0; // HS PHY -#endif // (OTG_HSPHY_INTERFACE != 0) } // --------------------------- GRSTCTL Register -------------------------------- @@ -351,24 +349,19 @@ static inline uint32_t usb_dwc_ll_gsnpsid_get_id(usb_dwc_dev_t *hw) // --------------------------- GHWCFGx Register -------------------------------- -/** - * @brief Get the hardware configuration registers of the DWC_OTG controller - * - * The hardware configuration regitsers are read only and indicate the various - * features of the DWC_OTG core. - * - * @param hw Start address of the DWC_OTG registers - * @param[out] ghwcfg1 Hardware configuration registesr 1 - * @param[out] ghwcfg2 Hardware configuration registesr 2 - * @param[out] ghwcfg3 Hardware configuration registesr 3 - * @param[out] ghwcfg4 Hardware configuration registesr 4 - */ -static inline void usb_dwc_ll_ghwcfg_get_hw_config(usb_dwc_dev_t *hw, uint32_t *ghwcfg1, uint32_t *ghwcfg2, uint32_t *ghwcfg3, uint32_t *ghwcfg4) +static inline unsigned usb_dwc_ll_ghwcfg_get_fifo_depth(usb_dwc_dev_t *hw) { - *ghwcfg1 = hw->ghwcfg1_reg.val; - *ghwcfg2 = hw->ghwcfg2_reg.val; - *ghwcfg3 = hw->ghwcfg3_reg.val; - *ghwcfg4 = hw->ghwcfg4_reg.val; + return hw->ghwcfg3_reg.dfifodepth; +} + +static inline unsigned usb_dwc_ll_ghwcfg_get_hsphy_type(usb_dwc_dev_t *hw) +{ + return hw->ghwcfg2_reg.hsphytype; +} + +static inline unsigned usb_dwc_ll_ghwcfg_get_channel_num(usb_dwc_dev_t *hw) +{ + return hw->ghwcfg2_reg.numhstchnl; } // --------------------------- HPTXFSIZ Register ------------------------------- @@ -433,47 +426,44 @@ static inline void usb_dwc_ll_hcfg_set_fsls_supp_only(usb_dwc_dev_t *hw) hw->hcfg_reg.fslssupp = 1; } -static inline void usb_dwc_ll_hcfg_set_fsls_pclk_sel(usb_dwc_dev_t *hw) -{ - hw->hcfg_reg.fslspclksel = 1; -} - /** - * @brief Sets some default values to HCFG to operate in Host mode with scatter/gather DMA + * @brief Set FSLS PHY clock * + * @attention This function should only be called if FSLS PHY is selected * @param[in] hw Start address of the DWC_OTG registers - * @param[in] speed Speed to initialize the host port at */ -static inline void usb_dwc_ll_hcfg_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed) +static inline void usb_dwc_ll_hcfg_set_fsls_phy_clock(usb_dwc_dev_t *hw) { - hw->hcfg_reg.descdma = 1; //Enable scatt/gatt -#if (OTG_HSPHY_INTERFACE == 0) /* Indicate to the OTG core what speed the PHY clock is at - Note: It seems like S2/S3 PHY has an implicit 8 divider applied when in LS mode, + Note: FSLS PHY has an implicit 8 divider applied when in LS mode, so the values of FSLSPclkSel and FrInt have to be adjusted accordingly. */ - hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2; //PHY clock on esp32-sx for FS/LS-only -#endif // (OTG_HSPHY_INTERFACE == 0) - hw->hcfg_reg.perschedena = 0; //Disable perio sched + usb_dwc_speed_t speed = (usb_dwc_speed_t)hw->hprt_reg.prtspd; + hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2; } // ----------------------------- HFIR Register --------------------------------- -static inline void usb_dwc_ll_hfir_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed) +/** + * @brief Set Frame Interval + * + * @attention This function should only be called if FSLS PHY is selected + * @param[in] hw Start address of the DWC_OTG registers + */ +static inline void usb_dwc_ll_hfir_set_frame_interval(usb_dwc_dev_t *hw) { -#if (OTG_HSPHY_INTERFACE == 0) usb_dwc_hfir_reg_t hfir; hfir.val = hw->hfir_reg.val; - hfir.hfirrldctrl = 0; //Disable dynamic loading + hfir.hfirrldctrl = 0; // Disable dynamic loading /* Set frame interval to be equal to 1ms - Note: It seems like our PHY has an implicit 8 divider applied when in LS mode, + Note: FSLS PHY has an implicit 8 divider applied when in LS mode, so the values of FSLSPclkSel and FrInt have to be adjusted accordingly. */ - hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000; //esp32-sx targets only support FS or LS + usb_dwc_speed_t speed = (usb_dwc_speed_t)hw->hprt_reg.prtspd; + hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000; hw->hfir_reg.val = hfir.val; -#endif // (OTG_HSPHY_INTERFACE == 0) } // ----------------------------- HFNUM Register -------------------------------- diff --git a/components/hal/include/hal/usb_dwc_hal.h b/components/hal/include/hal/usb_dwc_hal.h index 33ac57be75..d4c880571f 100644 --- a/components/hal/include/hal/usb_dwc_hal.h +++ b/components/hal/include/hal/usb_dwc_hal.h @@ -171,13 +171,23 @@ typedef struct { * @brief HAL context structure */ typedef struct { - //Context - usb_dwc_dev_t *dev; /**< Pointer to base address of DWC_OTG registers */ - //Host Port related - uint32_t *periodic_frame_list; /**< Pointer to scheduling frame list */ - usb_hal_frame_list_len_t frame_list_len; /**< Length of the periodic scheduling frame list */ - //FIFO related - usb_dwc_hal_fifo_config_t fifo_config; /**< FIFO sizes configuration */ + // HW context + usb_dwc_dev_t *dev; /**< Pointer to base address of DWC_OTG registers */ + + // Host Port related + uint32_t *periodic_frame_list; /**< Pointer to scheduling frame list */ + usb_hal_frame_list_len_t frame_list_len; /**< Length of the periodic scheduling frame list */ + + // FIFO related + usb_dwc_hal_fifo_config_t fifo_config; /**< FIFO sizes configuration */ + + // Configuration of the USB-DWC core. Read from read-only HW registers + struct { + unsigned chan_num_total; /**< Total number of channels for this configuration */ + unsigned hsphy_type; /**< HS PHY type of this configuration */ + unsigned fifo_size; /**< Total FIFO size [in lines] in this configuration */ + } constant_config; + union { struct { uint32_t dbnc_lock_enabled: 1; /**< Debounce lock enabled */ @@ -188,11 +198,12 @@ typedef struct { }; uint32_t val; } flags; - //Channel related + + // Channel related struct { - int num_allocd; /**< Number of channels currently allocated */ - uint32_t chan_pend_intrs_msk; /**< Bit mask of channels with pending interrupts */ - usb_dwc_hal_chan_t *hdls[OTG_NUM_HOST_CHAN]; /**< Handles of each channel. Set to NULL if channel has not been allocated */ + int num_allocated; /**< Number of channels currently allocated */ + uint32_t chan_pend_intrs_msk; /**< Bit mask of channels with pending interrupts */ + usb_dwc_hal_chan_t **hdls; /**< Handles of each channel. Set to NULL if channel has not been allocated */ } channels; } usb_dwc_hal_context_t; @@ -208,16 +219,20 @@ typedef struct { * - Interrupt allocated but DISABLED (in case of an unknown interrupt state) * Exit: * - Checks to see if DWC_OTG is alive, and if HW version/config is correct - * - HAl context initialized + * - HAL context initialized + * - Read and save relevant USB-DWC configuration parameters * - Sets default values to some global and OTG registers (GAHBCFG and GUSBCFG) * - Umask global interrupt signal * - Put DWC_OTG into host mode. Require 25ms delay before this takes effect. * - State -> USB_DWC_HAL_PORT_STATE_OTG * - Interrupts cleared. Users can now enable their ISR * - * @param[inout] hal Context of the HAL layer + * @attention The user must allocate memory for channel handlers with + * `hal->channels.hdls = malloc(hal->constant_config.chan_num_total * sizeof(usb_dwc_hal_chan_t*))` + * @param[inout] hal Context of the HAL layer + * @param[in] port_id USB port ID */ -void usb_dwc_hal_init(usb_dwc_hal_context_t *hal); +void usb_dwc_hal_init(usb_dwc_hal_context_t *hal, int port_id); /** * @brief Deinitialize the HAL context @@ -241,7 +256,7 @@ void usb_dwc_hal_deinit(usb_dwc_hal_context_t *hal); * * @note This has nothing to do with a USB bus reset. It simply resets the peripheral * - * @param hal Context of the HAL layer + * @param[in] hal Context of the HAL layer */ void usb_dwc_hal_core_soft_reset(usb_dwc_hal_context_t *hal); diff --git a/components/hal/usb_dwc_hal.c b/components/hal/usb_dwc_hal.c index b6f3201b71..3f43762637 100644 --- a/components/hal/usb_dwc_hal.c +++ b/components/hal/usb_dwc_hal.c @@ -10,7 +10,6 @@ #include // For abort() #include "sdkconfig.h" #include "soc/chip_revision.h" -#include "soc/usb_dwc_cfg.h" #include "soc/usb_dwc_periph.h" #include "hal/usb_dwc_hal.h" #include "hal/usb_dwc_ll.h" @@ -112,10 +111,8 @@ static void set_defaults(usb_dwc_hal_context_t *hal) usb_dwc_ll_gusbcfg_dis_hnp_cap(hal->dev); //Disable HNP usb_dwc_ll_gusbcfg_dis_srp_cap(hal->dev); //Disable SRP - // Check if this USB-DWC supports HS PHY, if yes, use it - uint32_t ghwcfg[4]; - usb_dwc_ll_ghwcfg_get_hw_config(hal->dev, &ghwcfg[0], &ghwcfg[1], &ghwcfg[2], &ghwcfg[3]); - if (((usb_dwc_ghwcfg2_reg_t)ghwcfg[1]).hsphytype != 0) { + // If this USB-DWC supports HS PHY, use it + if (hal->constant_config.hsphy_type != 0) { usb_dwc_ll_gusbcfg_set_timeout_cal(hal->dev, 5); // 5 PHY clocks for our HS PHY usb_dwc_ll_gusbcfg_set_utmi_phy(hal->dev); } @@ -128,16 +125,29 @@ static void set_defaults(usb_dwc_hal_context_t *hal) usb_dwc_ll_gusbcfg_force_host_mode(hal->dev); } -void usb_dwc_hal_init(usb_dwc_hal_context_t *hal) +void usb_dwc_hal_init(usb_dwc_hal_context_t *hal, int port_id) { - //Check if a peripheral is alive by reading the core ID registers - usb_dwc_dev_t *dev = USB_DWC_LL_GET_HW(0); + // Check if a peripheral is alive by reading the core ID registers + HAL_ASSERT(port_id < SOC_USB_OTG_PERIPH_NUM); + usb_dwc_dev_t *dev = USB_DWC_LL_GET_HW(port_id); uint32_t core_id = usb_dwc_ll_gsnpsid_get_id(dev); HAL_ASSERT(core_id == CORE_REG_GSNPSID); (void) core_id; //Suppress unused variable warning if asserts are disabled - //Initialize HAL context + + // Initialize HAL context memset(hal, 0, sizeof(usb_dwc_hal_context_t)); hal->dev = dev; + + // Save constant configuration of this USB-DWC instance + /* + * EPINFO_CTL is located at the end of FIFO, its size is fixed in HW. + * The reserved size is always the worst-case, which is device mode that requires 4 locations per EP direction (including EP0). + * Here we just read the FIFO size from HW register, to avoid any ambivalence + */ + hal->constant_config.fifo_size = usb_dwc_ll_ghwcfg_get_fifo_depth(dev); + hal->constant_config.hsphy_type = usb_dwc_ll_ghwcfg_get_hsphy_type(dev); + hal->constant_config.chan_num_total = usb_dwc_ll_ghwcfg_get_channel_num(dev); + set_defaults(hal); } @@ -154,32 +164,31 @@ void usb_dwc_hal_core_soft_reset(usb_dwc_hal_context_t *hal) { usb_dwc_ll_grstctl_core_soft_reset(hal->dev); while (usb_dwc_ll_grstctl_is_core_soft_reset_in_progress(hal->dev)) { - ; //Wait until core reset is done + ; // Wait until core reset is done } while (!usb_dwc_ll_grstctl_is_ahb_idle(hal->dev)) { - ; //Wait until AHB Master bus is idle before doing any other operations + ; // Wait until AHB Master bus is idle before doing any other operations } - //Set the default bits + + // Set the default bits in USB-DWC registers set_defaults(hal); - //Clear all the flags and channels + + // Clear all the flags and channels hal->periodic_frame_list = NULL; hal->flags.val = 0; - hal->channels.num_allocd = 0; + hal->channels.num_allocated = 0; hal->channels.chan_pend_intrs_msk = 0; - memset(hal->channels.hdls, 0, sizeof(usb_dwc_hal_chan_t *) * OTG_NUM_HOST_CHAN); + if (hal->channels.hdls) { + for (int i = 0; i < hal->constant_config.chan_num_total; i++) { + hal->channels.hdls[i] = NULL; + } + } } void usb_dwc_hal_set_fifo_bias(usb_dwc_hal_context_t *hal, const usb_hal_fifo_bias_t fifo_bias) { - /* - * EPINFO_CTL is located at the end of FIFO, its size is fixed in HW. - * The reserved size is always the worst-case, which is device mode that requires 4 locations per EP direction (including EP0). - * Here we just read the FIFO size from HW register, to avoid any ambivalence - */ - uint32_t ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4; - usb_dwc_ll_ghwcfg_get_hw_config(hal->dev, &ghwcfg1, &ghwcfg2, &ghwcfg3, &ghwcfg4); - const uint16_t fifo_size_lines = ((usb_dwc_ghwcfg3_reg_t)ghwcfg3).dfifodepth; - + HAL_ASSERT(hal->channels.hdls); + const uint16_t fifo_size_lines = hal->constant_config.fifo_size; /* * Recommended FIFO sizes (see 2.1.2.4 for programming guide) * @@ -190,23 +199,28 @@ void usb_dwc_hal_set_fifo_bias(usb_dwc_hal_context_t *hal, const usb_hal_fifo_bi * Recommended sizes fit 2 packets of each type. For S2 and S3 we can't fit even one MPS ISOC packet (1023 FS and 1024 HS). * So the calculations below are compromises between the available FIFO size and optimal performance. */ + + // Information for maintainers: this calculation is here for backward compatibility + // It should be removed when we allow HAL users to configure the FIFO sizes IDF-9042 + const int otg_dfifo_depth = hal->constant_config.hsphy_type ? 1024 : 256; + usb_dwc_hal_fifo_config_t fifo_config; switch (fifo_bias) { // Define minimum viable (fits at least 1 MPS) FIFO sizes for non-biased FIFO types // Allocate the remaining size to the biased FIFO type case USB_HAL_FIFO_BIAS_DEFAULT: - fifo_config.nptx_fifo_lines = OTG_DFIFO_DEPTH / 4; - fifo_config.ptx_fifo_lines = OTG_DFIFO_DEPTH / 8; + fifo_config.nptx_fifo_lines = otg_dfifo_depth / 4; + fifo_config.ptx_fifo_lines = otg_dfifo_depth / 8; fifo_config.rx_fifo_lines = fifo_size_lines - fifo_config.ptx_fifo_lines - fifo_config.nptx_fifo_lines; break; case USB_HAL_FIFO_BIAS_RX: - fifo_config.nptx_fifo_lines = OTG_DFIFO_DEPTH / 16; - fifo_config.ptx_fifo_lines = OTG_DFIFO_DEPTH / 8; + fifo_config.nptx_fifo_lines = otg_dfifo_depth / 16; + fifo_config.ptx_fifo_lines = otg_dfifo_depth / 8; fifo_config.rx_fifo_lines = fifo_size_lines - fifo_config.ptx_fifo_lines - fifo_config.nptx_fifo_lines; break; case USB_HAL_FIFO_BIAS_PTX: - fifo_config.rx_fifo_lines = OTG_DFIFO_DEPTH / 8 + 2; // 2 extra lines are allocated for status information. See USB-OTG Programming Guide, chapter 2.1.2.1 - fifo_config.nptx_fifo_lines = OTG_DFIFO_DEPTH / 16; + fifo_config.rx_fifo_lines = otg_dfifo_depth / 8 + 2; // 2 extra lines are allocated for status information. See USB-OTG Programming Guide, chapter 2.1.2.1 + fifo_config.nptx_fifo_lines = otg_dfifo_depth / 16; fifo_config.ptx_fifo_lines = fifo_size_lines - fifo_config.nptx_fifo_lines - fifo_config.rx_fifo_lines; break; default: @@ -215,7 +229,7 @@ void usb_dwc_hal_set_fifo_bias(usb_dwc_hal_context_t *hal, const usb_hal_fifo_bi HAL_ASSERT((fifo_config.rx_fifo_lines + fifo_config.nptx_fifo_lines + fifo_config.ptx_fifo_lines) <= fifo_size_lines); //Check that none of the channels are active - for (int i = 0; i < OTG_NUM_HOST_CHAN; i++) { + for (int i = 0; i < hal->constant_config.chan_num_total; i++) { if (hal->channels.hdls[i] != NULL) { HAL_ASSERT(!hal->channels.hdls[i]->flags.active); } @@ -254,11 +268,15 @@ static inline void debounce_lock_enable(usb_dwc_hal_context_t *hal) void usb_dwc_hal_port_enable(usb_dwc_hal_context_t *hal) { - usb_dwc_speed_t speed = usb_dwc_ll_hprt_get_speed(hal->dev); - //Host Configuration - usb_dwc_ll_hcfg_set_defaults(hal->dev, speed); - //Configure HFIR - usb_dwc_ll_hfir_set_defaults(hal->dev, speed); + // Host Configuration + usb_dwc_ll_hcfg_en_scatt_gatt_dma(hal->dev); // Enable Scatther-Gather DMA mode + usb_dwc_ll_hcfg_dis_perio_sched(hal->dev); // Disable Periodic Scheduler (for now) + + // Configure PHY clock: Only for USB-DWC with FSLS PHY + if (hal->constant_config.hsphy_type == 0) { + usb_dwc_ll_hcfg_set_fsls_phy_clock(hal->dev); + usb_dwc_ll_hfir_set_frame_interval(hal->dev); + } } // ----------------------------------------------------- Channel ------------------------------------------------------- @@ -267,17 +285,18 @@ void usb_dwc_hal_port_enable(usb_dwc_hal_context_t *hal) bool usb_dwc_hal_chan_alloc(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan_obj, void *chan_ctx) { + HAL_ASSERT(hal->channels.hdls); HAL_ASSERT(hal->flags.fifo_sizes_set); //FIFO sizes should be set before attempting to allocate a channel //Attempt to allocate channel - if (hal->channels.num_allocd == OTG_NUM_HOST_CHAN) { + if (hal->channels.num_allocated == hal->constant_config.chan_num_total) { return false; //Out of free channels } int chan_idx = -1; - for (int i = 0; i < OTG_NUM_HOST_CHAN; i++) { + for (int i = 0; i < hal->constant_config.chan_num_total; i++) { if (hal->channels.hdls[i] == NULL) { hal->channels.hdls[i] = chan_obj; chan_idx = i; - hal->channels.num_allocd++; + hal->channels.num_allocated++; break; } } @@ -299,6 +318,7 @@ bool usb_dwc_hal_chan_alloc(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan void usb_dwc_hal_chan_free(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan_obj) { + HAL_ASSERT(hal->channels.hdls); if (chan_obj->type == USB_DWC_XFER_TYPE_INTR || chan_obj->type == USB_DWC_XFER_TYPE_ISOCHRONOUS) { //Unschedule this channel for (int i = 0; i < hal->frame_list_len; i++) { @@ -311,8 +331,8 @@ void usb_dwc_hal_chan_free(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan_ usb_dwc_ll_haintmsk_dis_chan_intr(hal->dev, 1 << chan_obj->flags.chan_idx); //Deallocate channel hal->channels.hdls[chan_obj->flags.chan_idx] = NULL; - hal->channels.num_allocd--; - HAL_ASSERT(hal->channels.num_allocd >= 0); + hal->channels.num_allocated--; + HAL_ASSERT(hal->channels.num_allocated >= 0); } // ---------------- Channel Configuration ------------------ @@ -464,6 +484,7 @@ usb_dwc_hal_port_event_t usb_dwc_hal_decode_intr(usb_dwc_hal_context_t *hal) usb_dwc_hal_chan_t *usb_dwc_hal_get_chan_pending_intr(usb_dwc_hal_context_t *hal) { + HAL_ASSERT(hal->channels.hdls); int chan_num = __builtin_ffs(hal->channels.chan_pend_intrs_msk); if (chan_num) { hal->channels.chan_pend_intrs_msk &= ~(1 << (chan_num - 1)); //Clear the pending bit for that channel diff --git a/components/soc/esp32p4/include/soc/usb_dwc_cfg.h b/components/soc/esp32p4/include/soc/usb_dwc_cfg.h index 3b5b887568..816cff4285 100644 --- a/components/soc/esp32p4/include/soc/usb_dwc_cfg.h +++ b/components/soc/esp32p4/include/soc/usb_dwc_cfg.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,94 +11,170 @@ extern "C" { #endif /* +HS Instance: Configuration Set ID: 11 */ /* 3.1 Basic Config Parameters */ -#define OTG_MODE 0 -#define OTG_ARCHITECTURE 2 -#define OTG_SINGLE_POINT 1 -#define OTG_ENABLE_LPM 0 -#define OTG_EN_DED_TX_FIFO 1 -#define OTG_EN_DESC_DMA 1 -#define OTG_MULTI_PROC_INTRPT 1 +#define OTG20_MODE 0 +#define OTG20_ARCHITECTURE 2 +#define OTG20_SINGLE_POINT 1 +#define OTG20_ENABLE_LPM 0 +#define OTG20_EN_DED_TX_FIFO 1 +#define OTG20_EN_DESC_DMA 1 +#define OTG20_MULTI_PROC_INTRPT 1 /* 3.2 USB Physical Layer Interface Parameters */ -#define OTG_HSPHY_INTERFACE 3 -#define OTG_HSPHY_DWIDTH 2 -#define OTG_FSPHY_INTERFACE 2 -#define OTG_ENABLE_IC_USB 0 -#define OTG_ENABLE_HSIC 0 -#define OTG_I2C_INTERFACE 0 -#define OTG_ULPI_CARKIT 1 -#define OTG_ADP_SUPPORT 1 -#define OTG_BC_SUPPORT 0 -#define OTG_VENDOR_CTL_INTERFACE 1 +#define OTG20_HSPHY_INTERFACE 3 +#define OTG20_HSPHY_DWIDTH 2 +#define OTG20_FSPHY_INTERFACE 2 +#define OTG20_ENABLE_IC_USB 0 +#define OTG20_ENABLE_HSIC 0 +#define OTG20_I2C_INTERFACE 0 +#define OTG20_ULPI_CARKIT 1 +#define OTG20_ADP_SUPPORT 1 +#define OTG20_BC_SUPPORT 0 +#define OTG20_VENDOR_CTL_INTERFACE 1 /* 3.3 Device Endpoint Configuration Parameters */ -#define OTG_NUM_EPS 15 -#define OTG_NUM_IN_EPS 8 -#define OTG_NUM_CRL_EPS 1 +#define OTG20_NUM_EPS 15 +#define OTG20_NUM_IN_EPS 8 +#define OTG20_NUM_CRL_EPS 1 /* 3.4 Host Endpoint Configuration Parameters */ -#define OTG_NUM_HOST_CHAN 16 -#define OTG_EN_PERIO_HOST 1 +#define OTG20_NUM_HOST_CHAN 16 +#define OTG20_EN_PERIO_HOST 1 /* 3.5 Endpoint Channel FIFO Configuration Parameters */ -#define OTG_DFIFO_DEPTH 1024 -#define OTG_DFIFO_DYNAMIC 1 -#define OTG_RX_DFIFO_DEPTH 1024 -#define OTG_TX_HNPERIO_DFIFO_DEPTH 1024 -#define OTG_TX_HPERIO_DFIFO_DEPTH 1024 -#define OTG_NPERIO_TX_QUEUE_DEPTH 4 -#define OTG_PERIO_TX_QUEUE_DEPTH 4 +#define OTG20_DFIFO_DEPTH 1024 +#define OTG20_DFIFO_DYNAMIC 1 +#define OTG20_RX_DFIFO_DEPTH 1024 +#define OTG20_TX_HNPERIO_DFIFO_DEPTH 1024 +#define OTG20_TX_HPERIO_DFIFO_DEPTH 1024 +#define OTG20_NPERIO_TX_QUEUE_DEPTH 4 +#define OTG20_PERIO_TX_QUEUE_DEPTH 4 /* 3.6 Additional Configuration Options Parameters */ -#define OTG_TRANS_COUNT_WIDTH 17 -#define OTG_PACKET_COUNT_WIDTH 8 -#define OTG_RM_OPT_FEATURES 1 -#define OTG_EN_PWROPT 1 -#define OTG_SYNC_RESET_TYPE 0 -#define OTG_EN_IDDIG_FILTER 1 -#define OTG_EN_VBUSVALID_FILTER 1 -#define OTG_EN_A_VALID_FILTER 1 -#define OTG_EN_B_VALID_FILTER 1 -#define OTG_EN_SESSIONEND_FILTER 1 -#define OTG_EXCP_CNTL_XFER_FLOW 1 -#define OTG_PWR_CLAMP 0 -#define OTG_PWR_SWITCH_POLARITY 0 +#define OTG20_TRANS_COUNT_WIDTH 17 +#define OTG20_PACKET_COUNT_WIDTH 8 +#define OTG20_RM_OPT_FEATURES 1 +#define OTG20_EN_PWROPT 1 +#define OTG20_SYNC_RESET_TYPE 0 +#define OTG20_EN_IDDIG_FILTER 1 +#define OTG20_EN_VBUSVALID_FILTER 1 +#define OTG20_EN_A_VALID_FILTER 1 +#define OTG20_EN_B_VALID_FILTER 1 +#define OTG20_EN_SESSIONEND_FILTER 1 +#define OTG20_EXCP_CNTL_XFER_FLOW 1 +#define OTG20_PWR_CLAMP 0 +#define OTG20_PWR_SWITCH_POLARITY 0 /* 3.7 Endpoint Direction Parameters */ -#define OTG_EP_DIR_1 0 -#define OTG_EP_DIR_2 0 -#define OTG_EP_DIR_3 0 -#define OTG_EP_DIR_4 0 -#define OTG_EP_DIR_5 0 -#define OTG_EP_DIR_6 0 -#define OTG_EP_DIR_7 0 -#define OTG_EP_DIR_8 0 -#define OTG_EP_DIR_9 0 -#define OTG_EP_DIR_10 0 -#define OTG_EP_DIR_11 0 -#define OTG_EP_DIR_12 0 -#define OTG_EP_DIR_13 0 -#define OTG_EP_DIR_14 0 -#define OTG_EP_DIR_15 0 +#define OTG20_EP_DIR_1 0 +#define OTG20_EP_DIR_2 0 +#define OTG20_EP_DIR_3 0 +#define OTG20_EP_DIR_4 0 +#define OTG20_EP_DIR_5 0 +#define OTG20_EP_DIR_6 0 +#define OTG20_EP_DIR_7 0 +#define OTG20_EP_DIR_8 0 +#define OTG20_EP_DIR_9 0 +#define OTG20_EP_DIR_10 0 +#define OTG20_EP_DIR_11 0 +#define OTG20_EP_DIR_12 0 +#define OTG20_EP_DIR_13 0 +#define OTG20_EP_DIR_14 0 +#define OTG20_EP_DIR_15 0 /* 3.8 Device Periodic FIFO Depth Parameters */ /* 3.9 Device IN Endpoint FIFO Depth Parameters */ -#define OTG_TX_DINEP_DFIFO_DEPTH_0 512 -#define OTG_TX_DINEP_DFIFO_DEPTH_1 512 -#define OTG_TX_DINEP_DFIFO_DEPTH_2 512 -#define OTG_TX_DINEP_DFIFO_DEPTH_3 512 -#define OTG_TX_DINEP_DFIFO_DEPTH_4 512 -#define OTG_TX_DINEP_DFIFO_DEPTH_5 512 -#define OTG_TX_DINEP_DFIFO_DEPTH_6 512 -#define OTG_TX_DINEP_DFIFO_DEPTH_7 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_0 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_1 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_2 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_3 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_4 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_5 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_6 512 +#define OTG20_TX_DINEP_DFIFO_DEPTH_7 512 /* 3.10 UTMI-To-UTMI Bridge Component Parameters */ -#define DWC_U2UB_EN 0 +#define OTG20_U2UB_EN 0 + +/* +FS Instance: +Configuration Set ID: 1 +*/ + +/* 3.1 Basic Config Parameters */ +#define OTG11_MODE 0 +#define OTG11_ARCHITECTURE 2 +#define OTG11_SINGLE_POINT 1 +#define OTG11_ENABLE_LPM 0 +#define OTG11_EN_DED_TX_FIFO 1 +#define OTG11_EN_DESC_DMA 1 +#define OTG11_MULTI_PROC_INTRPT 0 + +/* 3.2 USB Physical Layer Interface Parameters */ +#define OTG11_HSPHY_INTERFACE 0 +#define OTG11_FSPHY_INTERFACE 1 +#define OTG11_ENABLE_IC_USB 0 +#define OTG11_I2C_INTERFACE 0 +#define OTG11_ADP_SUPPORT 0 +#define OTG11_BC_SUPPORT 0 + +/* 3.3 Device Endpoint Configuration Parameters */ +#define OTG11_NUM_EPS 6 +#define OTG11_NUM_IN_EPS 5 +#define OTG11_NUM_CRL_EPS 0 + +/* 3.4 Host Endpoint Configuration Parameters */ +#define OTG11_NUM_HOST_CHAN 8 +#define OTG11_EN_PERIO_HOST 1 + +/* 3.5 Endpoint Channel FIFO Configuration Parameters */ +#define OTG11_DFIFO_DEPTH 256 +#define OTG11_DFIFO_DYNAMIC 1 +#define OTG11_RX_DFIFO_DEPTH 256 +#define OTG11_TX_HNPERIO_DFIFO_DEPTH 256 +#define OTG11_TX_NPERIO_DFIFO_DEPTH 256 +#define OTG11_TX_HPERIO_DFIFO_DEPTH 256 +#define OTG11_NPERIO_TX_QUEUE_DEPTH 4 +#define OTG11_PERIO_TX_QUEUE_DEPTH 8 + +/* 3.6 Additional Configuration Options Parameters */ +#define OTG11_TRANS_COUNT_WIDTH 16 +#define OTG11_PACKET_COUNT_WIDTH 7 +#define OTG11_RM_OPT_FEATURES 1 +#define OTG11_EN_PWROPT 1 +#define OTG11_SYNC_RESET_TYPE 0 +#define OTG11_EN_IDDIG_FILTER 1 +#define OTG11_EN_VBUSVALID_FILTER 1 +#define OTG11_EN_A_VALID_FILTER 1 +#define OTG11_EN_B_VALID_FILTER 1 +#define OTG11_EN_SESSIONEND_FILTER 1 +#define OTG11_EXCP_CNTL_XFER_FLOW 1 +#define OTG11_PWR_CLAMP 0 +#define OTG11_PWR_SWITCH_POLARITY 0 + +/* 3.7 Endpoint Direction Parameters */ +#define OTG11_EP_DIR_1 0 +#define OTG11_EP_DIR_2 0 +#define OTG11_EP_DIR_3 0 +#define OTG11_EP_DIR_4 0 +#define OTG11_EP_DIR_5 0 +#define OTG11_EP_DIR_6 0 + +/* 3.8 Device Periodic FIFO Depth Parameters */ + +/* 3.9 Device IN Endpoint FIFO Depth Parameters */ +#define OTG11_TX_DINEP_DFIFO_DEPTH_1 256 +#define OTG11_TX_DINEP_DFIFO_DEPTH_2 256 +#define OTG11_TX_DINEP_DFIFO_DEPTH_3 256 +#define OTG11_TX_DINEP_DFIFO_DEPTH_4 256 + +/* 3.10 UTMI-To-UTMI Bridge Component Parameters */ +#define OTG11_U2UB_EN 0 #ifdef __cplusplus } diff --git a/components/soc/esp32p4/include/soc/usb_dwc_struct.h b/components/soc/esp32p4/include/soc/usb_dwc_struct.h index 206d566277..f07575c52a 100644 --- a/components/soc/esp32p4/include/soc/usb_dwc_struct.h +++ b/components/soc/esp32p4/include/soc/usb_dwc_struct.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,7 +13,10 @@ extern "C" { #endif /* -Registers and fields were generated based on a set of configuration options. +Registers and fields were generated based on a set of USB-DWC configuration options. +ESP32-P4 contains 2 instances of USB-DWC with different configurations, the structure below corresponds to the HS instance. +The FS instance contains a subset of registers from HS instance, the user (HAL) is responsible for accessing only existing fields. + See ESP32-P4 "usb_dwc_cfg.h" for more details. */ @@ -1368,6 +1371,7 @@ _Static_assert(sizeof(usb_dwc_dev_t) == 0xe08, "Invalid size of usb_dwc_dev_t st #endif extern usb_dwc_dev_t USB_DWC_HS; +extern usb_dwc_dev_t USB_DWC_FS; #ifdef __cplusplus } diff --git a/components/soc/esp32s2/include/soc/usb_dwc_struct.h b/components/soc/esp32s2/include/soc/usb_dwc_struct.h index c6da8d901f..4d8f3e4a79 100644 --- a/components/soc/esp32s2/include/soc/usb_dwc_struct.h +++ b/components/soc/esp32s2/include/soc/usb_dwc_struct.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -88,7 +88,7 @@ typedef union { struct { uint32_t toutcal: 3; uint32_t phyif: 1; - uint32_t reserved_4: 1; + uint32_t ulpiutmisel: 1; uint32_t fsintf: 1; uint32_t physel: 1; uint32_t reserved_7: 1; diff --git a/components/soc/esp32s3/include/soc/usb_dwc_struct.h b/components/soc/esp32s3/include/soc/usb_dwc_struct.h index 70f73e37b7..1910ca2049 100644 --- a/components/soc/esp32s3/include/soc/usb_dwc_struct.h +++ b/components/soc/esp32s3/include/soc/usb_dwc_struct.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -88,7 +88,7 @@ typedef union { struct { uint32_t toutcal: 3; uint32_t phyif: 1; - uint32_t reserved_4: 1; + uint32_t ulpiutmisel: 1; uint32_t fsintf: 1; uint32_t physel: 1; uint32_t reserved_7: 1; diff --git a/components/usb/hcd_dwc.c b/components/usb/hcd_dwc.c index 7254ba3f0c..21e13db301 100644 --- a/components/usb/hcd_dwc.c +++ b/components/usb/hcd_dwc.c @@ -1276,7 +1276,9 @@ esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, h port_obj->callback = port_config->callback; port_obj->callback_arg = port_config->callback_arg; port_obj->context = port_config->context; - usb_dwc_hal_init(port_obj->hal); + usb_dwc_hal_init(port_obj->hal, 0); + port_obj->hal->channels.hdls = calloc(port_obj->hal->constant_config.chan_num_total, sizeof(usb_dwc_hal_chan_t*)); + HCD_CHECK_FROM_CRIT(port_obj->hal->channels.hdls != NULL, ESP_ERR_NO_MEM); port_obj->initialized = true; // Clear the frame list. We set the frame list register and enable periodic scheduling after a successful reset memset(port_obj->frame_list, 0, FRAME_LIST_LEN * sizeof(uint32_t)); @@ -1300,6 +1302,7 @@ esp_err_t hcd_port_deinit(hcd_port_handle_t port_hdl) ESP_ERR_INVALID_STATE); port->initialized = false; esp_intr_disable(s_hcd_obj->isr_hdl); + free(port->hal->channels.hdls); usb_dwc_hal_deinit(port->hal); HCD_EXIT_CRITICAL(); @@ -1412,14 +1415,14 @@ esp_err_t hcd_port_recover(hcd_port_handle_t port_hdl) && port->num_pipes_idle == 0 && port->num_pipes_queued == 0 && port->flags.val == 0 && port->task_waiting_port_notif == NULL, ESP_ERR_INVALID_STATE); + // We are about to do a soft reset on the peripheral. Disable the peripheral throughout esp_intr_disable(s_hcd_obj->isr_hdl); usb_dwc_hal_core_soft_reset(port->hal); port->state = HCD_PORT_STATE_NOT_POWERED; port->last_event = HCD_PORT_EVENT_NONE; port->flags.val = 0; - // Soft reset wipes all registers so we need to reinitialize the HAL - usb_dwc_hal_init(port->hal); + // Clear the frame list. We set the frame list register and enable periodic scheduling after a successful reset memset(port->frame_list, 0, FRAME_LIST_LEN * sizeof(uint32_t)); esp_intr_enable(s_hcd_obj->isr_hdl); diff --git a/components/usb/test_apps/hcd/main/test_hcd_isoc.c b/components/usb/test_apps/hcd/main/test_hcd_isoc.c index 1f6420bf81..2f5f837af4 100644 --- a/components/usb/test_apps/hcd/main/test_hcd_isoc.c +++ b/components/usb/test_apps/hcd/main/test_hcd_isoc.c @@ -6,7 +6,7 @@ #include #include -#include "soc/usb_dwc_cfg.h" +#include "hal/usb_dwc_ll.h" // For USB-DWC configuration #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "unity.h" @@ -17,7 +17,7 @@ #define NUM_URBS 3 #define NUM_PACKETS_PER_URB 3 #define POST_ENQUEUE_DELAY_US 20 -#define ENQUEUE_DELAY (OTG_HSPHY_INTERFACE ? 100 : 500) // With this delay we want to enqueue the URBs at different times +#define ENQUEUE_DELAY (usb_dwc_ll_ghwcfg_get_hsphy_type(USB_DWC_LL_GET_HW(0)) ? 100 : 500) // With this delay we want to enqueue the URBs at different times /* Test HCD ISOC pipe URBs @@ -126,12 +126,12 @@ TEST_CASE("Test HCD isochronous pipe URBs all", "[isoc][full_speed][high_speed]" uint8_t dev_addr = test_hcd_enum_device(default_pipe); urb_t *urb_list[NUM_URBS]; - hcd_pipe_handle_t unused_pipes[OTG_NUM_HOST_CHAN]; + hcd_pipe_handle_t unused_pipes[16]; const usb_ep_desc_t *out_ep_desc = dev_isoc_get_out_ep_desc(port_speed); const int isoc_packet_size = USB_EP_DESC_GET_MPS(out_ep_desc); - // For all channels - for (int channel = 0; channel < OTG_NUM_HOST_CHAN - 1; channel++) { + // For all channels (except channel allocated for EP0) + for (int channel = 0; channel < usb_dwc_ll_ghwcfg_get_channel_num(USB_DWC_LL_GET_HW(0)) - 1; channel++) { // Allocate unused pipes, so the active isoc_out_pipe uses different channel index for (int ch = 0; ch < channel; ch++) { unused_pipes[ch] = test_hcd_pipe_alloc(port_hdl, out_ep_desc, dev_addr + 1, port_speed);