arm: tegra: save and restore actmon context
Prashant Gaikwad [Mon, 21 Oct 2013 04:59:13 +0000 (09:59 +0530)]
Save actmon context before entering LP0 from cpuidle
and restore after exit.

Bug 1254633

Change-Id: I4e96cd1465aa57a032d4f782f00deb0af620f660
Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
Reviewed-on: http://git-master/r/299472
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>

arch/arm/mach-tegra/include/mach/pm_domains.h
arch/arm/mach-tegra/tegra3_actmon.c

index 3a42bf8..e923b85 100644 (file)
@@ -34,6 +34,8 @@ int tegra_dma_restore(void);
 int tegra_dma_save(void);
 int tegra_i2c_restore(struct device *dev);
 int tegra_pd_i2c_restore(void);
+int tegra_actmon_save(void);
+int tegra_actmon_restore(void);
 
 #ifdef CONFIG_TEGRA_MC_DOMAINS
 void tegra_pd_add_device(struct device *dev);
index da66e53..b7afa32 100644 (file)
@@ -416,12 +416,9 @@ static void actmon_dev_disable(struct actmon_dev *dev)
        spin_unlock_irqrestore(&dev->lock, flags);
 }
 
-static void actmon_dev_suspend(struct actmon_dev *dev)
+static void actmon_dev_save(struct actmon_dev *dev)
 {
        u32 val;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev->lock, flags);
 
        if ((dev->state == ACTMON_ON) || (dev->state == ACTMON_OFF)){
                dev->saved_state = dev->state;
@@ -433,20 +430,27 @@ static void actmon_dev_suspend(struct actmon_dev *dev)
                actmon_writel(0xffffffff, offs(ACTMON_DEV_INTR_STATUS));
                actmon_wmb();
        }
+}
+
+static void actmon_dev_suspend(struct actmon_dev *dev)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       actmon_dev_save(dev);
+
        spin_unlock_irqrestore(&dev->lock, flags);
 
        if (dev->suspend_freq)
                clk_set_rate(dev->clk, dev->suspend_freq * 1000);
 }
 
-static void actmon_dev_resume(struct actmon_dev *dev)
+static void actmon_dev_restore(struct actmon_dev *dev)
 {
        u32 val;
-       unsigned long flags;
        unsigned long freq = clk_get_rate(dev->clk) / 1000;
 
-       spin_lock_irqsave(&dev->lock, flags);
-
        if (dev->state == ACTMON_SUSPENDED) {
                actmon_dev_configure(dev, freq);
                dev->state = dev->saved_state;
@@ -457,6 +461,16 @@ static void actmon_dev_resume(struct actmon_dev *dev)
                        actmon_wmb();
                }
        }
+}
+
+static void actmon_dev_resume(struct actmon_dev *dev)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       actmon_dev_restore(dev);
+
        spin_unlock_irqrestore(&dev->lock, flags);
 }
 
@@ -630,6 +644,28 @@ static struct actmon_dev *actmon_devices[] = {
        &actmon_dev_cpu_emc,
 };
 
+int tegra_actmon_save(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(actmon_devices); i++)
+               actmon_dev_save(actmon_devices[i]);
+
+       return 0;
+}
+
+int tegra_actmon_restore(void)
+{
+       int i;
+
+       actmon_writel(actmon_sampling_period - 1,
+                     ACTMON_GLB_PERIOD_CTRL);
+       for (i = 0; i < ARRAY_SIZE(actmon_devices); i++)
+               actmon_dev_restore(actmon_devices[i]);
+
+       return 0;
+}
+
 /* Activity monitor suspend/resume */
 static int actmon_pm_notify(struct notifier_block *nb,
                            unsigned long event, void *data)