From patchwork Mon Mar 4 11:40:07 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Lo X-Patchwork-Id: 2212201 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 A2A594006E for ; Mon, 4 Mar 2013 11:49: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 1UCTkl-0008Pm-Gi; Mon, 04 Mar 2013 11:40:23 +0000 Received: from hqemgate04.nvidia.com ([216.228.121.35]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UCTkb-0008Oa-Sx for linux-arm-kernel@lists.infradead.org; Mon, 04 Mar 2013 11:40:15 +0000 Received: from hqnvupgp08.nvidia.com (Not Verified[216.228.121.13]) by hqemgate04.nvidia.com id ; Mon, 04 Mar 2013 03:40:07 -0800 Received: from hqemhub01.nvidia.com ([172.17.108.22]) by hqnvupgp08.nvidia.com (PGP Universal service); Mon, 04 Mar 2013 03:34:22 -0800 X-PGP-Universal: processed; by hqnvupgp08.nvidia.com on Mon, 04 Mar 2013 03:34:22 -0800 Received: from jlo-ubuntu-64.nvidia.com (172.20.144.16) by hqemhub01.nvidia.com (172.20.150.30) with Microsoft SMTP Server (TLS) id 8.3.297.1; Mon, 4 Mar 2013 03:40:12 -0800 From: Joseph Lo To: Stephen Warren Subject: [PATCH 03/10] ARM: tegra: get power management configurations for PMC from DT Date: Mon, 4 Mar 2013 19:40:07 +0800 Message-ID: <1362397207-5597-1-git-send-email-josephl@nvidia.com> X-Mailer: git-send-email 1.8.1.1 X-NVConfidentiality: public MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130304_064014_070836_063A86E8 X-CRM114-Status: GOOD ( 13.93 ) X-Spam-Score: -7.5 (-------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-7.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.35 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record -0.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: linux-tegra@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Joseph Lo 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 If the system supports deep sleep mode (i.e. suspend), it should have the power management configuration for PMC in the DT under the sub-node of PMC. Different system may have different configurations, it should be parsed from DT. Signed-off-by: Joseph Lo --- arch/arm/mach-tegra/pmc.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-tegra/pmc.h | 8 +++++ 2 files changed, 91 insertions(+) diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c index b30e921..f30c660 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 { + unsigned long cpu_good_time; /* CPU power good time in uS */ + unsigned long cpu_off_time; /* CPU power off time in uS */ + unsigned long core_osc_time; /* Core power good osc time in uS */ + unsigned long core_pmu_time; /* Core power good pmu time in uS */ + unsigned long 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);