diff options
-rw-r--r-- | drivers/clk/qcom/gdsc.c | 42 | ||||
-rw-r--r-- | drivers/clk/qcom/gdsc.h | 1 |
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 | ||
48 | static int gdsc_is_enabled(struct gdsc *sc, unsigned int reg) | 53 | static 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 | ||
67 | static int gdsc_poll_status(struct gdsc *sc, unsigned int reg, bool en) | 85 | static 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 | ||
122 | static inline int gdsc_deassert_reset(struct gdsc *sc) | 137 | static 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; |