Skip to content

Commit 37416e5

Browse files
anderssonbebarino
authored andcommitted
clk: qcom: gdsc: Handle GDSC regulator supplies
Certain GDSCs, such as the GPU_GX on MSM8996, requires that the upstream regulator supply is powered in order to be turned on. It's not guaranteed that the bootloader will leave these supplies on and the driver core will attempt to enable any GDSCs before allowing the individual drivers to probe defer on the PMIC regulator driver not yet being present. So the gdsc driver needs to be made aware of supplying regulators and probe defer on their absence, and it needs to enable and disable the regulator accordingly. Voltage adjustments of the supplying regulator are deferred to the client drivers themselves. Signed-off-by: Bjorn Andersson <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Reviewed-by: Vinod Koul <[email protected]> Signed-off-by: Stephen Boyd <[email protected]>
1 parent f47ab3c commit 37416e5

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

drivers/clk/qcom/gdsc.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/ktime.h>
1212
#include <linux/pm_domain.h>
1313
#include <linux/regmap.h>
14+
#include <linux/regulator/consumer.h>
1415
#include <linux/reset-controller.h>
1516
#include <linux/slab.h>
1617
#include "gdsc.h"
@@ -112,6 +113,12 @@ static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status)
112113
int ret;
113114
u32 val = (status == GDSC_ON) ? 0 : SW_COLLAPSE_MASK;
114115

116+
if (status == GDSC_ON && sc->rsupply) {
117+
ret = regulator_enable(sc->rsupply);
118+
if (ret < 0)
119+
return ret;
120+
}
121+
115122
ret = regmap_update_bits(sc->regmap, sc->gdscr, SW_COLLAPSE_MASK, val);
116123
if (ret)
117124
return ret;
@@ -143,6 +150,13 @@ static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status)
143150

144151
ret = gdsc_poll_status(sc, status);
145152
WARN(ret, "%s status stuck at 'o%s'", sc->pd.name, status ? "ff" : "n");
153+
154+
if (!ret && status == GDSC_OFF && sc->rsupply) {
155+
ret = regulator_disable(sc->rsupply);
156+
if (ret < 0)
157+
return ret;
158+
}
159+
146160
return ret;
147161
}
148162

@@ -371,6 +385,15 @@ int gdsc_register(struct gdsc_desc *desc,
371385
if (!data->domains)
372386
return -ENOMEM;
373387

388+
for (i = 0; i < num; i++) {
389+
if (!scs[i] || !scs[i]->supply)
390+
continue;
391+
392+
scs[i]->rsupply = devm_regulator_get(dev, scs[i]->supply);
393+
if (IS_ERR(scs[i]->rsupply))
394+
return PTR_ERR(scs[i]->rsupply);
395+
}
396+
374397
data->num_domains = num;
375398
for (i = 0; i < num; i++) {
376399
if (!scs[i])

drivers/clk/qcom/gdsc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/pm_domain.h>
1111

1212
struct regmap;
13+
struct regulator;
1314
struct reset_controller_dev;
1415

1516
/**
@@ -52,6 +53,9 @@ struct gdsc {
5253
struct reset_controller_dev *rcdev;
5354
unsigned int *resets;
5455
unsigned int reset_count;
56+
57+
const char *supply;
58+
struct regulator *rsupply;
5559
};
5660

5761
struct gdsc_desc {

0 commit comments

Comments
 (0)