diff options
author | Joseph Lo <josephl@nvidia.com> | 2012-10-31 05:41:20 -0400 |
---|---|---|
committer | Stephen Warren <swarren@nvidia.com> | 2012-11-15 17:09:21 -0500 |
commit | 01459c69dd48badeb7833c3293e43f7b8ae75e31 (patch) | |
tree | 4ebe32a49b2b81560c8fb5fc94c9937360f16618 /arch/arm/mach-tegra/flowctrl.c | |
parent | a6e293eef2eafc31dbe008301182e7124bd87755 (diff) |
ARM: tegra30: flowctrl: add cpu_suspend_exter/exit function
The flow controller can help CPU to go into suspend mode (powered-down
state). When CPU go into powered-down state, it needs some careful
settings before getting into and after leaving. The enter and exit
functions do that by configuring appropriate mode for flow controller.
Signed-off-by: Joseph Lo <josephl@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/flowctrl.c')
-rw-r--r-- | arch/arm/mach-tegra/flowctrl.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c index ffaa286a71e1..a2250ddae797 100644 --- a/arch/arm/mach-tegra/flowctrl.c +++ b/arch/arm/mach-tegra/flowctrl.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/cpumask.h> | ||
24 | 25 | ||
25 | #include "flowctrl.h" | 26 | #include "flowctrl.h" |
26 | #include "iomap.h" | 27 | #include "iomap.h" |
@@ -50,6 +51,14 @@ static void flowctrl_update(u8 offset, u32 value) | |||
50 | readl_relaxed(addr); | 51 | readl_relaxed(addr); |
51 | } | 52 | } |
52 | 53 | ||
54 | u32 flowctrl_read_cpu_csr(unsigned int cpuid) | ||
55 | { | ||
56 | u8 offset = flowctrl_offset_cpu_csr[cpuid]; | ||
57 | void __iomem *addr = IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + offset; | ||
58 | |||
59 | return readl(addr); | ||
60 | } | ||
61 | |||
53 | void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value) | 62 | void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value) |
54 | { | 63 | { |
55 | return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value); | 64 | return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value); |
@@ -59,3 +68,41 @@ void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value) | |||
59 | { | 68 | { |
60 | return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value); | 69 | return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value); |
61 | } | 70 | } |
71 | |||
72 | void flowctrl_cpu_suspend_enter(unsigned int cpuid) | ||
73 | { | ||
74 | unsigned int reg; | ||
75 | int i; | ||
76 | |||
77 | reg = flowctrl_read_cpu_csr(cpuid); | ||
78 | reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP; /* clear wfe bitmap */ | ||
79 | reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP; /* clear wfi bitmap */ | ||
80 | reg |= FLOW_CTRL_CSR_INTR_FLAG; /* clear intr flag */ | ||
81 | reg |= FLOW_CTRL_CSR_EVENT_FLAG; /* clear event flag */ | ||
82 | reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid; /* pwr gating on wfi */ | ||
83 | reg |= FLOW_CTRL_CSR_ENABLE; /* pwr gating */ | ||
84 | flowctrl_write_cpu_csr(cpuid, reg); | ||
85 | |||
86 | for (i = 0; i < num_possible_cpus(); i++) { | ||
87 | if (i == cpuid) | ||
88 | continue; | ||
89 | reg = flowctrl_read_cpu_csr(i); | ||
90 | reg |= FLOW_CTRL_CSR_EVENT_FLAG; | ||
91 | reg |= FLOW_CTRL_CSR_INTR_FLAG; | ||
92 | flowctrl_write_cpu_csr(i, reg); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | void flowctrl_cpu_suspend_exit(unsigned int cpuid) | ||
97 | { | ||
98 | unsigned int reg; | ||
99 | |||
100 | /* Disable powergating via flow controller for CPU0 */ | ||
101 | reg = flowctrl_read_cpu_csr(cpuid); | ||
102 | reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP; /* clear wfe bitmap */ | ||
103 | reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP; /* clear wfi bitmap */ | ||
104 | reg &= ~FLOW_CTRL_CSR_ENABLE; /* clear enable */ | ||
105 | reg |= FLOW_CTRL_CSR_INTR_FLAG; /* clear intr */ | ||
106 | reg |= FLOW_CTRL_CSR_EVENT_FLAG; /* clear event */ | ||
107 | flowctrl_write_cpu_csr(cpuid, reg); | ||
108 | } | ||