clk: qcom: gdsc: Implement NO_RET_PERIPH flag
authorAngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Wed, 13 Jan 2021 18:38:15 +0000 (19:38 +0100)
committerStephen Boyd <sboyd@kernel.org>
Sun, 14 Feb 2021 20:56:54 +0000 (12:56 -0800)
In some rare occasions, we want to only set the RETAIN_MEM bit, but
not the RETAIN_PERIPH one: this is seen on at least SDM630/636/660's
GPU-GX GDSC, where unsetting and setting back the RETAIN_PERIPH bit
will generate chaos and panics during GPU suspend time (mainly, the
chaos is unaligned access).

For this reason, introduce a new NO_RET_PERIPH flag to the GDSC
driver to address this corner case.

Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
Link: https://lore.kernel.org/r/20210113183817.447866-8-angelogioacchino.delregno@somainline.org
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
drivers/clk/qcom/gdsc.c
drivers/clk/qcom/gdsc.h

index af26e06..51ed640 100644 (file)
@@ -183,7 +183,10 @@ static inline int gdsc_assert_reset(struct gdsc *sc)
 static inline void gdsc_force_mem_on(struct gdsc *sc)
 {
        int i;
-       u32 mask = RETAIN_MEM | RETAIN_PERIPH;
+       u32 mask = RETAIN_MEM;
+
+       if (!(sc->flags & NO_RET_PERIPH))
+               mask |= RETAIN_PERIPH;
 
        for (i = 0; i < sc->cxc_count; i++)
                regmap_update_bits(sc->regmap, sc->cxcs[i], mask, mask);
@@ -192,7 +195,10 @@ static inline void gdsc_force_mem_on(struct gdsc *sc)
 static inline void gdsc_clear_mem_on(struct gdsc *sc)
 {
        int i;
-       u32 mask = RETAIN_MEM | RETAIN_PERIPH;
+       u32 mask = RETAIN_MEM;
+
+       if (!(sc->flags & NO_RET_PERIPH))
+               mask |= RETAIN_PERIPH;
 
        for (i = 0; i < sc->cxc_count; i++)
                regmap_update_bits(sc->regmap, sc->cxcs[i], mask, 0);
index bd53743..5bb396b 100644 (file)
@@ -42,7 +42,7 @@ struct gdsc {
 #define PWRSTS_ON              BIT(2)
 #define PWRSTS_OFF_ON          (PWRSTS_OFF | PWRSTS_ON)
 #define PWRSTS_RET_ON          (PWRSTS_RET | PWRSTS_ON)
-       const u                       flags;
+       const u16                       flags;
 #define VOTABLE                BIT(0)
 #define CLAMP_IO       BIT(1)
 #define HW_CTRL                BIT(2)
@@ -51,6 +51,7 @@ struct gdsc {
 #define POLL_CFG_GDSCR BIT(5)
 #define ALWAYS_ON      BIT(6)
 #define RETAIN_FF_ENABLE       BIT(7)
+#define NO_RET_PERIPH  BIT(8)
        struct reset_controller_dev     *rcdev;
        unsigned int                    *resets;
        unsigned int                    reset_count;