xref: /openbmc/linux/drivers/i2c/busses/i2c-powermac.c (revision 5af5073004071cedd0343eee51d77955037ec6f3)
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>
30*5af50730SRob Herring #include <linux/of_irq.h>
31a28d3af2SBenjamin Herrenschmidt #include <asm/prom.h>
32a28d3af2SBenjamin Herrenschmidt #include <asm/pmac_low_i2c.h>
33a28d3af2SBenjamin Herrenschmidt 
34a28d3af2SBenjamin Herrenschmidt MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
35a28d3af2SBenjamin Herrenschmidt MODULE_DESCRIPTION("I2C driver for Apple PowerMac");
36a28d3af2SBenjamin Herrenschmidt MODULE_LICENSE("GPL");
37a28d3af2SBenjamin Herrenschmidt 
38a28d3af2SBenjamin Herrenschmidt /*
39a28d3af2SBenjamin Herrenschmidt  * SMBUS-type transfer entrypoint
40a28d3af2SBenjamin Herrenschmidt  */
41a28d3af2SBenjamin Herrenschmidt static s32 i2c_powermac_smbus_xfer(	struct i2c_adapter*	adap,
42a28d3af2SBenjamin Herrenschmidt 					u16			addr,
43a28d3af2SBenjamin Herrenschmidt 					unsigned short		flags,
44a28d3af2SBenjamin Herrenschmidt 					char			read_write,
45a28d3af2SBenjamin Herrenschmidt 					u8			command,
46a28d3af2SBenjamin Herrenschmidt 					int			size,
47a28d3af2SBenjamin Herrenschmidt 					union i2c_smbus_data*	data)
48a28d3af2SBenjamin Herrenschmidt {
49a28d3af2SBenjamin Herrenschmidt 	struct pmac_i2c_bus	*bus = i2c_get_adapdata(adap);
50a28d3af2SBenjamin Herrenschmidt 	int			rc = 0;
51a28d3af2SBenjamin Herrenschmidt 	int			read = (read_write == I2C_SMBUS_READ);
52a28d3af2SBenjamin Herrenschmidt 	int			addrdir = (addr << 1) | read;
5302864d58SJean Delvare 	int			mode, subsize, len;
5402864d58SJean Delvare 	u32			subaddr;
5502864d58SJean Delvare 	u8			*buf;
56a28d3af2SBenjamin Herrenschmidt 	u8			local[2];
57a28d3af2SBenjamin Herrenschmidt 
5802864d58SJean Delvare 	if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) {
5902864d58SJean Delvare 		mode = pmac_i2c_mode_std;
6002864d58SJean Delvare 		subsize = 0;
6102864d58SJean Delvare 		subaddr = 0;
6202864d58SJean Delvare 	} else {
6302864d58SJean Delvare 		mode = read ? pmac_i2c_mode_combined : pmac_i2c_mode_stdsub;
6402864d58SJean Delvare 		subsize = 1;
6502864d58SJean Delvare 		subaddr = command;
6602864d58SJean Delvare 	}
67a28d3af2SBenjamin Herrenschmidt 
68a28d3af2SBenjamin Herrenschmidt 	switch (size) {
69a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_QUICK:
7002864d58SJean Delvare 		buf = NULL;
7102864d58SJean Delvare 		len = 0;
72a28d3af2SBenjamin Herrenschmidt 	    	break;
73a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_BYTE:
74a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_BYTE_DATA:
7502864d58SJean Delvare 		buf = &data->byte;
7602864d58SJean Delvare 		len = 1;
77a28d3af2SBenjamin Herrenschmidt 	    	break;
78a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_WORD_DATA:
79a28d3af2SBenjamin Herrenschmidt 		if (!read) {
80a28d3af2SBenjamin Herrenschmidt 			local[0] = data->word & 0xff;
81a28d3af2SBenjamin Herrenschmidt 			local[1] = (data->word >> 8) & 0xff;
82a28d3af2SBenjamin Herrenschmidt 		}
8302864d58SJean Delvare 		buf = local;
8402864d58SJean Delvare 		len = 2;
85a28d3af2SBenjamin Herrenschmidt 	    	break;
86a28d3af2SBenjamin Herrenschmidt 
87a28d3af2SBenjamin Herrenschmidt 	/* Note that these are broken vs. the expected smbus API where
8896acafe0SJoe Perches 	 * on reads, the length is actually returned from the function,
89a28d3af2SBenjamin Herrenschmidt 	 * but I think the current API makes no sense and I don't want
90a28d3af2SBenjamin Herrenschmidt 	 * any driver that I haven't verified for correctness to go
91a28d3af2SBenjamin Herrenschmidt 	 * anywhere near a pmac i2c bus anyway ...
92a28d3af2SBenjamin Herrenschmidt 	 *
93a28d3af2SBenjamin Herrenschmidt 	 * I'm also not completely sure what kind of phases to do between
94a28d3af2SBenjamin Herrenschmidt 	 * the actual command and the data (what I am _supposed_ to do that
95a28d3af2SBenjamin Herrenschmidt 	 * is). For now, I assume writes are a single stream and reads have
96a28d3af2SBenjamin Herrenschmidt 	 * a repeat start/addr phase (but not stop in between)
97a28d3af2SBenjamin Herrenschmidt 	 */
98a28d3af2SBenjamin Herrenschmidt         case I2C_SMBUS_BLOCK_DATA:
9902864d58SJean Delvare 		buf = data->block;
10002864d58SJean Delvare 		len = data->block[0] + 1;
101a28d3af2SBenjamin Herrenschmidt 		break;
102a28d3af2SBenjamin Herrenschmidt 	case I2C_SMBUS_I2C_BLOCK_DATA:
10302864d58SJean Delvare 		buf = &data->block[1];
10402864d58SJean Delvare 		len = data->block[0];
105a28d3af2SBenjamin Herrenschmidt 		break;
106a28d3af2SBenjamin Herrenschmidt 
107a28d3af2SBenjamin Herrenschmidt         default:
10802864d58SJean Delvare 		return -EINVAL;
109a28d3af2SBenjamin Herrenschmidt 	}
11002864d58SJean Delvare 
11102864d58SJean Delvare 	rc = pmac_i2c_open(bus, 0);
112d7d838a6SJean Delvare 	if (rc) {
113d7d838a6SJean Delvare 		dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
11402864d58SJean Delvare 		return rc;
115d7d838a6SJean Delvare 	}
11602864d58SJean Delvare 
11702864d58SJean Delvare 	rc = pmac_i2c_setmode(bus, mode);
118d7d838a6SJean Delvare 	if (rc) {
119d7d838a6SJean Delvare 		dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
120d7d838a6SJean Delvare 			mode, rc);
12102864d58SJean Delvare 		goto bail;
122d7d838a6SJean Delvare 	}
12302864d58SJean Delvare 
12402864d58SJean Delvare 	rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len);
125d7d838a6SJean Delvare 	if (rc) {
1268e4b980cSJean Delvare 		if (rc == -ENXIO)
1278e4b980cSJean Delvare 			dev_dbg(&adap->dev,
1288e4b980cSJean Delvare 				"I2C transfer at 0x%02x failed, size %d, "
1298e4b980cSJean Delvare 				"err %d\n", addrdir >> 1, size, rc);
1308e4b980cSJean Delvare 		else
131d7d838a6SJean Delvare 			dev_err(&adap->dev,
1328e4b980cSJean Delvare 				"I2C transfer at 0x%02x failed, size %d, "
1338e4b980cSJean Delvare 				"err %d\n", addrdir >> 1, size, rc);
13402864d58SJean Delvare 		goto bail;
135d7d838a6SJean Delvare 	}
13602864d58SJean Delvare 
13702864d58SJean Delvare 	if (size == I2C_SMBUS_WORD_DATA && read) {
13802864d58SJean Delvare 		data->word = ((u16)local[1]) << 8;
13902864d58SJean Delvare 		data->word |= local[0];
14002864d58SJean Delvare 	}
14102864d58SJean Delvare 
142a28d3af2SBenjamin Herrenschmidt  bail:
143a28d3af2SBenjamin Herrenschmidt 	pmac_i2c_close(bus);
144a28d3af2SBenjamin Herrenschmidt 	return rc;
145a28d3af2SBenjamin Herrenschmidt }
146a28d3af2SBenjamin Herrenschmidt 
147a28d3af2SBenjamin Herrenschmidt /*
148a28d3af2SBenjamin Herrenschmidt  * Generic i2c master transfer entrypoint. This driver only support single
149a28d3af2SBenjamin Herrenschmidt  * messages (for "lame i2c" transfers). Anything else should use the smbus
150a28d3af2SBenjamin Herrenschmidt  * entry point
151a28d3af2SBenjamin Herrenschmidt  */
152a28d3af2SBenjamin Herrenschmidt static int i2c_powermac_master_xfer(	struct i2c_adapter *adap,
153a28d3af2SBenjamin Herrenschmidt 					struct i2c_msg *msgs,
154a28d3af2SBenjamin Herrenschmidt 					int num)
155a28d3af2SBenjamin Herrenschmidt {
156a28d3af2SBenjamin Herrenschmidt 	struct pmac_i2c_bus	*bus = i2c_get_adapdata(adap);
157a28d3af2SBenjamin Herrenschmidt 	int			rc = 0;
158a28d3af2SBenjamin Herrenschmidt 	int			read;
159a28d3af2SBenjamin Herrenschmidt 	int			addrdir;
160a28d3af2SBenjamin Herrenschmidt 
1616f7e549fSJean Delvare 	if (num != 1) {
1626f7e549fSJean Delvare 		dev_err(&adap->dev,
1636f7e549fSJean Delvare 			"Multi-message I2C transactions not supported\n");
1646f7e549fSJean Delvare 		return -EOPNOTSUPP;
1656f7e549fSJean Delvare 	}
1666f7e549fSJean Delvare 
167a28d3af2SBenjamin Herrenschmidt 	if (msgs->flags & I2C_M_TEN)
168a28d3af2SBenjamin Herrenschmidt 		return -EINVAL;
169a28d3af2SBenjamin Herrenschmidt 	read = (msgs->flags & I2C_M_RD) != 0;
170a28d3af2SBenjamin Herrenschmidt 	addrdir = (msgs->addr << 1) | read;
171a28d3af2SBenjamin Herrenschmidt 
172a28d3af2SBenjamin Herrenschmidt 	rc = pmac_i2c_open(bus, 0);
173d7d838a6SJean Delvare 	if (rc) {
174d7d838a6SJean Delvare 		dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
175a28d3af2SBenjamin Herrenschmidt 		return rc;
176d7d838a6SJean Delvare 	}
177a28d3af2SBenjamin Herrenschmidt 	rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
178d7d838a6SJean Delvare 	if (rc) {
179d7d838a6SJean Delvare 		dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
180d7d838a6SJean Delvare 			pmac_i2c_mode_std, rc);
181a28d3af2SBenjamin Herrenschmidt 		goto bail;
182d7d838a6SJean Delvare 	}
183a28d3af2SBenjamin Herrenschmidt 	rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len);
1848e4b980cSJean Delvare 	if (rc < 0) {
1858e4b980cSJean Delvare 		if (rc == -ENXIO)
1868e4b980cSJean Delvare 			dev_dbg(&adap->dev, "I2C %s 0x%02x failed, err %d\n",
1878e4b980cSJean Delvare 				addrdir & 1 ? "read from" : "write to",
1888e4b980cSJean Delvare 				addrdir >> 1, rc);
1898e4b980cSJean Delvare 		else
190d7d838a6SJean Delvare 			dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n",
1918e4b980cSJean Delvare 				addrdir & 1 ? "read from" : "write to",
1928e4b980cSJean Delvare 				addrdir >> 1, rc);
1938e4b980cSJean Delvare 	}
194a28d3af2SBenjamin Herrenschmidt  bail:
195a28d3af2SBenjamin Herrenschmidt 	pmac_i2c_close(bus);
1968ced8eeeSJean Delvare 	return rc < 0 ? rc : 1;
197a28d3af2SBenjamin Herrenschmidt }
198a28d3af2SBenjamin Herrenschmidt 
199a28d3af2SBenjamin Herrenschmidt static u32 i2c_powermac_func(struct i2c_adapter * adapter)
200a28d3af2SBenjamin Herrenschmidt {
201a28d3af2SBenjamin Herrenschmidt 	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
202a28d3af2SBenjamin Herrenschmidt 		I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
203a28d3af2SBenjamin Herrenschmidt 		I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_I2C;
204a28d3af2SBenjamin Herrenschmidt }
205a28d3af2SBenjamin Herrenschmidt 
206a28d3af2SBenjamin Herrenschmidt /* For now, we only handle smbus */
2078f9082c5SJean Delvare static const struct i2c_algorithm i2c_powermac_algorithm = {
208a28d3af2SBenjamin Herrenschmidt 	.smbus_xfer	= i2c_powermac_smbus_xfer,
209a28d3af2SBenjamin Herrenschmidt 	.master_xfer	= i2c_powermac_master_xfer,
210a28d3af2SBenjamin Herrenschmidt 	.functionality	= i2c_powermac_func,
211a28d3af2SBenjamin Herrenschmidt };
212a28d3af2SBenjamin Herrenschmidt 
213a28d3af2SBenjamin Herrenschmidt 
2140b255e92SBill Pemberton static int i2c_powermac_remove(struct platform_device *dev)
215a28d3af2SBenjamin Herrenschmidt {
2169f2545c1SBenjamin Herrenschmidt 	struct i2c_adapter	*adapter = platform_get_drvdata(dev);
217a28d3af2SBenjamin Herrenschmidt 
218bf51a8c5SLars-Peter Clausen 	i2c_del_adapter(adapter);
2196dfa5ca3SJean Delvare 	memset(adapter, 0, sizeof(*adapter));
220a28d3af2SBenjamin Herrenschmidt 
221a28d3af2SBenjamin Herrenschmidt 	return 0;
222a28d3af2SBenjamin Herrenschmidt }
223a28d3af2SBenjamin Herrenschmidt 
2240b255e92SBill Pemberton static u32 i2c_powermac_get_addr(struct i2c_adapter *adap,
2253a3dd018SBenjamin Herrenschmidt 					   struct pmac_i2c_bus *bus,
2263a3dd018SBenjamin Herrenschmidt 					   struct device_node *node)
22781e5d864SBenjamin Herrenschmidt {
2283a3dd018SBenjamin Herrenschmidt 	const __be32 *prop;
22981e5d864SBenjamin Herrenschmidt 	int len;
23081e5d864SBenjamin Herrenschmidt 
2313a3dd018SBenjamin Herrenschmidt 	/* First check for valid "reg" */
2323a3dd018SBenjamin Herrenschmidt 	prop = of_get_property(node, "reg", &len);
2333a3dd018SBenjamin Herrenschmidt 	if (prop && (len >= sizeof(int)))
2343a3dd018SBenjamin Herrenschmidt 		return (be32_to_cpup(prop) & 0xff) >> 1;
2353a3dd018SBenjamin Herrenschmidt 
2363a3dd018SBenjamin Herrenschmidt 	/* Then check old-style "i2c-address" */
2373a3dd018SBenjamin Herrenschmidt 	prop = of_get_property(node, "i2c-address", &len);
2383a3dd018SBenjamin Herrenschmidt 	if (prop && (len >= sizeof(int)))
2393a3dd018SBenjamin Herrenschmidt 		return (be32_to_cpup(prop) & 0xff) >> 1;
2403a3dd018SBenjamin Herrenschmidt 
2413a3dd018SBenjamin Herrenschmidt 	/* Now handle some devices with missing "reg" properties */
2423a3dd018SBenjamin Herrenschmidt 	if (!strcmp(node->name, "cereal"))
2433a3dd018SBenjamin Herrenschmidt 		return 0x60;
2443a3dd018SBenjamin Herrenschmidt 	else if (!strcmp(node->name, "deq"))
2453a3dd018SBenjamin Herrenschmidt 		return 0x34;
2463a3dd018SBenjamin Herrenschmidt 
2473a3dd018SBenjamin Herrenschmidt 	dev_warn(&adap->dev, "No i2c address for %s\n", node->full_name);
2483a3dd018SBenjamin Herrenschmidt 
2493a3dd018SBenjamin Herrenschmidt 	return 0xffffffff;
25081e5d864SBenjamin Herrenschmidt }
25181e5d864SBenjamin Herrenschmidt 
2520b255e92SBill Pemberton static void i2c_powermac_create_one(struct i2c_adapter *adap,
2533a3dd018SBenjamin Herrenschmidt 					      const char *type,
2543a3dd018SBenjamin Herrenschmidt 					      u32 addr)
2553a3dd018SBenjamin Herrenschmidt {
2563a3dd018SBenjamin Herrenschmidt 	struct i2c_board_info info = {};
2573a3dd018SBenjamin Herrenschmidt 	struct i2c_client *newdev;
25881e5d864SBenjamin Herrenschmidt 
2593a3dd018SBenjamin Herrenschmidt 	strncpy(info.type, type, sizeof(info.type));
2603a3dd018SBenjamin Herrenschmidt 	info.addr = addr;
2613a3dd018SBenjamin Herrenschmidt 	newdev = i2c_new_device(adap, &info);
2623a3dd018SBenjamin Herrenschmidt 	if (!newdev)
2633a3dd018SBenjamin Herrenschmidt 		dev_err(&adap->dev,
2643a3dd018SBenjamin Herrenschmidt 			"i2c-powermac: Failure to register missing %s\n",
2653a3dd018SBenjamin Herrenschmidt 			type);
2663a3dd018SBenjamin Herrenschmidt }
26781e5d864SBenjamin Herrenschmidt 
2680b255e92SBill Pemberton static void i2c_powermac_add_missing(struct i2c_adapter *adap,
2693a3dd018SBenjamin Herrenschmidt 					       struct pmac_i2c_bus *bus,
2703a3dd018SBenjamin Herrenschmidt 					       bool found_onyx)
2713a3dd018SBenjamin Herrenschmidt {
2723a3dd018SBenjamin Herrenschmidt 	struct device_node *busnode = pmac_i2c_get_bus_node(bus);
2733a3dd018SBenjamin Herrenschmidt 	int rc;
2743a3dd018SBenjamin Herrenschmidt 
2753a3dd018SBenjamin Herrenschmidt 	/* Check for the onyx audio codec */
2763a3dd018SBenjamin Herrenschmidt #define ONYX_REG_CONTROL		67
2773a3dd018SBenjamin Herrenschmidt 	if (of_device_is_compatible(busnode, "k2-i2c") && !found_onyx) {
2783a3dd018SBenjamin Herrenschmidt 		union i2c_smbus_data data;
2793a3dd018SBenjamin Herrenschmidt 
2803a3dd018SBenjamin Herrenschmidt 		rc = i2c_smbus_xfer(adap, 0x46, 0, I2C_SMBUS_READ,
2813a3dd018SBenjamin Herrenschmidt 				    ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA,
2823a3dd018SBenjamin Herrenschmidt 				    &data);
2833a3dd018SBenjamin Herrenschmidt 		if (rc >= 0)
2843a3dd018SBenjamin Herrenschmidt 			i2c_powermac_create_one(adap, "MAC,pcm3052", 0x46);
2853a3dd018SBenjamin Herrenschmidt 
2863a3dd018SBenjamin Herrenschmidt 		rc = i2c_smbus_xfer(adap, 0x47, 0, I2C_SMBUS_READ,
2873a3dd018SBenjamin Herrenschmidt 				    ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA,
2883a3dd018SBenjamin Herrenschmidt 				    &data);
2893a3dd018SBenjamin Herrenschmidt 		if (rc >= 0)
2903a3dd018SBenjamin Herrenschmidt 			i2c_powermac_create_one(adap, "MAC,pcm3052", 0x47);
2913a3dd018SBenjamin Herrenschmidt 	}
2923a3dd018SBenjamin Herrenschmidt }
2933a3dd018SBenjamin Herrenschmidt 
2940b255e92SBill Pemberton static bool i2c_powermac_get_type(struct i2c_adapter *adap,
2953a3dd018SBenjamin Herrenschmidt 					    struct device_node *node,
2963a3dd018SBenjamin Herrenschmidt 					    u32 addr, char *type, int type_size)
2973a3dd018SBenjamin Herrenschmidt {
2983a3dd018SBenjamin Herrenschmidt 	char tmp[16];
2993a3dd018SBenjamin Herrenschmidt 
3003a3dd018SBenjamin Herrenschmidt 	/* Note: we to _NOT_ want the standard
30181e5d864SBenjamin Herrenschmidt 	 * i2c drivers to match with any of our powermac stuff
30281e5d864SBenjamin Herrenschmidt 	 * unless they have been specifically modified to handle
30381e5d864SBenjamin Herrenschmidt 	 * it on a case by case basis. For example, for thermal
30481e5d864SBenjamin Herrenschmidt 	 * control, things like lm75 etc... shall match with their
30581e5d864SBenjamin Herrenschmidt 	 * corresponding windfarm drivers, _NOT_ the generic ones,
30681e5d864SBenjamin Herrenschmidt 	 * so we force a prefix of AAPL, onto the modalias to
30781e5d864SBenjamin Herrenschmidt 	 * make that happen
30881e5d864SBenjamin Herrenschmidt 	 */
3093a3dd018SBenjamin Herrenschmidt 
3103a3dd018SBenjamin Herrenschmidt 	/* First try proper modalias */
3113a3dd018SBenjamin Herrenschmidt 	if (of_modalias_node(node, tmp, sizeof(tmp)) >= 0) {
3123a3dd018SBenjamin Herrenschmidt 		snprintf(type, type_size, "MAC,%s", tmp);
3133a3dd018SBenjamin Herrenschmidt 		return true;
3143a3dd018SBenjamin Herrenschmidt 	}
3153a3dd018SBenjamin Herrenschmidt 
3163a3dd018SBenjamin Herrenschmidt 	/* Now look for known workarounds */
3173a3dd018SBenjamin Herrenschmidt 	if (!strcmp(node->name, "deq")) {
3183a3dd018SBenjamin Herrenschmidt 		/* Apple uses address 0x34 for TAS3001 and 0x35 for TAS3004 */
3193a3dd018SBenjamin Herrenschmidt 		if (addr == 0x34) {
3203a3dd018SBenjamin Herrenschmidt 			snprintf(type, type_size, "MAC,tas3001");
3213a3dd018SBenjamin Herrenschmidt 			return true;
3223a3dd018SBenjamin Herrenschmidt 		} else if (addr == 0x35) {
3233a3dd018SBenjamin Herrenschmidt 			snprintf(type, type_size, "MAC,tas3004");
3243a3dd018SBenjamin Herrenschmidt 			return true;
3253a3dd018SBenjamin Herrenschmidt 		}
3263a3dd018SBenjamin Herrenschmidt 	}
3273a3dd018SBenjamin Herrenschmidt 
32881e5d864SBenjamin Herrenschmidt 	dev_err(&adap->dev, "i2c-powermac: modalias failure"
32981e5d864SBenjamin Herrenschmidt 		" on %s\n", node->full_name);
3303a3dd018SBenjamin Herrenschmidt 	return false;
3313a3dd018SBenjamin Herrenschmidt }
3323a3dd018SBenjamin Herrenschmidt 
3330b255e92SBill Pemberton static void i2c_powermac_register_devices(struct i2c_adapter *adap,
3343a3dd018SBenjamin Herrenschmidt 						    struct pmac_i2c_bus *bus)
3353a3dd018SBenjamin Herrenschmidt {
3363a3dd018SBenjamin Herrenschmidt 	struct i2c_client *newdev;
3373a3dd018SBenjamin Herrenschmidt 	struct device_node *node;
3383a3dd018SBenjamin Herrenschmidt 	bool found_onyx = 0;
3393a3dd018SBenjamin Herrenschmidt 
3403a3dd018SBenjamin Herrenschmidt 	/*
3413a3dd018SBenjamin Herrenschmidt 	 * In some cases we end up with the via-pmu node itself, in this
3423a3dd018SBenjamin Herrenschmidt 	 * case we skip this function completely as the device-tree will
3433a3dd018SBenjamin Herrenschmidt 	 * not contain anything useful.
3443a3dd018SBenjamin Herrenschmidt 	 */
3453a3dd018SBenjamin Herrenschmidt 	if (!strcmp(adap->dev.of_node->name, "via-pmu"))
3463a3dd018SBenjamin Herrenschmidt 		return;
3473a3dd018SBenjamin Herrenschmidt 
3483a3dd018SBenjamin Herrenschmidt 	for_each_child_of_node(adap->dev.of_node, node) {
3493a3dd018SBenjamin Herrenschmidt 		struct i2c_board_info info = {};
3503a3dd018SBenjamin Herrenschmidt 		u32 addr;
3513a3dd018SBenjamin Herrenschmidt 
3523a3dd018SBenjamin Herrenschmidt 		/* Get address & channel */
3533a3dd018SBenjamin Herrenschmidt 		addr = i2c_powermac_get_addr(adap, bus, node);
3543a3dd018SBenjamin Herrenschmidt 		if (addr == 0xffffffff)
3553a3dd018SBenjamin Herrenschmidt 			continue;
3563a3dd018SBenjamin Herrenschmidt 
3573a3dd018SBenjamin Herrenschmidt 		/* Multibus setup, check channel */
3583a3dd018SBenjamin Herrenschmidt 		if (!pmac_i2c_match_adapter(node, adap))
3593a3dd018SBenjamin Herrenschmidt 			continue;
3603a3dd018SBenjamin Herrenschmidt 
3613a3dd018SBenjamin Herrenschmidt 		dev_dbg(&adap->dev, "i2c-powermac: register %s\n",
3623a3dd018SBenjamin Herrenschmidt 			node->full_name);
3633a3dd018SBenjamin Herrenschmidt 
3643a3dd018SBenjamin Herrenschmidt 		/*
3653a3dd018SBenjamin Herrenschmidt 		 * Keep track of some device existence to handle
3663a3dd018SBenjamin Herrenschmidt 		 * workarounds later.
3673a3dd018SBenjamin Herrenschmidt 		 */
3683a3dd018SBenjamin Herrenschmidt 		if (of_device_is_compatible(node, "pcm3052"))
3693a3dd018SBenjamin Herrenschmidt 			found_onyx = true;
3703a3dd018SBenjamin Herrenschmidt 
3713a3dd018SBenjamin Herrenschmidt 		/* Make up a modalias */
3723a3dd018SBenjamin Herrenschmidt 		if (!i2c_powermac_get_type(adap, node, addr,
3733a3dd018SBenjamin Herrenschmidt 					   info.type, sizeof(info.type))) {
37481e5d864SBenjamin Herrenschmidt 			continue;
37581e5d864SBenjamin Herrenschmidt 		}
37681e5d864SBenjamin Herrenschmidt 
37781e5d864SBenjamin Herrenschmidt 		/* Fill out the rest of the info structure */
3783a3dd018SBenjamin Herrenschmidt 		info.addr = addr;
37981e5d864SBenjamin Herrenschmidt 		info.irq = irq_of_parse_and_map(node, 0);
38081e5d864SBenjamin Herrenschmidt 		info.of_node = of_node_get(node);
38181e5d864SBenjamin Herrenschmidt 
38281e5d864SBenjamin Herrenschmidt 		newdev = i2c_new_device(adap, &info);
38381e5d864SBenjamin Herrenschmidt 		if (!newdev) {
38481e5d864SBenjamin Herrenschmidt 			dev_err(&adap->dev, "i2c-powermac: Failure to register"
38581e5d864SBenjamin Herrenschmidt 				" %s\n", node->full_name);
38681e5d864SBenjamin Herrenschmidt 			of_node_put(node);
38781e5d864SBenjamin Herrenschmidt 			/* We do not dispose of the interrupt mapping on
38881e5d864SBenjamin Herrenschmidt 			 * purpose. It's not necessary (interrupt cannot be
38981e5d864SBenjamin Herrenschmidt 			 * re-used) and somebody else might have grabbed it
39081e5d864SBenjamin Herrenschmidt 			 * via direct DT lookup so let's not bother
39181e5d864SBenjamin Herrenschmidt 			 */
39281e5d864SBenjamin Herrenschmidt 			continue;
39381e5d864SBenjamin Herrenschmidt 		}
39481e5d864SBenjamin Herrenschmidt 	}
3953a3dd018SBenjamin Herrenschmidt 
3963a3dd018SBenjamin Herrenschmidt 	/* Additional workarounds */
3973a3dd018SBenjamin Herrenschmidt 	i2c_powermac_add_missing(adap, bus, found_onyx);
39881e5d864SBenjamin Herrenschmidt }
399a28d3af2SBenjamin Herrenschmidt 
4000b255e92SBill Pemberton static int i2c_powermac_probe(struct platform_device *dev)
401a28d3af2SBenjamin Herrenschmidt {
4026d4028c6SJingoo Han 	struct pmac_i2c_bus *bus = dev_get_platdata(&dev->dev);
403a28d3af2SBenjamin Herrenschmidt 	struct device_node *parent = NULL;
404a28d3af2SBenjamin Herrenschmidt 	struct i2c_adapter *adapter;
405018a3d1dSJeremy Kerr 	const char *basename;
406a28d3af2SBenjamin Herrenschmidt 	int rc;
407a28d3af2SBenjamin Herrenschmidt 
408a28d3af2SBenjamin Herrenschmidt 	if (bus == NULL)
409a28d3af2SBenjamin Herrenschmidt 		return -EINVAL;
410bc6286e5SJean Delvare 	adapter = pmac_i2c_get_adapter(bus);
411a28d3af2SBenjamin Herrenschmidt 
412a28d3af2SBenjamin Herrenschmidt 	/* Ok, now we need to make up a name for the interface that will
413a28d3af2SBenjamin Herrenschmidt 	 * match what we used to do in the past, that is basically the
414a28d3af2SBenjamin Herrenschmidt 	 * controller's parent device node for keywest. PMU didn't have a
415a28d3af2SBenjamin Herrenschmidt 	 * naming convention and SMU has a different one
416a28d3af2SBenjamin Herrenschmidt 	 */
417a28d3af2SBenjamin Herrenschmidt 	switch(pmac_i2c_get_type(bus)) {
418a28d3af2SBenjamin Herrenschmidt 	case pmac_i2c_bus_keywest:
419a28d3af2SBenjamin Herrenschmidt 		parent = of_get_parent(pmac_i2c_get_controller(bus));
420a28d3af2SBenjamin Herrenschmidt 		if (parent == NULL)
421a28d3af2SBenjamin Herrenschmidt 			return -EINVAL;
422a28d3af2SBenjamin Herrenschmidt 		basename = parent->name;
423a28d3af2SBenjamin Herrenschmidt 		break;
424a28d3af2SBenjamin Herrenschmidt 	case pmac_i2c_bus_pmu:
425a28d3af2SBenjamin Herrenschmidt 		basename = "pmu";
426a28d3af2SBenjamin Herrenschmidt 		break;
427a28d3af2SBenjamin Herrenschmidt 	case pmac_i2c_bus_smu:
428a28d3af2SBenjamin Herrenschmidt 		/* This is not what we used to do but I'm fixing drivers at
429a28d3af2SBenjamin Herrenschmidt 		 * the same time as this change
430a28d3af2SBenjamin Herrenschmidt 		 */
431a28d3af2SBenjamin Herrenschmidt 		basename = "smu";
432a28d3af2SBenjamin Herrenschmidt 		break;
433a28d3af2SBenjamin Herrenschmidt 	default:
434a28d3af2SBenjamin Herrenschmidt 		return -EINVAL;
435a28d3af2SBenjamin Herrenschmidt 	}
436bc6286e5SJean Delvare 	snprintf(adapter->name, sizeof(adapter->name), "%s %d", basename,
437bc6286e5SJean Delvare 		 pmac_i2c_get_channel(bus));
438a28d3af2SBenjamin Herrenschmidt 	of_node_put(parent);
439a28d3af2SBenjamin Herrenschmidt 
4409f2545c1SBenjamin Herrenschmidt 	platform_set_drvdata(dev, adapter);
441a28d3af2SBenjamin Herrenschmidt 	adapter->algo = &i2c_powermac_algorithm;
442a28d3af2SBenjamin Herrenschmidt 	i2c_set_adapdata(adapter, bus);
4439f2545c1SBenjamin Herrenschmidt 	adapter->dev.parent = &dev->dev;
444687b81d0SWolfram Sang 
445687b81d0SWolfram Sang 	/* Clear of_node to skip automatic registration of i2c child nodes */
446687b81d0SWolfram Sang 	adapter->dev.of_node = NULL;
447a28d3af2SBenjamin Herrenschmidt 	rc = i2c_add_adapter(adapter);
448a28d3af2SBenjamin Herrenschmidt 	if (rc) {
449a28d3af2SBenjamin Herrenschmidt 		printk(KERN_ERR "i2c-powermac: Adapter %s registration "
450bc6286e5SJean Delvare 		       "failed\n", adapter->name);
4516dfa5ca3SJean Delvare 		memset(adapter, 0, sizeof(*adapter));
452874e955bSWolfram Sang 		return rc;
453a28d3af2SBenjamin Herrenschmidt 	}
454a28d3af2SBenjamin Herrenschmidt 
455bc6286e5SJean Delvare 	printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name);
456810ad7b6SJean Delvare 
457687b81d0SWolfram Sang 	/* Use custom child registration due to Apple device-tree funkyness */
458687b81d0SWolfram Sang 	adapter->dev.of_node = dev->dev.of_node;
45981e5d864SBenjamin Herrenschmidt 	i2c_powermac_register_devices(adapter, bus);
460810ad7b6SJean Delvare 
461874e955bSWolfram Sang 	return 0;
462a28d3af2SBenjamin Herrenschmidt }
463a28d3af2SBenjamin Herrenschmidt 
4649f2545c1SBenjamin Herrenschmidt static struct platform_driver i2c_powermac_driver = {
4659f2545c1SBenjamin Herrenschmidt 	.probe = i2c_powermac_probe,
4660b255e92SBill Pemberton 	.remove = i2c_powermac_remove,
4679f2545c1SBenjamin Herrenschmidt 	.driver = {
468a28d3af2SBenjamin Herrenschmidt 		.name = "i2c-powermac",
469a28d3af2SBenjamin Herrenschmidt 		.bus = &platform_bus_type,
4709f2545c1SBenjamin Herrenschmidt 	},
471a28d3af2SBenjamin Herrenschmidt };
472a28d3af2SBenjamin Herrenschmidt 
473a3664b51SAxel Lin module_platform_driver(i2c_powermac_driver);
474a28d3af2SBenjamin Herrenschmidt 
475a3664b51SAxel Lin MODULE_ALIAS("platform:i2c-powermac");
476