Merge branch 'refactor/usb_fsls_phy_hal' into 'master'

refactor(hal/usb): Update USB PHY related HAL/LL API

See merge request espressif/esp-idf!29659
This commit is contained in:
Darian
2024-03-20 06:07:29 +08:00
23 changed files with 1036 additions and 581 deletions

View File

@@ -1,179 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "esp_attr.h"
#include "soc/soc.h"
#include "soc/system_struct.h"
#include "soc/usb_wrap_struct.h"
#include "soc/rtc_cntl_struct.h"
#include "soc/usb_serial_jtag_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Configures the internal PHY for USB_OTG
*
* @param hw Start address of the USB Wrap registers
*/
static inline void usb_fsls_phy_ll_int_otg_enable(usb_wrap_dev_t *hw)
{
// USB_OTG use internal PHY
hw->otg_conf.phy_sel = 0;
// phy_sel is controlled by the following register value
RTCCNTL.usb_conf.sw_hw_usb_phy_sel = 1;
// phy_sel=sw_usb_phy_sel=1, USB_OTG is connected with internal PHY
RTCCNTL.usb_conf.sw_usb_phy_sel = 1;
}
/**
* @brief Configures the external PHY for USB_OTG
*
* @param hw Start address of the USB Wrap registers
*/
static inline void usb_fsls_phy_ll_ext_otg_enable(usb_wrap_dev_t *hw)
{
// USB_OTG use external PHY
hw->otg_conf.phy_sel = 1;
// phy_sel is controlled by the following register value
RTCCNTL.usb_conf.sw_hw_usb_phy_sel = 1;
// phy_sel=sw_usb_phy_sel=0, USB_OTG is connected with external PHY through GPIO Matrix
RTCCNTL.usb_conf.sw_usb_phy_sel = 0;
}
/**
* @brief Configures the internal PHY for USB_Serial_JTAG
*
* @param hw Start address of the USB Serial_JTAG registers
*/
static inline void usb_fsls_phy_ll_int_jtag_enable(usb_serial_jtag_dev_t *hw)
{
// USB_Serial_JTAG use internal PHY
hw->conf0.phy_sel = 0;
// Disable software control USB D+ D- pullup pulldown (Device FS: dp_pullup = 1)
hw->conf0.pad_pull_override = 0;
// Enable USB D+ pullup
hw->conf0.dp_pullup = 1;
// Enable USB pad function
hw->conf0.usb_pad_enable = 1;
// phy_sel is controlled by the following register value
RTCCNTL.usb_conf.sw_hw_usb_phy_sel = 1;
// phy_sel=sw_usb_phy_sel=0, USB_Serial_JTAG is connected with internal PHY
RTCCNTL.usb_conf.sw_usb_phy_sel = 0;
}
/**
* @brief Disable the internal PHY for USB_Serial_JTAG
*
* @param hw Start address of the USB Serial_JTAG registers
*/
static inline void usb_fsls_phy_ll_int_jtag_disable(usb_serial_jtag_dev_t *hw)
{
// Disable USB D+ pullup
hw->conf0.dp_pullup = 0;
// Disable USB pad function
hw->conf0.usb_pad_enable = 0;
}
/**
* @brief Configures the external PHY for USB_Serial_JTAG
*
* @param hw Start address of the USB Serial_JTAG registers
*/
static inline void usb_fsls_phy_ll_ext_jtag_enable(usb_serial_jtag_dev_t *hw)
{
// USB_Serial_JTAG use external PHY
hw->conf0.phy_sel = 1;
// phy_sel is controlled by the following register value
RTCCNTL.usb_conf.sw_hw_usb_phy_sel = 1;
// phy_sel=sw_usb_phy_sel=1, USB_Serial_JTAG is connected with external PHY
RTCCNTL.usb_conf.sw_usb_phy_sel = 1;
}
/**
* @brief Configures port loads for the internal PHY
*
* @param hw Start address of the USB Wrap registers
* @param dp_pu D+ pullup load
* @param dp_pd D+ pulldown load
* @param dm_pu D- pullup load
* @param dm_pd D- pulldown load
*/
static inline void usb_fsls_phy_ll_int_load_conf(usb_wrap_dev_t *hw, bool dp_pu, bool dp_pd, bool dm_pu, bool dm_pd)
{
usb_wrap_otg_conf_reg_t conf;
conf.val = hw->otg_conf.val;
conf.pad_pull_override = 1;
conf.dp_pullup = dp_pu;
conf.dp_pulldown = dp_pd;
conf.dm_pullup = dm_pu;
conf.dm_pulldown = dm_pd;
hw->otg_conf.val = conf.val;
}
/**
* @brief Enable the internal PHY control to D+/D- pad
* @param hw Start address of the USB Wrap registers
* @param pad_en Enable the PHY control to D+/D- pad
*/
static inline void usb_fsls_phy_ll_usb_wrap_pad_enable(usb_wrap_dev_t *hw, bool pad_en)
{
hw->otg_conf.pad_enable = pad_en;
}
/**
* @brief Enable the internal PHY's test mode
*
* @param hw Start address of the USB Wrap registers
* @param en Whether to enable the internal PHY's test mode
*/
static inline void usb_fsls_phy_ll_int_enable_test_mode(usb_wrap_dev_t *hw, bool en)
{
if (en) {
// Clear USB_WRAP_TEST_CONF_REG
hw->test_conf.val = 0;
// Set USB test pad oen
hw->test_conf.test_usb_wrap_oe = 1;
// Enable USB test mode
hw->test_conf.test_enable = 1;
} else {
hw->test_conf.test_enable = 0;
}
}
/**
* Enable the bus clock for USB Wrap module
* @param clk_en True if enable the clock of USB Wrap module
*/
FORCE_INLINE_ATTR void usb_fsls_phy_ll_usb_wrap_enable_bus_clock(bool clk_en)
{
SYSTEM.perip_clk_en0.usb_clk_en = clk_en;
}
// SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way
#define usb_fsls_phy_ll_usb_wrap_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_fsls_phy_ll_usb_wrap_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the USB Wrap module
*/
FORCE_INLINE_ATTR void usb_fsls_phy_ll_usb_wrap_reset_register(void)
{
SYSTEM.perip_rst_en0.usb_rst = 1;
SYSTEM.perip_rst_en0.usb_rst = 0;
}
// SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way
#define usb_fsls_phy_ll_usb_wrap_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_fsls_phy_ll_usb_wrap_reset_register(__VA_ARGS__)
#ifdef __cplusplus
}
#endif

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,6 +10,7 @@
#include <stdbool.h>
#include "esp_attr.h"
#include "soc/system_struct.h"
#include "soc/rtc_cntl_struct.h"
#include "soc/usb_serial_jtag_reg.h"
#include "soc/usb_serial_jtag_struct.h"
@@ -34,6 +35,8 @@ typedef enum {
USB_SERIAL_JTAG_INTR_EP1_ZERO_PAYLOAD = (1 << 10),
} usb_serial_jtag_intr_t;
/* ----------------------------- USJ Peripheral ----------------------------- */
/**
* @brief Enable the USB_SERIAL_JTAG interrupt based on the given mask.
*
@@ -178,30 +181,142 @@ static inline void usb_serial_jtag_ll_txfifo_flush(void)
}
/**
* @brief Disable usb serial jtag pad during light sleep to avoid current leakage
* @brief Enable USJ JTAG bridge
*
* @return Initial configuration of usb serial jtag pad enable before light sleep
* If enabled, USJ is disconnected from internal JTAG interface. JTAG interface
* is routed through GPIO matrix instead.
*
* @param enable Enable USJ JTAG bridge
*/
FORCE_INLINE_ATTR bool usb_serial_jtag_ll_pad_backup_and_disable(void)
FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_set_jtag_bridge(bool enable)
{
bool pad_enabled = USB_SERIAL_JTAG.conf0.usb_pad_enable;
USB_SERIAL_JTAG.conf0.usb_jtag_bridge_en = enable;
}
// Disable USB pad function
USB_SERIAL_JTAG.conf0.usb_pad_enable = 0;
/* ---------------------------- USB PHY Control ---------------------------- */
return pad_enabled;
/**
* @brief Sets whether the USJ's FSLS PHY interface routes to an internal or external PHY
*
* @param enable Enables external PHY, internal otherwise
*/
FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_external(bool enable)
{
USB_SERIAL_JTAG.conf0.phy_sel = enable;
// Enable SW control of muxing USB OTG vs USJ to the internal USB FSLS PHY
RTCCNTL.usb_conf.sw_hw_usb_phy_sel = 1;
/*
For 'sw_usb_phy_sel':
0 - Internal USB FSLS PHY is mapped to the USJ. USB Wrap mapped to external PHY
1 - Internal USB FSLS PHY is mapped to the USB Wrap. USJ mapped to external PHY
*/
RTCCNTL.usb_conf.sw_usb_phy_sel = enable;
}
/**
* @brief Enable the internal USJ PHY control to D+/D- pad
* @brief Enables/disables exchanging of the D+/D- pins USB PHY
*
* @param enable_pad Enable the USJ PHY control to D+/D- pad
* @param enable Enables pin exchange, disabled otherwise
*/
FORCE_INLINE_ATTR void usb_serial_jtag_ll_enable_pad(bool enable_pad)
FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pin_exchg(bool enable)
{
USB_SERIAL_JTAG.conf0.usb_pad_enable = enable_pad;
if (enable) {
USB_SERIAL_JTAG.conf0.exchg_pins = 1;
USB_SERIAL_JTAG.conf0.exchg_pins_override = 1;
} else {
USB_SERIAL_JTAG.conf0.exchg_pins_override = 0;
USB_SERIAL_JTAG.conf0.exchg_pins = 0;
}
}
/**
* @brief Enables and sets voltage threshold overrides for USB FSLS PHY single-ended inputs
*
* @param vrefh_step High voltage threshold. 0 to 3 indicating 80mV steps from 1.76V to 2V.
* @param vrefl_step Low voltage threshold. 0 to 3 indicating 80mV steps from 0.8V to 1.04V.
*/
FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_vref_override(unsigned int vrefh_step, unsigned int vrefl_step)
{
USB_SERIAL_JTAG.conf0.vrefh = vrefh_step;
USB_SERIAL_JTAG.conf0.vrefl = vrefl_step;
USB_SERIAL_JTAG.conf0.vref_override = 1;
}
/**
* @brief Disables voltage threshold overrides for USB FSLS PHY single-ended inputs
*/
FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_disable_vref_override(void)
{
USB_SERIAL_JTAG.conf0.vref_override = 0;
}
/**
* @brief Enable override of USB FSLS PHY's pull up/down resistors
*
* @param dp_pu Enable D+ pullup
* @param dm_pu Enable D- pullup
* @param dp_pd Enable D+ pulldown
* @param dm_pd Enable D- pulldown
*/
FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pull_override(bool dp_pu, bool dm_pu, bool dp_pd, bool dm_pd)
{
USB_SERIAL_JTAG.conf0.dp_pullup = dp_pu;
USB_SERIAL_JTAG.conf0.dp_pulldown = dp_pd;
USB_SERIAL_JTAG.conf0.dm_pullup = dm_pu;
USB_SERIAL_JTAG.conf0.dm_pulldown = dm_pd;
USB_SERIAL_JTAG.conf0.pad_pull_override = 1;
}
/**
* @brief Disable override of USB FSLS PHY pull up/down resistors
*/
FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_disable_pull_override(void)
{
USB_SERIAL_JTAG.conf0.pad_pull_override = 0;
}
/**
* @brief Sets the strength of the pullup resistor
*
* @param strong True is a ~1.4K pullup, false is a ~2.4K pullup
*/
FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_set_pullup_strength(bool strong)
{
USB_SERIAL_JTAG.conf0.pullup_value = strong;
}
/**
* @brief Check if USB FSLS PHY pads are enabled
*
* @return True if enabled, false otherwise
*/
FORCE_INLINE_ATTR bool usb_serial_jtag_ll_phy_is_pad_enabled(void)
{
return USB_SERIAL_JTAG.conf0.usb_pad_enable;
}
/**
* @brief Enable the USB FSLS PHY pads
*
* @param enable Whether to enable the USB FSLS PHY pads
*/
FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_enable_pad(bool enable)
{
USB_SERIAL_JTAG.conf0.usb_pad_enable = enable;
}
/**
* @brief Set USB FSLS PHY TX output clock edge
*
* @param clk_neg_edge True if TX output at negedge, posedge otherwise
*/
FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_set_tx_edge(bool clk_neg_edge)
{
USB_SERIAL_JTAG.conf0.phy_tx_edge_sel = clk_neg_edge;
}
/* ----------------------------- RCC Functions ----------------------------- */
/**
* @brief Enable the bus clock for USB Serial_JTAG module
* @param clk_en True if enable the clock of USB Serial_JTAG module

View File

@@ -0,0 +1,249 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "esp_attr.h"
#include "soc/soc.h"
#include "soc/system_struct.h"
#include "soc/usb_wrap_struct.h"
#include "soc/rtc_cntl_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ---------------------------- USB PHY Control ---------------------------- */
/**
* @brief Enables and sets the override value for the session end signal
*
* @param hw Start address of the USB Wrap registers
* @param sessend Session end override value. True means VBus < 0.2V, false means VBus > 0.8V
*/
FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_srp_sessend_override(usb_wrap_dev_t *hw, bool sessend)
{
hw->otg_conf.srp_sessend_value = sessend;
hw->otg_conf.srp_sessend_override = 1;
}
/**
* @brief Disable session end override
*
* @param hw Start address of the USB Wrap registers
*/
FORCE_INLINE_ATTR void usb_wrap_ll_phy_disable_srp_sessend_override(usb_wrap_dev_t *hw)
{
hw->otg_conf.srp_sessend_override = 0;
}
/**
* @brief Sets whether the USB Wrap's FSLS PHY interface routes to an internal or external PHY
*
* @param hw Start address of the USB Wrap registers
* @param enable Enables external PHY, internal otherwise
*/
FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_external(usb_wrap_dev_t *hw, bool enable)
{
hw->otg_conf.phy_sel = enable;
// Enable SW control of muxing USB OTG vs USJ to the internal USB FSLS PHY
RTCCNTL.usb_conf.sw_hw_usb_phy_sel = 1;
/*
For 'sw_usb_phy_sel':
0 - Internal USB FSLS PHY is mapped to the USJ. USB Wrap mapped to external PHY
1 - Internal USB FSLS PHY is mapped to the USB Wrap. USJ mapped to external PHY
*/
RTCCNTL.usb_conf.sw_usb_phy_sel = !enable;
}
/**
* @brief Enables/disables exchanging of the D+/D- pins USB PHY
*
* @param hw Start address of the USB Wrap registers
* @param enable Enables pin exchange, disabled otherwise
*/
FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_pin_exchg(usb_wrap_dev_t *hw, bool enable)
{
if (enable) {
hw->otg_conf.exchg_pins = 1;
hw->otg_conf.exchg_pins_override = 1;
} else {
hw->otg_conf.exchg_pins_override = 0;
hw->otg_conf.exchg_pins = 0;
}
}
/**
* @brief Enables and sets voltage threshold overrides for USB FSLS PHY single-ended inputs
*
* @param hw Start address of the USB Wrap registers
* @param vrefh_step High voltage threshold. 0 to 3 indicating 80mV steps from 1.76V to 2V.
* @param vrefl_step Low voltage threshold. 0 to 3 indicating 80mV steps from 0.8V to 1.04V.
*/
FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_vref_override(usb_wrap_dev_t *hw, unsigned int vrefh_step, unsigned int vrefl_step)
{
hw->otg_conf.vrefh = vrefh_step;
hw->otg_conf.vrefl = vrefl_step;
hw->otg_conf.vref_override = 1;
}
/**
* @brief Disables voltage threshold overrides for USB FSLS PHY single-ended inputs
*
* @param hw Start address of the USB Wrap registers
*/
FORCE_INLINE_ATTR void usb_wrap_ll_phy_disable_vref_override(usb_wrap_dev_t *hw)
{
hw->otg_conf.vref_override = 0;
}
/**
* @brief Enable override of USB FSLS PHY's pull up/down resistors
*
* @param hw Start address of the USB Wrap registers
* @param dp_pu Enable D+ pullup
* @param dm_pu Enable D- pullup
* @param dp_pd Enable D+ pulldown
* @param dm_pd Enable D- pulldown
*/
FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_pull_override(usb_wrap_dev_t *hw, bool dp_pu, bool dm_pu, bool dp_pd, bool dm_pd)
{
hw->otg_conf.dp_pullup = dp_pu;
hw->otg_conf.dp_pulldown = dp_pd;
hw->otg_conf.dm_pullup = dm_pu;
hw->otg_conf.dm_pulldown = dm_pd;
hw->otg_conf.pad_pull_override = 1;
}
/**
* @brief Disable override of USB FSLS PHY pull up/down resistors
*
* @param hw Start address of the USB Wrap registers
*/
FORCE_INLINE_ATTR void usb_wrap_ll_phy_disable_pull_override(usb_wrap_dev_t *hw)
{
hw->otg_conf.pad_pull_override = 0;
}
/**
* @brief Sets the strength of the pullup resistor
*
* @param hw Start address of the USB Wrap registers
* @param strong True is a ~1.4K pullup, false is a ~2.4K pullup
*/
FORCE_INLINE_ATTR void usb_wrap_ll_phy_set_pullup_strength(usb_wrap_dev_t *hw, bool strong)
{
hw->otg_conf.pullup_value = strong;
}
/**
* @brief Check if USB FSLS PHY pads are enabled
*
* @param hw Start address of the USB Wrap registers
* @return True if enabled, false otherwise
*/
FORCE_INLINE_ATTR bool usb_wrap_ll_phy_is_pad_enabled(usb_wrap_dev_t *hw)
{
return hw->otg_conf.pad_enable;
}
/**
* @brief Enable the USB FSLS PHY pads
*
* @param hw Start address of the USB Wrap registers
* @param enable Whether to enable the USB FSLS PHY pads
*/
FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_pad(usb_wrap_dev_t *hw, bool enable)
{
hw->otg_conf.pad_enable = enable;
}
/**
* @brief Set USB FSLS PHY TX output clock edge
*
* @param hw Start address of the USB Wrap registers
* @param clk_neg_edge True if TX output at negedge, posedge otherwise
*/
FORCE_INLINE_ATTR void usb_wrap_ll_phy_set_tx_edge(usb_wrap_dev_t *hw, bool clk_neg_edge)
{
hw->otg_conf.phy_tx_edge_sel = clk_neg_edge;
}
/* ------------------------------ USB PHY Test ------------------------------ */
/**
* @brief Enable the USB FSLS PHY's test mode
*
* @param hw Start address of the USB Wrap registers
* @param enable Whether to enable the USB FSLS PHY's test mode
*/
FORCE_INLINE_ATTR void usb_wrap_ll_phy_enable_test_mode(usb_wrap_dev_t *hw, bool enable)
{
hw->test_conf.test_enable = enable;
}
/**
* @brief Set the USB FSLS PHY's signal test values
*
* @param hw Start address of the USB Wrap registers
* @param oen Output Enable (active low) signal
* @param tx_dp TX D+
* @param tx_dm TX D-
* @param rx_dp RX D+
* @param rx_dm RX D-
* @param rx_rcv RX RCV
*/
FORCE_INLINE_ATTR void usb_wrap_ll_phy_test_mode_set_signals(usb_wrap_dev_t *hw,
bool oen,
bool tx_dp,
bool tx_dm,
bool rx_dp,
bool rx_dm,
bool rx_rcv)
{
usb_wrap_test_conf_reg_t test_conf;
test_conf.val = hw->test_conf.val;
test_conf.test_usb_wrap_oe = oen;
test_conf.test_tx_dp = tx_dp;
test_conf.test_tx_dm = tx_dm;
test_conf.test_rx_rcv = rx_rcv;
test_conf.test_rx_dp = rx_dp;
test_conf.test_rx_dm = rx_dm;
hw->test_conf.val = test_conf.val;
}
/* ----------------------------- RCC Functions ----------------------------- */
/**
* Enable the bus clock for USB Wrap module
* @param clk_en True if enable the clock of USB Wrap module
*/
FORCE_INLINE_ATTR void usb_wrap_ll_enable_bus_clock(bool clk_en)
{
SYSTEM.perip_clk_en0.usb_clk_en = clk_en;
}
// SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way
#define usb_wrap_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_wrap_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the USB Wrap module
*/
FORCE_INLINE_ATTR void usb_wrap_ll_reset_register(void)
{
SYSTEM.perip_rst_en0.usb_rst = 1;
SYSTEM.perip_rst_en0.usb_rst = 0;
}
// SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way
#define usb_wrap_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_wrap_ll_reset_register(__VA_ARGS__)
#ifdef __cplusplus
}
#endif