005-compact-flash.patch 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. Index: linux-2.6.21.7/drivers/pcmcia/Makefile
  2. ===================================================================
  3. --- linux-2.6.21.7.orig/drivers/pcmcia/Makefile
  4. +++ linux-2.6.21.7/drivers/pcmcia/Makefile
  5. @@ -69,4 +69,4 @@ sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa
  6. pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock.o sa1111_generic.o
  7. pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
  8. pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
  9. -
  10. +pxa2xx_cs-$(CONFIG_ARCH_GUMSTIX) += pxa2xx_gumstix.o
  11. Index: linux-2.6.21.7/drivers/pcmcia/pxa2xx_gumstix.c
  12. ===================================================================
  13. --- /dev/null
  14. +++ linux-2.6.21.7/drivers/pcmcia/pxa2xx_gumstix.c
  15. @@ -0,0 +1,272 @@
  16. +/*
  17. + * linux/drivers/pcmcia/pxa2xx_gumstix.c
  18. + *
  19. + * Gumstix PCMCIA specific routines. Based on Mainstone
  20. + *
  21. + * Copyright 2004, Craig Hughes <[email protected]>
  22. + *
  23. + * This program is free software; you can redistribute it and/or modify
  24. + * it under the terms of the GNU General Public License version 2 as
  25. + * published by the Free Software Foundation.
  26. + */
  27. +
  28. +#include <linux/module.h>
  29. +#include <linux/init.h>
  30. +#include <linux/kernel.h>
  31. +#include <linux/errno.h>
  32. +#include <linux/interrupt.h>
  33. +#include <linux/device.h>
  34. +#include <linux/platform_device.h>
  35. +
  36. +#include <pcmcia/ss.h>
  37. +
  38. +#include <asm/hardware.h>
  39. +#include <asm/delay.h>
  40. +#include <asm/arch/pxa-regs.h>
  41. +#include <asm/irq.h>
  42. +#include <asm/io.h>
  43. +
  44. +#include <asm/arch/gumstix.h>
  45. +
  46. +#include "soc_common.h"
  47. +
  48. +static struct pcmcia_irqs gumstix_pcmcia_irqs0[] = {
  49. + { 0, GUMSTIX_S0_nCD_IRQ, "CF0 nCD" },
  50. + { 0, GUMSTIX_S0_nSTSCHG_IRQ, "CF0 nSTSCHG" },
  51. +};
  52. +
  53. +static struct pcmcia_irqs gumstix_pcmcia_irqs1[] = {
  54. + { 1, GUMSTIX_S1_nCD_IRQ, "CF1 nCD" },
  55. + { 1, GUMSTIX_S1_nSTSCHG_IRQ, "CF1 nSTSCHG" },
  56. +};
  57. +
  58. +static int net_cf_vx_mode = 0;
  59. +
  60. +static int gumstix_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
  61. +{
  62. + if(skt->nr == 0)
  63. + {
  64. + pxa_gpio_mode(GPIO_GUMSTIX_nSTSCHG_0_MD);
  65. + pxa_gpio_mode(GPIO_GUMSTIX_nCD_0_MD);
  66. + if(net_cf_vx_mode)
  67. + pxa_gpio_mode(GPIO_GUMSTIX_PRDY_nBSY_0_OLD_MD);
  68. + else
  69. + pxa_gpio_mode(GPIO_GUMSTIX_PRDY_nBSY_0_MD);
  70. + } else {
  71. + pxa_gpio_mode(GPIO_GUMSTIX_nSTSCHG_1_MD);
  72. + pxa_gpio_mode(GPIO_GUMSTIX_nCD_1_MD);
  73. + pxa_gpio_mode(GPIO_GUMSTIX_PRDY_nBSY_1_MD);
  74. + }
  75. +
  76. + pxa_gpio_mode(GPIO_GUMSTIX_nPOE_MD);
  77. + pxa_gpio_mode(GPIO_GUMSTIX_nPWE_MD);
  78. + pxa_gpio_mode(GPIO_GUMSTIX_nPIOR_MD);
  79. + pxa_gpio_mode(GPIO_GUMSTIX_nPIOW_MD);
  80. + pxa_gpio_mode(GPIO_GUMSTIX_nPCE_1_MD);
  81. + pxa_gpio_mode(GPIO_GUMSTIX_nPCE_2_MD);
  82. + pxa_gpio_mode(GPIO_GUMSTIX_pSKTSEL_MD);
  83. + pxa_gpio_mode(GPIO_GUMSTIX_nPREG_MD);
  84. + pxa_gpio_mode(GPIO_GUMSTIX_nPWAIT_MD);
  85. + pxa_gpio_mode(GPIO_GUMSTIX_nIOIS16_MD);
  86. +
  87. + skt->irq = (skt->nr == 0) ? ((net_cf_vx_mode == 0) ? GUMSTIX_S0_PRDY_nBSY_IRQ : GUMSTIX_S0_PRDY_nBSY_OLD_IRQ) : GUMSTIX_S1_PRDY_nBSY_IRQ;
  88. +
  89. + return (skt->nr == 0) ? soc_pcmcia_request_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0)) :
  90. + soc_pcmcia_request_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1));
  91. +}
  92. +
  93. +static void gumstix_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
  94. +{
  95. + if(skt->nr == 0)
  96. + {
  97. + soc_pcmcia_free_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0));
  98. + } else {
  99. + soc_pcmcia_free_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1));
  100. + }
  101. +}
  102. +
  103. +static void gumstix_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
  104. + struct pcmcia_state *state)
  105. +{
  106. + unsigned int cd, prdy_nbsy, nbvd1;
  107. + if(skt->nr == 0)
  108. + {
  109. + cd = GPIO_GUMSTIX_nCD_0;
  110. + if(net_cf_vx_mode)
  111. + prdy_nbsy = GPIO_GUMSTIX_PRDY_nBSY_0_OLD;
  112. + else
  113. + prdy_nbsy = GPIO_GUMSTIX_PRDY_nBSY_0;
  114. + nbvd1 = GPIO_GUMSTIX_nBVD1_0;
  115. + } else {
  116. + cd = GPIO_GUMSTIX_nCD_1;
  117. + prdy_nbsy = GPIO_GUMSTIX_PRDY_nBSY_1;
  118. + nbvd1 = GPIO_GUMSTIX_nBVD1_1;
  119. + }
  120. + state->detect = !(GPLR(cd) & GPIO_bit(cd));
  121. + state->ready = !!(GPLR(prdy_nbsy) & GPIO_bit(prdy_nbsy));
  122. + state->bvd1 = !!(GPLR(nbvd1) & GPIO_bit(nbvd1));
  123. + state->bvd2 = 1;
  124. + state->vs_3v = 0;
  125. + state->vs_Xv = 0;
  126. + state->wrprot = 0;
  127. +}
  128. +
  129. +static int gumstix_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  130. + const socket_state_t *state)
  131. +{
  132. + return 0;
  133. +}
  134. +
  135. +static void gumstix_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
  136. +{
  137. + if(skt->nr) {
  138. + soc_pcmcia_enable_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0));
  139. + } else {
  140. + soc_pcmcia_enable_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1));
  141. + }
  142. +}
  143. +
  144. +static void gumstix_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
  145. +{
  146. + if(skt->nr) {
  147. + soc_pcmcia_disable_irqs(skt, gumstix_pcmcia_irqs0, ARRAY_SIZE(gumstix_pcmcia_irqs0));
  148. + } else {
  149. + soc_pcmcia_disable_irqs(skt, gumstix_pcmcia_irqs1, ARRAY_SIZE(gumstix_pcmcia_irqs1));
  150. + }
  151. +}
  152. +
  153. +static struct pcmcia_low_level gumstix_pcmcia_ops = {
  154. + .owner = THIS_MODULE,
  155. + .hw_init = gumstix_pcmcia_hw_init,
  156. + .hw_shutdown = gumstix_pcmcia_hw_shutdown,
  157. + .socket_state = gumstix_pcmcia_socket_state,
  158. + .configure_socket = gumstix_pcmcia_configure_socket,
  159. + .socket_init = gumstix_pcmcia_socket_init,
  160. + .socket_suspend = gumstix_pcmcia_socket_suspend,
  161. + .nr = 2,
  162. +};
  163. +
  164. +static struct platform_device *gumstix_pcmcia_device;
  165. +
  166. +inline void __init gumstix_pcmcia_cpld_clk(void)
  167. +{
  168. + GPCR(GPIO_GUMSTIX_nPOE) = GPIO_bit(GPIO_GUMSTIX_nPOE);
  169. + GPSR(GPIO_GUMSTIX_nPOE) = GPIO_bit(GPIO_GUMSTIX_nPOE);
  170. +}
  171. +
  172. +inline unsigned char __init gumstix_pcmcia_cpld_read_bits(int bits)
  173. +{
  174. + unsigned char result = 0;
  175. + unsigned int shift = 0;
  176. + while(bits--)
  177. + {
  178. + result |= !!(GPLR(GPIO_GUMSTIX_nCD_0) & GPIO_bit(GPIO_GUMSTIX_nCD_0)) << shift;
  179. + shift ++;
  180. + gumstix_pcmcia_cpld_clk();
  181. + }
  182. + printk("CPLD responded with: %02x\n",result);
  183. + return result;
  184. +}
  185. +
  186. +/* We use the CPLD on the CF-CF card to read a value from a shift register. If we can read that
  187. + * magic sequence, then we have 2 CF cards; otherwise we assume just one
  188. + * The CPLD will send the value of the shift register on GPIO11 (the CD line for slot 0)
  189. + * when RESET is held in reset. We use GPIO48 (nPOE) as a clock signal,
  190. + * GPIO52/53 (card enable for both cards) to control read/write to the shift register
  191. + */
  192. +static void __init gumstix_count_cards(void)
  193. +{
  194. + pxa_gpio_mode(GPIO_GUMSTIX_nPOE | GPIO_OUT);
  195. + pxa_gpio_mode(GPIO_GUMSTIX_nPCE_1 | GPIO_OUT);
  196. + pxa_gpio_mode(GPIO_GUMSTIX_nPCE_2 | GPIO_OUT);
  197. + pxa_gpio_mode(GPIO_GUMSTIX_nCD_0 | GPIO_IN);
  198. + if(net_cf_vx_mode)
  199. + pxa_gpio_mode(GPIO_GUMSTIX_CF_OLD_RESET | GPIO_OUT);
  200. + else
  201. + pxa_gpio_mode(GPIO_GUMSTIX_CF_RESET | GPIO_OUT);
  202. +
  203. + // Enter reset
  204. + if(net_cf_vx_mode)
  205. + GPSR(GPIO_GUMSTIX_CF_OLD_RESET) = GPIO_bit(GPIO_GUMSTIX_CF_OLD_RESET);
  206. + else
  207. + GPSR(GPIO_GUMSTIX_CF_RESET) = GPIO_bit(GPIO_GUMSTIX_CF_RESET);
  208. +
  209. + // Setup the shift register
  210. + GPSR(GPIO_GUMSTIX_nPCE_1) = GPIO_bit(GPIO_GUMSTIX_nPCE_1);
  211. + GPCR(GPIO_GUMSTIX_nPCE_2) = GPIO_bit(GPIO_GUMSTIX_nPCE_2);
  212. +
  213. + // Tick the clock to program the shift register
  214. + gumstix_pcmcia_cpld_clk();
  215. +
  216. + // Now set shift register into read mode
  217. + GPCR(GPIO_GUMSTIX_nPCE_1) = GPIO_bit(GPIO_GUMSTIX_nPCE_1);
  218. + GPSR(GPIO_GUMSTIX_nPCE_2) = GPIO_bit(GPIO_GUMSTIX_nPCE_2);
  219. +
  220. + // We can read the bits now -- 0xC2 means "Dual compact flash"
  221. + if(gumstix_pcmcia_cpld_read_bits(8) != 0xC2)
  222. + {
  223. + // We do not have 2 CF slots
  224. + gumstix_pcmcia_ops.nr = 1;
  225. + }
  226. +}
  227. +
  228. +#ifdef CONFIG_ARCH_GUMSTIX_VERDEX
  229. +static void __init gumstix_check_if_netCF_vx(void)
  230. +{
  231. + void *network_controller_memory = ioremap(0x04000300,16);
  232. + // Look for the special 91c111 value in the bank select register
  233. + if((0xff00 & readw(network_controller_memory+0x0e)) == 0x3300) {
  234. + printk("Detected netCF-vx board: using older GPIO configuration\n");
  235. + net_cf_vx_mode = 1;
  236. + } else {
  237. + printk("Not netCF-vx board: using newer GPIO configuration\n");
  238. + net_cf_vx_mode = 0;
  239. + }
  240. + iounmap(network_controller_memory);
  241. +}
  242. +#endif
  243. +
  244. +static int __init gumstix_pcmcia_init(void)
  245. +{
  246. + int ret;
  247. +
  248. +#ifdef CONFIG_ARCH_GUMSTIX_VERDEX
  249. + gumstix_check_if_netCF_vx();
  250. +#endif
  251. +
  252. + gumstix_count_cards();
  253. +
  254. + udelay(50);
  255. + if(net_cf_vx_mode)
  256. + GPCR(GPIO_GUMSTIX_CF_OLD_RESET) = GPIO_bit(GPIO_GUMSTIX_CF_OLD_RESET);
  257. + else
  258. + GPCR(GPIO_GUMSTIX_CF_RESET) = GPIO_bit(GPIO_GUMSTIX_CF_RESET);
  259. +
  260. + gumstix_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
  261. + if (!gumstix_pcmcia_device)
  262. + return -ENOMEM;
  263. +
  264. + gumstix_pcmcia_device->dev.platform_data = &gumstix_pcmcia_ops;
  265. +
  266. + ret = platform_device_add(gumstix_pcmcia_device);
  267. + if (ret)
  268. + platform_device_put(gumstix_pcmcia_device);
  269. +
  270. + return ret;
  271. +}
  272. +
  273. +static void __exit gumstix_pcmcia_exit(void)
  274. +{
  275. + /*
  276. + * This call is supposed to free our gumstix_pcmcia_device.
  277. + * Unfortunately platform_device don't have a free method, and
  278. + * we can't assume it's free of any reference at this point so we
  279. + * can't free it either.
  280. + */
  281. + platform_device_unregister(gumstix_pcmcia_device);
  282. +}
  283. +
  284. +fs_initcall(gumstix_pcmcia_init);
  285. +module_exit(gumstix_pcmcia_exit);
  286. +
  287. +MODULE_LICENSE("GPL");