On Wed, Jan 3, 2018 at 4:58 PM, Manu Gautam <mgautam@xxxxxxxxxxxxxx> wrote: > New version of QUSB2 PHY has some registers offset changed. > Add support to have register layout for a target and update > the same in phy_configuration. > > Signed-off-by: Manu Gautam <mgautam@xxxxxxxxxxxxxx> > --- LGTM. Reviewed-by: Vivek Gautam <vivek.gautam@xxxxxxxxxxxxxx> > drivers/phy/qualcomm/phy-qcom-qusb2.c | 149 +++++++++++++++++++++++++--------- > 1 file changed, 109 insertions(+), 40 deletions(-) > > diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c > index 4a5b2a1..b65635f 100644 > --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c > +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c > @@ -37,17 +37,10 @@ > #define QUSB2PHY_PLL_AUTOPGM_CTL1 0x1c > #define QUSB2PHY_PLL_PWR_CTRL 0x18 > > -#define QUSB2PHY_PLL_STATUS 0x38 > +/* QUSB2PHY_PLL_STATUS register bits */ > #define PLL_LOCKED BIT(5) > > -#define QUSB2PHY_PORT_TUNE1 0x80 > -#define QUSB2PHY_PORT_TUNE2 0x84 > -#define QUSB2PHY_PORT_TUNE3 0x88 > -#define QUSB2PHY_PORT_TUNE4 0x8c > -#define QUSB2PHY_PORT_TUNE5 0x90 > -#define QUSB2PHY_PORT_TEST2 0x9c > - > -#define QUSB2PHY_PORT_POWERDOWN 0xb4 > +/* QUSB2PHY_PORT_POWERDOWN register bits */ > #define CLAMP_N_EN BIT(5) > #define FREEZIO_N BIT(1) > #define POWER_DOWN BIT(0) > @@ -59,6 +52,11 @@ > struct qusb2_phy_init_tbl { > unsigned int offset; > unsigned int val; > + /* > + * register part of layout ? > + * if yes, then offset gives index in the reg-layout > + */ > + int in_layout; > }; > > #define QUSB2_PHY_INIT_CFG(o, v) \ > @@ -67,15 +65,50 @@ struct qusb2_phy_init_tbl { > .val = v, \ > } > > +#define QUSB2_PHY_INIT_CFG_L(o, v) \ > + { \ > + .offset = o, \ > + .val = v, \ > + .in_layout = 1, \ > + } > + > +/* set of registers with offsets different per-PHY */ > +enum qusb2phy_reg_layout { > + QUSB2PHY_PLL_STATUS, > + QUSB2PHY_PORT_TUNE1, > + QUSB2PHY_PORT_TUNE2, > + QUSB2PHY_PORT_TUNE3, > + QUSB2PHY_PORT_TUNE4, > + QUSB2PHY_PORT_TUNE5, > + QUSB2PHY_PORT_TEST1, > + QUSB2PHY_PORT_TEST2, > + QUSB2PHY_PORT_POWERDOWN, > + QUSB2PHY_INTR_CTRL, > +}; > + > +static const unsigned int msm8996_regs_layout[] = { > + [QUSB2PHY_PLL_STATUS] = 0x38, > + [QUSB2PHY_PORT_TUNE1] = 0x80, > + [QUSB2PHY_PORT_TUNE2] = 0x84, > + [QUSB2PHY_PORT_TUNE3] = 0x88, > + [QUSB2PHY_PORT_TUNE4] = 0x8c, > + [QUSB2PHY_PORT_TUNE5] = 0x90, > + [QUSB2PHY_PORT_TEST2] = 0x9c, > + [QUSB2PHY_PORT_POWERDOWN] = 0xb4, > +}; > + > static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = { > - QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE1, 0xf8), > - QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE2, 0xb3), > - QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE3, 0x83), > - QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE4, 0xc0), > + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0xf8), > + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0xb3), > + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE3, 0x83), > + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0xc0), > + > QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TUNE, 0x30), > QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL1, 0x79), > QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL2, 0x21), > - QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TEST2, 0x14), > + > + QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TEST2, 0x14), > + > QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_AUTOPGM_CTL1, 0x9f), > QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00), > }; > @@ -86,11 +119,27 @@ struct qusb2_phy_cfg { > unsigned int tbl_num; > /* offset to PHY_CLK_SCHEME register in TCSR map */ > unsigned int clk_scheme_offset; > + > + /* array of registers with different offsets */ > + const unsigned int *regs; > + unsigned int mask_core_ready; > + unsigned int disable_ctrl; > + > + /* true if PHY has PLL_TEST register to select clk_scheme */ > + bool has_pll_test; > + > + /* true if TUNE1 register must be updated by fused value, else TUNE2 */ > + bool update_tune1_with_efuse; > }; > > static const struct qusb2_phy_cfg msm8996_phy_cfg = { > - .tbl = msm8996_init_tbl, > - .tbl_num = ARRAY_SIZE(msm8996_init_tbl), > + .tbl = msm8996_init_tbl, > + .tbl_num = ARRAY_SIZE(msm8996_init_tbl), > + .regs = msm8996_regs_layout, > + > + .has_pll_test = true, > + .disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN), > + .mask_core_ready = PLL_LOCKED, > }; > > static const char * const qusb2_phy_vreg_names[] = { > @@ -160,26 +209,32 @@ static inline void qusb2_clrbits(void __iomem *base, u32 offset, u32 val) > > static inline > void qcom_qusb2_phy_configure(void __iomem *base, > + const unsigned int *regs, > const struct qusb2_phy_init_tbl tbl[], int num) > { > int i; > > - for (i = 0; i < num; i++) > - writel(tbl[i].val, base + tbl[i].offset); > + for (i = 0; i < num; i++) { > + if (tbl[i].in_layout) > + writel(tbl[i].val, base + regs[tbl[i].offset]); > + else > + writel(tbl[i].val, base + tbl[i].offset); > + } > } > > /* > * Fetches HS Tx tuning value from nvmem and sets the > - * QUSB2PHY_PORT_TUNE2 register. > + * QUSB2PHY_PORT_TUNE1/2 register. > * For error case, skip setting the value and use the default value. > */ > static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) > { > struct device *dev = &qphy->phy->dev; > + const struct qusb2_phy_cfg *cfg = qphy->cfg; > u8 *val; > > /* > - * Read efuse register having TUNE2 parameter's high nibble. > + * Read efuse register having TUNE2/1 parameter's high nibble. > * If efuse register shows value as 0x0, or if we fail to find > * a valid efuse register settings, then use default value > * as 0xB for high nibble that we have already set while > @@ -191,14 +246,21 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) > return; > } > > - /* Fused TUNE2 value is the higher nibble only */ > - qusb2_setbits(qphy->base, QUSB2PHY_PORT_TUNE2, val[0] << 0x4); > + /* Fused TUNE1/2 value is the higher nibble only */ > + if (cfg->update_tune1_with_efuse) > + qusb2_setbits(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1], > + val[0] << 0x4); > + else > + qusb2_setbits(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE2], > + val[0] << 0x4); > + > } > > static int qusb2_phy_init(struct phy *phy) > { > struct qusb2_phy *qphy = phy_get_drvdata(phy); > - unsigned int val; > + const struct qusb2_phy_cfg *cfg = qphy->cfg; > + unsigned int val = 0; > unsigned int clk_scheme; > int ret; > > @@ -239,20 +301,23 @@ static int qusb2_phy_init(struct phy *phy) > } > > /* Disable the PHY */ > - qusb2_setbits(qphy->base, QUSB2PHY_PORT_POWERDOWN, > - CLAMP_N_EN | FREEZIO_N | POWER_DOWN); > + qusb2_setbits(qphy->base, cfg->regs[QUSB2PHY_PORT_POWERDOWN], > + qphy->cfg->disable_ctrl); > > - /* save reset value to override reference clock scheme later */ > - val = readl(qphy->base + QUSB2PHY_PLL_TEST); > + if (cfg->has_pll_test) { > + /* save reset value to override reference clock scheme later */ > + val = readl(qphy->base + QUSB2PHY_PLL_TEST); > + } > > - qcom_qusb2_phy_configure(qphy->base, qphy->cfg->tbl, > - qphy->cfg->tbl_num); > + qcom_qusb2_phy_configure(qphy->base, cfg->regs, cfg->tbl, > + cfg->tbl_num); > > /* Set efuse value for tuning the PHY */ > qusb2_phy_set_tune2_param(qphy); > > /* Enable the PHY */ > - qusb2_clrbits(qphy->base, QUSB2PHY_PORT_POWERDOWN, POWER_DOWN); > + qusb2_clrbits(qphy->base, cfg->regs[QUSB2PHY_PORT_POWERDOWN], > + POWER_DOWN); > > /* Required to get phy pll lock successfully */ > usleep_range(150, 160); > @@ -285,27 +350,31 @@ static int qusb2_phy_init(struct phy *phy) > } > > if (!qphy->has_se_clk_scheme) { > - val &= ~CLK_REF_SEL; > ret = clk_prepare_enable(qphy->ref_clk); > if (ret) { > dev_err(&phy->dev, "failed to enable ref clk, %d\n", > ret); > goto assert_phy_reset; > } > - } else { > - val |= CLK_REF_SEL; > } > > - writel(val, qphy->base + QUSB2PHY_PLL_TEST); > + if (cfg->has_pll_test) { > + if (!qphy->has_se_clk_scheme) > + val &= ~CLK_REF_SEL; > + else > + val |= CLK_REF_SEL; > + > + writel(val, qphy->base + QUSB2PHY_PLL_TEST); > > - /* ensure above write is through */ > - readl(qphy->base + QUSB2PHY_PLL_TEST); > + /* ensure above write is through */ > + readl(qphy->base + QUSB2PHY_PLL_TEST); > + } > > /* Required to get phy pll lock successfully */ > usleep_range(100, 110); > > - val = readb(qphy->base + QUSB2PHY_PLL_STATUS); > - if (!(val & PLL_LOCKED)) { > + val = readb(qphy->base + cfg->regs[QUSB2PHY_PLL_STATUS]); > + if (!(val & cfg->mask_core_ready)) { > dev_err(&phy->dev, > "QUSB2PHY pll lock failed: status reg = %x\n", val); > ret = -EBUSY; > @@ -334,8 +403,8 @@ static int qusb2_phy_exit(struct phy *phy) > struct qusb2_phy *qphy = phy_get_drvdata(phy); > > /* Disable the PHY */ > - qusb2_setbits(qphy->base, QUSB2PHY_PORT_POWERDOWN, > - CLAMP_N_EN | FREEZIO_N | POWER_DOWN); > + qusb2_setbits(qphy->base, qphy->cfg->regs[QUSB2PHY_PORT_POWERDOWN], > + qphy->cfg->disable_ctrl); > > if (!qphy->has_se_clk_scheme) > clk_disable_unprepare(qphy->ref_clk); > -- > The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, > a Linux Foundation Collaborative Project > > -- > To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html