Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzi...
[pandora-kernel.git] / arch / arm / mach-omap2 / mux.c
index 074536a..17bd639 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * linux/arch/arm/mach-omap2/mux.c
  *
- * OMAP2 and OMAP3 pin multiplexing configurations
+ * OMAP2, OMAP3 and OMAP4 pin multiplexing configurations
  *
- * Copyright (C) 2004 - 2008 Texas Instruments Inc.
+ * Copyright (C) 2004 - 2010 Texas Instruments Inc.
  * Copyright (C) 2003 - 2008 Nokia Corporation
  *
  * Written by Tony Lindgren
 
 #include <asm/system.h>
 
+#include <plat/omap_hwmod.h>
+
 #include "control.h"
 #include "mux.h"
 
 #define OMAP_MUX_BASE_OFFSET           0x30    /* Offset from CTRL_BASE */
 #define OMAP_MUX_BASE_SZ               0x5ca
-#define MUXABLE_GPIO_MODE3             BIT(0)
 
 struct omap_mux_entry {
        struct omap_mux         mux;
        struct list_head        node;
 };
 
-static unsigned long mux_phys;
-static void __iomem *mux_base;
-static u8 omap_mux_flags;
+static LIST_HEAD(mux_partitions);
+static DEFINE_MUTEX(muxmode_mutex);
+
+struct omap_mux_partition *omap_mux_get(const char *name)
+{
+       struct omap_mux_partition *partition;
+
+       list_for_each_entry(partition, &mux_partitions, node) {
+               if (!strcmp(name, partition->name))
+                       return partition;
+       }
+
+       return NULL;
+}
 
-u16 omap_mux_read(u16 reg)
+u16 omap_mux_read(struct omap_mux_partition *partition, u16 reg)
 {
-       if (cpu_is_omap24xx())
-               return __raw_readb(mux_base + reg);
+       if (partition->flags & OMAP_MUX_REG_8BIT)
+               return __raw_readb(partition->base + reg);
        else
-               return __raw_readw(mux_base + reg);
+               return __raw_readw(partition->base + reg);
 }
 
-void omap_mux_write(u16 val, u16 reg)
+void omap_mux_write(struct omap_mux_partition *partition, u16 val,
+                          u16 reg)
 {
-       if (cpu_is_omap24xx())
-               __raw_writeb(val, mux_base + reg);
+       if (partition->flags & OMAP_MUX_REG_8BIT)
+               __raw_writeb(val, partition->base + reg);
        else
-               __raw_writew(val, mux_base + reg);
+               __raw_writew(val, partition->base + reg);
 }
 
-void omap_mux_write_array(struct omap_board_mux *board_mux)
+void omap_mux_write_array(struct omap_mux_partition *partition,
+                                struct omap_board_mux *board_mux)
 {
-       while (board_mux->reg_offset !=  OMAP_MUX_TERMINATOR) {
-               omap_mux_write(board_mux->value, board_mux->reg_offset);
+       while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) {
+               omap_mux_write(partition, board_mux->value,
+                              board_mux->reg_offset);
                board_mux++;
        }
 }
 
-static LIST_HEAD(muxmodes);
-static DEFINE_MUTEX(muxmode_mutex);
-
 #ifdef CONFIG_OMAP_MUX
 
 static char *omap_mux_options;
 
-int __init omap_mux_init_gpio(int gpio, int val)
+static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
+                                     int gpio, int val)
 {
        struct omap_mux_entry *e;
        struct omap_mux *gpio_mux = NULL;
        u16 old_mode;
        u16 mux_mode;
        int found = 0;
+       struct list_head *muxmodes = &partition->muxmodes;
 
        if (!gpio)
                return -EINVAL;
 
-       list_for_each_entry(e, &muxmodes, node) {
+       list_for_each_entry(e, muxmodes, node) {
                struct omap_mux *m = &e->mux;
                if (gpio == m->gpio) {
                        gpio_mux = m;
@@ -102,34 +116,52 @@ int __init omap_mux_init_gpio(int gpio, int val)
        }
 
        if (found == 0) {
-               printk(KERN_ERR "mux: Could not set gpio%i\n", gpio);
+               pr_err("%s: Could not set gpio%i\n", __func__, gpio);
                return -ENODEV;
        }
 
        if (found > 1) {
-               printk(KERN_INFO "mux: Multiple gpio paths (%d) for gpio%i\n",
-                               found, gpio);
+               pr_info("%s: Multiple gpio paths (%d) for gpio%i\n", __func__,
+                       found, gpio);
                return -EINVAL;
        }
 
-       old_mode = omap_mux_read(gpio_mux->reg_offset);
+       old_mode = omap_mux_read(partition, gpio_mux->reg_offset);
        mux_mode = val & ~(OMAP_MUX_NR_MODES - 1);
-       if (omap_mux_flags & MUXABLE_GPIO_MODE3)
+       if (partition->flags & OMAP_MUX_GPIO_IN_MODE3)
                mux_mode |= OMAP_MUX_MODE3;
        else
                mux_mode |= OMAP_MUX_MODE4;
-       printk(KERN_DEBUG "mux: Setting signal %s.gpio%i 0x%04x -> 0x%04x\n",
-                       gpio_mux->muxnames[0], gpio, old_mode, mux_mode);
-       omap_mux_write(mux_mode, gpio_mux->reg_offset);
+       pr_debug("%s: Setting signal %s.gpio%i 0x%04x -> 0x%04x\n", __func__,
+                gpio_mux->muxnames[0], gpio, old_mode, mux_mode);
+       omap_mux_write(partition, mux_mode, gpio_mux->reg_offset);
 
        return 0;
 }
 
-int __init omap_mux_init_signal(const char *muxname, int val)
+int __init omap_mux_init_gpio(int gpio, int val)
+{
+       struct omap_mux_partition *partition;
+       int ret;
+
+       list_for_each_entry(partition, &mux_partitions, node) {
+               ret = _omap_mux_init_gpio(partition, gpio, val);
+               if (!ret)
+                       return ret;
+       }
+
+       return -ENODEV;
+}
+
+static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
+                                       const char *muxname,
+                                       struct omap_mux **found_mux)
 {
+       struct omap_mux *mux = NULL;
        struct omap_mux_entry *e;
        const char *mode_name;
-       int found = 0, mode0_len = 0;
+       int found = 0, found_mode, mode0_len = 0;
+       struct list_head *muxmodes = &partition->muxmodes;
 
        mode_name = strchr(muxname, '.');
        if (mode_name) {
@@ -139,51 +171,200 @@ int __init omap_mux_init_signal(const char *muxname, int val)
                mode_name = muxname;
        }
 
-       list_for_each_entry(e, &muxmodes, node) {
-               struct omap_mux *m = &e->mux;
-               char *m0_entry = m->muxnames[0];
+       list_for_each_entry(e, muxmodes, node) {
+               char *m0_entry;
                int i;
 
+               mux = &e->mux;
+               m0_entry = mux->muxnames[0];
+
                /* First check for full name in mode0.muxmode format */
                if (mode0_len && strncmp(muxname, m0_entry, mode0_len))
                        continue;
 
                /* Then check for muxmode only */
                for (i = 0; i < OMAP_MUX_NR_MODES; i++) {
-                       char *mode_cur = m->muxnames[i];
+                       char *mode_cur = mux->muxnames[i];
 
                        if (!mode_cur)
                                continue;
 
                        if (!strcmp(mode_name, mode_cur)) {
-                               u16 old_mode;
-                               u16 mux_mode;
-
-                               old_mode = omap_mux_read(m->reg_offset);
-                               mux_mode = val | i;
-                               printk(KERN_DEBUG "mux: Setting signal "
-                                       "%s.%s 0x%04x -> 0x%04x\n",
-                                       m0_entry, muxname, old_mode, mux_mode);
-                               omap_mux_write(mux_mode, m->reg_offset);
+                               *found_mux = mux;
                                found++;
+                               found_mode = i;
                        }
                }
        }
 
-       if (found == 1)
-               return 0;
+       if (found == 1) {
+               return found_mode;
+       }
 
        if (found > 1) {
-               printk(KERN_ERR "mux: Multiple signal paths (%i) for %s\n",
-                               found, muxname);
+               pr_err("%s: Multiple signal paths (%i) for %s\n", __func__,
+                      found, muxname);
                return -EINVAL;
        }
 
-       printk(KERN_ERR "mux: Could not set signal %s\n", muxname);
+       pr_err("%s: Could not find signal %s\n", __func__, muxname);
 
        return -ENODEV;
 }
 
+static int __init
+omap_mux_get_by_name(const char *muxname,
+                       struct omap_mux_partition **found_partition,
+                       struct omap_mux **found_mux)
+{
+       struct omap_mux_partition *partition;
+
+       list_for_each_entry(partition, &mux_partitions, node) {
+               struct omap_mux *mux = NULL;
+               int mux_mode = _omap_mux_get_by_name(partition, muxname, &mux);
+               if (mux_mode < 0)
+                       continue;
+
+               *found_partition = partition;
+               *found_mux = mux;
+
+               return mux_mode;
+       }
+
+       return -ENODEV;
+}
+
+int __init omap_mux_init_signal(const char *muxname, int val)
+{
+       struct omap_mux_partition *partition = NULL;
+       struct omap_mux *mux = NULL;
+       u16 old_mode;
+       int mux_mode;
+
+       mux_mode = omap_mux_get_by_name(muxname, &partition, &mux);
+       if (mux_mode < 0)
+               return mux_mode;
+
+       old_mode = omap_mux_read(partition, mux->reg_offset);
+       mux_mode |= val;
+       pr_debug("%s: Setting signal %s 0x%04x -> 0x%04x\n",
+                        __func__, muxname, old_mode, mux_mode);
+       omap_mux_write(partition, mux_mode, mux->reg_offset);
+
+       return 0;
+}
+
+struct omap_hwmod_mux_info * __init
+omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
+{
+       struct omap_hwmod_mux_info *hmux;
+       int i;
+
+       if (!bpads || nr_pads < 1)
+               return NULL;
+
+       hmux = kzalloc(sizeof(struct omap_hwmod_mux_info), GFP_KERNEL);
+       if (!hmux)
+               goto err1;
+
+       hmux->nr_pads = nr_pads;
+
+       hmux->pads = kzalloc(sizeof(struct omap_device_pad) *
+                               nr_pads, GFP_KERNEL);
+       if (!hmux->pads)
+               goto err2;
+
+       for (i = 0; i < hmux->nr_pads; i++) {
+               struct omap_mux_partition *partition;
+               struct omap_device_pad *bpad = &bpads[i], *pad = &hmux->pads[i];
+               struct omap_mux *mux;
+               int mux_mode;
+
+               mux_mode = omap_mux_get_by_name(bpad->name, &partition, &mux);
+               if (mux_mode < 0)
+                       goto err3;
+               if (!pad->partition)
+                       pad->partition = partition;
+               if (!pad->mux)
+                       pad->mux = mux;
+
+               pad->name = kzalloc(strlen(bpad->name) + 1, GFP_KERNEL);
+               if (!pad->name) {
+                       int j;
+
+                       for (j = i - 1; j >= 0; j--)
+                               kfree(hmux->pads[j].name);
+                       goto err3;
+               }
+               strcpy(pad->name, bpad->name);
+
+               pad->flags = bpad->flags;
+               pad->enable = bpad->enable;
+               pad->idle = bpad->idle;
+               pad->off = bpad->off;
+               pr_debug("%s: Initialized %s\n", __func__, pad->name);
+       }
+
+       return hmux;
+
+err3:
+       kfree(hmux->pads);
+err2:
+       kfree(hmux);
+err1:
+       pr_err("%s: Could not allocate device mux entry\n", __func__);
+
+       return NULL;
+}
+
+/* Assumes the calling function takes care of locking */
+void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
+{
+       int i;
+
+       for (i = 0; i < hmux->nr_pads; i++) {
+               struct omap_device_pad *pad = &hmux->pads[i];
+               int flags, val = -EINVAL;
+
+               flags = pad->flags;
+
+               switch (state) {
+               case _HWMOD_STATE_ENABLED:
+                       if (flags & OMAP_DEVICE_PAD_ENABLED)
+                               break;
+                       flags |= OMAP_DEVICE_PAD_ENABLED;
+                       val = pad->enable;
+                       pr_debug("%s: Enabling %s %x\n", __func__,
+                                       pad->name, val);
+                       break;
+               case _HWMOD_STATE_IDLE:
+                       if (!(flags & OMAP_DEVICE_PAD_REMUX))
+                               break;
+                       flags &= ~OMAP_DEVICE_PAD_ENABLED;
+                       val = pad->idle;
+                       pr_debug("%s: Idling %s %x\n", __func__,
+                                       pad->name, val);
+                       break;
+               case _HWMOD_STATE_DISABLED:
+               default:
+                       /* Use safe mode unless OMAP_DEVICE_PAD_REMUX */
+                       if (flags & OMAP_DEVICE_PAD_REMUX)
+                               val = pad->off;
+                       else
+                               val = OMAP_MUX_MODE7;
+                       flags &= ~OMAP_DEVICE_PAD_ENABLED;
+                       pr_debug("%s: Disabling %s %x\n", __func__,
+                                       pad->name, val);
+               };
+
+               if (val >= 0) {
+                       omap_mux_write(pad->partition, val,
+                                       pad->mux->reg_offset);
+                       pad->flags = flags;
+               }
+       }
+}
+
 #ifdef CONFIG_DEBUG_FS
 
 #define OMAP_MUX_MAX_NR_FLAGS  10
@@ -248,13 +429,15 @@ static inline void omap_mux_decode(struct seq_file *s, u16 val)
        } while (i-- > 0);
 }
 
-#define OMAP_MUX_DEFNAME_LEN   16
+#define OMAP_MUX_DEFNAME_LEN   32
 
 static int omap_mux_dbg_board_show(struct seq_file *s, void *unused)
 {
+       struct omap_mux_partition *partition = s->private;
        struct omap_mux_entry *e;
+       u8 omap_gen = omap_rev() >> 28;
 
-       list_for_each_entry(e, &muxmodes, node) {
+       list_for_each_entry(e, &partition->muxmodes, node) {
                struct omap_mux *m = &e->mux;
                char m0_def[OMAP_MUX_DEFNAME_LEN];
                char *m0_name = m->muxnames[0];
@@ -272,11 +455,16 @@ static int omap_mux_dbg_board_show(struct seq_file *s, void *unused)
                        }
                        m0_def[i] = toupper(m0_name[i]);
                }
-               val = omap_mux_read(m->reg_offset);
+               val = omap_mux_read(partition, m->reg_offset);
                mode = val & OMAP_MUX_MODE7;
-
-               seq_printf(s, "OMAP%i_MUX(%s, ",
-                                       cpu_is_omap34xx() ? 3 : 0, m0_def);
+               if (mode != 0)
+                       seq_printf(s, "/* %s */\n", m->muxnames[mode]);
+
+               /*
+                * XXX: Might be revisited to support differences accross
+                * same OMAP generation.
+                */
+               seq_printf(s, "OMAP%d_MUX(%s, ", omap_gen, m0_def);
                omap_mux_decode(s, val);
                seq_printf(s, "),\n");
        }
@@ -286,7 +474,7 @@ static int omap_mux_dbg_board_show(struct seq_file *s, void *unused)
 
 static int omap_mux_dbg_board_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, omap_mux_dbg_board_show, &inode->i_private);
+       return single_open(file, omap_mux_dbg_board_show, inode->i_private);
 }
 
 static const struct file_operations omap_mux_dbg_board_fops = {
@@ -296,19 +484,43 @@ static const struct file_operations omap_mux_dbg_board_fops = {
        .release        = single_release,
 };
 
+static struct omap_mux_partition *omap_mux_get_partition(struct omap_mux *mux)
+{
+       struct omap_mux_partition *partition;
+
+       list_for_each_entry(partition, &mux_partitions, node) {
+               struct list_head *muxmodes = &partition->muxmodes;
+               struct omap_mux_entry *e;
+
+               list_for_each_entry(e, muxmodes, node) {
+                       struct omap_mux *m = &e->mux;
+
+                       if (m == mux)
+                               return partition;
+               }
+       }
+
+       return NULL;
+}
+
 static int omap_mux_dbg_signal_show(struct seq_file *s, void *unused)
 {
        struct omap_mux *m = s->private;
+       struct omap_mux_partition *partition;
        const char *none = "NA";
        u16 val;
        int mode;
 
-       val = omap_mux_read(m->reg_offset);
+       partition = omap_mux_get_partition(m);
+       if (!partition)
+               return 0;
+
+       val = omap_mux_read(partition, m->reg_offset);
        mode = val & OMAP_MUX_MODE7;
 
-       seq_printf(s, "name: %s.%s (0x%08lx/0x%03x = 0x%04x), b %s, t %s\n",
+       seq_printf(s, "name: %s.%s (0x%08x/0x%03x = 0x%04x), b %s, t %s\n",
                        m->muxnames[0], m->muxnames[mode],
-                       mux_phys + m->reg_offset, m->reg_offset, val,
+                       partition->phys + m->reg_offset, m->reg_offset, val,
                        m->balls[0] ? m->balls[0] : none,
                        m->balls[1] ? m->balls[1] : none);
        seq_printf(s, "mode: ");
@@ -330,14 +542,15 @@ static int omap_mux_dbg_signal_show(struct seq_file *s, void *unused)
 #define OMAP_MUX_MAX_ARG_CHAR  7
 
 static ssize_t omap_mux_dbg_signal_write(struct file *file,
-                                               const char __user *user_buf,
-                                               size_t count, loff_t *ppos)
+                                        const char __user *user_buf,
+                                        size_t count, loff_t *ppos)
 {
        char buf[OMAP_MUX_MAX_ARG_CHAR];
        struct seq_file *seqf;
        struct omap_mux *m;
        unsigned long val;
        int buf_size, ret;
+       struct omap_mux_partition *partition;
 
        if (count > OMAP_MUX_MAX_ARG_CHAR)
                return -EINVAL;
@@ -358,7 +571,11 @@ static ssize_t omap_mux_dbg_signal_write(struct file *file,
        seqf = file->private_data;
        m = seqf->private;
 
-       omap_mux_write((u16)val, m->reg_offset);
+       partition = omap_mux_get_partition(m);
+       if (!partition)
+               return -ENODEV;
+
+       omap_mux_write(partition, (u16)val, m->reg_offset);
        *ppos += count;
 
        return count;
@@ -379,22 +596,38 @@ static const struct file_operations omap_mux_dbg_signal_fops = {
 
 static struct dentry *mux_dbg_dir;
 
-static void __init omap_mux_dbg_init(void)
+static void __init omap_mux_dbg_create_entry(
+                               struct omap_mux_partition *partition,
+                               struct dentry *mux_dbg_dir)
 {
        struct omap_mux_entry *e;
 
+       list_for_each_entry(e, &partition->muxmodes, node) {
+               struct omap_mux *m = &e->mux;
+
+               (void)debugfs_create_file(m->muxnames[0], S_IWUGO, mux_dbg_dir,
+                                         m, &omap_mux_dbg_signal_fops);
+       }
+}
+
+static void __init omap_mux_dbg_init(void)
+{
+       struct omap_mux_partition *partition;
+       static struct dentry *mux_dbg_board_dir;
+
        mux_dbg_dir = debugfs_create_dir("omap_mux", NULL);
        if (!mux_dbg_dir)
                return;
 
-       (void)debugfs_create_file("board", S_IRUGO, mux_dbg_dir,
-                                       NULL, &omap_mux_dbg_board_fops);
-
-       list_for_each_entry(e, &muxmodes, node) {
-               struct omap_mux *m = &e->mux;
+       mux_dbg_board_dir = debugfs_create_dir("board", mux_dbg_dir);
+       if (!mux_dbg_board_dir)
+               return;
 
-               (void)debugfs_create_file(m->muxnames[0], S_IWUGO, mux_dbg_dir,
-                                       m, &omap_mux_dbg_signal_fops);
+       list_for_each_entry(partition, &mux_partitions, node) {
+               omap_mux_dbg_create_entry(partition, mux_dbg_dir);
+               (void)debugfs_create_file(partition->name, S_IRUGO,
+                                         mux_dbg_board_dir, partition,
+                                         &omap_mux_dbg_board_fops);
        }
 }
 
@@ -421,23 +654,25 @@ static void __init omap_mux_free_names(struct omap_mux *m)
 /* Free all data except for GPIO pins unless CONFIG_DEBUG_FS is set */
 static int __init omap_mux_late_init(void)
 {
-       struct omap_mux_entry *e, *tmp;
+       struct omap_mux_partition *partition;
 
-       list_for_each_entry_safe(e, tmp, &muxmodes, node) {
-               struct omap_mux *m = &e->mux;
-               u16 mode = omap_mux_read(m->reg_offset);
+       list_for_each_entry(partition, &mux_partitions, node) {
+               struct omap_mux_entry *e, *tmp;
+               list_for_each_entry_safe(e, tmp, &partition->muxmodes, node) {
+                       struct omap_mux *m = &e->mux;
+                       u16 mode = omap_mux_read(partition, m->reg_offset);
 
-               if (OMAP_MODE_GPIO(mode))
-                       continue;
+                       if (OMAP_MODE_GPIO(mode))
+                               continue;
 
 #ifndef CONFIG_DEBUG_FS
-               mutex_lock(&muxmode_mutex);
-               list_del(&e->node);
-               mutex_unlock(&muxmode_mutex);
-               omap_mux_free_names(m);
-               kfree(m);
+                       mutex_lock(&muxmode_mutex);
+                       list_del(&e->node);
+                       mutex_unlock(&muxmode_mutex);
+                       omap_mux_free_names(m);
+                       kfree(m);
 #endif
-
+               }
        }
 
        omap_mux_dbg_init();
@@ -462,8 +697,8 @@ static void __init omap_mux_package_fixup(struct omap_mux *p,
                        s++;
                }
                if (!found)
-                       printk(KERN_ERR "mux: Unknown entry offset 0x%x\n",
-                                       p->reg_offset);
+                       pr_err("%s: Unknown entry offset 0x%x\n", __func__,
+                              p->reg_offset);
                p++;
        }
 }
@@ -487,8 +722,8 @@ static void __init omap_mux_package_init_balls(struct omap_ball *b,
                        s++;
                }
                if (!found)
-                       printk(KERN_ERR "mux: Unknown ball offset 0x%x\n",
-                                       b->reg_offset);
+                       pr_err("%s: Unknown ball offset 0x%x\n", __func__,
+                              b->reg_offset);
                b++;
        }
 }
@@ -554,7 +789,7 @@ static void __init omap_mux_set_cmdline_signals(void)
 }
 
 static int __init omap_mux_copy_names(struct omap_mux *src,
-                                       struct omap_mux *dst)
+                                     struct omap_mux *dst)
 {
        int i;
 
@@ -592,51 +827,63 @@ free:
 
 #endif /* CONFIG_OMAP_MUX */
 
-static u16 omap_mux_get_by_gpio(int gpio)
+static struct omap_mux *omap_mux_get_by_gpio(
+                               struct omap_mux_partition *partition,
+                               int gpio)
 {
        struct omap_mux_entry *e;
-       u16 offset = OMAP_MUX_TERMINATOR;
+       struct omap_mux *ret = NULL;
 
-       list_for_each_entry(e, &muxmodes, node) {
+       list_for_each_entry(e, &partition->muxmodes, node) {
                struct omap_mux *m = &e->mux;
                if (m->gpio == gpio) {
-                       offset = m->reg_offset;
+                       ret = m;
                        break;
                }
        }
 
-       return offset;
+       return ret;
 }
 
 /* Needed for dynamic muxing of GPIO pins for off-idle */
 u16 omap_mux_get_gpio(int gpio)
 {
-       u16 offset;
+       struct omap_mux_partition *partition;
+       struct omap_mux *m;
 
-       offset = omap_mux_get_by_gpio(gpio);
-       if (offset == OMAP_MUX_TERMINATOR) {
-               printk(KERN_ERR "mux: Could not get gpio%i\n", gpio);
-               return offset;
+       list_for_each_entry(partition, &mux_partitions, node) {
+               m = omap_mux_get_by_gpio(partition, gpio);
+               if (m)
+                       return omap_mux_read(partition, m->reg_offset);
        }
 
-       return omap_mux_read(offset);
+       if (!m || m->reg_offset == OMAP_MUX_TERMINATOR)
+               pr_err("%s: Could not get gpio%i\n", __func__, gpio);
+
+       return OMAP_MUX_TERMINATOR;
 }
 
 /* Needed for dynamic muxing of GPIO pins for off-idle */
 void omap_mux_set_gpio(u16 val, int gpio)
 {
-       u16 offset;
+       struct omap_mux_partition *partition;
+       struct omap_mux *m = NULL;
 
-       offset = omap_mux_get_by_gpio(gpio);
-       if (offset == OMAP_MUX_TERMINATOR) {
-               printk(KERN_ERR "mux: Could not set gpio%i\n", gpio);
-               return;
+       list_for_each_entry(partition, &mux_partitions, node) {
+               m = omap_mux_get_by_gpio(partition, gpio);
+               if (m) {
+                       omap_mux_write(partition, val, m->reg_offset);
+                       return;
+               }
        }
 
-       omap_mux_write(val, offset);
+       if (!m || m->reg_offset == OMAP_MUX_TERMINATOR)
+               pr_err("%s: Could not set gpio%i\n", __func__, gpio);
 }
 
-static struct omap_mux * __init omap_mux_list_add(struct omap_mux *src)
+static struct omap_mux * __init omap_mux_list_add(
+                                       struct omap_mux_partition *partition,
+                                       struct omap_mux *src)
 {
        struct omap_mux_entry *entry;
        struct omap_mux *m;
@@ -656,7 +903,7 @@ static struct omap_mux * __init omap_mux_list_add(struct omap_mux *src)
 #endif
 
        mutex_lock(&muxmode_mutex);
-       list_add_tail(&entry->node, &muxmodes);
+       list_add_tail(&entry->node, &partition->muxmodes);
        mutex_unlock(&muxmode_mutex);
 
        return m;
@@ -667,7 +914,8 @@ static struct omap_mux * __init omap_mux_list_add(struct omap_mux *src)
  * the GPIO to mux offset mapping that is needed for dynamic muxing
  * of GPIO pins for off-idle.
  */
-static void __init omap_mux_init_list(struct omap_mux *superset)
+static void __init omap_mux_init_list(struct omap_mux_partition *partition,
+                                     struct omap_mux *superset)
 {
        while (superset->reg_offset !=  OMAP_MUX_TERMINATOR) {
                struct omap_mux *entry;
@@ -679,15 +927,16 @@ static void __init omap_mux_init_list(struct omap_mux *superset)
                }
 #else
                /* Skip pins that are not muxed as GPIO by bootloader */
-               if (!OMAP_MODE_GPIO(omap_mux_read(superset->reg_offset))) {
+               if (!OMAP_MODE_GPIO(omap_mux_read(partition,
+                                   superset->reg_offset))) {
                        superset++;
                        continue;
                }
 #endif
 
-               entry = omap_mux_list_add(superset);
+               entry = omap_mux_list_add(partition, superset);
                if (!entry) {
-                       printk(KERN_ERR "mux: Could not add entry\n");
+                       pr_err("%s: Could not add entry\n", __func__);
                        return;
                }
                superset++;
@@ -706,10 +955,11 @@ static void omap_mux_init_package(struct omap_mux *superset,
                omap_mux_package_init_balls(package_balls, superset);
 }
 
-static void omap_mux_init_signals(struct omap_board_mux *board_mux)
+static void omap_mux_init_signals(struct omap_mux_partition *partition,
+                                 struct omap_board_mux *board_mux)
 {
        omap_mux_set_cmdline_signals();
-       omap_mux_write_array(board_mux);
+       omap_mux_write_array(partition, board_mux);
 }
 
 #else
@@ -720,34 +970,49 @@ static void omap_mux_init_package(struct omap_mux *superset,
 {
 }
 
-static void omap_mux_init_signals(struct omap_board_mux *board_mux)
+static void omap_mux_init_signals(struct omap_mux_partition *partition,
+                                 struct omap_board_mux *board_mux)
 {
 }
 
 #endif
 
-int __init omap_mux_init(u32 mux_pbase, u32 mux_size,
-                               struct omap_mux *superset,
-                               struct omap_mux *package_subset,
-                               struct omap_board_mux *board_mux,
-                               struct omap_ball *package_balls)
-{
-       if (mux_base)
-               return -EBUSY;
+static u32 mux_partitions_cnt;
 
-       mux_phys = mux_pbase;
-       mux_base = ioremap(mux_pbase, mux_size);
-       if (!mux_base) {
-               printk(KERN_ERR "mux: Could not ioremap\n");
+int __init omap_mux_init(const char *name, u32 flags,
+                        u32 mux_pbase, u32 mux_size,
+                        struct omap_mux *superset,
+                        struct omap_mux *package_subset,
+                        struct omap_board_mux *board_mux,
+                        struct omap_ball *package_balls)
+{
+       struct omap_mux_partition *partition;
+
+       partition = kzalloc(sizeof(struct omap_mux_partition), GFP_KERNEL);
+       if (!partition)
+               return -ENOMEM;
+
+       partition->name = name;
+       partition->flags = flags;
+       partition->size = mux_size;
+       partition->phys = mux_pbase;
+       partition->base = ioremap(mux_pbase, mux_size);
+       if (!partition->base) {
+               pr_err("%s: Could not ioremap mux partition at 0x%08x\n",
+                       __func__, partition->phys);
                return -ENODEV;
        }
 
-       if (cpu_is_omap24xx())
-               omap_mux_flags = MUXABLE_GPIO_MODE3;
+       INIT_LIST_HEAD(&partition->muxmodes);
+
+       list_add_tail(&partition->node, &mux_partitions);
+       mux_partitions_cnt++;
+       pr_info("%s: Add partition: #%d: %s, flags: %x\n", __func__,
+               mux_partitions_cnt, partition->name, partition->flags);
 
        omap_mux_init_package(superset, package_subset, package_balls);
-       omap_mux_init_list(superset);
-       omap_mux_init_signals(board_mux);
+       omap_mux_init_list(partition, superset);
+       omap_mux_init_signals(partition, board_mux);
 
        return 0;
 }