iomux-v1.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. * arch/arm/plat-mxc/iomux-v1.c
  3. *
  4. * Copyright (C) 2004 Sascha Hauer, Synertronixx GmbH
  5. * Copyright (C) 2009 Uwe Kleine-Koenig, Pengutronix
  6. *
  7. * Common code for i.MX1, i.MX21 and i.MX27
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software Foundation, Inc.,
  21. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  22. */
  23. #include <linux/errno.h>
  24. #include <linux/init.h>
  25. #include <linux/kernel.h>
  26. #include <linux/module.h>
  27. #include <linux/string.h>
  28. #include <linux/gpio.h>
  29. #include <mach/hardware.h>
  30. #include <asm/mach/map.h>
  31. #include <mach/iomux-v1.h>
  32. static void __iomem *imx_iomuxv1_baseaddr;
  33. static unsigned imx_iomuxv1_numports;
  34. static inline unsigned long imx_iomuxv1_readl(unsigned offset)
  35. {
  36. return __raw_readl(imx_iomuxv1_baseaddr + offset);
  37. }
  38. static inline void imx_iomuxv1_writel(unsigned long val, unsigned offset)
  39. {
  40. __raw_writel(val, imx_iomuxv1_baseaddr + offset);
  41. }
  42. static inline void imx_iomuxv1_rmwl(unsigned offset,
  43. unsigned long mask, unsigned long value)
  44. {
  45. unsigned long reg = imx_iomuxv1_readl(offset);
  46. reg &= ~mask;
  47. reg |= value;
  48. imx_iomuxv1_writel(reg, offset);
  49. }
  50. static inline void imx_iomuxv1_set_puen(
  51. unsigned int port, unsigned int pin, int on)
  52. {
  53. unsigned long mask = 1 << pin;
  54. imx_iomuxv1_rmwl(MXC_PUEN(port), mask, on ? mask : 0);
  55. }
  56. static inline void imx_iomuxv1_set_ddir(
  57. unsigned int port, unsigned int pin, int out)
  58. {
  59. unsigned long mask = 1 << pin;
  60. imx_iomuxv1_rmwl(MXC_DDIR(port), mask, out ? mask : 0);
  61. }
  62. static inline void imx_iomuxv1_set_gpr(
  63. unsigned int port, unsigned int pin, int af)
  64. {
  65. unsigned long mask = 1 << pin;
  66. imx_iomuxv1_rmwl(MXC_GPR(port), mask, af ? mask : 0);
  67. }
  68. static inline void imx_iomuxv1_set_gius(
  69. unsigned int port, unsigned int pin, int inuse)
  70. {
  71. unsigned long mask = 1 << pin;
  72. imx_iomuxv1_rmwl(MXC_GIUS(port), mask, inuse ? mask : 0);
  73. }
  74. static inline void imx_iomuxv1_set_ocr(
  75. unsigned int port, unsigned int pin, unsigned int ocr)
  76. {
  77. unsigned long shift = (pin & 0xf) << 1;
  78. unsigned long mask = 3 << shift;
  79. unsigned long value = ocr << shift;
  80. unsigned long offset = pin < 16 ? MXC_OCR1(port) : MXC_OCR2(port);
  81. imx_iomuxv1_rmwl(offset, mask, value);
  82. }
  83. static inline void imx_iomuxv1_set_iconfa(
  84. unsigned int port, unsigned int pin, unsigned int aout)
  85. {
  86. unsigned long shift = (pin & 0xf) << 1;
  87. unsigned long mask = 3 << shift;
  88. unsigned long value = aout << shift;
  89. unsigned long offset = pin < 16 ? MXC_ICONFA1(port) : MXC_ICONFA2(port);
  90. imx_iomuxv1_rmwl(offset, mask, value);
  91. }
  92. static inline void imx_iomuxv1_set_iconfb(
  93. unsigned int port, unsigned int pin, unsigned int bout)
  94. {
  95. unsigned long shift = (pin & 0xf) << 1;
  96. unsigned long mask = 3 << shift;
  97. unsigned long value = bout << shift;
  98. unsigned long offset = pin < 16 ? MXC_ICONFB1(port) : MXC_ICONFB2(port);
  99. imx_iomuxv1_rmwl(offset, mask, value);
  100. }
  101. int mxc_gpio_mode(int gpio_mode)
  102. {
  103. unsigned int pin = gpio_mode & GPIO_PIN_MASK;
  104. unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
  105. unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
  106. unsigned int aout = (gpio_mode >> GPIO_AOUT_SHIFT) & 3;
  107. unsigned int bout = (gpio_mode >> GPIO_BOUT_SHIFT) & 3;
  108. if (port >= imx_iomuxv1_numports)
  109. return -EINVAL;
  110. /* Pullup enable */
  111. imx_iomuxv1_set_puen(port, pin, gpio_mode & GPIO_PUEN);
  112. /* Data direction */
  113. imx_iomuxv1_set_ddir(port, pin, gpio_mode & GPIO_OUT);
  114. /* Primary / alternate function */
  115. imx_iomuxv1_set_gpr(port, pin, gpio_mode & GPIO_AF);
  116. /* use as gpio? */
  117. imx_iomuxv1_set_gius(port, pin, !(gpio_mode & (GPIO_PF | GPIO_AF)));
  118. imx_iomuxv1_set_ocr(port, pin, ocr);
  119. imx_iomuxv1_set_iconfa(port, pin, aout);
  120. imx_iomuxv1_set_iconfb(port, pin, bout);
  121. return 0;
  122. }
  123. EXPORT_SYMBOL(mxc_gpio_mode);
  124. static int imx_iomuxv1_setup_multiple(const int *list, unsigned count)
  125. {
  126. size_t i;
  127. int ret;
  128. for (i = 0; i < count; ++i) {
  129. ret = mxc_gpio_mode(list[i]);
  130. if (ret)
  131. return ret;
  132. }
  133. return ret;
  134. }
  135. int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
  136. const char *label)
  137. {
  138. size_t i;
  139. int ret;
  140. for (i = 0; i < count; ++i) {
  141. unsigned gpio = pin_list[i] & (GPIO_PIN_MASK | GPIO_PORT_MASK);
  142. ret = gpio_request(gpio, label);
  143. if (ret)
  144. goto err_gpio_request;
  145. }
  146. ret = imx_iomuxv1_setup_multiple(pin_list, count);
  147. if (ret)
  148. goto err_setup;
  149. return 0;
  150. err_setup:
  151. BUG_ON(i != count);
  152. err_gpio_request:
  153. mxc_gpio_release_multiple_pins(pin_list, i);
  154. return ret;
  155. }
  156. EXPORT_SYMBOL(mxc_gpio_setup_multiple_pins);
  157. void mxc_gpio_release_multiple_pins(const int *pin_list, int count)
  158. {
  159. size_t i;
  160. for (i = 0; i < count; ++i) {
  161. unsigned gpio = pin_list[i] & (GPIO_PIN_MASK | GPIO_PORT_MASK);
  162. gpio_free(gpio);
  163. }
  164. }
  165. EXPORT_SYMBOL(mxc_gpio_release_multiple_pins);
  166. int __init imx_iomuxv1_init(void __iomem *base, int numports)
  167. {
  168. imx_iomuxv1_baseaddr = base;
  169. imx_iomuxv1_numports = numports;
  170. return 0;
  171. }