aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/pmc.c
diff options
context:
space:
mode:
authorJoseph Lo <josephl@nvidia.com>2013-02-28 16:32:11 -0500
committerStephen Warren <swarren@nvidia.com>2013-03-11 16:29:44 -0400
commitc141753fc385df98a33790b59a22894537031a24 (patch)
tree448eff3ec8e6363ef3bdb1eb5fb223a578d80d4d /arch/arm/mach-tegra/pmc.c
parent291fde31a9e72ea81951f3f77444f61789276655 (diff)
ARM: tegra: pmc: add power on function for secondary CPUs
Adding the power on function for secondary CPUs in PMC driver, this can help us to remove legacy powergate driver and add generic power domain support later. Signed-off-by: Joseph Lo <josephl@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/pmc.c')
-rw-r--r--arch/arm/mach-tegra/pmc.c101
1 files changed, 99 insertions, 2 deletions
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
index a916ecaa96e6..b30e921cc3a9 100644
--- a/arch/arm/mach-tegra/pmc.c
+++ b/arch/arm/mach-tegra/pmc.c
@@ -20,8 +20,26 @@
20#include <linux/of.h> 20#include <linux/of.h>
21#include <linux/of_address.h> 21#include <linux/of_address.h>
22 22
23#define PMC_CTRL 0x0 23#define PMC_CTRL 0x0
24#define PMC_CTRL_INTR_LOW (1 << 17) 24#define PMC_CTRL_INTR_LOW (1 << 17)
25#define PMC_PWRGATE_TOGGLE 0x30
26#define PMC_PWRGATE_TOGGLE_START (1 << 8)
27#define PMC_REMOVE_CLAMPING 0x34
28#define PMC_PWRGATE_STATUS 0x38
29
30#define TEGRA_POWERGATE_PCIE 3
31#define TEGRA_POWERGATE_VDEC 4
32#define TEGRA_POWERGATE_CPU1 9
33#define TEGRA_POWERGATE_CPU2 10
34#define TEGRA_POWERGATE_CPU3 11
35
36static u8 tegra_cpu_domains[] = {
37 0xFF, /* not available for CPU0 */
38 TEGRA_POWERGATE_CPU1,
39 TEGRA_POWERGATE_CPU2,
40 TEGRA_POWERGATE_CPU3,
41};
42static DEFINE_SPINLOCK(tegra_powergate_lock);
25 43
26static void __iomem *tegra_pmc_base; 44static void __iomem *tegra_pmc_base;
27static bool tegra_pmc_invert_interrupt; 45static bool tegra_pmc_invert_interrupt;
@@ -36,6 +54,85 @@ static inline void tegra_pmc_writel(u32 val, u32 reg)
36 writel(val, tegra_pmc_base + reg); 54 writel(val, tegra_pmc_base + reg);
37} 55}
38 56
57static int tegra_pmc_get_cpu_powerdomain_id(int cpuid)
58{
59 if (cpuid <= 0 || cpuid >= num_possible_cpus())
60 return -EINVAL;
61 return tegra_cpu_domains[cpuid];
62}
63
64static bool tegra_pmc_powergate_is_powered(int id)
65{
66 return (tegra_pmc_readl(PMC_PWRGATE_STATUS) >> id) & 1;
67}
68
69static int tegra_pmc_powergate_set(int id, bool new_state)
70{
71 bool old_state;
72 unsigned long flags;
73
74 spin_lock_irqsave(&tegra_powergate_lock, flags);
75
76 old_state = tegra_pmc_powergate_is_powered(id);
77 WARN_ON(old_state == new_state);
78
79 tegra_pmc_writel(PMC_PWRGATE_TOGGLE_START | id, PMC_PWRGATE_TOGGLE);
80
81 spin_unlock_irqrestore(&tegra_powergate_lock, flags);
82
83 return 0;
84}
85
86static int tegra_pmc_powergate_remove_clamping(int id)
87{
88 u32 mask;
89
90 /*
91 * Tegra has a bug where PCIE and VDE clamping masks are
92 * swapped relatively to the partition ids.
93 */
94 if (id == TEGRA_POWERGATE_VDEC)
95 mask = (1 << TEGRA_POWERGATE_PCIE);
96 else if (id == TEGRA_POWERGATE_PCIE)
97 mask = (1 << TEGRA_POWERGATE_VDEC);
98 else
99 mask = (1 << id);
100
101 tegra_pmc_writel(mask, PMC_REMOVE_CLAMPING);
102
103 return 0;
104}
105
106bool tegra_pmc_cpu_is_powered(int cpuid)
107{
108 int id;
109
110 id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
111 if (id < 0)
112 return false;
113 return tegra_pmc_powergate_is_powered(id);
114}
115
116int tegra_pmc_cpu_power_on(int cpuid)
117{
118 int id;
119
120 id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
121 if (id < 0)
122 return id;
123 return tegra_pmc_powergate_set(id, true);
124}
125
126int tegra_pmc_cpu_remove_clamping(int cpuid)
127{
128 int id;
129
130 id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
131 if (id < 0)
132 return id;
133 return tegra_pmc_powergate_remove_clamping(id);
134}
135
39static const struct of_device_id matches[] __initconst = { 136static const struct of_device_id matches[] __initconst = {
40 { .compatible = "nvidia,tegra114-pmc" }, 137 { .compatible = "nvidia,tegra114-pmc" },
41 { .compatible = "nvidia,tegra30-pmc" }, 138 { .compatible = "nvidia,tegra30-pmc" },