aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/qcom/gdsc.c42
-rw-r--r--drivers/clk/qcom/gdsc.h1
2 files changed, 27 insertions, 16 deletions
diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c
index cb61c1590e9c..2a6b0ff7d451 100644
--- a/drivers/clk/qcom/gdsc.c
+++ b/drivers/clk/qcom/gdsc.c
@@ -33,6 +33,11 @@
33#define GMEM_CLAMP_IO_MASK BIT(0) 33#define GMEM_CLAMP_IO_MASK BIT(0)
34#define GMEM_RESET_MASK BIT(4) 34#define GMEM_RESET_MASK BIT(4)
35 35
36/* CFG_GDSCR */
37#define GDSC_POWER_UP_COMPLETE BIT(16)
38#define GDSC_POWER_DOWN_COMPLETE BIT(15)
39#define CFG_GDSCR_OFFSET 0x4
40
36/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */ 41/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
37#define EN_REST_WAIT_VAL (0x2 << 20) 42#define EN_REST_WAIT_VAL (0x2 << 20)
38#define EN_FEW_WAIT_VAL (0x8 << 16) 43#define EN_FEW_WAIT_VAL (0x8 << 16)
@@ -45,15 +50,28 @@
45 50
46#define domain_to_gdsc(domain) container_of(domain, struct gdsc, pd) 51#define domain_to_gdsc(domain) container_of(domain, struct gdsc, pd)
47 52
48static int gdsc_is_enabled(struct gdsc *sc, unsigned int reg) 53static int gdsc_is_enabled(struct gdsc *sc, bool en)
49{ 54{
55 unsigned int reg;
50 u32 val; 56 u32 val;
51 int ret; 57 int ret;
52 58
59 if (sc->flags & POLL_CFG_GDSCR)
60 reg = sc->gdscr + CFG_GDSCR_OFFSET;
61 else
62 reg = sc->gds_hw_ctrl ? sc->gds_hw_ctrl : sc->gdscr;
63
53 ret = regmap_read(sc->regmap, reg, &val); 64 ret = regmap_read(sc->regmap, reg, &val);
54 if (ret) 65 if (ret)
55 return ret; 66 return ret;
56 67
68 if (sc->flags & POLL_CFG_GDSCR) {
69 if (en)
70 return !!(val & GDSC_POWER_UP_COMPLETE);
71 else
72 return !(val & GDSC_POWER_DOWN_COMPLETE);
73 }
74
57 return !!(val & PWR_ON_MASK); 75 return !!(val & PWR_ON_MASK);
58} 76}
59 77
@@ -64,17 +82,17 @@ static int gdsc_hwctrl(struct gdsc *sc, bool en)
64 return regmap_update_bits(sc->regmap, sc->gdscr, HW_CONTROL_MASK, val); 82 return regmap_update_bits(sc->regmap, sc->gdscr, HW_CONTROL_MASK, val);
65} 83}
66 84
67static int gdsc_poll_status(struct gdsc *sc, unsigned int reg, bool en) 85static int gdsc_poll_status(struct gdsc *sc, bool en)
68{ 86{
69 ktime_t start; 87 ktime_t start;
70 88
71 start = ktime_get(); 89 start = ktime_get();
72 do { 90 do {
73 if (gdsc_is_enabled(sc, reg) == en) 91 if (gdsc_is_enabled(sc, en) == en)
74 return 0; 92 return 0;
75 } while (ktime_us_delta(ktime_get(), start) < TIMEOUT_US); 93 } while (ktime_us_delta(ktime_get(), start) < TIMEOUT_US);
76 94
77 if (gdsc_is_enabled(sc, reg) == en) 95 if (gdsc_is_enabled(sc, en) == en)
78 return 0; 96 return 0;
79 97
80 return -ETIMEDOUT; 98 return -ETIMEDOUT;
@@ -84,7 +102,6 @@ static int gdsc_toggle_logic(struct gdsc *sc, bool en)
84{ 102{
85 int ret; 103 int ret;
86 u32 val = en ? 0 : SW_COLLAPSE_MASK; 104 u32 val = en ? 0 : SW_COLLAPSE_MASK;
87 unsigned int status_reg = sc->gdscr;
88 105
89 ret = regmap_update_bits(sc->regmap, sc->gdscr, SW_COLLAPSE_MASK, val); 106 ret = regmap_update_bits(sc->regmap, sc->gdscr, SW_COLLAPSE_MASK, val);
90 if (ret) 107 if (ret)
@@ -101,8 +118,7 @@ static int gdsc_toggle_logic(struct gdsc *sc, bool en)
101 return 0; 118 return 0;
102 } 119 }
103 120
104 if (sc->gds_hw_ctrl) { 121 if (sc->gds_hw_ctrl)
105 status_reg = sc->gds_hw_ctrl;
106 /* 122 /*
107 * The gds hw controller asserts/de-asserts the status bit soon 123 * The gds hw controller asserts/de-asserts the status bit soon
108 * after it receives a power on/off request from a master. 124 * after it receives a power on/off request from a master.
@@ -114,9 +130,8 @@ static int gdsc_toggle_logic(struct gdsc *sc, bool en)
114 * and polling the status bit. 130 * and polling the status bit.
115 */ 131 */
116 udelay(1); 132 udelay(1);
117 }
118 133
119 return gdsc_poll_status(sc, status_reg, en); 134 return gdsc_poll_status(sc, en);
120} 135}
121 136
122static inline int gdsc_deassert_reset(struct gdsc *sc) 137static inline int gdsc_deassert_reset(struct gdsc *sc)
@@ -240,8 +255,6 @@ static int gdsc_disable(struct generic_pm_domain *domain)
240 255
241 /* Turn off HW trigger mode if supported */ 256 /* Turn off HW trigger mode if supported */
242 if (sc->flags & HW_CTRL) { 257 if (sc->flags & HW_CTRL) {
243 unsigned int reg;
244
245 ret = gdsc_hwctrl(sc, false); 258 ret = gdsc_hwctrl(sc, false);
246 if (ret < 0) 259 if (ret < 0)
247 return ret; 260 return ret;
@@ -253,8 +266,7 @@ static int gdsc_disable(struct generic_pm_domain *domain)
253 */ 266 */
254 udelay(1); 267 udelay(1);
255 268
256 reg = sc->gds_hw_ctrl ? sc->gds_hw_ctrl : sc->gdscr; 269 ret = gdsc_poll_status(sc, true);
257 ret = gdsc_poll_status(sc, reg, true);
258 if (ret) 270 if (ret)
259 return ret; 271 return ret;
260 } 272 }
@@ -276,7 +288,6 @@ static int gdsc_init(struct gdsc *sc)
276{ 288{
277 u32 mask, val; 289 u32 mask, val;
278 int on, ret; 290 int on, ret;
279 unsigned int reg;
280 291
281 /* 292 /*
282 * Disable HW trigger: collapse/restore occur based on registers writes. 293 * Disable HW trigger: collapse/restore occur based on registers writes.
@@ -297,8 +308,7 @@ static int gdsc_init(struct gdsc *sc)
297 return ret; 308 return ret;
298 } 309 }
299 310
300 reg = sc->gds_hw_ctrl ? sc->gds_hw_ctrl : sc->gdscr; 311 on = gdsc_is_enabled(sc, true);
301 on = gdsc_is_enabled(sc, reg);
302 if (on < 0) 312 if (on < 0)
303 return on; 313 return on;
304 314
diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h
index 9279278535cd..b0cbb87dd02b 100644
--- a/drivers/clk/qcom/gdsc.h
+++ b/drivers/clk/qcom/gdsc.h
@@ -55,6 +55,7 @@ struct gdsc {
55#define HW_CTRL BIT(2) 55#define HW_CTRL BIT(2)
56#define SW_RESET BIT(3) 56#define SW_RESET BIT(3)
57#define AON_RESET BIT(4) 57#define AON_RESET BIT(4)
58#define POLL_CFG_GDSCR BIT(5)
58 struct reset_controller_dev *rcdev; 59 struct reset_controller_dev *rcdev;
59 unsigned int *resets; 60 unsigned int *resets;
60 unsigned int reset_count; 61 unsigned int reset_count;