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 index 6a5069844f..220f155fe2 100644 --- a/src/soc/qualcomm/x1p42100/include/soc/usb/qmp_usb_phy.h +++ b/src/soc/qualcomm/x1p42100/include/soc/usb/qmp_usb_phy.h @@ -50,4 +50,4 @@ struct ss_usb_phy_reg { bool ss_qmp_phy_init(u32 phy_idx); /* Initialize SS0/SS1 QMP PHY - pass 0 for SS0, 1 for SS1 */ -enum cb_err qmp_usb4_dp_phy_ss_init(int phy_instance); +enum cb_err qmp_usb4_dp_phy_ss_init(int phy_instance, bool polarity_inverse); diff --git a/src/soc/qualcomm/x1p42100/include/soc/usb/usb.h b/src/soc/qualcomm/x1p42100/include/soc/usb/usb.h index 360e319939..4ac6dad763 100644 --- a/src/soc/qualcomm/x1p42100/include/soc/usb/usb.h +++ b/src/soc/qualcomm/x1p42100/include/soc/usb/usb.h @@ -124,6 +124,7 @@ #define SCHG_TYPE_C_TYPE_C_SRC_STATUS 0x2B08 #define SCHG_TYPE_C_TYPE_C_MODE_CFG 0x2B44 #define TYPEC_VBUS_STATUS_MASK BIT(5) +#define CCOUT_INVERT_POLARITY 0x03 /* Forward declaration */ struct dwc3_controller_config; diff --git a/src/soc/qualcomm/x1p42100/usb/qmpv4_usb4_dp_phy.c b/src/soc/qualcomm/x1p42100/usb/qmpv4_usb4_dp_phy.c index 6da080be6e..9a500b8e29 100644 --- a/src/soc/qualcomm/x1p42100/usb/qmpv4_usb4_dp_phy.c +++ b/src/soc/qualcomm/x1p42100/usb/qmpv4_usb4_dp_phy.c @@ -538,8 +538,9 @@ static void qcom_qmp_phy_configure(void *base_addr, const qmp_phy_init_tbl_t tbl } /* SS QMP PHY initialization function - supports both SS0 and SS1 */ -enum cb_err qmp_usb4_dp_phy_ss_init(int phy_instance) +enum cb_err qmp_usb4_dp_phy_ss_init(int phy_instance, bool polarity_inverse) { + unsigned int lane_num = 0; if (phy_instance < 0 || phy_instance >= ARRAY_SIZE(qmp_phy_ss_instance)) { printk(BIOS_ERR, "Invalid PHY instance %d\n", phy_instance); return CB_ERR; @@ -553,10 +554,13 @@ enum cb_err qmp_usb4_dp_phy_ss_init(int phy_instance) /* Configure TYPEC_CTRL register for lane selection */ struct usb43dp_com_reg_layout *current_com_reg = (struct usb43dp_com_reg_layout *)ss_phy_reg->com_base; + /* Swap lanes based on polarity */ + if (polarity_inverse) + lane_num = 1; /* Configure SW_PORTSELECT and SW_PORTSELECT_MUX using coreboot style */ clrsetbits32(¤t_com_reg->typec_ctrl, SW_PORTSELECT_MASK | SW_PORTSELECT_MUX_MASK, - (0 << SW_PORTSELECT_SHIFT) | SW_PORTSELECT_MUX_MASK); + (lane_num << SW_PORTSELECT_SHIFT) | SW_PORTSELECT_MUX_MASK); /* Step 1: COM registers */ qcom_qmp_phy_configure(ss_phy_reg->com_base, diff --git a/src/soc/qualcomm/x1p42100/usb/usb.c b/src/soc/qualcomm/x1p42100/usb/usb.c index 5916bcef81..9e91391d06 100644 --- a/src/soc/qualcomm/x1p42100/usb/usb.c +++ b/src/soc/qualcomm/x1p42100/usb/usb.c @@ -444,6 +444,20 @@ static const struct dwc3_controller_config sec_config = { .smb_slave_addr = SMB2_SLAVE_ID, }; +/* + * get_usb_typec_polarity - Reads Type-C polarity from PMIC + * @config: Controller configuration containing SMB slave address + * + * @return TRUE if polarify is inverse + * @return FALSE if polarify is normal + */ +static bool get_usb_typec_polarity(const struct dwc3_controller_config *config) +{ + u8 slave = config->smb_slave_addr; + u8 misc_status = spmi_read8(SPMI_ADDR(slave, SCHG_TYPE_C_TYPE_C_MISC_STATUS)); + return (misc_status & CCOUT_INVERT_POLARITY) == CCOUT_INVERT_POLARITY; +} + /* Initialization of DWC3 Core and PHY */ static void setup_usb_host(struct usb_dwc3_cfg *dwc3) { @@ -530,7 +544,7 @@ static void setup_usb_host(struct usb_dwc3_cfg *dwc3) clock_reset_bcr(dwc3->gcc_usb4_0_dp0_phy_prim_bcr, 0); udelay(10); /* Initialize USB4/USB3 EDP_DP_Con PHY Configuration */ - int ss0_ret = qmp_usb4_dp_phy_ss_init(0); + int ss0_ret = qmp_usb4_dp_phy_ss_init(0, get_usb_typec_polarity(&prim_config)); if (ss0_ret != CB_SUCCESS) { printk(BIOS_ERR, "SS0 QMP PHY initialization failed\n"); high_speed_only_primary = true; @@ -559,7 +573,7 @@ static void setup_usb_host(struct usb_dwc3_cfg *dwc3) clock_reset_bcr(dwc3->gcc_usb4_1_dp0_phy_sec_bcr, 0); udelay(10); /* Initialize USB4/USB3 EDP_DP_Con PHY Configuration (secondary) */ - int ss1_ret = qmp_usb4_dp_phy_ss_init(1); + int ss1_ret = qmp_usb4_dp_phy_ss_init(1, get_usb_typec_polarity(&sec_config)); if (ss1_ret != CB_SUCCESS) { printk(BIOS_ERR, "SS1 QMP PHY initialization failed\n"); high_speed_only_secondary = true;