summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSwapnil Jakhade <sjakhade@cadence.com>2022-01-28 11:11:46 +0300
committerTom Rini <trini@konsulko.com>2022-02-08 19:00:03 +0300
commitf0cb8096d9226d30b95363244287b4524742144d (patch)
tree048369d720b45bcfd1688b55c88fa838e63d67cb /drivers
parent48f29871f09dc059646deafa6e7f3b0cc8c892fc (diff)
downloadu-boot-f0cb8096d9226d30b95363244287b4524742144d.tar.xz
phy: cadence: Sierra: 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> Signed-off-by: Aswath Govindraju <a-govindraju@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/phy/cadence/phy-cadence-sierra.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c
index df31fb3f19..8518594b26 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -157,6 +157,11 @@
#define SIERRA_PHY_PMA_COMMON_OFFSET 0xe000
#define SIERRA_PHY_PMA_CMN_CTRL 0x0
+/* PHY PCS lane registers */
+#define SIERRA_PHY_PCS_LANE_CDB_OFFSET(ln, offset) \
+ (0xD000 + ((ln) * (0x800 >> (3 - (offset)))))
+#define SIERRA_PHY_ISO_LINK_CTRL 0xB
+
#define SIERRA_MACRO_ID 0x00007364
#define SIERRA_MAX_LANES 16
#define PLL_LOCK_TIME 100
@@ -181,6 +186,8 @@ static const struct reg_field pma_cmn_ready =
REG_FIELD(SIERRA_PHY_PMA_CMN_CTRL, 0, 0);
static const struct reg_field pllctrl_lock =
REG_FIELD(SIERRA_PLLCTRL_STATUS_PREG, 0, 0);
+static const struct reg_field phy_iso_link_ctrl_1 =
+ REG_FIELD(SIERRA_PHY_ISO_LINK_CTRL, 1, 1);
static const char * const clk_names[] = {
[CDNS_SIERRA_PLL_CMNLC] = "pll_cmnlc",
@@ -276,6 +283,7 @@ struct cdns_sierra_phy {
struct reset_control *phy_rst;
struct regmap *regmap_lane_cdb[SIERRA_MAX_LANES];
struct regmap *regmap_phy_pcs_common_cdb;
+ struct regmap *regmap_phy_pcs_lane_cdb[SIERRA_MAX_LANES];
struct regmap *regmap_phy_pma_common_cdb;
struct regmap *regmap_common_cdb;
struct regmap_field *macro_id_type;
@@ -286,6 +294,7 @@ struct cdns_sierra_phy {
struct regmap_field *cmn_refrcv_refclk_termen_preg[SIERRA_NUM_CMN_PLLC];
struct regmap_field *cmn_plllc_pfdclk1_sel_preg[SIERRA_NUM_CMN_PLLC];
struct clk *input_clks[CDNS_SIERRA_INPUT_CLOCKS];
+ struct regmap_field *phy_iso_link_ctrl_1[SIERRA_MAX_LANES];
int nsubnodes;
u32 num_lanes;
bool autoconf;
@@ -400,6 +409,15 @@ static int cdns_sierra_phy_on(struct phy *gphy)
return ret;
}
+ if (ins->phy_type == TYPE_PCIE || ins->phy_type == TYPE_USB) {
+ ret = regmap_field_read_poll_timeout(sp->phy_iso_link_ctrl_1[ins->mlane],
+ val, !val, 1000, PLL_LOCK_TIME);
+ if (ret) {
+ dev_err(dev, "Timeout waiting for PHY status ready\n");
+ return ret;
+ }
+ }
+
/*
* Wait for cmn_ready assertion
* PHY_PMA_CMN_CTRL[0] == 1
@@ -666,7 +684,17 @@ static int cdns_regfield_init(struct cdns_sierra_phy *sp)
dev_err(dev, "P%d_ENABLE reg field init failed\n", i);
return PTR_ERR(field);
}
- sp->pllctrl_lock[i] = field;
+ sp->pllctrl_lock[i] = field;
+ }
+
+ for (i = 0; i < SIERRA_MAX_LANES; i++) {
+ regmap = sp->regmap_phy_pcs_lane_cdb[i];
+ field = devm_regmap_field_alloc(dev, regmap, phy_iso_link_ctrl_1);
+ if (IS_ERR(field)) {
+ dev_err(dev, "PHY_ISO_LINK_CTRL reg field init for lane %d failed\n", i);
+ return PTR_ERR(field);
+ }
+ sp->phy_iso_link_ctrl_1[i] = field;
}
return 0;
@@ -708,6 +736,17 @@ static int cdns_regmap_init_blocks(struct cdns_sierra_phy *sp,
}
sp->regmap_phy_pcs_common_cdb = regmap;
+ for (i = 0; i < SIERRA_MAX_LANES; i++) {
+ block_offset = SIERRA_PHY_PCS_LANE_CDB_OFFSET(i, reg_offset_shift);
+ regmap = cdns_regmap_init(dev, base, block_offset,
+ block_offset_shift, reg_offset_shift);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "Failed to init PHY PCS lane CDB regmap\n");
+ return PTR_ERR(regmap);
+ }
+ sp->regmap_phy_pcs_lane_cdb[i] = regmap;
+ }
+
regmap = cdns_regmap_init(dev, base, SIERRA_PHY_PMA_COMMON_OFFSET,
block_offset_shift, reg_offset_shift);
if (IS_ERR(regmap)) {