diff options
Diffstat (limited to 'arch/arm/mach-omap2/mux.c')
-rw-r--r-- | arch/arm/mach-omap2/mux.c | 525 |
1 files changed, 395 insertions, 130 deletions
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 074536a..17bd639 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -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 @@ -35,65 +35,79 @@ #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; } |