pinmux.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  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) 2005-2007 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 <hwregs/reg_map.h>
  14. #include <hwregs/reg_rdwr.h>
  15. #include <pinmux.h>
  16. #include <hwregs/pinmux_defs.h>
  17. #include <hwregs/clkgen_defs.h>
  18. #undef DEBUG
  19. #define PINS 80
  20. #define PORT_PINS 32
  21. #define PORTS 3
  22. static char pins[PINS];
  23. static DEFINE_SPINLOCK(pinmux_lock);
  24. static void crisv32_pinmux_set(int port);
  25. int
  26. crisv32_pinmux_init(void)
  27. {
  28. static int initialized;
  29. if (!initialized) {
  30. initialized = 1;
  31. REG_WR_INT(pinmux, regi_pinmux, rw_hwprot, 0);
  32. crisv32_pinmux_alloc(PORT_A, 0, 31, pinmux_gpio);
  33. crisv32_pinmux_alloc(PORT_B, 0, 31, pinmux_gpio);
  34. crisv32_pinmux_alloc(PORT_C, 0, 15, pinmux_gpio);
  35. }
  36. return 0;
  37. }
  38. int
  39. crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
  40. {
  41. int i;
  42. unsigned long flags;
  43. crisv32_pinmux_init();
  44. if (port >= PORTS)
  45. return -EINVAL;
  46. spin_lock_irqsave(&pinmux_lock, flags);
  47. for (i = first_pin; i <= last_pin; i++) {
  48. if ((pins[port * PORT_PINS + i] != pinmux_none) &&
  49. (pins[port * PORT_PINS + i] != pinmux_gpio) &&
  50. (pins[port * PORT_PINS + i] != mode)) {
  51. spin_unlock_irqrestore(&pinmux_lock, flags);
  52. #ifdef DEBUG
  53. panic("Pinmux alloc failed!\n");
  54. #endif
  55. return -EPERM;
  56. }
  57. }
  58. for (i = first_pin; i <= last_pin; i++)
  59. pins[port * PORT_PINS + i] = mode;
  60. crisv32_pinmux_set(port);
  61. spin_unlock_irqrestore(&pinmux_lock, flags);
  62. return 0;
  63. }
  64. int
  65. crisv32_pinmux_alloc_fixed(enum fixed_function function)
  66. {
  67. int ret = -EINVAL;
  68. char saved[sizeof pins];
  69. unsigned long flags;
  70. spin_lock_irqsave(&pinmux_lock, flags);
  71. /* Save internal data for recovery */
  72. memcpy(saved, pins, sizeof pins);
  73. crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
  74. reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
  75. reg_clkgen_rw_clk_ctrl clk_ctrl = REG_RD(clkgen, regi_clkgen,
  76. rw_clk_ctrl);
  77. switch (function) {
  78. case pinmux_eth:
  79. clk_ctrl.eth = regk_clkgen_yes;
  80. clk_ctrl.dma0_1_eth = regk_clkgen_yes;
  81. ret = crisv32_pinmux_alloc(PORT_B, 8, 23, pinmux_fixed);
  82. ret |= crisv32_pinmux_alloc(PORT_B, 24, 25, pinmux_fixed);
  83. hwprot.eth = hwprot.eth_mdio = regk_pinmux_yes;
  84. break;
  85. case pinmux_geth:
  86. ret = crisv32_pinmux_alloc(PORT_B, 0, 7, pinmux_fixed);
  87. hwprot.geth = regk_pinmux_yes;
  88. break;
  89. case pinmux_tg_cmos:
  90. clk_ctrl.ccd_tg_100 = clk_ctrl.ccd_tg_200 = regk_clkgen_yes;
  91. ret = crisv32_pinmux_alloc(PORT_B, 27, 29, pinmux_fixed);
  92. hwprot.tg_clk = regk_pinmux_yes;
  93. break;
  94. case pinmux_tg_ccd:
  95. clk_ctrl.ccd_tg_100 = clk_ctrl.ccd_tg_200 = regk_clkgen_yes;
  96. ret = crisv32_pinmux_alloc(PORT_B, 27, 31, pinmux_fixed);
  97. ret |= crisv32_pinmux_alloc(PORT_C, 0, 15, pinmux_fixed);
  98. hwprot.tg = hwprot.tg_clk = regk_pinmux_yes;
  99. break;
  100. case pinmux_vout:
  101. clk_ctrl.strdma0_2_video = regk_clkgen_yes;
  102. ret = crisv32_pinmux_alloc(PORT_A, 8, 18, pinmux_fixed);
  103. hwprot.vout = hwprot.vout_sync = regk_pinmux_yes;
  104. break;
  105. case pinmux_ser1:
  106. clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
  107. ret = crisv32_pinmux_alloc(PORT_A, 24, 25, pinmux_fixed);
  108. hwprot.ser1 = regk_pinmux_yes;
  109. break;
  110. case pinmux_ser2:
  111. clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
  112. ret = crisv32_pinmux_alloc(PORT_A, 26, 27, pinmux_fixed);
  113. hwprot.ser2 = regk_pinmux_yes;
  114. break;
  115. case pinmux_ser3:
  116. clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
  117. ret = crisv32_pinmux_alloc(PORT_A, 28, 29, pinmux_fixed);
  118. hwprot.ser3 = regk_pinmux_yes;
  119. break;
  120. case pinmux_ser4:
  121. clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
  122. ret = crisv32_pinmux_alloc(PORT_A, 30, 31, pinmux_fixed);
  123. hwprot.ser4 = regk_pinmux_yes;
  124. break;
  125. case pinmux_sser:
  126. clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
  127. ret = crisv32_pinmux_alloc(PORT_A, 19, 23, pinmux_fixed);
  128. hwprot.sser = regk_pinmux_yes;
  129. break;
  130. case pinmux_pio:
  131. hwprot.pio = regk_pinmux_yes;
  132. ret = 0;
  133. break;
  134. case pinmux_pwm0:
  135. ret = crisv32_pinmux_alloc(PORT_A, 30, 30, pinmux_fixed);
  136. hwprot.pwm0 = regk_pinmux_yes;
  137. break;
  138. case pinmux_pwm1:
  139. ret = crisv32_pinmux_alloc(PORT_A, 31, 31, pinmux_fixed);
  140. hwprot.pwm1 = regk_pinmux_yes;
  141. break;
  142. case pinmux_pwm2:
  143. ret = crisv32_pinmux_alloc(PORT_B, 26, 26, pinmux_fixed);
  144. hwprot.pwm2 = regk_pinmux_yes;
  145. break;
  146. case pinmux_i2c0:
  147. ret = crisv32_pinmux_alloc(PORT_A, 0, 1, pinmux_fixed);
  148. hwprot.i2c0 = regk_pinmux_yes;
  149. break;
  150. case pinmux_i2c1:
  151. ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
  152. hwprot.i2c1 = regk_pinmux_yes;
  153. break;
  154. case pinmux_i2c1_3wire:
  155. ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
  156. ret |= crisv32_pinmux_alloc(PORT_A, 7, 7, pinmux_fixed);
  157. hwprot.i2c1 = hwprot.i2c1_sen = regk_pinmux_yes;
  158. break;
  159. case pinmux_i2c1_sda1:
  160. ret = crisv32_pinmux_alloc(PORT_A, 2, 4, pinmux_fixed);
  161. hwprot.i2c1 = hwprot.i2c1_sda1 = regk_pinmux_yes;
  162. break;
  163. case pinmux_i2c1_sda2:
  164. ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
  165. ret |= crisv32_pinmux_alloc(PORT_A, 5, 5, pinmux_fixed);
  166. hwprot.i2c1 = hwprot.i2c1_sda2 = regk_pinmux_yes;
  167. break;
  168. case pinmux_i2c1_sda3:
  169. ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
  170. ret |= crisv32_pinmux_alloc(PORT_A, 6, 6, pinmux_fixed);
  171. hwprot.i2c1 = hwprot.i2c1_sda3 = regk_pinmux_yes;
  172. break;
  173. default:
  174. ret = -EINVAL;
  175. break;
  176. }
  177. if (!ret) {
  178. REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
  179. REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl);
  180. } else
  181. memcpy(pins, saved, sizeof pins);
  182. spin_unlock_irqrestore(&pinmux_lock, flags);
  183. return ret;
  184. }
  185. void
  186. crisv32_pinmux_set(int port)
  187. {
  188. int i;
  189. int gpio_val = 0;
  190. int iop_val = 0;
  191. int pin = port * PORT_PINS;
  192. for (i = 0; (i < PORT_PINS) && (pin < PINS); i++, pin++) {
  193. if (pins[pin] == pinmux_gpio)
  194. gpio_val |= (1 << i);
  195. else if (pins[pin] == pinmux_iop)
  196. iop_val |= (1 << i);
  197. }
  198. REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_gio_pa + 4 * port,
  199. gpio_val);
  200. REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_iop_pa + 4 * port,
  201. iop_val);
  202. #ifdef DEBUG
  203. crisv32_pinmux_dump();
  204. #endif
  205. }
  206. int
  207. crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
  208. {
  209. int i;
  210. unsigned long flags;
  211. crisv32_pinmux_init();
  212. if (port > PORTS)
  213. return -EINVAL;
  214. spin_lock_irqsave(&pinmux_lock, flags);
  215. for (i = first_pin; i <= last_pin; i++)
  216. pins[port * PORT_PINS + i] = pinmux_none;
  217. crisv32_pinmux_set(port);
  218. spin_unlock_irqrestore(&pinmux_lock, flags);
  219. return 0;
  220. }
  221. int
  222. crisv32_pinmux_dealloc_fixed(enum fixed_function function)
  223. {
  224. int ret = -EINVAL;
  225. char saved[sizeof pins];
  226. unsigned long flags;
  227. spin_lock_irqsave(&pinmux_lock, flags);
  228. /* Save internal data for recovery */
  229. memcpy(saved, pins, sizeof pins);
  230. crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
  231. reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
  232. switch (function) {
  233. case pinmux_eth:
  234. ret = crisv32_pinmux_dealloc(PORT_B, 8, 23);
  235. ret |= crisv32_pinmux_dealloc(PORT_B, 24, 25);
  236. ret |= crisv32_pinmux_dealloc(PORT_B, 0, 7);
  237. hwprot.eth = hwprot.eth_mdio = hwprot.geth = regk_pinmux_no;
  238. break;
  239. case pinmux_tg_cmos:
  240. ret = crisv32_pinmux_dealloc(PORT_B, 27, 29);
  241. hwprot.tg_clk = regk_pinmux_no;
  242. break;
  243. case pinmux_tg_ccd:
  244. ret = crisv32_pinmux_dealloc(PORT_B, 27, 31);
  245. ret |= crisv32_pinmux_dealloc(PORT_C, 0, 15);
  246. hwprot.tg = hwprot.tg_clk = regk_pinmux_no;
  247. break;
  248. case pinmux_vout:
  249. ret = crisv32_pinmux_dealloc(PORT_A, 8, 18);
  250. hwprot.vout = hwprot.vout_sync = regk_pinmux_no;
  251. break;
  252. case pinmux_ser1:
  253. ret = crisv32_pinmux_dealloc(PORT_A, 24, 25);
  254. hwprot.ser1 = regk_pinmux_no;
  255. break;
  256. case pinmux_ser2:
  257. ret = crisv32_pinmux_dealloc(PORT_A, 26, 27);
  258. hwprot.ser2 = regk_pinmux_no;
  259. break;
  260. case pinmux_ser3:
  261. ret = crisv32_pinmux_dealloc(PORT_A, 28, 29);
  262. hwprot.ser3 = regk_pinmux_no;
  263. break;
  264. case pinmux_ser4:
  265. ret = crisv32_pinmux_dealloc(PORT_A, 30, 31);
  266. hwprot.ser4 = regk_pinmux_no;
  267. break;
  268. case pinmux_sser:
  269. ret = crisv32_pinmux_dealloc(PORT_A, 19, 23);
  270. hwprot.sser = regk_pinmux_no;
  271. break;
  272. case pinmux_pwm0:
  273. ret = crisv32_pinmux_dealloc(PORT_A, 30, 30);
  274. hwprot.pwm0 = regk_pinmux_no;
  275. break;
  276. case pinmux_pwm1:
  277. ret = crisv32_pinmux_dealloc(PORT_A, 31, 31);
  278. hwprot.pwm1 = regk_pinmux_no;
  279. break;
  280. case pinmux_pwm2:
  281. ret = crisv32_pinmux_dealloc(PORT_B, 26, 26);
  282. hwprot.pwm2 = regk_pinmux_no;
  283. break;
  284. case pinmux_i2c0:
  285. ret = crisv32_pinmux_dealloc(PORT_A, 0, 1);
  286. hwprot.i2c0 = regk_pinmux_no;
  287. break;
  288. case pinmux_i2c1:
  289. ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
  290. hwprot.i2c1 = regk_pinmux_no;
  291. break;
  292. case pinmux_i2c1_3wire:
  293. ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
  294. ret |= crisv32_pinmux_dealloc(PORT_A, 7, 7);
  295. hwprot.i2c1 = hwprot.i2c1_sen = regk_pinmux_no;
  296. break;
  297. case pinmux_i2c1_sda1:
  298. ret = crisv32_pinmux_dealloc(PORT_A, 2, 4);
  299. hwprot.i2c1_sda1 = regk_pinmux_no;
  300. break;
  301. case pinmux_i2c1_sda2:
  302. ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
  303. ret |= crisv32_pinmux_dealloc(PORT_A, 5, 5);
  304. hwprot.i2c1_sda2 = regk_pinmux_no;
  305. break;
  306. case pinmux_i2c1_sda3:
  307. ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
  308. ret |= crisv32_pinmux_dealloc(PORT_A, 6, 6);
  309. hwprot.i2c1_sda3 = regk_pinmux_no;
  310. break;
  311. default:
  312. ret = -EINVAL;
  313. break;
  314. }
  315. if (!ret)
  316. REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
  317. else
  318. memcpy(pins, saved, sizeof pins);
  319. spin_unlock_irqrestore(&pinmux_lock, flags);
  320. return ret;
  321. }
  322. void
  323. crisv32_pinmux_dump(void)
  324. {
  325. int i, j;
  326. int pin = 0;
  327. crisv32_pinmux_init();
  328. for (i = 0; i < PORTS; i++) {
  329. pin++;
  330. printk(KERN_DEBUG "Port %c\n", 'A'+i);
  331. for (j = 0; (j < PORT_PINS) && (pin < PINS); j++, pin++)
  332. printk(KERN_DEBUG
  333. " Pin %d = %d\n", j, pins[i * PORT_PINS + j]);
  334. }
  335. }
  336. __initcall(crisv32_pinmux_init);