ARM: tegra30: flowctrl: add cpu_suspend_exter/exit function
authorJoseph Lo <josephl@nvidia.com>
Wed, 31 Oct 2012 09:41:20 +0000 (17:41 +0800)
committerStephen Warren <swarren@nvidia.com>
Thu, 15 Nov 2012 22:09:21 +0000 (15:09 -0700)
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>
arch/arm/mach-tegra/flowctrl.c
arch/arm/mach-tegra/flowctrl.h

index ffaa286a71e17328c974cf077a89a5b8e9955ccd..a2250ddae797bdfecc705cf6f389c924aaed4981 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
+#include <linux/cpumask.h>
 
 #include "flowctrl.h"
 #include "iomap.h"
@@ -50,6 +51,14 @@ static void flowctrl_update(u8 offset, u32 value)
        readl_relaxed(addr);
 }
 
+u32 flowctrl_read_cpu_csr(unsigned int cpuid)
+{
+       u8 offset = flowctrl_offset_cpu_csr[cpuid];
+       void __iomem *addr = IO_ADDRESS(TEGRA_FLOW_CTRL_BASE) + offset;
+
+       return readl(addr);
+}
+
 void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value)
 {
        return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value);
@@ -59,3 +68,41 @@ void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value)
 {
        return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value);
 }
+
+void flowctrl_cpu_suspend_enter(unsigned int cpuid)
+{
+       unsigned int reg;
+       int i;
+
+       reg = flowctrl_read_cpu_csr(cpuid);
+       reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;       /* clear wfe bitmap */
+       reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;       /* clear wfi bitmap */
+       reg |= FLOW_CTRL_CSR_INTR_FLAG;                 /* clear intr flag */
+       reg |= FLOW_CTRL_CSR_EVENT_FLAG;                /* clear event flag */
+       reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid; /* pwr gating on wfi */
+       reg |= FLOW_CTRL_CSR_ENABLE;                    /* pwr gating */
+       flowctrl_write_cpu_csr(cpuid, reg);
+
+       for (i = 0; i < num_possible_cpus(); i++) {
+               if (i == cpuid)
+                       continue;
+               reg = flowctrl_read_cpu_csr(i);
+               reg |= FLOW_CTRL_CSR_EVENT_FLAG;
+               reg |= FLOW_CTRL_CSR_INTR_FLAG;
+               flowctrl_write_cpu_csr(i, reg);
+       }
+}
+
+void flowctrl_cpu_suspend_exit(unsigned int cpuid)
+{
+       unsigned int reg;
+
+       /* Disable powergating via flow controller for CPU0 */
+       reg = flowctrl_read_cpu_csr(cpuid);
+       reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;       /* clear wfe bitmap */
+       reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;       /* clear wfi bitmap */
+       reg &= ~FLOW_CTRL_CSR_ENABLE;                   /* clear enable */
+       reg |= FLOW_CTRL_CSR_INTR_FLAG;                 /* clear intr */
+       reg |= FLOW_CTRL_CSR_EVENT_FLAG;                /* clear event */
+       flowctrl_write_cpu_csr(cpuid, reg);
+}
index 19428173855efdbca2cfa127e383d3c2c60da89b..0798dec1832d5d8aa7e066e5afcb40e0876dbc39 100644 (file)
 #define FLOW_CTRL_HALT_CPU1_EVENTS     0x14
 #define FLOW_CTRL_CPU1_CSR             0x18
 
+#define TEGRA30_FLOW_CTRL_CSR_WFI_CPU0         (1 << 8)
+#define TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP       (0xF << 4)
+#define TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP       (0xF << 8)
+
 #ifndef __ASSEMBLY__
+u32 flowctrl_read_cpu_csr(unsigned int cpuid);
 void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value);
 void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value);
+
+void flowctrl_cpu_suspend_enter(unsigned int cpuid);
+void flowctrl_cpu_suspend_exit(unsigned int cpuid);
 #endif
 
 #endif
This page took 0.027209 seconds and 5 git commands to generate.