diff options
-rw-r--r-- | drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 54 |
1 files changed, 30 insertions, 24 deletions
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 6baacdf3a4cb..b44c029ef23f 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -19,6 +19,7 @@ #include <linux/regulator/consumer.h> #include <linux/reset.h> #include <linux/slab.h> +#include <linux/usb/typec.h> #include <dt-bindings/phy/phy-qcom-qmp.h> @@ -63,6 +64,10 @@ /* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */ #define CLAMP_EN BIT(0) /* enables i/o clamp_n */ +/* QPHY_V3_DP_COM_TYPEC_CTRL register bits */ +#define SW_PORTSELECT_VAL BIT(0) +#define SW_PORTSELECT_MUX BIT(1) + #define PHY_INIT_COMPLETE_TIMEOUT 10000 struct qmp_phy_init_tbl { @@ -1323,6 +1328,8 @@ struct qmp_combo { struct clk_fixed_rate pipe_clk_fixed; struct clk_hw dp_link_hw; struct clk_hw dp_pixel_hw; + + enum typec_orientation orientation; }; static void qmp_v3_dp_aux_init(struct qmp_combo *qmp); @@ -1954,30 +1961,24 @@ static void qmp_v3_configure_dp_tx(struct qmp_combo *qmp) static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp) { + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); + const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; u32 val; - bool reverse = false; val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN; - /* - * TODO: Assume orientation is CC1 for now and two lanes, need to - * use type-c connector to understand orientation and lanes. - * - * Otherwise val changes to be like below if this code understood - * the orientation of the type-c cable. - * - * if (lane_cnt == 4 || orientation == ORIENTATION_CC2) - * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; - * if (lane_cnt == 4 || orientation == ORIENTATION_CC1) - * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; - * if (orientation == ORIENTATION_CC2) - * writel(0x4c, qmp->dp_dp_phy + QSERDES_V3_DP_PHY_MODE); - */ - val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; + if (dp_opts->lanes == 4 || reverse) + val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; + if (dp_opts->lanes == 4 || !reverse) + val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; + writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL); - writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE); + if (reverse) + writel(0x4c, qmp->pcs + QSERDES_DP_PHY_MODE); + else + writel(0x5c, qmp->pcs + QSERDES_DP_PHY_MODE); return reverse; } @@ -2233,9 +2234,9 @@ static int qmp_v456_configure_dp_phy(struct qmp_combo *qmp, static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp) { + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; u32 bias0_en, drvr0_en, bias1_en, drvr1_en; - bool reverse = false; u32 status; int ret; @@ -2297,9 +2298,9 @@ static int qmp_v4_configure_dp_phy(struct qmp_combo *qmp) static int qmp_v5_configure_dp_phy(struct qmp_combo *qmp) { + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; u32 bias0_en, drvr0_en, bias1_en, drvr1_en; - bool reverse = false; u32 status; int ret; @@ -2356,9 +2357,9 @@ static int qmp_v5_configure_dp_phy(struct qmp_combo *qmp) static int qmp_v6_configure_dp_phy(struct qmp_combo *qmp) { + bool reverse = (qmp->orientation == TYPEC_ORIENTATION_REVERSE); const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts; u32 bias0_en, drvr0_en, bias1_en, drvr1_en; - bool reverse = false; u32 status; int ret; @@ -2471,6 +2472,7 @@ static int qmp_combo_com_init(struct qmp_combo *qmp) const struct qmp_phy_cfg *cfg = qmp->cfg; void __iomem *com = qmp->com; int ret; + u32 val; if (qmp->init_count++) return 0; @@ -2504,10 +2506,12 @@ static int qmp_combo_com_init(struct qmp_combo *qmp) SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); - /* Default type-c orientation, i.e CC1 */ - qphy_setbits(com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02); - - qphy_setbits(com, QPHY_V3_DP_COM_PHY_MODE_CTRL, USB3_MODE | DP_MODE); + /* Use software based port select and switch on typec orientation */ + val = SW_PORTSELECT_MUX; + if (qmp->orientation == TYPEC_ORIENTATION_REVERSE) + val |= SW_PORTSELECT_VAL; + writel(val, com + QPHY_V3_DP_COM_TYPEC_CTRL); + writel(USB3_MODE | DP_MODE, com + QPHY_V3_DP_COM_PHY_MODE_CTRL); /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ qphy_clrbits(com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, @@ -3379,6 +3383,8 @@ static int qmp_combo_probe(struct platform_device *pdev) qmp->dev = dev; + qmp->orientation = TYPEC_ORIENTATION_NORMAL; + qmp->cfg = of_device_get_match_data(dev); if (!qmp->cfg) return -EINVAL; |