Skip to content
This repository has been archived by the owner on Nov 21, 2022. It is now read-only.

Commit

Permalink
clk: qcom: gdsc: enable optional power domain support
Browse files Browse the repository at this point in the history
On sm8250 dispcc and videocc registers are powered up by the MMCX power
domain. Currently we use a regulator to enable this domain on demand,
however this has some consequences, as genpd code is not reentrant.

Make gdsc code also use pm_runtime calls to ensure that registers are
accessible during the gdsc_enable/gdsc_disable operations.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Link: https://lore.kernel.org/r/20210829154757.784699-6-dmitry.baryshkov@linaro.org
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
  • Loading branch information
lumag authored and bebarino committed Oct 15, 2021
1 parent a91c483 commit 1b77183
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
51 changes: 48 additions & 3 deletions drivers/clk/qcom/gdsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/ktime.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/reset-controller.h>
Expand Down Expand Up @@ -50,6 +51,22 @@ enum gdsc_status {
GDSC_ON
};

static int gdsc_pm_runtime_get(struct gdsc *sc)
{
if (!sc->dev)
return 0;

return pm_runtime_resume_and_get(sc->dev);
}

static int gdsc_pm_runtime_put(struct gdsc *sc)
{
if (!sc->dev)
return 0;

return pm_runtime_put_sync(sc->dev);
}

/* Returns 1 if GDSC status is status, 0 if not, and < 0 on error */
static int gdsc_check_status(struct gdsc *sc, enum gdsc_status status)
{
Expand Down Expand Up @@ -232,9 +249,8 @@ static void gdsc_retain_ff_on(struct gdsc *sc)
regmap_update_bits(sc->regmap, sc->gdscr, mask, mask);
}

static int gdsc_enable(struct generic_pm_domain *domain)
static int _gdsc_enable(struct gdsc *sc)
{
struct gdsc *sc = domain_to_gdsc(domain);
int ret;

if (sc->pwrsts == PWRSTS_ON)
Expand Down Expand Up @@ -290,11 +306,22 @@ static int gdsc_enable(struct generic_pm_domain *domain)
return 0;
}

static int gdsc_disable(struct generic_pm_domain *domain)
static int gdsc_enable(struct generic_pm_domain *domain)
{
struct gdsc *sc = domain_to_gdsc(domain);
int ret;

ret = gdsc_pm_runtime_get(sc);
if (ret)
return ret;

return _gdsc_enable(sc);
}

static int _gdsc_disable(struct gdsc *sc)
{
int ret;

if (sc->pwrsts == PWRSTS_ON)
return gdsc_assert_reset(sc);

Expand Down Expand Up @@ -329,6 +356,18 @@ static int gdsc_disable(struct generic_pm_domain *domain)
return 0;
}

static int gdsc_disable(struct generic_pm_domain *domain)
{
struct gdsc *sc = domain_to_gdsc(domain);
int ret;

ret = _gdsc_disable(sc);

gdsc_pm_runtime_put(sc);

return ret;
}

static int gdsc_init(struct gdsc *sc)
{
u32 mask, val;
Expand Down Expand Up @@ -443,6 +482,8 @@ int gdsc_register(struct gdsc_desc *desc,
for (i = 0; i < num; i++) {
if (!scs[i])
continue;
if (pm_runtime_enabled(dev))
scs[i]->dev = dev;
scs[i]->regmap = regmap;
scs[i]->rcdev = rcdev;
ret = gdsc_init(scs[i]);
Expand All @@ -457,6 +498,8 @@ int gdsc_register(struct gdsc_desc *desc,
continue;
if (scs[i]->parent)
pm_genpd_add_subdomain(scs[i]->parent, &scs[i]->pd);
else if (!IS_ERR_OR_NULL(dev->pm_domain))
pm_genpd_add_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd);
}

return of_genpd_add_provider_onecell(dev->of_node, data);
Expand All @@ -475,6 +518,8 @@ void gdsc_unregister(struct gdsc_desc *desc)
continue;
if (scs[i]->parent)
pm_genpd_remove_subdomain(scs[i]->parent, &scs[i]->pd);
else if (!IS_ERR_OR_NULL(dev->pm_domain))
pm_genpd_remove_subdomain(pd_to_genpd(dev->pm_domain), &scs[i]->pd);
}
of_genpd_del_provider(dev->of_node);
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/clk/qcom/gdsc.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct reset_controller_dev;
* @resets: ids of resets associated with this gdsc
* @reset_count: number of @resets
* @rcdev: reset controller
* @dev: the device holding the GDSC, used for pm_runtime calls
*/
struct gdsc {
struct generic_pm_domain pd;
Expand Down Expand Up @@ -58,6 +59,7 @@ struct gdsc {

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

struct gdsc_desc {
Expand Down

0 comments on commit 1b77183

Please sign in to comment.