diff options
Diffstat (limited to 'arch/arm/mach-tegra/pmc.c')
-rw-r--r-- | arch/arm/mach-tegra/pmc.c | 83 |
1 files changed, 83 insertions, 0 deletions
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; | |||
49 | static bool tegra_pmc_invert_interrupt; | 51 | static bool tegra_pmc_invert_interrupt; |
50 | static struct clk *tegra_pclk; | 52 | static struct clk *tegra_pclk; |
51 | 53 | ||
54 | struct 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 | }; | ||
68 | static struct pmc_pm_data pmc_pm_data; | ||
69 | |||
52 | static inline u32 tegra_pmc_readl(u32 reg) | 70 | static 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 = { | |||
176 | static void tegra_pmc_parse_dt(void) | 194 | static 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 | ||
191 | void __init tegra_pmc_init(void) | 274 | void __init tegra_pmc_init(void) |