aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2016-04-26 04:21:57 -0400
committerArnd Bergmann <arnd@arndb.de>2016-04-26 04:21:57 -0400
commita183d7f846de1ea87b9010f0aab77d2f4915e064 (patch)
tree89473fdfb30faf7092bf2e22b0c74e325113f0b5
parent2b9cf18982b0ba7317f258663560e181594a9bf8 (diff)
parent23f1e2ecdecee9f2ec45de0a468b82bb1f7f3ca2 (diff)
Merge tag 'renesas-rcar-sysc2-for-v4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas into next/drivers
Merge "Second Round of Renesas ARM Based SoC R-Car SYSC Updates for v4.7" from Simon Horman: Introduce a DT-based driver for the R-Car System Controller, as found on Renesas R-Car H1, R-Car Gen2, and R-Car Gen3 SoCs. * tag 'renesas-rcar-sysc2-for-v4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas: (30 commits) soc: renesas: rcar-sysc: Add support for R-Car H3 power areas soc: renesas: rcar-sysc: Add support for R-Car E2 power areas soc: renesas: rcar-sysc: Add support for R-Car M2-N power areas soc: renesas: rcar-sysc: Add support for R-Car M2-W power areas soc: renesas: rcar-sysc: Add support for R-Car H2 power areas soc: renesas: rcar-sysc: Add support for R-Car H1 power areas soc: renesas: rcar-sysc: Enable Clock Domain for I/O devices soc: renesas: rcar-sysc: Make rcar_sysc_power_is_off() static soc: renesas: rcar-sysc: Add DT support for SYSC PM domains soc: renesas: rcar-sysc: Improve rcar_sysc_power() debug info soc: renesas: Move pm-rcar to drivers/soc/renesas/rcar-sysc clk: renesas: cpg-mssr: Export cpg_mssr_{at,de}tach_dev() clk: renesas: mstp: Provide dummy attach/detach_dev callbacks clk: renesas: Provide Kconfig symbols for CPG/MSSR and CPG/MSTP support soc: renesas: Add r8a7795 SYSC PM Domain Binding Definitions soc: renesas: Add r8a7794 SYSC PM Domain Binding Definitions soc: renesas: Add r8a7793 SYSC PM Domain Binding Definitions soc: renesas: Add r8a7791 SYSC PM Domain Binding Definitions soc: renesas: Add r8a7790 SYSC PM Domain Binding Definitions soc: renesas: Add r8a7779 SYSC PM Domain Binding Definitions ...
-rw-r--r--Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt48
-rw-r--r--MAINTAINERS4
-rw-r--r--arch/arm/mach-shmobile/Kconfig11
-rw-r--r--arch/arm/mach-shmobile/Makefile1
-rw-r--r--arch/arm/mach-shmobile/pm-r8a7779.c3
-rw-r--r--arch/arm/mach-shmobile/pm-rcar-gen2.c2
-rw-r--r--arch/arm/mach-shmobile/pm-rcar.c164
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7779.c2
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7790.c2
-rw-r--r--drivers/clk/Kconfig1
-rw-r--r--drivers/clk/renesas/Kconfig16
-rw-r--r--drivers/clk/renesas/Makefile26
-rw-r--r--drivers/clk/renesas/clk-mstp.c7
-rw-r--r--drivers/clk/renesas/r8a7795-cpg-mssr.c34
-rw-r--r--drivers/clk/renesas/renesas-cpg-mssr.c47
-rw-r--r--drivers/clk/renesas/renesas-cpg-mssr.h6
-rw-r--r--drivers/soc/Makefile3
-rw-r--r--drivers/soc/renesas/Makefile7
-rw-r--r--drivers/soc/renesas/r8a7779-sysc.c34
-rw-r--r--drivers/soc/renesas/r8a7790-sysc.c48
-rw-r--r--drivers/soc/renesas/r8a7791-sysc.c33
-rw-r--r--drivers/soc/renesas/r8a7794-sysc.c33
-rw-r--r--drivers/soc/renesas/r8a7795-sysc.c56
-rw-r--r--drivers/soc/renesas/rcar-sysc.c401
-rw-r--r--drivers/soc/renesas/rcar-sysc.h58
-rw-r--r--include/dt-bindings/power/r8a7779-sysc.h27
-rw-r--r--include/dt-bindings/power/r8a7790-sysc.h34
-rw-r--r--include/dt-bindings/power/r8a7791-sysc.h26
-rw-r--r--include/dt-bindings/power/r8a7793-sysc.h28
-rw-r--r--include/dt-bindings/power/r8a7794-sysc.h26
-rw-r--r--include/dt-bindings/power/r8a7795-sysc.h42
-rw-r--r--include/linux/clk/renesas.h16
-rw-r--r--include/linux/soc/renesas/rcar-sysc.h (renamed from arch/arm/mach-shmobile/pm-rcar.h)9
33 files changed, 1023 insertions, 232 deletions
diff --git a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt
new file mode 100644
index 000000000000..b74e4d4785ab
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt
@@ -0,0 +1,48 @@
1DT bindings for the Renesas R-Car System Controller
2
3== System Controller Node ==
4
5The R-Car System Controller provides power management for the CPU cores and
6various coprocessors.
7
8Required properties:
9 - compatible: Must contain exactly one of the following:
10 - "renesas,r8a7779-sysc" (R-Car H1)
11 - "renesas,r8a7790-sysc" (R-Car H2)
12 - "renesas,r8a7791-sysc" (R-Car M2-W)
13 - "renesas,r8a7792-sysc" (R-Car V2H)
14 - "renesas,r8a7793-sysc" (R-Car M2-N)
15 - "renesas,r8a7794-sysc" (R-Car E2)
16 - "renesas,r8a7795-sysc" (R-Car H3)
17 - reg: Address start and address range for the device.
18 - #power-domain-cells: Must be 1.
19
20
21Example:
22
23 sysc: system-controller@e6180000 {
24 compatible = "renesas,r8a7791-sysc";
25 reg = <0 0xe6180000 0 0x0200>;
26 #power-domain-cells = <1>;
27 };
28
29
30== PM Domain Consumers ==
31
32Devices residing in a power area must refer to that power area, as documented
33by the generic PM domain bindings in
34Documentation/devicetree/bindings/power/power_domain.txt.
35
36Required properties:
37 - power-domains: A phandle and symbolic PM domain specifier, as defined in
38 <dt-bindings/power/r8a77*-sysc.h>.
39
40
41Example:
42
43 L2_CA15: cache-controller@0 {
44 compatible = "cache";
45 power-domains = <&sysc R8A7791_PD_CA15_SCU>;
46 cache-unified;
47 cache-level = <2>;
48 };
diff --git a/MAINTAINERS b/MAINTAINERS
index ee877ff96213..d15c64368037 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1494,6 +1494,8 @@ Q: http://patchwork.kernel.org/project/linux-renesas-soc/list/
1494T: git git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next 1494T: git git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next
1495S: Supported 1495S: Supported
1496F: arch/arm64/boot/dts/renesas/ 1496F: arch/arm64/boot/dts/renesas/
1497F: drivers/soc/renesas/
1498F: include/linux/soc/renesas/
1497 1499
1498ARM/RISCPC ARCHITECTURE 1500ARM/RISCPC ARCHITECTURE
1499M: Russell King <linux@arm.linux.org.uk> 1501M: Russell King <linux@arm.linux.org.uk>
@@ -1607,6 +1609,8 @@ F: arch/arm/configs/shmobile_defconfig
1607F: arch/arm/include/debug/renesas-scif.S 1609F: arch/arm/include/debug/renesas-scif.S
1608F: arch/arm/mach-shmobile/ 1610F: arch/arm/mach-shmobile/
1609F: drivers/sh/ 1611F: drivers/sh/
1612F: drivers/soc/renesas/
1613F: include/linux/soc/renesas/
1610 1614
1611ARM/SOCFPGA ARCHITECTURE 1615ARM/SOCFPGA ARCHITECTURE
1612M: Dinh Nguyen <dinguyen@opensource.altera.com> 1616M: Dinh Nguyen <dinguyen@opensource.altera.com>
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index f2bc5c353119..fe4ccb52f921 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -4,11 +4,6 @@ config ARCH_SHMOBILE
4config ARCH_SHMOBILE_MULTI 4config ARCH_SHMOBILE_MULTI
5 bool 5 bool
6 6
7config PM_RCAR
8 bool
9 select PM
10 select PM_GENERIC_DOMAINS
11
12config PM_RMOBILE 7config PM_RMOBILE
13 bool 8 bool
14 select PM 9 select PM
@@ -16,13 +11,15 @@ config PM_RMOBILE
16 11
17config ARCH_RCAR_GEN1 12config ARCH_RCAR_GEN1
18 bool 13 bool
19 select PM_RCAR 14 select PM
15 select PM_GENERIC_DOMAINS
20 select RENESAS_INTC_IRQPIN 16 select RENESAS_INTC_IRQPIN
21 select SYS_SUPPORTS_SH_TMU 17 select SYS_SUPPORTS_SH_TMU
22 18
23config ARCH_RCAR_GEN2 19config ARCH_RCAR_GEN2
24 bool 20 bool
25 select PM_RCAR 21 select PM
22 select PM_GENERIC_DOMAINS
26 select RENESAS_IRQC 23 select RENESAS_IRQC
27 select SYS_SUPPORTS_SH_CMT 24 select SYS_SUPPORTS_SH_CMT
28 select PCI_DOMAINS if PCI 25 select PCI_DOMAINS if PCI
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index a65c80ac9009..ebb909c55b85 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -39,7 +39,6 @@ smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o
39# PM objects 39# PM objects
40obj-$(CONFIG_SUSPEND) += suspend.o 40obj-$(CONFIG_SUSPEND) += suspend.o
41obj-$(CONFIG_CPU_FREQ) += cpufreq.o 41obj-$(CONFIG_CPU_FREQ) += cpufreq.o
42obj-$(CONFIG_PM_RCAR) += pm-rcar.o
43obj-$(CONFIG_PM_RMOBILE) += pm-rmobile.o 42obj-$(CONFIG_PM_RMOBILE) += pm-rmobile.o
44obj-$(CONFIG_ARCH_RCAR_GEN2) += pm-rcar-gen2.o 43obj-$(CONFIG_ARCH_RCAR_GEN2) += pm-rcar-gen2.o
45 44
diff --git a/arch/arm/mach-shmobile/pm-r8a7779.c b/arch/arm/mach-shmobile/pm-r8a7779.c
index 14c42a1bdf1e..4174cbcbc467 100644
--- a/arch/arm/mach-shmobile/pm-r8a7779.c
+++ b/arch/arm/mach-shmobile/pm-r8a7779.c
@@ -9,9 +9,10 @@
9 * for more details. 9 * for more details.
10 */ 10 */
11 11
12#include <linux/soc/renesas/rcar-sysc.h>
13
12#include <asm/io.h> 14#include <asm/io.h>
13 15
14#include "pm-rcar.h"
15#include "r8a7779.h" 16#include "r8a7779.h"
16 17
17/* SYSC */ 18/* SYSC */
diff --git a/arch/arm/mach-shmobile/pm-rcar-gen2.c b/arch/arm/mach-shmobile/pm-rcar-gen2.c
index 6815781ad116..691ac166a277 100644
--- a/arch/arm/mach-shmobile/pm-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/pm-rcar-gen2.c
@@ -13,9 +13,9 @@
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/smp.h> 15#include <linux/smp.h>
16#include <linux/soc/renesas/rcar-sysc.h>
16#include <asm/io.h> 17#include <asm/io.h>
17#include "common.h" 18#include "common.h"
18#include "pm-rcar.h"
19#include "rcar-gen2.h" 19#include "rcar-gen2.h"
20 20
21/* RST */ 21/* RST */
diff --git a/arch/arm/mach-shmobile/pm-rcar.c b/arch/arm/mach-shmobile/pm-rcar.c
deleted file mode 100644
index 0af05d288b09..000000000000
--- a/arch/arm/mach-shmobile/pm-rcar.c
+++ /dev/null
@@ -1,164 +0,0 @@
1/*
2 * R-Car SYSC Power management support
3 *
4 * Copyright (C) 2014 Magnus Damm
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/delay.h>
12#include <linux/err.h>
13#include <linux/mm.h>
14#include <linux/spinlock.h>
15#include <linux/io.h>
16#include "pm-rcar.h"
17
18/* SYSC Common */
19#define SYSCSR 0x00 /* SYSC Status Register */
20#define SYSCISR 0x04 /* Interrupt Status Register */
21#define SYSCISCR 0x08 /* Interrupt Status Clear Register */
22#define SYSCIER 0x0c /* Interrupt Enable Register */
23#define SYSCIMR 0x10 /* Interrupt Mask Register */
24
25/* SYSC Status Register */
26#define SYSCSR_PONENB 1 /* Ready for power resume requests */
27#define SYSCSR_POFFENB 0 /* Ready for power shutoff requests */
28
29/*
30 * Power Control Register Offsets inside the register block for each domain
31 * Note: The "CR" registers for ARM cores exist on H1 only
32 * Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2
33 */
34#define PWRSR_OFFS 0x00 /* Power Status Register */
35#define PWROFFCR_OFFS 0x04 /* Power Shutoff Control Register */
36#define PWROFFSR_OFFS 0x08 /* Power Shutoff Status Register */
37#define PWRONCR_OFFS 0x0c /* Power Resume Control Register */
38#define PWRONSR_OFFS 0x10 /* Power Resume Status Register */
39#define PWRER_OFFS 0x14 /* Power Shutoff/Resume Error */
40
41
42#define SYSCSR_RETRIES 100
43#define SYSCSR_DELAY_US 1
44
45#define PWRER_RETRIES 100
46#define PWRER_DELAY_US 1
47
48#define SYSCISR_RETRIES 1000
49#define SYSCISR_DELAY_US 1
50
51static void __iomem *rcar_sysc_base;
52static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
53
54static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on)
55{
56 unsigned int sr_bit, reg_offs;
57 int k;
58
59 if (on) {
60 sr_bit = SYSCSR_PONENB;
61 reg_offs = PWRONCR_OFFS;
62 } else {
63 sr_bit = SYSCSR_POFFENB;
64 reg_offs = PWROFFCR_OFFS;
65 }
66
67 /* Wait until SYSC is ready to accept a power request */
68 for (k = 0; k < SYSCSR_RETRIES; k++) {
69 if (ioread32(rcar_sysc_base + SYSCSR) & BIT(sr_bit))
70 break;
71 udelay(SYSCSR_DELAY_US);
72 }
73
74 if (k == SYSCSR_RETRIES)
75 return -EAGAIN;
76
77 /* Submit power shutoff or power resume request */
78 iowrite32(BIT(sysc_ch->chan_bit),
79 rcar_sysc_base + sysc_ch->chan_offs + reg_offs);
80
81 return 0;
82}
83
84static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
85{
86 unsigned int isr_mask = BIT(sysc_ch->isr_bit);
87 unsigned int chan_mask = BIT(sysc_ch->chan_bit);
88 unsigned int status;
89 unsigned long flags;
90 int ret = 0;
91 int k;
92
93 spin_lock_irqsave(&rcar_sysc_lock, flags);
94
95 iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
96
97 /* Submit power shutoff or resume request until it was accepted */
98 for (k = 0; k < PWRER_RETRIES; k++) {
99 ret = rcar_sysc_pwr_on_off(sysc_ch, on);
100 if (ret)
101 goto out;
102
103 status = ioread32(rcar_sysc_base +
104 sysc_ch->chan_offs + PWRER_OFFS);
105 if (!(status & chan_mask))
106 break;
107
108 udelay(PWRER_DELAY_US);
109 }
110
111 if (k == PWRER_RETRIES) {
112 ret = -EIO;
113 goto out;
114 }
115
116 /* Wait until the power shutoff or resume request has completed * */
117 for (k = 0; k < SYSCISR_RETRIES; k++) {
118 if (ioread32(rcar_sysc_base + SYSCISR) & isr_mask)
119 break;
120 udelay(SYSCISR_DELAY_US);
121 }
122
123 if (k == SYSCISR_RETRIES)
124 ret = -EIO;
125
126 iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
127
128 out:
129 spin_unlock_irqrestore(&rcar_sysc_lock, flags);
130
131 pr_debug("sysc power domain %d: %08x -> %d\n",
132 sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret);
133 return ret;
134}
135
136int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
137{
138 return rcar_sysc_power(sysc_ch, false);
139}
140
141int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
142{
143 return rcar_sysc_power(sysc_ch, true);
144}
145
146bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch)
147{
148 unsigned int st;
149
150 st = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRSR_OFFS);
151 if (st & BIT(sysc_ch->chan_bit))
152 return true;
153
154 return false;
155}
156
157void __iomem *rcar_sysc_init(phys_addr_t base)
158{
159 rcar_sysc_base = ioremap_nocache(base, PAGE_SIZE);
160 if (!rcar_sysc_base)
161 panic("unable to ioremap R-Car SYSC hardware block\n");
162
163 return rcar_sysc_base;
164}
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index f5c31fbc10b2..c6951ee24588 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -19,13 +19,13 @@
19#include <linux/spinlock.h> 19#include <linux/spinlock.h>
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/soc/renesas/rcar-sysc.h>
22 23
23#include <asm/cacheflush.h> 24#include <asm/cacheflush.h>
24#include <asm/smp_plat.h> 25#include <asm/smp_plat.h>
25#include <asm/smp_scu.h> 26#include <asm/smp_scu.h>
26 27
27#include "common.h" 28#include "common.h"
28#include "pm-rcar.h"
29#include "r8a7779.h" 29#include "r8a7779.h"
30 30
31#define AVECR IOMEM(0xfe700040) 31#define AVECR IOMEM(0xfe700040)
diff --git a/arch/arm/mach-shmobile/smp-r8a7790.c b/arch/arm/mach-shmobile/smp-r8a7790.c
index f6426c6fdefc..28f26d5362d8 100644
--- a/arch/arm/mach-shmobile/smp-r8a7790.c
+++ b/arch/arm/mach-shmobile/smp-r8a7790.c
@@ -17,12 +17,12 @@
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/smp.h> 18#include <linux/smp.h>
19#include <linux/io.h> 19#include <linux/io.h>
20#include <linux/soc/renesas/rcar-sysc.h>
20 21
21#include <asm/smp_plat.h> 22#include <asm/smp_plat.h>
22 23
23#include "common.h" 24#include "common.h"
24#include "platsmp-apmu.h" 25#include "platsmp-apmu.h"
25#include "pm-rcar.h"
26#include "rcar-gen2.h" 26#include "rcar-gen2.h"
27#include "r8a7790.h" 27#include "r8a7790.h"
28 28
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 16f7d33421d8..c45554957499 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -201,6 +201,7 @@ source "drivers/clk/bcm/Kconfig"
201source "drivers/clk/hisilicon/Kconfig" 201source "drivers/clk/hisilicon/Kconfig"
202source "drivers/clk/mvebu/Kconfig" 202source "drivers/clk/mvebu/Kconfig"
203source "drivers/clk/qcom/Kconfig" 203source "drivers/clk/qcom/Kconfig"
204source "drivers/clk/renesas/Kconfig"
204source "drivers/clk/samsung/Kconfig" 205source "drivers/clk/samsung/Kconfig"
205source "drivers/clk/tegra/Kconfig" 206source "drivers/clk/tegra/Kconfig"
206source "drivers/clk/ti/Kconfig" 207source "drivers/clk/ti/Kconfig"
diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig
new file mode 100644
index 000000000000..2115ce410cfb
--- /dev/null
+++ b/drivers/clk/renesas/Kconfig
@@ -0,0 +1,16 @@
1config CLK_RENESAS_CPG_MSSR
2 bool
3 default y if ARCH_R8A7795
4
5config CLK_RENESAS_CPG_MSTP
6 bool
7 default y if ARCH_R7S72100
8 default y if ARCH_R8A73A4
9 default y if ARCH_R8A7740
10 default y if ARCH_R8A7778
11 default y if ARCH_R8A7779
12 default y if ARCH_R8A7790
13 default y if ARCH_R8A7791
14 default y if ARCH_R8A7793
15 default y if ARCH_R8A7794
16 default y if ARCH_SH73A0
diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile
index 7e2579b30326..ead8bb843524 100644
--- a/drivers/clk/renesas/Makefile
+++ b/drivers/clk/renesas/Makefile
@@ -1,13 +1,15 @@
1obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o 1obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o
2obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o clk-mstp.o 2obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o
3obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-mstp.o clk-div6.o 3obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-div6.o
4obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-mstp.o clk-div6.o 4obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-div6.o
5obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o clk-mstp.o 5obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o
6obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o clk-mstp.o 6obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o
7obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-mstp.o clk-div6.o 7obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-div6.o
8obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-mstp.o clk-div6.o 8obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-div6.o
9obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-mstp.o clk-div6.o 9obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-div6.o
10obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-mstp.o clk-div6.o 10obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-div6.o
11obj-$(CONFIG_ARCH_R8A7795) += renesas-cpg-mssr.o \ 11obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o
12 r8a7795-cpg-mssr.o clk-div6.o 12obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-div6.o
13obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-mstp.o clk-div6.o 13
14obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o clk-div6.o
15obj-$(CONFIG_CLK_RENESAS_CPG_MSTP) += clk-mstp.o
diff --git a/drivers/clk/renesas/clk-mstp.c b/drivers/clk/renesas/clk-mstp.c
index 3d44e183aedd..8b597b9a3804 100644
--- a/drivers/clk/renesas/clk-mstp.c
+++ b/drivers/clk/renesas/clk-mstp.c
@@ -243,9 +243,7 @@ static void __init cpg_mstp_clocks_init(struct device_node *np)
243} 243}
244CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init); 244CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init);
245 245
246 246int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev)
247#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
248int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev)
249{ 247{
250 struct device_node *np = dev->of_node; 248 struct device_node *np = dev->of_node;
251 struct of_phandle_args clkspec; 249 struct of_phandle_args clkspec;
@@ -297,7 +295,7 @@ fail_put:
297 return error; 295 return error;
298} 296}
299 297
300void cpg_mstp_detach_dev(struct generic_pm_domain *domain, struct device *dev) 298void cpg_mstp_detach_dev(struct generic_pm_domain *unused, struct device *dev)
301{ 299{
302 if (!list_empty(&dev->power.subsys_data->clock_list)) 300 if (!list_empty(&dev->power.subsys_data->clock_list))
303 pm_clk_destroy(dev); 301 pm_clk_destroy(dev);
@@ -326,4 +324,3 @@ void __init cpg_mstp_add_clk_domain(struct device_node *np)
326 324
327 of_genpd_add_provider_simple(np, pd); 325 of_genpd_add_provider_simple(np, pd);
328} 326}
329#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */
diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c
index b2198aef5ed4..6af7f5b6e824 100644
--- a/drivers/clk/renesas/r8a7795-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c
@@ -13,6 +13,7 @@
13 */ 13 */
14 14
15#include <linux/bug.h> 15#include <linux/bug.h>
16#include <linux/clk.h>
16#include <linux/clk-provider.h> 17#include <linux/clk-provider.h>
17#include <linux/device.h> 18#include <linux/device.h>
18#include <linux/err.h> 19#include <linux/err.h>
@@ -26,6 +27,7 @@
26 27
27#include "renesas-cpg-mssr.h" 28#include "renesas-cpg-mssr.h"
28 29
30#define CPG_RCKCR 0x240
29 31
30enum clk_ids { 32enum clk_ids {
31 /* Core Clock Outputs exported to DT */ 33 /* Core Clock Outputs exported to DT */
@@ -50,6 +52,7 @@ enum clk_ids {
50 CLK_S3, 52 CLK_S3,
51 CLK_SDSRC, 53 CLK_SDSRC,
52 CLK_SSPSRC, 54 CLK_SSPSRC,
55 CLK_RINT,
53 56
54 /* Module Clocks */ 57 /* Module Clocks */
55 MOD_CLK_BASE 58 MOD_CLK_BASE
@@ -63,8 +66,12 @@ enum r8a7795_clk_types {
63 CLK_TYPE_GEN3_PLL3, 66 CLK_TYPE_GEN3_PLL3,
64 CLK_TYPE_GEN3_PLL4, 67 CLK_TYPE_GEN3_PLL4,
65 CLK_TYPE_GEN3_SD, 68 CLK_TYPE_GEN3_SD,
69 CLK_TYPE_GEN3_R,
66}; 70};
67 71
72#define DEF_GEN3_SD(_name, _id, _parent, _offset) \
73 DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset)
74
68static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { 75static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
69 /* External Clock Inputs */ 76 /* External Clock Inputs */
70 DEF_INPUT("extal", CLK_EXTAL), 77 DEF_INPUT("extal", CLK_EXTAL),
@@ -102,10 +109,10 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
102 DEF_FIXED("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1), 109 DEF_FIXED("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1),
103 DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1), 110 DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1),
104 111
105 DEF_SD("sd0", R8A7795_CLK_SD0, CLK_PLL1_DIV2, 0x0074), 112 DEF_GEN3_SD("sd0", R8A7795_CLK_SD0, CLK_PLL1_DIV2, 0x0074),
106 DEF_SD("sd1", R8A7795_CLK_SD1, CLK_PLL1_DIV2, 0x0078), 113 DEF_GEN3_SD("sd1", R8A7795_CLK_SD1, CLK_PLL1_DIV2, 0x0078),
107 DEF_SD("sd2", R8A7795_CLK_SD2, CLK_PLL1_DIV2, 0x0268), 114 DEF_GEN3_SD("sd2", R8A7795_CLK_SD2, CLK_PLL1_DIV2, 0x0268),
108 DEF_SD("sd3", R8A7795_CLK_SD3, CLK_PLL1_DIV2, 0x026c), 115 DEF_GEN3_SD("sd3", R8A7795_CLK_SD3, CLK_PLL1_DIV2, 0x026c),
109 116
110 DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1), 117 DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1),
111 DEF_FIXED("cp", R8A7795_CLK_CP, CLK_EXTAL, 2, 1), 118 DEF_FIXED("cp", R8A7795_CLK_CP, CLK_EXTAL, 2, 1),
@@ -113,6 +120,11 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
113 DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014), 120 DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014),
114 DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV2, 0x250), 121 DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV2, 0x250),
115 DEF_DIV6P1("canfd", R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244), 122 DEF_DIV6P1("canfd", R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
123
124 DEF_DIV6_RO("osc", R8A7795_CLK_OSC, CLK_EXTAL, CPG_RCKCR, 8),
125 DEF_DIV6_RO("r_int", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32),
126
127 DEF_BASE("r", R8A7795_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
116}; 128};
117 129
118static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { 130static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
@@ -139,6 +151,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
139 DEF_MOD("usb3-if0", 328, R8A7795_CLK_S3D1), 151 DEF_MOD("usb3-if0", 328, R8A7795_CLK_S3D1),
140 DEF_MOD("usb-dmac0", 330, R8A7795_CLK_S3D1), 152 DEF_MOD("usb-dmac0", 330, R8A7795_CLK_S3D1),
141 DEF_MOD("usb-dmac1", 331, R8A7795_CLK_S3D1), 153 DEF_MOD("usb-dmac1", 331, R8A7795_CLK_S3D1),
154 DEF_MOD("rwdt0", 402, R8A7795_CLK_R),
142 DEF_MOD("intc-ex", 407, R8A7795_CLK_CP), 155 DEF_MOD("intc-ex", 407, R8A7795_CLK_CP),
143 DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1), 156 DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1),
144 DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4), 157 DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4),
@@ -148,6 +161,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
148 DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1), 161 DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1),
149 DEF_MOD("hscif1", 519, R8A7795_CLK_S3D1), 162 DEF_MOD("hscif1", 519, R8A7795_CLK_S3D1),
150 DEF_MOD("hscif0", 520, R8A7795_CLK_S3D1), 163 DEF_MOD("hscif0", 520, R8A7795_CLK_S3D1),
164 DEF_MOD("pwm", 523, R8A7795_CLK_S3D4),
151 DEF_MOD("fcpvd3", 600, R8A7795_CLK_S2D1), 165 DEF_MOD("fcpvd3", 600, R8A7795_CLK_S2D1),
152 DEF_MOD("fcpvd2", 601, R8A7795_CLK_S2D1), 166 DEF_MOD("fcpvd2", 601, R8A7795_CLK_S2D1),
153 DEF_MOD("fcpvd1", 602, R8A7795_CLK_S2D1), 167 DEF_MOD("fcpvd1", 602, R8A7795_CLK_S2D1),
@@ -578,6 +592,18 @@ struct clk * __init r8a7795_cpg_clk_register(struct device *dev,
578 case CLK_TYPE_GEN3_SD: 592 case CLK_TYPE_GEN3_SD:
579 return cpg_sd_clk_register(core, base, __clk_get_name(parent)); 593 return cpg_sd_clk_register(core, base, __clk_get_name(parent));
580 594
595 case CLK_TYPE_GEN3_R:
596 /* RINT is default. Only if EXTALR is populated, we switch to it */
597 value = readl(base + CPG_RCKCR) & 0x3f;
598
599 if (clk_get_rate(clks[CLK_EXTALR])) {
600 parent = clks[CLK_EXTALR];
601 value |= BIT(15);
602 }
603
604 writel(value, base + CPG_RCKCR);
605 break;
606
581 default: 607 default:
582 return ERR_PTR(-EINVAL); 608 return ERR_PTR(-EINVAL);
583 } 609 }
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
index 58e24b326a48..1f2dc3629f0e 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.c
+++ b/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -15,6 +15,7 @@
15 15
16#include <linux/clk.h> 16#include <linux/clk.h>
17#include <linux/clk-provider.h> 17#include <linux/clk-provider.h>
18#include <linux/clk/renesas.h>
18#include <linux/device.h> 19#include <linux/device.h>
19#include <linux/init.h> 20#include <linux/init.h>
20#include <linux/mod_devicetable.h> 21#include <linux/mod_devicetable.h>
@@ -253,7 +254,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
253{ 254{
254 struct clk *clk = NULL, *parent; 255 struct clk *clk = NULL, *parent;
255 struct device *dev = priv->dev; 256 struct device *dev = priv->dev;
256 unsigned int id = core->id; 257 unsigned int id = core->id, div = core->div;
257 const char *parent_name; 258 const char *parent_name;
258 259
259 WARN_DEBUG(id >= priv->num_core_clks); 260 WARN_DEBUG(id >= priv->num_core_clks);
@@ -266,6 +267,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
266 267
267 case CLK_TYPE_FF: 268 case CLK_TYPE_FF:
268 case CLK_TYPE_DIV6P1: 269 case CLK_TYPE_DIV6P1:
270 case CLK_TYPE_DIV6_RO:
269 WARN_DEBUG(core->parent >= priv->num_core_clks); 271 WARN_DEBUG(core->parent >= priv->num_core_clks);
270 parent = priv->clks[core->parent]; 272 parent = priv->clks[core->parent];
271 if (IS_ERR(parent)) { 273 if (IS_ERR(parent)) {
@@ -274,13 +276,18 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
274 } 276 }
275 277
276 parent_name = __clk_get_name(parent); 278 parent_name = __clk_get_name(parent);
277 if (core->type == CLK_TYPE_FF) { 279
278 clk = clk_register_fixed_factor(NULL, core->name, 280 if (core->type == CLK_TYPE_DIV6_RO)
279 parent_name, 0, 281 /* Multiply with the DIV6 register value */
280 core->mult, core->div); 282 div *= (readl(priv->base + core->offset) & 0x3f) + 1;
281 } else { 283
284 if (core->type == CLK_TYPE_DIV6P1) {
282 clk = cpg_div6_register(core->name, 1, &parent_name, 285 clk = cpg_div6_register(core->name, 1, &parent_name,
283 priv->base + core->offset); 286 priv->base + core->offset);
287 } else {
288 clk = clk_register_fixed_factor(NULL, core->name,
289 parent_name, 0,
290 core->mult, div);
284 } 291 }
285 break; 292 break;
286 293
@@ -375,8 +382,6 @@ fail:
375 kfree(clock); 382 kfree(clock);
376} 383}
377 384
378
379#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
380struct cpg_mssr_clk_domain { 385struct cpg_mssr_clk_domain {
381 struct generic_pm_domain genpd; 386 struct generic_pm_domain genpd;
382 struct device_node *np; 387 struct device_node *np;
@@ -384,6 +389,8 @@ struct cpg_mssr_clk_domain {
384 unsigned int core_pm_clks[0]; 389 unsigned int core_pm_clks[0];
385}; 390};
386 391
392static struct cpg_mssr_clk_domain *cpg_mssr_clk_domain;
393
387static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec, 394static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec,
388 struct cpg_mssr_clk_domain *pd) 395 struct cpg_mssr_clk_domain *pd)
389{ 396{
@@ -407,17 +414,20 @@ static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec,
407 } 414 }
408} 415}
409 416
410static int cpg_mssr_attach_dev(struct generic_pm_domain *genpd, 417int cpg_mssr_attach_dev(struct generic_pm_domain *unused, struct device *dev)
411 struct device *dev)
412{ 418{
413 struct cpg_mssr_clk_domain *pd = 419 struct cpg_mssr_clk_domain *pd = cpg_mssr_clk_domain;
414 container_of(genpd, struct cpg_mssr_clk_domain, genpd);
415 struct device_node *np = dev->of_node; 420 struct device_node *np = dev->of_node;
416 struct of_phandle_args clkspec; 421 struct of_phandle_args clkspec;
417 struct clk *clk; 422 struct clk *clk;
418 int i = 0; 423 int i = 0;
419 int error; 424 int error;
420 425
426 if (!pd) {
427 dev_dbg(dev, "CPG/MSSR clock domain not yet available\n");
428 return -EPROBE_DEFER;
429 }
430
421 while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, 431 while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
422 &clkspec)) { 432 &clkspec)) {
423 if (cpg_mssr_is_pm_clk(&clkspec, pd)) 433 if (cpg_mssr_is_pm_clk(&clkspec, pd))
@@ -457,8 +467,7 @@ fail_put:
457 return error; 467 return error;
458} 468}
459 469
460static void cpg_mssr_detach_dev(struct generic_pm_domain *genpd, 470void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev)
461 struct device *dev)
462{ 471{
463 if (!list_empty(&dev->power.subsys_data->clock_list)) 472 if (!list_empty(&dev->power.subsys_data->clock_list))
464 pm_clk_destroy(dev); 473 pm_clk_destroy(dev);
@@ -487,19 +496,11 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
487 pm_genpd_init(genpd, &simple_qos_governor, false); 496 pm_genpd_init(genpd, &simple_qos_governor, false);
488 genpd->attach_dev = cpg_mssr_attach_dev; 497 genpd->attach_dev = cpg_mssr_attach_dev;
489 genpd->detach_dev = cpg_mssr_detach_dev; 498 genpd->detach_dev = cpg_mssr_detach_dev;
499 cpg_mssr_clk_domain = pd;
490 500
491 of_genpd_add_provider_simple(np, genpd); 501 of_genpd_add_provider_simple(np, genpd);
492 return 0; 502 return 0;
493} 503}
494#else
495static inline int cpg_mssr_add_clk_domain(struct device *dev,
496 const unsigned int *core_pm_clks,
497 unsigned int num_core_pm_clks)
498{
499 return 0;
500}
501#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */
502
503 504
504static const struct of_device_id cpg_mssr_match[] = { 505static const struct of_device_id cpg_mssr_match[] = {
505#ifdef CONFIG_ARCH_R8A7795 506#ifdef CONFIG_ARCH_R8A7795
diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h
index 952b6957233b..0d1e3e811e79 100644
--- a/drivers/clk/renesas/renesas-cpg-mssr.h
+++ b/drivers/clk/renesas/renesas-cpg-mssr.h
@@ -37,6 +37,7 @@ enum clk_types {
37 CLK_TYPE_IN, /* External Clock Input */ 37 CLK_TYPE_IN, /* External Clock Input */
38 CLK_TYPE_FF, /* Fixed Factor Clock */ 38 CLK_TYPE_FF, /* Fixed Factor Clock */
39 CLK_TYPE_DIV6P1, /* DIV6 Clock with 1 parent clock */ 39 CLK_TYPE_DIV6P1, /* DIV6 Clock with 1 parent clock */
40 CLK_TYPE_DIV6_RO, /* DIV6 Clock read only with extra divisor */
40 41
41 /* Custom definitions start here */ 42 /* Custom definitions start here */
42 CLK_TYPE_CUSTOM, 43 CLK_TYPE_CUSTOM,
@@ -53,9 +54,8 @@ enum clk_types {
53 DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult) 54 DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult)
54#define DEF_DIV6P1(_name, _id, _parent, _offset) \ 55#define DEF_DIV6P1(_name, _id, _parent, _offset) \
55 DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset) 56 DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset)
56#define DEF_SD(_name, _id, _parent, _offset) \ 57#define DEF_DIV6_RO(_name, _id, _parent, _offset, _div) \
57 DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset) 58 DEF_BASE(_name, _id, CLK_TYPE_DIV6_RO, _parent, .offset = _offset, .div = _div, .mult = 1)
58
59 59
60 /* 60 /*
61 * Definitions of Module Clocks 61 * Definitions of Module Clocks
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 5ade71306ee1..380230f03874 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -9,7 +9,8 @@ obj-$(CONFIG_MACH_DOVE) += dove/
9obj-y += fsl/ 9obj-y += fsl/
10obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ 10obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
11obj-$(CONFIG_ARCH_QCOM) += qcom/ 11obj-$(CONFIG_ARCH_QCOM) += qcom/
12obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ 12obj-$(CONFIG_ARCH_RENESAS) += renesas/
13obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
13obj-$(CONFIG_SOC_SAMSUNG) += samsung/ 14obj-$(CONFIG_SOC_SAMSUNG) += samsung/
14obj-$(CONFIG_ARCH_SUNXI) += sunxi/ 15obj-$(CONFIG_ARCH_SUNXI) += sunxi/
15obj-$(CONFIG_ARCH_TEGRA) += tegra/ 16obj-$(CONFIG_ARCH_TEGRA) += tegra/
diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile
new file mode 100644
index 000000000000..151fcd3f025b
--- /dev/null
+++ b/drivers/soc/renesas/Makefile
@@ -0,0 +1,7 @@
1obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o r8a7779-sysc.o
2obj-$(CONFIG_ARCH_R8A7790) += rcar-sysc.o r8a7790-sysc.o
3obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o r8a7791-sysc.o
4# R-Car M2-N is identical to R-Car M2-W w.r.t. power domains.
5obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o r8a7791-sysc.o
6obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o r8a7794-sysc.o
7obj-$(CONFIG_ARCH_R8A7795) += rcar-sysc.o r8a7795-sysc.o
diff --git a/drivers/soc/renesas/r8a7779-sysc.c b/drivers/soc/renesas/r8a7779-sysc.c
new file mode 100644
index 000000000000..9e8e6b7faa04
--- /dev/null
+++ b/drivers/soc/renesas/r8a7779-sysc.c
@@ -0,0 +1,34 @@
1/*
2 * Renesas R-Car H1 System Controller
3 *
4 * Copyright (C) 2016 Glider bvba
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 as published by
8 * the Free Software Foundation; version 2 of the License.
9 */
10
11#include <linux/bug.h>
12#include <linux/kernel.h>
13
14#include <dt-bindings/power/r8a7779-sysc.h>
15
16#include "rcar-sysc.h"
17
18static const struct rcar_sysc_area r8a7779_areas[] __initconst = {
19 { "always-on", 0, 0, R8A7779_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
20 { "arm1", 0x40, 1, R8A7779_PD_ARM1, R8A7779_PD_ALWAYS_ON,
21 PD_CPU_CR },
22 { "arm2", 0x40, 2, R8A7779_PD_ARM2, R8A7779_PD_ALWAYS_ON,
23 PD_CPU_CR },
24 { "arm3", 0x40, 3, R8A7779_PD_ARM3, R8A7779_PD_ALWAYS_ON,
25 PD_CPU_CR },
26 { "sgx", 0xc0, 0, R8A7779_PD_SGX, R8A7779_PD_ALWAYS_ON },
27 { "vdp", 0x100, 0, R8A7779_PD_VDP, R8A7779_PD_ALWAYS_ON },
28 { "imp", 0x140, 0, R8A7779_PD_IMP, R8A7779_PD_ALWAYS_ON },
29};
30
31const struct rcar_sysc_info r8a7779_sysc_info __initconst = {
32 .areas = r8a7779_areas,
33 .num_areas = ARRAY_SIZE(r8a7779_areas),
34};
diff --git a/drivers/soc/renesas/r8a7790-sysc.c b/drivers/soc/renesas/r8a7790-sysc.c
new file mode 100644
index 000000000000..7a567ad0ff73
--- /dev/null
+++ b/drivers/soc/renesas/r8a7790-sysc.c
@@ -0,0 +1,48 @@
1/*
2 * Renesas R-Car H2 System Controller
3 *
4 * Copyright (C) 2016 Glider bvba
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 as published by
8 * the Free Software Foundation; version 2 of the License.
9 */
10
11#include <linux/bug.h>
12#include <linux/kernel.h>
13
14#include <dt-bindings/power/r8a7790-sysc.h>
15
16#include "rcar-sysc.h"
17
18static const struct rcar_sysc_area r8a7790_areas[] __initconst = {
19 { "always-on", 0, 0, R8A7790_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
20 { "ca15-scu", 0x180, 0, R8A7790_PD_CA15_SCU, R8A7790_PD_ALWAYS_ON,
21 PD_SCU },
22 { "ca15-cpu0", 0x40, 0, R8A7790_PD_CA15_CPU0, R8A7790_PD_CA15_SCU,
23 PD_CPU_NOCR },
24 { "ca15-cpu1", 0x40, 1, R8A7790_PD_CA15_CPU1, R8A7790_PD_CA15_SCU,
25 PD_CPU_NOCR },
26 { "ca15-cpu2", 0x40, 2, R8A7790_PD_CA15_CPU2, R8A7790_PD_CA15_SCU,
27 PD_CPU_NOCR },
28 { "ca15-cpu3", 0x40, 3, R8A7790_PD_CA15_CPU3, R8A7790_PD_CA15_SCU,
29 PD_CPU_NOCR },
30 { "ca7-scu", 0x100, 0, R8A7790_PD_CA7_SCU, R8A7790_PD_ALWAYS_ON,
31 PD_SCU },
32 { "ca7-cpu0", 0x1c0, 0, R8A7790_PD_CA7_CPU0, R8A7790_PD_CA7_SCU,
33 PD_CPU_NOCR },
34 { "ca7-cpu1", 0x1c0, 1, R8A7790_PD_CA7_CPU1, R8A7790_PD_CA7_SCU,
35 PD_CPU_NOCR },
36 { "ca7-cpu2", 0x1c0, 2, R8A7790_PD_CA7_CPU2, R8A7790_PD_CA7_SCU,
37 PD_CPU_NOCR },
38 { "ca7-cpu3", 0x1c0, 3, R8A7790_PD_CA7_CPU3, R8A7790_PD_CA7_SCU,
39 PD_CPU_NOCR },
40 { "sh-4a", 0x80, 0, R8A7790_PD_SH_4A, R8A7790_PD_ALWAYS_ON },
41 { "rgx", 0xc0, 0, R8A7790_PD_RGX, R8A7790_PD_ALWAYS_ON },
42 { "imp", 0x140, 0, R8A7790_PD_IMP, R8A7790_PD_ALWAYS_ON },
43};
44
45const struct rcar_sysc_info r8a7790_sysc_info __initconst = {
46 .areas = r8a7790_areas,
47 .num_areas = ARRAY_SIZE(r8a7790_areas),
48};
diff --git a/drivers/soc/renesas/r8a7791-sysc.c b/drivers/soc/renesas/r8a7791-sysc.c
new file mode 100644
index 000000000000..03b9f41a34e6
--- /dev/null
+++ b/drivers/soc/renesas/r8a7791-sysc.c
@@ -0,0 +1,33 @@
1/*
2 * Renesas R-Car M2-W/N System Controller
3 *
4 * Copyright (C) 2016 Glider bvba
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 as published by
8 * the Free Software Foundation; version 2 of the License.
9 */
10
11#include <linux/bug.h>
12#include <linux/kernel.h>
13
14#include <dt-bindings/power/r8a7791-sysc.h>
15
16#include "rcar-sysc.h"
17
18static const struct rcar_sysc_area r8a7791_areas[] __initconst = {
19 { "always-on", 0, 0, R8A7791_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
20 { "ca15-scu", 0x180, 0, R8A7791_PD_CA15_SCU, R8A7791_PD_ALWAYS_ON,
21 PD_SCU },
22 { "ca15-cpu0", 0x40, 0, R8A7791_PD_CA15_CPU0, R8A7791_PD_CA15_SCU,
23 PD_CPU_NOCR },
24 { "ca15-cpu1", 0x40, 1, R8A7791_PD_CA15_CPU1, R8A7791_PD_CA15_SCU,
25 PD_CPU_NOCR },
26 { "sh-4a", 0x80, 0, R8A7791_PD_SH_4A, R8A7791_PD_ALWAYS_ON },
27 { "sgx", 0xc0, 0, R8A7791_PD_SGX, R8A7791_PD_ALWAYS_ON },
28};
29
30const struct rcar_sysc_info r8a7791_sysc_info __initconst = {
31 .areas = r8a7791_areas,
32 .num_areas = ARRAY_SIZE(r8a7791_areas),
33};
diff --git a/drivers/soc/renesas/r8a7794-sysc.c b/drivers/soc/renesas/r8a7794-sysc.c
new file mode 100644
index 000000000000..c4da2941e06c
--- /dev/null
+++ b/drivers/soc/renesas/r8a7794-sysc.c
@@ -0,0 +1,33 @@
1/*
2 * Renesas R-Car E2 System Controller
3 *
4 * Copyright (C) 2016 Glider bvba
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 as published by
8 * the Free Software Foundation; version 2 of the License.
9 */
10
11#include <linux/bug.h>
12#include <linux/kernel.h>
13
14#include <dt-bindings/power/r8a7794-sysc.h>
15
16#include "rcar-sysc.h"
17
18static const struct rcar_sysc_area r8a7794_areas[] __initconst = {
19 { "always-on", 0, 0, R8A7794_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
20 { "ca7-scu", 0x100, 0, R8A7794_PD_CA7_SCU, R8A7794_PD_ALWAYS_ON,
21 PD_SCU },
22 { "ca7-cpu0", 0x1c0, 0, R8A7794_PD_CA7_CPU0, R8A7794_PD_CA7_SCU,
23 PD_CPU_NOCR },
24 { "ca7-cpu1", 0x1c0, 1, R8A7794_PD_CA7_CPU1, R8A7794_PD_CA7_SCU,
25 PD_CPU_NOCR },
26 { "sh-4a", 0x80, 0, R8A7794_PD_SH_4A, R8A7794_PD_ALWAYS_ON },
27 { "sgx", 0xc0, 0, R8A7794_PD_SGX, R8A7794_PD_ALWAYS_ON },
28};
29
30const struct rcar_sysc_info r8a7794_sysc_info __initconst = {
31 .areas = r8a7794_areas,
32 .num_areas = ARRAY_SIZE(r8a7794_areas),
33};
diff --git a/drivers/soc/renesas/r8a7795-sysc.c b/drivers/soc/renesas/r8a7795-sysc.c
new file mode 100644
index 000000000000..5e7537c96f7b
--- /dev/null
+++ b/drivers/soc/renesas/r8a7795-sysc.c
@@ -0,0 +1,56 @@
1/*
2 * Renesas R-Car H3 System Controller
3 *
4 * Copyright (C) 2016 Glider bvba
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 as published by
8 * the Free Software Foundation; version 2 of the License.
9 */
10
11#include <linux/bug.h>
12#include <linux/kernel.h>
13
14#include <dt-bindings/power/r8a7795-sysc.h>
15
16#include "rcar-sysc.h"
17
18static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
19 { "always-on", 0, 0, R8A7795_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
20 { "ca57-scu", 0x1c0, 0, R8A7795_PD_CA57_SCU, R8A7795_PD_ALWAYS_ON,
21 PD_SCU },
22 { "ca57-cpu0", 0x80, 0, R8A7795_PD_CA57_CPU0, R8A7795_PD_CA57_SCU,
23 PD_CPU_NOCR },
24 { "ca57-cpu1", 0x80, 1, R8A7795_PD_CA57_CPU1, R8A7795_PD_CA57_SCU,
25 PD_CPU_NOCR },
26 { "ca57-cpu2", 0x80, 2, R8A7795_PD_CA57_CPU2, R8A7795_PD_CA57_SCU,
27 PD_CPU_NOCR },
28 { "ca57-cpu3", 0x80, 3, R8A7795_PD_CA57_CPU3, R8A7795_PD_CA57_SCU,
29 PD_CPU_NOCR },
30 { "ca53-scu", 0x140, 0, R8A7795_PD_CA53_SCU, R8A7795_PD_ALWAYS_ON,
31 PD_SCU },
32 { "ca53-cpu0", 0x200, 0, R8A7795_PD_CA53_CPU0, R8A7795_PD_CA53_SCU,
33 PD_CPU_NOCR },
34 { "ca53-cpu1", 0x200, 1, R8A7795_PD_CA53_CPU1, R8A7795_PD_CA53_SCU,
35 PD_CPU_NOCR },
36 { "ca53-cpu2", 0x200, 2, R8A7795_PD_CA53_CPU2, R8A7795_PD_CA53_SCU,
37 PD_CPU_NOCR },
38 { "ca53-cpu3", 0x200, 3, R8A7795_PD_CA53_CPU3, R8A7795_PD_CA53_SCU,
39 PD_CPU_NOCR },
40 { "a3vp", 0x340, 0, R8A7795_PD_A3VP, R8A7795_PD_ALWAYS_ON },
41 { "cr7", 0x240, 0, R8A7795_PD_CR7, R8A7795_PD_ALWAYS_ON },
42 { "a3vc", 0x380, 0, R8A7795_PD_A3VC, R8A7795_PD_ALWAYS_ON },
43 { "a2vc0", 0x3c0, 0, R8A7795_PD_A2VC0, R8A7795_PD_A3VC },
44 { "a2vc1", 0x3c0, 1, R8A7795_PD_A2VC1, R8A7795_PD_A3VC },
45 { "3dg-a", 0x100, 0, R8A7795_PD_3DG_A, R8A7795_PD_ALWAYS_ON },
46 { "3dg-b", 0x100, 1, R8A7795_PD_3DG_B, R8A7795_PD_3DG_A },
47 { "3dg-c", 0x100, 2, R8A7795_PD_3DG_C, R8A7795_PD_3DG_B },
48 { "3dg-d", 0x100, 3, R8A7795_PD_3DG_D, R8A7795_PD_3DG_C },
49 { "3dg-e", 0x100, 4, R8A7795_PD_3DG_E, R8A7795_PD_3DG_D },
50 { "a3ir", 0x180, 0, R8A7795_PD_A3IR, R8A7795_PD_ALWAYS_ON },
51};
52
53const struct rcar_sysc_info r8a7795_sysc_info __initconst = {
54 .areas = r8a7795_areas,
55 .num_areas = ARRAY_SIZE(r8a7795_areas),
56};
diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c
new file mode 100644
index 000000000000..79dbc770895f
--- /dev/null
+++ b/drivers/soc/renesas/rcar-sysc.c
@@ -0,0 +1,401 @@
1/*
2 * R-Car SYSC Power management support
3 *
4 * Copyright (C) 2014 Magnus Damm
5 * Copyright (C) 2015-2016 Glider bvba
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
11
12#include <linux/clk/renesas.h>
13#include <linux/delay.h>
14#include <linux/err.h>
15#include <linux/mm.h>
16#include <linux/of_address.h>
17#include <linux/pm_domain.h>
18#include <linux/slab.h>
19#include <linux/spinlock.h>
20#include <linux/io.h>
21#include <linux/soc/renesas/rcar-sysc.h>
22
23#include "rcar-sysc.h"
24
25/* SYSC Common */
26#define SYSCSR 0x00 /* SYSC Status Register */
27#define SYSCISR 0x04 /* Interrupt Status Register */
28#define SYSCISCR 0x08 /* Interrupt Status Clear Register */
29#define SYSCIER 0x0c /* Interrupt Enable Register */
30#define SYSCIMR 0x10 /* Interrupt Mask Register */
31
32/* SYSC Status Register */
33#define SYSCSR_PONENB 1 /* Ready for power resume requests */
34#define SYSCSR_POFFENB 0 /* Ready for power shutoff requests */
35
36/*
37 * Power Control Register Offsets inside the register block for each domain
38 * Note: The "CR" registers for ARM cores exist on H1 only
39 * Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2
40 * Use PSCI on R-Car Gen3
41 */
42#define PWRSR_OFFS 0x00 /* Power Status Register */
43#define PWROFFCR_OFFS 0x04 /* Power Shutoff Control Register */
44#define PWROFFSR_OFFS 0x08 /* Power Shutoff Status Register */
45#define PWRONCR_OFFS 0x0c /* Power Resume Control Register */
46#define PWRONSR_OFFS 0x10 /* Power Resume Status Register */
47#define PWRER_OFFS 0x14 /* Power Shutoff/Resume Error */
48
49
50#define SYSCSR_RETRIES 100
51#define SYSCSR_DELAY_US 1
52
53#define PWRER_RETRIES 100
54#define PWRER_DELAY_US 1
55
56#define SYSCISR_RETRIES 1000
57#define SYSCISR_DELAY_US 1
58
59#define RCAR_PD_ALWAYS_ON 32 /* Always-on power area */
60
61static void __iomem *rcar_sysc_base;
62static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
63
64static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on)
65{
66 unsigned int sr_bit, reg_offs;
67 int k;
68
69 if (on) {
70 sr_bit = SYSCSR_PONENB;
71 reg_offs = PWRONCR_OFFS;
72 } else {
73 sr_bit = SYSCSR_POFFENB;
74 reg_offs = PWROFFCR_OFFS;
75 }
76
77 /* Wait until SYSC is ready to accept a power request */
78 for (k = 0; k < SYSCSR_RETRIES; k++) {
79 if (ioread32(rcar_sysc_base + SYSCSR) & BIT(sr_bit))
80 break;
81 udelay(SYSCSR_DELAY_US);
82 }
83
84 if (k == SYSCSR_RETRIES)
85 return -EAGAIN;
86
87 /* Submit power shutoff or power resume request */
88 iowrite32(BIT(sysc_ch->chan_bit),
89 rcar_sysc_base + sysc_ch->chan_offs + reg_offs);
90
91 return 0;
92}
93
94static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
95{
96 unsigned int isr_mask = BIT(sysc_ch->isr_bit);
97 unsigned int chan_mask = BIT(sysc_ch->chan_bit);
98 unsigned int status;
99 unsigned long flags;
100 int ret = 0;
101 int k;
102
103 spin_lock_irqsave(&rcar_sysc_lock, flags);
104
105 iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
106
107 /* Submit power shutoff or resume request until it was accepted */
108 for (k = 0; k < PWRER_RETRIES; k++) {
109 ret = rcar_sysc_pwr_on_off(sysc_ch, on);
110 if (ret)
111 goto out;
112
113 status = ioread32(rcar_sysc_base +
114 sysc_ch->chan_offs + PWRER_OFFS);
115 if (!(status & chan_mask))
116 break;
117
118 udelay(PWRER_DELAY_US);
119 }
120
121 if (k == PWRER_RETRIES) {
122 ret = -EIO;
123 goto out;
124 }
125
126 /* Wait until the power shutoff or resume request has completed * */
127 for (k = 0; k < SYSCISR_RETRIES; k++) {
128 if (ioread32(rcar_sysc_base + SYSCISR) & isr_mask)
129 break;
130 udelay(SYSCISR_DELAY_US);
131 }
132
133 if (k == SYSCISR_RETRIES)
134 ret = -EIO;
135
136 iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
137
138 out:
139 spin_unlock_irqrestore(&rcar_sysc_lock, flags);
140
141 pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off",
142 sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret);
143 return ret;
144}
145
146int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
147{
148 return rcar_sysc_power(sysc_ch, false);
149}
150
151int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
152{
153 return rcar_sysc_power(sysc_ch, true);
154}
155
156static bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch)
157{
158 unsigned int st;
159
160 st = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRSR_OFFS);
161 if (st & BIT(sysc_ch->chan_bit))
162 return true;
163
164 return false;
165}
166
167void __iomem *rcar_sysc_init(phys_addr_t base)
168{
169 rcar_sysc_base = ioremap_nocache(base, PAGE_SIZE);
170 if (!rcar_sysc_base)
171 panic("unable to ioremap R-Car SYSC hardware block\n");
172
173 return rcar_sysc_base;
174}
175
176struct rcar_sysc_pd {
177 struct generic_pm_domain genpd;
178 struct rcar_sysc_ch ch;
179 unsigned int flags;
180 char name[0];
181};
182
183static inline struct rcar_sysc_pd *to_rcar_pd(struct generic_pm_domain *d)
184{
185 return container_of(d, struct rcar_sysc_pd, genpd);
186}
187
188static int rcar_sysc_pd_power_off(struct generic_pm_domain *genpd)
189{
190 struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
191
192 pr_debug("%s: %s\n", __func__, genpd->name);
193
194 if (pd->flags & PD_NO_CR) {
195 pr_debug("%s: Cannot control %s\n", __func__, genpd->name);
196 return -EBUSY;
197 }
198
199 if (pd->flags & PD_BUSY) {
200 pr_debug("%s: %s busy\n", __func__, genpd->name);
201 return -EBUSY;
202 }
203
204 return rcar_sysc_power_down(&pd->ch);
205}
206
207static int rcar_sysc_pd_power_on(struct generic_pm_domain *genpd)
208{
209 struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
210
211 pr_debug("%s: %s\n", __func__, genpd->name);
212
213 if (pd->flags & PD_NO_CR) {
214 pr_debug("%s: Cannot control %s\n", __func__, genpd->name);
215 return 0;
216 }
217
218 return rcar_sysc_power_up(&pd->ch);
219}
220
221static bool has_cpg_mstp;
222
223static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd)
224{
225 struct generic_pm_domain *genpd = &pd->genpd;
226 const char *name = pd->genpd.name;
227 struct dev_power_governor *gov = &simple_qos_governor;
228
229 if (pd->flags & PD_CPU) {
230 /*
231 * This domain contains a CPU core and therefore it should
232 * only be turned off if the CPU is not in use.
233 */
234 pr_debug("PM domain %s contains %s\n", name, "CPU");
235 pd->flags |= PD_BUSY;
236 gov = &pm_domain_always_on_gov;
237 } else if (pd->flags & PD_SCU) {
238 /*
239 * This domain contains an SCU and cache-controller, and
240 * therefore it should only be turned off if the CPU cores are
241 * not in use.
242 */
243 pr_debug("PM domain %s contains %s\n", name, "SCU");
244 pd->flags |= PD_BUSY;
245 gov = &pm_domain_always_on_gov;
246 } else if (pd->flags & PD_NO_CR) {
247 /*
248 * This domain cannot be turned off.
249 */
250 pd->flags |= PD_BUSY;
251 gov = &pm_domain_always_on_gov;
252 }
253
254 if (!(pd->flags & (PD_CPU | PD_SCU))) {
255 /* Enable Clock Domain for I/O devices */
256 genpd->flags = GENPD_FLAG_PM_CLK;
257 if (has_cpg_mstp) {
258 genpd->attach_dev = cpg_mstp_attach_dev;
259 genpd->detach_dev = cpg_mstp_detach_dev;
260 } else {
261 genpd->attach_dev = cpg_mssr_attach_dev;
262 genpd->detach_dev = cpg_mssr_detach_dev;
263 }
264 }
265
266 genpd->power_off = rcar_sysc_pd_power_off;
267 genpd->power_on = rcar_sysc_pd_power_on;
268
269 if (pd->flags & (PD_CPU | PD_NO_CR)) {
270 /* Skip CPUs (handled by SMP code) and areas without control */
271 pr_debug("%s: Not touching %s\n", __func__, genpd->name);
272 goto finalize;
273 }
274
275 if (!rcar_sysc_power_is_off(&pd->ch)) {
276 pr_debug("%s: %s is already powered\n", __func__, genpd->name);
277 goto finalize;
278 }
279
280 rcar_sysc_power_up(&pd->ch);
281
282finalize:
283 pm_genpd_init(genpd, gov, false);
284}
285
286static const struct of_device_id rcar_sysc_matches[] = {
287#ifdef CONFIG_ARCH_R8A7779
288 { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info },
289#endif
290#ifdef CONFIG_ARCH_R8A7790
291 { .compatible = "renesas,r8a7790-sysc", .data = &r8a7790_sysc_info },
292#endif
293#ifdef CONFIG_ARCH_R8A7791
294 { .compatible = "renesas,r8a7791-sysc", .data = &r8a7791_sysc_info },
295#endif
296#ifdef CONFIG_ARCH_R8A7793
297 /* R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. */
298 { .compatible = "renesas,r8a7793-sysc", .data = &r8a7791_sysc_info },
299#endif
300#ifdef CONFIG_ARCH_R8A7794
301 { .compatible = "renesas,r8a7794-sysc", .data = &r8a7794_sysc_info },
302#endif
303#ifdef CONFIG_ARCH_R8A7795
304 { .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info },
305#endif
306 { /* sentinel */ }
307};
308
309struct rcar_pm_domains {
310 struct genpd_onecell_data onecell_data;
311 struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1];
312};
313
314static int __init rcar_sysc_pd_init(void)
315{
316 const struct rcar_sysc_info *info;
317 const struct of_device_id *match;
318 struct rcar_pm_domains *domains;
319 struct device_node *np;
320 u32 syscier, syscimr;
321 void __iomem *base;
322 unsigned int i;
323 int error;
324
325 np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match);
326 if (!np)
327 return -ENODEV;
328
329 info = match->data;
330
331 has_cpg_mstp = of_find_compatible_node(NULL, NULL,
332 "renesas,cpg-mstp-clocks");
333
334 base = of_iomap(np, 0);
335 if (!base) {
336 pr_warn("%s: Cannot map regs\n", np->full_name);
337 error = -ENOMEM;
338 goto out_put;
339 }
340
341 rcar_sysc_base = base;
342
343 domains = kzalloc(sizeof(*domains), GFP_KERNEL);
344 if (!domains) {
345 error = -ENOMEM;
346 goto out_put;
347 }
348
349 domains->onecell_data.domains = domains->domains;
350 domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
351
352 for (i = 0, syscier = 0; i < info->num_areas; i++)
353 syscier |= BIT(info->areas[i].isr_bit);
354
355 /*
356 * Mask all interrupt sources to prevent the CPU from receiving them.
357 * Make sure not to clear reserved bits that were set before.
358 */
359 syscimr = ioread32(base + SYSCIMR);
360 syscimr |= syscier;
361 pr_debug("%s: syscimr = 0x%08x\n", np->full_name, syscimr);
362 iowrite32(syscimr, base + SYSCIMR);
363
364 /*
365 * SYSC needs all interrupt sources enabled to control power.
366 */
367 pr_debug("%s: syscier = 0x%08x\n", np->full_name, syscier);
368 iowrite32(syscier, base + SYSCIER);
369
370 for (i = 0; i < info->num_areas; i++) {
371 const struct rcar_sysc_area *area = &info->areas[i];
372 struct rcar_sysc_pd *pd;
373
374 pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL);
375 if (!pd) {
376 error = -ENOMEM;
377 goto out_put;
378 }
379
380 strcpy(pd->name, area->name);
381 pd->genpd.name = pd->name;
382 pd->ch.chan_offs = area->chan_offs;
383 pd->ch.chan_bit = area->chan_bit;
384 pd->ch.isr_bit = area->isr_bit;
385 pd->flags = area->flags;
386
387 rcar_sysc_pd_setup(pd);
388 if (area->parent >= 0)
389 pm_genpd_add_subdomain(domains->domains[area->parent],
390 &pd->genpd);
391
392 domains->domains[area->isr_bit] = &pd->genpd;
393 }
394
395 of_genpd_add_provider_onecell(np, &domains->onecell_data);
396
397out_put:
398 of_node_put(np);
399 return error;
400}
401early_initcall(rcar_sysc_pd_init);
diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h
new file mode 100644
index 000000000000..5e766174c2f4
--- /dev/null
+++ b/drivers/soc/renesas/rcar-sysc.h
@@ -0,0 +1,58 @@
1/*
2 * Renesas R-Car System Controller
3 *
4 * Copyright (C) 2016 Glider bvba
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 as published by
8 * the Free Software Foundation; version 2 of the License.
9 */
10#ifndef __SOC_RENESAS_RCAR_SYSC_H__
11#define __SOC_RENESAS_RCAR_SYSC_H__
12
13#include <linux/types.h>
14
15
16/*
17 * Power Domain flags
18 */
19#define PD_CPU BIT(0) /* Area contains main CPU core */
20#define PD_SCU BIT(1) /* Area contains SCU and L2 cache */
21#define PD_NO_CR BIT(2) /* Area lacks PWR{ON,OFF}CR registers */
22
23#define PD_BUSY BIT(3) /* Busy, for internal use only */
24
25#define PD_CPU_CR PD_CPU /* CPU area has CR (R-Car H1) */
26#define PD_CPU_NOCR PD_CPU | PD_NO_CR /* CPU area lacks CR (R-Car Gen2/3) */
27#define PD_ALWAYS_ON PD_NO_CR /* Always-on area */
28
29
30/*
31 * Description of a Power Area
32 */
33
34struct rcar_sysc_area {
35 const char *name;
36 u16 chan_offs; /* Offset of PWRSR register for this area */
37 u8 chan_bit; /* Bit in PWR* (except for PWRUP in PWRSR) */
38 u8 isr_bit; /* Bit in SYSCI*R */
39 int parent; /* -1 if none */
40 unsigned int flags; /* See PD_* */
41};
42
43
44/*
45 * SoC-specific Power Area Description
46 */
47
48struct rcar_sysc_info {
49 const struct rcar_sysc_area *areas;
50 unsigned int num_areas;
51};
52
53extern const struct rcar_sysc_info r8a7779_sysc_info;
54extern const struct rcar_sysc_info r8a7790_sysc_info;
55extern const struct rcar_sysc_info r8a7791_sysc_info;
56extern const struct rcar_sysc_info r8a7794_sysc_info;
57extern const struct rcar_sysc_info r8a7795_sysc_info;
58#endif /* __SOC_RENESAS_RCAR_SYSC_H__ */
diff --git a/include/dt-bindings/power/r8a7779-sysc.h b/include/dt-bindings/power/r8a7779-sysc.h
new file mode 100644
index 000000000000..183571da507e
--- /dev/null
+++ b/include/dt-bindings/power/r8a7779-sysc.h
@@ -0,0 +1,27 @@
1/*
2 * Copyright (C) 2016 Glider bvba
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 */
8#ifndef __DT_BINDINGS_POWER_R8A7779_SYSC_H__
9#define __DT_BINDINGS_POWER_R8A7779_SYSC_H__
10
11/*
12 * These power domain indices match the numbers of the interrupt bits
13 * representing the power areas in the various Interrupt Registers
14 * (e.g. SYSCISR, Interrupt Status Register)
15 */
16
17#define R8A7779_PD_ARM1 1
18#define R8A7779_PD_ARM2 2
19#define R8A7779_PD_ARM3 3
20#define R8A7779_PD_SGX 20
21#define R8A7779_PD_VDP 21
22#define R8A7779_PD_IMP 24
23
24/* Always-on power area */
25#define R8A7779_PD_ALWAYS_ON 32
26
27#endif /* __DT_BINDINGS_POWER_R8A7779_SYSC_H__ */
diff --git a/include/dt-bindings/power/r8a7790-sysc.h b/include/dt-bindings/power/r8a7790-sysc.h
new file mode 100644
index 000000000000..6af4e9929bd0
--- /dev/null
+++ b/include/dt-bindings/power/r8a7790-sysc.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2016 Glider bvba
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 */
8#ifndef __DT_BINDINGS_POWER_R8A7790_SYSC_H__
9#define __DT_BINDINGS_POWER_R8A7790_SYSC_H__
10
11/*
12 * These power domain indices match the numbers of the interrupt bits
13 * representing the power areas in the various Interrupt Registers
14 * (e.g. SYSCISR, Interrupt Status Register)
15 */
16
17#define R8A7790_PD_CA15_CPU0 0
18#define R8A7790_PD_CA15_CPU1 1
19#define R8A7790_PD_CA15_CPU2 2
20#define R8A7790_PD_CA15_CPU3 3
21#define R8A7790_PD_CA7_CPU0 5
22#define R8A7790_PD_CA7_CPU1 6
23#define R8A7790_PD_CA7_CPU2 7
24#define R8A7790_PD_CA7_CPU3 8
25#define R8A7790_PD_CA15_SCU 12
26#define R8A7790_PD_SH_4A 16
27#define R8A7790_PD_RGX 20
28#define R8A7790_PD_CA7_SCU 21
29#define R8A7790_PD_IMP 24
30
31/* Always-on power area */
32#define R8A7790_PD_ALWAYS_ON 32
33
34#endif /* __DT_BINDINGS_POWER_R8A7790_SYSC_H__ */
diff --git a/include/dt-bindings/power/r8a7791-sysc.h b/include/dt-bindings/power/r8a7791-sysc.h
new file mode 100644
index 000000000000..1403baa0514f
--- /dev/null
+++ b/include/dt-bindings/power/r8a7791-sysc.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright (C) 2016 Glider bvba
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 */
8#ifndef __DT_BINDINGS_POWER_R8A7791_SYSC_H__
9#define __DT_BINDINGS_POWER_R8A7791_SYSC_H__
10
11/*
12 * These power domain indices match the numbers of the interrupt bits
13 * representing the power areas in the various Interrupt Registers
14 * (e.g. SYSCISR, Interrupt Status Register)
15 */
16
17#define R8A7791_PD_CA15_CPU0 0
18#define R8A7791_PD_CA15_CPU1 1
19#define R8A7791_PD_CA15_SCU 12
20#define R8A7791_PD_SH_4A 16
21#define R8A7791_PD_SGX 20
22
23/* Always-on power area */
24#define R8A7791_PD_ALWAYS_ON 32
25
26#endif /* __DT_BINDINGS_POWER_R8A7791_SYSC_H__ */
diff --git a/include/dt-bindings/power/r8a7793-sysc.h b/include/dt-bindings/power/r8a7793-sysc.h
new file mode 100644
index 000000000000..b5693df3d830
--- /dev/null
+++ b/include/dt-bindings/power/r8a7793-sysc.h
@@ -0,0 +1,28 @@
1/*
2 * Copyright (C) 2016 Glider bvba
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 */
8#ifndef __DT_BINDINGS_POWER_R8A7793_SYSC_H__
9#define __DT_BINDINGS_POWER_R8A7793_SYSC_H__
10
11/*
12 * These power domain indices match the numbers of the interrupt bits
13 * representing the power areas in the various Interrupt Registers
14 * (e.g. SYSCISR, Interrupt Status Register)
15 *
16 * Note that R-Car M2-N is identical to R-Car M2-W w.r.t. power domains.
17 */
18
19#define R8A7793_PD_CA15_CPU0 0
20#define R8A7793_PD_CA15_CPU1 1
21#define R8A7793_PD_CA15_SCU 12
22#define R8A7793_PD_SH_4A 16
23#define R8A7793_PD_SGX 20
24
25/* Always-on power area */
26#define R8A7793_PD_ALWAYS_ON 32
27
28#endif /* __DT_BINDINGS_POWER_R8A7793_SYSC_H__ */
diff --git a/include/dt-bindings/power/r8a7794-sysc.h b/include/dt-bindings/power/r8a7794-sysc.h
new file mode 100644
index 000000000000..862241c2d27b
--- /dev/null
+++ b/include/dt-bindings/power/r8a7794-sysc.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright (C) 2016 Glider bvba
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 */
8#ifndef __DT_BINDINGS_POWER_R8A7794_SYSC_H__
9#define __DT_BINDINGS_POWER_R8A7794_SYSC_H__
10
11/*
12 * These power domain indices match the numbers of the interrupt bits
13 * representing the power areas in the various Interrupt Registers
14 * (e.g. SYSCISR, Interrupt Status Register)
15 */
16
17#define R8A7794_PD_CA7_CPU0 5
18#define R8A7794_PD_CA7_CPU1 6
19#define R8A7794_PD_SH_4A 16
20#define R8A7794_PD_SGX 20
21#define R8A7794_PD_CA7_SCU 21
22
23/* Always-on power area */
24#define R8A7794_PD_ALWAYS_ON 32
25
26#endif /* __DT_BINDINGS_POWER_R8A7794_SYSC_H__ */
diff --git a/include/dt-bindings/power/r8a7795-sysc.h b/include/dt-bindings/power/r8a7795-sysc.h
new file mode 100644
index 000000000000..ee2e26ba605e
--- /dev/null
+++ b/include/dt-bindings/power/r8a7795-sysc.h
@@ -0,0 +1,42 @@
1/*
2 * Copyright (C) 2016 Glider bvba
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 */
8#ifndef __DT_BINDINGS_POWER_R8A7795_SYSC_H__
9#define __DT_BINDINGS_POWER_R8A7795_SYSC_H__
10
11/*
12 * These power domain indices match the numbers of the interrupt bits
13 * representing the power areas in the various Interrupt Registers
14 * (e.g. SYSCISR, Interrupt Status Register)
15 */
16
17#define R8A7795_PD_CA57_CPU0 0
18#define R8A7795_PD_CA57_CPU1 1
19#define R8A7795_PD_CA57_CPU2 2
20#define R8A7795_PD_CA57_CPU3 3
21#define R8A7795_PD_CA53_CPU0 5
22#define R8A7795_PD_CA53_CPU1 6
23#define R8A7795_PD_CA53_CPU2 7
24#define R8A7795_PD_CA53_CPU3 8
25#define R8A7795_PD_A3VP 9
26#define R8A7795_PD_CA57_SCU 12
27#define R8A7795_PD_CR7 13
28#define R8A7795_PD_A3VC 14
29#define R8A7795_PD_3DG_A 17
30#define R8A7795_PD_3DG_B 18
31#define R8A7795_PD_3DG_C 19
32#define R8A7795_PD_3DG_D 20
33#define R8A7795_PD_CA53_SCU 21
34#define R8A7795_PD_3DG_E 22
35#define R8A7795_PD_A3IR 24
36#define R8A7795_PD_A2VC0 25
37#define R8A7795_PD_A2VC1 26
38
39/* Always-on power area */
40#define R8A7795_PD_ALWAYS_ON 32
41
42#endif /* __DT_BINDINGS_POWER_R8A7795_SYSC_H__ */
diff --git a/include/linux/clk/renesas.h b/include/linux/clk/renesas.h
index 7adfd80fbf55..ba6fa4148515 100644
--- a/include/linux/clk/renesas.h
+++ b/include/linux/clk/renesas.h
@@ -24,12 +24,20 @@ void r8a7778_clocks_init(u32 mode);
24void r8a7779_clocks_init(u32 mode); 24void r8a7779_clocks_init(u32 mode);
25void rcar_gen2_clocks_init(u32 mode); 25void rcar_gen2_clocks_init(u32 mode);
26 26
27#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
28void cpg_mstp_add_clk_domain(struct device_node *np); 27void cpg_mstp_add_clk_domain(struct device_node *np);
29int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev); 28#ifdef CONFIG_CLK_RENESAS_CPG_MSTP
30void cpg_mstp_detach_dev(struct generic_pm_domain *domain, struct device *dev); 29int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev);
30void cpg_mstp_detach_dev(struct generic_pm_domain *unused, struct device *dev);
31#else 31#else
32static inline void cpg_mstp_add_clk_domain(struct device_node *np) {} 32#define cpg_mstp_attach_dev NULL
33#define cpg_mstp_detach_dev NULL
33#endif 34#endif
34 35
36#ifdef CONFIG_CLK_RENESAS_CPG_MSSR
37int cpg_mssr_attach_dev(struct generic_pm_domain *unused, struct device *dev);
38void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev);
39#else
40#define cpg_mssr_attach_dev NULL
41#define cpg_mssr_detach_dev NULL
42#endif
35#endif 43#endif
diff --git a/arch/arm/mach-shmobile/pm-rcar.h b/include/linux/soc/renesas/rcar-sysc.h
index 1b901db4a24c..92fc613ab23d 100644
--- a/arch/arm/mach-shmobile/pm-rcar.h
+++ b/include/linux/soc/renesas/rcar-sysc.h
@@ -1,5 +1,7 @@
1#ifndef PM_RCAR_H 1#ifndef __LINUX_SOC_RENESAS_RCAR_SYSC_H__
2#define PM_RCAR_H 2#define __LINUX_SOC_RENESAS_RCAR_SYSC_H__
3
4#include <linux/types.h>
3 5
4struct rcar_sysc_ch { 6struct rcar_sysc_ch {
5 u16 chan_offs; 7 u16 chan_offs;
@@ -9,7 +11,6 @@ struct rcar_sysc_ch {
9 11
10int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch); 12int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch);
11int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch); 13int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch);
12bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch);
13void __iomem *rcar_sysc_init(phys_addr_t base); 14void __iomem *rcar_sysc_init(phys_addr_t base);
14 15
15#endif /* PM_RCAR_H */ 16#endif /* __LINUX_SOC_RENESAS_RCAR_SYSC_H__ */