Message ID | 1617946456-27773-3-git-send-email-sjakhade@cadence.com |
---|---|
State | Changes Requested |
Headers | show |
Series | PHY: Add multilink DP support in Cadence Torrent PHY driver | expand |
Hi Swapnil, On 09/04/21 11:04 am, Swapnil Jakhade wrote: > Reorder some functions to avoid function declarations. > No functional change. > > Signed-off-by: Swapnil Jakhade <sjakhade@cadence.com> Please squash patches 2, 6 and 7 together unless you have a specific reason to keep them separate. Thanks Kishon > --- > drivers/phy/cadence/phy-cadence-torrent.c | 474 +++++++++++----------- > 1 file changed, 229 insertions(+), 245 deletions(-) > > diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c > index ff647669f1a3..6eeb753fbb78 100644 > --- a/drivers/phy/cadence/phy-cadence-torrent.c > +++ b/drivers/phy/cadence/phy-cadence-torrent.c > @@ -333,12 +333,6 @@ struct cdns_torrent_derived_refclk { > #define to_cdns_torrent_derived_refclk(_hw) \ > container_of(_hw, struct cdns_torrent_derived_refclk, hw) > > -static int cdns_torrent_phy_init(struct phy *phy); > -static int cdns_torrent_dp_init(struct phy *phy); > -static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, > - u32 num_lanes); > -static > -int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy); > static void cdns_torrent_dp_pma_cfg(struct cdns_torrent_phy *cdns_phy, > struct cdns_torrent_inst *inst); > static > @@ -353,36 +347,6 @@ void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy, > u32 rate, bool ssc); > static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy, > unsigned int lane); > -static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, > - u32 rate, u32 num_lanes); > -static int cdns_torrent_dp_configure(struct phy *phy, > - union phy_configure_opts *opts); > -static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, > - u32 num_lanes, > - enum phy_powerstate powerstate); > -static int cdns_torrent_phy_on(struct phy *phy); > -static int cdns_torrent_phy_off(struct phy *phy); > - > -static const struct phy_ops cdns_torrent_phy_ops = { > - .init = cdns_torrent_phy_init, > - .configure = cdns_torrent_dp_configure, > - .power_on = cdns_torrent_phy_on, > - .power_off = cdns_torrent_phy_off, > - .owner = THIS_MODULE, > -}; > - > -static int cdns_torrent_noop_phy_on(struct phy *phy) > -{ > - /* Give 5ms to 10ms delay for the PIPE clock to be stable */ > - usleep_range(5000, 10000); > - > - return 0; > -} > - > -static const struct phy_ops noop_ops = { > - .power_on = cdns_torrent_noop_phy_on, > - .owner = THIS_MODULE, > -}; > > struct cdns_reg_pairs { > u32 val; > @@ -669,6 +633,164 @@ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy, > return ret; > } > > +static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, > + u32 num_lanes, > + enum phy_powerstate powerstate) > +{ > + /* Register value for power state for a single byte. */ > + u32 value_part; > + u32 value; > + u32 mask; > + u32 read_val; > + u32 ret; > + struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; > + > + switch (powerstate) { > + case (POWERSTATE_A0): > + value_part = 0x01U; > + break; > + case (POWERSTATE_A2): > + value_part = 0x04U; > + break; > + default: > + /* Powerstate A3 */ > + value_part = 0x08U; > + 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; > + } > + > + /* Set power state A<n>. */ > + cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, value); > + /* Wait, until PHY acknowledges power state completion. */ > + ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_POWER_STATE_ACK, > + read_val, (read_val & mask) == value, 0, > + POLL_TIMEOUT_US); > + cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, 0x00000000); > + ndelay(100); > + > + return ret; > +} > + > +static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes) > +{ > + unsigned int read_val; > + int ret; > + struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; > + > + /* > + * 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, > + 0, POLL_TIMEOUT_US); > + if (ret == -ETIMEDOUT) { > + dev_err(cdns_phy->dev, > + "timeout waiting for link PLL clock enable ack\n"); > + return ret; > + } > + > + ndelay(100); > + > + ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, > + POWERSTATE_A2); > + if (ret) > + return ret; > + > + ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, > + POWERSTATE_A0); > + > + return ret; > +} > + > +static int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy) > +{ > + unsigned int reg; > + int ret; > + struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; > + > + ret = regmap_read_poll_timeout(regmap, PHY_PMA_CMN_READY, reg, > + reg & 1, 0, POLL_TIMEOUT_US); > + if (ret == -ETIMEDOUT) { > + dev_err(cdns_phy->dev, > + "timeout waiting for PMA common ready\n"); > + return -ETIMEDOUT; > + } > + > + return 0; > +} > + > +static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, > + u32 rate, u32 num_lanes) > +{ > + unsigned int clk_sel_val = 0; > + unsigned int hsclk_div_val = 0; > + unsigned int i; > + > + /* 16'h0000 for single DP link configuration */ > + regmap_field_write(cdns_phy->phy_pll_cfg, 0x0); > + > + switch (rate) { > + case 1620: > + clk_sel_val = 0x0f01; > + hsclk_div_val = 2; > + break; > + case 2160: > + case 2430: > + case 2700: > + clk_sel_val = 0x0701; > + hsclk_div_val = 1; > + break; > + case 3240: > + clk_sel_val = 0x0b00; > + hsclk_div_val = 2; > + break; > + case 4320: > + case 5400: > + clk_sel_val = 0x0301; > + hsclk_div_val = 0; > + break; > + case 8100: > + clk_sel_val = 0x0200; > + hsclk_div_val = 0; > + 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); > + > + /* 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], > + XCVR_DIAG_HSCLK_DIV, hsclk_div_val); > +} > + > /* > * Perform register operations related to setting link rate, once powerstate is > * set and PLL disable request was processed. > @@ -984,6 +1106,56 @@ static int cdns_torrent_dp_configure(struct phy *phy, > return ret; > } > > +static int cdns_torrent_phy_on(struct phy *phy) > +{ > + struct cdns_torrent_inst *inst = phy_get_drvdata(phy); > + struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); > + u32 read_val; > + int ret; > + > + if (cdns_phy->nsubnodes == 1) { > + /* Take the PHY lane group out of reset */ > + reset_control_deassert(inst->lnk_rst); > + > + /* Take the PHY out of reset */ > + ret = reset_control_deassert(cdns_phy->phy_rst); > + if (ret) > + return ret; > + } > + > + /* > + * Wait for cmn_ready assertion > + * PHY_PMA_CMN_CTRL1[0] == 1 > + */ > + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_1, > + read_val, read_val, 1000, > + PLL_LOCK_TIMEOUT); > + if (ret) { > + dev_err(cdns_phy->dev, "Timeout waiting for CMN ready\n"); > + return ret; > + } > + > + mdelay(10); > + > + return 0; > +} > + > +static int cdns_torrent_phy_off(struct phy *phy) > +{ > + struct cdns_torrent_inst *inst = phy_get_drvdata(phy); > + struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); > + int ret; > + > + if (cdns_phy->nsubnodes != 1) > + return 0; > + > + ret = reset_control_assert(cdns_phy->phy_rst); > + if (ret) > + return ret; > + > + return reset_control_assert(inst->lnk_rst); > +} > + > static int cdns_torrent_dp_init(struct phy *phy) > { > unsigned char lane_bits; > @@ -1051,24 +1223,6 @@ static int cdns_torrent_dp_init(struct phy *phy) > return ret; > } > > -static > -int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy) > -{ > - unsigned int reg; > - int ret; > - struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; > - > - ret = regmap_read_poll_timeout(regmap, PHY_PMA_CMN_READY, reg, > - reg & 1, 0, POLL_TIMEOUT_US); > - if (ret == -ETIMEDOUT) { > - dev_err(cdns_phy->dev, > - "timeout waiting for PMA common ready\n"); > - return -ETIMEDOUT; > - } > - > - return 0; > -} > - > static void cdns_torrent_dp_pma_cfg(struct cdns_torrent_phy *cdns_phy, > struct cdns_torrent_inst *inst) > { > @@ -1478,53 +1632,6 @@ void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy, > cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_START, 0x00C7); > } > > -static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, > - u32 rate, u32 num_lanes) > -{ > - unsigned int clk_sel_val = 0; > - unsigned int hsclk_div_val = 0; > - unsigned int i; > - > - /* 16'h0000 for single DP link configuration */ > - regmap_field_write(cdns_phy->phy_pll_cfg, 0x0); > - > - switch (rate) { > - case 1620: > - clk_sel_val = 0x0f01; > - hsclk_div_val = 2; > - break; > - case 2160: > - case 2430: > - case 2700: > - clk_sel_val = 0x0701; > - hsclk_div_val = 1; > - break; > - case 3240: > - clk_sel_val = 0x0b00; > - hsclk_div_val = 2; > - break; > - case 4320: > - case 5400: > - clk_sel_val = 0x0301; > - hsclk_div_val = 0; > - break; > - case 8100: > - clk_sel_val = 0x0200; > - hsclk_div_val = 0; > - 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); > - > - /* 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], > - XCVR_DIAG_HSCLK_DIV, hsclk_div_val); > -} > - > static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy, > unsigned int lane) > { > @@ -1568,100 +1675,6 @@ static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy, > XCVR_DIAG_HSCLK_SEL, 0x0000); > } > > -static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, > - u32 num_lanes, > - enum phy_powerstate powerstate) > -{ > - /* Register value for power state for a single byte. */ > - u32 value_part; > - u32 value; > - u32 mask; > - u32 read_val; > - u32 ret; > - struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; > - > - switch (powerstate) { > - case (POWERSTATE_A0): > - value_part = 0x01U; > - break; > - case (POWERSTATE_A2): > - value_part = 0x04U; > - break; > - default: > - /* Powerstate A3 */ > - value_part = 0x08U; > - 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; > - } > - > - /* Set power state A<n>. */ > - cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, value); > - /* Wait, until PHY acknowledges power state completion. */ > - ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_POWER_STATE_ACK, > - read_val, (read_val & mask) == value, 0, > - POLL_TIMEOUT_US); > - cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, 0x00000000); > - ndelay(100); > - > - return ret; > -} > - > -static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes) > -{ > - unsigned int read_val; > - int ret; > - struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; > - > - /* > - * 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, > - 0, POLL_TIMEOUT_US); > - if (ret == -ETIMEDOUT) { > - dev_err(cdns_phy->dev, > - "timeout waiting for link PLL clock enable ack\n"); > - return ret; > - } > - > - ndelay(100); > - > - ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, > - POWERSTATE_A2); > - if (ret) > - return ret; > - > - ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, > - POWERSTATE_A0); > - > - return ret; > -} > - > static int cdns_torrent_derived_refclk_enable(struct clk_hw *hw) > { > struct cdns_torrent_derived_refclk *derived_refclk = to_cdns_torrent_derived_refclk(hw); > @@ -1764,56 +1777,6 @@ static int cdns_torrent_derived_refclk_register(struct cdns_torrent_phy *cdns_ph > return 0; > } > > -static int cdns_torrent_phy_on(struct phy *phy) > -{ > - struct cdns_torrent_inst *inst = phy_get_drvdata(phy); > - struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); > - u32 read_val; > - int ret; > - > - if (cdns_phy->nsubnodes == 1) { > - /* Take the PHY lane group out of reset */ > - reset_control_deassert(inst->lnk_rst); > - > - /* Take the PHY out of reset */ > - ret = reset_control_deassert(cdns_phy->phy_rst); > - if (ret) > - return ret; > - } > - > - /* > - * Wait for cmn_ready assertion > - * PHY_PMA_CMN_CTRL1[0] == 1 > - */ > - ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_1, > - read_val, read_val, 1000, > - PLL_LOCK_TIMEOUT); > - if (ret) { > - dev_err(cdns_phy->dev, "Timeout waiting for CMN ready\n"); > - return ret; > - } > - > - mdelay(10); > - > - return 0; > -} > - > -static int cdns_torrent_phy_off(struct phy *phy) > -{ > - struct cdns_torrent_inst *inst = phy_get_drvdata(phy); > - struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); > - int ret; > - > - if (cdns_phy->nsubnodes != 1) > - return 0; > - > - ret = reset_control_assert(cdns_phy->phy_rst); > - if (ret) > - return ret; > - > - return reset_control_assert(inst->lnk_rst); > -} > - > static struct regmap *cdns_regmap_init(struct device *dev, void __iomem *base, > u32 block_offset, > u8 reg_offset_shift, > @@ -2091,6 +2054,27 @@ static int cdns_torrent_phy_init(struct phy *phy) > return 0; > } > > +static const struct phy_ops cdns_torrent_phy_ops = { > + .init = cdns_torrent_phy_init, > + .configure = cdns_torrent_dp_configure, > + .power_on = cdns_torrent_phy_on, > + .power_off = cdns_torrent_phy_off, > + .owner = THIS_MODULE, > +}; > + > +static int cdns_torrent_noop_phy_on(struct phy *phy) > +{ > + /* Give 5ms to 10ms delay for the PIPE clock to be stable */ > + usleep_range(5000, 10000); > + > + return 0; > +} > + > +static const struct phy_ops noop_ops = { > + .power_on = cdns_torrent_noop_phy_on, > + .owner = THIS_MODULE, > +}; > + > static > int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy) > { >
diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c index ff647669f1a3..6eeb753fbb78 100644 --- a/drivers/phy/cadence/phy-cadence-torrent.c +++ b/drivers/phy/cadence/phy-cadence-torrent.c @@ -333,12 +333,6 @@ struct cdns_torrent_derived_refclk { #define to_cdns_torrent_derived_refclk(_hw) \ container_of(_hw, struct cdns_torrent_derived_refclk, hw) -static int cdns_torrent_phy_init(struct phy *phy); -static int cdns_torrent_dp_init(struct phy *phy); -static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, - u32 num_lanes); -static -int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy); static void cdns_torrent_dp_pma_cfg(struct cdns_torrent_phy *cdns_phy, struct cdns_torrent_inst *inst); static @@ -353,36 +347,6 @@ void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy, u32 rate, bool ssc); static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy, unsigned int lane); -static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, - u32 rate, u32 num_lanes); -static int cdns_torrent_dp_configure(struct phy *phy, - union phy_configure_opts *opts); -static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, - u32 num_lanes, - enum phy_powerstate powerstate); -static int cdns_torrent_phy_on(struct phy *phy); -static int cdns_torrent_phy_off(struct phy *phy); - -static const struct phy_ops cdns_torrent_phy_ops = { - .init = cdns_torrent_phy_init, - .configure = cdns_torrent_dp_configure, - .power_on = cdns_torrent_phy_on, - .power_off = cdns_torrent_phy_off, - .owner = THIS_MODULE, -}; - -static int cdns_torrent_noop_phy_on(struct phy *phy) -{ - /* Give 5ms to 10ms delay for the PIPE clock to be stable */ - usleep_range(5000, 10000); - - return 0; -} - -static const struct phy_ops noop_ops = { - .power_on = cdns_torrent_noop_phy_on, - .owner = THIS_MODULE, -}; struct cdns_reg_pairs { u32 val; @@ -669,6 +633,164 @@ static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy, return ret; } +static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, + u32 num_lanes, + enum phy_powerstate powerstate) +{ + /* Register value for power state for a single byte. */ + u32 value_part; + u32 value; + u32 mask; + u32 read_val; + u32 ret; + struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; + + switch (powerstate) { + case (POWERSTATE_A0): + value_part = 0x01U; + break; + case (POWERSTATE_A2): + value_part = 0x04U; + break; + default: + /* Powerstate A3 */ + value_part = 0x08U; + 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; + } + + /* Set power state A<n>. */ + cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, value); + /* Wait, until PHY acknowledges power state completion. */ + ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_POWER_STATE_ACK, + read_val, (read_val & mask) == value, 0, + POLL_TIMEOUT_US); + cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, 0x00000000); + ndelay(100); + + return ret; +} + +static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes) +{ + unsigned int read_val; + int ret; + struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; + + /* + * 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, + 0, POLL_TIMEOUT_US); + if (ret == -ETIMEDOUT) { + dev_err(cdns_phy->dev, + "timeout waiting for link PLL clock enable ack\n"); + return ret; + } + + ndelay(100); + + ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, + POWERSTATE_A2); + if (ret) + return ret; + + ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, + POWERSTATE_A0); + + return ret; +} + +static int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy) +{ + unsigned int reg; + int ret; + struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; + + ret = regmap_read_poll_timeout(regmap, PHY_PMA_CMN_READY, reg, + reg & 1, 0, POLL_TIMEOUT_US); + if (ret == -ETIMEDOUT) { + dev_err(cdns_phy->dev, + "timeout waiting for PMA common ready\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, + u32 rate, u32 num_lanes) +{ + unsigned int clk_sel_val = 0; + unsigned int hsclk_div_val = 0; + unsigned int i; + + /* 16'h0000 for single DP link configuration */ + regmap_field_write(cdns_phy->phy_pll_cfg, 0x0); + + switch (rate) { + case 1620: + clk_sel_val = 0x0f01; + hsclk_div_val = 2; + break; + case 2160: + case 2430: + case 2700: + clk_sel_val = 0x0701; + hsclk_div_val = 1; + break; + case 3240: + clk_sel_val = 0x0b00; + hsclk_div_val = 2; + break; + case 4320: + case 5400: + clk_sel_val = 0x0301; + hsclk_div_val = 0; + break; + case 8100: + clk_sel_val = 0x0200; + hsclk_div_val = 0; + 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); + + /* 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], + XCVR_DIAG_HSCLK_DIV, hsclk_div_val); +} + /* * Perform register operations related to setting link rate, once powerstate is * set and PLL disable request was processed. @@ -984,6 +1106,56 @@ static int cdns_torrent_dp_configure(struct phy *phy, return ret; } +static int cdns_torrent_phy_on(struct phy *phy) +{ + struct cdns_torrent_inst *inst = phy_get_drvdata(phy); + struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); + u32 read_val; + int ret; + + if (cdns_phy->nsubnodes == 1) { + /* Take the PHY lane group out of reset */ + reset_control_deassert(inst->lnk_rst); + + /* Take the PHY out of reset */ + ret = reset_control_deassert(cdns_phy->phy_rst); + if (ret) + return ret; + } + + /* + * Wait for cmn_ready assertion + * PHY_PMA_CMN_CTRL1[0] == 1 + */ + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_1, + read_val, read_val, 1000, + PLL_LOCK_TIMEOUT); + if (ret) { + dev_err(cdns_phy->dev, "Timeout waiting for CMN ready\n"); + return ret; + } + + mdelay(10); + + return 0; +} + +static int cdns_torrent_phy_off(struct phy *phy) +{ + struct cdns_torrent_inst *inst = phy_get_drvdata(phy); + struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); + int ret; + + if (cdns_phy->nsubnodes != 1) + return 0; + + ret = reset_control_assert(cdns_phy->phy_rst); + if (ret) + return ret; + + return reset_control_assert(inst->lnk_rst); +} + static int cdns_torrent_dp_init(struct phy *phy) { unsigned char lane_bits; @@ -1051,24 +1223,6 @@ static int cdns_torrent_dp_init(struct phy *phy) return ret; } -static -int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy) -{ - unsigned int reg; - int ret; - struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; - - ret = regmap_read_poll_timeout(regmap, PHY_PMA_CMN_READY, reg, - reg & 1, 0, POLL_TIMEOUT_US); - if (ret == -ETIMEDOUT) { - dev_err(cdns_phy->dev, - "timeout waiting for PMA common ready\n"); - return -ETIMEDOUT; - } - - return 0; -} - static void cdns_torrent_dp_pma_cfg(struct cdns_torrent_phy *cdns_phy, struct cdns_torrent_inst *inst) { @@ -1478,53 +1632,6 @@ void cdns_torrent_dp_pma_cmn_vco_cfg_25mhz(struct cdns_torrent_phy *cdns_phy, cdns_torrent_phy_write(regmap, CMN_PLL1_LOCK_PLLCNT_START, 0x00C7); } -static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy, - u32 rate, u32 num_lanes) -{ - unsigned int clk_sel_val = 0; - unsigned int hsclk_div_val = 0; - unsigned int i; - - /* 16'h0000 for single DP link configuration */ - regmap_field_write(cdns_phy->phy_pll_cfg, 0x0); - - switch (rate) { - case 1620: - clk_sel_val = 0x0f01; - hsclk_div_val = 2; - break; - case 2160: - case 2430: - case 2700: - clk_sel_val = 0x0701; - hsclk_div_val = 1; - break; - case 3240: - clk_sel_val = 0x0b00; - hsclk_div_val = 2; - break; - case 4320: - case 5400: - clk_sel_val = 0x0301; - hsclk_div_val = 0; - break; - case 8100: - clk_sel_val = 0x0200; - hsclk_div_val = 0; - 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); - - /* 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], - XCVR_DIAG_HSCLK_DIV, hsclk_div_val); -} - static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy, unsigned int lane) { @@ -1568,100 +1675,6 @@ static void cdns_torrent_dp_pma_lane_cfg(struct cdns_torrent_phy *cdns_phy, XCVR_DIAG_HSCLK_SEL, 0x0000); } -static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy, - u32 num_lanes, - enum phy_powerstate powerstate) -{ - /* Register value for power state for a single byte. */ - u32 value_part; - u32 value; - u32 mask; - u32 read_val; - u32 ret; - struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; - - switch (powerstate) { - case (POWERSTATE_A0): - value_part = 0x01U; - break; - case (POWERSTATE_A2): - value_part = 0x04U; - break; - default: - /* Powerstate A3 */ - value_part = 0x08U; - 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; - } - - /* Set power state A<n>. */ - cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, value); - /* Wait, until PHY acknowledges power state completion. */ - ret = regmap_read_poll_timeout(regmap, PHY_PMA_XCVR_POWER_STATE_ACK, - read_val, (read_val & mask) == value, 0, - POLL_TIMEOUT_US); - cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, 0x00000000); - ndelay(100); - - return ret; -} - -static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes) -{ - unsigned int read_val; - int ret; - struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; - - /* - * 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, - 0, POLL_TIMEOUT_US); - if (ret == -ETIMEDOUT) { - dev_err(cdns_phy->dev, - "timeout waiting for link PLL clock enable ack\n"); - return ret; - } - - ndelay(100); - - ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, - POWERSTATE_A2); - if (ret) - return ret; - - ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes, - POWERSTATE_A0); - - return ret; -} - static int cdns_torrent_derived_refclk_enable(struct clk_hw *hw) { struct cdns_torrent_derived_refclk *derived_refclk = to_cdns_torrent_derived_refclk(hw); @@ -1764,56 +1777,6 @@ static int cdns_torrent_derived_refclk_register(struct cdns_torrent_phy *cdns_ph return 0; } -static int cdns_torrent_phy_on(struct phy *phy) -{ - struct cdns_torrent_inst *inst = phy_get_drvdata(phy); - struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); - u32 read_val; - int ret; - - if (cdns_phy->nsubnodes == 1) { - /* Take the PHY lane group out of reset */ - reset_control_deassert(inst->lnk_rst); - - /* Take the PHY out of reset */ - ret = reset_control_deassert(cdns_phy->phy_rst); - if (ret) - return ret; - } - - /* - * Wait for cmn_ready assertion - * PHY_PMA_CMN_CTRL1[0] == 1 - */ - ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_1, - read_val, read_val, 1000, - PLL_LOCK_TIMEOUT); - if (ret) { - dev_err(cdns_phy->dev, "Timeout waiting for CMN ready\n"); - return ret; - } - - mdelay(10); - - return 0; -} - -static int cdns_torrent_phy_off(struct phy *phy) -{ - struct cdns_torrent_inst *inst = phy_get_drvdata(phy); - struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); - int ret; - - if (cdns_phy->nsubnodes != 1) - return 0; - - ret = reset_control_assert(cdns_phy->phy_rst); - if (ret) - return ret; - - return reset_control_assert(inst->lnk_rst); -} - static struct regmap *cdns_regmap_init(struct device *dev, void __iomem *base, u32 block_offset, u8 reg_offset_shift, @@ -2091,6 +2054,27 @@ static int cdns_torrent_phy_init(struct phy *phy) return 0; } +static const struct phy_ops cdns_torrent_phy_ops = { + .init = cdns_torrent_phy_init, + .configure = cdns_torrent_dp_configure, + .power_on = cdns_torrent_phy_on, + .power_off = cdns_torrent_phy_off, + .owner = THIS_MODULE, +}; + +static int cdns_torrent_noop_phy_on(struct phy *phy) +{ + /* Give 5ms to 10ms delay for the PIPE clock to be stable */ + usleep_range(5000, 10000); + + return 0; +} + +static const struct phy_ops noop_ops = { + .power_on = cdns_torrent_noop_phy_on, + .owner = THIS_MODULE, +}; + static int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy) {
Reorder some functions to avoid function declarations. No functional change. Signed-off-by: Swapnil Jakhade <sjakhade@cadence.com> --- drivers/phy/cadence/phy-cadence-torrent.c | 474 +++++++++++----------- 1 file changed, 229 insertions(+), 245 deletions(-)