bcm63xx_pcmcia.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2008 Maxime Bizon <[email protected]>
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/module.h>
  10. #include <linux/ioport.h>
  11. #include <linux/timer.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/slab.h>
  14. #include <linux/delay.h>
  15. #include <linux/pci.h>
  16. #include <linux/gpio.h>
  17. #include <bcm63xx_regs.h>
  18. #include <bcm63xx_io.h>
  19. #include "bcm63xx_pcmcia.h"
  20. #define PFX "bcm63xx_pcmcia: "
  21. #ifdef CONFIG_CARDBUS
  22. /* if cardbus is used, platform device needs reference to actual pci
  23. * device */
  24. static struct pci_dev *bcm63xx_cb_dev;
  25. #endif
  26. /*
  27. * read/write helper for pcmcia regs
  28. */
  29. static inline u32 pcmcia_readl(struct bcm63xx_pcmcia_socket *skt, u32 off)
  30. {
  31. return bcm_readl(skt->base + off);
  32. }
  33. static inline void pcmcia_writel(struct bcm63xx_pcmcia_socket *skt,
  34. u32 val, u32 off)
  35. {
  36. bcm_writel(val, skt->base + off);
  37. }
  38. /*
  39. * This callback should (re-)initialise the socket, turn on status
  40. * interrupts and PCMCIA bus, and wait for power to stabilise so that
  41. * the card status signals report correctly.
  42. *
  43. * Hardware cannot do that.
  44. */
  45. static int bcm63xx_pcmcia_sock_init(struct pcmcia_socket *sock)
  46. {
  47. return 0;
  48. }
  49. /*
  50. * This callback should remove power on the socket, disable IRQs from
  51. * the card, turn off status interrupts, and disable the PCMCIA bus.
  52. *
  53. * Hardware cannot do that.
  54. */
  55. static int bcm63xx_pcmcia_suspend(struct pcmcia_socket *sock)
  56. {
  57. return 0;
  58. }
  59. /*
  60. * Implements the set_socket() operation for the in-kernel PCMCIA
  61. * service (formerly SS_SetSocket in Card Services). We more or
  62. * less punt all of this work and let the kernel handle the details
  63. * of power configuration, reset, &c. We also record the value of
  64. * `state' in order to regurgitate it to the PCMCIA core later.
  65. */
  66. static int bcm63xx_pcmcia_set_socket(struct pcmcia_socket *sock,
  67. socket_state_t *state)
  68. {
  69. struct bcm63xx_pcmcia_socket *skt;
  70. unsigned long flags;
  71. u32 val;
  72. skt = sock->driver_data;
  73. spin_lock_irqsave(&skt->lock, flags);
  74. /* note: hardware cannot control socket power, so we will
  75. * always report SS_POWERON */
  76. /* apply socket reset */
  77. val = pcmcia_readl(skt, PCMCIA_C1_REG);
  78. if (state->flags & SS_RESET)
  79. val |= PCMCIA_C1_RESET_MASK;
  80. else
  81. val &= ~PCMCIA_C1_RESET_MASK;
  82. /* reverse reset logic for cardbus card */
  83. if (skt->card_detected && (skt->card_type & CARD_CARDBUS))
  84. val ^= PCMCIA_C1_RESET_MASK;
  85. pcmcia_writel(skt, val, PCMCIA_C1_REG);
  86. /* keep requested state for event reporting */
  87. skt->requested_state = *state;
  88. spin_unlock_irqrestore(&skt->lock, flags);
  89. return 0;
  90. }
  91. /*
  92. * identity cardtype from VS[12] input, CD[12] input while only VS2 is
  93. * floating, and CD[12] input while only VS1 is floating
  94. */
  95. enum {
  96. IN_VS1 = (1 << 0),
  97. IN_VS2 = (1 << 1),
  98. IN_CD1_VS2H = (1 << 2),
  99. IN_CD2_VS2H = (1 << 3),
  100. IN_CD1_VS1H = (1 << 4),
  101. IN_CD2_VS1H = (1 << 5),
  102. };
  103. static const u8 vscd_to_cardtype[] = {
  104. /* VS1 float, VS2 float */
  105. [IN_VS1 | IN_VS2] = (CARD_PCCARD | CARD_5V),
  106. /* VS1 grounded, VS2 float */
  107. [IN_VS2] = (CARD_PCCARD | CARD_5V | CARD_3V),
  108. /* VS1 grounded, VS2 grounded */
  109. [0] = (CARD_PCCARD | CARD_5V | CARD_3V | CARD_XV),
  110. /* VS1 tied to CD1, VS2 float */
  111. [IN_VS1 | IN_VS2 | IN_CD1_VS1H] = (CARD_CARDBUS | CARD_3V),
  112. /* VS1 grounded, VS2 tied to CD2 */
  113. [IN_VS2 | IN_CD2_VS2H] = (CARD_CARDBUS | CARD_3V | CARD_XV),
  114. /* VS1 tied to CD2, VS2 grounded */
  115. [IN_VS1 | IN_CD2_VS1H] = (CARD_CARDBUS | CARD_3V | CARD_XV | CARD_YV),
  116. /* VS1 float, VS2 grounded */
  117. [IN_VS1] = (CARD_PCCARD | CARD_XV),
  118. /* VS1 float, VS2 tied to CD2 */
  119. [IN_VS1 | IN_VS2 | IN_CD2_VS2H] = (CARD_CARDBUS | CARD_3V),
  120. /* VS1 float, VS2 tied to CD1 */
  121. [IN_VS1 | IN_VS2 | IN_CD1_VS2H] = (CARD_CARDBUS | CARD_XV | CARD_YV),
  122. /* VS1 tied to CD2, VS2 float */
  123. [IN_VS1 | IN_VS2 | IN_CD2_VS1H] = (CARD_CARDBUS | CARD_YV),
  124. /* VS2 grounded, VS1 is tied to CD1, CD2 is grounded */
  125. [IN_VS1 | IN_CD1_VS1H] = 0, /* ignore cardbay */
  126. };
  127. /*
  128. * poll hardware to check card insertion status
  129. */
  130. static unsigned int __get_socket_status(struct bcm63xx_pcmcia_socket *skt)
  131. {
  132. unsigned int stat;
  133. u32 val;
  134. stat = 0;
  135. /* check CD for card presence */
  136. val = pcmcia_readl(skt, PCMCIA_C1_REG);
  137. if (!(val & PCMCIA_C1_CD1_MASK) && !(val & PCMCIA_C1_CD2_MASK))
  138. stat |= SS_DETECT;
  139. /* if new insertion, detect cardtype */
  140. if ((stat & SS_DETECT) && !skt->card_detected) {
  141. unsigned int stat = 0;
  142. /* float VS1, float VS2 */
  143. val |= PCMCIA_C1_VS1OE_MASK;
  144. val |= PCMCIA_C1_VS2OE_MASK;
  145. pcmcia_writel(skt, val, PCMCIA_C1_REG);
  146. /* wait for output to stabilize and read VS[12] */
  147. udelay(10);
  148. val = pcmcia_readl(skt, PCMCIA_C1_REG);
  149. stat |= (val & PCMCIA_C1_VS1_MASK) ? IN_VS1 : 0;
  150. stat |= (val & PCMCIA_C1_VS2_MASK) ? IN_VS2 : 0;
  151. /* drive VS1 low, float VS2 */
  152. val &= ~PCMCIA_C1_VS1OE_MASK;
  153. val |= PCMCIA_C1_VS2OE_MASK;
  154. pcmcia_writel(skt, val, PCMCIA_C1_REG);
  155. /* wait for output to stabilize and read CD[12] */
  156. udelay(10);
  157. val = pcmcia_readl(skt, PCMCIA_C1_REG);
  158. stat |= (val & PCMCIA_C1_CD1_MASK) ? IN_CD1_VS2H : 0;
  159. stat |= (val & PCMCIA_C1_CD2_MASK) ? IN_CD2_VS2H : 0;
  160. /* float VS1, drive VS2 low */
  161. val |= PCMCIA_C1_VS1OE_MASK;
  162. val &= ~PCMCIA_C1_VS2OE_MASK;
  163. pcmcia_writel(skt, val, PCMCIA_C1_REG);
  164. /* wait for output to stabilize and read CD[12] */
  165. udelay(10);
  166. val = pcmcia_readl(skt, PCMCIA_C1_REG);
  167. stat |= (val & PCMCIA_C1_CD1_MASK) ? IN_CD1_VS1H : 0;
  168. stat |= (val & PCMCIA_C1_CD2_MASK) ? IN_CD2_VS1H : 0;
  169. /* guess cardtype from all this */
  170. skt->card_type = vscd_to_cardtype[stat];
  171. if (!skt->card_type)
  172. dev_err(&skt->socket.dev, "unsupported card type\n");
  173. /* drive both VS pin to 0 again */
  174. val &= ~(PCMCIA_C1_VS1OE_MASK | PCMCIA_C1_VS2OE_MASK);
  175. /* enable correct logic */
  176. val &= ~(PCMCIA_C1_EN_PCMCIA_MASK | PCMCIA_C1_EN_CARDBUS_MASK);
  177. if (skt->card_type & CARD_PCCARD)
  178. val |= PCMCIA_C1_EN_PCMCIA_MASK;
  179. else
  180. val |= PCMCIA_C1_EN_CARDBUS_MASK;
  181. pcmcia_writel(skt, val, PCMCIA_C1_REG);
  182. }
  183. skt->card_detected = (stat & SS_DETECT) ? 1 : 0;
  184. /* report card type/voltage */
  185. if (skt->card_type & CARD_CARDBUS)
  186. stat |= SS_CARDBUS;
  187. if (skt->card_type & CARD_3V)
  188. stat |= SS_3VCARD;
  189. if (skt->card_type & CARD_XV)
  190. stat |= SS_XVCARD;
  191. stat |= SS_POWERON;
  192. if (gpio_get_value(skt->pd->ready_gpio))
  193. stat |= SS_READY;
  194. return stat;
  195. }
  196. /*
  197. * core request to get current socket status
  198. */
  199. static int bcm63xx_pcmcia_get_status(struct pcmcia_socket *sock,
  200. unsigned int *status)
  201. {
  202. struct bcm63xx_pcmcia_socket *skt;
  203. skt = sock->driver_data;
  204. spin_lock_bh(&skt->lock);
  205. *status = __get_socket_status(skt);
  206. spin_unlock_bh(&skt->lock);
  207. return 0;
  208. }
  209. /*
  210. * socket polling timer callback
  211. */
  212. static void bcm63xx_pcmcia_poll(struct timer_list *t)
  213. {
  214. struct bcm63xx_pcmcia_socket *skt;
  215. unsigned int stat, events;
  216. skt = from_timer(skt, t, timer);
  217. spin_lock_bh(&skt->lock);
  218. stat = __get_socket_status(skt);
  219. /* keep only changed bits, and mask with required one from the
  220. * core */
  221. events = (stat ^ skt->old_status) & skt->requested_state.csc_mask;
  222. skt->old_status = stat;
  223. spin_unlock_bh(&skt->lock);
  224. if (events)
  225. pcmcia_parse_events(&skt->socket, events);
  226. mod_timer(&skt->timer,
  227. jiffies + msecs_to_jiffies(BCM63XX_PCMCIA_POLL_RATE));
  228. }
  229. static int bcm63xx_pcmcia_set_io_map(struct pcmcia_socket *sock,
  230. struct pccard_io_map *map)
  231. {
  232. /* this doesn't seem to be called by pcmcia layer if static
  233. * mapping is used */
  234. return 0;
  235. }
  236. static int bcm63xx_pcmcia_set_mem_map(struct pcmcia_socket *sock,
  237. struct pccard_mem_map *map)
  238. {
  239. struct bcm63xx_pcmcia_socket *skt;
  240. struct resource *res;
  241. skt = sock->driver_data;
  242. if (map->flags & MAP_ATTRIB)
  243. res = skt->attr_res;
  244. else
  245. res = skt->common_res;
  246. map->static_start = res->start + map->card_start;
  247. return 0;
  248. }
  249. static struct pccard_operations bcm63xx_pcmcia_operations = {
  250. .init = bcm63xx_pcmcia_sock_init,
  251. .suspend = bcm63xx_pcmcia_suspend,
  252. .get_status = bcm63xx_pcmcia_get_status,
  253. .set_socket = bcm63xx_pcmcia_set_socket,
  254. .set_io_map = bcm63xx_pcmcia_set_io_map,
  255. .set_mem_map = bcm63xx_pcmcia_set_mem_map,
  256. };
  257. /*
  258. * register pcmcia socket to core
  259. */
  260. static int bcm63xx_drv_pcmcia_probe(struct platform_device *pdev)
  261. {
  262. struct bcm63xx_pcmcia_socket *skt;
  263. struct pcmcia_socket *sock;
  264. struct resource *res;
  265. unsigned int regmem_size = 0, iomem_size = 0;
  266. u32 val;
  267. int ret;
  268. int irq;
  269. skt = kzalloc(sizeof(*skt), GFP_KERNEL);
  270. if (!skt)
  271. return -ENOMEM;
  272. spin_lock_init(&skt->lock);
  273. sock = &skt->socket;
  274. sock->driver_data = skt;
  275. /* make sure we have all resources we need */
  276. skt->common_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  277. skt->attr_res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
  278. irq = platform_get_irq(pdev, 0);
  279. skt->pd = pdev->dev.platform_data;
  280. if (!skt->common_res || !skt->attr_res || (irq < 0) || !skt->pd) {
  281. ret = -EINVAL;
  282. goto err;
  283. }
  284. /* remap pcmcia registers */
  285. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  286. regmem_size = resource_size(res);
  287. if (!request_mem_region(res->start, regmem_size, "bcm63xx_pcmcia")) {
  288. ret = -EINVAL;
  289. goto err;
  290. }
  291. skt->reg_res = res;
  292. skt->base = ioremap(res->start, regmem_size);
  293. if (!skt->base) {
  294. ret = -ENOMEM;
  295. goto err;
  296. }
  297. /* remap io registers */
  298. res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
  299. iomem_size = resource_size(res);
  300. skt->io_base = ioremap(res->start, iomem_size);
  301. if (!skt->io_base) {
  302. ret = -ENOMEM;
  303. goto err;
  304. }
  305. /* resources are static */
  306. sock->resource_ops = &pccard_static_ops;
  307. sock->ops = &bcm63xx_pcmcia_operations;
  308. sock->owner = THIS_MODULE;
  309. sock->dev.parent = &pdev->dev;
  310. sock->features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
  311. sock->io_offset = (unsigned long)skt->io_base;
  312. sock->pci_irq = irq;
  313. #ifdef CONFIG_CARDBUS
  314. sock->cb_dev = bcm63xx_cb_dev;
  315. if (bcm63xx_cb_dev)
  316. sock->features |= SS_CAP_CARDBUS;
  317. #endif
  318. /* assume common & attribute memory have the same size */
  319. sock->map_size = resource_size(skt->common_res);
  320. /* initialize polling timer */
  321. timer_setup(&skt->timer, bcm63xx_pcmcia_poll, 0);
  322. /* initialize pcmcia control register, drive VS[12] to 0,
  323. * leave CB IDSEL to the old value since it is set by the PCI
  324. * layer */
  325. val = pcmcia_readl(skt, PCMCIA_C1_REG);
  326. val &= PCMCIA_C1_CBIDSEL_MASK;
  327. val |= PCMCIA_C1_EN_PCMCIA_GPIO_MASK;
  328. pcmcia_writel(skt, val, PCMCIA_C1_REG);
  329. /*
  330. * Hardware has only one set of timings registers, not one for
  331. * each memory access type, so we configure them for the
  332. * slowest one: attribute memory.
  333. */
  334. val = PCMCIA_C2_DATA16_MASK;
  335. val |= 10 << PCMCIA_C2_RWCOUNT_SHIFT;
  336. val |= 6 << PCMCIA_C2_INACTIVE_SHIFT;
  337. val |= 3 << PCMCIA_C2_SETUP_SHIFT;
  338. val |= 3 << PCMCIA_C2_HOLD_SHIFT;
  339. pcmcia_writel(skt, val, PCMCIA_C2_REG);
  340. ret = pcmcia_register_socket(sock);
  341. if (ret)
  342. goto err;
  343. /* start polling socket */
  344. mod_timer(&skt->timer,
  345. jiffies + msecs_to_jiffies(BCM63XX_PCMCIA_POLL_RATE));
  346. platform_set_drvdata(pdev, skt);
  347. return 0;
  348. err:
  349. if (skt->io_base)
  350. iounmap(skt->io_base);
  351. if (skt->base)
  352. iounmap(skt->base);
  353. if (skt->reg_res)
  354. release_mem_region(skt->reg_res->start, regmem_size);
  355. kfree(skt);
  356. return ret;
  357. }
  358. static int bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
  359. {
  360. struct bcm63xx_pcmcia_socket *skt;
  361. struct resource *res;
  362. skt = platform_get_drvdata(pdev);
  363. del_timer_sync(&skt->timer);
  364. iounmap(skt->base);
  365. iounmap(skt->io_base);
  366. res = skt->reg_res;
  367. release_mem_region(res->start, resource_size(res));
  368. kfree(skt);
  369. return 0;
  370. }
  371. struct platform_driver bcm63xx_pcmcia_driver = {
  372. .probe = bcm63xx_drv_pcmcia_probe,
  373. .remove = bcm63xx_drv_pcmcia_remove,
  374. .driver = {
  375. .name = "bcm63xx_pcmcia",
  376. .owner = THIS_MODULE,
  377. },
  378. };
  379. #ifdef CONFIG_CARDBUS
  380. static int bcm63xx_cb_probe(struct pci_dev *dev,
  381. const struct pci_device_id *id)
  382. {
  383. /* keep pci device */
  384. bcm63xx_cb_dev = dev;
  385. return platform_driver_register(&bcm63xx_pcmcia_driver);
  386. }
  387. static void bcm63xx_cb_exit(struct pci_dev *dev)
  388. {
  389. platform_driver_unregister(&bcm63xx_pcmcia_driver);
  390. bcm63xx_cb_dev = NULL;
  391. }
  392. static const struct pci_device_id bcm63xx_cb_table[] = {
  393. {
  394. .vendor = PCI_VENDOR_ID_BROADCOM,
  395. .device = BCM6348_CPU_ID,
  396. .subvendor = PCI_VENDOR_ID_BROADCOM,
  397. .subdevice = PCI_ANY_ID,
  398. .class = PCI_CLASS_BRIDGE_CARDBUS << 8,
  399. .class_mask = ~0,
  400. },
  401. {
  402. .vendor = PCI_VENDOR_ID_BROADCOM,
  403. .device = BCM6358_CPU_ID,
  404. .subvendor = PCI_VENDOR_ID_BROADCOM,
  405. .subdevice = PCI_ANY_ID,
  406. .class = PCI_CLASS_BRIDGE_CARDBUS << 8,
  407. .class_mask = ~0,
  408. },
  409. { },
  410. };
  411. MODULE_DEVICE_TABLE(pci, bcm63xx_cb_table);
  412. static struct pci_driver bcm63xx_cardbus_driver = {
  413. .name = "bcm63xx_cardbus",
  414. .id_table = bcm63xx_cb_table,
  415. .probe = bcm63xx_cb_probe,
  416. .remove = bcm63xx_cb_exit,
  417. };
  418. #endif
  419. /*
  420. * if cardbus support is enabled, register our platform device after
  421. * our fake cardbus bridge has been registered
  422. */
  423. static int __init bcm63xx_pcmcia_init(void)
  424. {
  425. #ifdef CONFIG_CARDBUS
  426. return pci_register_driver(&bcm63xx_cardbus_driver);
  427. #else
  428. return platform_driver_register(&bcm63xx_pcmcia_driver);
  429. #endif
  430. }
  431. static void __exit bcm63xx_pcmcia_exit(void)
  432. {
  433. #ifdef CONFIG_CARDBUS
  434. return pci_unregister_driver(&bcm63xx_cardbus_driver);
  435. #else
  436. platform_driver_unregister(&bcm63xx_pcmcia_driver);
  437. #endif
  438. }
  439. module_init(bcm63xx_pcmcia_init);
  440. module_exit(bcm63xx_pcmcia_exit);
  441. MODULE_LICENSE("GPL");
  442. MODULE_AUTHOR("Maxime Bizon <[email protected]>");
  443. MODULE_DESCRIPTION("Linux PCMCIA Card Services: bcm63xx Socket Controller");