]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch '2_6_32_for_next' of git://git.pwsan.com/linux-2.6 into for-next
authorTony Lindgren <tony@atomide.com>
Thu, 3 Sep 2009 17:17:39 +0000 (10:17 -0700)
committerTony Lindgren <tony@atomide.com>
Thu, 3 Sep 2009 17:17:39 +0000 (10:17 -0700)
15 files changed:
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/mach-omap2/board-zoom-debugboard.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-omap2/serial.c
arch/arm/mach-omap2/usb-musb.c
arch/arm/plat-omap/include/mach/clockdomain.h
arch/arm/plat-omap/include/mach/mux.h
arch/arm/plat-omap/include/mach/powerdomain.h

index 4500e7f674d737cfa033ac86525d6a57b678c8c9..bd57ec76dc5eedde9f672d34456ed843e0cb0f64 100644 (file)
@@ -475,6 +475,11 @@ static inline void board_smc91x_init(void)
 
 #endif
 
+static void enable_board_wakeup_source(void)
+{
+       omap_cfg_reg(AF26_34XX_SYS_NIRQ); /* T2 interrupt line (keypad) */
+}
+
 static void __init omap_3430sdp_init(void)
 {
        omap3430_i2c_init();
@@ -490,6 +495,7 @@ static void __init omap_3430sdp_init(void)
        omap_serial_init();
        usb_musb_init();
        board_smc91x_init();
+       enable_board_wakeup_source();
 }
 
 static void __init omap_3430sdp_map_io(void)
index f546063775b398927b6bbc2b5d17fbc731217394..1f13e2a1f322178c7878d0fb9a54fc6f519328b2 100644 (file)
@@ -96,7 +96,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
 
 static struct platform_device zoom2_debugboard_serial_device = {
        .name                   = "serial8250",
-       .id                     = PLAT8250_DEV_PLATFORM1,
+       .id                     = 3,
        .dev                    = {
                .platform_data  = serial_platform_data,
        },
@@ -129,6 +129,7 @@ static inline void __init zoom2_init_quaduart(void)
 static inline int omap_zoom2_debugboard_detect(void)
 {
        int debug_board_detect = 0;
+       int ret = 1;
 
        debug_board_detect = ZOOM2_SMSC911X_GPIO;
 
@@ -140,10 +141,10 @@ static inline int omap_zoom2_debugboard_detect(void)
        gpio_direction_input(debug_board_detect);
 
        if (!gpio_get_value(debug_board_detect)) {
-               gpio_free(debug_board_detect);
-               return 0;
+               ret = 0;
        }
-       return 1;
+       gpio_free(debug_board_detect);
+       return ret;
 }
 
 static struct platform_device *zoom2_devices[] __initdata = {
index 456e2ad5f62136bb33187980f92b1323e1868462..f2a92d614f0fc5ec95c91d5b9b2de4a9378cdda4 100644 (file)
@@ -1043,5 +1043,7 @@ void omap2_clk_disable_unused(struct clk *clk)
                omap2_clk_disable(clk);
        } else
                _omap2_clk_disable(clk);
+       if (clk->clkdm != NULL)
+               pwrdm_clkdm_state_switch(clk->clkdm);
 }
 #endif
index 0e7d501865b602c41f65c5e13693fc078fe5ef05..4ef7b4f5474e581e12983c2e827d13229ceb2683 100644 (file)
@@ -299,7 +299,8 @@ struct clockdomain *clkdm_lookup(const char *name)
  * anything else to indicate failure; or -EINVAL if the function pointer
  * is null.
  */
-int clkdm_for_each(int (*fn)(struct clockdomain *clkdm))
+int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
+                       void *user)
 {
        struct clockdomain *clkdm;
        int ret = 0;
@@ -309,7 +310,7 @@ int clkdm_for_each(int (*fn)(struct clockdomain *clkdm))
 
        mutex_lock(&clkdm_mutex);
        list_for_each_entry(clkdm, &clkdm_list, node) {
-               ret = (*fn)(clkdm);
+               ret = (*fn)(clkdm, user);
                if (ret)
                        break;
        }
@@ -484,6 +485,8 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
                            v << __ffs(clkdm->clktrctrl_mask),
                            clkdm->pwrdm.ptr->prcm_offs,
                            CM_CLKSTCTRL);
+
+       pwrdm_clkdm_state_switch(clkdm);
 }
 
 /**
@@ -572,6 +575,7 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
                omap2_clkdm_wakeup(clkdm);
 
        pwrdm_wait_transition(clkdm->pwrdm.ptr);
+       pwrdm_clkdm_state_switch(clkdm);
 
        return 0;
 }
@@ -624,6 +628,8 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
        else
                omap2_clkdm_sleep(clkdm);
 
+       pwrdm_clkdm_state_switch(clkdm);
+
        return 0;
 }
 
index f63f3a237825576b9ab3d9b31eb756b221381a6b..2daa595aaff40b7195772e5ce9aed761b20ee186 100644 (file)
@@ -542,6 +542,11 @@ MUX_CFG_34XX("AF13_3430_MMC3_DAT2", 0x5e8,
                OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLUP)
 MUX_CFG_34XX("AF13_3430_MMC3_DAT3", 0x5e2,
                OMAP34XX_MUX_MODE2 | OMAP34XX_PIN_INPUT_PULLUP)
+
+/* SYS_NIRQ T2 INT1 */
+MUX_CFG_34XX("AF26_34XX_SYS_NIRQ", 0x1E0,
+               OMAP3_WAKEUP_EN | OMAP34XX_PIN_INPUT_PULLUP |
+               OMAP34XX_MUX_MODE0)
 };
 
 #define OMAP34XX_PINS_SZ       ARRAY_SIZE(omap34xx_pins)
index da3a53f8ccc8005e6efb36ab35827d0d2a48f5c8..1b4c1600f8d8c4c0f53ed5f70bd974d219777b83 100644 (file)
  */
 
 #include <linux/kernel.h>
-#include <linux/timer.h>
+#include <linux/sched.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/module.h>
 
 #include <mach/clock.h>
 #include <mach/board.h>
+#include <mach/powerdomain.h>
+#include <mach/clockdomain.h>
 
 #include "prm.h"
 #include "cm.h"
@@ -50,6 +53,8 @@ int omap2_pm_debug;
        regs[reg_count].name = #reg; \
        regs[reg_count++].val = __raw_readl(OMAP2_IO_ADDRESS(0x480fe000 + (off)))
 
+static int __init pm_dbg_init(void);
+
 void omap2_pm_dump(int mode, int resume, unsigned int us)
 {
        struct reg {
@@ -150,3 +155,425 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
        for (i = 0; i < reg_count; i++)
                printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val);
 }
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static void pm_dbg_regset_store(u32 *ptr);
+
+struct dentry *pm_dbg_dir;
+
+static int pm_dbg_init_done;
+
+enum {
+       DEBUG_FILE_COUNTERS = 0,
+       DEBUG_FILE_TIMERS,
+};
+
+struct pm_module_def {
+       char name[8]; /* Name of the module */
+       short type; /* CM or PRM */
+       unsigned short offset;
+       int low; /* First register address on this module */
+       int high; /* Last register address on this module */
+};
+
+#define MOD_CM 0
+#define MOD_PRM 1
+
+static const struct pm_module_def *pm_dbg_reg_modules;
+static const struct pm_module_def omap3_pm_reg_modules[] = {
+       { "IVA2", MOD_CM, OMAP3430_IVA2_MOD, 0, 0x4c },
+       { "OCP", MOD_CM, OCP_MOD, 0, 0x10 },
+       { "MPU", MOD_CM, MPU_MOD, 4, 0x4c },
+       { "CORE", MOD_CM, CORE_MOD, 0, 0x4c },
+       { "SGX", MOD_CM, OMAP3430ES2_SGX_MOD, 0, 0x4c },
+       { "WKUP", MOD_CM, WKUP_MOD, 0, 0x40 },
+       { "CCR", MOD_CM, PLL_MOD, 0, 0x70 },
+       { "DSS", MOD_CM, OMAP3430_DSS_MOD, 0, 0x4c },
+       { "CAM", MOD_CM, OMAP3430_CAM_MOD, 0, 0x4c },
+       { "PER", MOD_CM, OMAP3430_PER_MOD, 0, 0x4c },
+       { "EMU", MOD_CM, OMAP3430_EMU_MOD, 0x40, 0x54 },
+       { "NEON", MOD_CM, OMAP3430_NEON_MOD, 0x20, 0x48 },
+       { "USB", MOD_CM, OMAP3430ES2_USBHOST_MOD, 0, 0x4c },
+
+       { "IVA2", MOD_PRM, OMAP3430_IVA2_MOD, 0x50, 0xfc },
+       { "OCP", MOD_PRM, OCP_MOD, 4, 0x1c },
+       { "MPU", MOD_PRM, MPU_MOD, 0x58, 0xe8 },
+       { "CORE", MOD_PRM, CORE_MOD, 0x58, 0xf8 },
+       { "SGX", MOD_PRM, OMAP3430ES2_SGX_MOD, 0x58, 0xe8 },
+       { "WKUP", MOD_PRM, WKUP_MOD, 0xa0, 0xb0 },
+       { "CCR", MOD_PRM, PLL_MOD, 0x40, 0x70 },
+       { "DSS", MOD_PRM, OMAP3430_DSS_MOD, 0x58, 0xe8 },
+       { "CAM", MOD_PRM, OMAP3430_CAM_MOD, 0x58, 0xe8 },
+       { "PER", MOD_PRM, OMAP3430_PER_MOD, 0x58, 0xe8 },
+       { "EMU", MOD_PRM, OMAP3430_EMU_MOD, 0x58, 0xe4 },
+       { "GLBL", MOD_PRM, OMAP3430_GR_MOD, 0x20, 0xe4 },
+       { "NEON", MOD_PRM, OMAP3430_NEON_MOD, 0x58, 0xe8 },
+       { "USB", MOD_PRM, OMAP3430ES2_USBHOST_MOD, 0x58, 0xe8 },
+       { "", 0, 0, 0, 0 },
+};
+
+#define PM_DBG_MAX_REG_SETS 4
+
+static void *pm_dbg_reg_set[PM_DBG_MAX_REG_SETS];
+
+static int pm_dbg_get_regset_size(void)
+{
+       static int regset_size;
+
+       if (regset_size == 0) {
+               int i = 0;
+
+               while (pm_dbg_reg_modules[i].name[0] != 0) {
+                       regset_size += pm_dbg_reg_modules[i].high +
+                               4 - pm_dbg_reg_modules[i].low;
+                       i++;
+               }
+       }
+       return regset_size;
+}
+
+static int pm_dbg_show_regs(struct seq_file *s, void *unused)
+{
+       int i, j;
+       unsigned long val;
+       int reg_set = (int)s->private;
+       u32 *ptr;
+       void *store = NULL;
+       int regs;
+       int linefeed;
+
+       if (reg_set == 0) {
+               store = kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
+               ptr = store;
+               pm_dbg_regset_store(ptr);
+       } else {
+               ptr = pm_dbg_reg_set[reg_set - 1];
+       }
+
+       i = 0;
+
+       while (pm_dbg_reg_modules[i].name[0] != 0) {
+               regs = 0;
+               linefeed = 0;
+               if (pm_dbg_reg_modules[i].type == MOD_CM)
+                       seq_printf(s, "MOD: CM_%s (%08x)\n",
+                               pm_dbg_reg_modules[i].name,
+                               (u32)(OMAP3430_CM_BASE +
+                               pm_dbg_reg_modules[i].offset));
+               else
+                       seq_printf(s, "MOD: PRM_%s (%08x)\n",
+                               pm_dbg_reg_modules[i].name,
+                               (u32)(OMAP3430_PRM_BASE +
+                               pm_dbg_reg_modules[i].offset));
+
+               for (j = pm_dbg_reg_modules[i].low;
+                       j <= pm_dbg_reg_modules[i].high; j += 4) {
+                       val = *(ptr++);
+                       if (val != 0) {
+                               regs++;
+                               if (linefeed) {
+                                       seq_printf(s, "\n");
+                                       linefeed = 0;
+                               }
+                               seq_printf(s, "  %02x => %08lx", j, val);
+                               if (regs % 4 == 0)
+                                       linefeed = 1;
+                       }
+               }
+               seq_printf(s, "\n");
+               i++;
+       }
+
+       if (store != NULL)
+               kfree(store);
+
+       return 0;
+}
+
+static void pm_dbg_regset_store(u32 *ptr)
+{
+       int i, j;
+       u32 val;
+
+       i = 0;
+
+       while (pm_dbg_reg_modules[i].name[0] != 0) {
+               for (j = pm_dbg_reg_modules[i].low;
+                       j <= pm_dbg_reg_modules[i].high; j += 4) {
+                       if (pm_dbg_reg_modules[i].type == MOD_CM)
+                               val = cm_read_mod_reg(
+                                       pm_dbg_reg_modules[i].offset, j);
+                       else
+                               val = prm_read_mod_reg(
+                                       pm_dbg_reg_modules[i].offset, j);
+                       *(ptr++) = val;
+               }
+               i++;
+       }
+}
+
+int pm_dbg_regset_save(int reg_set)
+{
+       if (pm_dbg_reg_set[reg_set-1] == NULL)
+               return -EINVAL;
+
+       pm_dbg_regset_store(pm_dbg_reg_set[reg_set-1]);
+
+       return 0;
+}
+
+static const char pwrdm_state_names[][4] = {
+       "OFF",
+       "RET",
+       "INA",
+       "ON"
+};
+
+void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
+{
+       s64 t;
+
+       if (!pm_dbg_init_done)
+               return ;
+
+       /* Update timer for previous state */
+       t = sched_clock();
+
+       pwrdm->state_timer[prev] += t - pwrdm->timer;
+
+       pwrdm->timer = t;
+}
+
+static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
+{
+       struct seq_file *s = (struct seq_file *)user;
+
+       if (strcmp(clkdm->name, "emu_clkdm") == 0 ||
+               strcmp(clkdm->name, "wkup_clkdm") == 0 ||
+               strncmp(clkdm->name, "dpll", 4) == 0)
+               return 0;
+
+       seq_printf(s, "%s->%s (%d)", clkdm->name,
+                       clkdm->pwrdm.ptr->name,
+                       atomic_read(&clkdm->usecount));
+       seq_printf(s, "\n");
+
+       return 0;
+}
+
+static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user)
+{
+       struct seq_file *s = (struct seq_file *)user;
+       int i;
+
+       if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
+               strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
+               strncmp(pwrdm->name, "dpll", 4) == 0)
+               return 0;
+
+       if (pwrdm->state != pwrdm_read_pwrst(pwrdm))
+               printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n",
+                       pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm));
+
+       seq_printf(s, "%s (%s)", pwrdm->name,
+                       pwrdm_state_names[pwrdm->state]);
+       for (i = 0; i < 4; i++)
+               seq_printf(s, ",%s:%d", pwrdm_state_names[i],
+                       pwrdm->state_counter[i]);
+
+       seq_printf(s, "\n");
+
+       return 0;
+}
+
+static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user)
+{
+       struct seq_file *s = (struct seq_file *)user;
+       int i;
+
+       if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
+               strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
+               strncmp(pwrdm->name, "dpll", 4) == 0)
+               return 0;
+
+       pwrdm_state_switch(pwrdm);
+
+       seq_printf(s, "%s (%s)", pwrdm->name,
+               pwrdm_state_names[pwrdm->state]);
+
+       for (i = 0; i < 4; i++)
+               seq_printf(s, ",%s:%lld", pwrdm_state_names[i],
+                       pwrdm->state_timer[i]);
+
+       seq_printf(s, "\n");
+       return 0;
+}
+
+static int pm_dbg_show_counters(struct seq_file *s, void *unused)
+{
+       pwrdm_for_each(pwrdm_dbg_show_counter, s);
+       clkdm_for_each(clkdm_dbg_show_counter, s);
+
+       return 0;
+}
+
+static int pm_dbg_show_timers(struct seq_file *s, void *unused)
+{
+       pwrdm_for_each(pwrdm_dbg_show_timer, s);
+       return 0;
+}
+
+static int pm_dbg_open(struct inode *inode, struct file *file)
+{
+       switch ((int)inode->i_private) {
+       case DEBUG_FILE_COUNTERS:
+               return single_open(file, pm_dbg_show_counters,
+                       &inode->i_private);
+       case DEBUG_FILE_TIMERS:
+       default:
+               return single_open(file, pm_dbg_show_timers,
+                       &inode->i_private);
+       };
+}
+
+static int pm_dbg_reg_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, pm_dbg_show_regs, inode->i_private);
+}
+
+static const struct file_operations debug_fops = {
+       .open           = pm_dbg_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static const struct file_operations debug_reg_fops = {
+       .open           = pm_dbg_reg_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+int pm_dbg_regset_init(int reg_set)
+{
+       char name[2];
+
+       if (!pm_dbg_init_done)
+               pm_dbg_init();
+
+       if (reg_set < 1 || reg_set > PM_DBG_MAX_REG_SETS ||
+               pm_dbg_reg_set[reg_set-1] != NULL)
+               return -EINVAL;
+
+       pm_dbg_reg_set[reg_set-1] =
+               kmalloc(pm_dbg_get_regset_size(), GFP_KERNEL);
+
+       if (pm_dbg_reg_set[reg_set-1] == NULL)
+               return -ENOMEM;
+
+       if (pm_dbg_dir != NULL) {
+               sprintf(name, "%d", reg_set);
+
+               (void) debugfs_create_file(name, S_IRUGO,
+                       pm_dbg_dir, (void *)reg_set, &debug_reg_fops);
+       }
+
+       return 0;
+}
+
+static int pwrdm_suspend_get(void *data, u64 *val)
+{
+       *val = omap3_pm_get_suspend_state((struct powerdomain *)data);
+
+       if (*val >= 0)
+               return 0;
+       return *val;
+}
+
+static int pwrdm_suspend_set(void *data, u64 val)
+{
+       return omap3_pm_set_suspend_state((struct powerdomain *)data, (int)val);
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pwrdm_suspend_fops, pwrdm_suspend_get,
+                       pwrdm_suspend_set, "%llu\n");
+
+static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
+{
+       int i;
+       s64 t;
+       struct dentry *d;
+
+       t = sched_clock();
+
+       for (i = 0; i < 4; i++)
+               pwrdm->state_timer[i] = 0;
+
+       pwrdm->timer = t;
+
+       if (strncmp(pwrdm->name, "dpll", 4) == 0)
+               return 0;
+
+       d = debugfs_create_dir(pwrdm->name, (struct dentry *)dir);
+
+       (void) debugfs_create_file("suspend", S_IRUGO|S_IWUSR, d,
+                       (void *)pwrdm, &pwrdm_suspend_fops);
+
+       return 0;
+}
+
+static int __init pm_dbg_init(void)
+{
+       int i;
+       struct dentry *d;
+       char name[2];
+
+       if (pm_dbg_init_done)
+               return 0;
+
+       if (cpu_is_omap34xx())
+               pm_dbg_reg_modules = omap3_pm_reg_modules;
+       else {
+               printk(KERN_ERR "%s: only OMAP3 supported\n", __func__);
+               return -ENODEV;
+       }
+               
+       d = debugfs_create_dir("pm_debug", NULL);
+       if (IS_ERR(d))
+               return PTR_ERR(d);
+
+       (void) debugfs_create_file("count", S_IRUGO,
+               d, (void *)DEBUG_FILE_COUNTERS, &debug_fops);
+       (void) debugfs_create_file("time", S_IRUGO,
+               d, (void *)DEBUG_FILE_TIMERS, &debug_fops);
+
+       pwrdm_for_each(pwrdms_setup, (void *)d);
+
+       pm_dbg_dir = debugfs_create_dir("registers", d);
+       if (IS_ERR(pm_dbg_dir))
+               return PTR_ERR(pm_dbg_dir);
+
+       (void) debugfs_create_file("current", S_IRUGO,
+               pm_dbg_dir, (void *)0, &debug_reg_fops);
+
+       for (i = 0; i < PM_DBG_MAX_REG_SETS; i++)
+               if (pm_dbg_reg_set[i] != NULL) {
+                       sprintf(name, "%d", i+1);
+                       (void) debugfs_create_file(name, S_IRUGO,
+                               pm_dbg_dir, (void *)(i+1), &debug_reg_fops);
+
+               }
+
+       pm_dbg_init_done = 1;
+
+       return 0;
+}
+arch_initcall(pm_dbg_init);
+
+#else
+void pm_dbg_update_time(struct powerdomain *pwrdm, int prev) {}
+#endif
index 21201cd4117b5d55a4380422d253687372657bad..8400f57689232ac0334d52c2340d1fa375c1e6d1 100644 (file)
 #ifndef __ARCH_ARM_MACH_OMAP2_PM_H
 #define __ARCH_ARM_MACH_OMAP2_PM_H
 
+#include <mach/powerdomain.h>
+
+extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm);
+extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state);
+
 #ifdef CONFIG_PM_DEBUG
 extern void omap2_pm_dump(int mode, int resume, unsigned int us);
 extern int omap2_pm_debug;
+extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev);
+extern int pm_dbg_regset_save(int reg_set);
+extern int pm_dbg_regset_init(int reg_set);
 #else
 #define omap2_pm_dump(mode, resume, us)                do {} while (0);
 #define omap2_pm_debug                         0
+#define pm_dbg_update_time(pwrdm, prev) do {} while (0);
+#define pm_dbg_regset_save(reg_set) do {} while (0);
+#define pm_dbg_regset_init(reg_set) do {} while (0);
 #endif /* CONFIG_PM_DEBUG */
 
 extern void omap24xx_idle_loop_suspend(void);
index 528dbdc26e2363536335c88446b8c17ebbef234b..bff5c4e89742f59c8de35550db88acdce44785ab 100644 (file)
@@ -333,7 +333,7 @@ static struct platform_suspend_ops omap_pm_ops = {
        .valid          = suspend_valid_only_mem,
 };
 
-static int _pm_clkdm_enable_hwsup(struct clockdomain *clkdm)
+static int _pm_clkdm_enable_hwsup(struct clockdomain *clkdm, void *unused)
 {
        omap2_clkdm_allow_idle(clkdm);
        return 0;
@@ -385,7 +385,7 @@ static void __init prcm_setup_regs(void)
        omap2_clkdm_sleep(gfx_clkdm);
 
        /* Enable clockdomain hardware-supervised control for all clkdms */
-       clkdm_for_each(_pm_clkdm_enable_hwsup);
+       clkdm_for_each(_pm_clkdm_enable_hwsup, NULL);
 
        /* Enable clock autoidle for all domains */
        cm_write_mod_reg(OMAP24XX_AUTO_CAM |
index 488d595d8e4b337a29a589a950a5d3f73aca15a4..0ff5a6c53aa0e79fca0f58d90493273f7e1b123c 100644 (file)
@@ -170,6 +170,8 @@ static void omap_sram_idle(void)
                printk(KERN_ERR "Invalid mpu state in sram_idle\n");
                return;
        }
+       pwrdm_pre_transition();
+
        omap2_gpio_prepare_for_retention();
        omap_uart_prepare_idle(0);
        omap_uart_prepare_idle(1);
@@ -182,6 +184,9 @@ static void omap_sram_idle(void)
        omap_uart_resume_idle(1);
        omap_uart_resume_idle(0);
        omap2_gpio_resume_after_retention();
+
+       pwrdm_post_transition();
+
 }
 
 /*
@@ -271,6 +276,7 @@ static int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
        if (sleep_switch) {
                omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
                pwrdm_wait_transition(pwrdm);
+               pwrdm_state_switch(pwrdm);
        }
 
 err:
@@ -658,14 +664,38 @@ static void __init prcm_setup_regs(void)
        omap3_d2d_idle();
 }
 
-static int __init pwrdms_setup(struct powerdomain *pwrdm)
+int omap3_pm_get_suspend_state(struct powerdomain *pwrdm)
+{
+       struct power_state *pwrst;
+
+       list_for_each_entry(pwrst, &pwrst_list, node) {
+               if (pwrst->pwrdm == pwrdm)
+                       return pwrst->next_state;
+       }
+       return -EINVAL;
+}
+
+int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state)
+{
+       struct power_state *pwrst;
+
+       list_for_each_entry(pwrst, &pwrst_list, node) {
+               if (pwrst->pwrdm == pwrdm) {
+                       pwrst->next_state = state;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 {
        struct power_state *pwrst;
 
        if (!pwrdm->pwrsts)
                return 0;
 
-       pwrst = kmalloc(sizeof(struct power_state), GFP_KERNEL);
+       pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
        if (!pwrst)
                return -ENOMEM;
        pwrst->pwrdm = pwrdm;
@@ -683,7 +713,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm)
  * supported. Initiate sleep transition for other clockdomains, if
  * they are not used
  */
-static int __init clkdms_setup(struct clockdomain *clkdm)
+static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
        if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
                omap2_clkdm_allow_idle(clkdm);
@@ -716,13 +746,13 @@ static int __init omap3_pm_init(void)
                goto err1;
        }
 
-       ret = pwrdm_for_each(pwrdms_setup);
+       ret = pwrdm_for_each(pwrdms_setup, NULL);
        if (ret) {
                printk(KERN_ERR "Failed to setup powerdomains\n");
                goto err2;
        }
 
-       (void) clkdm_for_each(clkdms_setup);
+       (void) clkdm_for_each(clkdms_setup, NULL);
 
        mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
        if (mpu_pwrdm == NULL) {
index 66206b6357fc7e7d118a645a8dbc7f1d498d26a6..2594cbff3947e12f8d37c966e22fd99a22c5a1d1 100644 (file)
 #include <mach/powerdomain.h>
 #include <mach/clockdomain.h>
 
+#include "pm.h"
+
+enum {
+       PWRDM_STATE_NOW = 0,
+       PWRDM_STATE_PREV,
+};
+
 /* pwrdm_list contains all registered struct powerdomains */
 static LIST_HEAD(pwrdm_list);
 
@@ -102,6 +109,65 @@ static struct powerdomain *_pwrdm_deps_lookup(struct powerdomain *pwrdm,
        return pd->pwrdm;
 }
 
+static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
+{
+
+       int prev;
+       int state;
+
+       if (pwrdm == NULL)
+               return -EINVAL;
+
+       state = pwrdm_read_pwrst(pwrdm);
+
+       switch (flag) {
+       case PWRDM_STATE_NOW:
+               prev = pwrdm->state;
+               break;
+       case PWRDM_STATE_PREV:
+               prev = pwrdm_read_prev_pwrst(pwrdm);
+               if (pwrdm->state != prev)
+                       pwrdm->state_counter[prev]++;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (state != prev)
+               pwrdm->state_counter[state]++;
+
+       pm_dbg_update_time(pwrdm, prev);
+
+       pwrdm->state = state;
+
+       return 0;
+}
+
+static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused)
+{
+       pwrdm_clear_all_prev_pwrst(pwrdm);
+       _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
+       return 0;
+}
+
+static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
+{
+       _pwrdm_state_switch(pwrdm, PWRDM_STATE_PREV);
+       return 0;
+}
+
+static __init void _pwrdm_setup(struct powerdomain *pwrdm)
+{
+       int i;
+
+       for (i = 0; i < 4; i++)
+               pwrdm->state_counter[i] = 0;
+
+       pwrdm_wait_transition(pwrdm);
+       pwrdm->state = pwrdm_read_pwrst(pwrdm);
+       pwrdm->state_counter[pwrdm->state] = 1;
+
+}
 
 /* Public functions */
 
@@ -117,9 +183,12 @@ void pwrdm_init(struct powerdomain **pwrdm_list)
 {
        struct powerdomain **p = NULL;
 
-       if (pwrdm_list)
-               for (p = pwrdm_list; *p; p++)
+       if (pwrdm_list) {
+               for (p = pwrdm_list; *p; p++) {
                        pwrdm_register(*p);
+                       _pwrdm_setup(*p);
+               }
+       }
 }
 
 /**
@@ -217,7 +286,8 @@ struct powerdomain *pwrdm_lookup(const char *name)
  * anything else to indicate failure; or -EINVAL if the function
  * pointer is null.
  */
-int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm))
+int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
+                       void *user)
 {
        struct powerdomain *temp_pwrdm;
        unsigned long flags;
@@ -228,7 +298,7 @@ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm))
 
        read_lock_irqsave(&pwrdm_rwlock, flags);
        list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {
-               ret = (*fn)(temp_pwrdm);
+               ret = (*fn)(temp_pwrdm, user);
                if (ret)
                        break;
        }
@@ -1110,4 +1180,36 @@ int pwrdm_wait_transition(struct powerdomain *pwrdm)
        return 0;
 }
 
+int pwrdm_state_switch(struct powerdomain *pwrdm)
+{
+       return _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
+}
+
+int pwrdm_clkdm_state_switch(struct clockdomain *clkdm)
+{
+       if (clkdm != NULL && clkdm->pwrdm.ptr != NULL) {
+               pwrdm_wait_transition(clkdm->pwrdm.ptr);
+               return pwrdm_state_switch(clkdm->pwrdm.ptr);
+       }
+
+       return -EINVAL;
+}
+int pwrdm_clk_state_switch(struct clk *clk)
+{
+       if (clk != NULL && clk->clkdm != NULL)
+               return pwrdm_clkdm_state_switch(clk->clkdm);
+       return -EINVAL;
+}
+
+int pwrdm_pre_transition(void)
+{
+       pwrdm_for_each(_pwrdm_pre_transition_cb, NULL);
+       return 0;
+}
+
+int pwrdm_post_transition(void)
+{
+       pwrdm_for_each(_pwrdm_post_transition_cb, NULL);
+       return 0;
+}
 
index ca28424f2fbda8accdd2ee66f48a54956e6ffea1..021130d830b5c42ddd28534a1e8d74f67a9134b2 100644 (file)
@@ -113,6 +113,21 @@ static struct plat_serial8250_port serial_platform_data2[] = {
        }
 };
 
+#ifdef CONFIG_ARCH_OMAP4
+static struct plat_serial8250_port serial_platform_data3[] = {
+       {
+               .membase        = IO_ADDRESS(OMAP_UART4_BASE),
+               .mapbase        = OMAP_UART4_BASE,
+               .irq            = 70,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .iotype         = UPIO_MEM,
+               .regshift       = 2,
+               .uartclk        = OMAP24XX_BASE_BAUD * 16,
+       }, {
+               .flags          = 0
+       }
+};
+#endif
 static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
                                           int offset)
 {
@@ -550,6 +565,17 @@ static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS] = {
                        },
                },
        },
+#ifdef CONFIG_ARCH_OMAP4
+       {
+               .pdev = {
+                       .name                   = "serial8250",
+                       .id                     = 3
+                       .dev                    = {
+                               .platform_data  = serial_platform_data3,
+                       },
+               },
+       },
+#endif
 };
 
 void __init omap_serial_early_init(void)
@@ -583,8 +609,11 @@ void __init omap_serial_early_init(void)
                        uart->fck = NULL;
                }
 
-               if (!uart->ick || !uart->fck)
-                       continue;
+               /* FIXME: Remove this once the clkdev is ready */
+               if (!cpu_is_omap44xx()) {
+                       if (!uart->ick || !uart->fck)
+                               continue;
+               }
 
                uart->num = i;
                p->private_data = uart;
index 739e59e8025cc7b109707ac7f4b302afbb82fb14..1145a2562b0f7fc9620793a34a526bdc4878f2b1 100644 (file)
 #include <mach/mux.h>
 #include <mach/usb.h>
 
-#define OTG_SYSCONFIG  (OMAP34XX_HSUSB_OTG_BASE + 0x404)
-
-static void __init usb_musb_pm_init(void)
-{
-       /* Ensure force-idle mode for OTG controller */
-       if (cpu_is_omap34xx())
-               omap_writel(0, OTG_SYSCONFIG);
-}
-
 #ifdef CONFIG_USB_MUSB_SOC
 
 static struct resource musb_resources[] = {
@@ -173,13 +164,10 @@ void __init usb_musb_init(void)
                printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
                return;
        }
-
-       usb_musb_pm_init();
 }
 
 #else
 void __init usb_musb_init(void)
 {
-       usb_musb_pm_init();
 }
 #endif /* CONFIG_USB_MUSB_SOC */
index b9d0dd2da89b4f4f47378e31157e895639e30d29..99ebd886f134ca4c76a0d7a95dce7a508795de12 100644 (file)
@@ -95,7 +95,8 @@ int clkdm_register(struct clockdomain *clkdm);
 int clkdm_unregister(struct clockdomain *clkdm);
 struct clockdomain *clkdm_lookup(const char *name);
 
-int clkdm_for_each(int (*fn)(struct clockdomain *clkdm));
+int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
+                       void *user);
 struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm);
 
 void omap2_clkdm_allow_idle(struct clockdomain *clkdm);
index 2c57bad65b0230f02ed331a96fac708e24787986..98dfab651dfc9198272af9f1f966d4b4b2fd1dbb 100644 (file)
@@ -885,6 +885,9 @@ enum omap34xx_index {
        AH9_3430_MMC3_DAT1,
        AF13_3430_MMC3_DAT2,
        AF13_3430_MMC3_DAT3,
+
+       /* SYS_NIRQ T2 INT1 */
+       AF26_34XX_SYS_NIRQ,
 };
 
 struct omap_mux_cfg {
index 69c9e675d8ee48d2dfbf488a03068011e55e657d..6271d8556a40f32d5ef8d360bc6bbf8b74265559 100644 (file)
@@ -117,6 +117,13 @@ struct powerdomain {
 
        struct list_head node;
 
+       int state;
+       unsigned state_counter[4];
+
+#ifdef CONFIG_PM_DEBUG
+       s64 timer;
+       s64 state_timer[4];
+#endif
 };
 
 
@@ -126,7 +133,8 @@ int pwrdm_register(struct powerdomain *pwrdm);
 int pwrdm_unregister(struct powerdomain *pwrdm);
 struct powerdomain *pwrdm_lookup(const char *name);
 
-int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm));
+int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
+                       void *user);
 
 int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
 int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm);
@@ -164,4 +172,9 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 
 int pwrdm_wait_transition(struct powerdomain *pwrdm);
 
+int pwrdm_state_switch(struct powerdomain *pwrdm);
+int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
+int pwrdm_pre_transition(void);
+int pwrdm_post_transition(void);
+
 #endif