janz-cmodio.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. * Janz CMOD-IO MODULbus Carrier Board PCI Driver
  3. *
  4. * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu>
  5. *
  6. * Lots of inspiration and code was copied from drivers/mfd/sm501.c
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2 of the License, or (at your
  11. * option) any later version.
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/init.h>
  16. #include <linux/pci.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/delay.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/slab.h>
  21. #include <linux/mfd/core.h>
  22. #include <linux/mfd/janz.h>
  23. #define DRV_NAME "janz-cmodio"
  24. /* Size of each MODULbus module in PCI BAR4 */
  25. #define CMODIO_MODULBUS_SIZE 0x200
  26. /* Maximum number of MODULbus modules on a CMOD-IO carrier board */
  27. #define CMODIO_MAX_MODULES 4
  28. /* Module Parameters */
  29. static unsigned int num_modules = CMODIO_MAX_MODULES;
  30. static unsigned char *modules[CMODIO_MAX_MODULES] = {
  31. "empty", "empty", "empty", "empty",
  32. };
  33. module_param_array(modules, charp, &num_modules, S_IRUGO);
  34. MODULE_PARM_DESC(modules, "MODULbus modules attached to the carrier board");
  35. /* Unique Device Id */
  36. static unsigned int cmodio_id;
  37. struct cmodio_device {
  38. /* Parent PCI device */
  39. struct pci_dev *pdev;
  40. /* PLX control registers */
  41. struct janz_cmodio_onboard_regs __iomem *ctrl;
  42. /* hex switch position */
  43. u8 hex;
  44. /* mfd-core API */
  45. struct mfd_cell cells[CMODIO_MAX_MODULES];
  46. struct resource resources[3 * CMODIO_MAX_MODULES];
  47. struct janz_platform_data pdata[CMODIO_MAX_MODULES];
  48. };
  49. /*
  50. * Subdevices using the mfd-core API
  51. */
  52. static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv,
  53. char *name, unsigned int devno,
  54. unsigned int modno)
  55. {
  56. struct janz_platform_data *pdata;
  57. struct mfd_cell *cell;
  58. struct resource *res;
  59. struct pci_dev *pci;
  60. pci = priv->pdev;
  61. cell = &priv->cells[devno];
  62. res = &priv->resources[devno * 3];
  63. pdata = &priv->pdata[devno];
  64. cell->name = name;
  65. cell->resources = res;
  66. cell->num_resources = 3;
  67. /* Setup the subdevice ID -- must be unique */
  68. cell->id = cmodio_id++;
  69. /* Add platform data */
  70. pdata->modno = modno;
  71. cell->mfd_data = pdata;
  72. /* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */
  73. res->flags = IORESOURCE_MEM;
  74. res->parent = &pci->resource[3];
  75. res->start = pci->resource[3].start + (CMODIO_MODULBUS_SIZE * modno);
  76. res->end = res->start + CMODIO_MODULBUS_SIZE - 1;
  77. res++;
  78. /* PLX Control Registers -- PCI BAR4 is interrupt and other registers */
  79. res->flags = IORESOURCE_MEM;
  80. res->parent = &pci->resource[4];
  81. res->start = pci->resource[4].start;
  82. res->end = pci->resource[4].end;
  83. res++;
  84. /*
  85. * IRQ
  86. *
  87. * The start and end fields are used as an offset to the irq_base
  88. * parameter passed into the mfd_add_devices() function call. All
  89. * devices share the same IRQ.
  90. */
  91. res->flags = IORESOURCE_IRQ;
  92. res->parent = NULL;
  93. res->start = 0;
  94. res->end = 0;
  95. res++;
  96. return 0;
  97. }
  98. /* Probe each submodule using kernel parameters */
  99. static int __devinit cmodio_probe_submodules(struct cmodio_device *priv)
  100. {
  101. struct pci_dev *pdev = priv->pdev;
  102. unsigned int num_probed = 0;
  103. char *name;
  104. int i;
  105. for (i = 0; i < num_modules; i++) {
  106. name = modules[i];
  107. if (!strcmp(name, "") || !strcmp(name, "empty"))
  108. continue;
  109. dev_dbg(&priv->pdev->dev, "MODULbus %d: name %s\n", i, name);
  110. cmodio_setup_subdevice(priv, name, num_probed, i);
  111. num_probed++;
  112. }
  113. /* print an error message if no modules were probed */
  114. if (num_probed == 0) {
  115. dev_err(&priv->pdev->dev, "no MODULbus modules specified, "
  116. "please set the ``modules'' kernel "
  117. "parameter according to your "
  118. "hardware configuration\n");
  119. return -ENODEV;
  120. }
  121. return mfd_add_devices(&pdev->dev, 0, priv->cells,
  122. num_probed, NULL, pdev->irq);
  123. }
  124. /*
  125. * SYSFS Attributes
  126. */
  127. static ssize_t mbus_show(struct device *dev, struct device_attribute *attr,
  128. char *buf)
  129. {
  130. struct cmodio_device *priv = dev_get_drvdata(dev);
  131. return snprintf(buf, PAGE_SIZE, "%x\n", priv->hex);
  132. }
  133. static DEVICE_ATTR(modulbus_number, S_IRUGO, mbus_show, NULL);
  134. static struct attribute *cmodio_sysfs_attrs[] = {
  135. &dev_attr_modulbus_number.attr,
  136. NULL,
  137. };
  138. static const struct attribute_group cmodio_sysfs_attr_group = {
  139. .attrs = cmodio_sysfs_attrs,
  140. };
  141. /*
  142. * PCI Driver
  143. */
  144. static int __devinit cmodio_pci_probe(struct pci_dev *dev,
  145. const struct pci_device_id *id)
  146. {
  147. struct cmodio_device *priv;
  148. int ret;
  149. priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  150. if (!priv) {
  151. dev_err(&dev->dev, "unable to allocate private data\n");
  152. ret = -ENOMEM;
  153. goto out_return;
  154. }
  155. pci_set_drvdata(dev, priv);
  156. priv->pdev = dev;
  157. /* Hardware Initialization */
  158. ret = pci_enable_device(dev);
  159. if (ret) {
  160. dev_err(&dev->dev, "unable to enable device\n");
  161. goto out_free_priv;
  162. }
  163. pci_set_master(dev);
  164. ret = pci_request_regions(dev, DRV_NAME);
  165. if (ret) {
  166. dev_err(&dev->dev, "unable to request regions\n");
  167. goto out_pci_disable_device;
  168. }
  169. /* Onboard configuration registers */
  170. priv->ctrl = pci_ioremap_bar(dev, 4);
  171. if (!priv->ctrl) {
  172. dev_err(&dev->dev, "unable to remap onboard regs\n");
  173. ret = -ENOMEM;
  174. goto out_pci_release_regions;
  175. }
  176. /* Read the hex switch on the carrier board */
  177. priv->hex = ioread8(&priv->ctrl->int_enable);
  178. /* Add the MODULbus number (hex switch value) to the device's sysfs */
  179. ret = sysfs_create_group(&dev->dev.kobj, &cmodio_sysfs_attr_group);
  180. if (ret) {
  181. dev_err(&dev->dev, "unable to create sysfs attributes\n");
  182. goto out_unmap_ctrl;
  183. }
  184. /*
  185. * Disable all interrupt lines, each submodule will enable its
  186. * own interrupt line if needed
  187. */
  188. iowrite8(0xf, &priv->ctrl->int_disable);
  189. /* Register drivers for all submodules */
  190. ret = cmodio_probe_submodules(priv);
  191. if (ret) {
  192. dev_err(&dev->dev, "unable to probe submodules\n");
  193. goto out_sysfs_remove_group;
  194. }
  195. return 0;
  196. out_sysfs_remove_group:
  197. sysfs_remove_group(&dev->dev.kobj, &cmodio_sysfs_attr_group);
  198. out_unmap_ctrl:
  199. iounmap(priv->ctrl);
  200. out_pci_release_regions:
  201. pci_release_regions(dev);
  202. out_pci_disable_device:
  203. pci_disable_device(dev);
  204. out_free_priv:
  205. kfree(priv);
  206. out_return:
  207. return ret;
  208. }
  209. static void __devexit cmodio_pci_remove(struct pci_dev *dev)
  210. {
  211. struct cmodio_device *priv = pci_get_drvdata(dev);
  212. mfd_remove_devices(&dev->dev);
  213. sysfs_remove_group(&dev->dev.kobj, &cmodio_sysfs_attr_group);
  214. iounmap(priv->ctrl);
  215. pci_release_regions(dev);
  216. pci_disable_device(dev);
  217. kfree(priv);
  218. }
  219. #define PCI_VENDOR_ID_JANZ 0x13c3
  220. /* The list of devices that this module will support */
  221. static DEFINE_PCI_DEVICE_TABLE(cmodio_pci_ids) = {
  222. { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_JANZ, 0x0101 },
  223. { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_JANZ, 0x0100 },
  224. { 0, }
  225. };
  226. MODULE_DEVICE_TABLE(pci, cmodio_pci_ids);
  227. static struct pci_driver cmodio_pci_driver = {
  228. .name = DRV_NAME,
  229. .id_table = cmodio_pci_ids,
  230. .probe = cmodio_pci_probe,
  231. .remove = __devexit_p(cmodio_pci_remove),
  232. };
  233. /*
  234. * Module Init / Exit
  235. */
  236. static int __init cmodio_init(void)
  237. {
  238. return pci_register_driver(&cmodio_pci_driver);
  239. }
  240. static void __exit cmodio_exit(void)
  241. {
  242. pci_unregister_driver(&cmodio_pci_driver);
  243. }
  244. MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
  245. MODULE_DESCRIPTION("Janz CMOD-IO PCI MODULbus Carrier Board Driver");
  246. MODULE_LICENSE("GPL");
  247. module_init(cmodio_init);
  248. module_exit(cmodio_exit);