Message ID | 1514978930-31341-8-git-send-email-mgautam@codeaurora.org (mailing list archive) |
---|---|
State | Not Applicable, archived |
Delegated to: | Andy Gross |
Headers | show |
On Wed, Jan 3, 2018 at 4:58 PM, Manu Gautam <mgautam@codeaurora.org> 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@codeaurora.org> > --- LGTM. Reviewed-by: Vivek Gautam <vivek.gautam@codeaurora.org> > 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@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html
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);
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@codeaurora.org> --- drivers/phy/qualcomm/phy-qcom-qusb2.c | 149 +++++++++++++++++++++++++--------- 1 file changed, 109 insertions(+), 40 deletions(-)