i2c-pxa-pci.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * The CE4100's I2C device is more or less the same one as found on PXA.
  3. * It does not support slave mode, the register slightly moved. This PCI
  4. * device provides three bars, every contains a single I2C controller.
  5. */
  6. #include <linux/module.h>
  7. #include <linux/pci.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/i2c/pxa-i2c.h>
  10. #include <linux/of.h>
  11. #include <linux/of_device.h>
  12. #include <linux/of_address.h>
  13. #define CE4100_PCI_I2C_DEVS 3
  14. struct ce4100_devices {
  15. struct platform_device *pdev[CE4100_PCI_I2C_DEVS];
  16. };
  17. static struct platform_device *add_i2c_device(struct pci_dev *dev, int bar)
  18. {
  19. struct platform_device *pdev;
  20. struct i2c_pxa_platform_data pdata;
  21. struct resource res[2];
  22. struct device_node *child;
  23. static int devnum;
  24. int ret;
  25. memset(&pdata, 0, sizeof(struct i2c_pxa_platform_data));
  26. memset(&res, 0, sizeof(res));
  27. res[0].flags = IORESOURCE_MEM;
  28. res[0].start = pci_resource_start(dev, bar);
  29. res[0].end = pci_resource_end(dev, bar);
  30. res[1].flags = IORESOURCE_IRQ;
  31. res[1].start = dev->irq;
  32. res[1].end = dev->irq;
  33. for_each_child_of_node(dev->dev.of_node, child) {
  34. const void *prop;
  35. struct resource r;
  36. int ret;
  37. ret = of_address_to_resource(child, 0, &r);
  38. if (ret < 0)
  39. continue;
  40. if (r.start != res[0].start)
  41. continue;
  42. if (r.end != res[0].end)
  43. continue;
  44. if (r.flags != res[0].flags)
  45. continue;
  46. prop = of_get_property(child, "fast-mode", NULL);
  47. if (prop)
  48. pdata.fast_mode = 1;
  49. break;
  50. }
  51. if (!child) {
  52. dev_err(&dev->dev, "failed to match a DT node for bar %d.\n",
  53. bar);
  54. ret = -EINVAL;
  55. goto out;
  56. }
  57. pdev = platform_device_alloc("ce4100-i2c", devnum);
  58. if (!pdev) {
  59. of_node_put(child);
  60. ret = -ENOMEM;
  61. goto out;
  62. }
  63. pdev->dev.parent = &dev->dev;
  64. pdev->dev.of_node = child;
  65. ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
  66. if (ret)
  67. goto err;
  68. ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
  69. if (ret)
  70. goto err;
  71. ret = platform_device_add(pdev);
  72. if (ret)
  73. goto err;
  74. devnum++;
  75. return pdev;
  76. err:
  77. platform_device_put(pdev);
  78. out:
  79. return ERR_PTR(ret);
  80. }
  81. static int ce4100_i2c_probe(struct pci_dev *dev,
  82. const struct pci_device_id *ent)
  83. {
  84. int ret;
  85. int i;
  86. struct ce4100_devices *sds;
  87. ret = pci_enable_device_mem(dev);
  88. if (ret)
  89. return ret;
  90. if (!dev->dev.of_node) {
  91. dev_err(&dev->dev, "Missing device tree node.\n");
  92. return -EINVAL;
  93. }
  94. sds = kzalloc(sizeof(*sds), GFP_KERNEL);
  95. if (!sds) {
  96. ret = -ENOMEM;
  97. goto err_mem;
  98. }
  99. for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) {
  100. sds->pdev[i] = add_i2c_device(dev, i);
  101. if (IS_ERR(sds->pdev[i])) {
  102. ret = PTR_ERR(sds->pdev[i]);
  103. while (--i >= 0)
  104. platform_device_unregister(sds->pdev[i]);
  105. goto err_dev_add;
  106. }
  107. }
  108. pci_set_drvdata(dev, sds);
  109. return 0;
  110. err_dev_add:
  111. kfree(sds);
  112. err_mem:
  113. pci_disable_device(dev);
  114. return ret;
  115. }
  116. static void ce4100_i2c_remove(struct pci_dev *dev)
  117. {
  118. struct ce4100_devices *sds;
  119. unsigned int i;
  120. sds = pci_get_drvdata(dev);
  121. for (i = 0; i < ARRAY_SIZE(sds->pdev); i++)
  122. platform_device_unregister(sds->pdev[i]);
  123. pci_disable_device(dev);
  124. kfree(sds);
  125. }
  126. static const struct pci_device_id ce4100_i2c_devices[] = {
  127. { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e68)},
  128. { },
  129. };
  130. MODULE_DEVICE_TABLE(pci, ce4100_i2c_devices);
  131. static struct pci_driver ce4100_i2c_driver = {
  132. .name = "ce4100_i2c",
  133. .id_table = ce4100_i2c_devices,
  134. .probe = ce4100_i2c_probe,
  135. .remove = ce4100_i2c_remove,
  136. };
  137. module_pci_driver(ce4100_i2c_driver);
  138. MODULE_DESCRIPTION("CE4100 PCI-I2C glue code for PXA's driver");
  139. MODULE_LICENSE("GPL v2");
  140. MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");