aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2017-01-30 00:17:24 -0500
committerOlof Johansson <olof@lixom.net>2017-01-30 00:17:24 -0500
commit2a742e1b180785464accac3adf14fa1ccc9d02b0 (patch)
tree1917b2d7b5601e82ba001574c0c058faa5d86e0b
parent2998954c40d2dd845484e30118c614cc6c397529 (diff)
parent3755584a91c1cb1e50dd24a456e2953fbd276adf (diff)
Merge tag 'zte-pd-4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into next/drivers
ZTE PM domain driver support for 4.11: - It includes a series which adds DT bindings and PM domain driver for PCU (Power Control Unit) block found on ZTE ZX2967 family SoC. * tag 'zte-pd-4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux: soc: zte: pm_domains: Add support for zx296718 soc: zte: pm_domains: Prepare for supporting ARMv8 zx2967 family soc: zte: Add header for PM domains specifiers MAINTAINERS: add zx2967 SoC drivers to ARM ZTE architecture dt-bindings: zte: add bindings document for zx2967 power domain controller Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--Documentation/devicetree/bindings/soc/zte/pd-2967xx.txt19
-rw-r--r--MAINTAINERS4
-rw-r--r--drivers/soc/Kconfig1
-rw-r--r--drivers/soc/Makefile1
-rw-r--r--drivers/soc/zte/Kconfig13
-rw-r--r--drivers/soc/zte/Makefile5
-rw-r--r--drivers/soc/zte/zx296718_pm_domains.c182
-rw-r--r--drivers/soc/zte/zx2967_pm_domains.c143
-rw-r--r--drivers/soc/zte/zx2967_pm_domains.h44
-rw-r--r--include/dt-bindings/soc/zte,pm_domains.h24
10 files changed, 436 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/soc/zte/pd-2967xx.txt b/Documentation/devicetree/bindings/soc/zte/pd-2967xx.txt
new file mode 100644
index 000000000000..7629de1c2c72
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/zte/pd-2967xx.txt
@@ -0,0 +1,19 @@
1* ZTE zx2967 family Power Domains
2
3zx2967 family includes support for multiple power domains which are used
4to gate power to one or more peripherals on the processor.
5
6Required Properties:
7 - compatible: should be one of the following.
8 * zte,zx296718-pcu - for zx296718 power domain.
9 - reg: physical base address of the controller and length of memory mapped
10 region.
11 - #power-domain-cells: Must be 1.
12
13Example:
14
15 pcu_domain: pcu@117000 {
16 compatible = "zte,zx296718-pcu";
17 reg = <0x00117000 0x1000>;
18 #power-domain-cells = <1>;
19 };
diff --git a/MAINTAINERS b/MAINTAINERS
index 33c0e0d17650..e4874cc6b1b9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1982,14 +1982,18 @@ F: arch/arm/mach-pxa/include/mach/z2.h
1982 1982
1983ARM/ZTE ARCHITECTURE 1983ARM/ZTE ARCHITECTURE
1984M: Jun Nie <jun.nie@linaro.org> 1984M: Jun Nie <jun.nie@linaro.org>
1985M: Baoyou Xie <baoyou.xie@linaro.org>
1985L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) 1986L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
1986S: Maintained 1987S: Maintained
1987F: arch/arm/mach-zx/ 1988F: arch/arm/mach-zx/
1988F: drivers/clk/zte/ 1989F: drivers/clk/zte/
1989F: drivers/reset/reset-zx2967.c 1990F: drivers/reset/reset-zx2967.c
1991F: drivers/soc/zte/
1990F: Documentation/devicetree/bindings/arm/zte.txt 1992F: Documentation/devicetree/bindings/arm/zte.txt
1991F: Documentation/devicetree/bindings/clock/zx296702-clk.txt 1993F: Documentation/devicetree/bindings/clock/zx296702-clk.txt
1992F: Documentation/devicetree/bindings/reset/zte,zx2967-reset.txt 1994F: Documentation/devicetree/bindings/reset/zte,zx2967-reset.txt
1995F: Documentation/devicetree/bindings/soc/zte/
1996F: include/dt-bindings/soc/zx*.h
1993 1997
1994ARM/ZYNQ ARCHITECTURE 1998ARM/ZYNQ ARCHITECTURE
1995M: Michal Simek <michal.simek@xilinx.com> 1999M: Michal Simek <michal.simek@xilinx.com>
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index f31bceb69c0d..f09023f7ab11 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -11,5 +11,6 @@ source "drivers/soc/tegra/Kconfig"
11source "drivers/soc/ti/Kconfig" 11source "drivers/soc/ti/Kconfig"
12source "drivers/soc/ux500/Kconfig" 12source "drivers/soc/ux500/Kconfig"
13source "drivers/soc/versatile/Kconfig" 13source "drivers/soc/versatile/Kconfig"
14source "drivers/soc/zte/Kconfig"
14 15
15endmenu 16endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 50c23d0bd457..05eae52a30b4 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
16obj-$(CONFIG_SOC_TI) += ti/ 16obj-$(CONFIG_SOC_TI) += ti/
17obj-$(CONFIG_ARCH_U8500) += ux500/ 17obj-$(CONFIG_ARCH_U8500) += ux500/
18obj-$(CONFIG_PLAT_VERSATILE) += versatile/ 18obj-$(CONFIG_PLAT_VERSATILE) += versatile/
19obj-$(CONFIG_ARCH_ZX) += zte/
diff --git a/drivers/soc/zte/Kconfig b/drivers/soc/zte/Kconfig
new file mode 100644
index 000000000000..20bde38ce2f9
--- /dev/null
+++ b/drivers/soc/zte/Kconfig
@@ -0,0 +1,13 @@
1#
2# ZTE SoC drivers
3#
4menuconfig SOC_ZTE
5 bool "ZTE SoC driver support"
6
7if SOC_ZTE
8
9config ZX2967_PM_DOMAINS
10 bool "ZX2967 PM domains"
11 depends on PM_GENERIC_DOMAINS
12
13endif
diff --git a/drivers/soc/zte/Makefile b/drivers/soc/zte/Makefile
new file mode 100644
index 000000000000..96b7cd4c9629
--- /dev/null
+++ b/drivers/soc/zte/Makefile
@@ -0,0 +1,5 @@
1#
2# ZTE SOC drivers
3#
4obj-$(CONFIG_ZX2967_PM_DOMAINS) += zx2967_pm_domains.o
5obj-$(CONFIG_ZX2967_PM_DOMAINS) += zx296718_pm_domains.o
diff --git a/drivers/soc/zte/zx296718_pm_domains.c b/drivers/soc/zte/zx296718_pm_domains.c
new file mode 100644
index 000000000000..5ed924fee855
--- /dev/null
+++ b/drivers/soc/zte/zx296718_pm_domains.c
@@ -0,0 +1,182 @@
1/*
2 * Copyright (C) 2017 ZTE Ltd.
3 *
4 * Author: Baoyou Xie <baoyou.xie@linaro.org>
5 * License terms: GNU General Public License (GPL) version 2
6 */
7
8#include <dt-bindings/soc/zte,pm_domains.h>
9#include "zx2967_pm_domains.h"
10
11static u16 zx296718_offsets[REG_ARRAY_SIZE] = {
12 [REG_CLKEN] = 0x18,
13 [REG_ISOEN] = 0x1c,
14 [REG_RSTEN] = 0x20,
15 [REG_PWREN] = 0x24,
16 [REG_ACK_SYNC] = 0x28,
17};
18
19enum {
20 PCU_DM_VOU = 0,
21 PCU_DM_SAPPU,
22 PCU_DM_VDE,
23 PCU_DM_VCE,
24 PCU_DM_HDE,
25 PCU_DM_VIU,
26 PCU_DM_USB20,
27 PCU_DM_USB21,
28 PCU_DM_USB30,
29 PCU_DM_HSIC,
30 PCU_DM_GMAC,
31 PCU_DM_TS,
32};
33
34static struct zx2967_pm_domain vou_domain = {
35 .dm = {
36 .name = "vou_domain",
37 },
38 .bit = PCU_DM_VOU,
39 .polarity = PWREN,
40 .reg_offset = zx296718_offsets,
41};
42
43static struct zx2967_pm_domain sappu_domain = {
44 .dm = {
45 .name = "sappu_domain",
46 },
47 .bit = PCU_DM_SAPPU,
48 .polarity = PWREN,
49 .reg_offset = zx296718_offsets,
50};
51
52static struct zx2967_pm_domain vde_domain = {
53 .dm = {
54 .name = "vde_domain",
55 },
56 .bit = PCU_DM_VDE,
57 .polarity = PWREN,
58 .reg_offset = zx296718_offsets,
59};
60
61static struct zx2967_pm_domain vce_domain = {
62 .dm = {
63 .name = "vce_domain",
64 },
65 .bit = PCU_DM_VCE,
66 .polarity = PWREN,
67 .reg_offset = zx296718_offsets,
68};
69
70static struct zx2967_pm_domain hde_domain = {
71 .dm = {
72 .name = "hde_domain",
73 },
74 .bit = PCU_DM_HDE,
75 .polarity = PWREN,
76 .reg_offset = zx296718_offsets,
77};
78
79static struct zx2967_pm_domain viu_domain = {
80 .dm = {
81 .name = "viu_domain",
82 },
83 .bit = PCU_DM_VIU,
84 .polarity = PWREN,
85 .reg_offset = zx296718_offsets,
86};
87
88static struct zx2967_pm_domain usb20_domain = {
89 .dm = {
90 .name = "usb20_domain",
91 },
92 .bit = PCU_DM_USB20,
93 .polarity = PWREN,
94 .reg_offset = zx296718_offsets,
95};
96
97static struct zx2967_pm_domain usb21_domain = {
98 .dm = {
99 .name = "usb21_domain",
100 },
101 .bit = PCU_DM_USB21,
102 .polarity = PWREN,
103 .reg_offset = zx296718_offsets,
104};
105
106static struct zx2967_pm_domain usb30_domain = {
107 .dm = {
108 .name = "usb30_domain",
109 },
110 .bit = PCU_DM_USB30,
111 .polarity = PWREN,
112 .reg_offset = zx296718_offsets,
113};
114
115static struct zx2967_pm_domain hsic_domain = {
116 .dm = {
117 .name = "hsic_domain",
118 },
119 .bit = PCU_DM_HSIC,
120 .polarity = PWREN,
121 .reg_offset = zx296718_offsets,
122};
123
124static struct zx2967_pm_domain gmac_domain = {
125 .dm = {
126 .name = "gmac_domain",
127 },
128 .bit = PCU_DM_GMAC,
129 .polarity = PWREN,
130 .reg_offset = zx296718_offsets,
131};
132
133static struct zx2967_pm_domain ts_domain = {
134 .dm = {
135 .name = "ts_domain",
136 },
137 .bit = PCU_DM_TS,
138 .polarity = PWREN,
139 .reg_offset = zx296718_offsets,
140};
141
142static struct generic_pm_domain *zx296718_pm_domains[] = {
143 [DM_ZX296718_VOU] = &vou_domain.dm,
144 [DM_ZX296718_SAPPU] = &sappu_domain.dm,
145 [DM_ZX296718_VDE] = &vde_domain.dm,
146 [DM_ZX296718_VCE] = &vce_domain.dm,
147 [DM_ZX296718_HDE] = &hde_domain.dm,
148 [DM_ZX296718_VIU] = &viu_domain.dm,
149 [DM_ZX296718_USB20] = &usb20_domain.dm,
150 [DM_ZX296718_USB21] = &usb21_domain.dm,
151 [DM_ZX296718_USB30] = &usb30_domain.dm,
152 [DM_ZX296718_HSIC] = &hsic_domain.dm,
153 [DM_ZX296718_GMAC] = &gmac_domain.dm,
154 [DM_ZX296718_TS] = &ts_domain.dm,
155};
156
157static int zx296718_pd_probe(struct platform_device *pdev)
158{
159 return zx2967_pd_probe(pdev,
160 zx296718_pm_domains,
161 ARRAY_SIZE(zx296718_pm_domains));
162}
163
164static const struct of_device_id zx296718_pm_domain_matches[] = {
165 { .compatible = "zte,zx296718-pcu", },
166 { },
167};
168
169static struct platform_driver zx296718_pd_driver = {
170 .driver = {
171 .name = "zx296718-powerdomain",
172 .owner = THIS_MODULE,
173 .of_match_table = zx296718_pm_domain_matches,
174 },
175 .probe = zx296718_pd_probe,
176};
177
178static int __init zx296718_pd_init(void)
179{
180 return platform_driver_register(&zx296718_pd_driver);
181}
182subsys_initcall(zx296718_pd_init);
diff --git a/drivers/soc/zte/zx2967_pm_domains.c b/drivers/soc/zte/zx2967_pm_domains.c
new file mode 100644
index 000000000000..61c8d84bf315
--- /dev/null
+++ b/drivers/soc/zte/zx2967_pm_domains.c
@@ -0,0 +1,143 @@
1/*
2 * Copyright (C) 2017 ZTE Ltd.
3 *
4 * Author: Baoyou Xie <baoyou.xie@linaro.org>
5 * License terms: GNU General Public License (GPL) version 2
6 */
7
8#include <linux/delay.h>
9#include <linux/err.h>
10#include <linux/io.h>
11#include <linux/of.h>
12
13#include "zx2967_pm_domains.h"
14
15#define PCU_DM_CLKEN(zpd) ((zpd)->reg_offset[REG_CLKEN])
16#define PCU_DM_ISOEN(zpd) ((zpd)->reg_offset[REG_ISOEN])
17#define PCU_DM_RSTEN(zpd) ((zpd)->reg_offset[REG_RSTEN])
18#define PCU_DM_PWREN(zpd) ((zpd)->reg_offset[REG_PWREN])
19#define PCU_DM_ACK_SYNC(zpd) ((zpd)->reg_offset[REG_ACK_SYNC])
20
21static void __iomem *pcubase;
22
23static int zx2967_power_on(struct generic_pm_domain *domain)
24{
25 struct zx2967_pm_domain *zpd = (struct zx2967_pm_domain *)domain;
26 unsigned long loop = 1000;
27 u32 val;
28
29 val = readl_relaxed(pcubase + PCU_DM_PWREN(zpd));
30 if (zpd->polarity == PWREN)
31 val |= BIT(zpd->bit);
32 else
33 val &= ~BIT(zpd->bit);
34 writel_relaxed(val, pcubase + PCU_DM_PWREN(zpd));
35
36 do {
37 udelay(1);
38 val = readl_relaxed(pcubase + PCU_DM_ACK_SYNC(zpd))
39 & BIT(zpd->bit);
40 } while (--loop && !val);
41
42 if (!loop) {
43 pr_err("Error: %s %s fail\n", __func__, domain->name);
44 return -EIO;
45 }
46
47 val = readl_relaxed(pcubase + PCU_DM_RSTEN(zpd));
48 val |= BIT(zpd->bit);
49 writel_relaxed(val, pcubase + PCU_DM_RSTEN(zpd));
50 udelay(5);
51
52 val = readl_relaxed(pcubase + PCU_DM_ISOEN(zpd));
53 val &= ~BIT(zpd->bit);
54 writel_relaxed(val, pcubase + PCU_DM_ISOEN(zpd));
55 udelay(5);
56
57 val = readl_relaxed(pcubase + PCU_DM_CLKEN(zpd));
58 val |= BIT(zpd->bit);
59 writel_relaxed(val, pcubase + PCU_DM_CLKEN(zpd));
60 udelay(5);
61
62 pr_debug("poweron %s\n", domain->name);
63
64 return 0;
65}
66
67static int zx2967_power_off(struct generic_pm_domain *domain)
68{
69 struct zx2967_pm_domain *zpd = (struct zx2967_pm_domain *)domain;
70 unsigned long loop = 1000;
71 u32 val;
72
73 val = readl_relaxed(pcubase + PCU_DM_CLKEN(zpd));
74 val &= ~BIT(zpd->bit);
75 writel_relaxed(val, pcubase + PCU_DM_CLKEN(zpd));
76 udelay(5);
77
78 val = readl_relaxed(pcubase + PCU_DM_ISOEN(zpd));
79 val |= BIT(zpd->bit);
80 writel_relaxed(val, pcubase + PCU_DM_ISOEN(zpd));
81 udelay(5);
82
83 val = readl_relaxed(pcubase + PCU_DM_RSTEN(zpd));
84 val &= ~BIT(zpd->bit);
85 writel_relaxed(val, pcubase + PCU_DM_RSTEN(zpd));
86 udelay(5);
87
88 val = readl_relaxed(pcubase + PCU_DM_PWREN(zpd));
89 if (zpd->polarity == PWREN)
90 val &= ~BIT(zpd->bit);
91 else
92 val |= BIT(zpd->bit);
93 writel_relaxed(val, pcubase + PCU_DM_PWREN(zpd));
94
95 do {
96 udelay(1);
97 val = readl_relaxed(pcubase + PCU_DM_ACK_SYNC(zpd))
98 & BIT(zpd->bit);
99 } while (--loop && val);
100
101 if (!loop) {
102 pr_err("Error: %s %s fail\n", __func__, domain->name);
103 return -EIO;
104 }
105
106 pr_debug("poweroff %s\n", domain->name);
107
108 return 0;
109}
110
111int zx2967_pd_probe(struct platform_device *pdev,
112 struct generic_pm_domain **zx_pm_domains,
113 int domain_num)
114{
115 struct genpd_onecell_data *genpd_data;
116 struct resource *res;
117 int i;
118
119 genpd_data = devm_kzalloc(&pdev->dev, sizeof(*genpd_data), GFP_KERNEL);
120 if (!genpd_data)
121 return -ENOMEM;
122
123 genpd_data->domains = zx_pm_domains;
124 genpd_data->num_domains = domain_num;
125
126 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
127 pcubase = devm_ioremap_resource(&pdev->dev, res);
128 if (IS_ERR(pcubase)) {
129 dev_err(&pdev->dev, "ioremap fail.\n");
130 return PTR_ERR(pcubase);
131 }
132
133 for (i = 0; i < domain_num; ++i) {
134 zx_pm_domains[i]->power_on = zx2967_power_on;
135 zx_pm_domains[i]->power_off = zx2967_power_off;
136
137 pm_genpd_init(zx_pm_domains[i], NULL, false);
138 }
139
140 of_genpd_add_provider_onecell(pdev->dev.of_node, genpd_data);
141 dev_info(&pdev->dev, "powerdomain init ok\n");
142 return 0;
143}
diff --git a/drivers/soc/zte/zx2967_pm_domains.h b/drivers/soc/zte/zx2967_pm_domains.h
new file mode 100644
index 000000000000..cb46595a7ff3
--- /dev/null
+++ b/drivers/soc/zte/zx2967_pm_domains.h
@@ -0,0 +1,44 @@
1/*
2 * Header for ZTE's Power Domain Driver support
3 *
4 * Copyright (C) 2017 ZTE Ltd.
5 *
6 * Author: Baoyou Xie <baoyou.xie@linaro.org>
7 * License terms: GNU General Public License (GPL) version 2
8 */
9
10#ifndef __ZTE_ZX2967_PM_DOMAIN_H
11#define __ZTE_ZX2967_PM_DOMAIN_H
12
13#include <linux/platform_device.h>
14#include <linux/pm_domain.h>
15
16enum {
17 REG_CLKEN,
18 REG_ISOEN,
19 REG_RSTEN,
20 REG_PWREN,
21 REG_PWRDN,
22 REG_ACK_SYNC,
23
24 /* The size of the array - must be last */
25 REG_ARRAY_SIZE,
26};
27
28enum zx2967_power_polarity {
29 PWREN,
30 PWRDN,
31};
32
33struct zx2967_pm_domain {
34 struct generic_pm_domain dm;
35 const u16 bit;
36 const enum zx2967_power_polarity polarity;
37 const u16 *reg_offset;
38};
39
40int zx2967_pd_probe(struct platform_device *pdev,
41 struct generic_pm_domain **zx_pm_domains,
42 int domain_num);
43
44#endif /* __ZTE_ZX2967_PM_DOMAIN_H */
diff --git a/include/dt-bindings/soc/zte,pm_domains.h b/include/dt-bindings/soc/zte,pm_domains.h
new file mode 100644
index 000000000000..a0b4019c8e01
--- /dev/null
+++ b/include/dt-bindings/soc/zte,pm_domains.h
@@ -0,0 +1,24 @@
1/*
2 * Copyright (C) 2017 Linaro Ltd.
3 *
4 * Author: Baoyou Xie <baoyou.xie@linaro.org>
5 * License terms: GNU General Public License (GPL) version 2
6 */
7
8#ifndef _DT_BINDINGS_SOC_ZTE_PM_DOMAINS_H
9#define _DT_BINDINGS_SOC_ZTE_PM_DOMAINS_H
10
11#define DM_ZX296718_SAPPU 0
12#define DM_ZX296718_VDE 1 /* g1v6 */
13#define DM_ZX296718_VCE 2 /* h1v6 */
14#define DM_ZX296718_HDE 3 /* g2v2 */
15#define DM_ZX296718_VIU 4
16#define DM_ZX296718_USB20 5
17#define DM_ZX296718_USB21 6
18#define DM_ZX296718_USB30 7
19#define DM_ZX296718_HSIC 8
20#define DM_ZX296718_GMAC 9
21#define DM_ZX296718_TS 10
22#define DM_ZX296718_VOU 11
23
24#endif /* _DT_BINDINGS_SOC_ZTE_PM_DOMAINS_H */