mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 04:59:55 +00:00 
			
		
		
		
	feat(hal/usb): Make USB-DWC HAL&LL configuration independent
Previously, we included symbols from soc/usb_dwc_cfg.h and configured the HAL and LL according to it. Now we get the configuration in runtime from USB-DWC registers. Added missing definition for USB FS peripheral on ESP32-P4.
This commit is contained in:
		| @@ -1,4 +1,4 @@ | ||||
| [codespell] | ||||
| skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/* | ||||
| ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,ot,wel,parms | ||||
| ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,ot,wel,parms,ehen | ||||
| write-changes = true | ||||
|   | ||||
| @@ -9,7 +9,6 @@ | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
| #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 -------------------------------- | ||||
|   | ||||
| @@ -39,7 +39,7 @@ FORCE_INLINE_ATTR void usb_utmi_ll_configure_ls(usb_utmi_dev_t *hw, bool paralle | ||||
|  * | ||||
|  * @param[in] clk_en True to enable, false to disable | ||||
|  */ | ||||
| FORCE_INLINE_ATTR void usb_utmi_ll_enable_bus_clock(bool clk_en) | ||||
| FORCE_INLINE_ATTR void _usb_utmi_ll_enable_bus_clock(bool clk_en) | ||||
| { | ||||
|     // Enable/disable system clock for USB_UTMI and USB_DWC_HS | ||||
|     HP_SYS_CLKRST.soc_clk_ctrl1.reg_usb_otg20_sys_clk_en = clk_en; | ||||
| @@ -48,7 +48,7 @@ FORCE_INLINE_ATTR void usb_utmi_ll_enable_bus_clock(bool clk_en) | ||||
| } | ||||
|  | ||||
| // HP_SYS_CLKRST.soc_clk_ctrlx and LP_AON_CLKRST.hp_usb_clkrst_ctrlx are shared registers, so this function must be used in an atomic way | ||||
| #define usb_utmi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_utmi_ll_enable_bus_clock(__VA_ARGS__) | ||||
| #define usb_utmi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _usb_utmi_ll_enable_bus_clock(__VA_ARGS__) | ||||
|  | ||||
| /** | ||||
|  * @brief Reset the USB UTMI PHY and USB_DWC_HS controller | ||||
|   | ||||
| @@ -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 -------------------------------- | ||||
|   | ||||
| @@ -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 -------------------------------- | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -10,7 +10,6 @@ | ||||
| #include <stdlib.h> // 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 | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -1274,7 +1274,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)); | ||||
| @@ -1298,6 +1300,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(); | ||||
|  | ||||
| @@ -1410,14 +1413,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); | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Tomas Rezucha
					Tomas Rezucha