]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blobdiff - drivers/phy/rockchip/phy-rockchip-typec.c
Merge remote-tracking branches 'asoc/topic/ac97', 'asoc/topic/ac97-mfd', 'asoc/topic...
[mirror_ubuntu-focal-kernel.git] / drivers / phy / rockchip / phy-rockchip-typec.c
index 4d2c57f21d7682bb6b08f31a1dab0ba74ab0e4e2..a958c9bced019d2da7520977a26f5c10a81cdea4 100644 (file)
@@ -443,14 +443,34 @@ static inline int property_enable(struct rockchip_typec_phy *tcphy,
        return regmap_write(tcphy->grf_regs, reg->offset, val | mask);
 }
 
+static void tcphy_dp_aux_set_flip(struct rockchip_typec_phy *tcphy)
+{
+       u16 tx_ana_ctrl_reg_1;
+
+       /*
+        * Select the polarity of the xcvr:
+        * 1, Reverses the polarity (If TYPEC, Pulls ups aux_p and pull
+        * down aux_m)
+        * 0, Normal polarity (if TYPEC, pulls up aux_m and pulls down
+        * aux_p)
+        */
+       tx_ana_ctrl_reg_1 = readl(tcphy->base + TX_ANA_CTRL_REG_1);
+       if (!tcphy->flip)
+               tx_ana_ctrl_reg_1 |= BIT(12);
+       else
+               tx_ana_ctrl_reg_1 &= ~BIT(12);
+       writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
+}
+
 static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
 {
+       u16 tx_ana_ctrl_reg_1;
        u16 rdata, rdata2, val;
 
        /* disable txda_cal_latch_en for rewrite the calibration values */
-       rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
-       val = rdata & 0xdfff;
-       writel(val, tcphy->base + TX_ANA_CTRL_REG_1);
+       tx_ana_ctrl_reg_1 = readl(tcphy->base + TX_ANA_CTRL_REG_1);
+       tx_ana_ctrl_reg_1 &= ~BIT(13);
+       writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
 
        /*
         * read a resistor calibration code from CMN_TXPUCAL_CTRL[6:0] and
@@ -472,9 +492,8 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
         * Activate this signal for 1 clock cycle to sample new calibration
         * values.
         */
-       rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1);
-       val = rdata | 0x2000;
-       writel(val, tcphy->base + TX_ANA_CTRL_REG_1);
+       tx_ana_ctrl_reg_1 |= BIT(13);
+       writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
        usleep_range(150, 200);
 
        /* set TX Voltage Level and TX Deemphasis to 0 */
@@ -482,8 +501,10 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
        /* re-enable decap */
        writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2);
        writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2);
-       writel(0x2008, tcphy->base + TX_ANA_CTRL_REG_1);
-       writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1);
+       tx_ana_ctrl_reg_1 |= BIT(3);
+       writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
+       tx_ana_ctrl_reg_1 |= BIT(4);
+       writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
 
        writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
 
@@ -494,8 +515,10 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
        writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4);
 
        /* re-enables Bandgap reference for LDO */
-       writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1);
-       writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1);
+       tx_ana_ctrl_reg_1 |= BIT(7);
+       writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
+       tx_ana_ctrl_reg_1 |= BIT(8);
+       writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
 
        /*
         * re-enables the transmitter pre-driver, driver data selection MUX,
@@ -505,27 +528,26 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
        writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2);
 
        /*
-        * BIT 12: Controls auxda_polarity, which selects the polarity of the
-        * xcvr:
-        * 1, Reverses the polarity (If TYPEC, Pulls ups aux_p and pull
-        * down aux_m)
-        * 0, Normal polarity (if TYPE_C, pulls up aux_m and pulls down
-        * aux_p)
+        * Do some magic undocumented stuff, some of which appears to
+        * undo the "re-enables Bandgap reference for LDO" above.
         */
-       val = 0xa078;
-       if (!tcphy->flip)
-               val |= BIT(12);
-       writel(val, tcphy->base + TX_ANA_CTRL_REG_1);
+       tx_ana_ctrl_reg_1 |=  BIT(15);
+       tx_ana_ctrl_reg_1 &= ~BIT(8);
+       tx_ana_ctrl_reg_1 &= ~BIT(7);
+       tx_ana_ctrl_reg_1 |=  BIT(6);
+       tx_ana_ctrl_reg_1 |=  BIT(5);
+       writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
 
        writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
        writel(0, tcphy->base + TX_ANA_CTRL_REG_4);
        writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
 
        /*
-        * Controls low_power_swing_en, set the voltage swing of the driver
-        * to 400mv. The values below are peak to peak (differential) values.
+        * Controls low_power_swing_en, don't set the voltage swing of the
+        * driver to 400mv. The values below are peak to peak (differential)
+        * values.
         */
-       writel(4, tcphy->base + TXDA_COEFF_CALC_CTRL);
+       writel(0, tcphy->base + TXDA_COEFF_CALC_CTRL);
        writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA);
 
        /* Controls tx_high_z_tm_en */
@@ -555,6 +577,7 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
        reset_control_deassert(tcphy->tcphy_rst);
 
        property_enable(tcphy, &cfg->typec_conn_dir, tcphy->flip);
+       tcphy_dp_aux_set_flip(tcphy);
 
        tcphy_cfg_24m(tcphy);
 
@@ -685,8 +708,11 @@ static int rockchip_usb3_phy_power_on(struct phy *phy)
        if (tcphy->mode == new_mode)
                goto unlock_ret;
 
-       if (tcphy->mode == MODE_DISCONNECT)
-               tcphy_phy_init(tcphy, new_mode);
+       if (tcphy->mode == MODE_DISCONNECT) {
+               ret = tcphy_phy_init(tcphy, new_mode);
+               if (ret)
+                       goto unlock_ret;
+       }
 
        /* wait TCPHY for pipe ready */
        for (timeout = 0; timeout < 100; timeout++) {
@@ -760,10 +786,12 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
         */
        if (new_mode == MODE_DFP_DP && tcphy->mode != MODE_DISCONNECT) {
                tcphy_phy_deinit(tcphy);
-               tcphy_phy_init(tcphy, new_mode);
+               ret = tcphy_phy_init(tcphy, new_mode);
        } else if (tcphy->mode == MODE_DISCONNECT) {
-               tcphy_phy_init(tcphy, new_mode);
+               ret = tcphy_phy_init(tcphy, new_mode);
        }
+       if (ret)
+               goto unlock_ret;
 
        ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
                                 val, val & DP_MODE_A2, 1000,