mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 22:52:35 +02:00
phy/rockchip: typec: improved handling of typec_dp_phy_config()
Change-Id: I61ca43ffe7fe85e041fb3ed66ba1d59f515770d9 Signed-off-by: Wyon Bi <bivvy.bi@rock-chips.com>
This commit is contained in:
parent
08aea10ffd
commit
363e47c6aa
|
|
@ -295,13 +295,37 @@
|
|||
#define RX_DIAG_SIGDET_TUNE(n) ((0x81dc | ((n) << 9)) << 2)
|
||||
#define RX_DIAG_SC2C_DELAY (0x81e1 << 2)
|
||||
|
||||
#define PMA_LANE_CFG (0xc000 << 2)
|
||||
#define PHY_PMA_LANE_CFG (0xc000 << 2)
|
||||
#define PMA_LANE3_DP_LANE_SEL(x) (((x) & 0x3) << 14)
|
||||
#define PMA_LANE3_INTERFACE_SEL(x) (((x) & 0x1) << 12)
|
||||
#define PMA_LANE2_DP_LANE_SEL(x) (((x) & 0x3) << 10)
|
||||
#define PMA_LANE2_INTERFACE_SEL(x) (((x) & 0x1) << 8)
|
||||
#define PMA_LANE1_DP_LANE_SEL(x) (((x) & 0x3) << 6)
|
||||
#define PMA_LANE1_INTERFACE_SEL(x) (((x) & 0x1) << 4)
|
||||
#define PMA_LANE0_DP_LANE_SEL(x) (((x) & 0x3) << 2)
|
||||
#define PMA_LANE0_INTERFACE_SEL(x) (((x) & 0x1) << 0)
|
||||
#define PIPE_CMN_CTRL1 (0xc001 << 2)
|
||||
#define PIPE_CMN_CTRL2 (0xc002 << 2)
|
||||
#define PIPE_COM_LOCK_CFG1 (0xc003 << 2)
|
||||
#define PIPE_COM_LOCK_CFG2 (0xc004 << 2)
|
||||
#define PIPE_RCV_DET_INH (0xc005 << 2)
|
||||
#define DP_MODE_CTL (0xc008 << 2)
|
||||
#define PHY_DP_MODE_CTL (0xc008 << 2)
|
||||
#define PHY_DP_LANE_DISABLE GENMASK(15, 12)
|
||||
#define PHY_DP_LANE_3_DISABLE BIT(15)
|
||||
#define PHY_DP_LANE_2_DISABLE BIT(14)
|
||||
#define PHY_DP_LANE_1_DISABLE BIT(13)
|
||||
#define PHY_DP_LANE_0_DISABLE BIT(12)
|
||||
#define PHY_DP_POWER_STATE_ACK_MASK GENMASK(7, 4)
|
||||
#define PHY_DP_POWER_STATE_ACK_SHIFT 4
|
||||
#define PHY_DP_POWER_STATE_MASK GENMASK(3, 0)
|
||||
#define PHY_DP_CLK_CTL (0xc009 << 2)
|
||||
#define DP_PLL_CLOCK_ENABLE_ACK BIT(3)
|
||||
#define DP_PLL_CLOCK_ENABLE_MASK BIT(2)
|
||||
#define DP_PLL_CLOCK_DISABLE 0
|
||||
#define DP_PLL_READY BIT(1)
|
||||
#define DP_PLL_ENABLE_MASK BIT(0)
|
||||
#define DP_PLL_ENABLE BIT(0)
|
||||
#define DP_PLL_DISABLE 0
|
||||
#define DP_CLK_CTL (0xc009 << 2)
|
||||
#define STS (0xc00F << 2)
|
||||
#define PHY_ISO_CMN_CTRL (0xc010 << 2)
|
||||
|
|
@ -468,6 +492,283 @@ static const struct phy_config tcphy_default_config[3][4] = {
|
|||
{ .swing = 0, .pe = 0 } },
|
||||
};
|
||||
|
||||
enum phy_dp_power_state {
|
||||
PHY_DP_POWER_STATE_DISABLED = -1,
|
||||
PHY_DP_POWER_STATE_A0,
|
||||
PHY_DP_POWER_STATE_A1,
|
||||
PHY_DP_POWER_STATE_A2,
|
||||
PHY_DP_POWER_STATE_A3,
|
||||
};
|
||||
|
||||
static int tcphy_dp_set_power_state(struct rockchip_typec_phy *tcphy,
|
||||
enum phy_dp_power_state state)
|
||||
{
|
||||
u32 ack, reg, sts = BIT(state);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Power state changes must not be requested until after the cmn_ready
|
||||
* signal has gone active.
|
||||
*/
|
||||
reg = readl(tcphy->base + PMA_CMN_CTRL1);
|
||||
if (!(reg & CMN_READY)) {
|
||||
dev_err(tcphy->dev, "cmn_ready in the inactive state\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
reg = readl(tcphy->base + PHY_DP_MODE_CTL);
|
||||
reg &= ~PHY_DP_POWER_STATE_MASK;
|
||||
reg |= sts;
|
||||
writel(reg, tcphy->base + PHY_DP_MODE_CTL);
|
||||
|
||||
ret = readl_poll_timeout(tcphy->base + PHY_DP_MODE_CTL,
|
||||
ack, (((ack & PHY_DP_POWER_STATE_ACK_MASK) >>
|
||||
PHY_DP_POWER_STATE_ACK_SHIFT) == sts), 10,
|
||||
PHY_MODE_SET_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
dev_err(tcphy->dev, "failed to enter power state %d\n", state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum {
|
||||
PHY_DP_LANE_0,
|
||||
PHY_DP_LANE_1,
|
||||
PHY_DP_LANE_2,
|
||||
PHY_DP_LANE_3,
|
||||
};
|
||||
|
||||
enum {
|
||||
PMA_IF_PIPE_PCS,
|
||||
PMA_IF_PHY_DP,
|
||||
};
|
||||
|
||||
/*
|
||||
* For the TypeC PHY, the 4 lanes are mapping to the USB TypeC receptacle pins
|
||||
* as follows:
|
||||
* -------------------------------------------------------------------
|
||||
* PHY Lanes/Module Pins TypeC Receptacle Pins
|
||||
* -------------------------------------------------------------------
|
||||
* Lane0 (tx_p/m_ln_0) TX1+/TX1- (pins A2/A3)
|
||||
* Lane1 (tx_rx_p/m_ln_1) RX1+/RX1- (pins B11/B10)
|
||||
* Lane2 (tx_rx_p/m_ln_2) RX2+/RX2- (pins A11/A10)
|
||||
* Lane3 (tx_p/m_ln_3) TX2+/TX2- (pins B2/B3)
|
||||
* -------------------------------------------------------------------
|
||||
*
|
||||
* USB and DP lanes mapping to TypeC PHY lanes for each of pin assignment
|
||||
* options (normal connector orientation) described in the VESA DisplayPort
|
||||
* Alt Mode on USB TypeC Standard as follows:
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
* PHY Lanes A B C D E F
|
||||
* ----------------------------------------------------------------------
|
||||
* 0 ML1 SSTX ML2 SSTX ML2 SSTX
|
||||
* 1 ML3 SSRX ML3 SSRX ML3 SSRX
|
||||
* 2 ML2 ML1 ML0 ML0 ML0 ML0
|
||||
* 3 ML0 ML0 ML1 ML1 ML1 ML1
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
static void tcphy_set_lane_mapping(struct rockchip_typec_phy *tcphy, u8 mode)
|
||||
{
|
||||
/*
|
||||
* The PHY_PMA_LANE_CFG register is used to select whether a PMA lane
|
||||
* is mapped for USB or PHY DP. The PHY_PMA_LANE_CFG register is
|
||||
* configured based on a normal connector orientation. Logic in the
|
||||
* PHY automatically handles the flipped connector case based on the
|
||||
* setting of orientation of TypeC PHY.
|
||||
*/
|
||||
if (mode == MODE_DFP_DP) {
|
||||
/* This maps to VESA DP Alt Mode pin assignments C and E. */
|
||||
writel(PMA_LANE3_DP_LANE_SEL(PHY_DP_LANE_1) |
|
||||
PMA_LANE3_INTERFACE_SEL(PMA_IF_PHY_DP) |
|
||||
PMA_LANE2_DP_LANE_SEL(PHY_DP_LANE_0) |
|
||||
PMA_LANE2_INTERFACE_SEL(PMA_IF_PHY_DP) |
|
||||
PMA_LANE1_DP_LANE_SEL(PHY_DP_LANE_3) |
|
||||
PMA_LANE1_INTERFACE_SEL(PMA_IF_PHY_DP) |
|
||||
PMA_LANE0_DP_LANE_SEL(PHY_DP_LANE_2) |
|
||||
PMA_LANE0_INTERFACE_SEL(PMA_IF_PHY_DP),
|
||||
tcphy->base + PHY_PMA_LANE_CFG);
|
||||
} else {
|
||||
/* This maps to VESA DP Alt Mode pin assignments D and F. */
|
||||
writel(PMA_LANE3_DP_LANE_SEL(PHY_DP_LANE_1) |
|
||||
PMA_LANE3_INTERFACE_SEL(PMA_IF_PHY_DP) |
|
||||
PMA_LANE2_DP_LANE_SEL(PHY_DP_LANE_0) |
|
||||
PMA_LANE2_INTERFACE_SEL(PMA_IF_PHY_DP) |
|
||||
PMA_LANE1_INTERFACE_SEL(PMA_IF_PIPE_PCS) |
|
||||
PMA_LANE0_INTERFACE_SEL(PMA_IF_PIPE_PCS),
|
||||
tcphy->base + PHY_PMA_LANE_CFG);
|
||||
}
|
||||
}
|
||||
|
||||
static int tcphy_dp_set_lane_count(struct rockchip_typec_phy *tcphy,
|
||||
u8 lane_count)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* In cases where fewer than the configured number of DP lanes are
|
||||
* being used. PHY_DP_MODE_CTL[15:12] must be set to disable and
|
||||
* power-down the unused PHY DP lanes (and their mapped PMA lanes).
|
||||
* Set the bit ([15:12]) associated with each DP PHY lane(s) to be
|
||||
* disabled.
|
||||
*/
|
||||
reg = readl(tcphy->base + PHY_DP_MODE_CTL);
|
||||
reg |= PHY_DP_LANE_DISABLE;
|
||||
|
||||
switch (lane_count) {
|
||||
case 4:
|
||||
reg &= ~(PHY_DP_LANE_3_DISABLE | PHY_DP_LANE_2_DISABLE |
|
||||
PHY_DP_LANE_1_DISABLE | PHY_DP_LANE_0_DISABLE);
|
||||
break;
|
||||
case 2:
|
||||
reg &= ~(PHY_DP_LANE_1_DISABLE | PHY_DP_LANE_0_DISABLE);
|
||||
break;
|
||||
case 1:
|
||||
reg &= ~PHY_DP_LANE_0_DISABLE;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
writel(reg, tcphy->base + PHY_DP_MODE_CTL);
|
||||
|
||||
tcphy->dp.lane_count = lane_count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tcphy_dp_set_link_rate(struct rockchip_typec_phy *tcphy,
|
||||
int link_rate)
|
||||
{
|
||||
const struct phy_reg *phy_cfg;
|
||||
u32 cmn_diag_hsclk_sel, phy_dp_clk_ctl, reg;
|
||||
u32 i, cfg_size;
|
||||
int ret;
|
||||
|
||||
/* Place the PHY lanes in the A3 power state. */
|
||||
ret = tcphy_dp_set_power_state(tcphy, PHY_DP_POWER_STATE_A3);
|
||||
if (ret) {
|
||||
dev_err(tcphy->dev, "failed to enter A3 state: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Gate the PLL clocks from PMA */
|
||||
reg = readl(tcphy->base + PHY_DP_CLK_CTL);
|
||||
reg &= ~DP_PLL_CLOCK_ENABLE_MASK;
|
||||
reg |= DP_PLL_CLOCK_DISABLE;
|
||||
writel(reg, tcphy->base + PHY_DP_CLK_CTL);
|
||||
|
||||
ret = readl_poll_timeout(tcphy->base + PHY_DP_CLK_CTL, reg,
|
||||
!(reg & DP_PLL_CLOCK_ENABLE_ACK),
|
||||
10, PHY_MODE_SET_TIMEOUT);
|
||||
if (ret) {
|
||||
dev_err(tcphy->dev, "wait DP PLL clock disabled timeout\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Disable the PLL */
|
||||
reg = readl(tcphy->base + PHY_DP_CLK_CTL);
|
||||
reg &= ~DP_PLL_ENABLE_MASK;
|
||||
reg |= DP_PLL_DISABLE;
|
||||
writel(reg, tcphy->base + PHY_DP_CLK_CTL);
|
||||
|
||||
ret = readl_poll_timeout(tcphy->base + PHY_DP_CLK_CTL, reg,
|
||||
!(reg & DP_PLL_READY),
|
||||
10, PHY_MODE_SET_TIMEOUT);
|
||||
if (ret) {
|
||||
dev_err(tcphy->dev, "wait DP PLL not ready timeout\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Re-configure PHY registers for the new data rate */
|
||||
cmn_diag_hsclk_sel = readl(tcphy->base + CMN_DIAG_HSCLK_SEL);
|
||||
cmn_diag_hsclk_sel &= ~(GENMASK(5, 4) | GENMASK(1, 0));
|
||||
|
||||
phy_dp_clk_ctl = readl(tcphy->base + PHY_DP_CLK_CTL);
|
||||
phy_dp_clk_ctl &= ~(GENMASK(15, 12) | GENMASK(11, 8));
|
||||
|
||||
switch (link_rate) {
|
||||
case 162000:
|
||||
cmn_diag_hsclk_sel |= (3 << 4) | (0 << 0);
|
||||
phy_dp_clk_ctl |= (2 << 12) | (4 << 8);
|
||||
|
||||
phy_cfg = dp_pll_rbr_cfg;
|
||||
cfg_size = ARRAY_SIZE(dp_pll_rbr_cfg);
|
||||
break;
|
||||
case 270000:
|
||||
cmn_diag_hsclk_sel |= (3 << 4) | (0 << 0);
|
||||
phy_dp_clk_ctl |= (2 << 12) | (4 << 8);
|
||||
|
||||
phy_cfg = dp_pll_hbr_cfg;
|
||||
cfg_size = ARRAY_SIZE(dp_pll_hbr_cfg);
|
||||
break;
|
||||
case 540000:
|
||||
cmn_diag_hsclk_sel |= (2 << 4) | (0 << 0);
|
||||
phy_dp_clk_ctl |= (1 << 12) | (2 << 8);
|
||||
|
||||
phy_cfg = dp_pll_hbr2_cfg;
|
||||
cfg_size = ARRAY_SIZE(dp_pll_hbr2_cfg);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
writel(cmn_diag_hsclk_sel, tcphy->base + CMN_DIAG_HSCLK_SEL);
|
||||
writel(phy_dp_clk_ctl, tcphy->base + PHY_DP_CLK_CTL);
|
||||
|
||||
/* load the configuration of PLL1 */
|
||||
for (i = 0; i < cfg_size; i++)
|
||||
writel(phy_cfg[i].value, tcphy->base + phy_cfg[i].addr);
|
||||
|
||||
/* Enable the PLL */
|
||||
reg = readl(tcphy->base + PHY_DP_CLK_CTL);
|
||||
reg &= ~DP_PLL_ENABLE_MASK;
|
||||
reg |= DP_PLL_ENABLE;
|
||||
writel(reg, tcphy->base + PHY_DP_CLK_CTL);
|
||||
|
||||
ret = readl_poll_timeout(tcphy->base + PHY_DP_CLK_CTL, reg,
|
||||
reg & DP_PLL_READY,
|
||||
10, PHY_MODE_SET_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
dev_err(tcphy->dev, "wait DP PLL ready timeout\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable PMA PLL clocks */
|
||||
reg = readl(tcphy->base + PHY_DP_CLK_CTL);
|
||||
reg &= ~DP_PLL_CLOCK_ENABLE_MASK;
|
||||
reg |= DP_PLL_CLOCK_ENABLE;
|
||||
writel(reg, tcphy->base + PHY_DP_CLK_CTL);
|
||||
|
||||
ret = readl_poll_timeout(tcphy->base + PHY_DP_CLK_CTL, reg,
|
||||
reg & DP_PLL_CLOCK_ENABLE_ACK,
|
||||
10, PHY_MODE_SET_TIMEOUT);
|
||||
if (ret) {
|
||||
dev_err(tcphy->dev, "wait DP PLL clock enabled timeout\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The PMA must go through the A2 power state upon a data rate change */
|
||||
ret = tcphy_dp_set_power_state(tcphy, PHY_DP_POWER_STATE_A2);
|
||||
if (ret) {
|
||||
dev_err(tcphy->dev, "failed to enter A2 state: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* change the PHY power state to A0 */
|
||||
ret = tcphy_dp_set_power_state(tcphy, PHY_DP_POWER_STATE_A0);
|
||||
if (ret) {
|
||||
dev_err(tcphy->dev, "failed to enter A0 state: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tcphy->dp.link_rate = link_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tcphy_cfg_24m(struct rockchip_typec_phy *tcphy)
|
||||
{
|
||||
u32 i, rdata;
|
||||
|
|
@ -535,12 +836,14 @@ static void tcphy_cfg_dp_pll(struct rockchip_typec_phy *tcphy, int link_rate)
|
|||
}
|
||||
|
||||
clk_ctrl |= DP_PLL_CLOCK_ENABLE | DP_PLL_ENABLE;
|
||||
writel(clk_ctrl, tcphy->base + DP_CLK_CTL);
|
||||
writel(clk_ctrl, tcphy->base + PHY_DP_CLK_CTL);
|
||||
writel(hsclk_sel, tcphy->base + CMN_DIAG_HSCLK_SEL);
|
||||
|
||||
/* load the configuration of PLL1 */
|
||||
for (i = 0; i < cfg_size; i++)
|
||||
writel(phy_cfg[i].value, tcphy->base + phy_cfg[i].addr);
|
||||
|
||||
tcphy->dp.link_rate = link_rate;
|
||||
}
|
||||
|
||||
static void tcphy_tx_usb3_cfg_lane(struct rockchip_typec_phy *tcphy, u32 lane)
|
||||
|
|
@ -792,13 +1095,12 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
|
|||
tcphy_dp_aux_set_flip(tcphy);
|
||||
|
||||
tcphy_cfg_24m(tcphy);
|
||||
tcphy_set_lane_mapping(tcphy, mode);
|
||||
|
||||
if (mode == MODE_DFP_DP) {
|
||||
tcphy_cfg_dp_pll(tcphy, DP_DEFAULT_RATE);
|
||||
for (i = 0; i < 4; i++)
|
||||
tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, i);
|
||||
|
||||
writel(PIN_ASSIGN_C_E, tcphy->base + PMA_LANE_CFG);
|
||||
} else {
|
||||
tcphy_cfg_usb3_pll(tcphy);
|
||||
tcphy_cfg_dp_pll(tcphy, DP_DEFAULT_RATE);
|
||||
|
|
@ -813,14 +1115,12 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
|
|||
tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 2);
|
||||
tcphy_dp_cfg_lane(tcphy, DP_DEFAULT_RATE, 0, 0, 3);
|
||||
}
|
||||
|
||||
writel(PIN_ASSIGN_D_F, tcphy->base + PMA_LANE_CFG);
|
||||
}
|
||||
|
||||
val = readl(tcphy->base + DP_MODE_CTL);
|
||||
val = readl(tcphy->base + PHY_DP_MODE_CTL);
|
||||
val &= ~DP_MODE_MASK;
|
||||
val |= DP_MODE_ENTER_A2 | DP_LINK_RESET_DEASSERTED;
|
||||
writel(val, tcphy->base + DP_MODE_CTL);
|
||||
writel(val, tcphy->base + PHY_DP_MODE_CTL);
|
||||
|
||||
reset_control_deassert(tcphy->uphy_rst);
|
||||
|
||||
|
|
@ -1055,7 +1355,7 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
|
|||
|
||||
property_enable(tcphy, &cfg->uphy_dp_sel, 1);
|
||||
|
||||
ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
|
||||
ret = readx_poll_timeout(readl, tcphy->base + PHY_DP_MODE_CTL,
|
||||
val, val & DP_MODE_A2_ACK, 1000,
|
||||
PHY_MODE_SET_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
|
|
@ -1066,19 +1366,9 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
|
|||
tcphy_dp_aux_calibration(tcphy);
|
||||
|
||||
/* enter A0 mode */
|
||||
val = readl(tcphy->base + DP_MODE_CTL);
|
||||
val &= ~DP_MODE_MASK;
|
||||
val |= DP_MODE_ENTER_A0;
|
||||
writel(val, tcphy->base + DP_MODE_CTL);
|
||||
|
||||
ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL,
|
||||
val, val & DP_MODE_A0_ACK, 1000,
|
||||
PHY_MODE_SET_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
val &= ~DP_MODE_MASK;
|
||||
val |= DP_MODE_ENTER_A2;
|
||||
writel(val, tcphy->base + DP_MODE_CTL);
|
||||
dev_err(tcphy->dev, "failed to wait TCPHY enter A0\n");
|
||||
ret = tcphy_dp_set_power_state(tcphy, PHY_DP_POWER_STATE_A0);
|
||||
if (ret) {
|
||||
dev_err(tcphy->dev, "failed to enter A0 power state\n");
|
||||
goto power_on_finish;
|
||||
}
|
||||
|
||||
|
|
@ -1095,7 +1385,7 @@ static int rockchip_dp_phy_power_on(struct phy *phy)
|
|||
static int rockchip_dp_phy_power_off(struct phy *phy)
|
||||
{
|
||||
struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&tcphy->lock);
|
||||
|
||||
|
|
@ -1104,10 +1394,11 @@ static int rockchip_dp_phy_power_off(struct phy *phy)
|
|||
|
||||
tcphy->mode &= ~MODE_DFP_DP;
|
||||
|
||||
val = readl(tcphy->base + DP_MODE_CTL);
|
||||
val &= ~DP_MODE_MASK;
|
||||
val |= DP_MODE_ENTER_A2;
|
||||
writel(val, tcphy->base + DP_MODE_CTL);
|
||||
ret = tcphy_dp_set_power_state(tcphy, PHY_DP_POWER_STATE_A2);
|
||||
if (ret) {
|
||||
dev_err(tcphy->dev, "failed to enter A2 power state\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (tcphy->mode == MODE_DISCONNECT)
|
||||
tcphy_phy_deinit(tcphy);
|
||||
|
|
@ -1124,12 +1415,32 @@ static const struct phy_ops rockchip_dp_phy_ops = {
|
|||
};
|
||||
|
||||
static int typec_dp_phy_config(struct phy *phy, int link_rate,
|
||||
int lanes, u8 swing, u8 pre_emp)
|
||||
int lane_count, u8 swing, u8 pre_emp)
|
||||
{
|
||||
struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy);
|
||||
u8 i;
|
||||
int ret;
|
||||
|
||||
tcphy_cfg_dp_pll(tcphy, link_rate);
|
||||
dev_dbg(tcphy->dev, "link_rate=%d, lane_count=%d\n",
|
||||
link_rate, lane_count);
|
||||
dev_dbg(tcphy->dev, "voltage_swing=%d, pre_emphasis=%d\n",
|
||||
swing, pre_emp);
|
||||
|
||||
if (lane_count != tcphy->dp.lane_count) {
|
||||
ret = tcphy_dp_set_lane_count(tcphy, lane_count);
|
||||
if (ret) {
|
||||
dev_err(tcphy->dev, "failed to set lane count\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (link_rate != tcphy->dp.link_rate) {
|
||||
ret = tcphy_dp_set_link_rate(tcphy, link_rate);
|
||||
if (ret) {
|
||||
dev_err(tcphy->dev, "failed to set lane rate\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (tcphy->mode == MODE_DFP_DP) {
|
||||
for (i = 0; i < 4; i++)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ struct rockchip_typec_phy {
|
|||
bool flip;
|
||||
u8 mode;
|
||||
struct phy_config config[3][4];
|
||||
struct {
|
||||
int link_rate;
|
||||
u8 lane_count;
|
||||
} dp;
|
||||
int (*typec_phy_config)(struct phy *phy, int link_rate,
|
||||
int lanes, u8 swing, u8 pre_emp);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user