aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2017-01-29 17:32:07 -0500
committerOlof Johansson <olof@lixom.net>2017-01-29 17:32:07 -0500
commit61c5e4927b271ee01c2f808e6196e1f62d7be092 (patch)
tree0b1bbaefa3dd35a5e30be1f11e9a3532147940f5
parentef73594a38a6df91bf9fa7a513237f677e7ad8c2 (diff)
parent19f0f3021e7532a1056886e3ddf524f9847e4f15 (diff)
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>
-rw-r--r--Documentation/devicetree/bindings/soc/rockchip/grf.txt4
-rw-r--r--Documentation/devicetree/bindings/soc/rockchip/power_domain.txt3
-rw-r--r--arch/arm/mach-rockchip/rockchip.c12
-rw-r--r--drivers/soc/rockchip/Kconfig10
-rw-r--r--drivers/soc/rockchip/Makefile1
-rw-r--r--drivers/soc/rockchip/grf.c134
-rw-r--r--drivers/soc/rockchip/pm_domains.c63
-rw-r--r--include/dt-bindings/power/rk3328-power.h18
8 files changed, 227 insertions, 18 deletions
diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.txt b/Documentation/devicetree/bindings/soc/rockchip/grf.txt
index 013e71a2cdc7..c6e62cb30712 100644
--- a/Documentation/devicetree/bindings/soc/rockchip/grf.txt
+++ b/Documentation/devicetree/bindings/soc/rockchip/grf.txt
@@ -5,11 +5,13 @@ is composed of many registers for system control.
5 5
6From RK3368 SoCs, the GRF is divided into two sections, 6From RK3368 SoCs, the GRF is divided into two sections,
7- GRF, used for general non-secure system, 7- GRF, used for general non-secure system,
8- SGRF, used for general secure system,
8- PMUGRF, used for always on system 9- PMUGRF, used for always on system
9 10
10Required Properties: 11Required Properties:
11 12
12- compatible: GRF should be one of the followings 13- compatible: GRF should be one of the followings
14 - "rockchip,rk3036-grf", "syscon": for rk3036
13 - "rockchip,rk3066-grf", "syscon": for rk3066 15 - "rockchip,rk3066-grf", "syscon": for rk3066
14 - "rockchip,rk3188-grf", "syscon": for rk3188 16 - "rockchip,rk3188-grf", "syscon": for rk3188
15 - "rockchip,rk3228-grf", "syscon": for rk3228 17 - "rockchip,rk3228-grf", "syscon": for rk3228
@@ -19,6 +21,8 @@ Required Properties:
19- compatible: PMUGRF should be one of the followings 21- compatible: PMUGRF should be one of the followings
20 - "rockchip,rk3368-pmugrf", "syscon": for rk3368 22 - "rockchip,rk3368-pmugrf", "syscon": for rk3368
21 - "rockchip,rk3399-pmugrf", "syscon": for rk3399 23 - "rockchip,rk3399-pmugrf", "syscon": for rk3399
24- compatible: SGRF should be one of the following
25 - "rockchip,rk3288-sgrf", "syscon": for rk3288
22- reg: physical base address of the controller and length of memory mapped 26- reg: physical base address of the controller and length of memory mapped
23 region. 27 region.
24 28
diff --git a/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
index f909ce06afc4..01bfb6745fbd 100644
--- a/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
+++ b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
@@ -6,6 +6,7 @@ powered up/down by software based on different application scenes to save power.
6Required properties for power domain controller: 6Required properties for power domain controller:
7- compatible: Should be one of the following. 7- compatible: Should be one of the following.
8 "rockchip,rk3288-power-controller" - for RK3288 SoCs. 8 "rockchip,rk3288-power-controller" - for RK3288 SoCs.
9 "rockchip,rk3328-power-controller" - for RK3328 SoCs.
9 "rockchip,rk3368-power-controller" - for RK3368 SoCs. 10 "rockchip,rk3368-power-controller" - for RK3368 SoCs.
10 "rockchip,rk3399-power-controller" - for RK3399 SoCs. 11 "rockchip,rk3399-power-controller" - for RK3399 SoCs.
11- #power-domain-cells: Number of cells in a power-domain specifier. 12- #power-domain-cells: Number of cells in a power-domain specifier.
@@ -16,6 +17,7 @@ Required properties for power domain controller:
16Required properties for power domain sub nodes: 17Required properties for power domain sub nodes:
17- reg: index of the power domain, should use macros in: 18- reg: index of the power domain, should use macros in:
18 "include/dt-bindings/power/rk3288-power.h" - for RK3288 type power domain. 19 "include/dt-bindings/power/rk3288-power.h" - for RK3288 type power domain.
20 "include/dt-bindings/power/rk3328-power.h" - for RK3328 type power domain.
19 "include/dt-bindings/power/rk3368-power.h" - for RK3368 type power domain. 21 "include/dt-bindings/power/rk3368-power.h" - for RK3368 type power domain.
20 "include/dt-bindings/power/rk3399-power.h" - for RK3399 type power domain. 22 "include/dt-bindings/power/rk3399-power.h" - for RK3399 type power domain.
21- clocks (optional): phandles to clocks which need to be enabled while power domain 23- 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
90power domain to use. 92power domain to use.
91The index should use macros in: 93The index should use macros in:
92 "include/dt-bindings/power/rk3288-power.h" - for rk3288 type power domain. 94 "include/dt-bindings/power/rk3288-power.h" - for rk3288 type power domain.
95 "include/dt-bindings/power/rk3328-power.h" - for rk3328 type power domain.
93 "include/dt-bindings/power/rk3368-power.h" - for rk3368 type power domain. 96 "include/dt-bindings/power/rk3368-power.h" - for rk3368 type power domain.
94 "include/dt-bindings/power/rk3399-power.h" - for rk3399 type power domain. 97 "include/dt-bindings/power/rk3399-power.h" - for rk3399 type power domain.
95 98
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index a7ab9ec141f8..ef0500a4c8ad 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -29,13 +29,11 @@
29#include "core.h" 29#include "core.h"
30#include "pm.h" 30#include "pm.h"
31 31
32#define RK3288_GRF_SOC_CON0 0x244
33#define RK3288_TIMER6_7_PHYS 0xff810000 32#define RK3288_TIMER6_7_PHYS 0xff810000
34 33
35static void __init rockchip_timer_init(void) 34static void __init rockchip_timer_init(void)
36{ 35{
37 if (of_machine_is_compatible("rockchip,rk3288")) { 36 if (of_machine_is_compatible("rockchip,rk3288")) {
38 struct regmap *grf;
39 void __iomem *reg_base; 37 void __iomem *reg_base;
40 38
41 /* 39 /*
@@ -54,16 +52,6 @@ static void __init rockchip_timer_init(void)
54 } else { 52 } else {
55 pr_err("rockchip: could not map timer7 registers\n"); 53 pr_err("rockchip: could not map timer7 registers\n");
56 } 54 }
57
58 /*
59 * Disable auto jtag/sdmmc switching that causes issues
60 * with the mmc controllers making them unreliable
61 */
62 grf = syscon_regmap_lookup_by_compatible("rockchip,rk3288-grf");
63 if (!IS_ERR(grf))
64 regmap_write(grf, RK3288_GRF_SOC_CON0, 0x10000000);
65 else
66 pr_err("rockchip: could not get grf syscon\n");
67 } 55 }
68 56
69 of_clk_init(NULL); 57 of_clk_init(NULL);
diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig
index 7140ff825598..20da55d9cbb1 100644
--- a/drivers/soc/rockchip/Kconfig
+++ b/drivers/soc/rockchip/Kconfig
@@ -3,6 +3,16 @@ if ARCH_ROCKCHIP || COMPILE_TEST
3# 3#
4# Rockchip Soc drivers 4# Rockchip Soc drivers
5# 5#
6
7config ROCKCHIP_GRF
8 bool
9 default y
10 help
11 The General Register Files are a central component providing
12 special additional settings registers for a lot of soc-components.
13 In a lot of cases there also need to be default settings initialized
14 to make some of them conform to expectations of the kernel.
15
6config ROCKCHIP_PM_DOMAINS 16config ROCKCHIP_PM_DOMAINS
7 bool "Rockchip generic power domain" 17 bool "Rockchip generic power domain"
8 depends on PM 18 depends on PM
diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile
index 3d73d0672d22..c851fa0056d0 100644
--- a/drivers/soc/rockchip/Makefile
+++ b/drivers/soc/rockchip/Makefile
@@ -1,4 +1,5 @@
1# 1#
2# Rockchip Soc drivers 2# Rockchip Soc drivers
3# 3#
4obj-$(CONFIG_ROCKCHIP_GRF) += grf.o
4obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o 5obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o
diff --git a/drivers/soc/rockchip/grf.c b/drivers/soc/rockchip/grf.c
new file mode 100644
index 000000000000..d61db34ad6dd
--- /dev/null
+++ b/drivers/soc/rockchip/grf.c
@@ -0,0 +1,134 @@
1/*
2 * Rockchip Generic Register Files setup
3 *
4 * Copyright (c) 2016 Heiko Stuebner <heiko@sntech.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/err.h>
12#include <linux/mfd/syscon.h>
13#include <linux/of_device.h>
14#include <linux/platform_device.h>
15#include <linux/regmap.h>
16
17#define HIWORD_UPDATE(val, mask, shift) \
18 ((val) << (shift) | (mask) << ((shift) + 16))
19
20struct rockchip_grf_value {
21 const char *desc;
22 u32 reg;
23 u32 val;
24};
25
26struct rockchip_grf_info {
27 const struct rockchip_grf_value *values;
28 int num_values;
29};
30
31#define RK3036_GRF_SOC_CON0 0x140
32
33static const struct rockchip_grf_value rk3036_defaults[] __initconst = {
34 /*
35 * Disable auto jtag/sdmmc switching that causes issues with the
36 * clock-framework and the mmc controllers making them unreliable.
37 */
38 { "jtag switching", RK3036_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 11) },
39};
40
41static const struct rockchip_grf_info rk3036_grf __initconst = {
42 .values = rk3036_defaults,
43 .num_values = ARRAY_SIZE(rk3036_defaults),
44};
45
46#define RK3288_GRF_SOC_CON0 0x244
47
48static const struct rockchip_grf_value rk3288_defaults[] __initconst = {
49 { "jtag switching", RK3288_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 12) },
50};
51
52static const struct rockchip_grf_info rk3288_grf __initconst = {
53 .values = rk3288_defaults,
54 .num_values = ARRAY_SIZE(rk3288_defaults),
55};
56
57#define RK3368_GRF_SOC_CON15 0x43c
58
59static const struct rockchip_grf_value rk3368_defaults[] __initconst = {
60 { "jtag switching", RK3368_GRF_SOC_CON15, HIWORD_UPDATE(0, 1, 13) },
61};
62
63static const struct rockchip_grf_info rk3368_grf __initconst = {
64 .values = rk3368_defaults,
65 .num_values = ARRAY_SIZE(rk3368_defaults),
66};
67
68#define RK3399_GRF_SOC_CON7 0xe21c
69
70static const struct rockchip_grf_value rk3399_defaults[] __initconst = {
71 { "jtag switching", RK3399_GRF_SOC_CON7, HIWORD_UPDATE(0, 1, 12) },
72};
73
74static const struct rockchip_grf_info rk3399_grf __initconst = {
75 .values = rk3399_defaults,
76 .num_values = ARRAY_SIZE(rk3399_defaults),
77};
78
79static const struct of_device_id rockchip_grf_dt_match[] __initconst = {
80 {
81 .compatible = "rockchip,rk3036-grf",
82 .data = (void *)&rk3036_grf,
83 }, {
84 .compatible = "rockchip,rk3288-grf",
85 .data = (void *)&rk3288_grf,
86 }, {
87 .compatible = "rockchip,rk3368-grf",
88 .data = (void *)&rk3368_grf,
89 }, {
90 .compatible = "rockchip,rk3399-grf",
91 .data = (void *)&rk3399_grf,
92 },
93 { /* sentinel */ },
94};
95
96static int __init rockchip_grf_init(void)
97{
98 const struct rockchip_grf_info *grf_info;
99 const struct of_device_id *match;
100 struct device_node *np;
101 struct regmap *grf;
102 int ret, i;
103
104 np = of_find_matching_node_and_match(NULL, rockchip_grf_dt_match,
105 &match);
106 if (!np)
107 return -ENODEV;
108 if (!match || !match->data) {
109 pr_err("%s: missing grf data\n", __func__);
110 return -EINVAL;
111 }
112
113 grf_info = match->data;
114
115 grf = syscon_node_to_regmap(np);
116 if (IS_ERR(grf)) {
117 pr_err("%s: could not get grf syscon\n", __func__);
118 return PTR_ERR(grf);
119 }
120
121 for (i = 0; i < grf_info->num_values; i++) {
122 const struct rockchip_grf_value *val = &grf_info->values[i];
123
124 pr_debug("%s: adjusting %s in %#6x to %#10x\n", __func__,
125 val->desc, val->reg, val->val);
126 ret = regmap_write(grf, val->reg, val->val);
127 if (ret < 0)
128 pr_err("%s: write to %#6x failed with %d\n",
129 __func__, val->reg, ret);
130 }
131
132 return 0;
133}
134postcore_initcall(rockchip_grf_init);
diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c
index 1c78c42416c6..796c46a6cbe7 100644
--- a/drivers/soc/rockchip/pm_domains.c
+++ b/drivers/soc/rockchip/pm_domains.c
@@ -19,6 +19,7 @@
19#include <linux/regmap.h> 19#include <linux/regmap.h>
20#include <linux/mfd/syscon.h> 20#include <linux/mfd/syscon.h>
21#include <dt-bindings/power/rk3288-power.h> 21#include <dt-bindings/power/rk3288-power.h>
22#include <dt-bindings/power/rk3328-power.h>
22#include <dt-bindings/power/rk3368-power.h> 23#include <dt-bindings/power/rk3368-power.h>
23#include <dt-bindings/power/rk3399-power.h> 24#include <dt-bindings/power/rk3399-power.h>
24 25
@@ -29,6 +30,8 @@ struct rockchip_domain_info {
29 int idle_mask; 30 int idle_mask;
30 int ack_mask; 31 int ack_mask;
31 bool active_wakeup; 32 bool active_wakeup;
33 int pwr_w_mask;
34 int req_w_mask;
32}; 35};
33 36
34struct rockchip_pmu_info { 37struct rockchip_pmu_info {
@@ -87,9 +90,24 @@ struct rockchip_pmu {
87 .active_wakeup = wakeup, \ 90 .active_wakeup = wakeup, \
88} 91}
89 92
93#define DOMAIN_M(pwr, status, req, idle, ack, wakeup) \
94{ \
95 .pwr_w_mask = (pwr >= 0) ? BIT(pwr + 16) : 0, \
96 .pwr_mask = (pwr >= 0) ? BIT(pwr) : 0, \
97 .status_mask = (status >= 0) ? BIT(status) : 0, \
98 .req_w_mask = (req >= 0) ? BIT(req + 16) : 0, \
99 .req_mask = (req >= 0) ? BIT(req) : 0, \
100 .idle_mask = (idle >= 0) ? BIT(idle) : 0, \
101 .ack_mask = (ack >= 0) ? BIT(ack) : 0, \
102 .active_wakeup = wakeup, \
103}
104
90#define DOMAIN_RK3288(pwr, status, req, wakeup) \ 105#define DOMAIN_RK3288(pwr, status, req, wakeup) \
91 DOMAIN(pwr, status, req, req, (req) + 16, wakeup) 106 DOMAIN(pwr, status, req, req, (req) + 16, wakeup)
92 107
108#define DOMAIN_RK3328(pwr, status, req, wakeup) \
109 DOMAIN_M(pwr, pwr, req, (req) + 10, req, wakeup)
110
93#define DOMAIN_RK3368(pwr, status, req, wakeup) \ 111#define DOMAIN_RK3368(pwr, status, req, wakeup) \
94 DOMAIN(pwr, status, req, (req) + 16, req, wakeup) 112 DOMAIN(pwr, status, req, (req) + 16, req, wakeup)
95 113
@@ -127,9 +145,13 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
127 145
128 if (pd_info->req_mask == 0) 146 if (pd_info->req_mask == 0)
129 return 0; 147 return 0;
130 148 else if (pd_info->req_w_mask)
131 regmap_update_bits(pmu->regmap, pmu->info->req_offset, 149 regmap_write(pmu->regmap, pmu->info->req_offset,
132 pd_info->req_mask, idle ? -1U : 0); 150 idle ? (pd_info->req_mask | pd_info->req_w_mask) :
151 pd_info->req_w_mask);
152 else
153 regmap_update_bits(pmu->regmap, pmu->info->req_offset,
154 pd_info->req_mask, idle ? -1U : 0);
133 155
134 dsb(sy); 156 dsb(sy);
135 157
@@ -230,9 +252,13 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
230 252
231 if (pd->info->pwr_mask == 0) 253 if (pd->info->pwr_mask == 0)
232 return; 254 return;
233 255 else if (pd->info->pwr_w_mask)
234 regmap_update_bits(pmu->regmap, pmu->info->pwr_offset, 256 regmap_write(pmu->regmap, pmu->info->pwr_offset,
235 pd->info->pwr_mask, on ? 0 : -1U); 257 on ? pd->info->pwr_mask :
258 (pd->info->pwr_mask | pd->info->pwr_w_mask));
259 else
260 regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
261 pd->info->pwr_mask, on ? 0 : -1U);
236 262
237 dsb(sy); 263 dsb(sy);
238 264
@@ -692,6 +718,18 @@ static const struct rockchip_domain_info rk3288_pm_domains[] = {
692 [RK3288_PD_GPU] = DOMAIN_RK3288(9, 9, 2, false), 718 [RK3288_PD_GPU] = DOMAIN_RK3288(9, 9, 2, false),
693}; 719};
694 720
721static const struct rockchip_domain_info rk3328_pm_domains[] = {
722 [RK3328_PD_CORE] = DOMAIN_RK3328(-1, 0, 0, false),
723 [RK3328_PD_GPU] = DOMAIN_RK3328(-1, 1, 1, false),
724 [RK3328_PD_BUS] = DOMAIN_RK3328(-1, 2, 2, true),
725 [RK3328_PD_MSCH] = DOMAIN_RK3328(-1, 3, 3, true),
726 [RK3328_PD_PERI] = DOMAIN_RK3328(-1, 4, 4, true),
727 [RK3328_PD_VIDEO] = DOMAIN_RK3328(-1, 5, 5, false),
728 [RK3328_PD_HEVC] = DOMAIN_RK3328(-1, 6, 6, false),
729 [RK3328_PD_VIO] = DOMAIN_RK3328(-1, 8, 8, false),
730 [RK3328_PD_VPU] = DOMAIN_RK3328(-1, 9, 9, false),
731};
732
695static const struct rockchip_domain_info rk3368_pm_domains[] = { 733static const struct rockchip_domain_info rk3368_pm_domains[] = {
696 [RK3368_PD_PERI] = DOMAIN_RK3368(13, 12, 6, true), 734 [RK3368_PD_PERI] = DOMAIN_RK3368(13, 12, 6, true),
697 [RK3368_PD_VIO] = DOMAIN_RK3368(15, 14, 8, false), 735 [RK3368_PD_VIO] = DOMAIN_RK3368(15, 14, 8, false),
@@ -747,6 +785,15 @@ static const struct rockchip_pmu_info rk3288_pmu = {
747 .domain_info = rk3288_pm_domains, 785 .domain_info = rk3288_pm_domains,
748}; 786};
749 787
788static const struct rockchip_pmu_info rk3328_pmu = {
789 .req_offset = 0x414,
790 .idle_offset = 0x484,
791 .ack_offset = 0x484,
792
793 .num_domains = ARRAY_SIZE(rk3328_pm_domains),
794 .domain_info = rk3328_pm_domains,
795};
796
750static const struct rockchip_pmu_info rk3368_pmu = { 797static const struct rockchip_pmu_info rk3368_pmu = {
751 .pwr_offset = 0x0c, 798 .pwr_offset = 0x0c,
752 .status_offset = 0x10, 799 .status_offset = 0x10,
@@ -783,6 +830,10 @@ static const struct of_device_id rockchip_pm_domain_dt_match[] = {
783 .data = (void *)&rk3288_pmu, 830 .data = (void *)&rk3288_pmu,
784 }, 831 },
785 { 832 {
833 .compatible = "rockchip,rk3328-power-controller",
834 .data = (void *)&rk3328_pmu,
835 },
836 {
786 .compatible = "rockchip,rk3368-power-controller", 837 .compatible = "rockchip,rk3368-power-controller",
787 .data = (void *)&rk3368_pmu, 838 .data = (void *)&rk3368_pmu,
788 }, 839 },
diff --git a/include/dt-bindings/power/rk3328-power.h b/include/dt-bindings/power/rk3328-power.h
new file mode 100644
index 000000000000..10c3c3715334
--- /dev/null
+++ b/include/dt-bindings/power/rk3328-power.h
@@ -0,0 +1,18 @@
1#ifndef __DT_BINDINGS_POWER_RK3328_POWER_H__
2#define __DT_BINDINGS_POWER_RK3328_POWER_H__
3
4/**
5 * RK3328 idle id Summary.
6 */
7#define RK3328_PD_CORE 0
8#define RK3328_PD_GPU 1
9#define RK3328_PD_BUS 2
10#define RK3328_PD_MSCH 3
11#define RK3328_PD_PERI 4
12#define RK3328_PD_VIDEO 5
13#define RK3328_PD_HEVC 6
14#define RK3328_PD_SYS 7
15#define RK3328_PD_VPU 8
16#define RK3328_PD_VIO 9
17
18#endif