[PATCH 2/4] phy: cadence-torrent: Prepare driver for multilink DP support

Vinod Koul vkoul at kernel.org
Tue Feb 22 05:03:08 PST 2022


On 27-01-22, 15:29, Swapnil Jakhade wrote:
> This patch prepares driver for multilink DP support as well as for
> multiprotocol PHY configurations involving DP as one of the required
> protocols. This needs changes in functions configuring default single
> link DP with master lane 0 to support non-zero master lane values and
> associated PLL configurations.
> 
> Signed-off-by: Swapnil Jakhade <sjakhade at cadence.com>
> ---
>  drivers/phy/cadence/phy-cadence-torrent.c | 315 ++++++++++++----------
>  1 file changed, 177 insertions(+), 138 deletions(-)
> 
> diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c
> index 0e2839a6c65d..72adc3a27367 100644
> --- a/drivers/phy/cadence/phy-cadence-torrent.c
> +++ b/drivers/phy/cadence/phy-cadence-torrent.c
> @@ -69,16 +69,11 @@
>   */
>  #define PHY_AUX_CTRL			0x04
>  #define PHY_RESET			0x20
> -#define PMA_TX_ELEC_IDLE_MASK		0xF0U
>  #define PMA_TX_ELEC_IDLE_SHIFT		4
> -#define PHY_L00_RESET_N_MASK		0x01U
>  #define PHY_PMA_XCVR_PLLCLK_EN		0x24
>  #define PHY_PMA_XCVR_PLLCLK_EN_ACK	0x28
>  #define PHY_PMA_XCVR_POWER_STATE_REQ	0x2c
> -#define PHY_POWER_STATE_LN_0	0x0000
> -#define PHY_POWER_STATE_LN_1	0x0008
> -#define PHY_POWER_STATE_LN_2	0x0010
> -#define PHY_POWER_STATE_LN_3	0x0018
> +#define PHY_POWER_STATE_LN(ln)		((ln) * 8)
>  #define PMA_XCVR_POWER_STATE_REQ_LN_MASK	0x3FU
>  #define PHY_PMA_XCVR_POWER_STATE_ACK	0x30
>  #define PHY_PMA_CMN_READY		0x34
> @@ -1010,43 +1005,37 @@ static int cdns_torrent_dp_get_pll(struct cdns_torrent_phy *cdns_phy,
>   * Enable or disable PLL for selected lanes.
>   */
>  static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy,
> +				      struct cdns_torrent_inst *inst,
>  				      struct phy_configure_opts_dp *dp,
>  				      bool enable)
>  {
> -	u32 rd_val;
> -	u32 ret;
>  	struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
> +	u32 rd_val, i, pll_ack_val;
> +	int ret;
>  
>  	/*
>  	 * Used to determine, which bits to check for or enable in
>  	 * PHY_PMA_XCVR_PLLCLK_EN register.
>  	 */
> -	u32 pll_bits;
> +	u32 pll_bits = 0;
>  	/* Used to enable or disable lanes. */
>  	u32 pll_val;
> +	u32 clane = 0;

clane is zero!

>  
> -	/* Select values of registers and mask, depending on enabled lane
> -	 * count.
> -	 */
> -	switch (dp->lanes) {
> -	/* lane 0 */
> -	case (1):
> -		pll_bits = 0x00000001;
> -		break;
> -	/* lanes 0-1 */
> -	case (2):
> -		pll_bits = 0x00000003;
> -		break;
> -	/* lanes 0-3, all */
> -	default:
> -		pll_bits = 0x0000000F;
> -		break;
> -	}
> +	/* Select values of registers and mask, depending on enabled lane count. */
> +	pll_val = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN);
>  
> -	if (enable)
> -		pll_val = pll_bits;
> -	else
> -		pll_val = 0x00000000;
> +	if (enable) {
> +		for (i = 0; i < dp->lanes; i++)
> +			pll_bits |= (0x01U << (clane + i));

so why clane here?
and sound like you may want to use set_bit for all the lanes?

> +		pll_val |= pll_bits;
> +		pll_ack_val = pll_bits;
> +	} else {
> +		for (i = 0; i < inst->num_lanes; i++)
> +			pll_bits |= (0x01U << (clane + i));
> +		pll_val &= (~pll_bits);
> +		pll_ack_val = 0;
> +	}
>  
>  	cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, pll_val);
>  
> @@ -1054,23 +1043,26 @@ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy,
>  	ret = regmap_read_poll_timeout(regmap,
>  				       PHY_PMA_XCVR_PLLCLK_EN_ACK,
>  				       rd_val,
> -				       (rd_val & pll_bits) == pll_val,
> +				       (rd_val & pll_bits) == pll_ack_val,
>  				       0, POLL_TIMEOUT_US);
>  	ndelay(100);
>  	return ret;
>  }
>  
>  static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
> +					   struct cdns_torrent_inst *inst,
>  					   u32 num_lanes,
>  					   enum phy_powerstate powerstate)
>  {
>  	/* Register value for power state for a single byte. */
>  	u32 value_part;
> -	u32 value;
> -	u32 mask;
> +	u32 value = 0;
> +	u32 mask = 0;
>  	u32 read_val;
> -	u32 ret;
> +	int ret;
> +	u32 i;
>  	struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
> +	u32 clane = 0;
>  
>  	switch (powerstate) {
>  	case (POWERSTATE_A0):
> @@ -1085,29 +1077,11 @@ static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
>  		break;
>  	}
>  
> -	/* Select values of registers and mask, depending on enabled
> -	 * lane count.
> -	 */
> -	switch (num_lanes) {
> -	/* lane 0 */
> -	case (1):
> -		value = value_part;
> -		mask = 0x0000003FU;
> -		break;
> -	/* lanes 0-1 */
> -	case (2):
> -		value = (value_part
> -			 | (value_part << 8));
> -		mask = 0x00003F3FU;
> -		break;
> -	/* lanes 0-3, all */
> -	default:
> -		value = (value_part
> -			 | (value_part << 8)
> -			 | (value_part << 16)
> -			 | (value_part << 24));
> -		mask = 0x3F3F3F3FU;
> -		break;
> +	/* Select values of registers and mask, depending on enabled lane count. */
> +
> +	for (i = 0; i < num_lanes; i++) {
> +		value |= (value_part << PHY_POWER_STATE_LN(clane + i));
> +		mask |= (PMA_XCVR_POWER_STATE_REQ_LN_MASK << PHY_POWER_STATE_LN(clane + i));
>  	}
>  
>  	/* Set power state A<n>. */
> @@ -1122,18 +1096,20 @@ static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
>  	return ret;
>  }
>  
> -static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes)
> +static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy,
> +			       struct cdns_torrent_inst *inst, u32 num_lanes)
>  {
>  	unsigned int read_val;
>  	int ret;
>  	struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
> +	u32 clane = 0;
>  
>  	/*
>  	 * waiting for ACK of pma_xcvr_pllclk_en_ln_*, only for the
>  	 * master lane
>  	 */
>  	ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_PLLCLK_EN_ACK,
> -				       read_val, read_val & 1,
> +				       read_val, (read_val & (1 << clane)),

again clane seems to be always 0

>  				       0, POLL_TIMEOUT_US);
>  	if (ret == -ETIMEDOUT) {
>  		dev_err(cdns_phy->dev,
> @@ -1143,12 +1119,12 @@ static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes)
>  
>  	ndelay(100);
>  
> -	ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
> +	ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, num_lanes,
>  					      POWERSTATE_A2);
>  	if (ret)
>  		return ret;
>  
> -	ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
> +	ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, num_lanes,
>  					      POWERSTATE_A0);
>  
>  	return ret;
> @@ -1172,6 +1148,7 @@ static int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy)
>  }
>  
>  static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
> +					 struct cdns_torrent_inst *inst,
>  					 u32 rate, u32 num_lanes)
>  {
>  	unsigned int clk_sel_val = 0;
> @@ -1204,14 +1181,17 @@ static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
>  		break;
>  	}
>  
> -	cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
> -			       CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val);
> -	cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
> -			       CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val);
> +	if (cdns_phy->dp_pll & DP_PLL0)
> +		cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
> +				       CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val);
> +
> +	if (cdns_phy->dp_pll & DP_PLL1)
> +		cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
> +				       CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val);
>  
>  	/* PMA lane configuration to deal with multi-link operation */
>  	for (i = 0; i < num_lanes; i++)
> -		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[i],
> +		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + i],
>  				       XCVR_DIAG_HSCLK_DIV, hsclk_div_val);
>  }
>  
> @@ -1220,23 +1200,44 @@ static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
>   * set and PLL disable request was processed.
>   */
>  static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy,
> +					  struct cdns_torrent_inst *inst,
>  					  struct phy_configure_opts_dp *dp)
>  {
> -	u32 read_val, ret;
> +	u32 read_val, field_val;
> +	int ret;
>  
> -	/* Disable the cmn_pll0_en before re-programming the new data rate. */
> -	regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x0);
> +	/*
> +	 * Disable the associated PLL (cmn_pll0_en or cmn_pll1_en) before
> +	 * re-programming the new data rate.
> +	 */
> +	ret = regmap_field_read(cdns_phy->phy_pma_pll_raw_ctrl, &field_val);
> +	if (ret)
> +		return ret;
> +	field_val &= ~(cdns_phy->dp_pll);
> +	regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, field_val);
>  
>  	/*
>  	 * Wait for PLL ready de-assertion.
>  	 * For PLL0 - PHY_PMA_CMN_CTRL2[2] == 1
> +	 * For PLL1 - PHY_PMA_CMN_CTRL2[3] == 1
>  	 */
> -	ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
> -					     read_val,
> -					     ((read_val >> 2) & 0x01) != 0,
> -					     0, POLL_TIMEOUT_US);
> -	if (ret)
> -		return ret;
> +	if (cdns_phy->dp_pll & DP_PLL0) {
> +		ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
> +						     read_val,
> +						     ((read_val >> 2) & 0x01) != 0,
> +						     0, POLL_TIMEOUT_US);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	if ((cdns_phy->dp_pll & DP_PLL1) && cdns_phy->nsubnodes != 1) {
> +		ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
> +						     read_val,
> +						     ((read_val >> 3) & 0x01) != 0,
> +						     0, POLL_TIMEOUT_US);
> +		if (ret)
> +			return ret;
> +	}
>  	ndelay(200);
>  
>  	/* DP Rate Change - VCO Output settings. */
> @@ -1250,19 +1251,35 @@ static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy,
>  		/* PMA common configuration 100MHz */
>  		cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(cdns_phy, dp->link_rate, dp->ssc);
>  
> -	cdns_torrent_dp_pma_cmn_rate(cdns_phy, dp->link_rate, dp->lanes);
> +	cdns_torrent_dp_pma_cmn_rate(cdns_phy, inst, dp->link_rate, dp->lanes);
>  
> -	/* Enable the cmn_pll0_en. */
> -	regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x3);
> +	/* Enable the associated PLL (cmn_pll0_en or cmn_pll1_en) */
> +	ret = regmap_field_read(cdns_phy->phy_pma_pll_raw_ctrl, &field_val);
> +	if (ret)
> +		return ret;
> +	field_val |= cdns_phy->dp_pll;
> +	regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, field_val);
>  
>  	/*
>  	 * Wait for PLL ready assertion.
>  	 * For PLL0 - PHY_PMA_CMN_CTRL2[0] == 1
> +	 * For PLL1 - PHY_PMA_CMN_CTRL2[1] == 1
>  	 */
> -	ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
> -					     read_val,
> -					     (read_val & 0x01) != 0,
> -					     0, POLL_TIMEOUT_US);
> +	if (cdns_phy->dp_pll & DP_PLL0) {
> +		ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
> +						     read_val,
> +						     (read_val & 0x01) != 0,
> +						     0, POLL_TIMEOUT_US);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	if ((cdns_phy->dp_pll & DP_PLL1) && cdns_phy->nsubnodes != 1)
> +		ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
> +						     read_val,
> +						     ((read_val >> 1) & 0x01) != 0,
> +						     0, POLL_TIMEOUT_US);
> +
>  	return ret;
>  }
>  
> @@ -1330,6 +1347,7 @@ static int cdns_torrent_dp_verify_config(struct cdns_torrent_inst *inst,
>  
>  /* Set power state A0 and PLL clock enable to 0 on enabled lanes. */
>  static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy,
> +				       struct cdns_torrent_inst *inst,
>  				       u32 num_lanes)
>  {
>  	struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
> @@ -1337,27 +1355,13 @@ static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy,
>  					     PHY_PMA_XCVR_POWER_STATE_REQ);
>  	u32 pll_clk_en = cdns_torrent_dp_read(regmap,
>  					      PHY_PMA_XCVR_PLLCLK_EN);
> +	u32 i;
>  
> -	/* Lane 0 is always enabled. */
> -	pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
> -		       PHY_POWER_STATE_LN_0);
> -	pll_clk_en &= ~0x01U;
> +	for (i = 0; i < num_lanes; i++) {
> +		pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK
> +			     << PHY_POWER_STATE_LN(inst->mlane + i));
>  
> -	if (num_lanes > 1) {
> -		/* lane 1 */
> -		pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
> -			       PHY_POWER_STATE_LN_1);
> -		pll_clk_en &= ~(0x01U << 1);
> -	}
> -
> -	if (num_lanes > 2) {
> -		/* lanes 2 and 3 */
> -		pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
> -			       PHY_POWER_STATE_LN_2);
> -		pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
> -			       PHY_POWER_STATE_LN_3);
> -		pll_clk_en &= ~(0x01U << 2);
> -		pll_clk_en &= ~(0x01U << 3);
> +		pll_clk_en &= ~(0x01U << (inst->mlane + i));
>  	}
>  
>  	cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, pwr_state);
> @@ -1366,36 +1370,57 @@ static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy,
>  
>  /* Configure lane count as required. */
>  static int cdns_torrent_dp_set_lanes(struct cdns_torrent_phy *cdns_phy,
> +				     struct cdns_torrent_inst *inst,
>  				     struct phy_configure_opts_dp *dp)
>  {
> -	u32 value;
> -	u32 ret;
>  	struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
>  	u8 lane_mask = (1 << dp->lanes) - 1;
> +	u8 pma_tx_elec_idle_mask = 0;
> +	u32 value, i;
> +	int ret;
> +	u32 clane = inst->mlane;
> +
> +	lane_mask <<= clane;
>  
>  	value = cdns_torrent_dp_read(regmap, PHY_RESET);
>  	/* clear pma_tx_elec_idle_ln_* bits. */
> -	value &= ~PMA_TX_ELEC_IDLE_MASK;
> +	pma_tx_elec_idle_mask = ((1 << inst->num_lanes) - 1) << clane;
> +
> +	pma_tx_elec_idle_mask <<= PMA_TX_ELEC_IDLE_SHIFT;
> +
> +	value &= ~pma_tx_elec_idle_mask;
> +
>  	/* Assert pma_tx_elec_idle_ln_* for disabled lanes. */
>  	value |= ((~lane_mask) << PMA_TX_ELEC_IDLE_SHIFT) &
> -		 PMA_TX_ELEC_IDLE_MASK;
> +		 pma_tx_elec_idle_mask;
> +
>  	cdns_torrent_dp_write(regmap, PHY_RESET, value);
>  
> -	/* reset the link by asserting phy_l00_reset_n low */
> +	/* reset the link by asserting master lane phy_l0*_reset_n low */
>  	cdns_torrent_dp_write(regmap, PHY_RESET,
> -			      value & (~PHY_L00_RESET_N_MASK));
> +			      value & (~(1 << clane)));
>  
>  	/*
> -	 * Assert lane reset on unused lanes and lane 0 so they remain in reset
> +	 * Assert lane reset on unused lanes and master lane so they remain in reset
>  	 * and powered down when re-enabling the link
>  	 */
> -	value = (value & 0x0000FFF0) | (0x0000000E & lane_mask);
> +	for (i = 0; i < inst->num_lanes; i++)
> +		value &= (~(1 << (clane + i)));
> +
> +	for (i = 1; i < inst->num_lanes; i++)
> +		value |= ((1 << (clane + i)) & lane_mask);
> +
>  	cdns_torrent_dp_write(regmap, PHY_RESET, value);
>  
> -	cdns_torrent_dp_set_a0_pll(cdns_phy, dp->lanes);
> +	cdns_torrent_dp_set_a0_pll(cdns_phy, inst, dp->lanes);
>  
>  	/* release phy_l0*_reset_n based on used laneCount */
> -	value = (value & 0x0000FFF0) | (0x0000000F & lane_mask);
> +	for (i = 0; i < inst->num_lanes; i++)
> +		value &= (~(1 << (clane + i)));
> +
> +	for (i = 0; i < inst->num_lanes; i++)
> +		value |= ((1 << (clane + i)) & lane_mask);
> +
>  	cdns_torrent_dp_write(regmap, PHY_RESET, value);
>  
>  	/* Wait, until PHY gets ready after releasing PHY reset signal. */
> @@ -1406,41 +1431,44 @@ static int cdns_torrent_dp_set_lanes(struct cdns_torrent_phy *cdns_phy,
>  	ndelay(100);
>  
>  	/* release pma_xcvr_pllclk_en_ln_*, only for the master lane */
> -	cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001);
> +	value = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN);
> +	value |= (1 << clane);
> +	cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, value);
>  
> -	ret = cdns_torrent_dp_run(cdns_phy, dp->lanes);
> +	ret = cdns_torrent_dp_run(cdns_phy, inst, dp->lanes);
>  
>  	return ret;
>  }
>  
>  /* Configure link rate as required. */
>  static int cdns_torrent_dp_set_rate(struct cdns_torrent_phy *cdns_phy,
> +				    struct cdns_torrent_inst *inst,
>  				    struct phy_configure_opts_dp *dp)
>  {
> -	u32 ret;
> +	int ret;
>  
> -	ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
> +	ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes,
>  					      POWERSTATE_A3);
>  	if (ret)
>  		return ret;
> -	ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, false);
> +	ret = cdns_torrent_dp_set_pll_en(cdns_phy, inst, dp, false);
>  	if (ret)
>  		return ret;
>  	ndelay(200);
>  
> -	ret = cdns_torrent_dp_configure_rate(cdns_phy, dp);
> +	ret = cdns_torrent_dp_configure_rate(cdns_phy, inst, dp);
>  	if (ret)
>  		return ret;
>  	ndelay(200);
>  
> -	ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, true);
> +	ret = cdns_torrent_dp_set_pll_en(cdns_phy, inst, dp, true);
>  	if (ret)
>  		return ret;
> -	ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
> +	ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes,
>  					      POWERSTATE_A2);
>  	if (ret)
>  		return ret;
> -	ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
> +	ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes,
>  					      POWERSTATE_A0);
>  	if (ret)
>  		return ret;
> @@ -1451,44 +1479,45 @@ static int cdns_torrent_dp_set_rate(struct cdns_torrent_phy *cdns_phy,
>  
>  /* Configure voltage swing and pre-emphasis for all enabled lanes. */
>  static void cdns_torrent_dp_set_voltages(struct cdns_torrent_phy *cdns_phy,
> +					 struct cdns_torrent_inst *inst,
>  					 struct phy_configure_opts_dp *dp)
>  {
>  	u8 lane;
>  	u16 val;
>  
>  	for (lane = 0; lane < dp->lanes; lane++) {
> -		val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane],
> +		val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
>  					    TX_DIAG_ACYA);
>  		/*
>  		 * Write 1 to register bit TX_DIAG_ACYA[0] to freeze the
>  		 * current state of the analog TX driver.
>  		 */
>  		val |= TX_DIAG_ACYA_HBDC_MASK;
> -		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
> +		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
>  				       TX_DIAG_ACYA, val);
>  
> -		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
> +		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
>  				       TX_TXCC_CTRL, 0x08A4);
>  		val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].diag_tx_drv;
> -		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
> +		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
>  				       DRV_DIAG_TX_DRV, val);
>  		val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].mgnfs_mult;
> -		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
> +		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
>  				       TX_TXCC_MGNFS_MULT_000,
>  				       val);
>  		val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].cpost_mult;
> -		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
> +		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
>  				       TX_TXCC_CPOST_MULT_00,
>  				       val);
>  
> -		val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane],
> +		val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
>  					    TX_DIAG_ACYA);
>  		/*
>  		 * Write 0 to register bit TX_DIAG_ACYA[0] to allow the state of
>  		 * analog TX driver to reflect the new programmed one.
>  		 */
>  		val &= ~TX_DIAG_ACYA_HBDC_MASK;
> -		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
> +		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
>  				       TX_DIAG_ACYA, val);
>  	}
>  };
> @@ -1507,7 +1536,7 @@ static int cdns_torrent_dp_configure(struct phy *phy,
>  	}
>  
>  	if (opts->dp.set_lanes) {
> -		ret = cdns_torrent_dp_set_lanes(cdns_phy, &opts->dp);
> +		ret = cdns_torrent_dp_set_lanes(cdns_phy, inst, &opts->dp);
>  		if (ret) {
>  			dev_err(&phy->dev, "cdns_torrent_dp_set_lanes failed\n");
>  			return ret;
> @@ -1515,7 +1544,7 @@ static int cdns_torrent_dp_configure(struct phy *phy,
>  	}
>  
>  	if (opts->dp.set_rate) {
> -		ret = cdns_torrent_dp_set_rate(cdns_phy, &opts->dp);
> +		ret = cdns_torrent_dp_set_rate(cdns_phy, inst, &opts->dp);
>  		if (ret) {
>  			dev_err(&phy->dev, "cdns_torrent_dp_set_rate failed\n");
>  			return ret;
> @@ -1523,7 +1552,7 @@ static int cdns_torrent_dp_configure(struct phy *phy,
>  	}
>  
>  	if (opts->dp.set_voltages)
> -		cdns_torrent_dp_set_voltages(cdns_phy, &opts->dp);
> +		cdns_torrent_dp_set_voltages(cdns_phy, inst, &opts->dp);
>  
>  	return ret;
>  }
> @@ -1591,6 +1620,8 @@ static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy,
>  {
>  	struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
>  	unsigned char lane_bits;
> +	u32 val;
> +	u32 clane = 0;
>  
>  	cdns_torrent_dp_write(regmap, PHY_AUX_CTRL, 0x0003); /* enable AUX */
>  
> @@ -1598,18 +1629,24 @@ static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy,
>  	 * Set lines power state to A0
>  	 * Set lines pll clk enable to 0
>  	 */
> -	cdns_torrent_dp_set_a0_pll(cdns_phy, inst->num_lanes);
> +	cdns_torrent_dp_set_a0_pll(cdns_phy, inst, inst->num_lanes);
>  
>  	/*
>  	 * release phy_l0*_reset_n and pma_tx_elec_idle_ln_* based on
>  	 * used lanes
>  	 */
>  	lane_bits = (1 << inst->num_lanes) - 1;
> -	cdns_torrent_dp_write(regmap, PHY_RESET,
> -			      ((0xF & ~lane_bits) << 4) | (0xF & lane_bits));
> +	lane_bits <<= clane;
> +
> +	val = cdns_torrent_dp_read(regmap, PHY_RESET);
> +	val |= (0xF & lane_bits);
> +	val &= ~(lane_bits << 4);
> +	cdns_torrent_dp_write(regmap, PHY_RESET, val);
>  
>  	/* release pma_xcvr_pllclk_en_ln_*, only for the master lane */
> -	cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001);
> +	val = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN);
> +	val |= (1 << clane);
> +	cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, val);
>  
>  	/*
>  	 * PHY PMA registers configuration functions
> @@ -1628,7 +1665,7 @@ static void cdns_torrent_dp_common_init(struct cdns_torrent_phy *cdns_phy,
>  						       cdns_phy->max_bit_rate,
>  						       false);
>  
> -	cdns_torrent_dp_pma_cmn_rate(cdns_phy, cdns_phy->max_bit_rate,
> +	cdns_torrent_dp_pma_cmn_rate(cdns_phy, inst, cdns_phy->max_bit_rate,
>  				     inst->num_lanes);
>  
>  	/* take out of reset */
> @@ -1641,13 +1678,15 @@ static int cdns_torrent_dp_start(struct cdns_torrent_phy *cdns_phy,
>  {
>  	int ret;
>  
> -	cdns_torrent_phy_on(phy);
> +	ret = cdns_torrent_phy_on(phy);
> +	if (ret)
> +		return ret;
>  
>  	ret = cdns_torrent_dp_wait_pma_cmn_ready(cdns_phy);
>  	if (ret)
>  		return ret;
>  
> -	ret = cdns_torrent_dp_run(cdns_phy, inst->num_lanes);
> +	ret = cdns_torrent_dp_run(cdns_phy, inst, inst->num_lanes);
>  
>  	return ret;
>  }
> -- 
> 2.34.1

-- 
~Vinod



More information about the linux-phy mailing list