pinmux.c 9.7 KB

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