From patchwork Mon Dec 29 01:43:52 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Horman X-Patchwork-Id: 5546691 Return-Path: X-Original-To: patchwork-linux-sh@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 87D17BF6C3 for ; Mon, 29 Dec 2014 01:44:06 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 62EA020173 for ; Mon, 29 Dec 2014 01:44:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E97BC20176 for ; Mon, 29 Dec 2014 01:44:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751836AbaL2BoD (ORCPT ); Sun, 28 Dec 2014 20:44:03 -0500 Received: from kirsty.vergenet.net ([202.4.237.240]:53450 "EHLO kirsty.vergenet.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751740AbaL2BoC (ORCPT ); Sun, 28 Dec 2014 20:44:02 -0500 Received: from penelope.kanocho.kobe.vergenet.net (p4076-ipbfp703kobeminato.hyogo.ocn.ne.jp [122.20.17.76]) by kirsty.vergenet.net (Postfix) with ESMTP id ECE4626717E; Mon, 29 Dec 2014 12:43:55 +1100 (EST) Received: by penelope.kanocho.kobe.vergenet.net (Postfix, from userid 7100) id 3213C604C1; Mon, 29 Dec 2014 10:43:54 +0900 (JST) From: Simon Horman To: linux-sh@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, Magnus Damm , Geert Uytterhoeven , Simon Horman Subject: [PATCH 5/6] ARM: shmobile: R-Mobile: Add DT support for PM domains Date: Mon, 29 Dec 2014 10:43:52 +0900 Message-Id: X-Mailer: git-send-email 2.1.3 In-Reply-To: References: Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Geert Uytterhoeven Populate the PM domains from DT, and provide support to hook up devices to their respective PM domain. The always-on power area (e.g. C5 on r8a7740) is created as a PM domain without software control, to allow Run-Time management of module clocks for hardware blocks inside this area. Special cases like PM domains containing CPUs, the console device, or Coresight-ETM, are handled by scanning the DT topology. As long as the ARM debug/perf code doesn't use resource management with runtime PM support, the power area containing Coresight-ETM (e.g. D4 on r8a7740) must be kept powered to avoid a crash during resume from s2ram (dbg_cpu_pm_notify() calls reset_ctrl_regs() unconditionally, causing an undefined instruction oops). Initialization is done from core_initcall(), as the "renesas,intc-irqpin" driver uses postcore_initcall(). Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/Kconfig | 3 +- arch/arm/mach-shmobile/pm-rmobile.c | 215 +++++++++++++++++++++++++++++++++++- arch/arm/mach-shmobile/pm-rmobile.h | 2 +- 3 files changed, 216 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 1b4fafe..76b80e5 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -7,6 +7,7 @@ config PM_RCAR config PM_RMOBILE bool + select PM_GENERIC_DOMAINS config ARCH_RCAR_GEN1 bool @@ -23,7 +24,7 @@ config ARCH_RCAR_GEN2 config ARCH_RMOBILE bool - select PM_RMOBILE if PM && !ARCH_SHMOBILE_MULTI + select PM_RMOBILE if PM select SYS_SUPPORTS_SH_CMT select SYS_SUPPORTS_SH_TMU diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c index a4ad718..3b9c8dd 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.c +++ b/arch/arm/mach-shmobile/pm-rmobile.c @@ -3,6 +3,7 @@ * * 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 @@ -13,10 +14,16 @@ */ #include #include +#include +#include +#include #include #include #include +#include + #include + #include "pm-rmobile.h" /* SYSC */ @@ -30,8 +37,12 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) { struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd); - unsigned int mask = 1 << rmobile_pd->bit_shift; + unsigned int mask; + + if (rmobile_pd->bit_shift == ~0) + return -EBUSY; + mask = 1 << rmobile_pd->bit_shift; if (rmobile_pd->suspend) { int ret = rmobile_pd->suspend(); @@ -61,10 +72,14 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd, bool do_resume) { - unsigned int mask = 1 << rmobile_pd->bit_shift; + unsigned int mask; unsigned int retry_count; int ret = 0; + if (rmobile_pd->bit_shift == ~0) + return 0; + + mask = 1 << rmobile_pd->bit_shift; if (__raw_readl(rmobile_pd->base + PSTR) & mask) goto out; @@ -156,6 +171,8 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) __rmobile_pd_power_up(rmobile_pd, false); } +#ifdef CONFIG_ARCH_SHMOBILE_LEGACY + void rmobile_init_domains(struct rmobile_pm_domain domains[], int num) { int j; @@ -188,3 +205,197 @@ void rmobile_add_devices_to_domains(struct pm_domain_device data[], rmobile_add_device_to_domain_td(data[j].domain_name, data[j].pdev, &latencies); } + +#else /* !CONFIG_ARCH_SHMOBILE_LEGACY */ + +static int rmobile_pd_suspend_cpu(void) +{ + /* + * This domain contains the CPU core and therefore it should + * only be turned off if the CPU is not in use. + */ + return -EBUSY; +} + +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; +} + +static int rmobile_pd_suspend_debug(void) +{ + /* + * This domain contains the Coresight-ETM hardware block and + * therefore it should only be turned off if the debug module is + * not in use. + */ + return -EBUSY; +} + +#define MAX_NUM_CPU_PDS 8 + +static unsigned int num_cpu_pds __initdata; +static struct device_node *cpu_pds[MAX_NUM_CPU_PDS] __initdata; +static struct device_node *console_pd __initdata; +static struct device_node *debug_pd __initdata; + +static void __init get_special_pds(void) +{ + struct device_node *np, *pd; + unsigned int i; + + /* PM domains containing CPUs */ + for_each_node_by_type(np, "cpu") { + pd = of_parse_phandle(np, "power-domains", 0); + if (!pd) + continue; + + for (i = 0; i < num_cpu_pds; i++) + if (pd == cpu_pds[i]) + break; + + if (i < num_cpu_pds) { + of_node_put(pd); + continue; + } + + if (num_cpu_pds == MAX_NUM_CPU_PDS) { + pr_warn("Too many CPU PM domains\n"); + of_node_put(pd); + continue; + } + + cpu_pds[num_cpu_pds++] = pd; + } + + /* PM domain containing console */ + if (of_stdout) + console_pd = of_parse_phandle(of_stdout, "power-domains", 0); + + /* PM domain containing Coresight-ETM */ + np = of_find_compatible_node(NULL, NULL, "arm,coresight-etm3x"); + if (np) + debug_pd = of_parse_phandle(np, "power-domains", 0); +} + +static void __init put_special_pds(void) +{ + unsigned int i; + + for (i = 0; i < num_cpu_pds; i++) + of_node_put(cpu_pds[i]); + of_node_put(console_pd); + of_node_put(debug_pd); +} + +static bool __init pd_contains_cpu(const struct device_node *pd) +{ + unsigned int i; + + for (i = 0; i < num_cpu_pds; i++) + if (pd == cpu_pds[i]) + return true; + + return false; +} + +static void __init rmobile_setup_pm_domain(struct device_node *np, + struct rmobile_pm_domain *pd) +{ + const char *name = pd->genpd.name; + + if (pd_contains_cpu(np)) { + pr_debug("PM domain %s contains CPU\n", name); + pd->gov = &pm_domain_always_on_gov; + pd->suspend = rmobile_pd_suspend_cpu; + } else if (np == console_pd) { + pr_debug("PM domain %s contains serial console\n", name); + pd->gov = &pm_domain_always_on_gov; + pd->suspend = rmobile_pd_suspend_console; + } else if (np == debug_pd) { + pr_debug("PM domain %s contains Coresight-ETM\n", name); + pd->gov = &pm_domain_always_on_gov; + pd->suspend = rmobile_pd_suspend_debug; + } + + 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) + 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("%s cannot map reg 0\n", np->full_name); + continue; + } + + pmd = of_find_node_by_name(np, "pm-domains"); + if (!pmd) { + pr_warn("%s lacks pm-domains node\n", np->full_name); + 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); + +#endif /* !CONFIG_ARCH_SHMOBILE_LEGACY */ diff --git a/arch/arm/mach-shmobile/pm-rmobile.h b/arch/arm/mach-shmobile/pm-rmobile.h index 0602130..5321978 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.h +++ b/arch/arm/mach-shmobile/pm-rmobile.h @@ -37,7 +37,7 @@ struct pm_domain_device { struct platform_device *pdev; }; -#ifdef CONFIG_PM_RMOBILE +#if defined(CONFIG_PM_RMOBILE) && defined(CONFIG_ARCH_SHMOBILE_LEGACY) extern void rmobile_init_domains(struct rmobile_pm_domain domains[], int num); extern void rmobile_add_device_to_domain_td(const char *domain_name, struct platform_device *pdev,