Message ID | 1522665945-28147-4-git-send-email-tdas@codeaurora.org (mailing list archive) |
---|---|
State | Changes Requested, archived |
Headers | show |
Quoting Taniya Das (2018-04-02 03:45:45) > diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c > index e89584e..e0c83ba 100644 > --- a/drivers/clk/qcom/gdsc.c > +++ b/drivers/clk/qcom/gdsc.c > @@ -83,6 +88,38 @@ static int gdsc_poll_status(struct gdsc *sc, unsigned int reg, bool en) > return -ETIMEDOUT; > } > > +static int gdsc_is_enabled_by_poll_cfg_reg(struct gdsc *sc, bool en) > +{ > + u32 val; > + int ret; > + > + ret = regmap_read(sc->regmap, sc->gdscr + CFG_GDSCR_OFFSET, &val); > + if (ret) > + return ret; > + > + if (en) > + return !!(val & GDSC_POWER_UP_COMPLETE); > + else > + return !(val & GDSC_POWER_DOWN_COMPLETE); Make this into if (en) return ... return ... > +} > + > +static int gdsc_poll_cfg_status(struct gdsc *sc, bool en) > +{ > + ktime_t start = ktime_get(); > + ktime_t timeout = > + (sc->flags & GDS_TIMEOUT) ? TIMEOUT_US_GDS : TIMEOUT_US; > + > + do { > + if (gdsc_is_enabled_by_poll_cfg_reg(sc, en) == en) > + return 0; > + } while (ktime_us_delta(ktime_get(), start) < timeout); > + > + if (gdsc_is_enabled_by_poll_cfg_reg(sc, en) == en) > + return 0; > + > + return -ETIMEDOUT; > +} > + > static int gdsc_toggle_logic(struct gdsc *sc, bool en) > { > int ret; > @@ -106,6 +143,9 @@ static int gdsc_toggle_logic(struct gdsc *sc, bool en) > return 0; > } > > + if (sc->flags & POLL_CFG_GDSCR) > + return gdsc_poll_cfg_status(sc, en); > + > if (sc->gds_hw_ctrl) { > status_reg = sc->gds_hw_ctrl; > /* > @@ -258,8 +298,12 @@ static int gdsc_disable(struct generic_pm_domain *domain) > */ > udelay(1); > > - reg = sc->gds_hw_ctrl ? sc->gds_hw_ctrl : sc->gdscr; > - ret = gdsc_poll_status(sc, reg, true); > + if (sc->flags & POLL_CFG_GDSCR) { > + ret = gdsc_poll_cfg_status(sc, true); > + } else { > + reg = sc->gds_hw_ctrl ? sc->gds_hw_ctrl : sc->gdscr; > + ret = gdsc_poll_status(sc, reg, true); > + } Maybe this can be pushed into the gdsc_poll_status() function so that we can keep the "how do we poll status bit" logic in one place. > if (ret) > return ret; > } -- To unsubscribe from this list: send the line "unsubscribe linux-clk" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hello Stephen, Thanks for the review comments. On 4/6/2018 10:10 PM, Stephen Boyd wrote: > Quoting Taniya Das (2018-04-02 03:45:45) >> diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c >> index e89584e..e0c83ba 100644 >> --- a/drivers/clk/qcom/gdsc.c >> +++ b/drivers/clk/qcom/gdsc.c >> @@ -83,6 +88,38 @@ static int gdsc_poll_status(struct gdsc *sc, unsigned int reg, bool en) >> return -ETIMEDOUT; >> } >> >> +static int gdsc_is_enabled_by_poll_cfg_reg(struct gdsc *sc, bool en) >> +{ >> + u32 val; >> + int ret; >> + >> + ret = regmap_read(sc->regmap, sc->gdscr + CFG_GDSCR_OFFSET, &val); >> + if (ret) >> + return ret; >> + >> + if (en) >> + return !!(val & GDSC_POWER_UP_COMPLETE); >> + else >> + return !(val & GDSC_POWER_DOWN_COMPLETE); > > Make this into > > if (en) > return ... > > return ... > Will fix this in the next series. >> +} >> + >> +static int gdsc_poll_cfg_status(struct gdsc *sc, bool en) >> +{ >> + ktime_t start = ktime_get(); >> + ktime_t timeout = >> + (sc->flags & GDS_TIMEOUT) ? TIMEOUT_US_GDS : TIMEOUT_US; >> + >> + do { >> + if (gdsc_is_enabled_by_poll_cfg_reg(sc, en) == en) >> + return 0; >> + } while (ktime_us_delta(ktime_get(), start) < timeout); >> + >> + if (gdsc_is_enabled_by_poll_cfg_reg(sc, en) == en) >> + return 0; >> + >> + return -ETIMEDOUT; >> +} >> + >> static int gdsc_toggle_logic(struct gdsc *sc, bool en) >> { >> int ret; >> @@ -106,6 +143,9 @@ static int gdsc_toggle_logic(struct gdsc *sc, bool en) >> return 0; >> } >> >> + if (sc->flags & POLL_CFG_GDSCR) >> + return gdsc_poll_cfg_status(sc, en); >> + >> if (sc->gds_hw_ctrl) { >> status_reg = sc->gds_hw_ctrl; >> /* >> @@ -258,8 +298,12 @@ static int gdsc_disable(struct generic_pm_domain *domain) >> */ >> udelay(1); >> >> - reg = sc->gds_hw_ctrl ? sc->gds_hw_ctrl : sc->gdscr; >> - ret = gdsc_poll_status(sc, reg, true); >> + if (sc->flags & POLL_CFG_GDSCR) { >> + ret = gdsc_poll_cfg_status(sc, true); >> + } else { >> + reg = sc->gds_hw_ctrl ? sc->gds_hw_ctrl : sc->gdscr; >> + ret = gdsc_poll_status(sc, reg, true); >> + } > > Maybe this can be pushed into the gdsc_poll_status() function so that > we can keep the "how do we poll status bit" logic in one place. > Yes, I will push the logic in the gdsc_poll_status() in the next series. >> if (ret) >> return ret; >> }
diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index e89584e..e0c83ba 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -33,6 +33,11 @@ #define GMEM_CLAMP_IO_MASK BIT(0) #define GMEM_RESET_MASK BIT(4) +/* CFG_GDSCR */ +#define GDSC_POWER_UP_COMPLETE BIT(16) +#define GDSC_POWER_DOWN_COMPLETE BIT(15) +#define CFG_GDSCR_OFFSET 0x4 + /* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */ #define EN_REST_WAIT_VAL (0x2 << 20) #define EN_FEW_WAIT_VAL (0x8 << 16) @@ -83,6 +88,38 @@ static int gdsc_poll_status(struct gdsc *sc, unsigned int reg, bool en) return -ETIMEDOUT; } +static int gdsc_is_enabled_by_poll_cfg_reg(struct gdsc *sc, bool en) +{ + u32 val; + int ret; + + ret = regmap_read(sc->regmap, sc->gdscr + CFG_GDSCR_OFFSET, &val); + if (ret) + return ret; + + if (en) + return !!(val & GDSC_POWER_UP_COMPLETE); + else + return !(val & GDSC_POWER_DOWN_COMPLETE); +} + +static int gdsc_poll_cfg_status(struct gdsc *sc, bool en) +{ + ktime_t start = ktime_get(); + ktime_t timeout = + (sc->flags & GDS_TIMEOUT) ? TIMEOUT_US_GDS : TIMEOUT_US; + + do { + if (gdsc_is_enabled_by_poll_cfg_reg(sc, en) == en) + return 0; + } while (ktime_us_delta(ktime_get(), start) < timeout); + + if (gdsc_is_enabled_by_poll_cfg_reg(sc, en) == en) + return 0; + + return -ETIMEDOUT; +} + static int gdsc_toggle_logic(struct gdsc *sc, bool en) { int ret; @@ -106,6 +143,9 @@ static int gdsc_toggle_logic(struct gdsc *sc, bool en) return 0; } + if (sc->flags & POLL_CFG_GDSCR) + return gdsc_poll_cfg_status(sc, en); + if (sc->gds_hw_ctrl) { status_reg = sc->gds_hw_ctrl; /* @@ -258,8 +298,12 @@ static int gdsc_disable(struct generic_pm_domain *domain) */ udelay(1); - reg = sc->gds_hw_ctrl ? sc->gds_hw_ctrl : sc->gdscr; - ret = gdsc_poll_status(sc, reg, true); + if (sc->flags & POLL_CFG_GDSCR) { + ret = gdsc_poll_cfg_status(sc, true); + } else { + reg = sc->gds_hw_ctrl ? sc->gds_hw_ctrl : sc->gdscr; + ret = gdsc_poll_status(sc, reg, true); + } if (ret) return ret; } diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h index 2e3abbf..a74f715 100644 --- a/drivers/clk/qcom/gdsc.h +++ b/drivers/clk/qcom/gdsc.h @@ -56,6 +56,7 @@ struct gdsc { #define SW_RESET BIT(3) #define AON_RESET BIT(4) #define GDS_TIMEOUT BIT(5) +#define POLL_CFG_GDSCR BIT(6) struct reset_controller_dev *rcdev; unsigned int *resets; unsigned int reset_count;