xref: /openbmc/linux/drivers/i2c/busses/i2c-powermac.c (revision 810ad7b62c0f075dc44ecc781b24c7f6ba388da5)
1a28d3af2SBenjamin Herrenschmidt /*
2a28d3af2SBenjamin Herrenschmidt     i2c Support for Apple SMU Controller
3a28d3af2SBenjamin Herrenschmidt 
4a28d3af2SBenjamin Herrenschmidt     Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp.
5a28d3af2SBenjamin Herrenschmidt                        <benh@kernel.crashing.org>
6a28d3af2SBenjamin Herrenschmidt 
7a28d3af2SBenjamin Herrenschmidt     This program is free software; you can redistribute it and/or modify
8a28d3af2SBenjamin Herrenschmidt     it under the terms of the GNU General Public License as published by
9a28d3af2SBenjamin Herrenschmidt     the Free Software Foundation; either version 2 of the License, or
10a28d3af2SBenjamin Herrenschmidt     (at your option) any later version.
11a28d3af2SBenjamin Herrenschmidt 
12a28d3af2SBenjamin Herrenschmidt     This program is distributed in the hope that it will be useful,
13a28d3af2SBenjamin Herrenschmidt     but WITHOUT ANY WARRANTY; without even the implied warranty of
14a28d3af2SBenjamin Herrenschmidt     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15a28d3af2SBenjamin Herrenschmidt     GNU General Public License for more details.
16a28d3af2SBenjamin Herrenschmidt 
17a28d3af2SBenjamin Herrenschmidt     You should have received a copy of the GNU General Public License
18a28d3af2SBenjamin Herrenschmidt     along with this program; if not, write to the Free Software
19a28d3af2SBenjamin Herrenschmidt     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20a28d3af2SBenjamin Herrenschmidt 
21a28d3af2SBenjamin Herrenschmidt */
22a28d3af2SBenjamin Herrenschmidt 
23a28d3af2SBenjamin Herrenschmidt #include <linux/module.h>
24a28d3af2SBenjamin Herrenschmidt #include <linux/kernel.h>
25a28d3af2SBenjamin Herrenschmidt #include <linux/types.h>
26a28d3af2SBenjamin Herrenschmidt #include <linux/i2c.h>
27a28d3af2SBenjamin Herrenschmidt #include <linux/init.h>
28a28d3af2SBenjamin Herrenschmidt #include <linux/device.h>
29a28d3af2SBenjamin Herrenschmidt #include <linux/platform_device.h>
30a28d3af2SBenjamin Herrenschmidt #include <asm/prom.h>
31a28d3af2SBenjamin Herrenschmidt #include <asm/pmac_low_i2c.h>
32a28d3af2SBenjamin Herrenschmidt 
33a28d3af2SBenjamin Herrenschmidt MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
34a28d3af2SBenjamin Herrenschmidt MODULE_DESCRIPTION("I2C driver for Apple PowerMac");
35a28d3af2SBenjamin Herrenschmidt MODULE_LICENSE("GPL");
36a28d3af2SBenjamin Herrenschmidt 
37a28d3af2SBenjamin Herrenschmidt /*
38a28d3af2SBenjamin Herrenschmidt  * SMBUS-type transfer entrypoint
39a28d3af2SBenjamin Herrenschmidt  */
40a28d3af2SBenjamin Herrenschmidt static s32 i2c_powermac_smbus_xfer(	struct i2c_adapter*	adap,
41a28d3af2SBenjamin Herrenschmidt 					u16			addr,
42a28d3af2SBenjamin Herrenschmidt 					unsigned short		flags,
43a28d3af2SBenjamin Herrenschmidt 					char			read_write,
44a28d3af2SBenjamin Herrenschmidt 					u8			command,
45a28d3af2SBenjamin Herrenschmidt 					int			size,
46a28d3af2SBenjamin Herrenschmidt 					union i2c_smbus_data*	data)
47a28d3af2SBenjamin Herrenschmidt {
48a28d3af2SBenjamin Herrenschmidt 	struct pmac_i2c_bus	*bus = i2c_get_adapdata(adap);
49a28d3af2SBenjamin Herrenschmidt 	int			rc = 0;
50a28d3af2SBenjamin Herrenschmidt 	int			read = (read_write == I2C_SMBUS_READ);
51a28d3af2SBenjamin Herrenschmidt 	int			addrdir = (addr << 1) | read;
52a28d3af2SBenjamin Herrenschmidt 	u8			local[2];
53a28d3af2SBenjamin Herrenschmidt 
54a28d3af2SBenjamin Herrenschmidt 	rc = pmac_i2c_open(bus, 0);
55a28d3af2SBenjamin Herrenschmidt 	if (rc)
56a28d3af2SBenjamin Herrenschmidt 		return rc;
57a28d3af2SBenjamin Herrenschmidt 
58a28d3af2SBenjamin Herrenschmidt 	switch (size) {
59a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_QUICK:
60a28d3af2SBenjamin Herrenschmidt 		rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
61a28d3af2SBenjamin Herrenschmidt 		if (rc)
62a28d3af2SBenjamin Herrenschmidt 			goto bail;
63a28d3af2SBenjamin Herrenschmidt 		rc = pmac_i2c_xfer(bus, addrdir, 0, 0, NULL, 0);
64a28d3af2SBenjamin Herrenschmidt 	    	break;
65a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_BYTE:
66a28d3af2SBenjamin Herrenschmidt 		rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
67a28d3af2SBenjamin Herrenschmidt 		if (rc)
68a28d3af2SBenjamin Herrenschmidt 			goto bail;
69a28d3af2SBenjamin Herrenschmidt 		rc = pmac_i2c_xfer(bus, addrdir, 0, 0, &data->byte, 1);
70a28d3af2SBenjamin Herrenschmidt 	    	break;
71a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_BYTE_DATA:
72a28d3af2SBenjamin Herrenschmidt 		rc = pmac_i2c_setmode(bus, read ?
73a28d3af2SBenjamin Herrenschmidt 				      pmac_i2c_mode_combined :
74a28d3af2SBenjamin Herrenschmidt 				      pmac_i2c_mode_stdsub);
75a28d3af2SBenjamin Herrenschmidt 		if (rc)
76a28d3af2SBenjamin Herrenschmidt 			goto bail;
77a28d3af2SBenjamin Herrenschmidt 		rc = pmac_i2c_xfer(bus, addrdir, 1, command, &data->byte, 1);
78a28d3af2SBenjamin Herrenschmidt 	    	break;
79a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_WORD_DATA:
80a28d3af2SBenjamin Herrenschmidt 		rc = pmac_i2c_setmode(bus, read ?
81a28d3af2SBenjamin Herrenschmidt 				      pmac_i2c_mode_combined :
82a28d3af2SBenjamin Herrenschmidt 				      pmac_i2c_mode_stdsub);
83a28d3af2SBenjamin Herrenschmidt 		if (rc)
84a28d3af2SBenjamin Herrenschmidt 			goto bail;
85a28d3af2SBenjamin Herrenschmidt 		if (!read) {
86a28d3af2SBenjamin Herrenschmidt 			local[0] = data->word & 0xff;
87a28d3af2SBenjamin Herrenschmidt 			local[1] = (data->word >> 8) & 0xff;
88a28d3af2SBenjamin Herrenschmidt 		}
89a28d3af2SBenjamin Herrenschmidt 		rc = pmac_i2c_xfer(bus, addrdir, 1, command, local, 2);
90a28d3af2SBenjamin Herrenschmidt 		if (rc == 0 && read) {
91a28d3af2SBenjamin Herrenschmidt 			data->word = ((u16)local[1]) << 8;
92a28d3af2SBenjamin Herrenschmidt 			data->word |= local[0];
93a28d3af2SBenjamin Herrenschmidt 		}
94a28d3af2SBenjamin Herrenschmidt 	    	break;
95a28d3af2SBenjamin Herrenschmidt 
96a28d3af2SBenjamin Herrenschmidt 	/* Note that these are broken vs. the expected smbus API where
9796acafe0SJoe Perches 	 * on reads, the length is actually returned from the function,
98a28d3af2SBenjamin Herrenschmidt 	 * but I think the current API makes no sense and I don't want
99a28d3af2SBenjamin Herrenschmidt 	 * any driver that I haven't verified for correctness to go
100a28d3af2SBenjamin Herrenschmidt 	 * anywhere near a pmac i2c bus anyway ...
101a28d3af2SBenjamin Herrenschmidt 	 *
102a28d3af2SBenjamin Herrenschmidt 	 * I'm also not completely sure what kind of phases to do between
103a28d3af2SBenjamin Herrenschmidt 	 * the actual command and the data (what I am _supposed_ to do that
104a28d3af2SBenjamin Herrenschmidt 	 * is). For now, I assume writes are a single stream and reads have
105a28d3af2SBenjamin Herrenschmidt 	 * a repeat start/addr phase (but not stop in between)
106a28d3af2SBenjamin Herrenschmidt 	 */
107a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_BLOCK_DATA:
108a28d3af2SBenjamin Herrenschmidt 		rc = pmac_i2c_setmode(bus, read ?
109a28d3af2SBenjamin Herrenschmidt 				      pmac_i2c_mode_combined :
110a28d3af2SBenjamin Herrenschmidt 				      pmac_i2c_mode_stdsub);
111a28d3af2SBenjamin Herrenschmidt 		if (rc)
112a28d3af2SBenjamin Herrenschmidt 			goto bail;
113a28d3af2SBenjamin Herrenschmidt 		rc = pmac_i2c_xfer(bus, addrdir, 1, command, data->block,
114a28d3af2SBenjamin Herrenschmidt 				   data->block[0] + 1);
115a28d3af2SBenjamin Herrenschmidt 
116a28d3af2SBenjamin Herrenschmidt 		break;
117a28d3af2SBenjamin Herrenschmidt 	case I2C_SMBUS_I2C_BLOCK_DATA:
118a28d3af2SBenjamin Herrenschmidt 		rc = pmac_i2c_setmode(bus, read ?
119a28d3af2SBenjamin Herrenschmidt 				      pmac_i2c_mode_combined :
120a28d3af2SBenjamin Herrenschmidt 				      pmac_i2c_mode_stdsub);
121a28d3af2SBenjamin Herrenschmidt 		if (rc)
122a28d3af2SBenjamin Herrenschmidt 			goto bail;
123a28d3af2SBenjamin Herrenschmidt 		rc = pmac_i2c_xfer(bus, addrdir, 1, command,
1244b2643d7SJean Delvare 				   &data->block[1], data->block[0]);
125a28d3af2SBenjamin Herrenschmidt 		break;
126a28d3af2SBenjamin Herrenschmidt 
127a28d3af2SBenjamin Herrenschmidt         default:
128a28d3af2SBenjamin Herrenschmidt 	    	rc = -EINVAL;
129a28d3af2SBenjamin Herrenschmidt 	}
130a28d3af2SBenjamin Herrenschmidt  bail:
131a28d3af2SBenjamin Herrenschmidt 	pmac_i2c_close(bus);
132a28d3af2SBenjamin Herrenschmidt 	return rc;
133a28d3af2SBenjamin Herrenschmidt }
134a28d3af2SBenjamin Herrenschmidt 
135a28d3af2SBenjamin Herrenschmidt /*
136a28d3af2SBenjamin Herrenschmidt  * Generic i2c master transfer entrypoint. This driver only support single
137a28d3af2SBenjamin Herrenschmidt  * messages (for "lame i2c" transfers). Anything else should use the smbus
138a28d3af2SBenjamin Herrenschmidt  * entry point
139a28d3af2SBenjamin Herrenschmidt  */
140a28d3af2SBenjamin Herrenschmidt static int i2c_powermac_master_xfer(	struct i2c_adapter *adap,
141a28d3af2SBenjamin Herrenschmidt 					struct i2c_msg *msgs,
142a28d3af2SBenjamin Herrenschmidt 					int num)
143a28d3af2SBenjamin Herrenschmidt {
144a28d3af2SBenjamin Herrenschmidt 	struct pmac_i2c_bus	*bus = i2c_get_adapdata(adap);
145a28d3af2SBenjamin Herrenschmidt 	int			rc = 0;
146a28d3af2SBenjamin Herrenschmidt 	int			read;
147a28d3af2SBenjamin Herrenschmidt 	int			addrdir;
148a28d3af2SBenjamin Herrenschmidt 
149a28d3af2SBenjamin Herrenschmidt 	if (msgs->flags & I2C_M_TEN)
150a28d3af2SBenjamin Herrenschmidt 		return -EINVAL;
151a28d3af2SBenjamin Herrenschmidt 	read = (msgs->flags & I2C_M_RD) != 0;
152a28d3af2SBenjamin Herrenschmidt 	addrdir = (msgs->addr << 1) | read;
153a28d3af2SBenjamin Herrenschmidt 	if (msgs->flags & I2C_M_REV_DIR_ADDR)
154a28d3af2SBenjamin Herrenschmidt 		addrdir ^= 1;
155a28d3af2SBenjamin Herrenschmidt 
156a28d3af2SBenjamin Herrenschmidt 	rc = pmac_i2c_open(bus, 0);
157a28d3af2SBenjamin Herrenschmidt 	if (rc)
158a28d3af2SBenjamin Herrenschmidt 		return rc;
159a28d3af2SBenjamin Herrenschmidt 	rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
160a28d3af2SBenjamin Herrenschmidt 	if (rc)
161a28d3af2SBenjamin Herrenschmidt 		goto bail;
162a28d3af2SBenjamin Herrenschmidt 	rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len);
163a28d3af2SBenjamin Herrenschmidt  bail:
164a28d3af2SBenjamin Herrenschmidt 	pmac_i2c_close(bus);
1658ced8eeeSJean Delvare 	return rc < 0 ? rc : 1;
166a28d3af2SBenjamin Herrenschmidt }
167a28d3af2SBenjamin Herrenschmidt 
168a28d3af2SBenjamin Herrenschmidt static u32 i2c_powermac_func(struct i2c_adapter * adapter)
169a28d3af2SBenjamin Herrenschmidt {
170a28d3af2SBenjamin Herrenschmidt 	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
171a28d3af2SBenjamin Herrenschmidt 		I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
172a28d3af2SBenjamin Herrenschmidt 		I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_I2C;
173a28d3af2SBenjamin Herrenschmidt }
174a28d3af2SBenjamin Herrenschmidt 
175a28d3af2SBenjamin Herrenschmidt /* For now, we only handle smbus */
1768f9082c5SJean Delvare static const struct i2c_algorithm i2c_powermac_algorithm = {
177a28d3af2SBenjamin Herrenschmidt 	.smbus_xfer	= i2c_powermac_smbus_xfer,
178a28d3af2SBenjamin Herrenschmidt 	.master_xfer	= i2c_powermac_master_xfer,
179a28d3af2SBenjamin Herrenschmidt 	.functionality	= i2c_powermac_func,
180a28d3af2SBenjamin Herrenschmidt };
181a28d3af2SBenjamin Herrenschmidt 
182a28d3af2SBenjamin Herrenschmidt 
1834ebb52d3SUwe Kleine-Koenig static int __devexit i2c_powermac_remove(struct platform_device *dev)
184a28d3af2SBenjamin Herrenschmidt {
1859f2545c1SBenjamin Herrenschmidt 	struct i2c_adapter	*adapter = platform_get_drvdata(dev);
186a28d3af2SBenjamin Herrenschmidt 	struct pmac_i2c_bus	*bus = i2c_get_adapdata(adapter);
187a28d3af2SBenjamin Herrenschmidt 	int			rc;
188a28d3af2SBenjamin Herrenschmidt 
189a28d3af2SBenjamin Herrenschmidt 	rc = i2c_del_adapter(adapter);
190a28d3af2SBenjamin Herrenschmidt 	pmac_i2c_detach_adapter(bus, adapter);
191a28d3af2SBenjamin Herrenschmidt 	i2c_set_adapdata(adapter, NULL);
192a28d3af2SBenjamin Herrenschmidt 	/* We aren't that prepared to deal with this... */
193a28d3af2SBenjamin Herrenschmidt 	if (rc)
194a28d3af2SBenjamin Herrenschmidt 		printk("i2c-powermac.c: Failed to remove bus %s !\n",
195a28d3af2SBenjamin Herrenschmidt 		       adapter->name);
1969f2545c1SBenjamin Herrenschmidt 	platform_set_drvdata(dev, NULL);
197a28d3af2SBenjamin Herrenschmidt 	kfree(adapter);
198a28d3af2SBenjamin Herrenschmidt 
199a28d3af2SBenjamin Herrenschmidt 	return 0;
200a28d3af2SBenjamin Herrenschmidt }
201a28d3af2SBenjamin Herrenschmidt 
202a28d3af2SBenjamin Herrenschmidt 
2034ebb52d3SUwe Kleine-Koenig static int __devinit i2c_powermac_probe(struct platform_device *dev)
204a28d3af2SBenjamin Herrenschmidt {
2059f2545c1SBenjamin Herrenschmidt 	struct pmac_i2c_bus *bus = dev->dev.platform_data;
206a28d3af2SBenjamin Herrenschmidt 	struct device_node *parent = NULL;
207a28d3af2SBenjamin Herrenschmidt 	struct i2c_adapter *adapter;
208018a3d1dSJeremy Kerr 	char name[32];
209018a3d1dSJeremy Kerr 	const char *basename;
210a28d3af2SBenjamin Herrenschmidt 	int rc;
211a28d3af2SBenjamin Herrenschmidt 
212a28d3af2SBenjamin Herrenschmidt 	if (bus == NULL)
213a28d3af2SBenjamin Herrenschmidt 		return -EINVAL;
214a28d3af2SBenjamin Herrenschmidt 
215a28d3af2SBenjamin Herrenschmidt 	/* Ok, now we need to make up a name for the interface that will
216a28d3af2SBenjamin Herrenschmidt 	 * match what we used to do in the past, that is basically the
217a28d3af2SBenjamin Herrenschmidt 	 * controller's parent device node for keywest. PMU didn't have a
218a28d3af2SBenjamin Herrenschmidt 	 * naming convention and SMU has a different one
219a28d3af2SBenjamin Herrenschmidt 	 */
220a28d3af2SBenjamin Herrenschmidt 	switch(pmac_i2c_get_type(bus)) {
221a28d3af2SBenjamin Herrenschmidt 	case pmac_i2c_bus_keywest:
222a28d3af2SBenjamin Herrenschmidt 		parent = of_get_parent(pmac_i2c_get_controller(bus));
223a28d3af2SBenjamin Herrenschmidt 		if (parent == NULL)
224a28d3af2SBenjamin Herrenschmidt 			return -EINVAL;
225a28d3af2SBenjamin Herrenschmidt 		basename = parent->name;
226a28d3af2SBenjamin Herrenschmidt 		break;
227a28d3af2SBenjamin Herrenschmidt 	case pmac_i2c_bus_pmu:
228a28d3af2SBenjamin Herrenschmidt 		basename = "pmu";
229a28d3af2SBenjamin Herrenschmidt 		break;
230a28d3af2SBenjamin Herrenschmidt 	case pmac_i2c_bus_smu:
231a28d3af2SBenjamin Herrenschmidt 		/* This is not what we used to do but I'm fixing drivers at
232a28d3af2SBenjamin Herrenschmidt 		 * the same time as this change
233a28d3af2SBenjamin Herrenschmidt 		 */
234a28d3af2SBenjamin Herrenschmidt 		basename = "smu";
235a28d3af2SBenjamin Herrenschmidt 		break;
236a28d3af2SBenjamin Herrenschmidt 	default:
237a28d3af2SBenjamin Herrenschmidt 		return -EINVAL;
238a28d3af2SBenjamin Herrenschmidt 	}
239a28d3af2SBenjamin Herrenschmidt 	snprintf(name, 32, "%s %d", basename, pmac_i2c_get_channel(bus));
240a28d3af2SBenjamin Herrenschmidt 	of_node_put(parent);
241a28d3af2SBenjamin Herrenschmidt 
242a28d3af2SBenjamin Herrenschmidt 	adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
243a28d3af2SBenjamin Herrenschmidt 	if (adapter == NULL) {
244a28d3af2SBenjamin Herrenschmidt 		printk(KERN_ERR "i2c-powermac: can't allocate inteface !\n");
245a28d3af2SBenjamin Herrenschmidt 		return -ENOMEM;
246a28d3af2SBenjamin Herrenschmidt 	}
2479f2545c1SBenjamin Herrenschmidt 	platform_set_drvdata(dev, adapter);
248a28d3af2SBenjamin Herrenschmidt 	strcpy(adapter->name, name);
249a28d3af2SBenjamin Herrenschmidt 	adapter->algo = &i2c_powermac_algorithm;
250a28d3af2SBenjamin Herrenschmidt 	i2c_set_adapdata(adapter, bus);
2519f2545c1SBenjamin Herrenschmidt 	adapter->dev.parent = &dev->dev;
252a28d3af2SBenjamin Herrenschmidt 	pmac_i2c_attach_adapter(bus, adapter);
253a28d3af2SBenjamin Herrenschmidt 	rc = i2c_add_adapter(adapter);
254a28d3af2SBenjamin Herrenschmidt 	if (rc) {
255a28d3af2SBenjamin Herrenschmidt 		printk(KERN_ERR "i2c-powermac: Adapter %s registration "
256a28d3af2SBenjamin Herrenschmidt 		       "failed\n", name);
257a28d3af2SBenjamin Herrenschmidt 		i2c_set_adapdata(adapter, NULL);
258a28d3af2SBenjamin Herrenschmidt 		pmac_i2c_detach_adapter(bus, adapter);
259a28d3af2SBenjamin Herrenschmidt 	}
260a28d3af2SBenjamin Herrenschmidt 
261a28d3af2SBenjamin Herrenschmidt 	printk(KERN_INFO "PowerMac i2c bus %s registered\n", name);
262*810ad7b6SJean Delvare 
263*810ad7b6SJean Delvare 	if (!strncmp(basename, "uni-n", 5)) {
264*810ad7b6SJean Delvare 		struct device_node *np;
265*810ad7b6SJean Delvare 		const u32 *prop;
266*810ad7b6SJean Delvare 		struct i2c_board_info info;
267*810ad7b6SJean Delvare 
268*810ad7b6SJean Delvare 		/* Instantiate I2C motion sensor if present */
269*810ad7b6SJean Delvare 		np = of_find_node_by_name(NULL, "accelerometer");
270*810ad7b6SJean Delvare 		if (np && of_device_is_compatible(np, "AAPL,accelerometer_1") &&
271*810ad7b6SJean Delvare 		    (prop = of_get_property(np, "reg", NULL))) {
272*810ad7b6SJean Delvare 			int i2c_bus;
273*810ad7b6SJean Delvare 			const char *tmp_bus;
274*810ad7b6SJean Delvare 
275*810ad7b6SJean Delvare 			/* look for bus either using "reg" or by path */
276*810ad7b6SJean Delvare 			tmp_bus = strstr(np->full_name, "/i2c-bus@");
277*810ad7b6SJean Delvare 			if (tmp_bus)
278*810ad7b6SJean Delvare 				i2c_bus = *(tmp_bus + 9) - '0';
279*810ad7b6SJean Delvare 			else
280*810ad7b6SJean Delvare 				i2c_bus = ((*prop) >> 8) & 0x0f;
281*810ad7b6SJean Delvare 
282*810ad7b6SJean Delvare 			if (pmac_i2c_get_channel(bus) == i2c_bus) {
283*810ad7b6SJean Delvare 				memset(&info, 0, sizeof(struct i2c_board_info));
284*810ad7b6SJean Delvare 				info.addr = ((*prop) & 0xff) >> 1;
285*810ad7b6SJean Delvare 				strlcpy(info.type, "ams", I2C_NAME_SIZE);
286*810ad7b6SJean Delvare 				i2c_new_device(adapter, &info);
287*810ad7b6SJean Delvare 			}
288*810ad7b6SJean Delvare 		}
289*810ad7b6SJean Delvare 	}
290*810ad7b6SJean Delvare 
291a28d3af2SBenjamin Herrenschmidt 	return rc;
292a28d3af2SBenjamin Herrenschmidt }
293a28d3af2SBenjamin Herrenschmidt 
294a28d3af2SBenjamin Herrenschmidt 
295add8eda7SKay Sievers /* work with hotplug and coldplug */
296add8eda7SKay Sievers MODULE_ALIAS("platform:i2c-powermac");
297add8eda7SKay Sievers 
2989f2545c1SBenjamin Herrenschmidt static struct platform_driver i2c_powermac_driver = {
2999f2545c1SBenjamin Herrenschmidt 	.probe = i2c_powermac_probe,
3009f2545c1SBenjamin Herrenschmidt 	.remove = __devexit_p(i2c_powermac_remove),
3019f2545c1SBenjamin Herrenschmidt 	.driver = {
302a28d3af2SBenjamin Herrenschmidt 		.name = "i2c-powermac",
303a28d3af2SBenjamin Herrenschmidt 		.bus = &platform_bus_type,
3049f2545c1SBenjamin Herrenschmidt 	},
305a28d3af2SBenjamin Herrenschmidt };
306a28d3af2SBenjamin Herrenschmidt 
307a28d3af2SBenjamin Herrenschmidt static int __init i2c_powermac_init(void)
308a28d3af2SBenjamin Herrenschmidt {
3099f2545c1SBenjamin Herrenschmidt 	platform_driver_register(&i2c_powermac_driver);
310a28d3af2SBenjamin Herrenschmidt 	return 0;
311a28d3af2SBenjamin Herrenschmidt }
312a28d3af2SBenjamin Herrenschmidt 
313a28d3af2SBenjamin Herrenschmidt 
314a28d3af2SBenjamin Herrenschmidt static void __exit i2c_powermac_cleanup(void)
315a28d3af2SBenjamin Herrenschmidt {
3169f2545c1SBenjamin Herrenschmidt 	platform_driver_unregister(&i2c_powermac_driver);
317a28d3af2SBenjamin Herrenschmidt }
318a28d3af2SBenjamin Herrenschmidt 
319a28d3af2SBenjamin Herrenschmidt module_init(i2c_powermac_init);
320a28d3af2SBenjamin Herrenschmidt module_exit(i2c_powermac_cleanup);
321