diff --git a/src/soc/qualcomm/x1p42100/Makefile.mk b/src/soc/qualcomm/x1p42100/Makefile.mk index fb82673a15..c7e39a8a12 100644 --- a/src/soc/qualcomm/x1p42100/Makefile.mk +++ b/src/soc/qualcomm/x1p42100/Makefile.mk @@ -43,6 +43,9 @@ ramstage-y += soc.c ramstage-y += cbmem.c ramstage-y += ../common/mmu.c ramstage-$(CONFIG_DRIVERS_UART) += ../common/qupv3_uart.c +ramstage-y += usb/usb.c +ramstage-y += usb/snps_usb_phy.c +ramstage-y += usb/qmpv4_usb_phy.c ramstage-$(CONFIG_PCI) += ../common/pcie_common.c ramstage-y += ../common/spmi.c ramstage-$(CONFIG_PCI) += pcie.c diff --git a/src/soc/qualcomm/x1p42100/include/soc/addressmap.h b/src/soc/qualcomm/x1p42100/include/soc/addressmap.h index bfb51ad7b2..21341df24d 100644 --- a/src/soc/qualcomm/x1p42100/include/soc/addressmap.h +++ b/src/soc/qualcomm/x1p42100/include/soc/addressmap.h @@ -31,9 +31,7 @@ #define GPIO_FUNC_QSPI_DATA_1 GPIO129_FUNC_QSPI0_DATA_1 #define GPIO_FUNC_QSPI_CLK GPIO127_FUNC_QSPI0_CLK -/* - * QUP SERIAL ENGINE BASE ADDRESSES - */ +/* QUP SERIAL ENGINE BASE ADDRESSES */ /* QUPV3_0 */ #define QUP_SERIAL0_BASE 0x00B80000 #define QUP_SERIAL1_BASE 0x00B84000 @@ -70,6 +68,22 @@ #define QUP_WRAP2_BASE 0x008C0000 #define QUP_2_GSI_BASE 0x00804000 +/* USB BASE ADDRESSES */ +#define HS_USB_MP0_PHY_BASE 0x088e1000 +#define HS_USB_MP1_PHY_BASE 0x088E2000 +#define QMP_PHY_MP0_QSERDES_COM_REG_BASE 0x088E3000 +#define QMP_PHY_MP0_QSERDES_TX_REG_BASE 0x088E3E00 +#define QMP_PHY_MP0_QSERDES_RX_REG_BASE 0x088E4000 +#define QMP_PHY_MP0_PCS_REG_BASE 0x088E3200 +#define QMP_PHY_MP0_PCS_USB3_REG_BASE 0x088E4200 +#define USB_HOST_DWC3_BASE 0x0a40c100 + +#define QMP_PHY_MP1_QSERDES_COM_REG_BASE 0x088E5000 +#define QMP_PHY_MP1_QSERDES_TX_REG_BASE 0x088E5E00 +#define QMP_PHY_MP1_QSERDES_RX_REG_BASE 0x088E6000 +#define QMP_PHY_MP1_PCS_REG_BASE 0x088E5200 +#define QMP_PHY_MP1_PCS_USB3_REG_BASE 0x088E6200 + /* PCIE 6A */ #define PCIE6A_PCIE_PARF 0x01BF8000 #define PCIE6A_GEN1X4_PCIE_DBI 0x70000000 @@ -110,8 +124,23 @@ #define PCIE6A_BQPHY_PCS_PCIE_LANE1 0x01BFFE00 /* TCSR */ -#define TCSR_GCC_PCIE_4L_CLKREF_EN_PCIE_ENABLE ((void *)0x1FD512C) -#define TCSR_PCIE_CTRL_4LN_CONFIG_SEL ((void *)0x1FDA000) +#define TCSR_GCC_PCIE_4L_CLKREF_EN_PCIE_ENABLE ((void *)0x1FD512C) +#define TCSR_PCIE_CTRL_4LN_CONFIG_SEL ((void *)0x1FDA000) + +#define TCSR_GCC_CXO_1_REFGEN_BIAS_SEL__SEL_REFGEN_ADDR ((void *)0x1FD511C) +#define TCSR_GCC_CXO_0_REFGEN_BIAS_SEL__SEL_REFGEN_ADDR ((void *)0x1FD5134) + +#define TCSR_QREFS_CXO_0_RPT3_CONFIG_ADDR ((void *)0x1FD5014) +#define TCSR_QREFS_CXO_0_RPT4_CONFIG_ADDR ((void *)0x1FD5018) +#define TCSR_QREFS_CXO_1_RPT0_CONFIG_ADDR ((void *)0x1FD5000) +#define TCSR_QREFS_CXO_1_RX3_CONFIG_ADDR ((void *)0x1FD502C) +#define TCSR_QREFS_CXO_1_RX0_CONFIG_ADDR ((void *)0x1FD5020) +#define TCSR_QREFS_CXO_0_RX3_CONFIG_ADDR ((void *)0x1FD5030) +#define TCSR_QREFS_CXO_0_RX4_CONFIG_ADDR ((void *)0x1FD5034) + +#define TCSR_GCC_USB3_MP0_CLKREF_EN_ADDR ((void *)0x1FD510C) +#define TCSR_GCC_USB3_MP1_CLKREF_EN_ADDR ((void *)0x1FD5110) +#define USB3_CLKREF_ENABLE_VALUE 0x1 /* SPMI PMIC ARB */ #define SPMI_PMIC_ARB_CORE_BASE 0x0C400000 diff --git a/src/soc/qualcomm/x1p42100/include/soc/usb/qmp_usb_phy.h b/src/soc/qualcomm/x1p42100/include/soc/usb/qmp_usb_phy.h new file mode 100644 index 0000000000..e463c61b82 --- /dev/null +++ b/src/soc/qualcomm/x1p42100/include/soc/usb/qmp_usb_phy.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include + +/* USB3PHY_PCIE_USB3_PCS_PCS_STATUS bit */ +#define USB3_PCS_PHYSTATUS BIT(6) + +/* Define qmp_phy_init_tbl to use offsets instead of absolute addresses. +This makes the tables generic and reusable */ +typedef struct qmp_phy_init_tbl { + u32 offset; // Offset from the base address of the register block + u32 val; +} qmp_phy_init_tbl_t; + +/* Structure to encapsulate base addresses and configuration tables for a specific PHY instance */ +struct ss_usb_phy_reg { + void *com_base; + void *tx_base; + void *rx_base; + void *pcs_base; + void *pcs_usb3_base; + const char *name; + /* Init sequence for QMP PHY blocks - serdes, tx, rx, pcs */ + const qmp_phy_init_tbl_t *serdes_tbl; + int serdes_tbl_num; + const qmp_phy_init_tbl_t *tx_tbl; + int tx_tbl_num; + const qmp_phy_init_tbl_t *rx_tbl; + int rx_tbl_num; + const qmp_phy_init_tbl_t *pcs_tbl; + int pcs_tbl_num; + const qmp_phy_init_tbl_t *pcs_usb3_tbl; + int pcs_usb3_tbl_num; +}; +/* Initialize a specific QMP USB3 PHY instance */ +bool ss_qmp_phy_init(u32 phy_idx); diff --git a/src/soc/qualcomm/x1p42100/include/soc/usb/snps_usb_phy.h b/src/soc/qualcomm/x1p42100/include/soc/usb/snps_usb_phy.h new file mode 100644 index 0000000000..cb62b68b1f --- /dev/null +++ b/src/soc/qualcomm/x1p42100/include/soc/usb/snps_usb_phy.h @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include + +struct hs_usb_phy_reg { + /* Revision ID registers */ + u32 usb_phy_revision_id0; /* 0x000 */ + u32 usb_phy_revision_id1; /* 0x004 */ + u32 usb_phy_revision_id2; /* 0x008 */ + u32 usb_phy_revision_id3; /* 0x00c */ + + /* Debug bus status registers */ + u32 usb_phy_debug_bus_stat0; /* 0x010 */ + u32 usb_phy_debug_bus_stat1; /* 0x014 */ + u32 usb_phy_debug_bus_stat2; /* 0x018 */ + u32 usb_phy_debug_bus_stat3; /* 0x01c */ + + /* Test and status registers */ + u32 usb_phy_hs_rx_tester_out_1; /* 0x020 */ + u32 usb_phy_charging_det_output; /* 0x024 */ + u32 usb_phy_hs_phy_test_out_1; /* 0x028 */ + u32 usb_phy_refclk_rxtap_test_status; /* 0x02c */ + + /* UTMI RX status registers */ + u32 usb_phy_utmi_rx_datal_status; /* 0x030 */ + u32 usb_phy_utmi_rx_datah_status; /* 0x034 */ + u32 usb_phy_utmi_rx_port_status; /* 0x038 */ + + /* Original UTMI control registers */ + u32 utmi_ctrl0; /* 0x03c */ + u32 utmi_ctrl1; /* 0x040 */ + + /* Extended UTMI control registers */ + u32 utmi_ctrl2; /* 0x044 */ + u32 utmi_ctrl3; /* 0x048 */ + u32 utmi_ctrl4; /* 0x04c */ + u32 utmi_ctrl5; /* 0x050 */ + + /* HS PHY control registers */ + u32 hs_phy_ctrl_common0; /* 0x054 */ + + /* Configuration control registers */ + u32 cfg_ctrl_1; /* 0x058 */ + u32 cfg_ctrl_2; /* 0x05c */ + u32 cfg_ctrl_3; /* 0x060 */ + u32 hs_phy_ctrl2; /* 0x064 */ + u32 cfg_ctrl_4; /* 0x068 */ + + /* Additional configuration control registers */ + u32 cfg_ctrl_5; /* 0x06c */ + u32 cfg_ctrl_6; /* 0x070 */ + u32 cfg_ctrl_7; /* 0x074 */ + u32 cfg_ctrl_8; /* 0x078 */ + u32 cfg_ctrl_9; /* 0x07c */ + u32 cfg_ctrl_10; /* 0x080 */ + + u32 hs_phy_test1; /* 0x084 */ + u32 rx_tester_1_reg0; /* 0x088 */ + u32 rx_tester_1_reg1; /* 0x08c */ + u32 rx_tester_1_reg2; /* 0x090 */ + + /* Original cfg0 register */ + u32 cfg0; /* 0x094 */ + + /* Common control registers */ + u32 utmi_phy_cmn_ctrl0; /* 0x098 */ + u32 utmi_phy_cmn_ctrl1; /* 0x09c */ + + /* Original refclk_ctrl register */ + u32 refclk_ctrl; /* 0x0a0 */ + + /* Power and reset control registers */ + u32 usb_phy_pwrdown_ctrl; /* 0x0a4 */ + u32 usb_phy_test_debug_ctrl; /* 0x0a8 */ + u32 usb_phy_reset_ctrl; /* 0x0ac */ + u32 usb_phy_ac_en; /* 0x0b0 */ + u32 cfg_ctrl_11; /* 0x0b4 */ + u32 usb_phy_fsel_sel; /* 0x0b8 */ + + /* Skitter control registers */ + u32 usb_phy_skitter_ctrl_1; /* 0x0bc */ + u32 usb_phy_skitter_ctrl_2; /* 0x0c0 */ + u32 usb_phy_skitter_ctrl_3; /* 0x0c4 */ + u32 usb_phy_skitter_sticky_no_lsb; /* 0x0c8 */ + u32 usb_phy_skitter_sticky_no_msb; /* 0x0cc */ + u32 usb_phy_skitter_calib_counter_lsb; /* 0x0d0 */ + u32 usb_phy_skitter_calib_counter_msb; /* 0x0d4 */ + u32 usb_phy_skitter_mul_cons_lsb; /* 0x0d8 */ + u32 usb_phy_skitter_mul_cons_msb; /* 0x0dc */ + u32 usb_phy_skitter_mfs_misc_1; /* 0x0e0 */ + u32 usb_phy_skitter_mfs_misc_2; /* 0x0e4 */ + u32 usb_phy_skitter_spread_detect_range; /* 0x0e8 */ + u32 usb_phy_skitter_jitter_thrhold; /* 0x0ec */ + u32 usb_phy_skitter_status; /* 0x0f0 */ + u32 usb_phy_inv_dly_lsb; /* 0x0f4 */ + u32 usb_phy_inv_dly_msb; /* 0x0f8 */ + u32 usb_phy_eud_connected; /* 0x0fc */ + u32 usb_phy_skitter_jitter; /* 0x100 */ + u32 usb_phy_test_debug_ctrl_2; /* 0x104 */ + u32 eud_present_sel; /* 0x108 */ + u32 usb_phy_skitter_tie_jitter_lsb; /* 0x10c */ + u32 usb_phy_skitter_tie_jitter_msb; /* 0x110 */ + u32 usb_phy_skitter_calib_rodly_1; /* 0x114 */ + u32 usb_phy_skitter_calib_rodly_2; /* 0x118 */ + u32 usb_phy_skitter_calib_rodly_3; /* 0x11c */ + + /* Reserved registers */ + u32 usb_phy_reserved_0; /* 0x120 */ + u32 usb_phy_reserved_1; /* 0x124 */ + u32 usb_phy_reserved_2; /* 0x128 */ + u32 usb_phy_reserved_3; /* 0x12c */ + + /* APB access registers */ + u32 usb_phy_apb_access_cmd; /* 0x130 */ + u32 usb_phy_apb_access_status; /* 0x134 */ + u32 usb_phy_apb_address; /* 0x138 */ + u32 usb_phy_apb_wrdata_lsb; /* 0x13c */ + u32 usb_phy_apb_wrdata_msb; /* 0x140 */ + u32 usb_phy_apb_rddata_lsb; /* 0x144 */ + u32 usb_phy_apb_rddata_msb; /* 0x148 */ + + /* Final skitter registers */ + u32 usb_phy_skitter_insertion_dly_corr; /* 0x14c */ + u32 usb_phy_skitter_pos_edge_corr1; /* 0x150 */ +}; diff --git a/src/soc/qualcomm/x1p42100/include/soc/usb/usb.h b/src/soc/qualcomm/x1p42100/include/soc/usb/usb.h new file mode 100644 index 0000000000..4b62392d2f --- /dev/null +++ b/src/soc/qualcomm/x1p42100/include/soc/usb/usb.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "qmp_usb_phy.h" + +/* QSCRATCH_GENERAL_CFG register bit offset */ +#define PIPE_UTMI_CLK_SEL BIT(0) +#define PIPE3_PHYSTATUS_SW BIT(3) +#define PIPE_UTMI_CLK_DIS BIT(8) + +/* Global USB3 Control Registers */ +#define DWC3_GUSB3PIPECTL_DELAYP1TRANS BIT(18) +#define DWC3_GUSB3PIPECTL_PHYSOFTRS BIT(31) +#define DWC3_GUSB3PIPECTL_UX_EXIT_IN_PX BIT(27) +#define DWC3_GUSB3PIPECTL_P3EXSIGP2 BIT(10) +#define DWC3_GCTL_PRTCAPDIR(n) ((n) << 12) +#define DWC3_GCTL_PRTCAP_OTG 3 +#define DWC3_GCTL_PRTCAP_HOST 1 + +/* Global USB2 PHY Configuration Register */ +#define DWC3_GUSB2PHYCFG_USBTRDTIM(n) ((n) << 10) +#define DWC3_GUSB2PHYCFG_USB2TRDTIM_MASK DWC3_GUSB2PHYCFG_USBTRDTIM(0xf) +#define DWC3_GUSB2PHYCFG_PHYIF(n) ((n) << 3) +#define DWC3_GUSB2PHYCFG_PHYIF_MASK DWC3_GUSB2PHYCFG_PHYIF(1) +#define USBTRDTIM_UTMI_8_BIT 9 +#define UTMI_PHYIF_8_BIT 0 +#define DWC3_GUSB2PHYCFG_ENBLSLPM_MASK (0x1 << 0x8) +#define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) +#define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) +#define DWC3_GCTL_DISSCRAMBLE (1 << 3) +#define DWC3_GCTL_U2EXIT_LFPS (1 << 2) +#define DWC3_GCTL_DSBLCLKGTNG (1 << 0) +#define UTMI_CLK_DIS_0 (1 << 8) +#define UTMI_CLK_SEL_0 (1 << 0) +#define PIPE3_PHYSTATUS_SW_0 (1 << 3) +#define PIPE3_SET_PHYSTATUS_SW_0 (1 << 9) +#define USB3_MP_CGCTL_REG_ADDR ((void *)0x0A4F8828) +#define USB3_MP_DBM_FSM_EN_BIT (1 << 1) +#define USB3_MP_LINK_REGS_1_LU3LFPSRXTIM_ADDR ((void *)0X0A40D090) +#define USB3_MP_LINK_REGS_0_LU3LFPSRXTIM_ADDR ((void *)0X0A40D010) + +#define GEN2_U3_EXIT_RSP_RX_CLK_MASK (0xFF << 16) +#define GEN1_U3_EXIT_RSP_RX_CLK_MASK (0xFF << 0) + +#define GEN2_U3_EXIT_RSP_RX_CLK_VALUE (0x06 << 16) +#define GEN1_U3_EXIT_RSP_RX_CLK_VALUE (0x05 << 0) + +#define LFPS_RSP_RX_CLK_CLR_MASK (GEN2_U3_EXIT_RSP_RX_CLK_MASK | GEN1_U3_EXIT_RSP_RX_CLK_MASK) +#define LFPS_RSP_RX_CLK_SET_MASK (GEN2_U3_EXIT_RSP_RX_CLK_VALUE | GEN1_U3_EXIT_RSP_RX_CLK_VALUE) + +#define DWC3_GUCTL1_CLR_MASK (BIT(31) | BIT(24) | (0x7 << 21)) +#define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24) +#define DWC3_GUCTL1_IP_GAP_ADD_ON(val) ((val & 0x7) << 21) +#define DWC3_GUCTL1_DEV_DECOUPLE_L1L2_EVT BIT(31) + +#define DWC3_GUCTL1_SET_MASK (DWC3_GUCTL1_DEV_L1_EXIT_BY_HW | \ + DWC3_GUCTL1_IP_GAP_ADD_ON(0x3) | \ + DWC3_GUCTL1_DEV_DECOUPLE_L1L2_EVT) + +#define USB_HOST_DWC3_GENERAL_CFG_ADDR 0X0A4F8808 +#define USB3_MP_GUSB2PHYCFG_REGS_1_ADDR ((void *)0x0A40C204) +#define GUSB2PHYCFG_ENBLSLPM_BIT BIT(8) +#define USB3_MP_GUSB2PHYCFG_REGS_0_ADDR ((void *)0x0A40C200) +#define USB3_MP_PORTSC_20_REGS_0_ADDR ((void *)0x0A400420) +#define USB3_MP_PORTSC_20_REGS_1_ADDR ((void *)0x0A400430) +#define USB3_MP_PORTSC_30_REGS_0_ADDR ((void *)0x0A400440) +#define USB3_MP_PORTSC_30_REGS_1_ADDR ((void *)0x0A400450) +#define USB3_PORTSC_WCE_BIT BIT(25) + +/* Initializes a specific HS PHY instance */ +void hs_usb_phy_init(int index); +/* Initializes and configures the USB HOST0 controller */ +void setup_usb_host0(void); +/* Enable USB GDSC/Clocks */ +int qcom_enable_usb_clk(void); +/* Enable TCSR REFGEN */ +void enable_clock_tcsr(void); diff --git a/src/soc/qualcomm/x1p42100/usb/qmpv4_usb_phy.c b/src/soc/qualcomm/x1p42100/usb/qmpv4_usb_phy.c new file mode 100644 index 0000000000..38556b8b4d --- /dev/null +++ b/src/soc/qualcomm/x1p42100/usb/qmpv4_usb_phy.c @@ -0,0 +1,498 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include + +/* Only for QMP V4 PHY - QSERDES COM registers */ +struct usb3_phy_qserdes_com_reg_layout { + u32 com_ssc_step_size1_mode1; + u32 com_ssc_step_size2_mode1; + u32 com_ssc_step_size3_mode1; + u32 com_clk_ep_div_mode1; + u32 com_cp_ctrl_mode1; + u32 com_pll_rctrl_mode1; + u32 com_pll_cctrl_mode1; + u32 com_coreclk_div_mode1; + u32 com_lock_cmp1_mode1; + u32 com_lock_cmp2_mode1; + u32 com_dec_start_mode1; + u32 com_dec_start_msb_mode1; + u32 com_div_frac_start1_mode1; + u32 com_div_frac_start2_mode1; + u32 com_div_frac_start3_mode1; + u32 com_hsclk_sel_1; + u32 com_integloop_gain0_mode1; + u32 com_integloop_gain1_mode1; + u32 com_vco_tune1_mode1; + u32 com_vco_tune2_mode1; + u32 com_bin_vcocal_cmp_code1_mode1; + u32 com_bin_vcocal_cmp_code2_mode1; + u32 com_bin_vcocal_cmp_code1_mode0; + u32 com_bin_vcocal_cmp_code2_mode0; + u32 com_ssc_step_size1_mode0; + u32 com_ssc_step_size2_mode0; + u32 com_ssc_step_size3_mode0; + u32 com_clk_ep_div_mode0; + u32 com_cp_ctrl_mode0; + u32 com_pll_rctrl_mode0; + u32 com_pll_cctrl_mode0; + u32 com_coreclk_div_mode0; + u32 com_lock_cmp1_mode0; + u32 com_lock_cmp2_mode0; + u32 com_dec_start_mode0; + u32 com_dec_start_msb_mode0; + u32 com_div_frac_start1_mode0; + u32 com_div_frac_start2_mode0; + u32 com_div_frac_start3_mode0; + u32 com_hsclk_hs_switch_sel_1; + u32 com_integloop_gain0_mode0; + u32 com_integloop_gain1_mode0; + u32 com_vco_tune1_mode0; + u32 com_vco_tune2_mode0; + u32 com_atb_sel1; + u32 com_atb_sel2; + u32 com_freq_update; + u32 com_bg_timer; + u32 com_ssc_en_center; + u32 com_ssc_adj_per1; + u32 com_ssc_adj_per2; + u32 com_ssc_per1; + u32 com_ssc_per2; + u8 _reserved1[20]; + u32 com_sysclk_buf_enable; + u8 _reserved2[36]; + u32 com_sysclk_en_sel; + u8 _reserved3[16]; + u32 com_lock_cmp_cfg; + u8 _reserved4[24]; + u32 com_vco_tune_map; + u8 _reserved5[44]; + u32 com_core_clk_en; + u32 com_cmn_config_1; + u8 _reserved6[44]; + u32 com_auto_gain_adj_ctrl_1; + u32 com_auto_gain_adj_ctrl_2; + u32 com_auto_gain_adj_ctrl_3; + u32 com_auto_gain_adj_ctrl_4; + u32 com_additional_misc; +}; + +check_member(usb3_phy_qserdes_com_reg_layout, com_ssc_step_size1_mode1, 0x00); +check_member(usb3_phy_qserdes_com_reg_layout, com_sysclk_buf_enable, 0xe8); +check_member(usb3_phy_qserdes_com_reg_layout, com_sysclk_en_sel, 0x110); +check_member(usb3_phy_qserdes_com_reg_layout, com_lock_cmp_cfg, 0x124); +check_member(usb3_phy_qserdes_com_reg_layout, com_integloop_gain0_mode0, 0x0a0); +check_member(usb3_phy_qserdes_com_reg_layout, com_vco_tune_map, 0x0140); +check_member(usb3_phy_qserdes_com_reg_layout, com_core_clk_en, 0x170); +check_member(usb3_phy_qserdes_com_reg_layout, com_auto_gain_adj_ctrl_1, 0x1a4); + +/* Only for QMP V4 PHY - TX registers */ +struct usb3_phy_qserdes_tx_reg_layout { + u8 _reserved1[52]; + u32 tx_res_code_lane_tx; + u32 tx_res_code_lane_rx; + u32 tx_res_code_lane_offset_tx; + u32 tx_res_code_lane_offset_rx; + u8 _reserved2[64]; + u32 tx_lane_mode_1; + u32 tx_lane_mode_2; + u32 tx_lane_mode_3; + u32 tx_lane_mode_4; + u32 tx_lane_mode_5; + u8 _reserved3[12]; + u32 tx_rcv_detect_lvl_2; + u8 _reserved4[60]; + u32 tx_pi_qec_ctrl; +}; +check_member(usb3_phy_qserdes_tx_reg_layout, tx_res_code_lane_tx, 0x034); +check_member(usb3_phy_qserdes_tx_reg_layout, tx_lane_mode_1, 0x084); +check_member(usb3_phy_qserdes_tx_reg_layout, tx_rcv_detect_lvl_2, 0x0a4); +check_member(usb3_phy_qserdes_tx_reg_layout, tx_pi_qec_ctrl, 0x0e4); + +/* Only for QMP V4 PHY - RX registers */ +struct usb3_phy_qserdes_rx_reg_layout { + u8 _reserved1[8]; + u32 rx_ucdr_fo_gain; + u8 _reserved2[8]; + u32 rx_ucdr_so_gain; + u8 _reserved3[24]; + u32 rx_ucdr_fastlock_fo_gain; + u32 rx_ucdr_so_saturation_and_enable; + u32 rx_ucdr_fo_to_so_delay; + u32 rx_ucdr_fastlock_count_low; + u32 rx_ucdr_fastlock_count_high; + u32 rx_ucdr_pi_controls; + u32 rx_ucdr_pi_ctrl2; + u32 rx_ucdr_sb2_thresh1; + u32 rx_ucdr_sb2_thresh2; + u32 rx_ucdr_sb2_gain1; + u32 rx_ucdr_sb2_gain2; + u32 rx_aux_control; + u32 rx_aux_data_tcoarse_tfine; + u8 _reserved4[112]; + u32 rx_vga_cal_cntrl1; + u32 rx_vga_cal_cntrl2; + u32 rx_gm_cal; + u8 _reserved5[12]; + u32 rx_rx_equ_adaptor_cntrl2; + u32 rx_rx_equ_adaptor_cntrl3; + u32 rx_rx_equ_adaptor_cntrl4; + u32 rx_rx_idac_tsettle_low; + u32 rx_rx_idac_tsettle_high; + u8 _reserved6[16]; + u32 rx_rx_eq_offset_adaptor_cntrl1; + u32 rx_rx_offset_adaptor_cntrl2; + u32 rx_sigdet_enables; + u32 rx_sigdet_cntrl; + u32 rx_sigdet_lvl; + u32 rx_sigdet_deglitch_cntrl; + u8 _reserved7[52]; + u32 rx_rx_mode_00_low; + u32 rx_rx_mode_00_high; + u32 rx_rx_mode_00_high2; + u32 rx_rx_mode_00_high3; + u32 rx_rx_mode_00_high4; + u32 rx_rx_mode_01_low; + u32 rx_rx_mode_01_high; + u32 rx_rx_mode_01_high2; + u32 rx_rx_mode_01_high3; + u32 rx_rx_mode_01_high4; + u32 rx_rx_mode_10_low; + u32 rx_rx_mode_10_high; + u32 rx_rx_mode_10_high2; + u32 rx_rx_mode_10_high3; + u32 rx_rx_mode_10_high4; + u8 _reserved8[8]; + u32 rx_dfe_en_timer; + u32 rx_dfe_ctle_post_cal_offset; + u32 rx_dcc_ctrl1; + u32 rx_dcc_ctrl2; + u32 rx_vth_code; + u8 _reserved9[48]; + u32 rx_sigdet_cal_ctrl1; + u8 _reserved10[16]; + u32 rx_sigdet_cal_trim; +}; + +check_member(usb3_phy_qserdes_rx_reg_layout, rx_ucdr_so_gain, 0x014); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_ucdr_fastlock_fo_gain, 0x030); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_vga_cal_cntrl1, 0x0d4); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_equ_adaptor_cntrl2, 0x0ec); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_equ_adaptor_cntrl3, 0x0f0); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_equ_adaptor_cntrl4, 0x0f4); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_eq_offset_adaptor_cntrl1, 0x110); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_sigdet_cntrl, 0x11c); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_rx_mode_00_low, 0x15c); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_dfe_en_timer, 0x1a0); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_dcc_ctrl1, 0x1a8); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_vth_code, 0x1b0); +check_member(usb3_phy_qserdes_rx_reg_layout, rx_sigdet_cal_trim, 0x1f8); + +/* Only for QMP V4 PHY - PCS registers */ +struct usb3_phy_pcs_reg_layout { + u32 pcs_sw_reset; + u8 _reserved1[16]; + u32 pcs_pcs_status1; + u8 _reserved2[40]; + u32 pcs_power_down_control; + u32 pcs_start_control; + u8 _reserved3[124]; + u32 pcs_lock_detect_config1; + u32 pcs_lock_detect_config2; + u32 pcs_lock_detect_config3; + u8 _reserved4[8]; + u32 pcs_lock_detect_config6; + u32 pcs_refgen_req_config1; + u8 _reserved5[168]; + u32 pcs_rx_sigdet_lvl; + u8 _reserved6[4]; + u32 pcs_rcvr_dtct_dly_p1u2_l; + u32 pcs_rcvr_dtct_dly_p1u2_h; + u8 _reserved7[24]; + u32 pcs_cdr_reset_time; + u8 _reserved8[12]; + u32 pcs_align_detect_config1; + u32 pcs_align_detect_config2; + u8 _reserved9[8]; + u32 pcs_pcs_tx_rx_config; + u8 _reserved10[8]; + u32 pcs_eq_config1; + u8 _reserved11[12]; + u32 pcs_eq_config5; +}; + +check_member(usb3_phy_pcs_reg_layout, pcs_pcs_status1, 0x014); +check_member(usb3_phy_pcs_reg_layout, pcs_power_down_control, 0x040); +check_member(usb3_phy_pcs_reg_layout, pcs_lock_detect_config1, 0x0c4); +check_member(usb3_phy_pcs_reg_layout, pcs_lock_detect_config6, 0x0d8); +check_member(usb3_phy_pcs_reg_layout, pcs_rx_sigdet_lvl, 0x188); +check_member(usb3_phy_pcs_reg_layout, pcs_cdr_reset_time, 0x1b0); +check_member(usb3_phy_pcs_reg_layout, pcs_align_detect_config1, 0x1c0); +check_member(usb3_phy_pcs_reg_layout, pcs_pcs_tx_rx_config, 0x1d0); +check_member(usb3_phy_pcs_reg_layout, pcs_eq_config1, 0x1dc); +check_member(usb3_phy_pcs_reg_layout, pcs_eq_config5, 0x1ec); + + +struct usb3_phy_pcs_usb3_reg_layout { + u32 reserved[6]; + u32 pcs_usb3_lfps_det_high_count_val; + u32 reserved1[8]; + u32 pcs_usb3_rxeqtraining_dfe_time_s2; + u32 pcs_usb3_rcvr_dtct_dly_u3_l; + u32 pcs_usb3_rcvr_dtct_dly_u3_h; +}; + +/* Definition of the shared initialization tables using offsets */ +static const qmp_phy_init_tbl_t qmp_v4_usb3_serdes_tbl[] = { + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_ssc_step_size1_mode1), 0xc0}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_ssc_step_size2_mode1), 0x01}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_cp_ctrl_mode1), 0x02}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_pll_rctrl_mode1), 0x16}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_pll_cctrl_mode1), 0x36}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_coreclk_div_mode1), 0x04}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_lock_cmp1_mode1), 0x16}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_lock_cmp2_mode1), 0x41}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_dec_start_mode1), 0x41}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_div_frac_start1_mode1), 0x55}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_div_frac_start2_mode1), 0x75}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_div_frac_start3_mode1), 0x01}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_hsclk_sel_1), 0x01}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_vco_tune1_mode1), 0x25}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_vco_tune2_mode1), 0x02}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_bin_vcocal_cmp_code1_mode1), 0x5c}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_bin_vcocal_cmp_code2_mode1), 0x0f}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_bin_vcocal_cmp_code1_mode0), 0x5c}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_bin_vcocal_cmp_code2_mode0), 0x0f}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_ssc_step_size1_mode0), 0xc0}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_ssc_step_size2_mode0), 0x01}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_cp_ctrl_mode0), 0x02}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_pll_rctrl_mode0), 0x16}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_pll_cctrl_mode0), 0x36}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_lock_cmp1_mode0), 0x08}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_lock_cmp2_mode0), 0x1a}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_dec_start_mode0), 0x41}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_div_frac_start1_mode0), 0x55}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_div_frac_start2_mode0), 0x75}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_div_frac_start3_mode0), 0x01}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_vco_tune1_mode0), 0x25}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_vco_tune2_mode0), 0x02}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_bg_timer), 0x0a}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_ssc_en_center), 0x01}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_ssc_per1), 0x62}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_ssc_per2), 0x02}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_sysclk_buf_enable), 0x0a}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_sysclk_en_sel), 0x1a}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_lock_cmp_cfg), 0x14}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_vco_tune_map), 0x04}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_core_clk_en), 0x20}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_cmn_config_1), 0x16}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_auto_gain_adj_ctrl_1), 0xb6}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_auto_gain_adj_ctrl_2), 0x4b}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_auto_gain_adj_ctrl_3), 0x37}, + {(u32)offsetof(struct usb3_phy_qserdes_com_reg_layout, com_additional_misc), 0x0c}, +}; + +static const qmp_phy_init_tbl_t qmp_v4_usb3_tx_tbl[] = { + {(u32)offsetof(struct usb3_phy_qserdes_tx_reg_layout, tx_res_code_lane_tx), 0x00}, + {(u32)offsetof(struct usb3_phy_qserdes_tx_reg_layout, tx_res_code_lane_rx), 0x00}, + {(u32)offsetof(struct usb3_phy_qserdes_tx_reg_layout, tx_res_code_lane_offset_tx), 0x1f}, + {(u32)offsetof(struct usb3_phy_qserdes_tx_reg_layout, tx_res_code_lane_offset_rx), 0x09}, + {(u32)offsetof(struct usb3_phy_qserdes_tx_reg_layout, tx_lane_mode_1), 0xf5}, + {(u32)offsetof(struct usb3_phy_qserdes_tx_reg_layout, tx_lane_mode_3), 0x3f}, + {(u32)offsetof(struct usb3_phy_qserdes_tx_reg_layout, tx_lane_mode_4), 0x3f}, + {(u32)offsetof(struct usb3_phy_qserdes_tx_reg_layout, tx_lane_mode_5), 0x5f}, + {(u32)offsetof(struct usb3_phy_qserdes_tx_reg_layout, tx_rcv_detect_lvl_2), 0x12}, + {(u32)offsetof(struct usb3_phy_qserdes_tx_reg_layout, tx_pi_qec_ctrl), 0x21}, +}; + +static const qmp_phy_init_tbl_t qmp_v4_usb3_rx_tbl[] = { + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_ucdr_fo_gain), 0x0a}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_ucdr_so_gain), 0x06}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_ucdr_fastlock_fo_gain), 0x2f}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_ucdr_so_saturation_and_enable), 0x7f}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_ucdr_fastlock_count_low), 0xff}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_ucdr_fastlock_count_high), 0x0f}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_ucdr_pi_controls), 0x99}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_ucdr_sb2_thresh1), 0x08}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_ucdr_sb2_thresh2), 0x08}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_ucdr_sb2_gain1), 0x00}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_ucdr_sb2_gain2), 0x0a}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_aux_data_tcoarse_tfine), 0xa0}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_vga_cal_cntrl1), 0x54}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_vga_cal_cntrl2), 0x0f}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_gm_cal), 0x13}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_equ_adaptor_cntrl2), 0x0f}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_equ_adaptor_cntrl3), 0x4a}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_equ_adaptor_cntrl4), 0x0a}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_idac_tsettle_low), 0x07}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_idac_tsettle_high), 0x00}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_eq_offset_adaptor_cntrl1), 0x47}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_sigdet_cntrl), 0x04}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_sigdet_deglitch_cntrl), 0x0e}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_mode_00_low), 0x3f}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_mode_00_high), 0xbf}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_mode_00_high2), 0xff}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_mode_00_high3), 0xdf}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_mode_00_high4), 0xed}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_mode_01_low), 0xdc}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_mode_01_high), 0x5c}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_mode_01_high2), 0x9c}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_mode_01_high3), 0x1d}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_rx_mode_01_high4), 0x09}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_dfe_en_timer), 0x04}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_dfe_ctle_post_cal_offset), 0x38}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_dcc_ctrl1), 0x0c}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_vth_code), 0x10}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_sigdet_cal_ctrl1), 0x14}, + {(u32)offsetof(struct usb3_phy_qserdes_rx_reg_layout, rx_sigdet_cal_trim), 0x08}, +}; + +static const qmp_phy_init_tbl_t qmp_v4_usb3_pcs_tbl[] = { + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_lock_detect_config1), 0xc4}, + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_lock_detect_config2), 0x89}, + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_lock_detect_config3), 0x20}, + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_lock_detect_config6), 0x13}, + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_refgen_req_config1), 0x21}, + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_rx_sigdet_lvl), 0xaa}, + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_rcvr_dtct_dly_p1u2_l), 0xe7}, + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_rcvr_dtct_dly_p1u2_h), 0x03}, + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_cdr_reset_time), 0x0a}, + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_align_detect_config1), 0x88}, + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_align_detect_config2), 0x13}, + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_pcs_tx_rx_config), 0x0c}, + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_eq_config1), 0x4b}, + {(u32)offsetof(struct usb3_phy_pcs_reg_layout, pcs_eq_config5), 0x10}, +}; + +static const qmp_phy_init_tbl_t qmp_v4_usb3_pcs_usb3_tbl[] = { + {(u32)offsetof(struct usb3_phy_pcs_usb3_reg_layout, pcs_usb3_lfps_det_high_count_val), 0xf8}, + {(u32)offsetof(struct usb3_phy_pcs_usb3_reg_layout, pcs_usb3_rxeqtraining_dfe_time_s2), 0x07}, + {(u32)offsetof(struct usb3_phy_pcs_usb3_reg_layout, pcs_usb3_rcvr_dtct_dly_u3_l), 0x40}, + {(u32)offsetof(struct usb3_phy_pcs_usb3_reg_layout, pcs_usb3_rcvr_dtct_dly_u3_h), 0x00}, +}; + +/* Global instances of PHY data with their respective configuration tables */ +static const struct ss_usb_phy_reg qmp_phy_instances[] = { + { + .com_base = (void *)QMP_PHY_MP0_QSERDES_COM_REG_BASE, + .tx_base = (void *)QMP_PHY_MP0_QSERDES_TX_REG_BASE, + .rx_base = (void *)QMP_PHY_MP0_QSERDES_RX_REG_BASE, + .pcs_base = (void *)QMP_PHY_MP0_PCS_REG_BASE, + .pcs_usb3_base = (void *)QMP_PHY_MP0_PCS_USB3_REG_BASE, + .name = "MP0", + .serdes_tbl = qmp_v4_usb3_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(qmp_v4_usb3_serdes_tbl), + .tx_tbl = qmp_v4_usb3_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(qmp_v4_usb3_tx_tbl), + .rx_tbl = qmp_v4_usb3_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(qmp_v4_usb3_rx_tbl), + .pcs_tbl = qmp_v4_usb3_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(qmp_v4_usb3_pcs_tbl), + .pcs_usb3_tbl = qmp_v4_usb3_pcs_usb3_tbl, + .pcs_usb3_tbl_num = ARRAY_SIZE(qmp_v4_usb3_pcs_usb3_tbl), + }, + { + .com_base = (void *)QMP_PHY_MP1_QSERDES_COM_REG_BASE, + .tx_base = (void *)QMP_PHY_MP1_QSERDES_TX_REG_BASE, + .rx_base = (void *)QMP_PHY_MP1_QSERDES_RX_REG_BASE, + .pcs_base = (void *)QMP_PHY_MP1_PCS_REG_BASE, + .pcs_usb3_base = (void *)QMP_PHY_MP1_PCS_USB3_REG_BASE, + .name = "MP1", + .serdes_tbl = qmp_v4_usb3_serdes_tbl, + .serdes_tbl_num = ARRAY_SIZE(qmp_v4_usb3_serdes_tbl), + .tx_tbl = qmp_v4_usb3_tx_tbl, + .tx_tbl_num = ARRAY_SIZE(qmp_v4_usb3_tx_tbl), + .rx_tbl = qmp_v4_usb3_rx_tbl, + .rx_tbl_num = ARRAY_SIZE(qmp_v4_usb3_rx_tbl), + .pcs_tbl = qmp_v4_usb3_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(qmp_v4_usb3_pcs_tbl), + .pcs_usb3_tbl = qmp_v4_usb3_pcs_usb3_tbl, + .pcs_usb3_tbl_num = ARRAY_SIZE(qmp_v4_usb3_pcs_usb3_tbl), + }, +}; + +/* Modified configure function to accept a base address for the current block */ +static void qcom_qmp_phy_configure(void *base_addr, const qmp_phy_init_tbl_t tbl[], unsigned int num) +{ + int i; + const qmp_phy_init_tbl_t *t = tbl; + + if (!t) + return; + + for (i = 0; i < num; i++, t++) + write32((void *)((unsigned long)base_addr + t->offset), t->val); +} + +/* Unified PHY initialization function that takes PHY instance data */ +static bool ss_qmp_phy_init_common(const struct ss_usb_phy_reg *ss_phy_reg) +{ + bool ret = true; + /* Use the PCS base address from ss_phy_reg to cast to the PCS register layout */ + struct usb3_phy_pcs_reg_layout *current_pcs_reg = (struct usb3_phy_pcs_reg_layout *)ss_phy_reg->pcs_base; + + printk(BIOS_DEBUG, "QMP PHY %s init\n", ss_phy_reg->name); + + /* power up USB3 PHY */ + write32(¤t_pcs_reg->pcs_power_down_control, 0x01); + + /* Serdes configuration */ + qcom_qmp_phy_configure(ss_phy_reg->com_base, ss_phy_reg->serdes_tbl, + ss_phy_reg->serdes_tbl_num); + + /* Tx, Rx, and PCS configurations */ + qcom_qmp_phy_configure(ss_phy_reg->pcs_base, ss_phy_reg->pcs_tbl, + ss_phy_reg->pcs_tbl_num); + qcom_qmp_phy_configure(ss_phy_reg->tx_base, ss_phy_reg->tx_tbl, + ss_phy_reg->tx_tbl_num); + qcom_qmp_phy_configure(ss_phy_reg->rx_base, ss_phy_reg->rx_tbl, + ss_phy_reg->rx_tbl_num); + qcom_qmp_phy_configure(ss_phy_reg->pcs_usb3_base, ss_phy_reg->pcs_usb3_tbl, + ss_phy_reg->pcs_usb3_tbl_num); + + udelay(100); + + /* perform software reset of PCS/Serdes */ + write32(¤t_pcs_reg->pcs_sw_reset, 0x00); + /* start PCS/Serdes to operation mode */ + write32(¤t_pcs_reg->pcs_start_control, 0x03); + + udelay(100); + /* + * Wait for PHY initialization to be done + * PCS_STATUS: wait for 1ms for PHY STATUS; + * SW can continuously check for PHYSTATUS = 1.b0. + */ + long lock_us = wait_us(10000, + !(read32(¤t_pcs_reg->pcs_pcs_status1)& + USB3_PCS_PHYSTATUS)); + if (!lock_us) { + ret = false; + printk(BIOS_ERR, "QMP PHY %s PLL LOCK fails:\n", ss_phy_reg->name); + } else { + printk(BIOS_DEBUG, "QMP PHY %s initialized and locked in %ldus\n", + ss_phy_reg->name, lock_us); + } + return ret; +} + +/* Unified ss_qmp_phy_init function to initialize a specific PHY instance +Pass 0 for MP0, or 1 for MP1. */ +bool ss_qmp_phy_init(u32 phy_idx) +{ + bool ret = true; + + /* Ensure the provided index is valid */ + if (phy_idx >= ARRAY_SIZE(qmp_phy_instances)) { + printk(BIOS_ERR, "Invalid PHY index provided: %u\n", phy_idx); + return false; + } + + if (!ss_qmp_phy_init_common(&qmp_phy_instances[phy_idx])) { + ret = false; + } + return ret; +} diff --git a/src/soc/qualcomm/x1p42100/usb/snps_usb_phy.c b/src/soc/qualcomm/x1p42100/usb/snps_usb_phy.c new file mode 100644 index 0000000000..2fc35ad077 --- /dev/null +++ b/src/soc/qualcomm/x1p42100/usb/snps_usb_phy.c @@ -0,0 +1,239 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include + +#define SLEEPM BIT(0) + +#define TERMSEL BIT(5) + +#define POR BIT(1) + +/* Updated FSEL_MASK based on the table feedback (GENMASK(6,4) for 38.4MHz) */ +#define FSEL_MASK GENMASK(6, 4) +#define FSEL_DEFAULT (0x3 << 4) /* Original value, may not be used directly */ + +#define VBUSVLDEXTSEL0 BIT(4) +#define PLLBTUNE BIT(5) + +#define VREGBYPASS BIT(0) + +#define VBUSVLDEXT0 BIT(0) + +/* Updated macros for clarity as per feedback */ +#define USB2_SUSPEND_N_BIT BIT(2) +#define USB2_SUSPEND_N_SEL_BIT BIT(3) + +#define UTMI_PHY_CMN_CTRL_OVERRIDE_EN BIT(1) + +#define REFCLK_SEL_MASK GENMASK(1, 0) +#define REFCLK_SEL_DEFAULT (0x2 << 0) + +#define PARAM_OVRD_MASK 0xFF + +/* Streamlined macros for common control bits (from previous feedback) */ +#define USB_PHY_ENABLE_BIT BIT(0) +#define USB_PHY_RETENABLEN_BIT BIT(3) +#define APB_LOGIC_RESET_BIT BIT(2) +#define TESTBURNIN_BIT BIT(6) +#define FSEL_SEL_BIT BIT(0) + +/* New macros from table requirements (to be used in sequence) */ +#define FSEL_38_4_MHZ_VAL (0x4 << 4) /* 3'b100 for bits 6:4 -> 0x4, shifted by 4 */ +#define SIDDQ_SEL_BIT BIT(1) +#define SIDDQ_DISABLE_BIT BIT(2) /* SIDDQ is set to 0, means power up analog blocks */ + +#define CFG_CTRL_2_VALUE 0xC8 /* For phy_cfg_pll_fb_div_7_0 */ + +#define CFG_CTRL_3_FB_DIV_MASK GENMASK(3, 0) +#define CFG_CTRL_3_FB_DIV_VALUE 0x0 /* 4'b0000 */ + +#define CFG_CTRL_3_REF_DIV_MASK GENMASK(7, 4) +#define CFG_CTRL_3_REF_DIV_VALUE (0x0 << 4) /* 4'b0000 shifted to bits 7:4 */ + +#define CFG_CTRL_1_PLL_CPBIAS_MASK GENMASK(7, 1) +#define CFG_CTRL_1_PLL_CPBIAS_VALUE (0x0 << 1) /* 7'b0000000 shifted to bits 7:1 */ + +#define CFG_CTRL_4_PLL_VCO_GAIN_MASK GENMASK(1, 0) +#define CFG_CTRL_4_PLL_VCO_GAIN_VALUE 0x1 /* 2'b01 */ + +#define CFG_CTRL_4_PLL_INT_GAIN_MASK GENMASK(7, 2) +#define CFG_CTRL_4_PLL_INT_GAIN_VALUE (0x8 << 2) /* 6'b001000 shifted to bits 7:2 */ + +#define CFG_CTRL_5_PLL_PROP_GAIN_MASK GENMASK(5, 0) +#define CFG_CTRL_5_PLL_PROP_GAIN_VALUE 0x10 /* 6'b010000 */ + +#define CFG_CTRL_6_PLL_VCO_CFG_MASK GENMASK(2, 0) +#define CFG_CTRL_6_PLL_VCO_CFG_VALUE 0x0 /* 3'b000 */ + +#define CFG_CTRL_5_PLL_VREF_TUNE_MASK GENMASK(7, 6) +#define CFG_CTRL_5_PLL_VREF_TUNE_VALUE (0x1 << 6) /* 2'b01 shifted to bits 7:6 */ + +#define VBUS_DET_EXT_SEL_BIT BIT(4) +#define VBUS_VALID_EXT_BIT BIT(0) + +#define CFG_CTRL_9_TX_PREEMP_MASK GENMASK(2, 0) +#define CFG_CTRL_9_TX_PREEMP_VALUE 0x0 /* 3'b000 */ + +#define CFG_CTRL_8_TX_HS_VREF_MASK GENMASK(5, 3) +#define CFG_CTRL_8_TX_HS_VREF_VALUE (0x3 << 3) /* 3'b011 shifted to bits 5:3 */ + +#define CFG_CTRL_9_TX_RISE_TUNE_MASK GENMASK(6, 5) +#define CFG_CTRL_9_TX_RISE_TUNE_VALUE (0x2 << 5) /* 2'b10 shifted to bits 6:5 */ + +#define CFG_CTRL_8_TX_HS_XV_TUNE_MASK GENMASK(7, 6) +#define CFG_CTRL_8_TX_HS_XV_TUNE_VALUE (0x0 << 6) /* 2'b00 shifted to bits 7:6 */ + +#define CFG_CTRL_9_TX_RES_TUNE_MASK GENMASK(4, 3) +#define CFG_CTRL_9_TX_RES_TUNE_VALUE (0x1 << 3) /* 2'b01 shifted to bits 4:3 */ + + +struct hs_usb_phy_reg *hs_phy_reg = NULL; +void hs_usb_phy_init(int index) +{ + if (index == 0) + hs_phy_reg = (void *)HS_USB_MP0_PHY_BASE; + else + hs_phy_reg = (void *)HS_USB_MP1_PHY_BASE; + + /* + * This sequence initializes the USB HS PHY. + */ + + /* Step 1: USB_PHY_CFG0[1] = 1'b1 (UTMI_PHY_CMN_CNTRL_OVERRIDE_EN=1) */ + /* This is a MUX select signal to enable software override of UTMI PHY common control. */ + clrsetbits32(&hs_phy_reg->cfg0, UTMI_PHY_CMN_CTRL_OVERRIDE_EN, + UTMI_PHY_CMN_CTRL_OVERRIDE_EN); + + /* Step 2: USB_PHY_UTMI_CTRL5[1] = 1'b1 (POR asserted) */ + /* Assert the PHY reset. This reset must be held for at least 10us after all supplies ramp up. */ + clrsetbits32(&hs_phy_reg->utmi_ctrl5, POR, POR); + udelay(10); /* Hold POR for 10us */ + + /* Step 3: USB_PHY_HS_PHY_CTRL_COMMON0[0] = 1'b1 (phy_enable='1') */ + /* Asynchronous enable for the PHY. If low during POR de-assertion, PHY remains inactive. */ + clrsetbits32(&hs_phy_reg->hs_phy_ctrl_common0, USB_PHY_ENABLE_BIT, USB_PHY_ENABLE_BIT); + + /* Step 4: USB_PHY_HS_PHY_CTRL_COMMON0[3] = 1'b1 (Retention Mode Enable) */ + /* Set retenable_n = 1'b1. This signal must be high when VDD supply is powered. */ + clrsetbits32(&hs_phy_reg->hs_phy_ctrl_common0, USB_PHY_RETENABLEN_BIT, USB_PHY_RETENABLEN_BIT); + + /* Step 5: USB_PHY_APB_ACCESS_CMD[2] = 1'b1 (APB Logic Reset) */ + /* Reset all APB related logic, including SNPS APB FSM but not the APB registers. */ + clrsetbits32(&hs_phy_reg->usb_phy_apb_access_cmd, APB_LOGIC_RESET_BIT, APB_LOGIC_RESET_BIT); + + /* Step 6: UTMI_PHY_CMN_CTRL0[6] = 1'b0 (Burn-in Test Enable - clear the bit) */ + /* De-assert test_burnin. If asserted, PHY performs power-on-reset and enters HS Loopback mode. */ + clrsetbits32(&hs_phy_reg->utmi_phy_cmn_ctrl0, TESTBURNIN_BIT, 0); + + /* Step 7: USB_PHY_FSEL_SEL = 1'b1 (FSEL MUX select for SW override) */ + /* Select software override for frequency selection. */ + clrsetbits32(&hs_phy_reg->usb_phy_fsel_sel, FSEL_SEL_BIT, FSEL_SEL_BIT); + + /* Step 8: USB_PHY_HS_PHY_CTRL_COMMON0[6:4] = 3'b100 (Sets refclk frequency to 38.4 MHz) */ + /* Configure the reference clock frequency. */ + clrsetbits32(&hs_phy_reg->hs_phy_ctrl_common0, FSEL_MASK, FSEL_38_4_MHZ_VAL); + + /* Step 9: USB_PHY_CFG_CTRL_2[7:0] = 8'b11001000 (Control of the feedback multiplication ratio) */ + /* Configure phy_cfg_pll_fb_div_7_0. */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_2, 0xFF, CFG_CTRL_2_VALUE); /* Using 0xFF for full 8-bit mask */ + + /* Step 10: USB_PHY_CFG_CTRL_3[3:0] = 4'b0000 (Control of the feedback multiplication ratio) */ + /* Configure phy_cfg_pll_fb_div_11_8. */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_3, CFG_CTRL_3_FB_DIV_MASK, CFG_CTRL_3_FB_DIV_VALUE); + + /* Step 11: USB_PHY_CFG_CTRL_3[7:4] = 4'b0000 (Control of the input frequency division ratio) */ + /* Configure phy_cfg_pll_ref_div. */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_3, CFG_CTRL_3_REF_DIV_MASK, CFG_CTRL_3_REF_DIV_VALUE); + + /* Step 12: USB_PHY_CFG_CTRL_1[7:1] = 7'b0000000 (PLL loop bias configuration) */ + /* Configure phy_cfg_pll_cpbias_cntrl. */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_1, CFG_CTRL_1_PLL_CPBIAS_MASK, CFG_CTRL_1_PLL_CPBIAS_VALUE); + + /* Step 13: USB_PHY_CFG_CTRL_4[1:0] = 2'b01 (PLL vco source gain) */ + /* Configure phy_cfg_pll_gmp_cntrl. */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_4, CFG_CTRL_4_PLL_VCO_GAIN_MASK, CFG_CTRL_4_PLL_VCO_GAIN_VALUE); + + /* Step 14: USB_PHY_CFG_CTRL_4[7:2] = 6'b001000 (Gain of PLL Integral Charge Pump) */ + /* Configure phy_cfg_pll_int_cntrl. */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_4, CFG_CTRL_4_PLL_INT_GAIN_MASK, CFG_CTRL_4_PLL_INT_GAIN_VALUE); + + /* Step 15: USB_PHY_CFG_CTRL_5[5:0] = 6'b010000 (Gain of PLL Proportional Charge Pump) */ + /* Configure phy_cfg_pll_prop_cntrl. */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_5, CFG_CTRL_5_PLL_PROP_GAIN_MASK, CFG_CTRL_5_PLL_PROP_GAIN_VALUE); + + /* Step 16: USB_PHY_CFG_CTRL_6[2:0] = 3'b000 (PLL VCO configuration) */ + /* Configure phy_cfg_pll_vco_cntrl. */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_6, CFG_CTRL_6_PLL_VCO_CFG_MASK, CFG_CTRL_6_PLL_VCO_CFG_VALUE); + + /* Step 17: USB_PHY_CFG_CTRL_5[7:6] = 2'b01 (Configuration for PLL voltage reference level) */ + /* Configure phy_cfg_pll_vref_tune. */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_5, CFG_CTRL_5_PLL_VREF_TUNE_MASK, CFG_CTRL_5_PLL_VREF_TUNE_VALUE); + + /* Step 18: Selects UTMI data bus width. Wordinterface<#> = 0; for 8 bits interface (60 MHz) + * No register control, tied at chip top. + */ + + /* Step 19: USB_PHY_HS_PHY_CTRL2[4] = 1'b1 (VBUS MUX Selection) */ + /* Select software control for VBUS detection. */ + clrsetbits32(&hs_phy_reg->hs_phy_ctrl2, VBUS_DET_EXT_SEL_BIT, VBUS_DET_EXT_SEL_BIT); + + /* Step 20: USB_PHY_HS_PHY_CTRL2[0] = 1'b1 (VBUS valid indication) */ + /* Software writes this bit to indicate VBUS status. */ + clrsetbits32(&hs_phy_reg->hs_phy_ctrl2, VBUS_VALID_EXT_BIT, VBUS_VALID_EXT_BIT); + + /* Step 21: USB_PHY_CFG_CTRL_9[2:0] = 3'b000 (HS Transmitter Pre-Emphasis Control) */ + /* Set HS Transmitter pre-emphasis to off (design default). */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_9, CFG_CTRL_9_TX_PREEMP_MASK, CFG_CTRL_9_TX_PREEMP_VALUE); + + /* Step 22: USB_PHY_CFG_CTRL_8[5:3] = 3'b011 (HS DC Voltage Level Adjustment) */ + /* Set HS DC Voltage Level to default (increased). */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_8, CFG_CTRL_8_TX_HS_VREF_MASK, CFG_CTRL_8_TX_HS_VREF_VALUE); + + /* Step 23: USB_PHY_CFG_CTRL_9[6:5] = 2'b10 (HS Transmitter Rise/Fall Time Adjustment) */ + /* Set HS Transmitter Rise/Fall Time Adjustment to default. */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_9, CFG_CTRL_9_TX_RISE_TUNE_MASK, CFG_CTRL_9_TX_RISE_TUNE_VALUE); + + /* Step 24: USB_PHY_CFG_CTRL_8[7:6] = 2'b00 (Transmitter High-Speed Crossover Adjustment) */ + /* Set Transmitter High-Speed Crossover Adjustment to default (0V). */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_8, CFG_CTRL_8_TX_HS_XV_TUNE_MASK, CFG_CTRL_8_TX_HS_XV_TUNE_VALUE); + + /* Step 25: USB_PHY_CFG_CTRL_9[4:3] = 2'b01 (USB Source Impedance Adjustment) */ + /* Set USB Source Impedance Adjustment to default. */ + clrsetbits32(&hs_phy_reg->cfg_ctrl_9, CFG_CTRL_9_TX_RES_TUNE_MASK, CFG_CTRL_9_TX_RES_TUNE_VALUE); + + /* Step 26: USB_PHY_HS_PHY_CTRL2[3] = 1'b1 (USB2_SUSPEND_N_SEL) */ + /* Select SW option for suspend_n signal. */ + clrsetbits32(&hs_phy_reg->hs_phy_ctrl2, USB2_SUSPEND_N_SEL_BIT, USB2_SUSPEND_N_SEL_BIT); + + /* Step 27: USB_PHY_HS_PHY_CTRL2[2] = 1'b1 (USB2_SUSPEND_N) */ + /* Assert USB2_SUSPEND_N. */ + clrsetbits32(&hs_phy_reg->hs_phy_ctrl2, USB2_SUSPEND_N_BIT, USB2_SUSPEND_N_BIT); + + /* Step 28: USB_PHY_UTMI_CTRL0[0] = 1'b1 (SLEEPM) */ + /* Set sleepm = 1; until PHYCLOCK is available. */ + clrsetbits32(&hs_phy_reg->utmi_ctrl0, SLEEPM, SLEEPM); + + /* Step 29: USB_PHY_HS_PHY_CTRL_COMMON0[1] = 1'b1 (SIDDQ MUX Selection) */ + /* Select internal CSR register (SIDDQ) for SIDDQ control. */ + clrsetbits32(&hs_phy_reg->hs_phy_ctrl_common0, SIDDQ_SEL_BIT, SIDDQ_SEL_BIT); + + /* Step 30: USB_PHY_HS_PHY_CTRL_COMMON0[2] = 1'b0 (SIDDQ set to 0) */ + /* Power up the analog blocks by setting SIDDQ to 0. */ + clrsetbits32(&hs_phy_reg->hs_phy_ctrl_common0, SIDDQ_DISABLE_BIT, 0); + + /* Step 31: USB_PHY_UTMI_CTRL5[1] = 1'b0 (POR release) */ + /* Release the POR from high to low. */ + clrsetbits32(&hs_phy_reg->utmi_ctrl5, POR, 0); + + /* Step 32: USB_PHY_HS_PHY_CTRL2[3] = 1'b0 (USB2_SUSPEND_N_SEL de-selects SW override) */ + /* De-select SW override for suspend_n, allowing HW control. */ + clrsetbits32(&hs_phy_reg->hs_phy_ctrl2, USB2_SUSPEND_N_SEL_BIT, 0); + + udelay(20); + printk(BIOS_DEBUG, "USB HS PHY initialized for index %d\n", index); +} diff --git a/src/soc/qualcomm/x1p42100/usb/usb.c b/src/soc/qualcomm/x1p42100/usb/usb.c new file mode 100644 index 0000000000..c969693c4f --- /dev/null +++ b/src/soc/qualcomm/x1p42100/usb/usb.c @@ -0,0 +1,327 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include + +struct usb_dwc3 { + u32 sbuscfg0; + u32 sbuscfg1; + u32 txthrcfg; + u32 rxthrcfg; + u32 ctl; + u32 pmsts; + u32 sts; + u32 uctl1; + u32 snpsid; + u32 gpio; + u32 uid; + u32 uctl; + u64 buserraddr; + u64 prtbimap; + u8 reserved1[32]; + u32 dbgfifospace; + u32 dbgltssm; + u32 dbglnmcc; + u32 dbgbmu; + u32 dbglspmux; + u32 dbglsp; + u32 dbgepinfo0; + u32 dbgepinfo1; + u64 prtbimap_hs; + u64 prtbimap_fs; + u8 reserved2[112]; + u32 usb2phycfg; + u32 usb2phycfg_mp1; + u8 reserved3[120]; + u32 usb2phyacc; + u8 reserved4[60]; + u32 usb3pipectl; + u32 usb3pipectl_mp1; + u8 reserved5[56]; +}; +check_member(usb_dwc3, usb2phycfg_mp1, 0x104); +check_member(usb_dwc3, usb3pipectl_mp1, 0x1c4); + +struct usb_dwc3_cfg { + struct usb_dwc3 *usb_host_dwc3; + u32 *usb3_bcr; + u32 *qusb2phy_bcr; + u32 *qusb2phy1_bcr; + u32 *gcc_usb3phy_bcr_reg; + u32 *gcc_qmpphy_bcr_reg; + u32 *gcc_usb3phy1_bcr_reg; + u32 *gcc_qmpphy1_bcr_reg; + u32 *qusb2secphy_bcr; + u32 *gcc_usb3secphy_bcr_reg; + u32 *gcc_qmpsecphy_bcr_reg; +}; + +static struct usb_dwc3_cfg usb_port0 = { + .usb_host_dwc3 = (void *)USB_HOST_DWC3_BASE, + .usb3_bcr = &gcc->gcc_usb30_mp_bcr, + .qusb2phy_bcr = &gcc->qusb2phy_hs0_mp_bcr, + .gcc_usb3phy_bcr_reg = &gcc->usb3uniphy_phy_mp0_bcr, + .gcc_qmpphy_bcr_reg = &gcc->usb3_uniphy_mp0_bcr, + .qusb2phy1_bcr = &gcc->qusb2phy_hs1_mp_bcr, + .gcc_usb3phy1_bcr_reg = &gcc->usb3uniphy_phy_mp1_bcr, + .gcc_qmpphy1_bcr_reg = &gcc->usb3_uniphy_mp1_bcr, +}; + +bool hs_speed_only = false; +u32 *usb3_general_cfg_addr = (void *)USB_HOST_DWC3_GENERAL_CFG_ADDR; + +/* Enables Repeaters /Refgen blocks for USB */ +void enable_clock_tcsr(void) +{ + write32(TCSR_GCC_CXO_1_REFGEN_BIAS_SEL__SEL_REFGEN_ADDR, 0x00000001); + write32(TCSR_GCC_CXO_0_REFGEN_BIAS_SEL__SEL_REFGEN_ADDR, 0x00000001); + + write32(TCSR_QREFS_CXO_0_RPT3_CONFIG_ADDR, 0x3); + write32(TCSR_QREFS_CXO_0_RPT4_CONFIG_ADDR, 0x3); + write32(TCSR_QREFS_CXO_1_RPT0_CONFIG_ADDR, 0x3); + write32(TCSR_QREFS_CXO_1_RX3_CONFIG_ADDR, 0x3); + write32(TCSR_QREFS_CXO_1_RX0_CONFIG_ADDR, 0x3); + write32(TCSR_QREFS_CXO_0_RX3_CONFIG_ADDR, 0x3); + write32(TCSR_QREFS_CXO_0_RX4_CONFIG_ADDR, 0x3); +} +/* + * qcom_enable_usb_clk - Enables USB clocks and GDSCs for Qualcomm SoCs. + * @return 0 on success, or a negative error code on failure. + */ +int32_t qcom_enable_usb_clk(void) +{ + int32_t ret, clk, gdsc; + + /* Enable USB GDSCs before enabling USB clocks */ + for (gdsc = USB30_MP_GDSC; gdsc < MAX_USB_GDSC; gdsc++) { + ret = clock_enable_usb_gdsc(gdsc); + if (ret) { + printk(BIOS_ERR, "Failed to enable USB GDSC %d\n", gdsc); + return ret; + } + } + + clock_configure_usb(); + /* Set USB3 PHY PIPE 0 clock source to X0 */ + if (usb_clock_configure_mux(USB3_PHY_PIPE_0, USB_PHY_XO_SRC_SEL)) { + printk(BIOS_ERR, "%s(): USB3 PHY PIPE 0 clock enable failed\n", __func__); + return -1; + } + if (usb_clock_configure_mux(USB3_PHY_PIPE_1, USB_PHY_XO_SRC_SEL)) { + printk(BIOS_ERR, "%s(): USB3 PHY PIPE 0 clock enable failed\n", __func__); + return -1; + } + /* Enable USB MP clocks */ + for (clk = USB30_MP_MASTER_CBCR; clk < USB_CLK_COUNT; clk++) { + ret = usb_clock_enable(clk); + if (ret) { + printk(BIOS_ERR, "Failed to enable %d clock\n", clk); + return ret; + } + } + + write32(TCSR_GCC_USB3_MP0_CLKREF_EN_ADDR, USB3_CLKREF_ENABLE_VALUE); + write32(TCSR_GCC_USB3_MP1_CLKREF_EN_ADDR, USB3_CLKREF_ENABLE_VALUE); + /* Set USB3 PHY PIPE 1 clock source to USB PHY */ + + if (usb_clock_configure_mux(USB3_PHY_PIPE_0, USB_PHY_PIPE_SRC_SEL)) { + printk(BIOS_ERR, "%s(): USB3 PHY PIPE 1 clock enable failed\n", __func__); + return -1; + } + + if (usb_clock_configure_mux(USB3_PHY_PIPE_1, USB_PHY_PIPE_SRC_SEL)) { + printk(BIOS_ERR, "%s(): USB3 PHY PIPE 1 clock enable failed\n", __func__); + return -1; + } + + return ret; +} + +/* + * setup_dwc3 - Configures the DWC3 USB controller. + * @dwc3: Pointer to the USB DWC3 configuration structure. + * Handles high-speed operation, power management, and sets to host mode. + */ + +static void setup_dwc3(struct usb_dwc3 *dwc3) +{ + u32 *reg = usb3_general_cfg_addr; + if (hs_speed_only) { + /* Set UTMI_CLK_DIS_0 */ + setbits32(reg, UTMI_CLK_DIS_0); + udelay(10); + + /* Set UTMI_CLK_SEL_0 */ + setbits32(reg, UTMI_CLK_SEL_0); + + /* Set PIPE3_PHYSTATUS_SW_0 */ + setbits32(reg, PIPE3_PHYSTATUS_SW_0); + + /* Clear PIPE3_SET_PHYSTATUS_SW_0 */ + clrbits32(reg, PIPE3_SET_PHYSTATUS_SW_0); + udelay(10); + + /* Clear UTMI_CLK_DIS_0 */ + clrbits32(reg, UTMI_CLK_DIS_0); + } else { + /* core exits U1/U2/U3 only in PHY power state P1/P2/P3 respectively */ + clrsetbits32(&dwc3->usb3pipectl, + DWC3_GUSB3PIPECTL_DELAYP1TRANS, + DWC3_GUSB3PIPECTL_UX_EXIT_IN_PX); + + clrsetbits32(&dwc3->usb3pipectl_mp1, + DWC3_GUSB3PIPECTL_DELAYP1TRANS, + DWC3_GUSB3PIPECTL_UX_EXIT_IN_PX); + } + /* + * Configure USB phy interface of DWC3 core. + * 1. Select UTMI+ PHY with 16-bit interface. + * 2. Set USBTRDTIM to the corresponding value + * according to the UTMI+ PHY interface. + */ + clrsetbits32(&dwc3->usb2phycfg, + (DWC3_GUSB2PHYCFG_USB2TRDTIM_MASK | + DWC3_GUSB2PHYCFG_PHYIF_MASK | + DWC3_GUSB2PHYCFG_ENBLSLPM_MASK), + (DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) | + DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT))); + + clrsetbits32(&dwc3->usb2phycfg_mp1, + (DWC3_GUSB2PHYCFG_USB2TRDTIM_MASK | + DWC3_GUSB2PHYCFG_PHYIF_MASK | + DWC3_GUSB2PHYCFG_ENBLSLPM_MASK), + (DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) | + DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT))); + /* + To save power, enable the hardware-based clock gating (not relevant for PBL): + a. usb30_reg_cgctl[DBM_FSM_EN] = 0x1 + */ + setbits32(USB3_MP_CGCTL_REG_ADDR, USB3_MP_DBM_FSM_EN_BIT); + //Disable clock gating: DWC_USB3_GCTL.DSBLCLKGTNG = 1 + clrsetbits32(&dwc3->ctl, (DWC3_GCTL_SCALEDOWN_MASK | + DWC3_GCTL_DISSCRAMBLE), + DWC3_GCTL_U2EXIT_LFPS | DWC3_GCTL_DSBLCLKGTNG); + + //Allow PHY to transition to P2 from suspend (P3) state. + setbits32(&dwc3->usb3pipectl, + (DWC3_GUSB3PIPECTL_P3EXSIGP2| + DWC3_GUSB3PIPECTL_UX_EXIT_IN_PX)); + + setbits32(&dwc3->usb3pipectl_mp1, + (DWC3_GUSB3PIPECTL_P3EXSIGP2| + DWC3_GUSB3PIPECTL_UX_EXIT_IN_PX)); + + // Reduce U3 exit handshake timer to 300ns + clrsetbits32(USB3_MP_LINK_REGS_0_LU3LFPSRXTIM_ADDR, + LFPS_RSP_RX_CLK_CLR_MASK, LFPS_RSP_RX_CLK_SET_MASK); + + clrsetbits32(USB3_MP_LINK_REGS_1_LU3LFPSRXTIM_ADDR, + LFPS_RSP_RX_CLK_CLR_MASK, LFPS_RSP_RX_CLK_SET_MASK); + + clrsetbits32(&dwc3->uctl1, + DWC3_GUCTL1_CLR_MASK, // Clear L1 exit and IP gap bits + DWC3_GUCTL1_SET_MASK); + + clrbits32(USB3_MP_GUSB2PHYCFG_REGS_0_ADDR, GUSB2PHYCFG_ENBLSLPM_BIT); + + clrbits32(USB3_MP_GUSB2PHYCFG_REGS_1_ADDR, GUSB2PHYCFG_ENBLSLPM_BIT); + + /* configure controller in Host mode */ + clrsetbits32(&dwc3->ctl, (DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)), + DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_HOST)); + printk(BIOS_SPEW, "Configure USB in Host mode\n"); + + setbits32(USB3_MP_PORTSC_20_REGS_0_ADDR, USB3_PORTSC_WCE_BIT); + + setbits32(USB3_MP_PORTSC_20_REGS_1_ADDR, USB3_PORTSC_WCE_BIT); + + setbits32(USB3_MP_PORTSC_30_REGS_0_ADDR, USB3_PORTSC_WCE_BIT); + + setbits32(USB3_MP_PORTSC_30_REGS_1_ADDR, USB3_PORTSC_WCE_BIT); + +} + +/* Initialization of DWC3 Core and PHY */ +static void setup_usb_host(struct usb_dwc3_cfg *dwc3) +{ + /* Call Clock Enable */ + qcom_enable_usb_clk(); + + enable_clock_tcsr(); + + /* Clear core reset. */ + clock_reset_bcr(dwc3->usb3_bcr, 1); + udelay(10); + clock_reset_bcr(dwc3->usb3_bcr, 0); + udelay(10); + + /* Repeater enable MP0*/ + gpio_output(GPIO(6), 0x1); + + /* Repeater enable MP1*/ + gpio_output(GPIO(184), 0x1); + + /* Clear QUSB PHY reset. */ + clock_reset_bcr(dwc3->qusb2phy_bcr, 1); + clock_reset_bcr(dwc3->qusb2phy1_bcr, 1); + udelay(10); + clock_reset_bcr(dwc3->qusb2phy_bcr, 0); + clock_reset_bcr(dwc3->qusb2phy1_bcr, 0); + + /* Initialize HS PHY */ + hs_usb_phy_init(0); + hs_usb_phy_init(1); + + /* Clear QMP PHY resets. */ + usb_clock_reset(USB3_MP_PHY_PIPE_0_CBCR, 1); + usb_clock_reset(USB3_MP_PHY_PIPE_1_CBCR, 1); + udelay(10); + + usb_clock_reset(USB30_MP_MASTER_CBCR, 1); + usb_clock_reset(USB30_MP_MASTER_CBCR, 0); + udelay(10); + + clock_reset_bcr(dwc3->gcc_usb3phy_bcr_reg, 1); + clock_reset_bcr(dwc3->gcc_qmpphy_bcr_reg, 1); + + clock_reset_bcr(dwc3->gcc_usb3phy1_bcr_reg, 1); + clock_reset_bcr(dwc3->gcc_qmpphy1_bcr_reg, 1); + udelay(10); + + clock_reset_bcr(dwc3->gcc_usb3phy_bcr_reg, 0); + clock_reset_bcr(dwc3->gcc_qmpphy_bcr_reg, 0); + + clock_reset_bcr(dwc3->gcc_usb3phy1_bcr_reg, 0); + clock_reset_bcr(dwc3->gcc_qmpphy1_bcr_reg, 0); + udelay(10); + + usb_clock_reset(USB3_MP_PHY_PIPE_0_CBCR, 0); + usb_clock_reset(USB3_MP_PHY_PIPE_1_CBCR, 0); + + /* Initialize QMP PHY */ + bool ret0 = ss_qmp_phy_init(0); + bool ret1 = ss_qmp_phy_init(1); + + /* If SS PHY init fails fall back to HS speed */ + if (!ret0 || !ret1) + hs_speed_only = true; + + setup_dwc3(dwc3->usb_host_dwc3); + + printk(BIOS_INFO, "DWC3 and PHY setup finished\n"); +} +/* + * setup_usb_host0 - Sets up USB HOST0 controller. + * Initializes and configures the USB HOST0 controller, including clocks, + * PHY resets, and DWC3 core for host mode. +*/ +void setup_usb_host0(void) +{ + printk(BIOS_INFO, "Setting up USB HOST0 controller.\n"); + setup_usb_host(&usb_port0); +}