@@ -245,8 +245,8 @@ struct port_obj {
245245 uint32_t val ;
246246 } flags ;
247247 bool initialized ;
248- // FIFO biasing related
249- usb_hal_fifo_bias_t fifo_bias ; // Bias is saved so it can be reconfigured upon reset
248+ // FIFO related
249+ usb_dwc_hal_fifo_config_t fifo_config ; // FIFO config to be applied at HAL level
250250 // Port callback and context
251251 hcd_port_callback_t callback ;
252252 void * callback_arg ;
@@ -549,6 +549,23 @@ static bool _port_check_all_pipes_halted(port_t *port);
549549 */
550550static bool _port_debounce (port_t * port );
551551
552+ /**
553+ * @brief Convert user-provided FIFO configuration to HAL format
554+ *
555+ * This function validates and converts a user-defined FIFO configuration
556+ * (provided via `hcd_config_t.fifo_config`) into the format expected by the HAL.
557+ * It ensures that both RX FIFO and Non-Periodic TX FIFO sizes are non-zero.
558+ *
559+ * @param[in] src Pointer to user-defined FIFO settings (HCD format)
560+ * @param[out] dst Pointer to HAL-compatible FIFO configuration structure
561+ *
562+ * @return
563+ * - ESP_OK: Conversion successful and values copied
564+ * - ESP_ERR_INVALID_SIZE: Either RX FIFO or Non-Periodic TX FIFO is zero
565+ */
566+
567+ static esp_err_t convert_fifo_config_to_hal_config (const hcd_fifo_settings_t * src , usb_dwc_hal_fifo_config_t * dst );
568+
552569/**
553570 * @brief Power ON the port
554571 *
@@ -739,16 +756,6 @@ static usb_speed_t get_usb_port_speed(usb_dwc_speed_t priv)
739756 }
740757}
741758
742- static usb_hal_fifo_bias_t get_hal_fifo_bias (hcd_port_fifo_bias_t public )
743- {
744- switch (public ) {
745- case HCD_PORT_FIFO_BIAS_BALANCED : return USB_HAL_FIFO_BIAS_DEFAULT ;
746- case HCD_PORT_FIFO_BIAS_RX : return USB_HAL_FIFO_BIAS_RX ;
747- case HCD_PORT_FIFO_BIAS_PTX : return USB_HAL_FIFO_BIAS_PTX ;
748- default : abort ();
749- }
750- }
751-
752759// ----------------- Interrupt Handlers --------------------
753760
754761/**
@@ -949,6 +956,46 @@ static void intr_hdlr_main(void *arg)
949956 }
950957}
951958
959+ // ----------------------- FIFO Config -------------------------
960+
961+ /**
962+ * @brief Calculate default FIFO configuration based on bias preference
963+ *
964+ * This function calculates the FIFO configuration (RX, non-periodic TX, and periodic TX)
965+ * according to the selected bias mode from Kconfig:
966+ *
967+ * - CONFIG_USB_HOST_HW_BUFFER_BIAS_IN: Prioritize RX FIFO space, useful for IN-heavy traffic.
968+ * - CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT: Prioritize periodic TX FIFO, suitable for periodic OUT transfers.
969+ * - USB_HOST_HW_BUFFER_BIAS_BALANCED: Balanced configuration between RX and both TX FIFOs.
970+ *
971+ * @param[inout] port Pointer to the port object whose fifo_config will be filled
972+ * @param[in] hal Pointer to an initialized HAL context providing hardware FIFO limits
973+ */
974+ static void _calculate_fifo_from_bias (port_t * port , const usb_dwc_hal_context_t * hal )
975+ {
976+ const int otg_dfifo_depth = hal -> constant_config .hsphy_type ? 1024 : 256 ;
977+ const uint16_t fifo_size_lines = hal -> constant_config .fifo_size ;
978+
979+ #if CONFIG_USB_HOST_HW_BUFFER_BIAS_IN
980+ // Prioritize RX FIFO (best for IN-heavy workloads)
981+ port -> fifo_config .nptx_fifo_lines = otg_dfifo_depth / 16 ;
982+ port -> fifo_config .ptx_fifo_lines = otg_dfifo_depth / 8 ;
983+ port -> fifo_config .rx_fifo_lines = fifo_size_lines - port -> fifo_config .ptx_fifo_lines - port -> fifo_config .nptx_fifo_lines ;
984+
985+ #elif CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT
986+ // Prioritize periodic TX FIFO (useful for high throughput periodic endpoints)
987+ port -> 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
988+ port -> fifo_config .nptx_fifo_lines = otg_dfifo_depth / 16 ;
989+ port -> fifo_config .ptx_fifo_lines = fifo_size_lines - port -> fifo_config .nptx_fifo_lines - port -> fifo_config .rx_fifo_lines ;
990+
991+ #else // USB_HOST_HW_BUFFER_BIAS_BALANCED
992+ // Balanced configuration (default)
993+ port -> fifo_config .nptx_fifo_lines = otg_dfifo_depth / 4 ;
994+ port -> fifo_config .ptx_fifo_lines = otg_dfifo_depth / 8 ;
995+ port -> fifo_config .rx_fifo_lines = fifo_size_lines - port -> fifo_config .ptx_fifo_lines - port -> fifo_config .nptx_fifo_lines ;
996+ #endif
997+ }
998+
952999// --------------------------------------------- Host Controller Driver ------------------------------------------------
9531000
9541001static port_t * port_obj_alloc (void )
@@ -1013,6 +1060,15 @@ esp_err_t hcd_install(const hcd_config_t *config)
10131060 ESP_LOGE (HCD_DWC_TAG , "Interrupt alloc error: %s" , esp_err_to_name (err_ret ));
10141061 goto intr_alloc_err ;
10151062 }
1063+ // Apply custom FIFO config if provided, otherwise mark as default (all zeros)
1064+ memset (& p_hcd_obj_dmy -> port_obj -> fifo_config , 0 , sizeof (p_hcd_obj_dmy -> port_obj -> fifo_config ));
1065+ if (config -> fifo_config != NULL ) {
1066+ // Convert and validate user-provided config
1067+ err_ret = convert_fifo_config_to_hal_config (config -> fifo_config , & p_hcd_obj_dmy -> port_obj -> fifo_config );
1068+ if (err_ret != ESP_OK ) {
1069+ goto assign_err ;
1070+ }
1071+ }
10161072 HCD_ENTER_CRITICAL ();
10171073 if (s_hcd_obj != NULL ) {
10181074 HCD_EXIT_CRITICAL ();
@@ -1095,6 +1151,34 @@ static bool _port_debounce(port_t *port)
10951151 return is_connected ;
10961152}
10971153
1154+ static esp_err_t convert_fifo_config_to_hal_config (const hcd_fifo_settings_t * src , usb_dwc_hal_fifo_config_t * dst )
1155+ {
1156+ // Check at least RX and NPTX are non-zero
1157+ if (src -> rx_fifo_lines == 0 || src -> nptx_fifo_lines == 0 ) {
1158+ ESP_LOGE (HCD_DWC_TAG , "RX and Non-Periodic TX FIFO must be > 0" );
1159+ return ESP_ERR_INVALID_SIZE ;
1160+ }
1161+ // Assign valid values
1162+ dst -> rx_fifo_lines = src -> rx_fifo_lines ;
1163+ dst -> nptx_fifo_lines = src -> nptx_fifo_lines ;
1164+ dst -> ptx_fifo_lines = src -> ptx_fifo_lines ; // OK even if zero
1165+
1166+ return ESP_OK ;
1167+ }
1168+
1169+ /**
1170+ * @brief Check if the FIFO config is marked to use bias-based default values.
1171+ *
1172+ * If all FIFO line sizes are zero, the configuration is considered uninitialized,
1173+ * and default values will be calculated based on bias settings.
1174+ */
1175+ static inline bool _is_fifo_config_by_bias (const usb_dwc_hal_fifo_config_t * cfg )
1176+ {
1177+ return (cfg -> rx_fifo_lines == 0 &&
1178+ cfg -> nptx_fifo_lines == 0 &&
1179+ cfg -> ptx_fifo_lines == 0 );
1180+ }
1181+
10981182// ---------------------- Commands -------------------------
10991183
11001184static esp_err_t _port_cmd_power_on (port_t * port )
@@ -1172,8 +1256,16 @@ static esp_err_t _port_cmd_reset(port_t *port)
11721256 goto bailout ;
11731257 }
11741258
1175- // Reinitialize port registers.
1176- usb_dwc_hal_set_fifo_bias (port -> hal , port -> fifo_bias ); // Set FIFO biases
1259+ // Reinitialize port registers
1260+ if (!usb_dwc_hal_fifo_config_is_valid (port -> hal , & port -> fifo_config )) {
1261+ HCD_EXIT_CRITICAL ();
1262+ ret = ESP_ERR_INVALID_SIZE ;
1263+ ESP_LOGE (HCD_DWC_TAG , "Invalid FIFO config" );
1264+ HCD_ENTER_CRITICAL ();
1265+ goto bailout ;
1266+ }
1267+ usb_dwc_hal_set_fifo_config (port -> hal , & port -> fifo_config );// Apply FIFO settings
1268+
11771269 usb_dwc_hal_port_set_frame_list (port -> hal , port -> frame_list , FRAME_LIST_LEN ); // Set periodic frame list
11781270 usb_dwc_hal_port_periodic_enable (port -> hal ); // Enable periodic scheduling
11791271
@@ -1282,7 +1374,6 @@ esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, h
12821374 TAILQ_INIT (& port_obj -> pipes_active_tailq );
12831375 port_obj -> state = HCD_PORT_STATE_NOT_POWERED ;
12841376 port_obj -> last_event = HCD_PORT_EVENT_NONE ;
1285- port_obj -> fifo_bias = get_hal_fifo_bias (port_config -> fifo_bias );
12861377 port_obj -> callback = port_config -> callback ;
12871378 port_obj -> callback_arg = port_config -> callback_arg ;
12881379 port_obj -> context = port_config -> context ;
@@ -1292,10 +1383,18 @@ esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, h
12921383 port_obj -> initialized = true;
12931384 // Clear the frame list. We set the frame list register and enable periodic scheduling after a successful reset
12941385 memset (port_obj -> frame_list , 0 , FRAME_LIST_LEN * sizeof (uint32_t ));
1386+ // If FIFO config is zeroed -> calculate from bias
1387+ if (_is_fifo_config_by_bias (& port_obj -> fifo_config )) {
1388+ // Calculate default FIFO sizes based on Kconfig bias settings
1389+ _calculate_fifo_from_bias (port_obj , port_obj -> hal );
1390+ }
12951391 esp_intr_enable (s_hcd_obj -> isr_hdl );
12961392 * port_hdl = (hcd_port_handle_t )port_obj ;
12971393 HCD_EXIT_CRITICAL ();
1298-
1394+ ESP_LOGD (HCD_DWC_TAG , "FIFO config lines: RX=%u, PTX=%u, NPTX=%u" ,
1395+ port_obj -> fifo_config .rx_fifo_lines ,
1396+ port_obj -> fifo_config .ptx_fifo_lines ,
1397+ port_obj -> fifo_config .nptx_fifo_lines );
12991398 vTaskDelay (pdMS_TO_TICKS (INIT_DELAY_MS )); // Need a short delay before host mode takes effect
13001399 return ESP_OK ;
13011400}
@@ -1450,28 +1549,6 @@ void *hcd_port_get_context(hcd_port_handle_t port_hdl)
14501549 return ret ;
14511550}
14521551
1453- esp_err_t hcd_port_set_fifo_bias (hcd_port_handle_t port_hdl , hcd_port_fifo_bias_t bias )
1454- {
1455- esp_err_t ret ;
1456- usb_hal_fifo_bias_t hal_bias = get_hal_fifo_bias (bias );
1457-
1458- // Configure the new FIFO sizes and store the pointers
1459- port_t * port = (port_t * )port_hdl ;
1460- xSemaphoreTake (port -> port_mux , portMAX_DELAY );
1461- HCD_ENTER_CRITICAL ();
1462- // Check that port is in the correct state to update FIFO sizes
1463- if (port -> initialized && !port -> flags .event_pending && port -> num_pipes_idle == 0 && port -> num_pipes_queued == 0 ) {
1464- usb_dwc_hal_set_fifo_bias (port -> hal , hal_bias );
1465- port -> fifo_bias = hal_bias ;
1466- ret = ESP_OK ;
1467- } else {
1468- ret = ESP_ERR_INVALID_STATE ;
1469- }
1470- HCD_EXIT_CRITICAL ();
1471- xSemaphoreGive (port -> port_mux );
1472- return ret ;
1473- }
1474-
14751552// --------------------------------------------------- HCD Pipes -------------------------------------------------------
14761553
14771554// ----------------------- Private -------------------------
0 commit comments