mux.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * linux/arch/arm/plat-omap/mux.c
  3. *
  4. * Utility to set the Omap MUX and PULL_DWN registers from a table in mux.h
  5. *
  6. * Copyright (C) 2003 Nokia Corporation
  7. *
  8. * Written by Tony Lindgren <tony.lindgren@nokia.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. *
  24. */
  25. #include <linux/config.h>
  26. #include <linux/module.h>
  27. #include <linux/init.h>
  28. #include <asm/system.h>
  29. #include <asm/io.h>
  30. #include <linux/spinlock.h>
  31. #define __MUX_C__
  32. #include <asm/arch/mux.h>
  33. #ifdef CONFIG_OMAP_MUX
  34. /*
  35. * Sets the Omap MUX and PULL_DWN registers based on the table
  36. */
  37. int __init_or_module
  38. omap_cfg_reg(const reg_cfg_t reg_cfg)
  39. {
  40. static DEFINE_SPINLOCK(mux_spin_lock);
  41. unsigned long flags;
  42. reg_cfg_set *cfg;
  43. unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0,
  44. pull_orig = 0, pull = 0;
  45. unsigned int mask, warn = 0;
  46. if (cpu_is_omap7xx())
  47. return 0;
  48. if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) {
  49. printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg);
  50. return -EINVAL;
  51. }
  52. cfg = (reg_cfg_set *)&reg_cfg_table[reg_cfg];
  53. /* Check the mux register in question */
  54. if (cfg->mux_reg) {
  55. unsigned tmp1, tmp2;
  56. spin_lock_irqsave(&mux_spin_lock, flags);
  57. reg_orig = omap_readl(cfg->mux_reg);
  58. /* The mux registers always seem to be 3 bits long */
  59. mask = (0x7 << cfg->mask_offset);
  60. tmp1 = reg_orig & mask;
  61. reg = reg_orig & ~mask;
  62. tmp2 = (cfg->mask << cfg->mask_offset);
  63. reg |= tmp2;
  64. if (tmp1 != tmp2)
  65. warn = 1;
  66. omap_writel(reg, cfg->mux_reg);
  67. spin_unlock_irqrestore(&mux_spin_lock, flags);
  68. }
  69. /* Check for pull up or pull down selection on 1610 */
  70. if (!cpu_is_omap1510()) {
  71. if (cfg->pu_pd_reg && cfg->pull_val) {
  72. spin_lock_irqsave(&mux_spin_lock, flags);
  73. pu_pd_orig = omap_readl(cfg->pu_pd_reg);
  74. mask = 1 << cfg->pull_bit;
  75. if (cfg->pu_pd_val) {
  76. if (!(pu_pd_orig & mask))
  77. warn = 1;
  78. /* Use pull up */
  79. pu_pd = pu_pd_orig | mask;
  80. } else {
  81. if (pu_pd_orig & mask)
  82. warn = 1;
  83. /* Use pull down */
  84. pu_pd = pu_pd_orig & ~mask;
  85. }
  86. omap_writel(pu_pd, cfg->pu_pd_reg);
  87. spin_unlock_irqrestore(&mux_spin_lock, flags);
  88. }
  89. }
  90. /* Check for an associated pull down register */
  91. if (cfg->pull_reg) {
  92. spin_lock_irqsave(&mux_spin_lock, flags);
  93. pull_orig = omap_readl(cfg->pull_reg);
  94. mask = 1 << cfg->pull_bit;
  95. if (cfg->pull_val) {
  96. if (pull_orig & mask)
  97. warn = 1;
  98. /* Low bit = pull enabled */
  99. pull = pull_orig & ~mask;
  100. } else {
  101. if (!(pull_orig & mask))
  102. warn = 1;
  103. /* High bit = pull disabled */
  104. pull = pull_orig | mask;
  105. }
  106. omap_writel(pull, cfg->pull_reg);
  107. spin_unlock_irqrestore(&mux_spin_lock, flags);
  108. }
  109. if (warn) {
  110. #ifdef CONFIG_OMAP_MUX_WARNINGS
  111. printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
  112. #endif
  113. }
  114. #ifdef CONFIG_OMAP_MUX_DEBUG
  115. if (cfg->debug || warn) {
  116. printk("MUX: Setting register %s\n", cfg->name);
  117. printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
  118. cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
  119. if (!cpu_is_omap1510()) {
  120. if (cfg->pu_pd_reg && cfg->pull_val) {
  121. printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
  122. cfg->pu_pd_name, cfg->pu_pd_reg,
  123. pu_pd_orig, pu_pd);
  124. }
  125. }
  126. if (cfg->pull_reg)
  127. printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
  128. cfg->pull_name, cfg->pull_reg, pull_orig, pull);
  129. }
  130. #endif
  131. #ifdef CONFIG_OMAP_MUX_ERRORS
  132. return warn ? -ETXTBSY : 0;
  133. #else
  134. return 0;
  135. #endif
  136. }
  137. EXPORT_SYMBOL(omap_cfg_reg);
  138. #endif /* CONFIG_OMAP_MUX */