Merge tag 'renesas-soc2-for-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorOlof Johansson <olof@lixom.net>
Thu, 7 Jul 2016 05:21:11 +0000 (22:21 -0700)
committerOlof Johansson <olof@lixom.net>
Thu, 7 Jul 2016 05:21:11 +0000 (22:21 -0700)
Second Round of Renesas ARM Based SoC Updates for v4.8

* Add DT support to the APMU driver and prioritise DT APMU support
* Obtain extal frequency from DT
* Add support for r8a7792

* tag 'renesas-soc2-for-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas:
  ARM: shmobile: r8a7791: Prioritize DT APMU support
  ARM: shmobile: r8a7790: Prioritize DT APMU support
  ARM: shmobile: smp: Add function to prioritize DT SMP
  ARM: shmobile: apmu: Add APMU DT support via Enable method
  ARM: shmobile: apmu: Move #ifdef CONFIG_SMP to cover more functions
  ARM: shmobile: rcar-gen2: Correct arch timer frequency on R-Car V2H
  ARM: shmobile: rcar-gen2: Obtain extal frequency from DT
  ARM: shmobile: r8a7792: basic SoC support
  soc: renesas: rcar-sysc: Improve SYSC interrupt config in legacy wrapper
  soc: renesas: rcar-sysc: Move SYSC interrupt config to rcar-sysc driver
  soc: renesas: rcar-sysc: Make rcar_sysc_init() init the PM domains
  soc: renesas: rcar-sysc: Fix uninitialized error code in rcar_sysc_pd_init()
  soc: renesas: rcar-sysc: add R8A7792 support
  soc: renesas: rcar-sysc: Add support for R-Car M3-W power areas
  soc: renesas: Add r8a7796 SYSC PM Domain Binding Definitions
  soc: renesas: rcar-sysc: Document r8a7796 support

Signed-off-by: Olof Johansson <olof@lixom.net>
19 files changed:
Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-shmobile/Makefile
arch/arm/mach-shmobile/common.h
arch/arm/mach-shmobile/platsmp-apmu.c
arch/arm/mach-shmobile/platsmp.c
arch/arm/mach-shmobile/pm-r8a7779.c
arch/arm/mach-shmobile/pm-rcar-gen2.c
arch/arm/mach-shmobile/setup-r8a7790.c
arch/arm/mach-shmobile/setup-r8a7791.c
arch/arm/mach-shmobile/setup-r8a7792.c [new file with mode: 0644]
arch/arm/mach-shmobile/setup-rcar-gen2.c
drivers/soc/renesas/Makefile
drivers/soc/renesas/r8a7792-sysc.c [new file with mode: 0644]
drivers/soc/renesas/r8a7796-sysc.c [new file with mode: 0644]
drivers/soc/renesas/rcar-sysc.c
drivers/soc/renesas/rcar-sysc.h
include/dt-bindings/power/r8a7796-sysc.h [new file with mode: 0644]
include/linux/soc/renesas/rcar-sysc.h

index b74e4d4..0725fb3 100644 (file)
@@ -14,6 +14,7 @@ Required properties:
       - "renesas,r8a7793-sysc" (R-Car M2-N)
       - "renesas,r8a7794-sysc" (R-Car E2)
       - "renesas,r8a7795-sysc" (R-Car H3)
+      - "renesas,r8a7796-sysc" (R-Car M3-W)
   - reg: Address start and address range for the device.
   - #power-domain-cells: Must be 1.
 
index 108ae2b..4a48c9f 100644 (file)
@@ -86,6 +86,10 @@ config ARCH_R8A7791
        select ARCH_RCAR_GEN2
        select I2C
 
+config ARCH_R8A7792
+       bool "R-Car V2H (R8A77920)"
+       select ARCH_RCAR_GEN2
+
 config ARCH_R8A7793
        bool "R-Car M2-N (R8A7793)"
        select ARCH_RCAR_GEN2
index fc95f7b..3fc48b0 100644 (file)
@@ -13,6 +13,7 @@ obj-$(CONFIG_ARCH_R8A7778)    += setup-r8a7778.o
 obj-$(CONFIG_ARCH_R8A7779)     += setup-r8a7779.o pm-r8a7779.o
 obj-$(CONFIG_ARCH_R8A7790)     += setup-r8a7790.o
 obj-$(CONFIG_ARCH_R8A7791)     += setup-r8a7791.o
+obj-$(CONFIG_ARCH_R8A7792)     += setup-r8a7792.o
 obj-$(CONFIG_ARCH_R8A7793)     += setup-r8a7793.o
 obj-$(CONFIG_ARCH_R8A7794)     += setup-r8a7794.o
 obj-$(CONFIG_ARCH_EMEV2)       += setup-emev2.o
index 3b562d8..1a8f7b3 100644 (file)
@@ -10,6 +10,7 @@ extern void shmobile_smp_sleep(void);
 extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn,
                              unsigned long arg);
 extern bool shmobile_smp_cpu_can_disable(unsigned int cpu);
+extern bool shmobile_smp_init_fallback_ops(void);
 extern void shmobile_boot_scu(void);
 extern void shmobile_smp_scu_prepare_cpus(phys_addr_t scu_base_phys,
                                          unsigned int max_cpus);
index aba75c8..0c6bb45 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/suspend.h>
 #include "common.h"
 #include "platsmp-apmu.h"
+#include "rcar-gen2.h"
 
 static struct {
        void __iomem *iomem;
@@ -74,6 +75,7 @@ static int __maybe_unused apmu_wrap(int cpu, int (*fn)(void __iomem *p, int cpu)
        return p ? fn(p, apmu_cpus[cpu].bit) : -EINVAL;
 }
 
+#ifdef CONFIG_SMP
 static void apmu_init_cpu(struct resource *res, int cpu, int bit)
 {
        if ((cpu >= ARRAY_SIZE(apmu_cpus)) || apmu_cpus[cpu].iomem)
@@ -117,18 +119,69 @@ static void apmu_parse_cfg(void (*fn)(struct resource *res, int cpu, int bit),
        }
 }
 
-void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus,
-                                          struct rcar_apmu_config *apmu_config,
-                                          int num)
+static const struct of_device_id apmu_ids[] = {
+       { .compatible = "renesas,apmu" },
+       { /*sentinel*/ }
+};
+
+static void apmu_parse_dt(void (*fn)(struct resource *res, int cpu, int bit))
+{
+       struct device_node *np_apmu, *np_cpu;
+       struct resource res;
+       int bit, index;
+       u32 id;
+
+       for_each_matching_node(np_apmu, apmu_ids) {
+               /* only enable the cluster that includes the boot CPU */
+               bool is_allowed = false;
+
+               for (bit = 0; bit < CONFIG_NR_CPUS; bit++) {
+                       np_cpu = of_parse_phandle(np_apmu, "cpus", bit);
+                       if (np_cpu) {
+                               if (!of_property_read_u32(np_cpu, "reg", &id)) {
+                                       if (id == cpu_logical_map(0)) {
+                                               is_allowed = true;
+                                               of_node_put(np_cpu);
+                                               break;
+                                       }
+
+                               }
+                               of_node_put(np_cpu);
+                       }
+               }
+               if (!is_allowed)
+                       continue;
+
+               for (bit = 0; bit < CONFIG_NR_CPUS; bit++) {
+                       np_cpu = of_parse_phandle(np_apmu, "cpus", bit);
+                       if (np_cpu) {
+                               if (!of_property_read_u32(np_cpu, "reg", &id)) {
+                                       index = get_logical_index(id);
+                                       if ((index >= 0) &&
+                                           !of_address_to_resource(np_apmu,
+                                                                   0, &res))
+                                               fn(&res, index, bit);
+                               }
+                               of_node_put(np_cpu);
+                       }
+               }
+       }
+}
+
+static void __init shmobile_smp_apmu_setup_boot(void)
 {
        /* install boot code shared by all CPUs */
        shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
+}
 
-       /* perform per-cpu setup */
+void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus,
+                                          struct rcar_apmu_config *apmu_config,
+                                          int num)
+{
+       shmobile_smp_apmu_setup_boot();
        apmu_parse_cfg(apmu_init_cpu, apmu_config, num);
 }
 
-#ifdef CONFIG_SMP
 int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
        /* For this particular CPU register boot vector */
@@ -136,7 +189,38 @@ int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
 
        return apmu_wrap(cpu, apmu_power_on);
 }
+
+static void __init shmobile_smp_apmu_prepare_cpus_dt(unsigned int max_cpus)
+{
+       shmobile_smp_apmu_setup_boot();
+       apmu_parse_dt(apmu_init_cpu);
+       rcar_gen2_pm_init();
+}
+
+static int shmobile_smp_apmu_boot_secondary_md21(unsigned int cpu,
+                                                struct task_struct *idle)
+{
+       /* Error out when hardware debug mode is enabled */
+       if (rcar_gen2_read_mode_pins() & BIT(21)) {
+               pr_warn("Unable to boot CPU%u when MD21 is set\n", cpu);
+               return -ENOTSUPP;
+       }
+
+       return shmobile_smp_apmu_boot_secondary(cpu, idle);
+}
+
+static struct smp_operations apmu_smp_ops __initdata = {
+       .smp_prepare_cpus       = shmobile_smp_apmu_prepare_cpus_dt,
+       .smp_boot_secondary     = shmobile_smp_apmu_boot_secondary_md21,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_can_disable        = shmobile_smp_cpu_can_disable,
+       .cpu_die                = shmobile_smp_apmu_cpu_die,
+       .cpu_kill               = shmobile_smp_apmu_cpu_kill,
 #endif
+};
+
+CPU_METHOD_OF_DECLARE(shmobile_smp_apmu, "renesas,apmu", &apmu_smp_ops);
+#endif /* CONFIG_SMP */
 
 #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_SUSPEND)
 /* nicked from arch/arm/mach-exynos/hotplug.c */
index b23378f..f3dba6f 100644 (file)
@@ -36,3 +36,9 @@ bool shmobile_smp_cpu_can_disable(unsigned int cpu)
        return true; /* Hotplug of any CPU is supported */
 }
 #endif
+
+bool __init shmobile_smp_init_fallback_ops(void)
+{
+       /* fallback on PSCI/smp_ops if no other DT based method is detected */
+       return platform_can_secondary_boot() ? true : false;
+}
index 4174cbc..5c9a93f 100644 (file)
 
 static void __init r8a7779_sysc_init(void)
 {
-       void __iomem *base = rcar_sysc_init(0xffd85000);
-
-       /* enable all interrupt sources, but do not use interrupt handler */
-       iowrite32(0x0131000e, base + SYSCIER);
-       iowrite32(0, base + SYSCIMR);
+       rcar_sysc_init(0xffd85000, 0x0131000e);
 }
 
 #else /* CONFIG_PM || CONFIG_SMP */
index 61361da..dd9ac36 100644 (file)
 
 static void __init rcar_gen2_sysc_init(u32 syscier)
 {
-       void __iomem *base = rcar_sysc_init(0xe6180000);
-
-       /* enable all interrupt sources, but do not use interrupt handler */
-       iowrite32(syscier, base + SYSCIER);
-       iowrite32(0, base + SYSCIMR);
+       rcar_sysc_init(0xe6180000, syscier);
 }
 
 #else /* CONFIG_SMP */
index 3a18af4..3506327 100644 (file)
@@ -28,6 +28,7 @@ static const char * const r8a7790_boards_compat_dt[] __initconst = {
 };
 
 DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
+       .smp_init       = shmobile_smp_init_fallback_ops,
        .smp            = smp_ops(r8a7790_smp_ops),
        .init_early     = shmobile_init_delay,
        .init_time      = rcar_gen2_timer_init,
index 3b8dbaf..110e8b5 100644 (file)
@@ -29,6 +29,7 @@ static const char *const r8a7791_boards_compat_dt[] __initconst = {
 };
 
 DT_MACHINE_START(R8A7791_DT, "Generic R8A7791 (Flattened Device Tree)")
+       .smp_init       = shmobile_smp_init_fallback_ops,
        .smp            = smp_ops(r8a7791_smp_ops),
        .init_early     = shmobile_init_delay,
        .init_time      = rcar_gen2_timer_init,
diff --git a/arch/arm/mach-shmobile/setup-r8a7792.c b/arch/arm/mach-shmobile/setup-r8a7792.c
new file mode 100644 (file)
index 0000000..a091039
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * r8a7792 processor support
+ *
+ * Copyright (C) 2014 Renesas Electronics Corporation
+ * Copyright (C) 2016 Cogent  Embedded, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+#include "rcar-gen2.h"
+
+static const char * const r8a7792_boards_compat_dt[] __initconst = {
+       "renesas,r8a7792",
+       NULL,
+};
+
+DT_MACHINE_START(R8A7792_DT, "Generic R8A7792 (Flattened Device Tree)")
+       .init_early     = shmobile_init_delay,
+       .init_late      = shmobile_init_late,
+       .init_time      = rcar_gen2_timer_init,
+       .reserve        = rcar_gen2_reserve,
+       .dt_compat      = r8a7792_boards_compat_dt,
+MACHINE_END
index 1c6fd11..afb9fdc 100644 (file)
@@ -46,6 +46,26 @@ u32 rcar_gen2_read_mode_pins(void)
        return mode;
 }
 
+static unsigned int __init get_extal_freq(void)
+{
+       struct device_node *cpg, *extal;
+       u32 freq = 20000000;
+
+       cpg = of_find_compatible_node(NULL, NULL,
+                                     "renesas,rcar-gen2-cpg-clocks");
+       if (!cpg)
+               return freq;
+
+       extal = of_parse_phandle(cpg, "clocks", 0);
+       of_node_put(cpg);
+       if (!extal)
+               return freq;
+
+       of_property_read_u32(extal, "clock-frequency", &freq);
+       of_node_put(extal);
+       return freq;
+}
+
 #define CNTCR 0
 #define CNTFID0 0x20
 
@@ -54,10 +74,10 @@ void __init rcar_gen2_timer_init(void)
        u32 mode = rcar_gen2_read_mode_pins();
 #ifdef CONFIG_ARM_ARCH_TIMER
        void __iomem *base;
-       int extal_mhz = 0;
        u32 freq;
 
-       if (of_machine_is_compatible("renesas,r8a7794")) {
+       if (of_machine_is_compatible("renesas,r8a7792") ||
+           of_machine_is_compatible("renesas,r8a7794")) {
                freq = 260000000 / 8;   /* ZS / 8 */
                /* CNTVOFF has to be initialized either from non-secure
                 * Hypervisor mode or secure Monitor mode with SCR.NS==1.
@@ -82,26 +102,9 @@ void __init rcar_gen2_timer_init(void)
                 * with the counter disabled. Moreover, it may also report
                 * a potentially incorrect fixed 13 MHz frequency. To be
                 * correct these registers need to be updated to use the
-                * frequency EXTAL / 2 which can be determined by the MD pins.
+                * frequency EXTAL / 2.
                 */
-
-               switch (mode & (MD(14) | MD(13))) {
-               case 0:
-                       extal_mhz = 15;
-                       break;
-               case MD(13):
-                       extal_mhz = 20;
-                       break;
-               case MD(14):
-                       extal_mhz = 26;
-                       break;
-               case MD(13) | MD(14):
-                       extal_mhz = 30;
-                       break;
-               }
-
-               /* The arch timer frequency equals EXTAL / 2 */
-               freq = extal_mhz * (1000000 / 2);
+               freq = get_extal_freq() / 2;
        }
 
        /* Remap "armgcnt address map" space */
index 151fcd3..623039c 100644 (file)
@@ -1,7 +1,9 @@
 obj-$(CONFIG_ARCH_R8A7779)     += rcar-sysc.o r8a7779-sysc.o
 obj-$(CONFIG_ARCH_R8A7790)     += rcar-sysc.o r8a7790-sysc.o
 obj-$(CONFIG_ARCH_R8A7791)     += rcar-sysc.o r8a7791-sysc.o
+obj-$(CONFIG_ARCH_R8A7792)     += rcar-sysc.o r8a7792-sysc.o
 # R-Car M2-N is identical to R-Car M2-W w.r.t. power domains.
 obj-$(CONFIG_ARCH_R8A7793)     += rcar-sysc.o r8a7791-sysc.o
 obj-$(CONFIG_ARCH_R8A7794)     += rcar-sysc.o r8a7794-sysc.o
 obj-$(CONFIG_ARCH_R8A7795)     += rcar-sysc.o r8a7795-sysc.o
+obj-$(CONFIG_ARCH_R8A7796)     += rcar-sysc.o r8a7796-sysc.o
diff --git a/drivers/soc/renesas/r8a7792-sysc.c b/drivers/soc/renesas/r8a7792-sysc.c
new file mode 100644 (file)
index 0000000..ca7467d
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Renesas R-Car V2H (R8A7792) System Controller
+ *
+ * Copyright (C) 2016 Cogent Embedded Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a7792-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a7792_areas[] __initconst = {
+       { "always-on",      0, 0, R8A7792_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca15-scu",   0x180, 0, R8A7792_PD_CA15_SCU,  R8A7792_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca15-cpu0",   0x40, 0, R8A7792_PD_CA15_CPU0, R8A7792_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "ca15-cpu1",   0x40, 1, R8A7792_PD_CA15_CPU1, R8A7792_PD_CA15_SCU,
+         PD_CPU_NOCR },
+       { "sgx",         0xc0, 0, R8A7792_PD_SGX,       R8A7792_PD_ALWAYS_ON },
+       { "imp",        0x140, 0, R8A7792_PD_IMP,       R8A7792_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a7792_sysc_info __initconst = {
+       .areas = r8a7792_areas,
+       .num_areas = ARRAY_SIZE(r8a7792_areas),
+};
diff --git a/drivers/soc/renesas/r8a7796-sysc.c b/drivers/soc/renesas/r8a7796-sysc.c
new file mode 100644 (file)
index 0000000..f700c84
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Renesas R-Car M3-W System Controller
+ *
+ * Copyright (C) 2016 Glider bvba
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a7796-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a7796_areas[] __initconst = {
+       { "always-on",      0, 0, R8A7796_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+       { "ca57-scu",   0x1c0, 0, R8A7796_PD_CA57_SCU,  R8A7796_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca57-cpu0",   0x80, 0, R8A7796_PD_CA57_CPU0, R8A7796_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca57-cpu1",   0x80, 1, R8A7796_PD_CA57_CPU1, R8A7796_PD_CA57_SCU,
+         PD_CPU_NOCR },
+       { "ca53-scu",   0x140, 0, R8A7796_PD_CA53_SCU,  R8A7796_PD_ALWAYS_ON,
+         PD_SCU },
+       { "ca53-cpu0",  0x200, 0, R8A7796_PD_CA53_CPU0, R8A7796_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu1",  0x200, 1, R8A7796_PD_CA53_CPU1, R8A7796_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu2",  0x200, 2, R8A7796_PD_CA53_CPU2, R8A7796_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "ca53-cpu3",  0x200, 3, R8A7796_PD_CA53_CPU3, R8A7796_PD_CA53_SCU,
+         PD_CPU_NOCR },
+       { "cr7",        0x240, 0, R8A7796_PD_CR7,       R8A7796_PD_ALWAYS_ON },
+       { "a3vc",       0x380, 0, R8A7796_PD_A3VC,      R8A7796_PD_ALWAYS_ON },
+       { "a2vc0",      0x3c0, 0, R8A7796_PD_A2VC0,     R8A7796_PD_A3VC },
+       { "a2vc1",      0x3c0, 1, R8A7796_PD_A2VC1,     R8A7796_PD_A3VC },
+       { "3dg-a",      0x100, 0, R8A7796_PD_3DG_A,     R8A7796_PD_ALWAYS_ON },
+       { "3dg-b",      0x100, 1, R8A7796_PD_3DG_B,     R8A7796_PD_3DG_A },
+       { "a3ir",       0x180, 0, R8A7796_PD_A3IR,      R8A7796_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a7796_sysc_info __initconst = {
+       .areas = r8a7796_areas,
+       .num_areas = ARRAY_SIZE(r8a7796_areas),
+};
index 79dbc77..65c8e1e 100644 (file)
@@ -164,15 +164,6 @@ static bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch)
        return false;
 }
 
-void __iomem *rcar_sysc_init(phys_addr_t base)
-{
-       rcar_sysc_base = ioremap_nocache(base, PAGE_SIZE);
-       if (!rcar_sysc_base)
-               panic("unable to ioremap R-Car SYSC hardware block\n");
-
-       return rcar_sysc_base;
-}
-
 struct rcar_sysc_pd {
        struct generic_pm_domain genpd;
        struct rcar_sysc_ch ch;
@@ -293,6 +284,9 @@ static const struct of_device_id rcar_sysc_matches[] = {
 #ifdef CONFIG_ARCH_R8A7791
        { .compatible = "renesas,r8a7791-sysc", .data = &r8a7791_sysc_info },
 #endif
+#ifdef CONFIG_ARCH_R8A7792
+       { .compatible = "renesas,r8a7792-sysc", .data = &r8a7792_sysc_info },
+#endif
 #ifdef CONFIG_ARCH_R8A7793
        /* R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. */
        { .compatible = "renesas,r8a7793-sysc", .data = &r8a7791_sysc_info },
@@ -302,6 +296,9 @@ static const struct of_device_id rcar_sysc_matches[] = {
 #endif
 #ifdef CONFIG_ARCH_R8A7795
        { .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info },
+#endif
+#ifdef CONFIG_ARCH_R8A7796
+       { .compatible = "renesas,r8a7796-sysc", .data = &r8a7796_sysc_info },
 #endif
        { /* sentinel */ }
 };
@@ -322,6 +319,9 @@ static int __init rcar_sysc_pd_init(void)
        unsigned int i;
        int error;
 
+       if (rcar_sysc_base)
+               return 0;
+
        np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match);
        if (!np)
                return -ENODEV;
@@ -392,10 +392,35 @@ static int __init rcar_sysc_pd_init(void)
                domains->domains[area->isr_bit] = &pd->genpd;
        }
 
-       of_genpd_add_provider_onecell(np, &domains->onecell_data);
+       error = of_genpd_add_provider_onecell(np, &domains->onecell_data);
 
 out_put:
        of_node_put(np);
        return error;
 }
 early_initcall(rcar_sysc_pd_init);
+
+void __init rcar_sysc_init(phys_addr_t base, u32 syscier)
+{
+       u32 syscimr;
+
+       if (!rcar_sysc_pd_init())
+               return;
+
+       rcar_sysc_base = ioremap_nocache(base, PAGE_SIZE);
+
+       /*
+        * Mask all interrupt sources to prevent the CPU from receiving them.
+        * Make sure not to clear reserved bits that were set before.
+        */
+       syscimr = ioread32(rcar_sysc_base + SYSCIMR);
+       syscimr |= syscier;
+       pr_debug("%s: syscimr = 0x%08x\n", __func__, syscimr);
+       iowrite32(syscimr, rcar_sysc_base + SYSCIMR);
+
+       /*
+        * SYSC needs all interrupt sources enabled to control power.
+        */
+       pr_debug("%s: syscier = 0x%08x\n", __func__, syscier);
+       iowrite32(syscier, rcar_sysc_base + SYSCIER);
+}
index 5e76617..77dbe86 100644 (file)
@@ -53,6 +53,8 @@ struct rcar_sysc_info {
 extern const struct rcar_sysc_info r8a7779_sysc_info;
 extern const struct rcar_sysc_info r8a7790_sysc_info;
 extern const struct rcar_sysc_info r8a7791_sysc_info;
+extern const struct rcar_sysc_info r8a7792_sysc_info;
 extern const struct rcar_sysc_info r8a7794_sysc_info;
 extern const struct rcar_sysc_info r8a7795_sysc_info;
+extern const struct rcar_sysc_info r8a7796_sysc_info;
 #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */
diff --git a/include/dt-bindings/power/r8a7796-sysc.h b/include/dt-bindings/power/r8a7796-sysc.h
new file mode 100644 (file)
index 0000000..5b4daab
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 Glider bvba
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+#ifndef __DT_BINDINGS_POWER_R8A7796_SYSC_H__
+#define __DT_BINDINGS_POWER_R8A7796_SYSC_H__
+
+/*
+ * These power domain indices match the numbers of the interrupt bits
+ * representing the power areas in the various Interrupt Registers
+ * (e.g. SYSCISR, Interrupt Status Register)
+ */
+
+#define R8A7796_PD_CA57_CPU0            0
+#define R8A7796_PD_CA57_CPU1            1
+#define R8A7796_PD_CA53_CPU0            5
+#define R8A7796_PD_CA53_CPU1            6
+#define R8A7796_PD_CA53_CPU2            7
+#define R8A7796_PD_CA53_CPU3            8
+#define R8A7796_PD_CA57_SCU            12
+#define R8A7796_PD_CR7                 13
+#define R8A7796_PD_A3VC                        14
+#define R8A7796_PD_3DG_A               17
+#define R8A7796_PD_3DG_B               18
+#define R8A7796_PD_CA53_SCU            21
+#define R8A7796_PD_A3IR                        24
+#define R8A7796_PD_A2VC0               25
+#define R8A7796_PD_A2VC1               26
+
+/* Always-on power area */
+#define R8A7796_PD_ALWAYS_ON           32
+
+#endif /* __DT_BINDINGS_POWER_R8A7796_SYSC_H__ */
index 92fc613..7b8b280 100644 (file)
@@ -11,6 +11,6 @@ struct rcar_sysc_ch {
 
 int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch);
 int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch);
-void __iomem *rcar_sysc_init(phys_addr_t base);
+void rcar_sysc_init(phys_addr_t base, u32 syscier);
 
 #endif /* __LINUX_SOC_RENESAS_RCAR_SYSC_H__ */