soc/qualcomm/x1p42100: Handle Type-C polarity for USB4/DP PHY init
This commit introduces necessary changes to correctly initialize the Qualcomm X1p42100 USB4/DP PHY based on the USB Type-C CC polarity detection. When a Type-C cable is connected, the CC lines determine the connector orientation (polarity). The USB PHY lanes must be swapped accordingly to ensure the SuperSpeed signals are routed correctly. Key changes: - Adds 'get_usb_typec_polarity()' to read the CC polarity state from the PMIC (SMB1/SMB2) via the 'SCHG_TYPE_C_MISC_STATUS' register. - Extends 'qmp_usb4_dp_phy_ss_init()' to accept a 'polarity_inverse' boolean. - Uses the polarity state to set the 'SW_PORTSELECT' register in the USB4/DP common configuration, effectively swapping the lanes when needed. - Calls the updated PHY initialization function with the appropriate polarity for both primary (SS0) and secondary (SS1) USB instances. This ensures robust USB functionality regardless of the cable insertion orientation. BUG=b:448107633 TEST=Verify USB-C works in both polarities on Google/Quenbi. Without this CL - USB3 key doesn't work in inverted polarity. With this CL - USB3 key works in both polarities. Change-Id: I1855a12e32a76032d4c1b57770143c152b806008 Signed-off-by: Kapil Porwal <kapilporwal@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/89468 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Subrata Banik <subratabanik@google.com>
This commit is contained in:
parent
f1708cf21a
commit
7ebcd6763f
4 changed files with 24 additions and 5 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue