refactor(hal/usb): Add new USB PHY related HAL API

This commit adds/updates the USB PHY related HAL APIs. The following changes
are made:

- Updated 'usb_wrap_hal.h' API
- Added 'usb_serial_jtag_hal.h' API
This commit is contained in:
Darian Leung 2024-04-02 21:10:35 +08:00
parent 023eae4f0b
commit 778c2e6863
No known key found for this signature in database
GPG Key ID: 8AC9127B487AA4EF
6 changed files with 185 additions and 142 deletions

View File

@ -256,6 +256,10 @@ if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "ds_hal.c") list(APPEND srcs "ds_hal.c")
endif() endif()
if(CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED)
list(APPEND srcs "usb_serial_jtag_hal.c")
endif()
if(CONFIG_SOC_USB_OTG_SUPPORTED) if(CONFIG_SOC_USB_OTG_SUPPORTED)
list(APPEND srcs list(APPEND srcs
"usb_dwc_hal.c" "usb_dwc_hal.c"

View File

@ -0,0 +1,51 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/soc_caps.h"
#if SOC_USB_SERIAL_JTAG_SUPPORTED
#include "hal/usb_serial_jtag_ll.h"
#endif
#include "hal/usb_serial_jtag_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_USB_SERIAL_JTAG_SUPPORTED
/**
* @brief HAL context type of USJ driver
*/
typedef struct {
usb_serial_jtag_dev_t *dev;
} usb_serial_jtag_hal_context_t;
/**
* @brief Initialize the USJ HAL driver
*
* @param hal USJ HAL context
*/
void usb_serial_jtag_hal_init(usb_serial_jtag_hal_context_t *hal);
/* ---------------------------- USB PHY Control ---------------------------- */
#if USB_SERIAL_JTAG_LL_EXT_PHY_SUPPORTED
/**
* @brief Configure whether USJ is routed to internal/external FSLS PHY
*
* @param hal USJ HAL context
* @param external True if external, False if internal
*/
void usb_serial_jtag_hal_phy_set_external(usb_serial_jtag_hal_context_t *hal, bool external);
#endif // USB_SERIAL_JTAG_LL_EXT_PHY_SUPPORTED
#endif // SOC_USB_SERIAL_JTAG_SUPPORTED
#ifdef __cplusplus
}
#endif

View File

@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -7,85 +7,89 @@
#pragma once #pragma once
#include <stdbool.h> #include <stdbool.h>
#include "usb_dwc_types.h"
#include "usb_phy_types.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#if SOC_USB_OTG_SUPPORTED #if SOC_USB_OTG_SUPPORTED
#include "soc/usb_wrap_struct.h" #include "soc/usb_wrap_struct.h"
#include "hal/usb_wrap_ll.h" #include "hal/usb_wrap_ll.h"
#endif #endif
#if SOC_USB_SERIAL_JTAG_SUPPORTED #include "hal/usb_wrap_types.h"
#include "soc/usb_serial_jtag_struct.h"
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#if SOC_USB_OTG_SUPPORTED #if SOC_USB_OTG_SUPPORTED
/**
* Context that should be maintained by both the driver and the HAL
*/
/**
* @brief HAL context type of USB WRAP driver
*/
typedef struct { typedef struct {
usb_wrap_dev_t *wrap_dev; /**< Pointer to base address of USB Wrapper registers */ usb_wrap_dev_t *dev;
#if SOC_USB_SERIAL_JTAG_SUPPORTED } usb_wrap_hal_context_t;
usb_serial_jtag_dev_t *jtag_dev; /**< Pointer to base address of USB Serial JTAG registers */
#endif
} usb_fsls_phy_hal_context_t;
/** /**
* @brief Init the USB PHY hal. This function should be called first before other hal layer function is called * @brief Initialize the USB WRAP HAL driver
* *
* @param hal Context of the HAL layer * @param hal USB WRAP HAL context
*/ */
void usb_fsls_phy_hal_init(usb_fsls_phy_hal_context_t *hal); void usb_wrap_hal_init(usb_wrap_hal_context_t *hal);
/* ---------------------------- USB PHY Control ---------------------------- */
#if USB_WRAP_LL_EXT_PHY_SUPPORTED #if USB_WRAP_LL_EXT_PHY_SUPPORTED
/** /**
* @brief Configure internal/external PHY for USB_OTG * @brief Configure whether USB WRAP is routed to internal/external FSLS PHY
* *
* @param hal Context of the HAL layer * @param hal USB WRAP HAL context
* @param phy_target USB PHY target * @param external True if external, False if internal
*/ */
void usb_fsls_phy_hal_otg_conf(usb_fsls_phy_hal_context_t *hal, usb_phy_target_t phy_target); void usb_wrap_hal_phy_set_external(usb_wrap_hal_context_t *hal, bool external);
#endif // USB_WRAP_LL_EXT_PHY_SUPPORTED #endif // USB_WRAP_LL_EXT_PHY_SUPPORTED
#if SOC_USB_SERIAL_JTAG_SUPPORTED
/** /**
* @brief Configure internal/external PHY for USB_Serial_JTAG * @brief Enables and sets override of pull up/down resistors
* *
* @param hal Context of the HAL layer * @param hal USB WRAP HAL context
* @param phy_target USB PHY target * @param vals Override values
*/ */
void usb_fsls_phy_hal_jtag_conf(usb_fsls_phy_hal_context_t *hal, usb_phy_target_t phy_target); static inline void usb_wrap_hal_phy_enable_pull_override(usb_wrap_hal_context_t *hal, const usb_wrap_pull_override_vals_t *vals)
#endif {
usb_wrap_ll_phy_enable_pull_override(hal->dev, vals);
}
/** /**
* @brief Configure pullup/pulldown loads for the D+/D- as a host * @brief Disables pull up/down resistor override
* *
* @param hal Context of the HAL layer * @param hal USB WRAP HAL context
*/ */
void usb_fsls_phy_hal_int_load_conf_host(usb_fsls_phy_hal_context_t *hal); static inline void usb_wrap_hal_phy_disable_pull_override(usb_wrap_hal_context_t *hal)
{
usb_wrap_ll_phy_disable_pull_override(hal->dev);
}
/** /**
* @brief Configure pullup/pulldown loads for the D+/D- as a device * @brief Enables/disables the USB FSLS PHY's test mode
* *
* @param hal Context of the HAL layer * @param hal USB WRAP HAL context
* @param speed USB speed * @param enable Whether to enable test mode
*/ */
void usb_fsls_phy_hal_int_load_conf_dev(usb_fsls_phy_hal_context_t *hal, usb_phy_speed_t speed); static inline void usb_wrap_hal_phy_enable_test_mode(usb_wrap_hal_context_t *hal, bool enable)
{
usb_wrap_ll_phy_enable_test_mode(hal->dev, enable);
}
/** /**
* @brief Enable/Disable test mode for internal PHY to mimic host-device disconnection * @brief Set the USB FSLS PHY's signal test values
* *
* @param hal Context of the HAL layer * @param hal USB WRAP HAL context
* @param disconn Whether to disconnect * @param vals Test values
*/ */
void usb_fsls_phy_hal_int_mimick_disconn(usb_fsls_phy_hal_context_t *hal, bool disconn); static inline void usb_wrap_hal_phy_test_mode_set_signals(usb_wrap_hal_context_t *hal, const usb_wrap_test_mode_vals_t *vals)
{
usb_wrap_ll_phy_test_mode_set_signals(hal->dev, vals);
}
#endif #endif // SOC_USB_OTG_SUPPORTED
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hal/usb_serial_jtag_ll.h"
#include "hal/usb_serial_jtag_hal.h"
void usb_serial_jtag_hal_init(usb_serial_jtag_hal_context_t *hal)
{
hal->dev = &USB_SERIAL_JTAG;
#if !USB_SERIAL_JTAG_LL_EXT_PHY_SUPPORTED
usb_serial_jtag_ll_phy_set_defaults();
#endif
}
#if USB_SERIAL_JTAG_LL_EXT_PHY_SUPPORTED
void usb_serial_jtag_hal_phy_set_external(usb_serial_jtag_hal_context_t *hal, bool external)
{
if (external) {
usb_serial_jtag_ll_phy_enable_external(true);
} else {
usb_serial_jtag_ll_phy_enable_external(false);
usb_serial_jtag_ll_phy_enable_pad(true);
}
}
#endif // USB_SERIAL_JTAG_LL_EXT_PHY_SUPPORTED

View File

@ -5,101 +5,25 @@
*/ */
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#if SOC_USB_SERIAL_JTAG_SUPPORTED
#include "hal/usb_serial_jtag_ll.h"
#endif
#include "hal/usb_wrap_ll.h" #include "hal/usb_wrap_ll.h"
#include "hal/usb_wrap_hal.h" #include "hal/usb_wrap_hal.h"
void usb_fsls_phy_hal_init(usb_fsls_phy_hal_context_t *hal) void usb_wrap_hal_init(usb_wrap_hal_context_t *hal)
{ {
hal->wrap_dev = &USB_WRAP; hal->dev = &USB_WRAP;
#if SOC_USB_SERIAL_JTAG_SUPPORTED
hal->jtag_dev = &USB_SERIAL_JTAG;
#endif
#if !USB_WRAP_LL_EXT_PHY_SUPPORTED #if !USB_WRAP_LL_EXT_PHY_SUPPORTED
usb_wrap_ll_phy_set_defaults(hal->wrap_dev); usb_wrap_ll_phy_set_defaults(hal->dev);
#endif #endif
} }
#if USB_WRAP_LL_EXT_PHY_SUPPORTED #if USB_WRAP_LL_EXT_PHY_SUPPORTED
void usb_fsls_phy_hal_otg_conf(usb_fsls_phy_hal_context_t *hal, usb_phy_target_t phy_target) void usb_wrap_hal_phy_set_external(usb_wrap_hal_context_t *hal, bool external)
{ {
if (phy_target == USB_PHY_TARGET_EXT) { if (external) {
usb_wrap_ll_phy_enable_external(hal->wrap_dev, true); usb_wrap_ll_phy_enable_external(hal->dev, true);
} else if (phy_target == USB_PHY_TARGET_INT) { } else {
usb_wrap_ll_phy_enable_external(hal->wrap_dev, false); usb_wrap_ll_phy_enable_external(hal->dev, false);
usb_wrap_ll_phy_enable_pad(hal->wrap_dev, true); usb_wrap_ll_phy_enable_pad(hal->dev, true);
} }
} }
#endif // USB_WRAP_LL_EXT_PHY_SUPPORTED #endif // USB_WRAP_LL_EXT_PHY_SUPPORTED
#if SOC_USB_SERIAL_JTAG_SUPPORTED
void usb_fsls_phy_hal_jtag_conf(usb_fsls_phy_hal_context_t *hal, usb_phy_target_t phy_target)
{
if (phy_target == USB_PHY_TARGET_EXT) {
usb_serial_jtag_ll_phy_enable_external(true); // USJ uses external PHY
} else if (phy_target == USB_PHY_TARGET_INT) {
usb_serial_jtag_ll_phy_enable_external(false); // USJ uses internal PHY
usb_serial_jtag_ll_phy_enable_pad(true); // Enable USB PHY pads
}
}
#endif
void usb_fsls_phy_hal_int_load_conf_host(usb_fsls_phy_hal_context_t *hal)
{
// HOST - upstream: dp_pd = 1, dm_pd = 1
usb_wrap_pull_override_vals_t vals = {
.dp_pu = false,
.dm_pu = false,
.dp_pd = true,
.dm_pd = true,
};
usb_wrap_ll_phy_enable_pull_override(hal->wrap_dev, &vals);
}
void usb_fsls_phy_hal_int_load_conf_dev(usb_fsls_phy_hal_context_t *hal, usb_phy_speed_t speed)
{
// DEVICE - downstream
if (speed == USB_PHY_SPEED_LOW) {
// LS: dm_pu = 1
usb_wrap_pull_override_vals_t vals = {
.dp_pu = false,
.dm_pu = true,
.dp_pd = false,
.dm_pd = false,
};
usb_wrap_ll_phy_enable_pull_override(hal->wrap_dev, &vals);
} else {
// FS: dp_pu = 1
usb_wrap_pull_override_vals_t vals = {
.dp_pu = true,
.dm_pu = false,
.dm_pd = false,
.dp_pd = false,
};
usb_wrap_ll_phy_enable_pull_override(hal->wrap_dev, &vals);
}
}
void usb_fsls_phy_hal_int_mimick_disconn(usb_fsls_phy_hal_context_t *hal, bool disconn)
{
if (disconn) {
/*
We mimic a disconnect by enabling the internal PHY's test mode, then forcing the output_enable to HIGH. This will:
A HIGH output_enable will cause the received VP and VM to be zero, thus mimicking a disconnection.
*/
usb_wrap_test_mode_vals_t vals = {
.tx_enable_n = true,
.tx_dp = false,
.tx_dm = false,
.rx_dp = false,
.rx_dm = false,
.rx_rcv = false,
};
usb_wrap_ll_phy_test_mode_set_signals(hal->wrap_dev, &vals);
usb_wrap_ll_phy_enable_test_mode(hal->wrap_dev, true);
} else {
usb_wrap_ll_phy_enable_test_mode(hal->wrap_dev, false);
}
}

View File

@ -13,7 +13,7 @@
#include "esp_private/usb_phy.h" #include "esp_private/usb_phy.h"
#include "soc/usb_dwc_periph.h" #include "soc/usb_dwc_periph.h"
#include "hal/usb_wrap_hal.h" #include "hal/usb_wrap_hal.h"
#include "hal/usb_wrap_ll.h" #include "hal/usb_serial_jtag_hal.h"
#include "esp_rom_gpio.h" #include "esp_rom_gpio.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "hal/gpio_ll.h" #include "hal/gpio_ll.h"
@ -39,7 +39,10 @@ struct phy_context_t {
usb_otg_mode_t otg_mode; /**< USB OTG mode */ usb_otg_mode_t otg_mode; /**< USB OTG mode */
usb_phy_speed_t otg_speed; /**< USB speed */ usb_phy_speed_t otg_speed; /**< USB speed */
usb_phy_ext_io_conf_t *iopins; /**< external PHY I/O pins */ usb_phy_ext_io_conf_t *iopins; /**< external PHY I/O pins */
usb_fsls_phy_hal_context_t hal_context; /**< USB_PHY hal context */ usb_wrap_hal_context_t wrap_hal; /**< USB WRAP HAL context */
#if SOC_USB_SERIAL_JTAG_SUPPORTED
usb_serial_jtag_hal_context_t usj_hal; /**< USJ HAL context */
#endif
}; };
typedef struct { typedef struct {
@ -126,7 +129,14 @@ esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode)
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, false); // receiving a valid Vbus from host esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, false); // receiving a valid Vbus from host
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_AVALID_IN_IDX, false); // HIGH to force USB host mode esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_AVALID_IN_IDX, false); // HIGH to force USB host mode
if (handle->target == USB_PHY_TARGET_INT) { if (handle->target == USB_PHY_TARGET_INT) {
usb_fsls_phy_hal_int_load_conf_host(&(handle->hal_context)); // Configure pull resistors for host
usb_wrap_pull_override_vals_t vals = {
.dp_pu = false,
.dm_pu = false,
.dp_pd = true,
.dm_pd = true,
};
usb_wrap_hal_phy_enable_pull_override(&handle->wrap_hal, &vals);
} }
} else if (mode == USB_OTG_MODE_DEVICE) { } else if (mode == USB_OTG_MODE_DEVICE) {
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_IDDIG_IN_IDX, false); // connected connector is mini-B side esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_IDDIG_IN_IDX, false); // connected connector is mini-B side
@ -147,7 +157,19 @@ esp_err_t usb_phy_otg_dev_set_speed(usb_phy_handle_t handle, usb_phy_speed_t spe
USBPHY_TAG, "set speed not supported"); USBPHY_TAG, "set speed not supported");
handle->otg_speed = speed; handle->otg_speed = speed;
usb_fsls_phy_hal_int_load_conf_dev(&(handle->hal_context), speed); // Configure pull resistors for device
usb_wrap_pull_override_vals_t vals = {
.dp_pd = false,
.dm_pd = false,
};
if (speed == USB_PHY_SPEED_LOW) {
vals.dp_pu = false;
vals.dm_pu = true;
} else {
vals.dp_pu = true;
vals.dm_pu = false;
}
usb_wrap_hal_phy_enable_pull_override(&handle->wrap_hal, &vals);
return ESP_OK; return ESP_OK;
} }
@ -163,7 +185,7 @@ esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action)
switch (action) { switch (action) {
case USB_PHY_ACTION_HOST_ALLOW_CONN: case USB_PHY_ACTION_HOST_ALLOW_CONN:
if (handle->target == USB_PHY_TARGET_INT) { if (handle->target == USB_PHY_TARGET_INT) {
usb_fsls_phy_hal_int_mimick_disconn(&(handle->hal_context), false); usb_wrap_hal_phy_enable_test_mode(&handle->wrap_hal, false);
} else { } else {
if (!handle->iopins) { if (!handle->iopins) {
ret = ESP_FAIL; ret = ESP_FAIL;
@ -180,7 +202,21 @@ esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action)
case USB_PHY_ACTION_HOST_FORCE_DISCONN: case USB_PHY_ACTION_HOST_FORCE_DISCONN:
if (handle->target == USB_PHY_TARGET_INT) { if (handle->target == USB_PHY_TARGET_INT) {
usb_fsls_phy_hal_int_mimick_disconn(&(handle->hal_context), true); /*
We mimic a disconnect by enabling the internal PHY's test mode,
then forcing the output_enable to HIGH. This will cause the received
VP and VM to be zero, thus mimicking a disconnection.
*/
const usb_wrap_test_mode_vals_t vals = {
.tx_enable_n = true,
.tx_dp = false,
.tx_dm = false,
.rx_dp = false,
.rx_dm = false,
.rx_rcv = false,
};
usb_wrap_hal_phy_test_mode_set_signals(&handle->wrap_hal, &vals);
usb_wrap_hal_phy_enable_test_mode(&handle->wrap_hal, true);
} else { } else {
/* /*
Disable connections on the external PHY by connecting the VP and VM signals to the constant LOW signal. Disable connections on the external PHY by connecting the VP and VM signals to the constant LOW signal.
@ -263,15 +299,18 @@ esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_r
phy_context->controller = config->controller; phy_context->controller = config->controller;
phy_context->status = USB_PHY_STATUS_IN_USE; phy_context->status = USB_PHY_STATUS_IN_USE;
usb_fsls_phy_hal_init(&(phy_context->hal_context)); usb_wrap_hal_init(&phy_context->wrap_hal);
#if SOC_USB_SERIAL_JTAG_SUPPORTED
usb_serial_jtag_hal_init(&phy_context->usj_hal);
#endif
if (config->controller == USB_PHY_CTRL_OTG) { if (config->controller == USB_PHY_CTRL_OTG) {
#if USB_WRAP_LL_EXT_PHY_SUPPORTED #if USB_WRAP_LL_EXT_PHY_SUPPORTED
usb_fsls_phy_hal_otg_conf(&(phy_context->hal_context), config->target == USB_PHY_TARGET_EXT); usb_wrap_hal_phy_set_external(&phy_context->wrap_hal, (config->target == USB_PHY_TARGET_EXT));
#endif #endif
} }
#if SOC_USB_SERIAL_JTAG_SUPPORTED #if SOC_USB_SERIAL_JTAG_SUPPORTED
else if (config->controller == USB_PHY_CTRL_SERIAL_JTAG) { else if (config->controller == USB_PHY_CTRL_SERIAL_JTAG) {
usb_fsls_phy_hal_jtag_conf(&(phy_context->hal_context), config->target == USB_PHY_TARGET_EXT); usb_serial_jtag_hal_phy_set_external(&phy_context->usj_hal, (config->target == USB_PHY_TARGET_EXT));
phy_context->otg_mode = USB_OTG_MODE_DEVICE; phy_context->otg_mode = USB_OTG_MODE_DEVICE;
phy_context->otg_speed = USB_PHY_SPEED_FULL; phy_context->otg_speed = USB_PHY_SPEED_FULL;
} }
@ -336,14 +375,7 @@ esp_err_t usb_del_phy(usb_phy_handle_t handle)
p_phy_ctrl_obj->external_phy = NULL; p_phy_ctrl_obj->external_phy = NULL;
} else { } else {
// Clear pullup and pulldown loads on D+ / D-, and disable the pads // Clear pullup and pulldown loads on D+ / D-, and disable the pads
usb_wrap_pull_override_vals_t vals = { usb_wrap_hal_phy_disable_pull_override(&handle->wrap_hal);
.dp_pu = false,
.dm_pu = false,
.dp_pd = false,
.dm_pd = false,
};
usb_wrap_ll_phy_enable_pull_override(handle->hal_context.wrap_dev, &vals);
usb_wrap_ll_phy_enable_pad(handle->hal_context.wrap_dev, false);
p_phy_ctrl_obj->internal_phy = NULL; p_phy_ctrl_obj->internal_phy = NULL;
} }
portEXIT_CRITICAL(&phy_spinlock); portEXIT_CRITICAL(&phy_spinlock);