janz-cmodio.c 7.0 KB

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