]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/arm/mach-omap2/pm.c
Merge current mainline tree into linux-omap tree
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / pm.c
index 8671e1079ab54c7764adfe729294e793e9504d17..4652136de15f7150b61496d0bd190bb0e785cd1b 100644 (file)
@@ -1,13 +1,18 @@
 /*
  * linux/arch/arm/mach-omap2/pm.c
  *
- * OMAP2 Power Management Routines
- *
- * Copyright (C) 2006 Nokia Corporation
- * Tony Lindgren <tony@atomide.com>
+ * OMAP Power Management Common Routines
  *
  * Copyright (C) 2005 Texas Instruments, Inc.
+ * Copyright (C) 2006-2008 Nokia Corporation
+ *
+ * Written by:
  * Richard Woodruff <r-woodruff2@ti.com>
+ * Tony Lindgren
+ * Juha Yrjola
+ * Amit Kucheria <amit.kucheria@nokia.com>
+ * Igor Stoppa <igor.stoppa@nokia.com>
+ * Jouni Hogander
  *
  * Based on pm.c for omap1
  *
  */
 
 #include <linux/suspend.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/interrupt.h>
-#include <linux/sysfs.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/atomic.h>
+#include <linux/time.h>
+
+#include <mach/cpu.h>
 #include <asm/mach/time.h>
-#include <asm/mach/irq.h>
+#include <asm/atomic.h>
 
-#include <mach/irqs.h>
-#include <mach/clock.h>
-#include <mach/sram.h>
 #include <mach/pm.h>
+#include "pm.h"
 
-static struct clk *vclk;
-static void (*omap2_sram_idle)(void);
-static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
-static void (*saved_idle)(void);
+unsigned short enable_dyn_sleep;
+unsigned short clocks_off_while_idle;
+atomic_t sleep_block = ATOMIC_INIT(0);
 
-extern void __init pmdomain_init(void);
-extern void pmdomain_set_autoidle(void);
+static ssize_t idle_show(struct kobject *, struct kobj_attribute *, char *);
+static ssize_t idle_store(struct kobject *k, struct kobj_attribute *,
+                         const char *buf, size_t n);
 
-static unsigned int omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_SIZE];
+static struct kobj_attribute sleep_while_idle_attr =
+       __ATTR(sleep_while_idle, 0644, idle_show, idle_store);
 
-void omap2_pm_idle(void)
-{
-       local_irq_disable();
-       local_fiq_disable();
-       if (need_resched()) {
-               local_fiq_enable();
-               local_irq_enable();
-               return;
-       }
-
-       omap2_sram_idle();
-       local_fiq_enable();
-       local_irq_enable();
-}
+static struct kobj_attribute clocks_off_while_idle_attr =
+       __ATTR(clocks_off_while_idle, 0644, idle_show, idle_store);
 
-static int omap2_pm_prepare(void)
+static ssize_t idle_show(struct kobject *kobj, struct kobj_attribute *attr,
+                        char *buf)
 {
-       /* We cannot sleep in idle until we have resumed */
-       saved_idle = pm_idle;
-       pm_idle = NULL;
-       return 0;
+       if (attr == &sleep_while_idle_attr)
+               return sprintf(buf, "%hu\n", enable_dyn_sleep);
+       else if (attr == &clocks_off_while_idle_attr)
+               return sprintf(buf, "%hu\n", clocks_off_while_idle);
+       else
+               return -EINVAL;
 }
 
-static int omap2_pm_suspend(void)
+static ssize_t idle_store(struct kobject *kobj, struct kobj_attribute *attr,
+                         const char *buf, size_t n)
 {
-       return 0;
-}
+       unsigned short value;
 
-static int omap2_pm_enter(suspend_state_t state)
-{
-       int ret = 0;
-
-       switch (state)
-       {
-       case PM_SUSPEND_STANDBY:
-       case PM_SUSPEND_MEM:
-               ret = omap2_pm_suspend();
-               break;
-       default:
-               ret = -EINVAL;
+       if (sscanf(buf, "%hu", &value) != 1 ||
+           (value != 0 && value != 1)) {
+               printk(KERN_ERR "idle_store: Invalid value\n");
+               return -EINVAL;
        }
 
-       return ret;
+       if (attr == &sleep_while_idle_attr)
+               enable_dyn_sleep = value;
+       else if (attr == &clocks_off_while_idle_attr)
+               clocks_off_while_idle = value;
+       else
+               return -EINVAL;
+
+       return n;
 }
 
-static void omap2_pm_finish(void)
+void omap2_block_sleep(void)
 {
-       pm_idle = saved_idle;
+       atomic_inc(&sleep_block);
 }
 
-static struct platform_suspend_ops omap_pm_ops = {
-       .prepare        = omap2_pm_prepare,
-       .enter          = omap2_pm_enter,
-       .finish         = omap2_pm_finish,
-       .valid          = suspend_valid_only_mem,
-};
+void omap2_allow_sleep(void)
+{
+       int i;
+
+       i = atomic_dec_return(&sleep_block);
+       BUG_ON(i < 0);
+}
 
-int __init omap2_pm_init(void)
+static int __init omap_pm_init(void)
 {
-       return 0;
+       int error = -1;
+
+       if (cpu_is_omap24xx())
+               error = omap2_pm_init();
+       if (cpu_is_omap34xx())
+               error = omap3_pm_init();
+       if (error) {
+               printk(KERN_ERR "omap2|3_pm_init failed: %d\n", error);
+               return error;
+       }
+
+       /* disabled till drivers are fixed */
+       enable_dyn_sleep = 0;
+       error = sysfs_create_file(power_kobj, &sleep_while_idle_attr.attr);
+       if (error)
+               printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
+       error = sysfs_create_file(power_kobj,
+                                 &clocks_off_while_idle_attr.attr);
+       if (error)
+               printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
+
+       return error;
 }
 
-__initcall(omap2_pm_init);
+late_initcall(omap_pm_init);