Skip to content

Commit

Permalink
clk: qcom: gdsc: Handle GDSC regulator supplies
Browse files Browse the repository at this point in the history
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 <bjorn.andersson@linaro.org>
Link: https://lkml.kernel.org/r/20200417070044.1376212-2-bjorn.andersson@linaro.org
Reviewed-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
  • Loading branch information
andersson authored and bebarino committed May 14, 2020
1 parent f47ab3c commit 37416e5
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 0 deletions.
23 changes: 23 additions & 0 deletions drivers/clk/qcom/gdsc.c
Expand Up @@ -11,6 +11,7 @@
#include <linux/ktime.h>
#include <linux/pm_domain.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include "gdsc.h"
Expand Down Expand Up @@ -112,6 +113,12 @@ static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status)
int ret;
u32 val = (status == GDSC_ON) ? 0 : SW_COLLAPSE_MASK;

if (status == GDSC_ON && sc->rsupply) {
ret = regulator_enable(sc->rsupply);
if (ret < 0)
return ret;
}

ret = regmap_update_bits(sc->regmap, sc->gdscr, SW_COLLAPSE_MASK, val);
if (ret)
return ret;
Expand Down Expand Up @@ -143,6 +150,13 @@ static int gdsc_toggle_logic(struct gdsc *sc, enum gdsc_status status)

ret = gdsc_poll_status(sc, status);
WARN(ret, "%s status stuck at 'o%s'", sc->pd.name, status ? "ff" : "n");

if (!ret && status == GDSC_OFF && sc->rsupply) {
ret = regulator_disable(sc->rsupply);
if (ret < 0)
return ret;
}

return ret;
}

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

for (i = 0; i < num; i++) {
if (!scs[i] || !scs[i]->supply)
continue;

scs[i]->rsupply = devm_regulator_get(dev, scs[i]->supply);
if (IS_ERR(scs[i]->rsupply))
return PTR_ERR(scs[i]->rsupply);
}

data->num_domains = num;
for (i = 0; i < num; i++) {
if (!scs[i])
Expand Down
4 changes: 4 additions & 0 deletions drivers/clk/qcom/gdsc.h
Expand Up @@ -10,6 +10,7 @@
#include <linux/pm_domain.h>

struct regmap;
struct regulator;
struct reset_controller_dev;

/**
Expand Down Expand Up @@ -52,6 +53,9 @@ struct gdsc {
struct reset_controller_dev *rcdev;
unsigned int *resets;
unsigned int reset_count;

const char *supply;
struct regulator *rsupply;
};

struct gdsc_desc {
Expand Down

0 comments on commit 37416e5

Please sign in to comment.