xref: /openbmc/linux/drivers/i2c/busses/i2c-pxa-pci.c (revision 7a703ade)
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/pci.h>
7 #include <linux/platform_device.h>
8 #include <linux/i2c/pxa-i2c.h>
9 #include <linux/of.h>
10 #include <linux/of_device.h>
11 #include <linux/of_address.h>
12 
13 #define CE4100_PCI_I2C_DEVS	3
14 
15 struct ce4100_devices {
16 	struct platform_device *pdev[CE4100_PCI_I2C_DEVS];
17 };
18 
19 static struct platform_device *add_i2c_device(struct pci_dev *dev, int bar)
20 {
21 	struct platform_device *pdev;
22 	struct i2c_pxa_platform_data pdata;
23 	struct resource res[2];
24 	struct device_node *child;
25 	static int devnum;
26 	int ret;
27 
28 	memset(&pdata, 0, sizeof(struct i2c_pxa_platform_data));
29 	memset(&res, 0, sizeof(res));
30 
31 	res[0].flags = IORESOURCE_MEM;
32 	res[0].start = pci_resource_start(dev, bar);
33 	res[0].end = pci_resource_end(dev, bar);
34 
35 	res[1].flags = IORESOURCE_IRQ;
36 	res[1].start = dev->irq;
37 	res[1].end = dev->irq;
38 
39 	for_each_child_of_node(dev->dev.of_node, child) {
40 		const void *prop;
41 		struct resource r;
42 		int ret;
43 
44 		ret = of_address_to_resource(child, 0, &r);
45 		if (ret < 0)
46 			continue;
47 		if (r.start != res[0].start)
48 			continue;
49 		if (r.end != res[0].end)
50 			continue;
51 		if (r.flags != res[0].flags)
52 			continue;
53 
54 		prop = of_get_property(child, "fast-mode", NULL);
55 		if (prop)
56 			pdata.fast_mode = 1;
57 
58 		break;
59 	}
60 
61 	if (!child) {
62 		dev_err(&dev->dev, "failed to match a DT node for bar %d.\n",
63 				bar);
64 		ret = -EINVAL;
65 		goto out;
66 	}
67 
68 	pdev = platform_device_alloc("ce4100-i2c", devnum);
69 	if (!pdev) {
70 		of_node_put(child);
71 		ret = -ENOMEM;
72 		goto out;
73 	}
74 	pdev->dev.parent = &dev->dev;
75 	pdev->dev.of_node = child;
76 
77 	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
78 	if (ret)
79 		goto err;
80 
81 	ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
82 	if (ret)
83 		goto err;
84 
85 	ret = platform_device_add(pdev);
86 	if (ret)
87 		goto err;
88 	devnum++;
89 	return pdev;
90 err:
91 	platform_device_put(pdev);
92 out:
93 	return ERR_PTR(ret);
94 }
95 
96 static int __devinit ce4100_i2c_probe(struct pci_dev *dev,
97 		const struct pci_device_id *ent)
98 {
99 	int ret;
100 	int i;
101 	struct ce4100_devices *sds;
102 
103 	ret = pci_enable_device_mem(dev);
104 	if (ret)
105 		return ret;
106 
107 	if (!dev->dev.of_node) {
108 		dev_err(&dev->dev, "Missing device tree node.\n");
109 		return -EINVAL;
110 	}
111 	sds = kzalloc(sizeof(*sds), GFP_KERNEL);
112 	if (!sds) {
113 		ret = -ENOMEM;
114 		goto err_mem;
115 	}
116 
117 	for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) {
118 		sds->pdev[i] = add_i2c_device(dev, i);
119 		if (IS_ERR(sds->pdev[i])) {
120 			ret = PTR_ERR(sds->pdev[i]);
121 			while (--i >= 0)
122 				platform_device_unregister(sds->pdev[i]);
123 			goto err_dev_add;
124 		}
125 	}
126 	pci_set_drvdata(dev, sds);
127 	return 0;
128 
129 err_dev_add:
130 	pci_set_drvdata(dev, NULL);
131 	kfree(sds);
132 err_mem:
133 	pci_disable_device(dev);
134 	return ret;
135 }
136 
137 static void __devexit ce4100_i2c_remove(struct pci_dev *dev)
138 {
139 	struct ce4100_devices *sds;
140 	unsigned int i;
141 
142 	sds = pci_get_drvdata(dev);
143 	pci_set_drvdata(dev, NULL);
144 
145 	for (i = 0; i < ARRAY_SIZE(sds->pdev); i++)
146 		platform_device_unregister(sds->pdev[i]);
147 
148 	pci_disable_device(dev);
149 	kfree(sds);
150 }
151 
152 static struct pci_device_id ce4100_i2c_devices[] __devinitdata = {
153 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e68)},
154 	{ },
155 };
156 MODULE_DEVICE_TABLE(pci, ce4100_i2c_devices);
157 
158 static struct pci_driver ce4100_i2c_driver = {
159 	.name           = "ce4100_i2c",
160 	.id_table       = ce4100_i2c_devices,
161 	.probe          = ce4100_i2c_probe,
162 	.remove         = __devexit_p(ce4100_i2c_remove),
163 };
164 
165 static int __init ce4100_i2c_init(void)
166 {
167 	return pci_register_driver(&ce4100_i2c_driver);
168 }
169 module_init(ce4100_i2c_init);
170 
171 static void __exit ce4100_i2c_exit(void)
172 {
173 	pci_unregister_driver(&ce4100_i2c_driver);
174 }
175 module_exit(ce4100_i2c_exit);
176 
177 MODULE_DESCRIPTION("CE4100 PCI-I2C glue code for PXA's driver");
178 MODULE_LICENSE("GPL v2");
179 MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
180