提交 d909072d 编写于 作者: J Jeffy Chen 提交者: Heiko Stuebner

soc: rockchip: power-domain: use clk_bulk APIs

Use clk_bulk APIs, and also add error handling for clk enable.
Signed-off-by: NJeffy Chen <jeffy.chen@rock-chips.com>
Signed-off-by: NHeiko Stuebner <heiko@sntech.de>
上级 6e61c891
...@@ -67,7 +67,7 @@ struct rockchip_pm_domain { ...@@ -67,7 +67,7 @@ struct rockchip_pm_domain {
struct regmap **qos_regmap; struct regmap **qos_regmap;
u32 *qos_save_regs[MAX_QOS_REGS_NUM]; u32 *qos_save_regs[MAX_QOS_REGS_NUM];
int num_clks; int num_clks;
struct clk *clks[]; struct clk_bulk_data *clks;
}; };
struct rockchip_pmu { struct rockchip_pmu {
...@@ -274,13 +274,18 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, ...@@ -274,13 +274,18 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
{ {
int i; struct rockchip_pmu *pmu = pd->pmu;
int ret;
mutex_lock(&pd->pmu->mutex); mutex_lock(&pmu->mutex);
if (rockchip_pmu_domain_is_on(pd) != power_on) { if (rockchip_pmu_domain_is_on(pd) != power_on) {
for (i = 0; i < pd->num_clks; i++) ret = clk_bulk_enable(pd->num_clks, pd->clks);
clk_enable(pd->clks[i]); if (ret < 0) {
dev_err(pmu->dev, "failed to enable clocks\n");
mutex_unlock(&pmu->mutex);
return ret;
}
if (!power_on) { if (!power_on) {
rockchip_pmu_save_qos(pd); rockchip_pmu_save_qos(pd);
...@@ -298,11 +303,10 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) ...@@ -298,11 +303,10 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
rockchip_pmu_restore_qos(pd); rockchip_pmu_restore_qos(pd);
} }
for (i = pd->num_clks - 1; i >= 0; i--) clk_bulk_disable(pd->num_clks, pd->clks);
clk_disable(pd->clks[i]);
} }
mutex_unlock(&pd->pmu->mutex); mutex_unlock(&pmu->mutex);
return 0; return 0;
} }
...@@ -364,8 +368,6 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, ...@@ -364,8 +368,6 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
const struct rockchip_domain_info *pd_info; const struct rockchip_domain_info *pd_info;
struct rockchip_pm_domain *pd; struct rockchip_pm_domain *pd;
struct device_node *qos_node; struct device_node *qos_node;
struct clk *clk;
int clk_cnt;
int i, j; int i, j;
u32 id; u32 id;
int error; int error;
...@@ -391,41 +393,36 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, ...@@ -391,41 +393,36 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
return -EINVAL; return -EINVAL;
} }
clk_cnt = of_count_phandle_with_args(node, "clocks", "#clock-cells"); pd = devm_kzalloc(pmu->dev, sizeof(*pd), GFP_KERNEL);
pd = devm_kzalloc(pmu->dev,
sizeof(*pd) + clk_cnt * sizeof(pd->clks[0]),
GFP_KERNEL);
if (!pd) if (!pd)
return -ENOMEM; return -ENOMEM;
pd->info = pd_info; pd->info = pd_info;
pd->pmu = pmu; pd->pmu = pmu;
for (i = 0; i < clk_cnt; i++) { pd->num_clks = of_count_phandle_with_args(node, "clocks",
clk = of_clk_get(node, i); "#clock-cells");
if (IS_ERR(clk)) {
error = PTR_ERR(clk); pd->clks = devm_kcalloc(pmu->dev, pd->num_clks, sizeof(*pd->clks),
GFP_KERNEL);
if (!pd->clks)
return -ENOMEM;
for (i = 0; i < pd->num_clks; i++) {
pd->clks[i].clk = of_clk_get(node, i);
if (IS_ERR(pd->clks[i].clk)) {
error = PTR_ERR(pd->clks[i].clk);
dev_err(pmu->dev, dev_err(pmu->dev,
"%s: failed to get clk at index %d: %d\n", "%s: failed to get clk at index %d: %d\n",
node->name, i, error); node->name, i, error);
goto err_out; return error;
}
error = clk_prepare(clk);
if (error) {
dev_err(pmu->dev,
"%s: failed to prepare clk %pC (index %d): %d\n",
node->name, clk, i, error);
clk_put(clk);
goto err_out;
} }
pd->clks[pd->num_clks++] = clk;
dev_dbg(pmu->dev, "added clock '%pC' to domain '%s'\n",
clk, node->name);
} }
error = clk_bulk_prepare(pd->num_clks, pd->clks);
if (error)
goto err_put_clocks;
pd->num_qos = of_count_phandle_with_args(node, "pm_qos", pd->num_qos = of_count_phandle_with_args(node, "pm_qos",
NULL); NULL);
...@@ -435,7 +432,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, ...@@ -435,7 +432,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
GFP_KERNEL); GFP_KERNEL);
if (!pd->qos_regmap) { if (!pd->qos_regmap) {
error = -ENOMEM; error = -ENOMEM;
goto err_out; goto err_unprepare_clocks;
} }
for (j = 0; j < MAX_QOS_REGS_NUM; j++) { for (j = 0; j < MAX_QOS_REGS_NUM; j++) {
...@@ -445,7 +442,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, ...@@ -445,7 +442,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
GFP_KERNEL); GFP_KERNEL);
if (!pd->qos_save_regs[j]) { if (!pd->qos_save_regs[j]) {
error = -ENOMEM; error = -ENOMEM;
goto err_out; goto err_unprepare_clocks;
} }
} }
...@@ -453,13 +450,13 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, ...@@ -453,13 +450,13 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
qos_node = of_parse_phandle(node, "pm_qos", j); qos_node = of_parse_phandle(node, "pm_qos", j);
if (!qos_node) { if (!qos_node) {
error = -ENODEV; error = -ENODEV;
goto err_out; goto err_unprepare_clocks;
} }
pd->qos_regmap[j] = syscon_node_to_regmap(qos_node); pd->qos_regmap[j] = syscon_node_to_regmap(qos_node);
if (IS_ERR(pd->qos_regmap[j])) { if (IS_ERR(pd->qos_regmap[j])) {
error = -ENODEV; error = -ENODEV;
of_node_put(qos_node); of_node_put(qos_node);
goto err_out; goto err_unprepare_clocks;
} }
of_node_put(qos_node); of_node_put(qos_node);
} }
...@@ -470,7 +467,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, ...@@ -470,7 +467,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
dev_err(pmu->dev, dev_err(pmu->dev,
"failed to power on domain '%s': %d\n", "failed to power on domain '%s': %d\n",
node->name, error); node->name, error);
goto err_out; goto err_unprepare_clocks;
} }
pd->genpd.name = node->name; pd->genpd.name = node->name;
...@@ -486,17 +483,16 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, ...@@ -486,17 +483,16 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
pmu->genpd_data.domains[id] = &pd->genpd; pmu->genpd_data.domains[id] = &pd->genpd;
return 0; return 0;
err_out: err_unprepare_clocks:
while (--i >= 0) { clk_bulk_unprepare(pd->num_clks, pd->clks);
clk_unprepare(pd->clks[i]); err_put_clocks:
clk_put(pd->clks[i]); clk_bulk_put(pd->num_clks, pd->clks);
}
return error; return error;
} }
static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd) static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd)
{ {
int i, ret; int ret;
/* /*
* We're in the error cleanup already, so we only complain, * We're in the error cleanup already, so we only complain,
...@@ -507,10 +503,8 @@ static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd) ...@@ -507,10 +503,8 @@ static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd)
dev_err(pd->pmu->dev, "failed to remove domain '%s' : %d - state may be inconsistent\n", dev_err(pd->pmu->dev, "failed to remove domain '%s' : %d - state may be inconsistent\n",
pd->genpd.name, ret); pd->genpd.name, ret);
for (i = 0; i < pd->num_clks; i++) { clk_bulk_unprepare(pd->num_clks, pd->clks);
clk_unprepare(pd->clks[i]); clk_bulk_put(pd->num_clks, pd->clks);
clk_put(pd->clks[i]);
}
/* protect the zeroing of pm->num_clks */ /* protect the zeroing of pm->num_clks */
mutex_lock(&pd->pmu->mutex); mutex_lock(&pd->pmu->mutex);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册