diff options
author | Arnd Bergmann <arnd@arndb.de> | 2018-03-28 17:08:34 +0200 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2018-03-28 17:08:34 +0200 |
commit | 7df3f0bb5f90e3470de2798452000e221420059c (patch) | |
tree | dfd2220e8c23a86bd1b446bb30f7fca01d97f2fa | |
parent | Merge tag 'reset-for-4.17-2' of git://git.pengutronix.de/git/pza/linux into n... (diff) | |
parent | soc: rockchip: power-domain: Add a sanity check on pd->num_clks (diff) | |
download | linux-7df3f0bb5f90e3470de2798452000e221420059c.tar.xz linux-7df3f0bb5f90e3470de2798452000e221420059c.zip |
Merge tag 'v4.17-rockchip-drivers-1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip into next/drivers
Pull "Rockchip driver changes for 4.17" from Heiko Stübner:
Rockchip soc drivers containing conversion of the power-domain driver
to use the clk-bulk APIs and two more socs to disable jtag-switching.
On the plus-side the issue we see with that are _supposed_ to be fixed
in hardware in upcoming socs, so maybe this can be the last of those.
* tag 'v4.17-rockchip-drivers-1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip:
soc: rockchip: power-domain: Add a sanity check on pd->num_clks
soc: rockchip: power-domain: use clk_bulk APIs
soc: rockchip: disable jtag switching for RK3128 SoCs
soc: rockchip: disable jtag switching for RK3228/RK3229 SoCs
-rw-r--r-- | drivers/soc/rockchip/grf.c | 28 | ||||
-rw-r--r-- | drivers/soc/rockchip/pm_domains.c | 95 |
2 files changed, 75 insertions, 48 deletions
diff --git a/drivers/soc/rockchip/grf.c b/drivers/soc/rockchip/grf.c index 15e71fd6c513..96882ffde67e 100644 --- a/drivers/soc/rockchip/grf.c +++ b/drivers/soc/rockchip/grf.c @@ -43,6 +43,28 @@ static const struct rockchip_grf_info rk3036_grf __initconst = { .num_values = ARRAY_SIZE(rk3036_defaults), }; +#define RK3128_GRF_SOC_CON0 0x140 + +static const struct rockchip_grf_value rk3128_defaults[] __initconst = { + { "jtag switching", RK3128_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 8) }, +}; + +static const struct rockchip_grf_info rk3128_grf __initconst = { + .values = rk3128_defaults, + .num_values = ARRAY_SIZE(rk3128_defaults), +}; + +#define RK3228_GRF_SOC_CON6 0x418 + +static const struct rockchip_grf_value rk3228_defaults[] __initconst = { + { "jtag switching", RK3228_GRF_SOC_CON6, HIWORD_UPDATE(0, 1, 8) }, +}; + +static const struct rockchip_grf_info rk3228_grf __initconst = { + .values = rk3228_defaults, + .num_values = ARRAY_SIZE(rk3228_defaults), +}; + #define RK3288_GRF_SOC_CON0 0x244 static const struct rockchip_grf_value rk3288_defaults[] __initconst = { @@ -92,6 +114,12 @@ static const struct of_device_id rockchip_grf_dt_match[] __initconst = { .compatible = "rockchip,rk3036-grf", .data = (void *)&rk3036_grf, }, { + .compatible = "rockchip,rk3128-grf", + .data = (void *)&rk3128_grf, + }, { + .compatible = "rockchip,rk3228-grf", + .data = (void *)&rk3228_grf, + }, { .compatible = "rockchip,rk3288-grf", .data = (void *)&rk3288_grf, }, { diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 5c342167b9db..53efc386b1ad 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -67,7 +67,7 @@ struct rockchip_pm_domain { struct regmap **qos_regmap; u32 *qos_save_regs[MAX_QOS_REGS_NUM]; int num_clks; - struct clk *clks[]; + struct clk_bulk_data *clks; }; struct rockchip_pmu { @@ -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) { - 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) { - for (i = 0; i < pd->num_clks; i++) - clk_enable(pd->clks[i]); + ret = clk_bulk_enable(pd->num_clks, pd->clks); + if (ret < 0) { + dev_err(pmu->dev, "failed to enable clocks\n"); + mutex_unlock(&pmu->mutex); + return ret; + } if (!power_on) { rockchip_pmu_save_qos(pd); @@ -298,11 +303,10 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on) rockchip_pmu_restore_qos(pd); } - for (i = pd->num_clks - 1; i >= 0; i--) - clk_disable(pd->clks[i]); + clk_bulk_disable(pd->num_clks, pd->clks); } - mutex_unlock(&pd->pmu->mutex); + mutex_unlock(&pmu->mutex); return 0; } @@ -364,8 +368,6 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, const struct rockchip_domain_info *pd_info; struct rockchip_pm_domain *pd; struct device_node *qos_node; - struct clk *clk; - int clk_cnt; int i, j; u32 id; int error; @@ -391,41 +393,41 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, return -EINVAL; } - clk_cnt = of_count_phandle_with_args(node, "clocks", "#clock-cells"); - pd = devm_kzalloc(pmu->dev, - sizeof(*pd) + clk_cnt * sizeof(pd->clks[0]), - GFP_KERNEL); + pd = devm_kzalloc(pmu->dev, sizeof(*pd), GFP_KERNEL); if (!pd) return -ENOMEM; pd->info = pd_info; pd->pmu = pmu; - for (i = 0; i < clk_cnt; i++) { - clk = of_clk_get(node, i); - if (IS_ERR(clk)) { - error = PTR_ERR(clk); + pd->num_clks = of_count_phandle_with_args(node, "clocks", + "#clock-cells"); + if (pd->num_clks > 0) { + pd->clks = devm_kcalloc(pmu->dev, pd->num_clks, + sizeof(*pd->clks), GFP_KERNEL); + if (!pd->clks) + return -ENOMEM; + } else { + dev_dbg(pmu->dev, "%s: doesn't have clocks: %d\n", + node->name, pd->num_clks); + pd->num_clks = 0; + } + + 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, "%s: failed to get clk at index %d: %d\n", node->name, i, error); - goto err_out; - } - - 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; + return error; } - - 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", NULL); @@ -435,7 +437,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, GFP_KERNEL); if (!pd->qos_regmap) { error = -ENOMEM; - goto err_out; + goto err_unprepare_clocks; } for (j = 0; j < MAX_QOS_REGS_NUM; j++) { @@ -445,7 +447,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, GFP_KERNEL); if (!pd->qos_save_regs[j]) { error = -ENOMEM; - goto err_out; + goto err_unprepare_clocks; } } @@ -453,13 +455,13 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, qos_node = of_parse_phandle(node, "pm_qos", j); if (!qos_node) { error = -ENODEV; - goto err_out; + goto err_unprepare_clocks; } pd->qos_regmap[j] = syscon_node_to_regmap(qos_node); if (IS_ERR(pd->qos_regmap[j])) { error = -ENODEV; of_node_put(qos_node); - goto err_out; + goto err_unprepare_clocks; } of_node_put(qos_node); } @@ -470,7 +472,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, dev_err(pmu->dev, "failed to power on domain '%s': %d\n", node->name, error); - goto err_out; + goto err_unprepare_clocks; } pd->genpd.name = node->name; @@ -486,17 +488,16 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu, pmu->genpd_data.domains[id] = &pd->genpd; return 0; -err_out: - while (--i >= 0) { - clk_unprepare(pd->clks[i]); - clk_put(pd->clks[i]); - } +err_unprepare_clocks: + clk_bulk_unprepare(pd->num_clks, pd->clks); +err_put_clocks: + clk_bulk_put(pd->num_clks, pd->clks); return error; } 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, @@ -507,10 +508,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", pd->genpd.name, ret); - for (i = 0; i < pd->num_clks; i++) { - clk_unprepare(pd->clks[i]); - clk_put(pd->clks[i]); - } + clk_bulk_unprepare(pd->num_clks, pd->clks); + clk_bulk_put(pd->num_clks, pd->clks); /* protect the zeroing of pm->num_clks */ mutex_lock(&pd->pmu->mutex); |