From patchwork Wed Mar 13 08:01:17 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Lo X-Patchwork-Id: 2262171 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id D4C8B3FCF6 for ; Wed, 13 Mar 2013 08:06:59 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UFgf0-0001sz-Mg; Wed, 13 Mar 2013 08:03:42 +0000 Received: from hqemgate03.nvidia.com ([216.228.121.140]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UFgdQ-0001KH-LE for linux-arm-kernel@lists.infradead.org; Wed, 13 Mar 2013 08:02:08 +0000 Received: from hqnvupgp07.nvidia.com (Not Verified[216.228.121.13]) by hqemgate03.nvidia.com id ; Wed, 13 Mar 2013 01:07:06 -0700 Received: from hqemhub03.nvidia.com ([172.17.108.22]) by hqnvupgp07.nvidia.com (PGP Universal service); Wed, 13 Mar 2013 01:01:53 -0700 X-PGP-Universal: processed; by hqnvupgp07.nvidia.com on Wed, 13 Mar 2013 01:01:53 -0700 Received: from jlo-ubuntu-64.nvidia.com (172.20.144.16) by hqemhub03.nvidia.com (172.20.150.15) with Microsoft SMTP Server (TLS) id 8.3.298.1; Wed, 13 Mar 2013 01:01:52 -0700 From: Joseph Lo To: Stephen Warren Subject: [PATCH V3 3/9] ARM: dt: tegra: add bindings of power management configurations for PMC Date: Wed, 13 Mar 2013 16:01:17 +0800 Message-ID: <1363161683-20825-4-git-send-email-josephl@nvidia.com> X-Mailer: git-send-email 1.8.1.5 In-Reply-To: <1363161683-20825-1-git-send-email-josephl@nvidia.com> References: <1363161683-20825-1-git-send-email-josephl@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130313_040205_003757_BE517C93 X-CRM114-Status: GOOD ( 20.43 ) X-Spam-Score: -9.5 (---------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-9.5 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [216.228.121.140 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record -2.6 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: devicetree-discuss@lists.ozlabs.org, Rob Herring , Grant Likely , Joseph Lo , linux-tegra@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org The PMC mostly controls the entry and exit of the system from different sleep modes. Different platform or system may have different configurations. The power management configurations of PMC is represented as some properties. The system needs to define the properties when the system supports deep sleep mode (i.e. suspend). Cc: Grant Likely Cc: Rob Herring Cc: devicetree-discuss@lists.ozlabs.org Signed-off-by: Joseph Lo --- V3: * fix typos V2: * squash the patches that defined the PM bindings for PMC and the implementation * replace the "unsigned long" with "u32" for the variables that are parsed from DT --- .../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 42 ++++++++++- arch/arm/mach-tegra/pmc.c | 83 ++++++++++++++++++++++ arch/arm/mach-tegra/pmc.h | 8 +++ 3 files changed, 132 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt index b5846e2..ae4e3ee 100644 --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt +++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt @@ -1,14 +1,46 @@ NVIDIA Tegra Power Management Controller (PMC) -Properties: +The PMC block interacts with an external Power Management Unit. The PMC +mostly controls the entry and exit of the system from different sleep +modes. It provides power-gating controllers for SoC and CPU power-islands. + +Required properties: - name : Should be pmc - compatible : Should contain "nvidia,tegra-pmc". - reg : Offset and length of the register set for the device + +Optional properties: - nvidia,invert-interrupt : If present, inverts the PMU interrupt signal. The PMU is an external Power Management Unit, whose interrupt output signal is fed into the PMC. This signal is optionally inverted, and then fed into the ARM GIC. The PMC is not involved in the detection or handling of this interrupt signal, merely its inversion. +- nvidia,suspend-mode : The suspend mode that the platform should use. + Valid values are 0, 1 and 2: + 0 (LP0): CPU + Core voltage off and DRAM in self-refresh + 1 (LP1): CPU vlotage off and DRAM in self-refresh + 2 (LP2): CPU voltage off +- nvidia,core-power-req-active-high : Boolean, core power request active-high +- nvidia,sys-clock-req-active-high : Boolean, system clock request active-high +- nvidia,combined-power-req : Boolean, combined power request for CPU & Core +- nvidia,cpu-pwr-good-en : Boolean, CPU power good signal (from PMIC to PMC) + is enabled. + +Required properties when nvidia,suspend-mode is specified: +- nvidia,cpu-pwr-good-time : CPU power good time in uS. +- nvidia,cpu-pwr-off-time : CPU power off time in uS. +- nvidia,core-pwr-good-time : + Core power good time in uS. +- nvidia,core-pwr-off-time : Core power off time in uS. + +Required properties when nvidia,suspend-mode=<0>: +- nvidia,lp0-vec : Starting address and length of LP0 vector + The LP0 vector contains the warm boot code that is executed by AVP when + resuming from the LP0 state. The AVP (Audio-Video Processor) is an ARM7 + processor and always being the first boot processor when chip is power on + or resume from deep sleep mode. When the system is resumed from the deep + sleep mode, the warm boot code will restore some PLLs, clocks and then + bring up CPU0 for resuming the system. Example: @@ -16,4 +48,12 @@ pmc@7000f400 { compatible = "nvidia,tegra20-pmc"; reg = <0x7000e400 0x400>; nvidia,invert-interrupt; + nvidia,suspend-mode = <1>; + nvidia,cpu-pwr-good-time = <2000>; + nvidia,cpu-pwr-off-time = <100>; + nvidia,core-pwr-good-time = <3845 3845>; + nvidia,core-pwr-off-time = <458>; + nvidia,core-power-req-active-high; + nvidia,sys-clock-req-active-high; + nvidia,lp0-vec = <0xbdffd000 0x2000>; }; diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c index b30e921..d331f87 100644 --- a/arch/arm/mach-tegra/pmc.c +++ b/arch/arm/mach-tegra/pmc.c @@ -20,6 +20,8 @@ #include #include +#include "pmc.h" + #define PMC_CTRL 0x0 #define PMC_CTRL_INTR_LOW (1 << 17) #define PMC_PWRGATE_TOGGLE 0x30 @@ -44,6 +46,22 @@ static DEFINE_SPINLOCK(tegra_powergate_lock); static void __iomem *tegra_pmc_base; static bool tegra_pmc_invert_interrupt; +struct pmc_pm_data { + u32 cpu_good_time; /* CPU power good time in uS */ + u32 cpu_off_time; /* CPU power off time in uS */ + u32 core_osc_time; /* Core power good osc time in uS */ + u32 core_pmu_time; /* Core power good pmu time in uS */ + u32 core_off_time; /* Core power off time in uS */ + bool corereq_high; /* Core power request active-high */ + bool sysclkreq_high; /* System clock request active-high */ + bool combined_req; /* Combined pwr req for CPU & Core */ + bool cpu_pwr_good_en; /* CPU power good signal is enabled */ + u32 lp0_vec_phy_addr; /* The phy addr of LP0 warm boot code */ + u32 lp0_vec_size; /* The size of LP0 warm boot code */ + enum tegra_suspend_mode suspend_mode; +}; +static struct pmc_pm_data pmc_pm_data; + static inline u32 tegra_pmc_readl(u32 reg) { return readl(tegra_pmc_base + reg); @@ -143,6 +161,10 @@ static const struct of_device_id matches[] __initconst = { static void tegra_pmc_parse_dt(void) { struct device_node *np; + u32 prop; + enum tegra_suspend_mode suspend_mode; + u32 core_good_time[2] = {0, 0}; + u32 lp0_vec[2] = {0, 0}; np = of_find_matching_node(NULL, matches); BUG_ON(!np); @@ -151,6 +173,67 @@ static void tegra_pmc_parse_dt(void) tegra_pmc_invert_interrupt = of_property_read_bool(np, "nvidia,invert-interrupt"); + + /* Grabbing the power management configurations */ + if (of_property_read_u32(np, "nvidia,suspend-mode", &prop)) { + suspend_mode = TEGRA_SUSPEND_NONE; + } else { + switch (prop) { + case 0: + suspend_mode = TEGRA_SUSPEND_LP0; + break; + case 1: + suspend_mode = TEGRA_SUSPEND_LP1; + break; + case 2: + suspend_mode = TEGRA_SUSPEND_LP2; + break; + default: + suspend_mode = TEGRA_SUSPEND_NONE; + break; + } + } + + if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &prop)) + suspend_mode = TEGRA_SUSPEND_NONE; + pmc_pm_data.cpu_good_time = prop; + + if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &prop)) + suspend_mode = TEGRA_SUSPEND_NONE; + pmc_pm_data.cpu_off_time = prop; + + if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time", + core_good_time, ARRAY_SIZE(core_good_time))) + suspend_mode = TEGRA_SUSPEND_NONE; + pmc_pm_data.core_osc_time = core_good_time[0]; + pmc_pm_data.core_pmu_time = core_good_time[1]; + + if (of_property_read_u32(np, "nvidia,core-pwr-off-time", + &prop)) + suspend_mode = TEGRA_SUSPEND_NONE; + pmc_pm_data.core_off_time = prop; + + pmc_pm_data.corereq_high = of_property_read_bool(np, + "nvidia,core-power-req-active-high"); + + pmc_pm_data.sysclkreq_high = of_property_read_bool(np, + "nvidia,sys-clock-req-active-high"); + + pmc_pm_data.combined_req = of_property_read_bool(np, + "nvidia,combined-power-req"); + + pmc_pm_data.cpu_pwr_good_en = of_property_read_bool(np, + "nvidia,cpu-pwr-good-en"); + + if (of_property_read_u32_array(np, "nvidia,lp0-vec", lp0_vec, + ARRAY_SIZE(lp0_vec))) + if (suspend_mode == TEGRA_SUSPEND_LP0) + suspend_mode = TEGRA_SUSPEND_LP1; + + pmc_pm_data.lp0_vec_phy_addr = lp0_vec[0]; + pmc_pm_data.lp0_vec_size = lp0_vec[1]; + + pmc_pm_data.suspend_mode = suspend_mode; } void __init tegra_pmc_init(void) diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h index 7d44710..1c4b4de 100644 --- a/arch/arm/mach-tegra/pmc.h +++ b/arch/arm/mach-tegra/pmc.h @@ -18,6 +18,14 @@ #ifndef __MACH_TEGRA_PMC_H #define __MACH_TEGRA_PMC_H +enum tegra_suspend_mode { + TEGRA_SUSPEND_NONE = 0, + TEGRA_SUSPEND_LP2, /* CPU voltage off */ + TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */ + TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */ + TEGRA_MAX_SUSPEND_MODE, +}; + bool tegra_pmc_cpu_is_powered(int cpuid); int tegra_pmc_cpu_power_on(int cpuid); int tegra_pmc_cpu_remove_clamping(int cpuid);