diff options
author | Swapnil Jakhade <sjakhade@cadence.com> | 2021-07-28 16:54:54 +0200 |
---|---|---|
committer | Vinod Koul <vkoul@kernel.org> | 2021-08-17 15:42:44 +0530 |
commit | 48ac6085bdfcf568e24c1efd45615ec3d5d3545b (patch) | |
tree | cfdd655b418d6f0ceaa2065a493667f04ac0d49f /drivers | |
parent | 84f55df836916be2b052a5000cca8d7d9fcf2520 (diff) | |
download | linux-stable-48ac6085bdfcf568e24c1efd45615ec3d5d3545b.tar.gz linux-stable-48ac6085bdfcf568e24c1efd45615ec3d5d3545b.tar.bz2 linux-stable-48ac6085bdfcf568e24c1efd45615ec3d5d3545b.zip |
phy: cadence-torrent: Check PIPE mode PHY status to be ready for operation
PIPE PHY status is used to communicate the completion of several PHY
functions. Check if PHY is ready for operation while configured for
PIPE mode during startup.
Signed-off-by: Swapnil Jakhade <sjakhade@cadence.com>
Link: https://lore.kernel.org/r/20210728145454.15945-10-sjakhade@cadence.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/phy/cadence/phy-cadence-torrent.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c index 4024db052cf9..415ace64adc5 100644 --- a/drivers/phy/cadence/phy-cadence-torrent.c +++ b/drivers/phy/cadence/phy-cadence-torrent.c @@ -51,6 +51,10 @@ #define TORRENT_PHY_PCS_COMMON_OFFSET(block_offset) \ (0xC000 << (block_offset)) +#define TORRENT_PHY_PCS_LANE_CDB_OFFSET(ln, block_offset, reg_offset) \ + ((0xD000 << (block_offset)) + \ + (((ln) << 8) << (reg_offset))) + #define TORRENT_PHY_PMA_COMMON_OFFSET(block_offset) \ (0xE000 << (block_offset)) @@ -223,6 +227,9 @@ #define PHY_PIPE_USB3_GEN2_POST_CFG0 0x0022U #define PHY_PIPE_USB3_GEN2_POST_CFG1 0x0023U +/* PHY PCS lane registers */ +#define PHY_PCS_ISO_LINK_CTRL 0x000BU + /* PHY PMA common registers */ #define PHY_PMA_CMN_CTRL1 0x0000U #define PHY_PMA_CMN_CTRL2 0x0001U @@ -247,6 +254,9 @@ static const struct reg_field phy_pma_pll_raw_ctrl = static const struct reg_field phy_reset_ctrl = REG_FIELD(PHY_RESET, 8, 8); +static const struct reg_field phy_pcs_iso_link_ctrl_1 = + REG_FIELD(PHY_PCS_ISO_LINK_CTRL, 1, 1); + static const struct reg_field phy_pipe_cmn_ctrl1_0 = REG_FIELD(PHY_PIPE_CMN_CTRL1, 0, 0); #define REFCLK_OUT_NUM_CMN_CONFIG 5 @@ -315,12 +325,14 @@ struct cdns_torrent_phy { struct regmap *regmap_phy_pma_common_cdb; struct regmap *regmap_tx_lane_cdb[MAX_NUM_LANES]; struct regmap *regmap_rx_lane_cdb[MAX_NUM_LANES]; + struct regmap *regmap_phy_pcs_lane_cdb[MAX_NUM_LANES]; struct regmap *regmap_dptx_phy_reg; struct regmap_field *phy_pll_cfg; struct regmap_field *phy_pma_cmn_ctrl_1; struct regmap_field *phy_pma_cmn_ctrl_2; struct regmap_field *phy_pma_pll_raw_ctrl; struct regmap_field *phy_reset_ctrl; + struct regmap_field *phy_pcs_iso_link_ctrl_1[MAX_NUM_LANES]; struct clk *clks[CDNS_TORRENT_REFCLK_DRIVER + 1]; struct clk_onecell_data clk_data; }; @@ -455,6 +467,22 @@ static const struct regmap_config cdns_torrent_common_cdb_config = { .reg_read = cdns_regmap_read, }; +#define TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF(n) \ +{ \ + .name = "torrent_phy_pcs_lane" n "_cdb", \ + .reg_stride = 1, \ + .fast_io = true, \ + .reg_write = cdns_regmap_write, \ + .reg_read = cdns_regmap_read, \ +} + +static const struct regmap_config cdns_torrent_phy_pcs_lane_cdb_config[] = { + TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF("0"), + TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF("1"), + TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF("2"), + TORRENT_PHY_PCS_LANE_CDB_REGMAP_CONF("3"), +}; + static const struct regmap_config cdns_torrent_phy_pcs_cmn_cdb_config = { .name = "torrent_phy_pcs_cmn_cdb", .reg_stride = 1, @@ -1469,7 +1497,15 @@ static int cdns_torrent_phy_on(struct phy *phy) return ret; } - mdelay(10); + if (inst->phy_type == TYPE_PCIE || inst->phy_type == TYPE_USB) { + ret = regmap_field_read_poll_timeout(cdns_phy->phy_pcs_iso_link_ctrl_1[inst->mlane], + read_val, !read_val, 1000, + PLL_LOCK_TIMEOUT); + if (ret == -ETIMEDOUT) { + dev_err(cdns_phy->dev, "Timeout waiting for PHY status ready\n"); + return ret; + } + } return 0; } @@ -1719,6 +1755,7 @@ static int cdns_torrent_regfield_init(struct cdns_torrent_phy *cdns_phy) struct device *dev = cdns_phy->dev; struct regmap_field *field; struct regmap *regmap; + int i; regmap = cdns_phy->regmap_phy_pcs_common_cdb; field = devm_regmap_field_alloc(dev, regmap, phy_pll_cfg); @@ -1752,6 +1789,16 @@ static int cdns_torrent_regfield_init(struct cdns_torrent_phy *cdns_phy) } cdns_phy->phy_pma_pll_raw_ctrl = field; + for (i = 0; i < MAX_NUM_LANES; i++) { + regmap = cdns_phy->regmap_phy_pcs_lane_cdb[i]; + field = devm_regmap_field_alloc(dev, regmap, phy_pcs_iso_link_ctrl_1); + if (IS_ERR(field)) { + dev_err(dev, "PHY_PCS_ISO_LINK_CTRL reg field init for ln %d failed\n", i); + return PTR_ERR(field); + } + cdns_phy->phy_pcs_iso_link_ctrl_1[i] = field; + } + return 0; } @@ -1812,6 +1859,17 @@ static int cdns_torrent_regmap_init(struct cdns_torrent_phy *cdns_phy) return PTR_ERR(regmap); } cdns_phy->regmap_rx_lane_cdb[i] = regmap; + + block_offset = TORRENT_PHY_PCS_LANE_CDB_OFFSET(i, block_offset_shift, + reg_offset_shift); + regmap = cdns_regmap_init(dev, sd_base, block_offset, + reg_offset_shift, + &cdns_torrent_phy_pcs_lane_cdb_config[i]); + if (IS_ERR(regmap)) { + dev_err(dev, "Failed to init PHY PCS lane CDB regmap\n"); + return PTR_ERR(regmap); + } + cdns_phy->regmap_phy_pcs_lane_cdb[i] = regmap; } block_offset = TORRENT_COMMON_CDB_OFFSET; |