au1000_pb1x00.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*
  2. *
  3. * Alchemy Semi Pb1000 boards specific pcmcia routines.
  4. *
  5. * Copyright 2002 MontaVista Software Inc.
  6. * Author: MontaVista Software, Inc.
  7. * ppopov@mvista.com or source@mvista.com
  8. *
  9. * ########################################################################
  10. *
  11. * This program is free software; you can distribute it and/or modify it
  12. * under the terms of the GNU General Public License (Version 2) as
  13. * published by the Free Software Foundation.
  14. *
  15. * This program is distributed in the hope it will be useful, but WITHOUT
  16. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  17. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  18. * for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License along
  21. * with this program; if not, write to the Free Software Foundation, Inc.,
  22. * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  23. */
  24. #include <linux/module.h>
  25. #include <linux/init.h>
  26. #include <linux/delay.h>
  27. #include <linux/ioport.h>
  28. #include <linux/kernel.h>
  29. #include <linux/timer.h>
  30. #include <linux/mm.h>
  31. #include <linux/proc_fs.h>
  32. #include <linux/types.h>
  33. #include <pcmcia/cs.h>
  34. #include <pcmcia/ss.h>
  35. #include <pcmcia/cistpl.h>
  36. #include <asm/io.h>
  37. #include <asm/irq.h>
  38. #include <asm/system.h>
  39. #include <asm/au1000.h>
  40. #include <asm/au1000_pcmcia.h>
  41. #define debug(fmt, arg...) do { } while (0)
  42. #include <asm/pb1000.h>
  43. #define PCMCIA_IRQ AU1000_GPIO_15
  44. static int pb1x00_pcmcia_init(struct pcmcia_init *init)
  45. {
  46. u16 pcr;
  47. pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST;
  48. au_writel(0x8000, PB1000_MDR); /* clear pcmcia interrupt */
  49. au_sync_delay(100);
  50. au_writel(0x4000, PB1000_MDR); /* enable pcmcia interrupt */
  51. au_sync();
  52. pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0);
  53. pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,1);
  54. au_writel(pcr, PB1000_PCR);
  55. au_sync_delay(20);
  56. return PCMCIA_NUM_SOCKS;
  57. }
  58. static int pb1x00_pcmcia_shutdown(void)
  59. {
  60. u16 pcr;
  61. pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST;
  62. pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0);
  63. pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,1);
  64. au_writel(pcr, PB1000_PCR);
  65. au_sync_delay(20);
  66. return 0;
  67. }
  68. static int
  69. pb1x00_pcmcia_socket_state(unsigned sock, struct pcmcia_state *state)
  70. {
  71. u32 inserted0, inserted1;
  72. u16 vs0, vs1;
  73. vs0 = vs1 = (u16)au_readl(PB1000_ACR1);
  74. inserted0 = !(vs0 & (ACR1_SLOT_0_CD1 | ACR1_SLOT_0_CD2));
  75. inserted1 = !(vs1 & (ACR1_SLOT_1_CD1 | ACR1_SLOT_1_CD2));
  76. vs0 = (vs0 >> 4) & 0x3;
  77. vs1 = (vs1 >> 12) & 0x3;
  78. state->ready = 0;
  79. state->vs_Xv = 0;
  80. state->vs_3v = 0;
  81. state->detect = 0;
  82. if (sock == 0) {
  83. if (inserted0) {
  84. switch (vs0) {
  85. case 0:
  86. case 2:
  87. state->vs_3v=1;
  88. break;
  89. case 3: /* 5V */
  90. break;
  91. default:
  92. /* return without setting 'detect' */
  93. printk(KERN_ERR "pb1x00 bad VS (%d)\n",
  94. vs0);
  95. return 0;
  96. }
  97. state->detect = 1;
  98. }
  99. }
  100. else {
  101. if (inserted1) {
  102. switch (vs1) {
  103. case 0:
  104. case 2:
  105. state->vs_3v=1;
  106. break;
  107. case 3: /* 5V */
  108. break;
  109. default:
  110. /* return without setting 'detect' */
  111. printk(KERN_ERR "pb1x00 bad VS (%d)\n",
  112. vs1);
  113. return 0;
  114. }
  115. state->detect = 1;
  116. }
  117. }
  118. if (state->detect) {
  119. state->ready = 1;
  120. }
  121. state->bvd1=1;
  122. state->bvd2=1;
  123. state->wrprot=0;
  124. return 1;
  125. }
  126. static int pb1x00_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
  127. {
  128. if(info->sock > PCMCIA_MAX_SOCK) return -1;
  129. /*
  130. * Even in the case of the Pb1000, both sockets are connected
  131. * to the same irq line.
  132. */
  133. info->irq = PCMCIA_IRQ;
  134. return 0;
  135. }
  136. static int
  137. pb1x00_pcmcia_configure_socket(const struct pcmcia_configure *configure)
  138. {
  139. u16 pcr;
  140. if(configure->sock > PCMCIA_MAX_SOCK) return -1;
  141. pcr = au_readl(PB1000_PCR);
  142. if (configure->sock == 0) {
  143. pcr &= ~(PCR_SLOT_0_VCC0 | PCR_SLOT_0_VCC1 |
  144. PCR_SLOT_0_VPP0 | PCR_SLOT_0_VPP1);
  145. }
  146. else {
  147. pcr &= ~(PCR_SLOT_1_VCC0 | PCR_SLOT_1_VCC1 |
  148. PCR_SLOT_1_VPP0 | PCR_SLOT_1_VPP1);
  149. }
  150. pcr &= ~PCR_SLOT_0_RST;
  151. debug("Vcc %dV Vpp %dV, pcr %x\n",
  152. configure->vcc, configure->vpp, pcr);
  153. switch(configure->vcc){
  154. case 0: /* Vcc 0 */
  155. switch(configure->vpp) {
  156. case 0:
  157. pcr |= SET_VCC_VPP(VCC_HIZ,VPP_GND,
  158. configure->sock);
  159. break;
  160. case 12:
  161. pcr |= SET_VCC_VPP(VCC_HIZ,VPP_12V,
  162. configure->sock);
  163. break;
  164. case 50:
  165. pcr |= SET_VCC_VPP(VCC_HIZ,VPP_5V,
  166. configure->sock);
  167. break;
  168. case 33:
  169. pcr |= SET_VCC_VPP(VCC_HIZ,VPP_3V,
  170. configure->sock);
  171. break;
  172. default:
  173. pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
  174. configure->sock);
  175. printk("%s: bad Vcc/Vpp (%d:%d)\n",
  176. __func__,
  177. configure->vcc,
  178. configure->vpp);
  179. break;
  180. }
  181. break;
  182. case 50: /* Vcc 5V */
  183. switch(configure->vpp) {
  184. case 0:
  185. pcr |= SET_VCC_VPP(VCC_5V,VPP_GND,
  186. configure->sock);
  187. break;
  188. case 50:
  189. pcr |= SET_VCC_VPP(VCC_5V,VPP_5V,
  190. configure->sock);
  191. break;
  192. case 12:
  193. pcr |= SET_VCC_VPP(VCC_5V,VPP_12V,
  194. configure->sock);
  195. break;
  196. case 33:
  197. pcr |= SET_VCC_VPP(VCC_5V,VPP_3V,
  198. configure->sock);
  199. break;
  200. default:
  201. pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
  202. configure->sock);
  203. printk("%s: bad Vcc/Vpp (%d:%d)\n",
  204. __func__,
  205. configure->vcc,
  206. configure->vpp);
  207. break;
  208. }
  209. break;
  210. case 33: /* Vcc 3.3V */
  211. switch(configure->vpp) {
  212. case 0:
  213. pcr |= SET_VCC_VPP(VCC_3V,VPP_GND,
  214. configure->sock);
  215. break;
  216. case 50:
  217. pcr |= SET_VCC_VPP(VCC_3V,VPP_5V,
  218. configure->sock);
  219. break;
  220. case 12:
  221. pcr |= SET_VCC_VPP(VCC_3V,VPP_12V,
  222. configure->sock);
  223. break;
  224. case 33:
  225. pcr |= SET_VCC_VPP(VCC_3V,VPP_3V,
  226. configure->sock);
  227. break;
  228. default:
  229. pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,
  230. configure->sock);
  231. printk("%s: bad Vcc/Vpp (%d:%d)\n",
  232. __func__,
  233. configure->vcc,
  234. configure->vpp);
  235. break;
  236. }
  237. break;
  238. default: /* what's this ? */
  239. pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,configure->sock);
  240. printk(KERN_ERR "%s: bad Vcc %d\n",
  241. __func__, configure->vcc);
  242. break;
  243. }
  244. if (configure->sock == 0) {
  245. pcr &= ~(PCR_SLOT_0_RST);
  246. if (configure->reset)
  247. pcr |= PCR_SLOT_0_RST;
  248. }
  249. else {
  250. pcr &= ~(PCR_SLOT_1_RST);
  251. if (configure->reset)
  252. pcr |= PCR_SLOT_1_RST;
  253. }
  254. au_writel(pcr, PB1000_PCR);
  255. au_sync_delay(300);
  256. return 0;
  257. }
  258. struct pcmcia_low_level pb1x00_pcmcia_ops = {
  259. pb1x00_pcmcia_init,
  260. pb1x00_pcmcia_shutdown,
  261. pb1x00_pcmcia_socket_state,
  262. pb1x00_pcmcia_get_irq_info,
  263. pb1x00_pcmcia_configure_socket
  264. };