From fa43948f6736b74c5840ec0b028d3662caf0f558 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 16 Nov 2018 14:48:41 +0100 Subject: arm64: renesas: Move SoC Kconfig symbols to drivers/soc/renesas/ arch/arm64/Kconfig.platforms has SoC-specific Kconfig symbols for Renesas SoCs, while other vendors have only a single Kconfig symbol. Increase consistency with other vendors by moving the SoC-specific Kconfig symbols to drivers/soc/renesas/Kconfig. Increase consistency with R-Car Gen1 and Gen2 SoCs on arm32 by introducing a family-specific Kconfig symbol for R-Car Gen3 (ARCH_RCAR_GEN3), which enables family-specific hardware features. While so far only a single family (R-Car Gen3 and derivatives) of Renesas arm64 SoCs is supported by Linux, this will make it easier to add support for other SoC families later. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- drivers/soc/renesas/Kconfig | 90 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 13 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 407f02c80e8b..2f5bc5a6ae2b 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -3,30 +3,94 @@ config SOC_RENESAS bool "Renesas SoC driver support" if COMPILE_TEST && !ARCH_RENESAS default y if ARCH_RENESAS select SOC_BUS - select RST_RCAR if ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 || \ - ARCH_R8A774A1 || ARCH_R8A774C0 || ARCH_R8A7795 || \ - ARCH_R8A7796 || ARCH_R8A77965 || ARCH_R8A77970 || \ - ARCH_R8A77980 || ARCH_R8A77990 || ARCH_R8A77995 + select RST_RCAR if ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 select SYSC_R8A7743 if ARCH_R8A7743 || ARCH_R8A7744 select SYSC_R8A7745 if ARCH_R8A7745 select SYSC_R8A77470 if ARCH_R8A77470 - select SYSC_R8A774A1 if ARCH_R8A774A1 - select SYSC_R8A774C0 if ARCH_R8A774C0 select SYSC_R8A7779 if ARCH_R8A7779 select SYSC_R8A7790 if ARCH_R8A7790 select SYSC_R8A7791 if ARCH_R8A7791 || ARCH_R8A7793 select SYSC_R8A7792 if ARCH_R8A7792 select SYSC_R8A7794 if ARCH_R8A7794 - select SYSC_R8A7795 if ARCH_R8A7795 - select SYSC_R8A7796 if ARCH_R8A7796 - select SYSC_R8A77965 if ARCH_R8A77965 - select SYSC_R8A77970 if ARCH_R8A77970 - select SYSC_R8A77980 if ARCH_R8A77980 - select SYSC_R8A77990 if ARCH_R8A77990 - select SYSC_R8A77995 if ARCH_R8A77995 if SOC_RENESAS +config ARCH_RCAR_GEN3 + bool + select PM + select PM_GENERIC_DOMAINS + select RENESAS_IRQC + select RST_RCAR + select SYS_SUPPORTS_SH_CMT + select SYS_SUPPORTS_SH_TMU + +if ARM64 + +config ARCH_R8A774A1 + bool "Renesas RZ/G2M SoC Platform" + select ARCH_RCAR_GEN3 + select SYSC_R8A774A1 + help + This enables support for the Renesas RZ/G2M SoC. + +config ARCH_R8A774C0 + bool "Renesas RZ/G2E SoC Platform" + select ARCH_RCAR_GEN3 + select SYSC_R8A774C0 + help + This enables support for the Renesas RZ/G2E SoC. + +config ARCH_R8A7795 + bool "Renesas R-Car H3 SoC Platform" + select ARCH_RCAR_GEN3 + select SYSC_R8A7795 + help + This enables support for the Renesas R-Car H3 SoC. + +config ARCH_R8A7796 + bool "Renesas R-Car M3-W SoC Platform" + select ARCH_RCAR_GEN3 + select SYSC_R8A7796 + help + This enables support for the Renesas R-Car M3-W SoC. + +config ARCH_R8A77965 + bool "Renesas R-Car M3-N SoC Platform" + select ARCH_RCAR_GEN3 + select SYSC_R8A77965 + help + This enables support for the Renesas R-Car M3-N SoC. + +config ARCH_R8A77970 + bool "Renesas R-Car V3M SoC Platform" + select ARCH_RCAR_GEN3 + select SYSC_R8A77970 + help + This enables support for the Renesas R-Car V3M SoC. + +config ARCH_R8A77980 + bool "Renesas R-Car V3H SoC Platform" + select ARCH_RCAR_GEN3 + select SYSC_R8A77980 + help + This enables support for the Renesas R-Car V3H SoC. + +config ARCH_R8A77990 + bool "Renesas R-Car E3 SoC Platform" + select ARCH_RCAR_GEN3 + select SYSC_R8A77990 + help + This enables support for the Renesas R-Car E3 SoC. + +config ARCH_R8A77995 + bool "Renesas R-Car D3 SoC Platform" + select ARCH_RCAR_GEN3 + select SYSC_R8A77995 + help + This enables support for the Renesas R-Car D3 SoC. + +endif # ARM64 + # SoC config SYSC_R8A7743 bool "RZ/G1M System Controller support" if COMPILE_TEST -- cgit v1.2.3 From 062887bf5ef733133e51c77900ad5a570a974817 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 16 Nov 2018 14:48:42 +0100 Subject: ARM: shmobile: Move SoC Kconfig symbols to drivers/soc/renesas/ For consistency with arm64, where vendors have a single Kconfig symbol in arch/arm64/Kconfig.platforms. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/Kconfig | 126 ----------------------------------- drivers/soc/renesas/Kconfig | 148 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 139 insertions(+), 135 deletions(-) (limited to 'drivers/soc') diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 70c6f557f8cd..9b798c9dffe4 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -4,31 +4,6 @@ config PM_RMOBILE select PM select PM_GENERIC_DOMAINS -config ARCH_RCAR_GEN1 - bool - select PM - select PM_GENERIC_DOMAINS - select RENESAS_INTC_IRQPIN - select SYS_SUPPORTS_SH_TMU - -config ARCH_RCAR_GEN2 - bool - select HAVE_ARM_ARCH_TIMER - select PM - select PM_GENERIC_DOMAINS - select RENESAS_IRQC - select SYS_SUPPORTS_SH_CMT - -config ARCH_RMOBILE - bool - select PM_RMOBILE - select SYS_SUPPORTS_SH_CMT - select SYS_SUPPORTS_SH_TMU - -config ARCH_RZN1 - bool - select ARM_AMBA - menuconfig ARCH_RENESAS bool "Renesas ARM SoCs" depends on ARCH_MULTI_V7 && MMU @@ -38,104 +13,3 @@ menuconfig ARCH_RENESAS select PINCTRL select SOC_BUS select ZONE_DMA if ARM_LPAE - -if ARCH_RENESAS - -#comment "Renesas ARM SoCs System Type" - -config ARCH_EMEV2 - bool "Emma Mobile EV2" - select HAVE_ARM_SCU if SMP - select SYS_SUPPORTS_EM_STI - -config ARCH_R7S72100 - bool "RZ/A1H (R7S72100)" - select PM - select PM_GENERIC_DOMAINS - select SYS_SUPPORTS_SH_MTU2 - select RENESAS_OSTM - -config ARCH_R7S9210 - bool "RZ/A2 (R7S9210)" - select PM - select PM_GENERIC_DOMAINS - select RENESAS_OSTM - -config ARCH_R8A73A4 - bool "R-Mobile APE6 (R8A73A40)" - select ARCH_RMOBILE - select ARM_ERRATA_798181 if SMP - select HAVE_ARM_ARCH_TIMER - select RENESAS_IRQC - -config ARCH_R8A7740 - bool "R-Mobile A1 (R8A77400)" - select ARCH_RMOBILE - select RENESAS_INTC_IRQPIN - -config ARCH_R8A7743 - bool "RZ/G1M (R8A77430)" - select ARCH_RCAR_GEN2 - select ARM_ERRATA_798181 if SMP - -config ARCH_R8A7744 - bool "RZ/G1N (R8A77440)" - select ARCH_RCAR_GEN2 - select ARM_ERRATA_798181 if SMP - -config ARCH_R8A7745 - bool "RZ/G1E (R8A77450)" - select ARCH_RCAR_GEN2 - -config ARCH_R8A77470 - bool "RZ/G1C (R8A77470)" - select ARCH_RCAR_GEN2 - -config ARCH_R8A7778 - bool "R-Car M1A (R8A77781)" - select ARCH_RCAR_GEN1 - -config ARCH_R8A7779 - bool "R-Car H1 (R8A77790)" - select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if SMP - select ARCH_RCAR_GEN1 - -config ARCH_R8A7790 - bool "R-Car H2 (R8A77900)" - select ARCH_RCAR_GEN2 - select ARM_ERRATA_798181 if SMP - select I2C - -config ARCH_R8A7791 - bool "R-Car M2-W (R8A77910)" - select ARCH_RCAR_GEN2 - select ARM_ERRATA_798181 if SMP - select I2C - -config ARCH_R8A7792 - bool "R-Car V2H (R8A77920)" - select ARCH_RCAR_GEN2 - select ARM_ERRATA_798181 if SMP - -config ARCH_R8A7793 - bool "R-Car M2-N (R8A7793)" - select ARCH_RCAR_GEN2 - select ARM_ERRATA_798181 if SMP - select I2C - -config ARCH_R8A7794 - bool "R-Car E2 (R8A77940)" - select ARCH_RCAR_GEN2 - -config ARCH_R9A06G032 - bool "RZ/N1D (R9A06G032)" - select ARCH_RZN1 - -config ARCH_SH73A0 - bool "SH-Mobile AG5 (R8A73A00)" - select ARCH_RMOBILE - select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if SMP - select RENESAS_INTC_IRQPIN -endif diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 2f5bc5a6ae2b..fe7f58616cdd 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -3,18 +3,26 @@ config SOC_RENESAS bool "Renesas SoC driver support" if COMPILE_TEST && !ARCH_RENESAS default y if ARCH_RENESAS select SOC_BUS - select RST_RCAR if ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 - select SYSC_R8A7743 if ARCH_R8A7743 || ARCH_R8A7744 - select SYSC_R8A7745 if ARCH_R8A7745 - select SYSC_R8A77470 if ARCH_R8A77470 - select SYSC_R8A7779 if ARCH_R8A7779 - select SYSC_R8A7790 if ARCH_R8A7790 - select SYSC_R8A7791 if ARCH_R8A7791 || ARCH_R8A7793 - select SYSC_R8A7792 if ARCH_R8A7792 - select SYSC_R8A7794 if ARCH_R8A7794 if SOC_RENESAS +config ARCH_RCAR_GEN1 + bool + select PM + select PM_GENERIC_DOMAINS + select RENESAS_INTC_IRQPIN + select RST_RCAR + select SYS_SUPPORTS_SH_TMU + +config ARCH_RCAR_GEN2 + bool + select HAVE_ARM_ARCH_TIMER + select PM + select PM_GENERIC_DOMAINS + select RENESAS_IRQC + select RST_RCAR + select SYS_SUPPORTS_SH_CMT + config ARCH_RCAR_GEN3 bool select PM @@ -24,6 +32,128 @@ config ARCH_RCAR_GEN3 select SYS_SUPPORTS_SH_CMT select SYS_SUPPORTS_SH_TMU +config ARCH_RMOBILE + bool + select PM_RMOBILE + select SYS_SUPPORTS_SH_CMT + select SYS_SUPPORTS_SH_TMU + +config ARCH_RZN1 + bool + select ARM_AMBA + +if ARM + +#comment "Renesas ARM SoCs System Type" + +config ARCH_EMEV2 + bool "Emma Mobile EV2" + select HAVE_ARM_SCU if SMP + select SYS_SUPPORTS_EM_STI + +config ARCH_R7S72100 + bool "RZ/A1H (R7S72100)" + select PM + select PM_GENERIC_DOMAINS + select SYS_SUPPORTS_SH_MTU2 + select RENESAS_OSTM + +config ARCH_R7S9210 + bool "RZ/A2 (R7S9210)" + select PM + select PM_GENERIC_DOMAINS + select RENESAS_OSTM + +config ARCH_R8A73A4 + bool "R-Mobile APE6 (R8A73A40)" + select ARCH_RMOBILE + select ARM_ERRATA_798181 if SMP + select HAVE_ARM_ARCH_TIMER + select RENESAS_IRQC + +config ARCH_R8A7740 + bool "R-Mobile A1 (R8A77400)" + select ARCH_RMOBILE + select RENESAS_INTC_IRQPIN + +config ARCH_R8A7743 + bool "RZ/G1M (R8A77430)" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP + select SYSC_R8A7743 + +config ARCH_R8A7744 + bool "RZ/G1N (R8A77440)" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP + select SYSC_R8A7743 + +config ARCH_R8A7745 + bool "RZ/G1E (R8A77450)" + select ARCH_RCAR_GEN2 + select SYSC_R8A7745 + +config ARCH_R8A77470 + bool "RZ/G1C (R8A77470)" + select ARCH_RCAR_GEN2 + select SYSC_R8A77470 + +config ARCH_R8A7778 + bool "R-Car M1A (R8A77781)" + select ARCH_RCAR_GEN1 + +config ARCH_R8A7779 + bool "R-Car H1 (R8A77790)" + select ARCH_RCAR_GEN1 + select HAVE_ARM_SCU if SMP + select HAVE_ARM_TWD if SMP + select SYSC_R8A7779 + +config ARCH_R8A7790 + bool "R-Car H2 (R8A77900)" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP + select I2C + select SYSC_R8A7790 + +config ARCH_R8A7791 + bool "R-Car M2-W (R8A77910)" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP + select I2C + select SYSC_R8A7791 + +config ARCH_R8A7792 + bool "R-Car V2H (R8A77920)" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP + select SYSC_R8A7792 + +config ARCH_R8A7793 + bool "R-Car M2-N (R8A7793)" + select ARCH_RCAR_GEN2 + select ARM_ERRATA_798181 if SMP + select I2C + select SYSC_R8A7791 + +config ARCH_R8A7794 + bool "R-Car E2 (R8A77940)" + select ARCH_RCAR_GEN2 + select SYSC_R8A7794 + +config ARCH_R9A06G032 + bool "RZ/N1D (R9A06G032)" + select ARCH_RZN1 + +config ARCH_SH73A0 + bool "SH-Mobile AG5 (R8A73A00)" + select ARCH_RMOBILE + select HAVE_ARM_SCU if SMP + select HAVE_ARM_TWD if SMP + select RENESAS_INTC_IRQPIN + +endif # ARM + if ARM64 config ARCH_R8A774A1 -- cgit v1.2.3 From 2ed29e15e4b2500ae78de658a18f4482e7ac288b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 29 Nov 2018 12:09:31 +0100 Subject: ARM: shmobile: R-Mobile: Move pm-rmobile to drivers/soc/renesas/ The pm-rmobile driver is really a driver for the System Controller (SYSC) found in R-Mobile SoCs. An equivalent driver for R-Car SoCs is already located under drivers/soc/renesas/. Hence move the pm-rmobile driver from arch/arm/mach-shmobile/ to drivers/soc/renesas/, and rename it to rmobile-sysc. Enable compile-testing on non-ARM and non-R-Mobile SoCs. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/Kconfig | 5 - arch/arm/mach-shmobile/Makefile | 1 - arch/arm/mach-shmobile/pm-rmobile.c | 352 ------------------------------------ drivers/soc/renesas/Kconfig | 7 +- drivers/soc/renesas/Makefile | 1 + drivers/soc/renesas/rmobile-sysc.c | 352 ++++++++++++++++++++++++++++++++++++ 6 files changed, 359 insertions(+), 359 deletions(-) delete mode 100644 arch/arm/mach-shmobile/pm-rmobile.c create mode 100644 drivers/soc/renesas/rmobile-sysc.c (limited to 'drivers/soc') diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 9b798c9dffe4..3683d6f10973 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -1,9 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -config PM_RMOBILE - bool - select PM - select PM_GENERIC_DOMAINS - menuconfig ARCH_RENESAS bool "Renesas ARM SoCs" depends on ARCH_MULTI_V7 && MMU diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 5591646cb9bb..f7bf17b7abae 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -35,7 +35,6 @@ smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o # PM objects obj-$(CONFIG_SUSPEND) += suspend.o -obj-$(CONFIG_PM_RMOBILE) += pm-rmobile.o obj-$(CONFIG_ARCH_RCAR_GEN2) += pm-rcar-gen2.o # Framework support diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c deleted file mode 100644 index 421ae1c887d8..000000000000 --- a/arch/arm/mach-shmobile/pm-rmobile.c +++ /dev/null @@ -1,352 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * rmobile power management support - * - * Copyright (C) 2012 Renesas Solutions Corp. - * Copyright (C) 2012 Kuninori Morimoto - * Copyright (C) 2014 Glider bvba - * - * based on pm-sh7372.c - * Copyright (C) 2011 Magnus Damm - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* SYSC */ -#define SPDCR 0x08 /* SYS Power Down Control Register */ -#define SWUCR 0x14 /* SYS Wakeup Control Register */ -#define PSTR 0x80 /* Power Status Register */ - -#define PSTR_RETRIES 100 -#define PSTR_DELAY_US 10 - -struct rmobile_pm_domain { - struct generic_pm_domain genpd; - struct dev_power_governor *gov; - int (*suspend)(void); - void __iomem *base; - unsigned int bit_shift; -}; - -static inline -struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d) -{ - return container_of(d, struct rmobile_pm_domain, genpd); -} - -static int rmobile_pd_power_down(struct generic_pm_domain *genpd) -{ - struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd); - unsigned int mask; - - if (rmobile_pd->bit_shift == ~0) - return -EBUSY; - - mask = BIT(rmobile_pd->bit_shift); - if (rmobile_pd->suspend) { - int ret = rmobile_pd->suspend(); - - if (ret) - return ret; - } - - if (__raw_readl(rmobile_pd->base + PSTR) & mask) { - unsigned int retry_count; - __raw_writel(mask, rmobile_pd->base + SPDCR); - - for (retry_count = PSTR_RETRIES; retry_count; retry_count--) { - if (!(__raw_readl(rmobile_pd->base + SPDCR) & mask)) - break; - cpu_relax(); - } - } - - pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", genpd->name, mask, - __raw_readl(rmobile_pd->base + PSTR)); - - return 0; -} - -static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd) -{ - unsigned int mask; - unsigned int retry_count; - int ret = 0; - - if (rmobile_pd->bit_shift == ~0) - return 0; - - mask = BIT(rmobile_pd->bit_shift); - if (__raw_readl(rmobile_pd->base + PSTR) & mask) - return ret; - - __raw_writel(mask, rmobile_pd->base + SWUCR); - - for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { - if (!(__raw_readl(rmobile_pd->base + SWUCR) & mask)) - break; - if (retry_count > PSTR_RETRIES) - udelay(PSTR_DELAY_US); - else - cpu_relax(); - } - if (!retry_count) - ret = -EIO; - - pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n", - rmobile_pd->genpd.name, mask, - __raw_readl(rmobile_pd->base + PSTR)); - - return ret; -} - -static int rmobile_pd_power_up(struct generic_pm_domain *genpd) -{ - return __rmobile_pd_power_up(to_rmobile_pd(genpd)); -} - -static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) -{ - struct generic_pm_domain *genpd = &rmobile_pd->genpd; - struct dev_power_governor *gov = rmobile_pd->gov; - - genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; - genpd->power_off = rmobile_pd_power_down; - genpd->power_on = rmobile_pd_power_up; - genpd->attach_dev = cpg_mstp_attach_dev; - genpd->detach_dev = cpg_mstp_detach_dev; - __rmobile_pd_power_up(rmobile_pd); - pm_genpd_init(genpd, gov ? : &simple_qos_governor, false); -} - -static int rmobile_pd_suspend_console(void) -{ - /* - * Serial consoles make use of SCIF hardware located in this domain, - * hence keep the power domain on if "no_console_suspend" is set. - */ - return console_suspend_enabled ? 0 : -EBUSY; -} - -enum pd_types { - PD_NORMAL, - PD_CPU, - PD_CONSOLE, - PD_DEBUG, - PD_MEMCTL, -}; - -#define MAX_NUM_SPECIAL_PDS 16 - -static struct special_pd { - struct device_node *pd; - enum pd_types type; -} special_pds[MAX_NUM_SPECIAL_PDS] __initdata; - -static unsigned int num_special_pds __initdata; - -static const struct of_device_id special_ids[] __initconst = { - { .compatible = "arm,coresight-etm3x", .data = (void *)PD_DEBUG }, - { .compatible = "renesas,dbsc-r8a73a4", .data = (void *)PD_MEMCTL, }, - { .compatible = "renesas,dbsc3-r8a7740", .data = (void *)PD_MEMCTL, }, - { .compatible = "renesas,sbsc-sh73a0", .data = (void *)PD_MEMCTL, }, - { /* sentinel */ }, -}; - -static void __init add_special_pd(struct device_node *np, enum pd_types type) -{ - unsigned int i; - struct device_node *pd; - - pd = of_parse_phandle(np, "power-domains", 0); - if (!pd) - return; - - for (i = 0; i < num_special_pds; i++) - if (pd == special_pds[i].pd && type == special_pds[i].type) { - of_node_put(pd); - return; - } - - if (num_special_pds == ARRAY_SIZE(special_pds)) { - pr_warn("Too many special PM domains\n"); - of_node_put(pd); - return; - } - - pr_debug("Special PM domain %pOFn type %d for %pOF\n", pd, type, np); - - special_pds[num_special_pds].pd = pd; - special_pds[num_special_pds].type = type; - num_special_pds++; -} - -static void __init get_special_pds(void) -{ - struct device_node *np; - const struct of_device_id *id; - - /* PM domains containing CPUs */ - for_each_of_cpu_node(np) - add_special_pd(np, PD_CPU); - - /* PM domain containing console */ - if (of_stdout) - add_special_pd(of_stdout, PD_CONSOLE); - - /* PM domains containing other special devices */ - for_each_matching_node_and_match(np, special_ids, &id) - add_special_pd(np, (enum pd_types)id->data); -} - -static void __init put_special_pds(void) -{ - unsigned int i; - - for (i = 0; i < num_special_pds; i++) - of_node_put(special_pds[i].pd); -} - -static enum pd_types __init pd_type(const struct device_node *pd) -{ - unsigned int i; - - for (i = 0; i < num_special_pds; i++) - if (pd == special_pds[i].pd) - return special_pds[i].type; - - return PD_NORMAL; -} - -static void __init rmobile_setup_pm_domain(struct device_node *np, - struct rmobile_pm_domain *pd) -{ - const char *name = pd->genpd.name; - - switch (pd_type(np)) { - case PD_CPU: - /* - * This domain contains the CPU core and therefore it should - * only be turned off if the CPU is not in use. - */ - pr_debug("PM domain %s contains CPU\n", name); - pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; - break; - - case PD_CONSOLE: - pr_debug("PM domain %s contains serial console\n", name); - pd->gov = &pm_domain_always_on_gov; - pd->suspend = rmobile_pd_suspend_console; - break; - - case PD_DEBUG: - /* - * This domain contains the Coresight-ETM hardware block and - * therefore it should only be turned off if the debug module - * is not in use. - */ - pr_debug("PM domain %s contains Coresight-ETM\n", name); - pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; - break; - - case PD_MEMCTL: - /* - * This domain contains a memory-controller and therefore it - * should only be turned off if memory is not in use. - */ - pr_debug("PM domain %s contains MEMCTL\n", name); - pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; - break; - - case PD_NORMAL: - break; - } - - rmobile_init_pm_domain(pd); -} - -static int __init rmobile_add_pm_domains(void __iomem *base, - struct device_node *parent, - struct generic_pm_domain *genpd_parent) -{ - struct device_node *np; - - for_each_child_of_node(parent, np) { - struct rmobile_pm_domain *pd; - u32 idx = ~0; - - if (of_property_read_u32(np, "reg", &idx)) { - /* always-on domain */ - } - - pd = kzalloc(sizeof(*pd), GFP_KERNEL); - if (!pd) { - of_node_put(np); - return -ENOMEM; - } - - pd->genpd.name = np->name; - pd->base = base; - pd->bit_shift = idx; - - rmobile_setup_pm_domain(np, pd); - if (genpd_parent) - pm_genpd_add_subdomain(genpd_parent, &pd->genpd); - of_genpd_add_provider_simple(np, &pd->genpd); - - rmobile_add_pm_domains(base, np, &pd->genpd); - } - return 0; -} - -static int __init rmobile_init_pm_domains(void) -{ - struct device_node *np, *pmd; - bool scanned = false; - void __iomem *base; - int ret = 0; - - for_each_compatible_node(np, NULL, "renesas,sysc-rmobile") { - base = of_iomap(np, 0); - if (!base) { - pr_warn("%pOF cannot map reg 0\n", np); - continue; - } - - pmd = of_get_child_by_name(np, "pm-domains"); - if (!pmd) { - pr_warn("%pOF lacks pm-domains node\n", np); - continue; - } - - if (!scanned) { - /* Find PM domains containing special blocks */ - get_special_pds(); - scanned = true; - } - - ret = rmobile_add_pm_domains(base, pmd, NULL); - of_node_put(pmd); - if (ret) { - of_node_put(np); - break; - } - } - - put_special_pds(); - - return ret; -} - -core_initcall(rmobile_init_pm_domains); diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index fe7f58616cdd..4d8012e1205c 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -34,9 +34,11 @@ config ARCH_RCAR_GEN3 config ARCH_RMOBILE bool - select PM_RMOBILE + select PM + select PM_GENERIC_DOMAINS select SYS_SUPPORTS_SH_CMT select SYS_SUPPORTS_SH_TMU + select SYSC_RMOBILE config ARCH_RZN1 bool @@ -297,4 +299,7 @@ config RST_RCAR config SYSC_RCAR bool "R-Car System Controller support" if COMPILE_TEST +config SYSC_RMOBILE + bool "R-Mobile System Controller support" if COMPILE_TEST + endif # SOC_RENESAS diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index 3bdd7dbc38a9..00764d5a60b3 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -27,3 +27,4 @@ endif # Family obj-$(CONFIG_RST_RCAR) += rcar-rst.o obj-$(CONFIG_SYSC_RCAR) += rcar-sysc.o +obj-$(CONFIG_SYSC_RMOBILE) += rmobile-sysc.o diff --git a/drivers/soc/renesas/rmobile-sysc.c b/drivers/soc/renesas/rmobile-sysc.c new file mode 100644 index 000000000000..421ae1c887d8 --- /dev/null +++ b/drivers/soc/renesas/rmobile-sysc.c @@ -0,0 +1,352 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * rmobile power management support + * + * Copyright (C) 2012 Renesas Solutions Corp. + * Copyright (C) 2012 Kuninori Morimoto + * Copyright (C) 2014 Glider bvba + * + * based on pm-sh7372.c + * Copyright (C) 2011 Magnus Damm + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* SYSC */ +#define SPDCR 0x08 /* SYS Power Down Control Register */ +#define SWUCR 0x14 /* SYS Wakeup Control Register */ +#define PSTR 0x80 /* Power Status Register */ + +#define PSTR_RETRIES 100 +#define PSTR_DELAY_US 10 + +struct rmobile_pm_domain { + struct generic_pm_domain genpd; + struct dev_power_governor *gov; + int (*suspend)(void); + void __iomem *base; + unsigned int bit_shift; +}; + +static inline +struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d) +{ + return container_of(d, struct rmobile_pm_domain, genpd); +} + +static int rmobile_pd_power_down(struct generic_pm_domain *genpd) +{ + struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd); + unsigned int mask; + + if (rmobile_pd->bit_shift == ~0) + return -EBUSY; + + mask = BIT(rmobile_pd->bit_shift); + if (rmobile_pd->suspend) { + int ret = rmobile_pd->suspend(); + + if (ret) + return ret; + } + + if (__raw_readl(rmobile_pd->base + PSTR) & mask) { + unsigned int retry_count; + __raw_writel(mask, rmobile_pd->base + SPDCR); + + for (retry_count = PSTR_RETRIES; retry_count; retry_count--) { + if (!(__raw_readl(rmobile_pd->base + SPDCR) & mask)) + break; + cpu_relax(); + } + } + + pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", genpd->name, mask, + __raw_readl(rmobile_pd->base + PSTR)); + + return 0; +} + +static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd) +{ + unsigned int mask; + unsigned int retry_count; + int ret = 0; + + if (rmobile_pd->bit_shift == ~0) + return 0; + + mask = BIT(rmobile_pd->bit_shift); + if (__raw_readl(rmobile_pd->base + PSTR) & mask) + return ret; + + __raw_writel(mask, rmobile_pd->base + SWUCR); + + for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { + if (!(__raw_readl(rmobile_pd->base + SWUCR) & mask)) + break; + if (retry_count > PSTR_RETRIES) + udelay(PSTR_DELAY_US); + else + cpu_relax(); + } + if (!retry_count) + ret = -EIO; + + pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n", + rmobile_pd->genpd.name, mask, + __raw_readl(rmobile_pd->base + PSTR)); + + return ret; +} + +static int rmobile_pd_power_up(struct generic_pm_domain *genpd) +{ + return __rmobile_pd_power_up(to_rmobile_pd(genpd)); +} + +static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) +{ + struct generic_pm_domain *genpd = &rmobile_pd->genpd; + struct dev_power_governor *gov = rmobile_pd->gov; + + genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; + genpd->power_off = rmobile_pd_power_down; + genpd->power_on = rmobile_pd_power_up; + genpd->attach_dev = cpg_mstp_attach_dev; + genpd->detach_dev = cpg_mstp_detach_dev; + __rmobile_pd_power_up(rmobile_pd); + pm_genpd_init(genpd, gov ? : &simple_qos_governor, false); +} + +static int rmobile_pd_suspend_console(void) +{ + /* + * Serial consoles make use of SCIF hardware located in this domain, + * hence keep the power domain on if "no_console_suspend" is set. + */ + return console_suspend_enabled ? 0 : -EBUSY; +} + +enum pd_types { + PD_NORMAL, + PD_CPU, + PD_CONSOLE, + PD_DEBUG, + PD_MEMCTL, +}; + +#define MAX_NUM_SPECIAL_PDS 16 + +static struct special_pd { + struct device_node *pd; + enum pd_types type; +} special_pds[MAX_NUM_SPECIAL_PDS] __initdata; + +static unsigned int num_special_pds __initdata; + +static const struct of_device_id special_ids[] __initconst = { + { .compatible = "arm,coresight-etm3x", .data = (void *)PD_DEBUG }, + { .compatible = "renesas,dbsc-r8a73a4", .data = (void *)PD_MEMCTL, }, + { .compatible = "renesas,dbsc3-r8a7740", .data = (void *)PD_MEMCTL, }, + { .compatible = "renesas,sbsc-sh73a0", .data = (void *)PD_MEMCTL, }, + { /* sentinel */ }, +}; + +static void __init add_special_pd(struct device_node *np, enum pd_types type) +{ + unsigned int i; + struct device_node *pd; + + pd = of_parse_phandle(np, "power-domains", 0); + if (!pd) + return; + + for (i = 0; i < num_special_pds; i++) + if (pd == special_pds[i].pd && type == special_pds[i].type) { + of_node_put(pd); + return; + } + + if (num_special_pds == ARRAY_SIZE(special_pds)) { + pr_warn("Too many special PM domains\n"); + of_node_put(pd); + return; + } + + pr_debug("Special PM domain %pOFn type %d for %pOF\n", pd, type, np); + + special_pds[num_special_pds].pd = pd; + special_pds[num_special_pds].type = type; + num_special_pds++; +} + +static void __init get_special_pds(void) +{ + struct device_node *np; + const struct of_device_id *id; + + /* PM domains containing CPUs */ + for_each_of_cpu_node(np) + add_special_pd(np, PD_CPU); + + /* PM domain containing console */ + if (of_stdout) + add_special_pd(of_stdout, PD_CONSOLE); + + /* PM domains containing other special devices */ + for_each_matching_node_and_match(np, special_ids, &id) + add_special_pd(np, (enum pd_types)id->data); +} + +static void __init put_special_pds(void) +{ + unsigned int i; + + for (i = 0; i < num_special_pds; i++) + of_node_put(special_pds[i].pd); +} + +static enum pd_types __init pd_type(const struct device_node *pd) +{ + unsigned int i; + + for (i = 0; i < num_special_pds; i++) + if (pd == special_pds[i].pd) + return special_pds[i].type; + + return PD_NORMAL; +} + +static void __init rmobile_setup_pm_domain(struct device_node *np, + struct rmobile_pm_domain *pd) +{ + const char *name = pd->genpd.name; + + switch (pd_type(np)) { + case PD_CPU: + /* + * This domain contains the CPU core and therefore it should + * only be turned off if the CPU is not in use. + */ + pr_debug("PM domain %s contains CPU\n", name); + pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; + break; + + case PD_CONSOLE: + pr_debug("PM domain %s contains serial console\n", name); + pd->gov = &pm_domain_always_on_gov; + pd->suspend = rmobile_pd_suspend_console; + break; + + case PD_DEBUG: + /* + * This domain contains the Coresight-ETM hardware block and + * therefore it should only be turned off if the debug module + * is not in use. + */ + pr_debug("PM domain %s contains Coresight-ETM\n", name); + pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; + break; + + case PD_MEMCTL: + /* + * This domain contains a memory-controller and therefore it + * should only be turned off if memory is not in use. + */ + pr_debug("PM domain %s contains MEMCTL\n", name); + pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; + break; + + case PD_NORMAL: + break; + } + + rmobile_init_pm_domain(pd); +} + +static int __init rmobile_add_pm_domains(void __iomem *base, + struct device_node *parent, + struct generic_pm_domain *genpd_parent) +{ + struct device_node *np; + + for_each_child_of_node(parent, np) { + struct rmobile_pm_domain *pd; + u32 idx = ~0; + + if (of_property_read_u32(np, "reg", &idx)) { + /* always-on domain */ + } + + pd = kzalloc(sizeof(*pd), GFP_KERNEL); + if (!pd) { + of_node_put(np); + return -ENOMEM; + } + + pd->genpd.name = np->name; + pd->base = base; + pd->bit_shift = idx; + + rmobile_setup_pm_domain(np, pd); + if (genpd_parent) + pm_genpd_add_subdomain(genpd_parent, &pd->genpd); + of_genpd_add_provider_simple(np, &pd->genpd); + + rmobile_add_pm_domains(base, np, &pd->genpd); + } + return 0; +} + +static int __init rmobile_init_pm_domains(void) +{ + struct device_node *np, *pmd; + bool scanned = false; + void __iomem *base; + int ret = 0; + + for_each_compatible_node(np, NULL, "renesas,sysc-rmobile") { + base = of_iomap(np, 0); + if (!base) { + pr_warn("%pOF cannot map reg 0\n", np); + continue; + } + + pmd = of_get_child_by_name(np, "pm-domains"); + if (!pmd) { + pr_warn("%pOF lacks pm-domains node\n", np); + continue; + } + + if (!scanned) { + /* Find PM domains containing special blocks */ + get_special_pds(); + scanned = true; + } + + ret = rmobile_add_pm_domains(base, pmd, NULL); + of_node_put(pmd); + if (ret) { + of_node_put(np); + break; + } + } + + put_special_pds(); + + return ret; +} + +core_initcall(rmobile_init_pm_domains); -- cgit v1.2.3