bcm63xx_pcmcia.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  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 <mbizon@freebox.fr>
  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, *irq_res;
  265. unsigned int regmem_size = 0, iomem_size = 0;
  266. u32 val;
  267. int ret;
  268. skt = kzalloc(sizeof(*skt), GFP_KERNEL);
  269. if (!skt)
  270. return -ENOMEM;
  271. spin_lock_init(&skt->lock);
  272. sock = &skt->socket;
  273. sock->driver_data = skt;
  274. /* make sure we have all resources we need */
  275. skt->common_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  276. skt->attr_res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
  277. irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  278. skt->pd = pdev->dev.platform_data;
  279. if (!skt->common_res || !skt->attr_res || !irq_res || !skt->pd) {
  280. ret = -EINVAL;
  281. goto err;
  282. }
  283. /* remap pcmcia registers */
  284. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  285. regmem_size = resource_size(res);
  286. if (!request_mem_region(res->start, regmem_size, "bcm63xx_pcmcia")) {
  287. ret = -EINVAL;
  288. goto err;
  289. }
  290. skt->reg_res = res;
  291. skt->base = ioremap(res->start, regmem_size);
  292. if (!skt->base) {
  293. ret = -ENOMEM;
  294. goto err;
  295. }
  296. /* remap io registers */
  297. res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
  298. iomem_size = resource_size(res);
  299. skt->io_base = ioremap(res->start, iomem_size);
  300. if (!skt->io_base) {
  301. ret = -ENOMEM;
  302. goto err;
  303. }
  304. /* resources are static */
  305. sock->resource_ops = &pccard_static_ops;
  306. sock->ops = &bcm63xx_pcmcia_operations;
  307. sock->owner = THIS_MODULE;
  308. sock->dev.parent = &pdev->dev;
  309. sock->features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
  310. sock->io_offset = (unsigned long)skt->io_base;
  311. sock->pci_irq = irq_res->start;
  312. #ifdef CONFIG_CARDBUS
  313. sock->cb_dev = bcm63xx_cb_dev;
  314. if (bcm63xx_cb_dev)
  315. sock->features |= SS_CAP_CARDBUS;
  316. #endif
  317. /* assume common & attribute memory have the same size */
  318. sock->map_size = resource_size(skt->common_res);
  319. /* initialize polling timer */
  320. timer_setup(&skt->timer, bcm63xx_pcmcia_poll, 0);
  321. /* initialize pcmcia control register, drive VS[12] to 0,
  322. * leave CB IDSEL to the old value since it is set by the PCI
  323. * layer */
  324. val = pcmcia_readl(skt, PCMCIA_C1_REG);
  325. val &= PCMCIA_C1_CBIDSEL_MASK;
  326. val |= PCMCIA_C1_EN_PCMCIA_GPIO_MASK;
  327. pcmcia_writel(skt, val, PCMCIA_C1_REG);
  328. /*
  329. * Hardware has only one set of timings registers, not one for
  330. * each memory access type, so we configure them for the
  331. * slowest one: attribute memory.
  332. */
  333. val = PCMCIA_C2_DATA16_MASK;
  334. val |= 10 << PCMCIA_C2_RWCOUNT_SHIFT;
  335. val |= 6 << PCMCIA_C2_INACTIVE_SHIFT;
  336. val |= 3 << PCMCIA_C2_SETUP_SHIFT;
  337. val |= 3 << PCMCIA_C2_HOLD_SHIFT;
  338. pcmcia_writel(skt, val, PCMCIA_C2_REG);
  339. ret = pcmcia_register_socket(sock);
  340. if (ret)
  341. goto err;
  342. /* start polling socket */
  343. mod_timer(&skt->timer,
  344. jiffies + msecs_to_jiffies(BCM63XX_PCMCIA_POLL_RATE));
  345. platform_set_drvdata(pdev, skt);
  346. return 0;
  347. err:
  348. if (skt->io_base)
  349. iounmap(skt->io_base);
  350. if (skt->base)
  351. iounmap(skt->base);
  352. if (skt->reg_res)
  353. release_mem_region(skt->reg_res->start, regmem_size);
  354. kfree(skt);
  355. return ret;
  356. }
  357. static int bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
  358. {
  359. struct bcm63xx_pcmcia_socket *skt;
  360. struct resource *res;
  361. skt = platform_get_drvdata(pdev);
  362. del_timer_sync(&skt->timer);
  363. iounmap(skt->base);
  364. iounmap(skt->io_base);
  365. res = skt->reg_res;
  366. release_mem_region(res->start, resource_size(res));
  367. kfree(skt);
  368. return 0;
  369. }
  370. struct platform_driver bcm63xx_pcmcia_driver = {
  371. .probe = bcm63xx_drv_pcmcia_probe,
  372. .remove = bcm63xx_drv_pcmcia_remove,
  373. .driver = {
  374. .name = "bcm63xx_pcmcia",
  375. .owner = THIS_MODULE,
  376. },
  377. };
  378. #ifdef CONFIG_CARDBUS
  379. static int bcm63xx_cb_probe(struct pci_dev *dev,
  380. const struct pci_device_id *id)
  381. {
  382. /* keep pci device */
  383. bcm63xx_cb_dev = dev;
  384. return platform_driver_register(&bcm63xx_pcmcia_driver);
  385. }
  386. static void bcm63xx_cb_exit(struct pci_dev *dev)
  387. {
  388. platform_driver_unregister(&bcm63xx_pcmcia_driver);
  389. bcm63xx_cb_dev = NULL;
  390. }
  391. static const struct pci_device_id bcm63xx_cb_table[] = {
  392. {
  393. .vendor = PCI_VENDOR_ID_BROADCOM,
  394. .device = BCM6348_CPU_ID,
  395. .subvendor = PCI_VENDOR_ID_BROADCOM,
  396. .subdevice = PCI_ANY_ID,
  397. .class = PCI_CLASS_BRIDGE_CARDBUS << 8,
  398. .class_mask = ~0,
  399. },
  400. {
  401. .vendor = PCI_VENDOR_ID_BROADCOM,
  402. .device = BCM6358_CPU_ID,
  403. .subvendor = PCI_VENDOR_ID_BROADCOM,
  404. .subdevice = PCI_ANY_ID,
  405. .class = PCI_CLASS_BRIDGE_CARDBUS << 8,
  406. .class_mask = ~0,
  407. },
  408. { },
  409. };
  410. MODULE_DEVICE_TABLE(pci, bcm63xx_cb_table);
  411. static struct pci_driver bcm63xx_cardbus_driver = {
  412. .name = "bcm63xx_cardbus",
  413. .id_table = bcm63xx_cb_table,
  414. .probe = bcm63xx_cb_probe,
  415. .remove = bcm63xx_cb_exit,
  416. };
  417. #endif
  418. /*
  419. * if cardbus support is enabled, register our platform device after
  420. * our fake cardbus bridge has been registered
  421. */
  422. static int __init bcm63xx_pcmcia_init(void)
  423. {
  424. #ifdef CONFIG_CARDBUS
  425. return pci_register_driver(&bcm63xx_cardbus_driver);
  426. #else
  427. return platform_driver_register(&bcm63xx_pcmcia_driver);
  428. #endif
  429. }
  430. static void __exit bcm63xx_pcmcia_exit(void)
  431. {
  432. #ifdef CONFIG_CARDBUS
  433. return pci_unregister_driver(&bcm63xx_cardbus_driver);
  434. #else
  435. platform_driver_unregister(&bcm63xx_pcmcia_driver);
  436. #endif
  437. }
  438. module_init(bcm63xx_pcmcia_init);
  439. module_exit(bcm63xx_pcmcia_exit);
  440. MODULE_LICENSE("GPL");
  441. MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>");
  442. MODULE_DESCRIPTION("Linux PCMCIA Card Services: bcm63xx Socket Controller");