forked from Minki/linux
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 <olof@lixom.net>
This commit is contained in:
commit
61c5e4927b
@ -5,11 +5,13 @@ is composed of many registers for system control.
|
||||
|
||||
From RK3368 SoCs, the GRF is divided into two sections,
|
||||
- GRF, used for general non-secure system,
|
||||
- SGRF, used for general secure system,
|
||||
- PMUGRF, used for always on system
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: GRF should be one of the followings
|
||||
- "rockchip,rk3036-grf", "syscon": for rk3036
|
||||
- "rockchip,rk3066-grf", "syscon": for rk3066
|
||||
- "rockchip,rk3188-grf", "syscon": for rk3188
|
||||
- "rockchip,rk3228-grf", "syscon": for rk3228
|
||||
@ -19,6 +21,8 @@ Required Properties:
|
||||
- compatible: PMUGRF should be one of the followings
|
||||
- "rockchip,rk3368-pmugrf", "syscon": for rk3368
|
||||
- "rockchip,rk3399-pmugrf", "syscon": for rk3399
|
||||
- compatible: SGRF should be one of the following
|
||||
- "rockchip,rk3288-sgrf", "syscon": for rk3288
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
|
||||
|
@ -6,6 +6,7 @@ powered up/down by software based on different application scenes to save power.
|
||||
Required properties for power domain controller:
|
||||
- compatible: Should be one of the following.
|
||||
"rockchip,rk3288-power-controller" - for RK3288 SoCs.
|
||||
"rockchip,rk3328-power-controller" - for RK3328 SoCs.
|
||||
"rockchip,rk3368-power-controller" - for RK3368 SoCs.
|
||||
"rockchip,rk3399-power-controller" - for RK3399 SoCs.
|
||||
- #power-domain-cells: Number of cells in a power-domain specifier.
|
||||
@ -16,6 +17,7 @@ Required properties for power domain controller:
|
||||
Required properties for power domain sub nodes:
|
||||
- reg: index of the power domain, should use macros in:
|
||||
"include/dt-bindings/power/rk3288-power.h" - for RK3288 type power domain.
|
||||
"include/dt-bindings/power/rk3328-power.h" - for RK3328 type power domain.
|
||||
"include/dt-bindings/power/rk3368-power.h" - for RK3368 type power domain.
|
||||
"include/dt-bindings/power/rk3399-power.h" - for RK3399 type power domain.
|
||||
- clocks (optional): phandles to clocks which need to be enabled while power domain
|
||||
@ -90,6 +92,7 @@ containing a phandle to the power device node and an index specifying which
|
||||
power domain to use.
|
||||
The index should use macros in:
|
||||
"include/dt-bindings/power/rk3288-power.h" - for rk3288 type power domain.
|
||||
"include/dt-bindings/power/rk3328-power.h" - for rk3328 type power domain.
|
||||
"include/dt-bindings/power/rk3368-power.h" - for rk3368 type power domain.
|
||||
"include/dt-bindings/power/rk3399-power.h" - for rk3399 type power domain.
|
||||
|
||||
|
@ -29,13 +29,11 @@
|
||||
#include "core.h"
|
||||
#include "pm.h"
|
||||
|
||||
#define RK3288_GRF_SOC_CON0 0x244
|
||||
#define RK3288_TIMER6_7_PHYS 0xff810000
|
||||
|
||||
static void __init rockchip_timer_init(void)
|
||||
{
|
||||
if (of_machine_is_compatible("rockchip,rk3288")) {
|
||||
struct regmap *grf;
|
||||
void __iomem *reg_base;
|
||||
|
||||
/*
|
||||
@ -54,16 +52,6 @@ static void __init rockchip_timer_init(void)
|
||||
} else {
|
||||
pr_err("rockchip: could not map timer7 registers\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable auto jtag/sdmmc switching that causes issues
|
||||
* with the mmc controllers making them unreliable
|
||||
*/
|
||||
grf = syscon_regmap_lookup_by_compatible("rockchip,rk3288-grf");
|
||||
if (!IS_ERR(grf))
|
||||
regmap_write(grf, RK3288_GRF_SOC_CON0, 0x10000000);
|
||||
else
|
||||
pr_err("rockchip: could not get grf syscon\n");
|
||||
}
|
||||
|
||||
of_clk_init(NULL);
|
||||
|
@ -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
|
||||
|
@ -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
134
drivers/soc/rockchip/grf.c
Normal 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);
|
@ -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,
|
||||
|
18
include/dt-bindings/power/rk3328-power.h
Normal file
18
include/dt-bindings/power/rk3328-power.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef __DT_BINDINGS_POWER_RK3328_POWER_H__
|
||||
#define __DT_BINDINGS_POWER_RK3328_POWER_H__
|
||||
|
||||
/**
|
||||
* RK3328 idle id Summary.
|
||||
*/
|
||||
#define RK3328_PD_CORE 0
|
||||
#define RK3328_PD_GPU 1
|
||||
#define RK3328_PD_BUS 2
|
||||
#define RK3328_PD_MSCH 3
|
||||
#define RK3328_PD_PERI 4
|
||||
#define RK3328_PD_VIDEO 5
|
||||
#define RK3328_PD_HEVC 6
|
||||
#define RK3328_PD_SYS 7
|
||||
#define RK3328_PD_VPU 8
|
||||
#define RK3328_PD_VIO 9
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user