pxa2xx_mainstone.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * linux/drivers/pcmcia/pxa2xx_mainstone.c
  3. *
  4. * Mainstone PCMCIA specific routines.
  5. *
  6. * Created: May 12, 2004
  7. * Author: Nicolas Pitre
  8. * Copyright: MontaVista Software Inc.
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. */
  14. #include <linux/module.h>
  15. #include <linux/init.h>
  16. #include <linux/kernel.h>
  17. #include <linux/errno.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/platform_device.h>
  20. #include <pcmcia/ss.h>
  21. #include <asm/hardware.h>
  22. #include <asm/irq.h>
  23. #include <asm/arch/pxa-regs.h>
  24. #include <asm/arch/mainstone.h>
  25. #include "soc_common.h"
  26. static struct pcmcia_irqs irqs[] = {
  27. { 0, MAINSTONE_S0_CD_IRQ, "PCMCIA0 CD" },
  28. { 1, MAINSTONE_S1_CD_IRQ, "PCMCIA1 CD" },
  29. { 0, MAINSTONE_S0_STSCHG_IRQ, "PCMCIA0 STSCHG" },
  30. { 1, MAINSTONE_S1_STSCHG_IRQ, "PCMCIA1 STSCHG" },
  31. };
  32. static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
  33. {
  34. /*
  35. * Setup default state of GPIO outputs
  36. * before we enable them as outputs.
  37. */
  38. GPSR(GPIO48_nPOE) =
  39. GPIO_bit(GPIO48_nPOE) |
  40. GPIO_bit(GPIO49_nPWE) |
  41. GPIO_bit(GPIO50_nPIOR) |
  42. GPIO_bit(GPIO51_nPIOW) |
  43. GPIO_bit(GPIO85_nPCE_1) |
  44. GPIO_bit(GPIO54_nPCE_2);
  45. pxa_gpio_mode(GPIO48_nPOE_MD);
  46. pxa_gpio_mode(GPIO49_nPWE_MD);
  47. pxa_gpio_mode(GPIO50_nPIOR_MD);
  48. pxa_gpio_mode(GPIO51_nPIOW_MD);
  49. pxa_gpio_mode(GPIO85_nPCE_1_MD);
  50. pxa_gpio_mode(GPIO54_nPCE_2_MD);
  51. pxa_gpio_mode(GPIO79_pSKTSEL_MD);
  52. pxa_gpio_mode(GPIO55_nPREG_MD);
  53. pxa_gpio_mode(GPIO56_nPWAIT_MD);
  54. pxa_gpio_mode(GPIO57_nIOIS16_MD);
  55. skt->irq = (skt->nr == 0) ? MAINSTONE_S0_IRQ : MAINSTONE_S1_IRQ;
  56. return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
  57. }
  58. static void mst_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
  59. {
  60. soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
  61. }
  62. static unsigned long mst_pcmcia_status[2];
  63. static void mst_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
  64. struct pcmcia_state *state)
  65. {
  66. unsigned long status, flip;
  67. status = (skt->nr == 0) ? MST_PCMCIA0 : MST_PCMCIA1;
  68. flip = (status ^ mst_pcmcia_status[skt->nr]) & MST_PCMCIA_nSTSCHG_BVD1;
  69. /*
  70. * Workaround for STSCHG which can't be deasserted:
  71. * We therefore disable/enable corresponding IRQs
  72. * as needed to avoid IRQ locks.
  73. */
  74. if (flip) {
  75. mst_pcmcia_status[skt->nr] = status;
  76. if (status & MST_PCMCIA_nSTSCHG_BVD1)
  77. enable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ
  78. : MAINSTONE_S1_STSCHG_IRQ );
  79. else
  80. disable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ
  81. : MAINSTONE_S1_STSCHG_IRQ );
  82. }
  83. state->detect = (status & MST_PCMCIA_nCD) ? 0 : 1;
  84. state->ready = (status & MST_PCMCIA_nIRQ) ? 1 : 0;
  85. state->bvd1 = (status & MST_PCMCIA_nSTSCHG_BVD1) ? 1 : 0;
  86. state->bvd2 = (status & MST_PCMCIA_nSPKR_BVD2) ? 1 : 0;
  87. state->vs_3v = (status & MST_PCMCIA_nVS1) ? 0 : 1;
  88. state->vs_Xv = (status & MST_PCMCIA_nVS2) ? 0 : 1;
  89. state->wrprot = 0; /* not available */
  90. }
  91. static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  92. const socket_state_t *state)
  93. {
  94. unsigned long power = 0;
  95. int ret = 0;
  96. switch (state->Vcc) {
  97. case 0: power |= MST_PCMCIA_PWR_VCC_0; break;
  98. case 33: power |= MST_PCMCIA_PWR_VCC_33; break;
  99. case 50: power |= MST_PCMCIA_PWR_VCC_50; break;
  100. default:
  101. printk(KERN_ERR "%s(): bad Vcc %u\n",
  102. __FUNCTION__, state->Vcc);
  103. ret = -1;
  104. }
  105. switch (state->Vpp) {
  106. case 0: power |= MST_PCMCIA_PWR_VPP_0; break;
  107. case 120: power |= MST_PCMCIA_PWR_VPP_120; break;
  108. default:
  109. if(state->Vpp == state->Vcc) {
  110. power |= MST_PCMCIA_PWR_VPP_VCC;
  111. } else {
  112. printk(KERN_ERR "%s(): bad Vpp %u\n",
  113. __FUNCTION__, state->Vpp);
  114. ret = -1;
  115. }
  116. }
  117. if (state->flags & SS_RESET)
  118. power |= MST_PCMCIA_RESET;
  119. switch (skt->nr) {
  120. case 0: MST_PCMCIA0 = power; break;
  121. case 1: MST_PCMCIA1 = power; break;
  122. default: ret = -1;
  123. }
  124. return ret;
  125. }
  126. static void mst_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
  127. {
  128. }
  129. static void mst_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
  130. {
  131. }
  132. static struct pcmcia_low_level mst_pcmcia_ops = {
  133. .owner = THIS_MODULE,
  134. .hw_init = mst_pcmcia_hw_init,
  135. .hw_shutdown = mst_pcmcia_hw_shutdown,
  136. .socket_state = mst_pcmcia_socket_state,
  137. .configure_socket = mst_pcmcia_configure_socket,
  138. .socket_init = mst_pcmcia_socket_init,
  139. .socket_suspend = mst_pcmcia_socket_suspend,
  140. .nr = 2,
  141. };
  142. static struct platform_device *mst_pcmcia_device;
  143. static int __init mst_pcmcia_init(void)
  144. {
  145. int ret;
  146. mst_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
  147. if (!mst_pcmcia_device)
  148. return -ENOMEM;
  149. mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops;
  150. ret = platform_device_add(mst_pcmcia_device);
  151. if (ret)
  152. platform_device_put(mst_pcmcia_device);
  153. return ret;
  154. }
  155. static void __exit mst_pcmcia_exit(void)
  156. {
  157. platform_device_unregister(mst_pcmcia_device);
  158. }
  159. fs_initcall(mst_pcmcia_init);
  160. module_exit(mst_pcmcia_exit);
  161. MODULE_LICENSE("GPL");