lkml.org 
[lkml]   [2018]   [Apr]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 3/3] clk: qcom: gdsc: Add support to poll CFG register to check GDSC state
    Date
    From: Amit Nischal <anischal@codeaurora.org>

    The default behavior of the GDSC enable/disable sequence is to
    poll the status bits of either the actual GDSCR or the
    corresponding HW_CTRL registers.

    On targets which have support for a CFG_GDSCR register, the
    status bits might not show the correct state of the GDSC,
    especially in the disable sequence, where the status bit
    will be cleared even before the core is completely power
    collapsed. On targets with this issue, poll the power on/off
    bits in the CFG_GDSCR register instead to correctly determine
    the GDSC state.

    Signed-off-by: Amit Nischal <anischal@codeaurora.org>
    Signed-off-by: Taniya Das <tdas@codeaurora.org>
    ---
    drivers/clk/qcom/gdsc.c | 39 +++++++++++++++++++++++++++++++++++----
    drivers/clk/qcom/gdsc.h | 1 +
    2 files changed, 36 insertions(+), 4 deletions(-)

    diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c
    index cb61c15..2dda2d5 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)
    @@ -64,18 +69,43 @@ static int gdsc_hwctrl(struct gdsc *sc, bool en)
    return regmap_update_bits(sc->regmap, sc->gdscr, HW_CONTROL_MASK, val);
    }

    +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);
    +
    + return !(val & GDSC_POWER_DOWN_COMPLETE);
    +}
    +
    static int gdsc_poll_status(struct gdsc *sc, unsigned int reg, bool en)
    {
    ktime_t start;

    start = ktime_get();
    do {
    - if (gdsc_is_enabled(sc, reg) == en)
    - return 0;
    + if (sc->flags & POLL_CFG_GDSCR) {
    + if (gdsc_is_enabled_by_poll_cfg_reg(sc, en) == en)
    + return 0;
    + } else {
    + if (gdsc_is_enabled(sc, reg) == en)
    + return 0;
    + }
    } while (ktime_us_delta(ktime_get(), start) < TIMEOUT_US);

    - if (gdsc_is_enabled(sc, reg) == en)
    - return 0;
    + if (sc->flags & POLL_CFG_GDSCR) {
    + if (gdsc_is_enabled_by_poll_cfg_reg(sc, en) == en)
    + return 0;
    + } else {
    + if (gdsc_is_enabled(sc, reg) == en)
    + return 0;
    + }

    return -ETIMEDOUT;
    }
    @@ -254,6 +284,7 @@ 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 (ret)
    return ret;
    diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h
    index 9279278..0f992e8 100644
    --- a/drivers/clk/qcom/gdsc.h
    +++ b/drivers/clk/qcom/gdsc.h
    @@ -55,6 +55,7 @@ struct gdsc {
    #define HW_CTRL BIT(2)
    #define SW_RESET BIT(3)
    #define AON_RESET BIT(4)
    +#define POLL_CFG_GDSCR BIT(5)
    struct reset_controller_dev *rcdev;
    unsigned int *resets;
    unsigned int reset_count;
    --
    Qualcomm INDIA, on behalf of Qualcomm Innovation Center, Inc.is a member
    of the Code Aurora Forum, hosted by the Linux Foundation.
    \
     
     \ /
      Last update: 2018-04-09 10:43    [W:2.856 / U:0.176 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site