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.
 -----BEGIN PGP SIGNATURE-----
 
 iQFEBAABCAAuFiEE7v+35S2Q1vLNA3Lx86Z5yZzRHYEFAlqpSUsQHGhlaWtvQHNu
 dGVjaC5kZQAKCRDzpnnJnNEdgdqIB/9UCXW7eLhVese5Htkd9OlBcBnWIovWSMf7
 TWj32YCqoMrIvRAbQ1/KCA8yQIeuyapLK8IpLVTRhX5G9GVd5Vk23o8seR2QYupN
 gjwzhEjrYYG6TeRNs89dzv2Nbl6UD8Nkw6TqxyVCa/wdNwNHkxvylrlca7RICGco
 Xi00qtbGBtp98MW/VQITiCCCRH8Htcn3Rn4uQMV/CRyukhUCQTy9hJyGXQembrF5
 fdYf9PhxJ07pEa4bZ3FHmfI/w3Qf/GIdWCflWV+0+vs2yQQ4qwXqbXCg5s3VIRB8
 Bd9uBx5lgxaF2cGH5zcQcwi+BWZTZwZKxSYdQZjDqk6eO/btmRBC
 =q5s4
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Arnd Bergmann 2018-03-28 17:08:34 +02:00
commit 7df3f0bb5f
2 changed files with 75 additions and 48 deletions

View File

@ -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 = {
@ -91,6 +113,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,

View File

@ -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;
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",
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);