xref: /openbmc/linux/drivers/i2c/busses/i2c-powermac.c (revision 7ee405ea068602d1fd42bf14ddc04d45733cfd7d)
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 */
18a28d3af2SBenjamin Herrenschmidt 
19a28d3af2SBenjamin Herrenschmidt #include <linux/module.h>
20a28d3af2SBenjamin Herrenschmidt #include <linux/kernel.h>
21a28d3af2SBenjamin Herrenschmidt #include <linux/types.h>
22a28d3af2SBenjamin Herrenschmidt #include <linux/i2c.h>
23a28d3af2SBenjamin Herrenschmidt #include <linux/device.h>
24a28d3af2SBenjamin Herrenschmidt #include <linux/platform_device.h>
255af50730SRob Herring #include <linux/of_irq.h>
26a28d3af2SBenjamin Herrenschmidt #include <asm/prom.h>
27a28d3af2SBenjamin Herrenschmidt #include <asm/pmac_low_i2c.h>
28a28d3af2SBenjamin Herrenschmidt 
29a28d3af2SBenjamin Herrenschmidt MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
30a28d3af2SBenjamin Herrenschmidt MODULE_DESCRIPTION("I2C driver for Apple PowerMac");
31a28d3af2SBenjamin Herrenschmidt MODULE_LICENSE("GPL");
32a28d3af2SBenjamin Herrenschmidt 
33a28d3af2SBenjamin Herrenschmidt /*
34a28d3af2SBenjamin Herrenschmidt  * SMBUS-type transfer entrypoint
35a28d3af2SBenjamin Herrenschmidt  */
36a28d3af2SBenjamin Herrenschmidt static s32 i2c_powermac_smbus_xfer(	struct i2c_adapter*	adap,
37a28d3af2SBenjamin Herrenschmidt 					u16			addr,
38a28d3af2SBenjamin Herrenschmidt 					unsigned short		flags,
39a28d3af2SBenjamin Herrenschmidt 					char			read_write,
40a28d3af2SBenjamin Herrenschmidt 					u8			command,
41a28d3af2SBenjamin Herrenschmidt 					int			size,
42a28d3af2SBenjamin Herrenschmidt 					union i2c_smbus_data*	data)
43a28d3af2SBenjamin Herrenschmidt {
44a28d3af2SBenjamin Herrenschmidt 	struct pmac_i2c_bus	*bus = i2c_get_adapdata(adap);
45a28d3af2SBenjamin Herrenschmidt 	int			rc = 0;
46a28d3af2SBenjamin Herrenschmidt 	int			read = (read_write == I2C_SMBUS_READ);
47a28d3af2SBenjamin Herrenschmidt 	int			addrdir = (addr << 1) | read;
4802864d58SJean Delvare 	int			mode, subsize, len;
4902864d58SJean Delvare 	u32			subaddr;
5002864d58SJean Delvare 	u8			*buf;
51a28d3af2SBenjamin Herrenschmidt 	u8			local[2];
52a28d3af2SBenjamin Herrenschmidt 
5302864d58SJean Delvare 	if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) {
5402864d58SJean Delvare 		mode = pmac_i2c_mode_std;
5502864d58SJean Delvare 		subsize = 0;
5602864d58SJean Delvare 		subaddr = 0;
5702864d58SJean Delvare 	} else {
5802864d58SJean Delvare 		mode = read ? pmac_i2c_mode_combined : pmac_i2c_mode_stdsub;
5902864d58SJean Delvare 		subsize = 1;
6002864d58SJean Delvare 		subaddr = command;
6102864d58SJean Delvare 	}
62a28d3af2SBenjamin Herrenschmidt 
63a28d3af2SBenjamin Herrenschmidt 	switch (size) {
64a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_QUICK:
6502864d58SJean Delvare 		buf = NULL;
6602864d58SJean Delvare 		len = 0;
67a28d3af2SBenjamin Herrenschmidt 	    	break;
68a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_BYTE:
69a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_BYTE_DATA:
7002864d58SJean Delvare 		buf = &data->byte;
7102864d58SJean Delvare 		len = 1;
72a28d3af2SBenjamin Herrenschmidt 	    	break;
73a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_WORD_DATA:
74a28d3af2SBenjamin Herrenschmidt 		if (!read) {
75a28d3af2SBenjamin Herrenschmidt 			local[0] = data->word & 0xff;
76a28d3af2SBenjamin Herrenschmidt 			local[1] = (data->word >> 8) & 0xff;
77a28d3af2SBenjamin Herrenschmidt 		}
7802864d58SJean Delvare 		buf = local;
7902864d58SJean Delvare 		len = 2;
80a28d3af2SBenjamin Herrenschmidt 	    	break;
81a28d3af2SBenjamin Herrenschmidt 
82a28d3af2SBenjamin Herrenschmidt 	/* Note that these are broken vs. the expected smbus API where
8396acafe0SJoe Perches 	 * on reads, the length is actually returned from the function,
84a28d3af2SBenjamin Herrenschmidt 	 * but I think the current API makes no sense and I don't want
85a28d3af2SBenjamin Herrenschmidt 	 * any driver that I haven't verified for correctness to go
86a28d3af2SBenjamin Herrenschmidt 	 * anywhere near a pmac i2c bus anyway ...
87a28d3af2SBenjamin Herrenschmidt 	 *
88a28d3af2SBenjamin Herrenschmidt 	 * I'm also not completely sure what kind of phases to do between
89a28d3af2SBenjamin Herrenschmidt 	 * the actual command and the data (what I am _supposed_ to do that
90a28d3af2SBenjamin Herrenschmidt 	 * is). For now, I assume writes are a single stream and reads have
91a28d3af2SBenjamin Herrenschmidt 	 * a repeat start/addr phase (but not stop in between)
92a28d3af2SBenjamin Herrenschmidt 	 */
93a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_BLOCK_DATA:
9402864d58SJean Delvare 		buf = data->block;
9502864d58SJean Delvare 		len = data->block[0] + 1;
96a28d3af2SBenjamin Herrenschmidt 		break;
97a28d3af2SBenjamin Herrenschmidt 	case I2C_SMBUS_I2C_BLOCK_DATA:
9802864d58SJean Delvare 		buf = &data->block[1];
9902864d58SJean Delvare 		len = data->block[0];
100a28d3af2SBenjamin Herrenschmidt 		break;
101a28d3af2SBenjamin Herrenschmidt 
102a28d3af2SBenjamin Herrenschmidt         default:
10302864d58SJean Delvare 		return -EINVAL;
104a28d3af2SBenjamin Herrenschmidt 	}
10502864d58SJean Delvare 
10602864d58SJean Delvare 	rc = pmac_i2c_open(bus, 0);
107d7d838a6SJean Delvare 	if (rc) {
108d7d838a6SJean Delvare 		dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
10902864d58SJean Delvare 		return rc;
110d7d838a6SJean Delvare 	}
11102864d58SJean Delvare 
11202864d58SJean Delvare 	rc = pmac_i2c_setmode(bus, mode);
113d7d838a6SJean Delvare 	if (rc) {
114d7d838a6SJean Delvare 		dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
115d7d838a6SJean Delvare 			mode, rc);
11602864d58SJean Delvare 		goto bail;
117d7d838a6SJean Delvare 	}
11802864d58SJean Delvare 
11902864d58SJean Delvare 	rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len);
120d7d838a6SJean Delvare 	if (rc) {
1218e4b980cSJean Delvare 		if (rc == -ENXIO)
1228e4b980cSJean Delvare 			dev_dbg(&adap->dev,
1238e4b980cSJean Delvare 				"I2C transfer at 0x%02x failed, size %d, "
1248e4b980cSJean Delvare 				"err %d\n", addrdir >> 1, size, rc);
1258e4b980cSJean Delvare 		else
126d7d838a6SJean Delvare 			dev_err(&adap->dev,
1278e4b980cSJean Delvare 				"I2C transfer at 0x%02x failed, size %d, "
1288e4b980cSJean Delvare 				"err %d\n", addrdir >> 1, size, rc);
12902864d58SJean Delvare 		goto bail;
130d7d838a6SJean Delvare 	}
13102864d58SJean Delvare 
13202864d58SJean Delvare 	if (size == I2C_SMBUS_WORD_DATA && read) {
13302864d58SJean Delvare 		data->word = ((u16)local[1]) << 8;
13402864d58SJean Delvare 		data->word |= local[0];
13502864d58SJean Delvare 	}
13602864d58SJean Delvare 
137a28d3af2SBenjamin Herrenschmidt  bail:
138a28d3af2SBenjamin Herrenschmidt 	pmac_i2c_close(bus);
139a28d3af2SBenjamin Herrenschmidt 	return rc;
140a28d3af2SBenjamin Herrenschmidt }
141a28d3af2SBenjamin Herrenschmidt 
142a28d3af2SBenjamin Herrenschmidt /*
143a28d3af2SBenjamin Herrenschmidt  * Generic i2c master transfer entrypoint. This driver only support single
144a28d3af2SBenjamin Herrenschmidt  * messages (for "lame i2c" transfers). Anything else should use the smbus
145a28d3af2SBenjamin Herrenschmidt  * entry point
146a28d3af2SBenjamin Herrenschmidt  */
147a28d3af2SBenjamin Herrenschmidt static int i2c_powermac_master_xfer(	struct i2c_adapter *adap,
148a28d3af2SBenjamin Herrenschmidt 					struct i2c_msg *msgs,
149a28d3af2SBenjamin Herrenschmidt 					int num)
150a28d3af2SBenjamin Herrenschmidt {
151a28d3af2SBenjamin Herrenschmidt 	struct pmac_i2c_bus	*bus = i2c_get_adapdata(adap);
152a28d3af2SBenjamin Herrenschmidt 	int			rc = 0;
153a28d3af2SBenjamin Herrenschmidt 	int			read;
154a28d3af2SBenjamin Herrenschmidt 	int			addrdir;
155a28d3af2SBenjamin Herrenschmidt 
156a28d3af2SBenjamin Herrenschmidt 	if (msgs->flags & I2C_M_TEN)
157a28d3af2SBenjamin Herrenschmidt 		return -EINVAL;
158a28d3af2SBenjamin Herrenschmidt 	read = (msgs->flags & I2C_M_RD) != 0;
159a28d3af2SBenjamin Herrenschmidt 	addrdir = (msgs->addr << 1) | read;
160a28d3af2SBenjamin Herrenschmidt 
161a28d3af2SBenjamin Herrenschmidt 	rc = pmac_i2c_open(bus, 0);
162d7d838a6SJean Delvare 	if (rc) {
163d7d838a6SJean Delvare 		dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
164a28d3af2SBenjamin Herrenschmidt 		return rc;
165d7d838a6SJean Delvare 	}
166a28d3af2SBenjamin Herrenschmidt 	rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
167d7d838a6SJean Delvare 	if (rc) {
168d7d838a6SJean Delvare 		dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
169d7d838a6SJean Delvare 			pmac_i2c_mode_std, rc);
170a28d3af2SBenjamin Herrenschmidt 		goto bail;
171d7d838a6SJean Delvare 	}
172a28d3af2SBenjamin Herrenschmidt 	rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len);
1738e4b980cSJean Delvare 	if (rc < 0) {
1748e4b980cSJean Delvare 		if (rc == -ENXIO)
1758e4b980cSJean Delvare 			dev_dbg(&adap->dev, "I2C %s 0x%02x failed, err %d\n",
1768e4b980cSJean Delvare 				addrdir & 1 ? "read from" : "write to",
1778e4b980cSJean Delvare 				addrdir >> 1, rc);
1788e4b980cSJean Delvare 		else
179d7d838a6SJean Delvare 			dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n",
1808e4b980cSJean Delvare 				addrdir & 1 ? "read from" : "write to",
1818e4b980cSJean Delvare 				addrdir >> 1, rc);
1828e4b980cSJean Delvare 	}
183a28d3af2SBenjamin Herrenschmidt  bail:
184a28d3af2SBenjamin Herrenschmidt 	pmac_i2c_close(bus);
1858ced8eeeSJean Delvare 	return rc < 0 ? rc : 1;
186a28d3af2SBenjamin Herrenschmidt }
187a28d3af2SBenjamin Herrenschmidt 
188a28d3af2SBenjamin Herrenschmidt static u32 i2c_powermac_func(struct i2c_adapter * adapter)
189a28d3af2SBenjamin Herrenschmidt {
190a28d3af2SBenjamin Herrenschmidt 	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
191a28d3af2SBenjamin Herrenschmidt 		I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
192a28d3af2SBenjamin Herrenschmidt 		I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_I2C;
193a28d3af2SBenjamin Herrenschmidt }
194a28d3af2SBenjamin Herrenschmidt 
195a28d3af2SBenjamin Herrenschmidt /* For now, we only handle smbus */
1968f9082c5SJean Delvare static const struct i2c_algorithm i2c_powermac_algorithm = {
197a28d3af2SBenjamin Herrenschmidt 	.smbus_xfer	= i2c_powermac_smbus_xfer,
198a28d3af2SBenjamin Herrenschmidt 	.master_xfer	= i2c_powermac_master_xfer,
199a28d3af2SBenjamin Herrenschmidt 	.functionality	= i2c_powermac_func,
200a28d3af2SBenjamin Herrenschmidt };
201a28d3af2SBenjamin Herrenschmidt 
202*7ee405eaSWolfram Sang static struct i2c_adapter_quirks i2c_powermac_quirks = {
203*7ee405eaSWolfram Sang 	.max_num_msgs = 1,
204*7ee405eaSWolfram Sang };
205a28d3af2SBenjamin Herrenschmidt 
2060b255e92SBill Pemberton static int i2c_powermac_remove(struct platform_device *dev)
207a28d3af2SBenjamin Herrenschmidt {
2089f2545c1SBenjamin Herrenschmidt 	struct i2c_adapter	*adapter = platform_get_drvdata(dev);
209a28d3af2SBenjamin Herrenschmidt 
210bf51a8c5SLars-Peter Clausen 	i2c_del_adapter(adapter);
2116dfa5ca3SJean Delvare 	memset(adapter, 0, sizeof(*adapter));
212a28d3af2SBenjamin Herrenschmidt 
213a28d3af2SBenjamin Herrenschmidt 	return 0;
214a28d3af2SBenjamin Herrenschmidt }
215a28d3af2SBenjamin Herrenschmidt 
2160b255e92SBill Pemberton static u32 i2c_powermac_get_addr(struct i2c_adapter *adap,
2173a3dd018SBenjamin Herrenschmidt 					   struct pmac_i2c_bus *bus,
2183a3dd018SBenjamin Herrenschmidt 					   struct device_node *node)
21981e5d864SBenjamin Herrenschmidt {
2203a3dd018SBenjamin Herrenschmidt 	const __be32 *prop;
22181e5d864SBenjamin Herrenschmidt 	int len;
22281e5d864SBenjamin Herrenschmidt 
2233a3dd018SBenjamin Herrenschmidt 	/* First check for valid "reg" */
2243a3dd018SBenjamin Herrenschmidt 	prop = of_get_property(node, "reg", &len);
2253a3dd018SBenjamin Herrenschmidt 	if (prop && (len >= sizeof(int)))
2263a3dd018SBenjamin Herrenschmidt 		return (be32_to_cpup(prop) & 0xff) >> 1;
2273a3dd018SBenjamin Herrenschmidt 
2283a3dd018SBenjamin Herrenschmidt 	/* Then check old-style "i2c-address" */
2293a3dd018SBenjamin Herrenschmidt 	prop = of_get_property(node, "i2c-address", &len);
2303a3dd018SBenjamin Herrenschmidt 	if (prop && (len >= sizeof(int)))
2313a3dd018SBenjamin Herrenschmidt 		return (be32_to_cpup(prop) & 0xff) >> 1;
2323a3dd018SBenjamin Herrenschmidt 
2333a3dd018SBenjamin Herrenschmidt 	/* Now handle some devices with missing "reg" properties */
2343a3dd018SBenjamin Herrenschmidt 	if (!strcmp(node->name, "cereal"))
2353a3dd018SBenjamin Herrenschmidt 		return 0x60;
2363a3dd018SBenjamin Herrenschmidt 	else if (!strcmp(node->name, "deq"))
2373a3dd018SBenjamin Herrenschmidt 		return 0x34;
2383a3dd018SBenjamin Herrenschmidt 
2393a3dd018SBenjamin Herrenschmidt 	dev_warn(&adap->dev, "No i2c address for %s\n", node->full_name);
2403a3dd018SBenjamin Herrenschmidt 
2413a3dd018SBenjamin Herrenschmidt 	return 0xffffffff;
24281e5d864SBenjamin Herrenschmidt }
24381e5d864SBenjamin Herrenschmidt 
2440b255e92SBill Pemberton static void i2c_powermac_create_one(struct i2c_adapter *adap,
2453a3dd018SBenjamin Herrenschmidt 					      const char *type,
2463a3dd018SBenjamin Herrenschmidt 					      u32 addr)
2473a3dd018SBenjamin Herrenschmidt {
2483a3dd018SBenjamin Herrenschmidt 	struct i2c_board_info info = {};
2493a3dd018SBenjamin Herrenschmidt 	struct i2c_client *newdev;
25081e5d864SBenjamin Herrenschmidt 
2513a3dd018SBenjamin Herrenschmidt 	strncpy(info.type, type, sizeof(info.type));
2523a3dd018SBenjamin Herrenschmidt 	info.addr = addr;
2533a3dd018SBenjamin Herrenschmidt 	newdev = i2c_new_device(adap, &info);
2543a3dd018SBenjamin Herrenschmidt 	if (!newdev)
2553a3dd018SBenjamin Herrenschmidt 		dev_err(&adap->dev,
2563a3dd018SBenjamin Herrenschmidt 			"i2c-powermac: Failure to register missing %s\n",
2573a3dd018SBenjamin Herrenschmidt 			type);
2583a3dd018SBenjamin Herrenschmidt }
25981e5d864SBenjamin Herrenschmidt 
2600b255e92SBill Pemberton static void i2c_powermac_add_missing(struct i2c_adapter *adap,
2613a3dd018SBenjamin Herrenschmidt 					       struct pmac_i2c_bus *bus,
2623a3dd018SBenjamin Herrenschmidt 					       bool found_onyx)
2633a3dd018SBenjamin Herrenschmidt {
2643a3dd018SBenjamin Herrenschmidt 	struct device_node *busnode = pmac_i2c_get_bus_node(bus);
2653a3dd018SBenjamin Herrenschmidt 	int rc;
2663a3dd018SBenjamin Herrenschmidt 
2673a3dd018SBenjamin Herrenschmidt 	/* Check for the onyx audio codec */
2683a3dd018SBenjamin Herrenschmidt #define ONYX_REG_CONTROL		67
2693a3dd018SBenjamin Herrenschmidt 	if (of_device_is_compatible(busnode, "k2-i2c") && !found_onyx) {
2703a3dd018SBenjamin Herrenschmidt 		union i2c_smbus_data data;
2713a3dd018SBenjamin Herrenschmidt 
2723a3dd018SBenjamin Herrenschmidt 		rc = i2c_smbus_xfer(adap, 0x46, 0, I2C_SMBUS_READ,
2733a3dd018SBenjamin Herrenschmidt 				    ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA,
2743a3dd018SBenjamin Herrenschmidt 				    &data);
2753a3dd018SBenjamin Herrenschmidt 		if (rc >= 0)
2763a3dd018SBenjamin Herrenschmidt 			i2c_powermac_create_one(adap, "MAC,pcm3052", 0x46);
2773a3dd018SBenjamin Herrenschmidt 
2783a3dd018SBenjamin Herrenschmidt 		rc = i2c_smbus_xfer(adap, 0x47, 0, I2C_SMBUS_READ,
2793a3dd018SBenjamin Herrenschmidt 				    ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA,
2803a3dd018SBenjamin Herrenschmidt 				    &data);
2813a3dd018SBenjamin Herrenschmidt 		if (rc >= 0)
2823a3dd018SBenjamin Herrenschmidt 			i2c_powermac_create_one(adap, "MAC,pcm3052", 0x47);
2833a3dd018SBenjamin Herrenschmidt 	}
2843a3dd018SBenjamin Herrenschmidt }
2853a3dd018SBenjamin Herrenschmidt 
2860b255e92SBill Pemberton static bool i2c_powermac_get_type(struct i2c_adapter *adap,
2873a3dd018SBenjamin Herrenschmidt 					    struct device_node *node,
2883a3dd018SBenjamin Herrenschmidt 					    u32 addr, char *type, int type_size)
2893a3dd018SBenjamin Herrenschmidt {
2903a3dd018SBenjamin Herrenschmidt 	char tmp[16];
2913a3dd018SBenjamin Herrenschmidt 
2923a3dd018SBenjamin Herrenschmidt 	/* Note: we to _NOT_ want the standard
29381e5d864SBenjamin Herrenschmidt 	 * i2c drivers to match with any of our powermac stuff
29481e5d864SBenjamin Herrenschmidt 	 * unless they have been specifically modified to handle
29581e5d864SBenjamin Herrenschmidt 	 * it on a case by case basis. For example, for thermal
29681e5d864SBenjamin Herrenschmidt 	 * control, things like lm75 etc... shall match with their
29781e5d864SBenjamin Herrenschmidt 	 * corresponding windfarm drivers, _NOT_ the generic ones,
29881e5d864SBenjamin Herrenschmidt 	 * so we force a prefix of AAPL, onto the modalias to
29981e5d864SBenjamin Herrenschmidt 	 * make that happen
30081e5d864SBenjamin Herrenschmidt 	 */
3013a3dd018SBenjamin Herrenschmidt 
3023a3dd018SBenjamin Herrenschmidt 	/* First try proper modalias */
3033a3dd018SBenjamin Herrenschmidt 	if (of_modalias_node(node, tmp, sizeof(tmp)) >= 0) {
3043a3dd018SBenjamin Herrenschmidt 		snprintf(type, type_size, "MAC,%s", tmp);
3053a3dd018SBenjamin Herrenschmidt 		return true;
3063a3dd018SBenjamin Herrenschmidt 	}
3073a3dd018SBenjamin Herrenschmidt 
3083a3dd018SBenjamin Herrenschmidt 	/* Now look for known workarounds */
3093a3dd018SBenjamin Herrenschmidt 	if (!strcmp(node->name, "deq")) {
3103a3dd018SBenjamin Herrenschmidt 		/* Apple uses address 0x34 for TAS3001 and 0x35 for TAS3004 */
3113a3dd018SBenjamin Herrenschmidt 		if (addr == 0x34) {
3123a3dd018SBenjamin Herrenschmidt 			snprintf(type, type_size, "MAC,tas3001");
3133a3dd018SBenjamin Herrenschmidt 			return true;
3143a3dd018SBenjamin Herrenschmidt 		} else if (addr == 0x35) {
3153a3dd018SBenjamin Herrenschmidt 			snprintf(type, type_size, "MAC,tas3004");
3163a3dd018SBenjamin Herrenschmidt 			return true;
3173a3dd018SBenjamin Herrenschmidt 		}
3183a3dd018SBenjamin Herrenschmidt 	}
3193a3dd018SBenjamin Herrenschmidt 
32081e5d864SBenjamin Herrenschmidt 	dev_err(&adap->dev, "i2c-powermac: modalias failure"
32181e5d864SBenjamin Herrenschmidt 		" on %s\n", node->full_name);
3223a3dd018SBenjamin Herrenschmidt 	return false;
3233a3dd018SBenjamin Herrenschmidt }
3243a3dd018SBenjamin Herrenschmidt 
3250b255e92SBill Pemberton static void i2c_powermac_register_devices(struct i2c_adapter *adap,
3263a3dd018SBenjamin Herrenschmidt 						    struct pmac_i2c_bus *bus)
3273a3dd018SBenjamin Herrenschmidt {
3283a3dd018SBenjamin Herrenschmidt 	struct i2c_client *newdev;
3293a3dd018SBenjamin Herrenschmidt 	struct device_node *node;
3303a3dd018SBenjamin Herrenschmidt 	bool found_onyx = 0;
3313a3dd018SBenjamin Herrenschmidt 
3323a3dd018SBenjamin Herrenschmidt 	/*
3333a3dd018SBenjamin Herrenschmidt 	 * In some cases we end up with the via-pmu node itself, in this
3343a3dd018SBenjamin Herrenschmidt 	 * case we skip this function completely as the device-tree will
3353a3dd018SBenjamin Herrenschmidt 	 * not contain anything useful.
3363a3dd018SBenjamin Herrenschmidt 	 */
3373a3dd018SBenjamin Herrenschmidt 	if (!strcmp(adap->dev.of_node->name, "via-pmu"))
3383a3dd018SBenjamin Herrenschmidt 		return;
3393a3dd018SBenjamin Herrenschmidt 
3403a3dd018SBenjamin Herrenschmidt 	for_each_child_of_node(adap->dev.of_node, node) {
3413a3dd018SBenjamin Herrenschmidt 		struct i2c_board_info info = {};
3423a3dd018SBenjamin Herrenschmidt 		u32 addr;
3433a3dd018SBenjamin Herrenschmidt 
3443a3dd018SBenjamin Herrenschmidt 		/* Get address & channel */
3453a3dd018SBenjamin Herrenschmidt 		addr = i2c_powermac_get_addr(adap, bus, node);
3463a3dd018SBenjamin Herrenschmidt 		if (addr == 0xffffffff)
3473a3dd018SBenjamin Herrenschmidt 			continue;
3483a3dd018SBenjamin Herrenschmidt 
3493a3dd018SBenjamin Herrenschmidt 		/* Multibus setup, check channel */
3503a3dd018SBenjamin Herrenschmidt 		if (!pmac_i2c_match_adapter(node, adap))
3513a3dd018SBenjamin Herrenschmidt 			continue;
3523a3dd018SBenjamin Herrenschmidt 
3533a3dd018SBenjamin Herrenschmidt 		dev_dbg(&adap->dev, "i2c-powermac: register %s\n",
3543a3dd018SBenjamin Herrenschmidt 			node->full_name);
3553a3dd018SBenjamin Herrenschmidt 
3563a3dd018SBenjamin Herrenschmidt 		/*
3573a3dd018SBenjamin Herrenschmidt 		 * Keep track of some device existence to handle
3583a3dd018SBenjamin Herrenschmidt 		 * workarounds later.
3593a3dd018SBenjamin Herrenschmidt 		 */
3603a3dd018SBenjamin Herrenschmidt 		if (of_device_is_compatible(node, "pcm3052"))
3613a3dd018SBenjamin Herrenschmidt 			found_onyx = true;
3623a3dd018SBenjamin Herrenschmidt 
3633a3dd018SBenjamin Herrenschmidt 		/* Make up a modalias */
3643a3dd018SBenjamin Herrenschmidt 		if (!i2c_powermac_get_type(adap, node, addr,
3653a3dd018SBenjamin Herrenschmidt 					   info.type, sizeof(info.type))) {
36681e5d864SBenjamin Herrenschmidt 			continue;
36781e5d864SBenjamin Herrenschmidt 		}
36881e5d864SBenjamin Herrenschmidt 
36981e5d864SBenjamin Herrenschmidt 		/* Fill out the rest of the info structure */
3703a3dd018SBenjamin Herrenschmidt 		info.addr = addr;
37181e5d864SBenjamin Herrenschmidt 		info.irq = irq_of_parse_and_map(node, 0);
37281e5d864SBenjamin Herrenschmidt 		info.of_node = of_node_get(node);
37381e5d864SBenjamin Herrenschmidt 
37481e5d864SBenjamin Herrenschmidt 		newdev = i2c_new_device(adap, &info);
37581e5d864SBenjamin Herrenschmidt 		if (!newdev) {
37681e5d864SBenjamin Herrenschmidt 			dev_err(&adap->dev, "i2c-powermac: Failure to register"
37781e5d864SBenjamin Herrenschmidt 				" %s\n", node->full_name);
37881e5d864SBenjamin Herrenschmidt 			of_node_put(node);
37981e5d864SBenjamin Herrenschmidt 			/* We do not dispose of the interrupt mapping on
38081e5d864SBenjamin Herrenschmidt 			 * purpose. It's not necessary (interrupt cannot be
38181e5d864SBenjamin Herrenschmidt 			 * re-used) and somebody else might have grabbed it
38281e5d864SBenjamin Herrenschmidt 			 * via direct DT lookup so let's not bother
38381e5d864SBenjamin Herrenschmidt 			 */
38481e5d864SBenjamin Herrenschmidt 			continue;
38581e5d864SBenjamin Herrenschmidt 		}
38681e5d864SBenjamin Herrenschmidt 	}
3873a3dd018SBenjamin Herrenschmidt 
3883a3dd018SBenjamin Herrenschmidt 	/* Additional workarounds */
3893a3dd018SBenjamin Herrenschmidt 	i2c_powermac_add_missing(adap, bus, found_onyx);
39081e5d864SBenjamin Herrenschmidt }
391a28d3af2SBenjamin Herrenschmidt 
3920b255e92SBill Pemberton static int i2c_powermac_probe(struct platform_device *dev)
393a28d3af2SBenjamin Herrenschmidt {
3946d4028c6SJingoo Han 	struct pmac_i2c_bus *bus = dev_get_platdata(&dev->dev);
395a28d3af2SBenjamin Herrenschmidt 	struct device_node *parent = NULL;
396a28d3af2SBenjamin Herrenschmidt 	struct i2c_adapter *adapter;
397018a3d1dSJeremy Kerr 	const char *basename;
398a28d3af2SBenjamin Herrenschmidt 	int rc;
399a28d3af2SBenjamin Herrenschmidt 
400a28d3af2SBenjamin Herrenschmidt 	if (bus == NULL)
401a28d3af2SBenjamin Herrenschmidt 		return -EINVAL;
402bc6286e5SJean Delvare 	adapter = pmac_i2c_get_adapter(bus);
403a28d3af2SBenjamin Herrenschmidt 
404a28d3af2SBenjamin Herrenschmidt 	/* Ok, now we need to make up a name for the interface that will
405a28d3af2SBenjamin Herrenschmidt 	 * match what we used to do in the past, that is basically the
406a28d3af2SBenjamin Herrenschmidt 	 * controller's parent device node for keywest. PMU didn't have a
407a28d3af2SBenjamin Herrenschmidt 	 * naming convention and SMU has a different one
408a28d3af2SBenjamin Herrenschmidt 	 */
409a28d3af2SBenjamin Herrenschmidt 	switch(pmac_i2c_get_type(bus)) {
410a28d3af2SBenjamin Herrenschmidt 	case pmac_i2c_bus_keywest:
411a28d3af2SBenjamin Herrenschmidt 		parent = of_get_parent(pmac_i2c_get_controller(bus));
412a28d3af2SBenjamin Herrenschmidt 		if (parent == NULL)
413a28d3af2SBenjamin Herrenschmidt 			return -EINVAL;
414a28d3af2SBenjamin Herrenschmidt 		basename = parent->name;
415a28d3af2SBenjamin Herrenschmidt 		break;
416a28d3af2SBenjamin Herrenschmidt 	case pmac_i2c_bus_pmu:
417a28d3af2SBenjamin Herrenschmidt 		basename = "pmu";
418a28d3af2SBenjamin Herrenschmidt 		break;
419a28d3af2SBenjamin Herrenschmidt 	case pmac_i2c_bus_smu:
420a28d3af2SBenjamin Herrenschmidt 		/* This is not what we used to do but I'm fixing drivers at
421a28d3af2SBenjamin Herrenschmidt 		 * the same time as this change
422a28d3af2SBenjamin Herrenschmidt 		 */
423a28d3af2SBenjamin Herrenschmidt 		basename = "smu";
424a28d3af2SBenjamin Herrenschmidt 		break;
425a28d3af2SBenjamin Herrenschmidt 	default:
426a28d3af2SBenjamin Herrenschmidt 		return -EINVAL;
427a28d3af2SBenjamin Herrenschmidt 	}
428bc6286e5SJean Delvare 	snprintf(adapter->name, sizeof(adapter->name), "%s %d", basename,
429bc6286e5SJean Delvare 		 pmac_i2c_get_channel(bus));
430a28d3af2SBenjamin Herrenschmidt 	of_node_put(parent);
431a28d3af2SBenjamin Herrenschmidt 
4329f2545c1SBenjamin Herrenschmidt 	platform_set_drvdata(dev, adapter);
433a28d3af2SBenjamin Herrenschmidt 	adapter->algo = &i2c_powermac_algorithm;
434*7ee405eaSWolfram Sang 	adapter->quirks = &i2c_powermac_quirks;
435a28d3af2SBenjamin Herrenschmidt 	i2c_set_adapdata(adapter, bus);
4369f2545c1SBenjamin Herrenschmidt 	adapter->dev.parent = &dev->dev;
437687b81d0SWolfram Sang 
438687b81d0SWolfram Sang 	/* Clear of_node to skip automatic registration of i2c child nodes */
439687b81d0SWolfram Sang 	adapter->dev.of_node = NULL;
440a28d3af2SBenjamin Herrenschmidt 	rc = i2c_add_adapter(adapter);
441a28d3af2SBenjamin Herrenschmidt 	if (rc) {
442a28d3af2SBenjamin Herrenschmidt 		printk(KERN_ERR "i2c-powermac: Adapter %s registration "
443bc6286e5SJean Delvare 		       "failed\n", adapter->name);
4446dfa5ca3SJean Delvare 		memset(adapter, 0, sizeof(*adapter));
445874e955bSWolfram Sang 		return rc;
446a28d3af2SBenjamin Herrenschmidt 	}
447a28d3af2SBenjamin Herrenschmidt 
448bc6286e5SJean Delvare 	printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name);
449810ad7b6SJean Delvare 
450687b81d0SWolfram Sang 	/* Use custom child registration due to Apple device-tree funkyness */
451687b81d0SWolfram Sang 	adapter->dev.of_node = dev->dev.of_node;
45281e5d864SBenjamin Herrenschmidt 	i2c_powermac_register_devices(adapter, bus);
453810ad7b6SJean Delvare 
454874e955bSWolfram Sang 	return 0;
455a28d3af2SBenjamin Herrenschmidt }
456a28d3af2SBenjamin Herrenschmidt 
4579f2545c1SBenjamin Herrenschmidt static struct platform_driver i2c_powermac_driver = {
4589f2545c1SBenjamin Herrenschmidt 	.probe = i2c_powermac_probe,
4590b255e92SBill Pemberton 	.remove = i2c_powermac_remove,
4609f2545c1SBenjamin Herrenschmidt 	.driver = {
461a28d3af2SBenjamin Herrenschmidt 		.name = "i2c-powermac",
462a28d3af2SBenjamin Herrenschmidt 		.bus = &platform_bus_type,
4639f2545c1SBenjamin Herrenschmidt 	},
464a28d3af2SBenjamin Herrenschmidt };
465a28d3af2SBenjamin Herrenschmidt 
466a3664b51SAxel Lin module_platform_driver(i2c_powermac_driver);
467a28d3af2SBenjamin Herrenschmidt 
468a3664b51SAxel Lin MODULE_ALIAS("platform:i2c-powermac");
469