Some extensions to the power-domain driver to support domains in

hiword registers (write-mask in upper 16bit) and domain-definitions
 for the rk3328 soc.
 
 Secondly a "driver" that attaches to the already existing grf nodes
 and is able to set static defaults for settings that cannot really
 be attached to any specific subsystem.
 Most GRF settings can already be set from drivers using them, but there
 are some behavioural settings like the mmc/jtag switch that cannot.
 
 As the commit message states this is really meant as a last line
 of defence for things that neither belong to a subsystem nor to the
 
 Having this here allows arm64 socs to have this as well and also
 moves another bit of code out of the arm32 mach-rockchip.
 -----BEGIN PGP SIGNATURE-----
 
 iQFEBAABCAAuFiEE7v+35S2Q1vLNA3Lx86Z5yZzRHYEFAliBTccQHGhlaWtvQHNu
 dGVjaC5kZQAKCRDzpnnJnNEdgdMAB/42pPY0pKqOWlAfqzTSlIh98vi9jp0nZUu+
 6RMlaqewhHq/zbH0qqJdcBrYRZF+EmJpTDGG2nltNi8FLNMyr+y7a0FVyjk/u43L
 FnYELcDm7yeCZ0012ZP/4hlhWI9YizojbIKH4p2o8nIj64CS132ZMVVgojyzvVc1
 0WLWUf8FBiMqsBpa6Kl117pvKayagk79PM570Ee2kRBxanN8yQaKmXTqG670eKzo
 7nar1VGAubAVpCZfbv4opugGfrjYPJFX4gcu3yJvtRRN+hTt6idRP40YoCMZSVds
 +okL0XW4G70ioXqZBS59Wq5FJS7frr8HRJbYD8lZg2vF948ZQnbC
 =4aXM
 -----END PGP SIGNATURE-----

Merge tag 'v4.11-armsoc-drivers1' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip into next/drivers

Some extensions to the power-domain driver to support domains in
hiword registers (write-mask in upper 16bit) and domain-definitions
for the rk3328 soc.

Secondly a "driver" that attaches to the already existing grf nodes
and is able to set static defaults for settings that cannot really
be attached to any specific subsystem.
Most GRF settings can already be set from drivers using them, but there
are some behavioural settings like the mmc/jtag switch that cannot.

As the commit message states this is really meant as a last line
of defence for things that neither belong to a subsystem nor to the

Having this here allows arm64 socs to have this as well and also
moves another bit of code out of the arm32 mach-rockchip.

* tag 'v4.11-armsoc-drivers1' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip:
  ARM: rockchip: drop rk3288 jtag/mmc switch handling
  soc: rockchip: add driver handling grf setup
  dt-bindings: add used but undocumented rockchip grf compatible values
  soc: rockchip: power-domain: add power domain support for rk3328
  dt-bindings: add binding for rk3328 power domains
  dt-bindings: power: add RK3328 SoCs header for idle-request
  soc: rockchip: power-domain: Support domain control in hiword-registers

Signed-off-by: Olof Johansson <[email protected]>
This commit is contained in:
Olof Johansson 2017-01-29 14:32:07 -08:00
commit 61c5e4927b
8 changed files with 227 additions and 18 deletions

View file

@ -3,6 +3,16 @@ if ARCH_ROCKCHIP || COMPILE_TEST
#
# Rockchip Soc drivers
#
config ROCKCHIP_GRF
bool
default y
help
The General Register Files are a central component providing
special additional settings registers for a lot of soc-components.
In a lot of cases there also need to be default settings initialized
to make some of them conform to expectations of the kernel.
config ROCKCHIP_PM_DOMAINS
bool "Rockchip generic power domain"
depends on PM

View file

@ -1,4 +1,5 @@
#
# Rockchip Soc drivers
#
obj-$(CONFIG_ROCKCHIP_GRF) += grf.o
obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o

134
drivers/soc/rockchip/grf.c Normal file
View file

@ -0,0 +1,134 @@
/*
* Rockchip Generic Register Files setup
*
* Copyright (c) 2016 Heiko Stuebner <heiko@sntech.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/err.h>
#include <linux/mfd/syscon.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#define HIWORD_UPDATE(val, mask, shift) \
((val) << (shift) | (mask) << ((shift) + 16))
struct rockchip_grf_value {
const char *desc;
u32 reg;
u32 val;
};
struct rockchip_grf_info {
const struct rockchip_grf_value *values;
int num_values;
};
#define RK3036_GRF_SOC_CON0 0x140
static const struct rockchip_grf_value rk3036_defaults[] __initconst = {
/*
* Disable auto jtag/sdmmc switching that causes issues with the
* clock-framework and the mmc controllers making them unreliable.
*/
{ "jtag switching", RK3036_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 11) },
};
static const struct rockchip_grf_info rk3036_grf __initconst = {
.values = rk3036_defaults,
.num_values = ARRAY_SIZE(rk3036_defaults),
};
#define RK3288_GRF_SOC_CON0 0x244
static const struct rockchip_grf_value rk3288_defaults[] __initconst = {
{ "jtag switching", RK3288_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 12) },
};
static const struct rockchip_grf_info rk3288_grf __initconst = {
.values = rk3288_defaults,
.num_values = ARRAY_SIZE(rk3288_defaults),
};
#define RK3368_GRF_SOC_CON15 0x43c
static const struct rockchip_grf_value rk3368_defaults[] __initconst = {
{ "jtag switching", RK3368_GRF_SOC_CON15, HIWORD_UPDATE(0, 1, 13) },
};
static const struct rockchip_grf_info rk3368_grf __initconst = {
.values = rk3368_defaults,
.num_values = ARRAY_SIZE(rk3368_defaults),
};
#define RK3399_GRF_SOC_CON7 0xe21c
static const struct rockchip_grf_value rk3399_defaults[] __initconst = {
{ "jtag switching", RK3399_GRF_SOC_CON7, HIWORD_UPDATE(0, 1, 12) },
};
static const struct rockchip_grf_info rk3399_grf __initconst = {
.values = rk3399_defaults,
.num_values = ARRAY_SIZE(rk3399_defaults),
};
static const struct of_device_id rockchip_grf_dt_match[] __initconst = {
{
.compatible = "rockchip,rk3036-grf",
.data = (void *)&rk3036_grf,
}, {
.compatible = "rockchip,rk3288-grf",
.data = (void *)&rk3288_grf,
}, {
.compatible = "rockchip,rk3368-grf",
.data = (void *)&rk3368_grf,
}, {
.compatible = "rockchip,rk3399-grf",
.data = (void *)&rk3399_grf,
},
{ /* sentinel */ },
};
static int __init rockchip_grf_init(void)
{
const struct rockchip_grf_info *grf_info;
const struct of_device_id *match;
struct device_node *np;
struct regmap *grf;
int ret, i;
np = of_find_matching_node_and_match(NULL, rockchip_grf_dt_match,
&match);
if (!np)
return -ENODEV;
if (!match || !match->data) {
pr_err("%s: missing grf data\n", __func__);
return -EINVAL;
}
grf_info = match->data;
grf = syscon_node_to_regmap(np);
if (IS_ERR(grf)) {
pr_err("%s: could not get grf syscon\n", __func__);
return PTR_ERR(grf);
}
for (i = 0; i < grf_info->num_values; i++) {
const struct rockchip_grf_value *val = &grf_info->values[i];
pr_debug("%s: adjusting %s in %#6x to %#10x\n", __func__,
val->desc, val->reg, val->val);
ret = regmap_write(grf, val->reg, val->val);
if (ret < 0)
pr_err("%s: write to %#6x failed with %d\n",
__func__, val->reg, ret);
}
return 0;
}
postcore_initcall(rockchip_grf_init);

View file

@ -19,6 +19,7 @@
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <dt-bindings/power/rk3288-power.h>
#include <dt-bindings/power/rk3328-power.h>
#include <dt-bindings/power/rk3368-power.h>
#include <dt-bindings/power/rk3399-power.h>
@ -29,6 +30,8 @@ struct rockchip_domain_info {
int idle_mask;
int ack_mask;
bool active_wakeup;
int pwr_w_mask;
int req_w_mask;
};
struct rockchip_pmu_info {
@ -87,9 +90,24 @@ struct rockchip_pmu {
.active_wakeup = wakeup, \
}
#define DOMAIN_M(pwr, status, req, idle, ack, wakeup) \
{ \
.pwr_w_mask = (pwr >= 0) ? BIT(pwr + 16) : 0, \
.pwr_mask = (pwr >= 0) ? BIT(pwr) : 0, \
.status_mask = (status >= 0) ? BIT(status) : 0, \
.req_w_mask = (req >= 0) ? BIT(req + 16) : 0, \
.req_mask = (req >= 0) ? BIT(req) : 0, \
.idle_mask = (idle >= 0) ? BIT(idle) : 0, \
.ack_mask = (ack >= 0) ? BIT(ack) : 0, \
.active_wakeup = wakeup, \
}
#define DOMAIN_RK3288(pwr, status, req, wakeup) \
DOMAIN(pwr, status, req, req, (req) + 16, wakeup)
#define DOMAIN_RK3328(pwr, status, req, wakeup) \
DOMAIN_M(pwr, pwr, req, (req) + 10, req, wakeup)
#define DOMAIN_RK3368(pwr, status, req, wakeup) \
DOMAIN(pwr, status, req, (req) + 16, req, wakeup)
@ -127,9 +145,13 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
if (pd_info->req_mask == 0)
return 0;
regmap_update_bits(pmu->regmap, pmu->info->req_offset,
pd_info->req_mask, idle ? -1U : 0);
else if (pd_info->req_w_mask)
regmap_write(pmu->regmap, pmu->info->req_offset,
idle ? (pd_info->req_mask | pd_info->req_w_mask) :
pd_info->req_w_mask);
else
regmap_update_bits(pmu->regmap, pmu->info->req_offset,
pd_info->req_mask, idle ? -1U : 0);
dsb(sy);
@ -230,9 +252,13 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
if (pd->info->pwr_mask == 0)
return;
regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
pd->info->pwr_mask, on ? 0 : -1U);
else if (pd->info->pwr_w_mask)
regmap_write(pmu->regmap, pmu->info->pwr_offset,
on ? pd->info->pwr_mask :
(pd->info->pwr_mask | pd->info->pwr_w_mask));
else
regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
pd->info->pwr_mask, on ? 0 : -1U);
dsb(sy);
@ -692,6 +718,18 @@ static const struct rockchip_domain_info rk3288_pm_domains[] = {
[RK3288_PD_GPU] = DOMAIN_RK3288(9, 9, 2, false),
};
static const struct rockchip_domain_info rk3328_pm_domains[] = {
[RK3328_PD_CORE] = DOMAIN_RK3328(-1, 0, 0, false),
[RK3328_PD_GPU] = DOMAIN_RK3328(-1, 1, 1, false),
[RK3328_PD_BUS] = DOMAIN_RK3328(-1, 2, 2, true),
[RK3328_PD_MSCH] = DOMAIN_RK3328(-1, 3, 3, true),
[RK3328_PD_PERI] = DOMAIN_RK3328(-1, 4, 4, true),
[RK3328_PD_VIDEO] = DOMAIN_RK3328(-1, 5, 5, false),
[RK3328_PD_HEVC] = DOMAIN_RK3328(-1, 6, 6, false),
[RK3328_PD_VIO] = DOMAIN_RK3328(-1, 8, 8, false),
[RK3328_PD_VPU] = DOMAIN_RK3328(-1, 9, 9, false),
};
static const struct rockchip_domain_info rk3368_pm_domains[] = {
[RK3368_PD_PERI] = DOMAIN_RK3368(13, 12, 6, true),
[RK3368_PD_VIO] = DOMAIN_RK3368(15, 14, 8, false),
@ -747,6 +785,15 @@ static const struct rockchip_pmu_info rk3288_pmu = {
.domain_info = rk3288_pm_domains,
};
static const struct rockchip_pmu_info rk3328_pmu = {
.req_offset = 0x414,
.idle_offset = 0x484,
.ack_offset = 0x484,
.num_domains = ARRAY_SIZE(rk3328_pm_domains),
.domain_info = rk3328_pm_domains,
};
static const struct rockchip_pmu_info rk3368_pmu = {
.pwr_offset = 0x0c,
.status_offset = 0x10,
@ -782,6 +829,10 @@ static const struct of_device_id rockchip_pm_domain_dt_match[] = {
.compatible = "rockchip,rk3288-power-controller",
.data = (void *)&rk3288_pmu,
},
{
.compatible = "rockchip,rk3328-power-controller",
.data = (void *)&rk3328_pmu,
},
{
.compatible = "rockchip,rk3368-power-controller",
.data = (void *)&rk3368_pmu,