mux.c revision c9d8230e316abb6a480f6bda85edf859896e9ab6
1/* 2 * linux/arch/arm/mach-omap2/mux.c 3 * 4 * OMAP2 and OMAP3 pin multiplexing configurations 5 * 6 * Copyright (C) 2004 - 2008 Texas Instruments Inc. 7 * Copyright (C) 2003 - 2008 Nokia Corporation 8 * 9 * Written by Tony Lindgren 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 * 25 */ 26#include <linux/module.h> 27#include <linux/init.h> 28#include <linux/io.h> 29#include <linux/slab.h> 30#include <linux/spinlock.h> 31#include <linux/list.h> 32#include <linux/ctype.h> 33#include <linux/debugfs.h> 34#include <linux/seq_file.h> 35#include <linux/uaccess.h> 36 37#include <asm/system.h> 38 39#include <plat/control.h> 40 41#include "mux.h" 42 43#define OMAP_MUX_BASE_OFFSET 0x30 /* Offset from CTRL_BASE */ 44#define OMAP_MUX_BASE_SZ 0x5ca 45#define MUXABLE_GPIO_MODE3 BIT(0) 46 47struct omap_mux_entry { 48 struct omap_mux mux; 49 struct list_head node; 50}; 51 52static unsigned long mux_phys; 53static void __iomem *mux_base; 54static u8 omap_mux_flags; 55 56u16 omap_mux_read(u16 reg) 57{ 58 if (cpu_is_omap24xx()) 59 return __raw_readb(mux_base + reg); 60 else 61 return __raw_readw(mux_base + reg); 62} 63 64void omap_mux_write(u16 val, u16 reg) 65{ 66 if (cpu_is_omap24xx()) 67 __raw_writeb(val, mux_base + reg); 68 else 69 __raw_writew(val, mux_base + reg); 70} 71 72void omap_mux_write_array(struct omap_board_mux *board_mux) 73{ 74 while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) { 75 omap_mux_write(board_mux->value, board_mux->reg_offset); 76 board_mux++; 77 } 78} 79 80static LIST_HEAD(muxmodes); 81static DEFINE_MUTEX(muxmode_mutex); 82 83#ifdef CONFIG_OMAP_MUX 84 85static char *omap_mux_options; 86 87int __init omap_mux_init_gpio(int gpio, int val) 88{ 89 struct omap_mux_entry *e; 90 int found = 0; 91 92 if (!gpio) 93 return -EINVAL; 94 95 list_for_each_entry(e, &muxmodes, node) { 96 struct omap_mux *m = &e->mux; 97 if (gpio == m->gpio) { 98 u16 old_mode; 99 u16 mux_mode; 100 101 old_mode = omap_mux_read(m->reg_offset); 102 mux_mode = val & ~(OMAP_MUX_NR_MODES - 1); 103 if (omap_mux_flags & MUXABLE_GPIO_MODE3) 104 mux_mode |= OMAP_MUX_MODE3; 105 else 106 mux_mode |= OMAP_MUX_MODE4; 107 printk(KERN_DEBUG "mux: Setting signal " 108 "%s.gpio%i 0x%04x -> 0x%04x\n", 109 m->muxnames[0], gpio, old_mode, mux_mode); 110 omap_mux_write(mux_mode, m->reg_offset); 111 found++; 112 } 113 } 114 115 if (found == 1) 116 return 0; 117 118 if (found > 1) { 119 printk(KERN_ERR "mux: Multiple gpio paths for gpio%i\n", gpio); 120 return -EINVAL; 121 } 122 123 printk(KERN_ERR "mux: Could not set gpio%i\n", gpio); 124 125 return -ENODEV; 126} 127 128int __init omap_mux_init_signal(char *muxname, int val) 129{ 130 struct omap_mux_entry *e; 131 char *m0_name = NULL, *mode_name = NULL; 132 int found = 0; 133 134 mode_name = strchr(muxname, '.'); 135 if (mode_name) { 136 *mode_name = '\0'; 137 mode_name++; 138 m0_name = muxname; 139 } else { 140 mode_name = muxname; 141 } 142 143 list_for_each_entry(e, &muxmodes, node) { 144 struct omap_mux *m = &e->mux; 145 char *m0_entry = m->muxnames[0]; 146 int i; 147 148 if (m0_name && strcmp(m0_name, m0_entry)) 149 continue; 150 151 for (i = 0; i < OMAP_MUX_NR_MODES; i++) { 152 char *mode_cur = m->muxnames[i]; 153 154 if (!mode_cur) 155 continue; 156 157 if (!strcmp(mode_name, mode_cur)) { 158 u16 old_mode; 159 u16 mux_mode; 160 161 old_mode = omap_mux_read(m->reg_offset); 162 mux_mode = val | i; 163 printk(KERN_DEBUG "mux: Setting signal " 164 "%s.%s 0x%04x -> 0x%04x\n", 165 m0_entry, muxname, old_mode, mux_mode); 166 omap_mux_write(mux_mode, m->reg_offset); 167 found++; 168 } 169 } 170 } 171 172 if (found == 1) 173 return 0; 174 175 if (found > 1) { 176 printk(KERN_ERR "mux: Multiple signal paths (%i) for %s\n", 177 found, muxname); 178 return -EINVAL; 179 } 180 181 printk(KERN_ERR "mux: Could not set signal %s\n", muxname); 182 183 return -ENODEV; 184} 185 186#ifdef CONFIG_DEBUG_FS 187 188#define OMAP_MUX_MAX_NR_FLAGS 10 189#define OMAP_MUX_TEST_FLAG(val, mask) \ 190 if (((val) & (mask)) == (mask)) { \ 191 i++; \ 192 flags[i] = #mask; \ 193 } 194 195/* REVISIT: Add checking for non-optimal mux settings */ 196static inline void omap_mux_decode(struct seq_file *s, u16 val) 197{ 198 char *flags[OMAP_MUX_MAX_NR_FLAGS]; 199 char mode[sizeof("OMAP_MUX_MODE") + 1]; 200 int i = -1; 201 202 sprintf(mode, "OMAP_MUX_MODE%d", val & 0x7); 203 i++; 204 flags[i] = mode; 205 206 OMAP_MUX_TEST_FLAG(val, OMAP_PIN_OFF_WAKEUPENABLE); 207 if (val & OMAP_OFF_EN) { 208 if (!(val & OMAP_OFFOUT_EN)) { 209 if (!(val & OMAP_OFF_PULL_UP)) { 210 OMAP_MUX_TEST_FLAG(val, 211 OMAP_PIN_OFF_INPUT_PULLDOWN); 212 } else { 213 OMAP_MUX_TEST_FLAG(val, 214 OMAP_PIN_OFF_INPUT_PULLUP); 215 } 216 } else { 217 if (!(val & OMAP_OFFOUT_VAL)) { 218 OMAP_MUX_TEST_FLAG(val, 219 OMAP_PIN_OFF_OUTPUT_LOW); 220 } else { 221 OMAP_MUX_TEST_FLAG(val, 222 OMAP_PIN_OFF_OUTPUT_HIGH); 223 } 224 } 225 } 226 227 if (val & OMAP_INPUT_EN) { 228 if (val & OMAP_PULL_ENA) { 229 if (!(val & OMAP_PULL_UP)) { 230 OMAP_MUX_TEST_FLAG(val, 231 OMAP_PIN_INPUT_PULLDOWN); 232 } else { 233 OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT_PULLUP); 234 } 235 } else { 236 OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT); 237 } 238 } else { 239 i++; 240 flags[i] = "OMAP_PIN_OUTPUT"; 241 } 242 243 do { 244 seq_printf(s, "%s", flags[i]); 245 if (i > 0) 246 seq_printf(s, " | "); 247 } while (i-- > 0); 248} 249 250#define OMAP_MUX_DEFNAME_LEN 16 251 252static int omap_mux_dbg_board_show(struct seq_file *s, void *unused) 253{ 254 struct omap_mux_entry *e; 255 256 list_for_each_entry(e, &muxmodes, node) { 257 struct omap_mux *m = &e->mux; 258 char m0_def[OMAP_MUX_DEFNAME_LEN]; 259 char *m0_name = m->muxnames[0]; 260 u16 val; 261 int i, mode; 262 263 if (!m0_name) 264 continue; 265 266 /* REVISIT: Needs to be updated if mode0 names get longer */ 267 for (i = 0; i < OMAP_MUX_DEFNAME_LEN; i++) { 268 if (m0_name[i] == '\0') { 269 m0_def[i] = m0_name[i]; 270 break; 271 } 272 m0_def[i] = toupper(m0_name[i]); 273 } 274 val = omap_mux_read(m->reg_offset); 275 mode = val & OMAP_MUX_MODE7; 276 277 seq_printf(s, "OMAP%i_MUX(%s, ", 278 cpu_is_omap34xx() ? 3 : 0, m0_def); 279 omap_mux_decode(s, val); 280 seq_printf(s, "),\n"); 281 } 282 283 return 0; 284} 285 286static int omap_mux_dbg_board_open(struct inode *inode, struct file *file) 287{ 288 return single_open(file, omap_mux_dbg_board_show, &inode->i_private); 289} 290 291static const struct file_operations omap_mux_dbg_board_fops = { 292 .open = omap_mux_dbg_board_open, 293 .read = seq_read, 294 .llseek = seq_lseek, 295 .release = single_release, 296}; 297 298static int omap_mux_dbg_signal_show(struct seq_file *s, void *unused) 299{ 300 struct omap_mux *m = s->private; 301 const char *none = "NA"; 302 u16 val; 303 int mode; 304 305 val = omap_mux_read(m->reg_offset); 306 mode = val & OMAP_MUX_MODE7; 307 308 seq_printf(s, "name: %s.%s (0x%08lx/0x%03x = 0x%04x), b %s, t %s\n", 309 m->muxnames[0], m->muxnames[mode], 310 mux_phys + m->reg_offset, m->reg_offset, val, 311 m->balls[0] ? m->balls[0] : none, 312 m->balls[1] ? m->balls[1] : none); 313 seq_printf(s, "mode: "); 314 omap_mux_decode(s, val); 315 seq_printf(s, "\n"); 316 seq_printf(s, "signals: %s | %s | %s | %s | %s | %s | %s | %s\n", 317 m->muxnames[0] ? m->muxnames[0] : none, 318 m->muxnames[1] ? m->muxnames[1] : none, 319 m->muxnames[2] ? m->muxnames[2] : none, 320 m->muxnames[3] ? m->muxnames[3] : none, 321 m->muxnames[4] ? m->muxnames[4] : none, 322 m->muxnames[5] ? m->muxnames[5] : none, 323 m->muxnames[6] ? m->muxnames[6] : none, 324 m->muxnames[7] ? m->muxnames[7] : none); 325 326 return 0; 327} 328 329#define OMAP_MUX_MAX_ARG_CHAR 7 330 331static ssize_t omap_mux_dbg_signal_write(struct file *file, 332 const char __user *user_buf, 333 size_t count, loff_t *ppos) 334{ 335 char buf[OMAP_MUX_MAX_ARG_CHAR]; 336 struct seq_file *seqf; 337 struct omap_mux *m; 338 unsigned long val; 339 int buf_size, ret; 340 341 if (count > OMAP_MUX_MAX_ARG_CHAR) 342 return -EINVAL; 343 344 memset(buf, 0, sizeof(buf)); 345 buf_size = min(count, sizeof(buf) - 1); 346 347 if (copy_from_user(buf, user_buf, buf_size)) 348 return -EFAULT; 349 350 ret = strict_strtoul(buf, 0x10, &val); 351 if (ret < 0) 352 return ret; 353 354 if (val > 0xffff) 355 return -EINVAL; 356 357 seqf = file->private_data; 358 m = seqf->private; 359 360 omap_mux_write((u16)val, m->reg_offset); 361 *ppos += count; 362 363 return count; 364} 365 366static int omap_mux_dbg_signal_open(struct inode *inode, struct file *file) 367{ 368 return single_open(file, omap_mux_dbg_signal_show, inode->i_private); 369} 370 371static const struct file_operations omap_mux_dbg_signal_fops = { 372 .open = omap_mux_dbg_signal_open, 373 .read = seq_read, 374 .write = omap_mux_dbg_signal_write, 375 .llseek = seq_lseek, 376 .release = single_release, 377}; 378 379static struct dentry *mux_dbg_dir; 380 381static void __init omap_mux_dbg_init(void) 382{ 383 struct omap_mux_entry *e; 384 385 mux_dbg_dir = debugfs_create_dir("omap_mux", NULL); 386 if (!mux_dbg_dir) 387 return; 388 389 (void)debugfs_create_file("board", S_IRUGO, mux_dbg_dir, 390 NULL, &omap_mux_dbg_board_fops); 391 392 list_for_each_entry(e, &muxmodes, node) { 393 struct omap_mux *m = &e->mux; 394 395 (void)debugfs_create_file(m->muxnames[0], S_IWUGO, mux_dbg_dir, 396 m, &omap_mux_dbg_signal_fops); 397 } 398} 399 400#else 401static inline void omap_mux_dbg_init(void) 402{ 403} 404#endif /* CONFIG_DEBUG_FS */ 405 406static void __init omap_mux_free_names(struct omap_mux *m) 407{ 408 int i; 409 410 for (i = 0; i < OMAP_MUX_NR_MODES; i++) 411 kfree(m->muxnames[i]); 412 413#ifdef CONFIG_DEBUG_FS 414 for (i = 0; i < OMAP_MUX_NR_SIDES; i++) 415 kfree(m->balls[i]); 416#endif 417 418} 419 420/* Free all data except for GPIO pins unless CONFIG_DEBUG_FS is set */ 421static int __init omap_mux_late_init(void) 422{ 423 struct omap_mux_entry *e, *tmp; 424 425 list_for_each_entry_safe(e, tmp, &muxmodes, node) { 426 struct omap_mux *m = &e->mux; 427 u16 mode = omap_mux_read(m->reg_offset); 428 429 if (OMAP_MODE_GPIO(mode)) 430 continue; 431 432#ifndef CONFIG_DEBUG_FS 433 mutex_lock(&muxmode_mutex); 434 list_del(&e->node); 435 mutex_unlock(&muxmode_mutex); 436 omap_mux_free_names(m); 437 kfree(m); 438#endif 439 440 } 441 442 omap_mux_dbg_init(); 443 444 return 0; 445} 446late_initcall(omap_mux_late_init); 447 448static void __init omap_mux_package_fixup(struct omap_mux *p, 449 struct omap_mux *superset) 450{ 451 while (p->reg_offset != OMAP_MUX_TERMINATOR) { 452 struct omap_mux *s = superset; 453 int found = 0; 454 455 while (s->reg_offset != OMAP_MUX_TERMINATOR) { 456 if (s->reg_offset == p->reg_offset) { 457 *s = *p; 458 found++; 459 break; 460 } 461 s++; 462 } 463 if (!found) 464 printk(KERN_ERR "mux: Unknown entry offset 0x%x\n", 465 p->reg_offset); 466 p++; 467 } 468} 469 470#ifdef CONFIG_DEBUG_FS 471 472static void __init omap_mux_package_init_balls(struct omap_ball *b, 473 struct omap_mux *superset) 474{ 475 while (b->reg_offset != OMAP_MUX_TERMINATOR) { 476 struct omap_mux *s = superset; 477 int found = 0; 478 479 while (s->reg_offset != OMAP_MUX_TERMINATOR) { 480 if (s->reg_offset == b->reg_offset) { 481 s->balls[0] = b->balls[0]; 482 s->balls[1] = b->balls[1]; 483 found++; 484 break; 485 } 486 s++; 487 } 488 if (!found) 489 printk(KERN_ERR "mux: Unknown ball offset 0x%x\n", 490 b->reg_offset); 491 b++; 492 } 493} 494 495#else /* CONFIG_DEBUG_FS */ 496 497static inline void omap_mux_package_init_balls(struct omap_ball *b, 498 struct omap_mux *superset) 499{ 500} 501 502#endif /* CONFIG_DEBUG_FS */ 503 504static int __init omap_mux_setup(char *options) 505{ 506 if (!options) 507 return 0; 508 509 omap_mux_options = options; 510 511 return 1; 512} 513__setup("omap_mux=", omap_mux_setup); 514 515/* 516 * Note that the omap_mux=some.signal1=0x1234,some.signal2=0x1234 517 * cmdline options only override the bootloader values. 518 * During development, please enable CONFIG_DEBUG_FS, and use the 519 * signal specific entries under debugfs. 520 */ 521static void __init omap_mux_set_cmdline_signals(void) 522{ 523 char *options, *next_opt, *token; 524 525 if (!omap_mux_options) 526 return; 527 528 options = kmalloc(strlen(omap_mux_options) + 1, GFP_KERNEL); 529 if (!options) 530 return; 531 532 strcpy(options, omap_mux_options); 533 next_opt = options; 534 535 while ((token = strsep(&next_opt, ",")) != NULL) { 536 char *keyval, *name; 537 unsigned long val; 538 539 keyval = token; 540 name = strsep(&keyval, "="); 541 if (name) { 542 int res; 543 544 res = strict_strtoul(keyval, 0x10, &val); 545 if (res < 0) 546 continue; 547 548 omap_mux_init_signal(name, (u16)val); 549 } 550 } 551 552 kfree(options); 553} 554 555static int __init omap_mux_copy_names(struct omap_mux *src, 556 struct omap_mux *dst) 557{ 558 int i; 559 560 for (i = 0; i < OMAP_MUX_NR_MODES; i++) { 561 if (src->muxnames[i]) { 562 dst->muxnames[i] = 563 kmalloc(strlen(src->muxnames[i]) + 1, 564 GFP_KERNEL); 565 if (!dst->muxnames[i]) 566 goto free; 567 strcpy(dst->muxnames[i], src->muxnames[i]); 568 } 569 } 570 571#ifdef CONFIG_DEBUG_FS 572 for (i = 0; i < OMAP_MUX_NR_SIDES; i++) { 573 if (src->balls[i]) { 574 dst->balls[i] = 575 kmalloc(strlen(src->balls[i]) + 1, 576 GFP_KERNEL); 577 if (!dst->balls[i]) 578 goto free; 579 strcpy(dst->balls[i], src->balls[i]); 580 } 581 } 582#endif 583 584 return 0; 585 586free: 587 omap_mux_free_names(dst); 588 return -ENOMEM; 589 590} 591 592#endif /* CONFIG_OMAP_MUX */ 593 594static u16 omap_mux_get_by_gpio(int gpio) 595{ 596 struct omap_mux_entry *e; 597 u16 offset = OMAP_MUX_TERMINATOR; 598 599 list_for_each_entry(e, &muxmodes, node) { 600 struct omap_mux *m = &e->mux; 601 if (m->gpio == gpio) { 602 offset = m->reg_offset; 603 break; 604 } 605 } 606 607 return offset; 608} 609 610/* Needed for dynamic muxing of GPIO pins for off-idle */ 611u16 omap_mux_get_gpio(int gpio) 612{ 613 u16 offset; 614 615 offset = omap_mux_get_by_gpio(gpio); 616 if (offset == OMAP_MUX_TERMINATOR) { 617 printk(KERN_ERR "mux: Could not get gpio%i\n", gpio); 618 return offset; 619 } 620 621 return omap_mux_read(offset); 622} 623 624/* Needed for dynamic muxing of GPIO pins for off-idle */ 625void omap_mux_set_gpio(u16 val, int gpio) 626{ 627 u16 offset; 628 629 offset = omap_mux_get_by_gpio(gpio); 630 if (offset == OMAP_MUX_TERMINATOR) { 631 printk(KERN_ERR "mux: Could not set gpio%i\n", gpio); 632 return; 633 } 634 635 omap_mux_write(val, offset); 636} 637 638static struct omap_mux * __init omap_mux_list_add(struct omap_mux *src) 639{ 640 struct omap_mux_entry *entry; 641 struct omap_mux *m; 642 643 entry = kzalloc(sizeof(struct omap_mux_entry), GFP_KERNEL); 644 if (!entry) 645 return NULL; 646 647 m = &entry->mux; 648 memcpy(m, src, sizeof(struct omap_mux_entry)); 649 650#ifdef CONFIG_OMAP_MUX 651 if (omap_mux_copy_names(src, m)) { 652 kfree(entry); 653 return NULL; 654 } 655#endif 656 657 mutex_lock(&muxmode_mutex); 658 list_add_tail(&entry->node, &muxmodes); 659 mutex_unlock(&muxmode_mutex); 660 661 return m; 662} 663 664/* 665 * Note if CONFIG_OMAP_MUX is not selected, we will only initialize 666 * the GPIO to mux offset mapping that is needed for dynamic muxing 667 * of GPIO pins for off-idle. 668 */ 669static void __init omap_mux_init_list(struct omap_mux *superset) 670{ 671 while (superset->reg_offset != OMAP_MUX_TERMINATOR) { 672 struct omap_mux *entry; 673 674#ifdef CONFIG_OMAP_MUX 675 if (!superset->muxnames || !superset->muxnames[0]) { 676 superset++; 677 continue; 678 } 679#else 680 /* Skip pins that are not muxed as GPIO by bootloader */ 681 if (!OMAP_MODE_GPIO(omap_mux_read(superset->reg_offset))) { 682 superset++; 683 continue; 684 } 685#endif 686 687 entry = omap_mux_list_add(superset); 688 if (!entry) { 689 printk(KERN_ERR "mux: Could not add entry\n"); 690 return; 691 } 692 superset++; 693 } 694} 695 696#ifdef CONFIG_OMAP_MUX 697 698static void omap_mux_init_package(struct omap_mux *superset, 699 struct omap_mux *package_subset, 700 struct omap_ball *package_balls) 701{ 702 if (package_subset) 703 omap_mux_package_fixup(package_subset, superset); 704 if (package_balls) 705 omap_mux_package_init_balls(package_balls, superset); 706} 707 708static void omap_mux_init_signals(struct omap_board_mux *board_mux) 709{ 710 omap_mux_set_cmdline_signals(); 711 omap_mux_write_array(board_mux); 712} 713 714#else 715 716static void omap_mux_init_package(struct omap_mux *superset, 717 struct omap_mux *package_subset, 718 struct omap_ball *package_balls) 719{ 720} 721 722static void omap_mux_init_signals(struct omap_board_mux *board_mux) 723{ 724} 725 726#endif 727 728int __init omap_mux_init(u32 mux_pbase, u32 mux_size, 729 struct omap_mux *superset, 730 struct omap_mux *package_subset, 731 struct omap_board_mux *board_mux, 732 struct omap_ball *package_balls) 733{ 734 if (mux_base) 735 return -EBUSY; 736 737 mux_phys = mux_pbase; 738 mux_base = ioremap(mux_pbase, mux_size); 739 if (!mux_base) { 740 printk(KERN_ERR "mux: Could not ioremap\n"); 741 return -ENODEV; 742 } 743 744 if (cpu_is_omap24xx()) 745 omap_mux_flags = MUXABLE_GPIO_MODE3; 746 747 omap_mux_init_package(superset, package_subset, package_balls); 748 omap_mux_init_list(superset); 749 omap_mux_init_signals(board_mux); 750 751 return 0; 752} 753 754