aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorJoseph Lo <josephl@nvidia.com>2013-04-03 07:31:28 -0400
committerStephen Warren <swarren@nvidia.com>2013-04-03 16:30:22 -0400
commit0337c3e0c3cbbb3a4f411c292f52fcc314abae67 (patch)
tree73107fcd904db7cab212ce15ed482cc87fe5b36c /arch/arm
parent7021d1220584ab1e6efd3d59da47b65674d9896a (diff)
ARM: tegra: moving the CPU power timer function to PMC driver
The CPU power timer set up function was related to PMC register. Now moving it to PMC driver. And it also help to clean up the PM related code later. The timer was calculated based on the input clock of PMC. In this patch, we also get the clock from DT. Signed-off-by: Joseph Lo <josephl@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-tegra/common.c2
-rw-r--r--arch/arm/mach-tegra/pm.c37
-rw-r--r--arch/arm/mach-tegra/pmc.c35
-rw-r--r--arch/arm/mach-tegra/pmc.h4
4 files changed, 41 insertions, 37 deletions
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index f0315c95c76d..b02ebe767e7f 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -61,6 +61,7 @@ u32 tegra_uart_config[4] = {
61void __init tegra_dt_init_irq(void) 61void __init tegra_dt_init_irq(void)
62{ 62{
63 tegra_clocks_init(); 63 tegra_clocks_init();
64 tegra_pmc_init();
64 tegra_init_irq(); 65 tegra_init_irq();
65 irqchip_init(); 66 irqchip_init();
66} 67}
@@ -100,7 +101,6 @@ void __init tegra_init_early(void)
100 tegra_apb_io_init(); 101 tegra_apb_io_init();
101 tegra_init_fuse(); 102 tegra_init_fuse();
102 tegra_init_cache(); 103 tegra_init_cache();
103 tegra_pmc_init();
104 tegra_powergate_init(); 104 tegra_powergate_init();
105 tegra_hotplug_init(); 105 tegra_hotplug_init();
106} 106}
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 0494f739c95f..5f5611f40b43 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -22,7 +22,6 @@
22#include <linux/cpumask.h> 22#include <linux/cpumask.h>
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/cpu_pm.h> 24#include <linux/cpu_pm.h>
25#include <linux/clk.h>
26#include <linux/err.h> 25#include <linux/err.h>
27#include <linux/clk/tegra.h> 26#include <linux/clk/tegra.h>
28 27
@@ -37,52 +36,18 @@
37#include "reset.h" 36#include "reset.h"
38#include "flowctrl.h" 37#include "flowctrl.h"
39#include "fuse.h" 38#include "fuse.h"
39#include "pmc.h"
40#include "sleep.h" 40#include "sleep.h"
41 41
42#define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */ 42#define TEGRA_POWER_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */
43 43
44#define PMC_CTRL 0x0 44#define PMC_CTRL 0x0
45#define PMC_CPUPWRGOOD_TIMER 0xc8
46#define PMC_CPUPWROFF_TIMER 0xcc
47 45
48#ifdef CONFIG_PM_SLEEP 46#ifdef CONFIG_PM_SLEEP
49static DEFINE_SPINLOCK(tegra_lp2_lock); 47static DEFINE_SPINLOCK(tegra_lp2_lock);
50static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); 48static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
51static struct clk *tegra_pclk;
52void (*tegra_tear_down_cpu)(void); 49void (*tegra_tear_down_cpu)(void);
53 50
54static void set_power_timers(unsigned long us_on, unsigned long us_off)
55{
56 unsigned long long ticks;
57 unsigned long long pclk;
58 unsigned long rate;
59 static unsigned long tegra_last_pclk;
60
61 if (tegra_pclk == NULL) {
62 tegra_pclk = clk_get_sys(NULL, "pclk");
63 WARN_ON(IS_ERR(tegra_pclk));
64 }
65
66 rate = clk_get_rate(tegra_pclk);
67
68 if (WARN_ON_ONCE(rate <= 0))
69 pclk = 100000000;
70 else
71 pclk = rate;
72
73 if ((rate != tegra_last_pclk)) {
74 ticks = (us_on * pclk) + 999999ull;
75 do_div(ticks, 1000000);
76 writel((unsigned long)ticks, pmc + PMC_CPUPWRGOOD_TIMER);
77
78 ticks = (us_off * pclk) + 999999ull;
79 do_div(ticks, 1000000);
80 writel((unsigned long)ticks, pmc + PMC_CPUPWROFF_TIMER);
81 wmb();
82 }
83 tegra_last_pclk = pclk;
84}
85
86/* 51/*
87 * restore_cpu_complex 52 * restore_cpu_complex
88 * 53 *
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
index b30e921cc3a9..faa33e8f937d 100644
--- a/arch/arm/mach-tegra/pmc.c
+++ b/arch/arm/mach-tegra/pmc.c
@@ -16,6 +16,7 @@
16 */ 16 */
17 17
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/clk.h>
19#include <linux/io.h> 20#include <linux/io.h>
20#include <linux/of.h> 21#include <linux/of.h>
21#include <linux/of_address.h> 22#include <linux/of_address.h>
@@ -27,6 +28,9 @@
27#define PMC_REMOVE_CLAMPING 0x34 28#define PMC_REMOVE_CLAMPING 0x34
28#define PMC_PWRGATE_STATUS 0x38 29#define PMC_PWRGATE_STATUS 0x38
29 30
31#define PMC_CPUPWRGOOD_TIMER 0xc8
32#define PMC_CPUPWROFF_TIMER 0xcc
33
30#define TEGRA_POWERGATE_PCIE 3 34#define TEGRA_POWERGATE_PCIE 3
31#define TEGRA_POWERGATE_VDEC 4 35#define TEGRA_POWERGATE_VDEC 4
32#define TEGRA_POWERGATE_CPU1 9 36#define TEGRA_POWERGATE_CPU1 9
@@ -43,6 +47,7 @@ static DEFINE_SPINLOCK(tegra_powergate_lock);
43 47
44static void __iomem *tegra_pmc_base; 48static void __iomem *tegra_pmc_base;
45static bool tegra_pmc_invert_interrupt; 49static bool tegra_pmc_invert_interrupt;
50static struct clk *tegra_pclk;
46 51
47static inline u32 tegra_pmc_readl(u32 reg) 52static inline u32 tegra_pmc_readl(u32 reg)
48{ 53{
@@ -133,6 +138,34 @@ int tegra_pmc_cpu_remove_clamping(int cpuid)
133 return tegra_pmc_powergate_remove_clamping(id); 138 return tegra_pmc_powergate_remove_clamping(id);
134} 139}
135 140
141#ifdef CONFIG_PM_SLEEP
142void set_power_timers(unsigned long us_on, unsigned long us_off)
143{
144 unsigned long long ticks;
145 unsigned long long pclk;
146 unsigned long rate;
147 static unsigned long tegra_last_pclk;
148
149 rate = clk_get_rate(tegra_pclk);
150 if (WARN_ON_ONCE(rate <= 0))
151 pclk = 100000000;
152 else
153 pclk = rate;
154
155 if ((rate != tegra_last_pclk)) {
156 ticks = (us_on * pclk) + 999999ull;
157 do_div(ticks, 1000000);
158 tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWRGOOD_TIMER);
159
160 ticks = (us_off * pclk) + 999999ull;
161 do_div(ticks, 1000000);
162 tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWROFF_TIMER);
163 wmb();
164 }
165 tegra_last_pclk = pclk;
166}
167#endif
168
136static const struct of_device_id matches[] __initconst = { 169static const struct of_device_id matches[] __initconst = {
137 { .compatible = "nvidia,tegra114-pmc" }, 170 { .compatible = "nvidia,tegra114-pmc" },
138 { .compatible = "nvidia,tegra30-pmc" }, 171 { .compatible = "nvidia,tegra30-pmc" },
@@ -151,6 +184,8 @@ static void tegra_pmc_parse_dt(void)
151 184
152 tegra_pmc_invert_interrupt = of_property_read_bool(np, 185 tegra_pmc_invert_interrupt = of_property_read_bool(np,
153 "nvidia,invert-interrupt"); 186 "nvidia,invert-interrupt");
187 tegra_pclk = of_clk_get_by_name(np, "pclk");
188 WARN_ON(IS_ERR(tegra_pclk));
154} 189}
155 190
156void __init tegra_pmc_init(void) 191void __init tegra_pmc_init(void)
diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h
index 7d44710368be..22f16c9dd44d 100644
--- a/arch/arm/mach-tegra/pmc.h
+++ b/arch/arm/mach-tegra/pmc.h
@@ -18,6 +18,10 @@
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
21#ifdef CONFIG_PM_SLEEP
22void set_power_timers(unsigned long us_on, unsigned long us_off);
23#endif
24
21bool tegra_pmc_cpu_is_powered(int cpuid); 25bool tegra_pmc_cpu_is_powered(int cpuid);
22int tegra_pmc_cpu_power_on(int cpuid); 26int tegra_pmc_cpu_power_on(int cpuid);
23int tegra_pmc_cpu_remove_clamping(int cpuid); 27int tegra_pmc_cpu_remove_clamping(int cpuid);