|
@@ -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
|
|
@@ -40,60 +40,72 @@
|
|
|
|
|
|
#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;
|
|
|
+ }
|
|
|
|
|
|
-u16 omap_mux_read(u16 reg)
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+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;
|
|
@@ -112,24 +124,40 @@ int __init omap_mux_init_gpio(int gpio, int val)
|
|
|
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;
|
|
|
pr_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);
|
|
|
+ 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_init_signal(struct omap_mux_partition *partition,
|
|
|
+ const char *muxname, int val)
|
|
|
{
|
|
|
struct omap_mux_entry *e;
|
|
|
const char *mode_name;
|
|
|
int found = 0, mode0_len = 0;
|
|
|
+ struct list_head *muxmodes = &partition->muxmodes;
|
|
|
|
|
|
mode_name = strchr(muxname, '.');
|
|
|
if (mode_name) {
|
|
@@ -139,7 +167,7 @@ int __init omap_mux_init_signal(const char *muxname, int val)
|
|
|
mode_name = muxname;
|
|
|
}
|
|
|
|
|
|
- list_for_each_entry(e, &muxmodes, node) {
|
|
|
+ list_for_each_entry(e, muxmodes, node) {
|
|
|
struct omap_mux *m = &e->mux;
|
|
|
char *m0_entry = m->muxnames[0];
|
|
|
int i;
|
|
@@ -159,12 +187,14 @@ int __init omap_mux_init_signal(const char *muxname, int val)
|
|
|
u16 old_mode;
|
|
|
u16 mux_mode;
|
|
|
|
|
|
- old_mode = omap_mux_read(m->reg_offset);
|
|
|
+ old_mode = omap_mux_read(partition,
|
|
|
+ m->reg_offset);
|
|
|
mux_mode = val | i;
|
|
|
pr_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);
|
|
|
+ omap_mux_write(partition, mux_mode,
|
|
|
+ m->reg_offset);
|
|
|
found++;
|
|
|
}
|
|
|
}
|
|
@@ -184,6 +214,21 @@ int __init omap_mux_init_signal(const char *muxname, int val)
|
|
|
return -ENODEV;
|
|
|
}
|
|
|
|
|
|
+int __init omap_mux_init_signal(const char *muxname, int val)
|
|
|
+{
|
|
|
+ struct omap_mux_partition *partition;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ list_for_each_entry(partition, &mux_partitions, node) {
|
|
|
+ ret = _omap_mux_init_signal(partition, muxname, val);
|
|
|
+ if (!ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
|
|
|
|
#define OMAP_MUX_MAX_NR_FLAGS 10
|
|
@@ -248,13 +293,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 +319,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 +338,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 +348,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 +406,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 +435,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 +460,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 +518,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();
|
|
@@ -554,7 +653,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 +691,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) {
|
|
|
- pr_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("mux: Could not get gpio%i\n", 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) {
|
|
|
- pr_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("mux: Could not set gpio%i\n", 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 +767,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 +778,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,13 +791,14 @@ 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) {
|
|
|
pr_err("mux: Could not add entry\n");
|
|
|
return;
|
|
@@ -706,10 +819,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 +834,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) {
|
|
|
- pr_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("mux: Could not ioremap mux partition at 0x%08x\n",
|
|
|
+ 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("MUX: Add partition: #%d: %s, flags: %x\n",
|
|
|
+ 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;
|
|
|
}
|