pinmux.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Allocator for I/O pins. All pins are allocated to GPIO at bootup.
  3. * Unassigned pins and GPIO pins can be allocated to a fixed interface
  4. * or the I/O processor instead.
  5. *
  6. * Copyright (c) 2004 Axis Communications AB.
  7. */
  8. #include <linux/init.h>
  9. #include <linux/errno.h>
  10. #include <linux/kernel.h>
  11. #include <linux/string.h>
  12. #include <linux/spinlock.h>
  13. #include <asm/arch/hwregs/reg_map.h>
  14. #include <asm/arch/hwregs/reg_rdwr.h>
  15. #include <asm/arch/pinmux.h>
  16. #include <asm/arch/hwregs/pinmux_defs.h>
  17. #undef DEBUG
  18. #define PORT_PINS 18
  19. #define PORTS 4
  20. static char pins[PORTS][PORT_PINS];
  21. static DEFINE_SPINLOCK(pinmux_lock);
  22. static void crisv32_pinmux_set(int port);
  23. int
  24. crisv32_pinmux_init(void)
  25. {
  26. static int initialized = 0;
  27. if (!initialized) {
  28. reg_pinmux_rw_pa pa = REG_RD(pinmux, regi_pinmux, rw_pa);
  29. initialized = 1;
  30. pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 =
  31. pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes;
  32. REG_WR(pinmux, regi_pinmux, rw_pa, pa);
  33. crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio);
  34. crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio);
  35. crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio);
  36. crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio);
  37. }
  38. return 0;
  39. }
  40. int
  41. crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
  42. {
  43. int i;
  44. unsigned long flags;
  45. crisv32_pinmux_init();
  46. if (port > PORTS)
  47. return -EINVAL;
  48. spin_lock_irqsave(&pinmux_lock, flags);
  49. for (i = first_pin; i <= last_pin; i++)
  50. {
  51. if ((pins[port][i] != pinmux_none) && (pins[port][i] != pinmux_gpio) &&
  52. (pins[port][i] != mode))
  53. {
  54. spin_unlock_irqrestore(&pinmux_lock, flags);
  55. #ifdef DEBUG
  56. panic("Pinmux alloc failed!\n");
  57. #endif
  58. return -EPERM;
  59. }
  60. }
  61. for (i = first_pin; i <= last_pin; i++)
  62. pins[port][i] = mode;
  63. crisv32_pinmux_set(port);
  64. spin_unlock_irqrestore(&pinmux_lock, flags);
  65. return 0;
  66. }
  67. int
  68. crisv32_pinmux_alloc_fixed(enum fixed_function function)
  69. {
  70. int ret = -EINVAL;
  71. char saved[sizeof pins];
  72. unsigned long flags;
  73. spin_lock_irqsave(&pinmux_lock, flags);
  74. /* Save internal data for recovery */
  75. memcpy(saved, pins, sizeof pins);
  76. reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
  77. switch(function)
  78. {
  79. case pinmux_ser1:
  80. ret = crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed);
  81. hwprot.ser1 = regk_pinmux_yes;
  82. break;
  83. case pinmux_ser2:
  84. ret = crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed);
  85. hwprot.ser2 = regk_pinmux_yes;
  86. break;
  87. case pinmux_ser3:
  88. ret = crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed);
  89. hwprot.ser3 = regk_pinmux_yes;
  90. break;
  91. case pinmux_sser0:
  92. ret = crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed);
  93. ret |= crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
  94. hwprot.sser0 = regk_pinmux_yes;
  95. break;
  96. case pinmux_sser1:
  97. ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
  98. hwprot.sser1 = regk_pinmux_yes;
  99. break;
  100. case pinmux_ata0:
  101. ret = crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed);
  102. ret |= crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed);
  103. hwprot.ata0 = regk_pinmux_yes;
  104. break;
  105. case pinmux_ata1:
  106. ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
  107. ret |= crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed);
  108. hwprot.ata1 = regk_pinmux_yes;
  109. break;
  110. case pinmux_ata2:
  111. ret = crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed);
  112. ret |= crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed);
  113. hwprot.ata2 = regk_pinmux_yes;
  114. break;
  115. case pinmux_ata3:
  116. ret = crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed);
  117. ret |= crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed);
  118. hwprot.ata2 = regk_pinmux_yes;
  119. break;
  120. case pinmux_ata:
  121. ret = crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed);
  122. ret |= crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed);
  123. hwprot.ata = regk_pinmux_yes;
  124. break;
  125. case pinmux_eth1:
  126. ret = crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed);
  127. hwprot.eth1 = regk_pinmux_yes;
  128. hwprot.eth1_mgm = regk_pinmux_yes;
  129. break;
  130. case pinmux_timer:
  131. ret = crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
  132. hwprot.timer = regk_pinmux_yes;
  133. spin_unlock_irqrestore(&pinmux_lock, flags);
  134. return ret;
  135. }
  136. if (!ret)
  137. REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
  138. else
  139. memcpy(pins, saved, sizeof pins);
  140. spin_unlock_irqrestore(&pinmux_lock, flags);
  141. return ret;
  142. }
  143. void
  144. crisv32_pinmux_set(int port)
  145. {
  146. int i;
  147. int gpio_val = 0;
  148. int iop_val = 0;
  149. for (i = 0; i < PORT_PINS; i++)
  150. {
  151. if (pins[port][i] == pinmux_gpio)
  152. gpio_val |= (1 << i);
  153. else if (pins[port][i] == pinmux_iop)
  154. iop_val |= (1 << i);
  155. }
  156. REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_gio + 8*port, gpio_val);
  157. REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_iop + 8*port, iop_val);
  158. #ifdef DEBUG
  159. crisv32_pinmux_dump();
  160. #endif
  161. }
  162. int
  163. crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
  164. {
  165. int i;
  166. unsigned long flags;
  167. crisv32_pinmux_init();
  168. if (port > PORTS)
  169. return -EINVAL;
  170. spin_lock_irqsave(&pinmux_lock, flags);
  171. for (i = first_pin; i <= last_pin; i++)
  172. pins[port][i] = pinmux_none;
  173. crisv32_pinmux_set(port);
  174. spin_unlock_irqrestore(&pinmux_lock, flags);
  175. return 0;
  176. }
  177. void
  178. crisv32_pinmux_dump(void)
  179. {
  180. int i, j;
  181. crisv32_pinmux_init();
  182. for (i = 0; i < PORTS; i++)
  183. {
  184. printk("Port %c\n", 'B'+i);
  185. for (j = 0; j < PORT_PINS; j++)
  186. printk(" Pin %d = %d\n", j, pins[i][j]);
  187. }
  188. }
  189. __initcall(crisv32_pinmux_init);