aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoseph Lo <josephl@nvidia.com>2013-04-03 07:31:46 -0400
committerStephen Warren <swarren@nvidia.com>2013-04-03 16:31:36 -0400
commit4b51ccbc469facb7b589a71c2a4ae47d3e425d02 (patch)
tree6d0693496b378a478b1268359b9dbad565160db4
parente307cc8941fc420f008e1f3cb86e16a4269aa2af (diff)
ARM: dt: tegra: add bindings of power management configurations for PMC
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 <grant.likely@secretlab.ca> Cc: Rob Herring <rob.herring@calxeda.com> Cc: devicetree-discuss@lists.ozlabs.org Signed-off-by: Joseph Lo <josephl@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
-rw-r--r--Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt38
-rw-r--r--arch/arm/mach-tegra/pmc.c83
-rw-r--r--arch/arm/mach-tegra/pmc.h8
3 files changed, 129 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
index ee529b17cb9f..1608a54e90e1 100644
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
@@ -1,5 +1,9 @@
1NVIDIA Tegra Power Management Controller (PMC) 1NVIDIA Tegra Power Management Controller (PMC)
2 2
3The PMC block interacts with an external Power Management Unit. The PMC
4mostly controls the entry and exit of the system from different sleep
5modes. It provides power-gating controllers for SoC and CPU power-islands.
6
3Required properties: 7Required properties:
4- name : Should be pmc 8- name : Should be pmc
5- compatible : Should contain "nvidia,tegra<chip>-pmc". 9- compatible : Should contain "nvidia,tegra<chip>-pmc".
@@ -15,6 +19,32 @@ Optional properties:
15 signal is fed into the PMC. This signal is optionally inverted, and then 19 signal is fed into the PMC. This signal is optionally inverted, and then
16 fed into the ARM GIC. The PMC is not involved in the detection or 20 fed into the ARM GIC. The PMC is not involved in the detection or
17 handling of this interrupt signal, merely its inversion. 21 handling of this interrupt signal, merely its inversion.
22- nvidia,suspend-mode : The suspend mode that the platform should use.
23 Valid values are 0, 1 and 2:
24 0 (LP0): CPU + Core voltage off and DRAM in self-refresh
25 1 (LP1): CPU voltage off and DRAM in self-refresh
26 2 (LP2): CPU voltage off
27- nvidia,core-power-req-active-high : Boolean, core power request active-high
28- nvidia,sys-clock-req-active-high : Boolean, system clock request active-high
29- nvidia,combined-power-req : Boolean, combined power request for CPU & Core
30- nvidia,cpu-pwr-good-en : Boolean, CPU power good signal (from PMIC to PMC)
31 is enabled.
32
33Required properties when nvidia,suspend-mode is specified:
34- nvidia,cpu-pwr-good-time : CPU power good time in uS.
35- nvidia,cpu-pwr-off-time : CPU power off time in uS.
36- nvidia,core-pwr-good-time : <Oscillator-stable-time Power-stable-time>
37 Core power good time in uS.
38- nvidia,core-pwr-off-time : Core power off time in uS.
39
40Required properties when nvidia,suspend-mode=<0>:
41- nvidia,lp0-vec : <start length> Starting address and length of LP0 vector
42 The LP0 vector contains the warm boot code that is executed by AVP when
43 resuming from the LP0 state. The AVP (Audio-Video Processor) is an ARM7
44 processor and always being the first boot processor when chip is power on
45 or resume from deep sleep mode. When the system is resumed from the deep
46 sleep mode, the warm boot code will restore some PLLs, clocks and then
47 bring up CPU0 for resuming the system.
18 48
19Example: 49Example:
20 50
@@ -25,6 +55,14 @@ pmc@7000f400 {
25 clocks = <&tegra_car 110>, <&clk32k_in>; 55 clocks = <&tegra_car 110>, <&clk32k_in>;
26 clock-names = "pclk", "clk32k_in"; 56 clock-names = "pclk", "clk32k_in";
27 nvidia,invert-interrupt; 57 nvidia,invert-interrupt;
58 nvidia,suspend-mode = <1>;
59 nvidia,cpu-pwr-good-time = <2000>;
60 nvidia,cpu-pwr-off-time = <100>;
61 nvidia,core-pwr-good-time = <3845 3845>;
62 nvidia,core-pwr-off-time = <458>;
63 nvidia,core-power-req-active-high;
64 nvidia,sys-clock-req-active-high;
65 nvidia,lp0-vec = <0xbdffd000 0x2000>;
28}; 66};
29 67
30/ Tegra board dts file 68/ Tegra board dts file
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
index faa33e8f937d..e896826d7d0f 100644
--- a/arch/arm/mach-tegra/pmc.c
+++ b/arch/arm/mach-tegra/pmc.c
@@ -21,6 +21,8 @@
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/of_address.h> 22#include <linux/of_address.h>
23 23
24#include "pmc.h"
25
24#define PMC_CTRL 0x0 26#define PMC_CTRL 0x0
25#define PMC_CTRL_INTR_LOW (1 << 17) 27#define PMC_CTRL_INTR_LOW (1 << 17)
26#define PMC_PWRGATE_TOGGLE 0x30 28#define PMC_PWRGATE_TOGGLE 0x30
@@ -49,6 +51,22 @@ static void __iomem *tegra_pmc_base;
49static bool tegra_pmc_invert_interrupt; 51static bool tegra_pmc_invert_interrupt;
50static struct clk *tegra_pclk; 52static struct clk *tegra_pclk;
51 53
54struct pmc_pm_data {
55 u32 cpu_good_time; /* CPU power good time in uS */
56 u32 cpu_off_time; /* CPU power off time in uS */
57 u32 core_osc_time; /* Core power good osc time in uS */
58 u32 core_pmu_time; /* Core power good pmu time in uS */
59 u32 core_off_time; /* Core power off time in uS */
60 bool corereq_high; /* Core power request active-high */
61 bool sysclkreq_high; /* System clock request active-high */
62 bool combined_req; /* Combined pwr req for CPU & Core */
63 bool cpu_pwr_good_en; /* CPU power good signal is enabled */
64 u32 lp0_vec_phy_addr; /* The phy addr of LP0 warm boot code */
65 u32 lp0_vec_size; /* The size of LP0 warm boot code */
66 enum tegra_suspend_mode suspend_mode;
67};
68static struct pmc_pm_data pmc_pm_data;
69
52static inline u32 tegra_pmc_readl(u32 reg) 70static inline u32 tegra_pmc_readl(u32 reg)
53{ 71{
54 return readl(tegra_pmc_base + reg); 72 return readl(tegra_pmc_base + reg);
@@ -176,6 +194,10 @@ static const struct of_device_id matches[] __initconst = {
176static void tegra_pmc_parse_dt(void) 194static void tegra_pmc_parse_dt(void)
177{ 195{
178 struct device_node *np; 196 struct device_node *np;
197 u32 prop;
198 enum tegra_suspend_mode suspend_mode;
199 u32 core_good_time[2] = {0, 0};
200 u32 lp0_vec[2] = {0, 0};
179 201
180 np = of_find_matching_node(NULL, matches); 202 np = of_find_matching_node(NULL, matches);
181 BUG_ON(!np); 203 BUG_ON(!np);
@@ -186,6 +208,67 @@ static void tegra_pmc_parse_dt(void)
186 "nvidia,invert-interrupt"); 208 "nvidia,invert-interrupt");
187 tegra_pclk = of_clk_get_by_name(np, "pclk"); 209 tegra_pclk = of_clk_get_by_name(np, "pclk");
188 WARN_ON(IS_ERR(tegra_pclk)); 210 WARN_ON(IS_ERR(tegra_pclk));
211
212 /* Grabbing the power management configurations */
213 if (of_property_read_u32(np, "nvidia,suspend-mode", &prop)) {
214 suspend_mode = TEGRA_SUSPEND_NONE;
215 } else {
216 switch (prop) {
217 case 0:
218 suspend_mode = TEGRA_SUSPEND_LP0;
219 break;
220 case 1:
221 suspend_mode = TEGRA_SUSPEND_LP1;
222 break;
223 case 2:
224 suspend_mode = TEGRA_SUSPEND_LP2;
225 break;
226 default:
227 suspend_mode = TEGRA_SUSPEND_NONE;
228 break;
229 }
230 }
231
232 if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &prop))
233 suspend_mode = TEGRA_SUSPEND_NONE;
234 pmc_pm_data.cpu_good_time = prop;
235
236 if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &prop))
237 suspend_mode = TEGRA_SUSPEND_NONE;
238 pmc_pm_data.cpu_off_time = prop;
239
240 if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
241 core_good_time, ARRAY_SIZE(core_good_time)))
242 suspend_mode = TEGRA_SUSPEND_NONE;
243 pmc_pm_data.core_osc_time = core_good_time[0];
244 pmc_pm_data.core_pmu_time = core_good_time[1];
245
246 if (of_property_read_u32(np, "nvidia,core-pwr-off-time",
247 &prop))
248 suspend_mode = TEGRA_SUSPEND_NONE;
249 pmc_pm_data.core_off_time = prop;
250
251 pmc_pm_data.corereq_high = of_property_read_bool(np,
252 "nvidia,core-power-req-active-high");
253
254 pmc_pm_data.sysclkreq_high = of_property_read_bool(np,
255 "nvidia,sys-clock-req-active-high");
256
257 pmc_pm_data.combined_req = of_property_read_bool(np,
258 "nvidia,combined-power-req");
259
260 pmc_pm_data.cpu_pwr_good_en = of_property_read_bool(np,
261 "nvidia,cpu-pwr-good-en");
262
263 if (of_property_read_u32_array(np, "nvidia,lp0-vec", lp0_vec,
264 ARRAY_SIZE(lp0_vec)))
265 if (suspend_mode == TEGRA_SUSPEND_LP0)
266 suspend_mode = TEGRA_SUSPEND_LP1;
267
268 pmc_pm_data.lp0_vec_phy_addr = lp0_vec[0];
269 pmc_pm_data.lp0_vec_size = lp0_vec[1];
270
271 pmc_pm_data.suspend_mode = suspend_mode;
189} 272}
190 273
191void __init tegra_pmc_init(void) 274void __init tegra_pmc_init(void)
diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h
index 22f16c9dd44d..6bc0fc095269 100644
--- a/arch/arm/mach-tegra/pmc.h
+++ b/arch/arm/mach-tegra/pmc.h
@@ -18,6 +18,14 @@
18#ifndef __MACH_TEGRA_PMC_H 18#ifndef __MACH_TEGRA_PMC_H
19#define __MACH_TEGRA_PMC_H 19#define __MACH_TEGRA_PMC_H
20 20
21enum tegra_suspend_mode {
22 TEGRA_SUSPEND_NONE = 0,
23 TEGRA_SUSPEND_LP2, /* CPU voltage off */
24 TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */
25 TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */
26 TEGRA_MAX_SUSPEND_MODE,
27};
28
21#ifdef CONFIG_PM_SLEEP 29#ifdef CONFIG_PM_SLEEP
22void set_power_timers(unsigned long us_on, unsigned long us_off); 30void set_power_timers(unsigned long us_on, unsigned long us_off);
23#endif 31#endif