Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * CE4100 PCI-I2C glue code for PXA's driver
0004  * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
0005  *
0006  * The CE4100's I2C device is more or less the same one as found on PXA.
0007  * It does not support slave mode, the register slightly moved. This PCI
0008  * device provides three bars, every contains a single I2C controller.
0009  */
0010 #include <linux/init.h>
0011 #include <linux/pci.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/platform_data/i2c-pxa.h>
0014 #include <linux/of.h>
0015 #include <linux/of_device.h>
0016 #include <linux/of_address.h>
0017 
0018 #define CE4100_PCI_I2C_DEVS 3
0019 
0020 struct ce4100_devices {
0021     struct platform_device *pdev[CE4100_PCI_I2C_DEVS];
0022 };
0023 
0024 static struct platform_device *add_i2c_device(struct pci_dev *dev, int bar)
0025 {
0026     struct platform_device *pdev;
0027     struct i2c_pxa_platform_data pdata;
0028     struct resource res[2];
0029     struct device_node *child;
0030     static int devnum;
0031     int ret;
0032 
0033     memset(&pdata, 0, sizeof(struct i2c_pxa_platform_data));
0034     memset(&res, 0, sizeof(res));
0035 
0036     res[0].flags = IORESOURCE_MEM;
0037     res[0].start = pci_resource_start(dev, bar);
0038     res[0].end = pci_resource_end(dev, bar);
0039 
0040     res[1].flags = IORESOURCE_IRQ;
0041     res[1].start = dev->irq;
0042     res[1].end = dev->irq;
0043 
0044     for_each_child_of_node(dev->dev.of_node, child) {
0045         const void *prop;
0046         struct resource r;
0047         int ret;
0048 
0049         ret = of_address_to_resource(child, 0, &r);
0050         if (ret < 0)
0051             continue;
0052         if (r.start != res[0].start)
0053             continue;
0054         if (r.end != res[0].end)
0055             continue;
0056         if (r.flags != res[0].flags)
0057             continue;
0058 
0059         prop = of_get_property(child, "fast-mode", NULL);
0060         if (prop)
0061             pdata.fast_mode = 1;
0062 
0063         break;
0064     }
0065 
0066     if (!child) {
0067         dev_err(&dev->dev, "failed to match a DT node for bar %d.\n",
0068                 bar);
0069         ret = -EINVAL;
0070         goto out;
0071     }
0072 
0073     pdev = platform_device_alloc("ce4100-i2c", devnum);
0074     if (!pdev) {
0075         of_node_put(child);
0076         ret = -ENOMEM;
0077         goto out;
0078     }
0079     pdev->dev.parent = &dev->dev;
0080     pdev->dev.of_node = child;
0081 
0082     ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
0083     if (ret)
0084         goto err;
0085 
0086     ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
0087     if (ret)
0088         goto err;
0089 
0090     ret = platform_device_add(pdev);
0091     if (ret)
0092         goto err;
0093     devnum++;
0094     return pdev;
0095 err:
0096     platform_device_put(pdev);
0097 out:
0098     return ERR_PTR(ret);
0099 }
0100 
0101 static int ce4100_i2c_probe(struct pci_dev *dev,
0102         const struct pci_device_id *ent)
0103 {
0104     int ret;
0105     int i;
0106     struct ce4100_devices *sds;
0107 
0108     ret = pci_enable_device_mem(dev);
0109     if (ret)
0110         return ret;
0111 
0112     if (!dev->dev.of_node) {
0113         dev_err(&dev->dev, "Missing device tree node.\n");
0114         return -EINVAL;
0115     }
0116     sds = kzalloc(sizeof(*sds), GFP_KERNEL);
0117     if (!sds) {
0118         ret = -ENOMEM;
0119         goto err_mem;
0120     }
0121 
0122     for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) {
0123         sds->pdev[i] = add_i2c_device(dev, i);
0124         if (IS_ERR(sds->pdev[i])) {
0125             ret = PTR_ERR(sds->pdev[i]);
0126             while (--i >= 0)
0127                 platform_device_unregister(sds->pdev[i]);
0128             goto err_dev_add;
0129         }
0130     }
0131     pci_set_drvdata(dev, sds);
0132     return 0;
0133 
0134 err_dev_add:
0135     kfree(sds);
0136 err_mem:
0137     pci_disable_device(dev);
0138     return ret;
0139 }
0140 
0141 static const struct pci_device_id ce4100_i2c_devices[] = {
0142     { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e68)},
0143     { },
0144 };
0145 
0146 static struct pci_driver ce4100_i2c_driver = {
0147     .driver = {
0148         .suppress_bind_attrs = true,
0149     },
0150     .name           = "ce4100_i2c",
0151     .id_table       = ce4100_i2c_devices,
0152     .probe          = ce4100_i2c_probe,
0153 };
0154 builtin_pci_driver(ce4100_i2c_driver);