162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci    i2c Support for Apple SMU Controller
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci    Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp.
662306a36Sopenharmony_ci                       <benh@kernel.crashing.org>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci*/
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <linux/kernel.h>
1362306a36Sopenharmony_ci#include <linux/types.h>
1462306a36Sopenharmony_ci#include <linux/i2c.h>
1562306a36Sopenharmony_ci#include <linux/device.h>
1662306a36Sopenharmony_ci#include <linux/platform_device.h>
1762306a36Sopenharmony_ci#include <linux/of_irq.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include <asm/pmac_low_i2c.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ciMODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
2262306a36Sopenharmony_ciMODULE_DESCRIPTION("I2C driver for Apple PowerMac");
2362306a36Sopenharmony_ciMODULE_LICENSE("GPL");
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/*
2662306a36Sopenharmony_ci * SMBUS-type transfer entrypoint
2762306a36Sopenharmony_ci */
2862306a36Sopenharmony_cistatic s32 i2c_powermac_smbus_xfer(	struct i2c_adapter*	adap,
2962306a36Sopenharmony_ci					u16			addr,
3062306a36Sopenharmony_ci					unsigned short		flags,
3162306a36Sopenharmony_ci					char			read_write,
3262306a36Sopenharmony_ci					u8			command,
3362306a36Sopenharmony_ci					int			size,
3462306a36Sopenharmony_ci					union i2c_smbus_data*	data)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	struct pmac_i2c_bus	*bus = i2c_get_adapdata(adap);
3762306a36Sopenharmony_ci	int			rc = 0;
3862306a36Sopenharmony_ci	int			read = (read_write == I2C_SMBUS_READ);
3962306a36Sopenharmony_ci	int			addrdir = (addr << 1) | read;
4062306a36Sopenharmony_ci	int			mode, subsize, len;
4162306a36Sopenharmony_ci	u32			subaddr;
4262306a36Sopenharmony_ci	u8			*buf;
4362306a36Sopenharmony_ci	u8			local[2];
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) {
4662306a36Sopenharmony_ci		mode = pmac_i2c_mode_std;
4762306a36Sopenharmony_ci		subsize = 0;
4862306a36Sopenharmony_ci		subaddr = 0;
4962306a36Sopenharmony_ci	} else {
5062306a36Sopenharmony_ci		mode = read ? pmac_i2c_mode_combined : pmac_i2c_mode_stdsub;
5162306a36Sopenharmony_ci		subsize = 1;
5262306a36Sopenharmony_ci		subaddr = command;
5362306a36Sopenharmony_ci	}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	switch (size) {
5662306a36Sopenharmony_ci        case I2C_SMBUS_QUICK:
5762306a36Sopenharmony_ci		buf = NULL;
5862306a36Sopenharmony_ci		len = 0;
5962306a36Sopenharmony_ci	    	break;
6062306a36Sopenharmony_ci        case I2C_SMBUS_BYTE:
6162306a36Sopenharmony_ci        case I2C_SMBUS_BYTE_DATA:
6262306a36Sopenharmony_ci		buf = &data->byte;
6362306a36Sopenharmony_ci		len = 1;
6462306a36Sopenharmony_ci	    	break;
6562306a36Sopenharmony_ci        case I2C_SMBUS_WORD_DATA:
6662306a36Sopenharmony_ci		if (!read) {
6762306a36Sopenharmony_ci			local[0] = data->word & 0xff;
6862306a36Sopenharmony_ci			local[1] = (data->word >> 8) & 0xff;
6962306a36Sopenharmony_ci		}
7062306a36Sopenharmony_ci		buf = local;
7162306a36Sopenharmony_ci		len = 2;
7262306a36Sopenharmony_ci	    	break;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	/* Note that these are broken vs. the expected smbus API where
7562306a36Sopenharmony_ci	 * on reads, the length is actually returned from the function,
7662306a36Sopenharmony_ci	 * but I think the current API makes no sense and I don't want
7762306a36Sopenharmony_ci	 * any driver that I haven't verified for correctness to go
7862306a36Sopenharmony_ci	 * anywhere near a pmac i2c bus anyway ...
7962306a36Sopenharmony_ci	 */
8062306a36Sopenharmony_ci        case I2C_SMBUS_BLOCK_DATA:
8162306a36Sopenharmony_ci		buf = data->block;
8262306a36Sopenharmony_ci		len = data->block[0] + 1;
8362306a36Sopenharmony_ci		break;
8462306a36Sopenharmony_ci	case I2C_SMBUS_I2C_BLOCK_DATA:
8562306a36Sopenharmony_ci		buf = &data->block[1];
8662306a36Sopenharmony_ci		len = data->block[0];
8762306a36Sopenharmony_ci		break;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci        default:
9062306a36Sopenharmony_ci		return -EINVAL;
9162306a36Sopenharmony_ci	}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	rc = pmac_i2c_open(bus, 0);
9462306a36Sopenharmony_ci	if (rc) {
9562306a36Sopenharmony_ci		dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
9662306a36Sopenharmony_ci		return rc;
9762306a36Sopenharmony_ci	}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	rc = pmac_i2c_setmode(bus, mode);
10062306a36Sopenharmony_ci	if (rc) {
10162306a36Sopenharmony_ci		dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
10262306a36Sopenharmony_ci			mode, rc);
10362306a36Sopenharmony_ci		goto bail;
10462306a36Sopenharmony_ci	}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len);
10762306a36Sopenharmony_ci	if (rc) {
10862306a36Sopenharmony_ci		if (rc == -ENXIO)
10962306a36Sopenharmony_ci			dev_dbg(&adap->dev,
11062306a36Sopenharmony_ci				"I2C transfer at 0x%02x failed, size %d, "
11162306a36Sopenharmony_ci				"err %d\n", addrdir >> 1, size, rc);
11262306a36Sopenharmony_ci		else
11362306a36Sopenharmony_ci			dev_err(&adap->dev,
11462306a36Sopenharmony_ci				"I2C transfer at 0x%02x failed, size %d, "
11562306a36Sopenharmony_ci				"err %d\n", addrdir >> 1, size, rc);
11662306a36Sopenharmony_ci		goto bail;
11762306a36Sopenharmony_ci	}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	if (size == I2C_SMBUS_WORD_DATA && read) {
12062306a36Sopenharmony_ci		data->word = ((u16)local[1]) << 8;
12162306a36Sopenharmony_ci		data->word |= local[0];
12262306a36Sopenharmony_ci	}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci bail:
12562306a36Sopenharmony_ci	pmac_i2c_close(bus);
12662306a36Sopenharmony_ci	return rc;
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci/*
13062306a36Sopenharmony_ci * Generic i2c master transfer entrypoint. This driver only support single
13162306a36Sopenharmony_ci * messages (for "lame i2c" transfers). Anything else should use the smbus
13262306a36Sopenharmony_ci * entry point
13362306a36Sopenharmony_ci */
13462306a36Sopenharmony_cistatic int i2c_powermac_master_xfer(	struct i2c_adapter *adap,
13562306a36Sopenharmony_ci					struct i2c_msg *msgs,
13662306a36Sopenharmony_ci					int num)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	struct pmac_i2c_bus	*bus = i2c_get_adapdata(adap);
13962306a36Sopenharmony_ci	int			rc = 0;
14062306a36Sopenharmony_ci	int			addrdir;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	if (msgs->flags & I2C_M_TEN)
14362306a36Sopenharmony_ci		return -EINVAL;
14462306a36Sopenharmony_ci	addrdir = i2c_8bit_addr_from_msg(msgs);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	rc = pmac_i2c_open(bus, 0);
14762306a36Sopenharmony_ci	if (rc) {
14862306a36Sopenharmony_ci		dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
14962306a36Sopenharmony_ci		return rc;
15062306a36Sopenharmony_ci	}
15162306a36Sopenharmony_ci	rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
15262306a36Sopenharmony_ci	if (rc) {
15362306a36Sopenharmony_ci		dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
15462306a36Sopenharmony_ci			pmac_i2c_mode_std, rc);
15562306a36Sopenharmony_ci		goto bail;
15662306a36Sopenharmony_ci	}
15762306a36Sopenharmony_ci	rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len);
15862306a36Sopenharmony_ci	if (rc < 0) {
15962306a36Sopenharmony_ci		if (rc == -ENXIO)
16062306a36Sopenharmony_ci			dev_dbg(&adap->dev, "I2C %s 0x%02x failed, err %d\n",
16162306a36Sopenharmony_ci				addrdir & 1 ? "read from" : "write to",
16262306a36Sopenharmony_ci				addrdir >> 1, rc);
16362306a36Sopenharmony_ci		else
16462306a36Sopenharmony_ci			dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n",
16562306a36Sopenharmony_ci				addrdir & 1 ? "read from" : "write to",
16662306a36Sopenharmony_ci				addrdir >> 1, rc);
16762306a36Sopenharmony_ci	}
16862306a36Sopenharmony_ci bail:
16962306a36Sopenharmony_ci	pmac_i2c_close(bus);
17062306a36Sopenharmony_ci	return rc < 0 ? rc : 1;
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_cistatic u32 i2c_powermac_func(struct i2c_adapter * adapter)
17462306a36Sopenharmony_ci{
17562306a36Sopenharmony_ci	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
17662306a36Sopenharmony_ci		I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
17762306a36Sopenharmony_ci		I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_I2C;
17862306a36Sopenharmony_ci}
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci/* For now, we only handle smbus */
18162306a36Sopenharmony_cistatic const struct i2c_algorithm i2c_powermac_algorithm = {
18262306a36Sopenharmony_ci	.smbus_xfer	= i2c_powermac_smbus_xfer,
18362306a36Sopenharmony_ci	.master_xfer	= i2c_powermac_master_xfer,
18462306a36Sopenharmony_ci	.functionality	= i2c_powermac_func,
18562306a36Sopenharmony_ci};
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_cistatic const struct i2c_adapter_quirks i2c_powermac_quirks = {
18862306a36Sopenharmony_ci	.max_num_msgs = 1,
18962306a36Sopenharmony_ci};
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_cistatic void i2c_powermac_remove(struct platform_device *dev)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	struct i2c_adapter	*adapter = platform_get_drvdata(dev);
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	i2c_del_adapter(adapter);
19662306a36Sopenharmony_ci	memset(adapter, 0, sizeof(*adapter));
19762306a36Sopenharmony_ci}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_cistatic u32 i2c_powermac_get_addr(struct i2c_adapter *adap,
20062306a36Sopenharmony_ci					   struct pmac_i2c_bus *bus,
20162306a36Sopenharmony_ci					   struct device_node *node)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	u32 prop;
20462306a36Sopenharmony_ci	int ret;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	/* First check for valid "reg" */
20762306a36Sopenharmony_ci	ret = of_property_read_u32(node, "reg", &prop);
20862306a36Sopenharmony_ci	if (ret == 0)
20962306a36Sopenharmony_ci		return (prop & 0xff) >> 1;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	/* Then check old-style "i2c-address" */
21262306a36Sopenharmony_ci	ret = of_property_read_u32(node, "i2c-address", &prop);
21362306a36Sopenharmony_ci	if (ret == 0)
21462306a36Sopenharmony_ci		return (prop & 0xff) >> 1;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	/* Now handle some devices with missing "reg" properties */
21762306a36Sopenharmony_ci	if (of_node_name_eq(node, "cereal"))
21862306a36Sopenharmony_ci		return 0x60;
21962306a36Sopenharmony_ci	else if (of_node_name_eq(node, "deq"))
22062306a36Sopenharmony_ci		return 0x34;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	dev_warn(&adap->dev, "No i2c address for %pOF\n", node);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	return 0xffffffff;
22562306a36Sopenharmony_ci}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_cistatic void i2c_powermac_create_one(struct i2c_adapter *adap,
22862306a36Sopenharmony_ci					      const char *type,
22962306a36Sopenharmony_ci					      u32 addr)
23062306a36Sopenharmony_ci{
23162306a36Sopenharmony_ci	struct i2c_board_info info = {};
23262306a36Sopenharmony_ci	struct i2c_client *newdev;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	strncpy(info.type, type, sizeof(info.type));
23562306a36Sopenharmony_ci	info.addr = addr;
23662306a36Sopenharmony_ci	newdev = i2c_new_client_device(adap, &info);
23762306a36Sopenharmony_ci	if (IS_ERR(newdev))
23862306a36Sopenharmony_ci		dev_err(&adap->dev,
23962306a36Sopenharmony_ci			"i2c-powermac: Failure to register missing %s\n",
24062306a36Sopenharmony_ci			type);
24162306a36Sopenharmony_ci}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_cistatic void i2c_powermac_add_missing(struct i2c_adapter *adap,
24462306a36Sopenharmony_ci					       struct pmac_i2c_bus *bus,
24562306a36Sopenharmony_ci					       bool found_onyx)
24662306a36Sopenharmony_ci{
24762306a36Sopenharmony_ci	struct device_node *busnode = pmac_i2c_get_bus_node(bus);
24862306a36Sopenharmony_ci	int rc;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	/* Check for the onyx audio codec */
25162306a36Sopenharmony_ci#define ONYX_REG_CONTROL		67
25262306a36Sopenharmony_ci	if (of_device_is_compatible(busnode, "k2-i2c") && !found_onyx) {
25362306a36Sopenharmony_ci		union i2c_smbus_data data;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci		rc = i2c_smbus_xfer(adap, 0x46, 0, I2C_SMBUS_READ,
25662306a36Sopenharmony_ci				    ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA,
25762306a36Sopenharmony_ci				    &data);
25862306a36Sopenharmony_ci		if (rc >= 0)
25962306a36Sopenharmony_ci			i2c_powermac_create_one(adap, "MAC,pcm3052", 0x46);
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci		rc = i2c_smbus_xfer(adap, 0x47, 0, I2C_SMBUS_READ,
26262306a36Sopenharmony_ci				    ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA,
26362306a36Sopenharmony_ci				    &data);
26462306a36Sopenharmony_ci		if (rc >= 0)
26562306a36Sopenharmony_ci			i2c_powermac_create_one(adap, "MAC,pcm3052", 0x47);
26662306a36Sopenharmony_ci	}
26762306a36Sopenharmony_ci}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_cistatic bool i2c_powermac_get_type(struct i2c_adapter *adap,
27062306a36Sopenharmony_ci					    struct device_node *node,
27162306a36Sopenharmony_ci					    u32 addr, char *type, int type_size)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	char tmp[16];
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	/*
27662306a36Sopenharmony_ci	 * Note: we do _NOT_ want the standard i2c drivers to match with any of
27762306a36Sopenharmony_ci	 * our powermac stuff unless they have been specifically modified to
27862306a36Sopenharmony_ci	 * handle it on a case by case basis. For example, for thermal control,
27962306a36Sopenharmony_ci	 * things like lm75 etc... shall match with their corresponding
28062306a36Sopenharmony_ci	 * windfarm drivers, _NOT_ the generic ones, so we force a prefix of
28162306a36Sopenharmony_ci	 * 'MAC', onto the modalias to make that happen
28262306a36Sopenharmony_ci	 */
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/* First try proper modalias */
28562306a36Sopenharmony_ci	if (of_alias_from_compatible(node, tmp, sizeof(tmp)) >= 0) {
28662306a36Sopenharmony_ci		snprintf(type, type_size, "MAC,%s", tmp);
28762306a36Sopenharmony_ci		return true;
28862306a36Sopenharmony_ci	}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	/* Now look for known workarounds */
29162306a36Sopenharmony_ci	if (of_node_name_eq(node, "deq")) {
29262306a36Sopenharmony_ci		/* Apple uses address 0x34 for TAS3001 and 0x35 for TAS3004 */
29362306a36Sopenharmony_ci		if (addr == 0x34) {
29462306a36Sopenharmony_ci			snprintf(type, type_size, "MAC,tas3001");
29562306a36Sopenharmony_ci			return true;
29662306a36Sopenharmony_ci		} else if (addr == 0x35) {
29762306a36Sopenharmony_ci			snprintf(type, type_size, "MAC,tas3004");
29862306a36Sopenharmony_ci			return true;
29962306a36Sopenharmony_ci		}
30062306a36Sopenharmony_ci	}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	dev_err(&adap->dev, "i2c-powermac: modalias failure on %pOF\n", node);
30362306a36Sopenharmony_ci	return false;
30462306a36Sopenharmony_ci}
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_cistatic void i2c_powermac_register_devices(struct i2c_adapter *adap,
30762306a36Sopenharmony_ci						    struct pmac_i2c_bus *bus)
30862306a36Sopenharmony_ci{
30962306a36Sopenharmony_ci	struct i2c_client *newdev;
31062306a36Sopenharmony_ci	struct device_node *node;
31162306a36Sopenharmony_ci	bool found_onyx = false;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	/*
31462306a36Sopenharmony_ci	 * In some cases we end up with the via-pmu node itself, in this
31562306a36Sopenharmony_ci	 * case we skip this function completely as the device-tree will
31662306a36Sopenharmony_ci	 * not contain anything useful.
31762306a36Sopenharmony_ci	 */
31862306a36Sopenharmony_ci	if (of_node_name_eq(adap->dev.of_node, "via-pmu"))
31962306a36Sopenharmony_ci		return;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	for_each_child_of_node(adap->dev.of_node, node) {
32262306a36Sopenharmony_ci		struct i2c_board_info info = {};
32362306a36Sopenharmony_ci		u32 addr;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci		/* Get address & channel */
32662306a36Sopenharmony_ci		addr = i2c_powermac_get_addr(adap, bus, node);
32762306a36Sopenharmony_ci		if (addr == 0xffffffff)
32862306a36Sopenharmony_ci			continue;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci		/* Multibus setup, check channel */
33162306a36Sopenharmony_ci		if (!pmac_i2c_match_adapter(node, adap))
33262306a36Sopenharmony_ci			continue;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci		dev_dbg(&adap->dev, "i2c-powermac: register %pOF\n", node);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci		/*
33762306a36Sopenharmony_ci		 * Keep track of some device existence to handle
33862306a36Sopenharmony_ci		 * workarounds later.
33962306a36Sopenharmony_ci		 */
34062306a36Sopenharmony_ci		if (of_device_is_compatible(node, "pcm3052"))
34162306a36Sopenharmony_ci			found_onyx = true;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci		/* Make up a modalias */
34462306a36Sopenharmony_ci		if (!i2c_powermac_get_type(adap, node, addr,
34562306a36Sopenharmony_ci					   info.type, sizeof(info.type))) {
34662306a36Sopenharmony_ci			continue;
34762306a36Sopenharmony_ci		}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci		/* Fill out the rest of the info structure */
35062306a36Sopenharmony_ci		info.addr = addr;
35162306a36Sopenharmony_ci		info.irq = irq_of_parse_and_map(node, 0);
35262306a36Sopenharmony_ci		info.of_node = of_node_get(node);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci		newdev = i2c_new_client_device(adap, &info);
35562306a36Sopenharmony_ci		if (IS_ERR(newdev)) {
35662306a36Sopenharmony_ci			dev_err(&adap->dev, "i2c-powermac: Failure to register"
35762306a36Sopenharmony_ci				" %pOF\n", node);
35862306a36Sopenharmony_ci			of_node_put(node);
35962306a36Sopenharmony_ci			/* We do not dispose of the interrupt mapping on
36062306a36Sopenharmony_ci			 * purpose. It's not necessary (interrupt cannot be
36162306a36Sopenharmony_ci			 * re-used) and somebody else might have grabbed it
36262306a36Sopenharmony_ci			 * via direct DT lookup so let's not bother
36362306a36Sopenharmony_ci			 */
36462306a36Sopenharmony_ci			continue;
36562306a36Sopenharmony_ci		}
36662306a36Sopenharmony_ci	}
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	/* Additional workarounds */
36962306a36Sopenharmony_ci	i2c_powermac_add_missing(adap, bus, found_onyx);
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_cistatic int i2c_powermac_probe(struct platform_device *dev)
37362306a36Sopenharmony_ci{
37462306a36Sopenharmony_ci	struct pmac_i2c_bus *bus = dev_get_platdata(&dev->dev);
37562306a36Sopenharmony_ci	struct device_node *parent;
37662306a36Sopenharmony_ci	struct i2c_adapter *adapter;
37762306a36Sopenharmony_ci	int rc;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	if (bus == NULL)
38062306a36Sopenharmony_ci		return -EINVAL;
38162306a36Sopenharmony_ci	adapter = pmac_i2c_get_adapter(bus);
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	/* Ok, now we need to make up a name for the interface that will
38462306a36Sopenharmony_ci	 * match what we used to do in the past, that is basically the
38562306a36Sopenharmony_ci	 * controller's parent device node for keywest. PMU didn't have a
38662306a36Sopenharmony_ci	 * naming convention and SMU has a different one
38762306a36Sopenharmony_ci	 */
38862306a36Sopenharmony_ci	switch(pmac_i2c_get_type(bus)) {
38962306a36Sopenharmony_ci	case pmac_i2c_bus_keywest:
39062306a36Sopenharmony_ci		parent = of_get_parent(pmac_i2c_get_controller(bus));
39162306a36Sopenharmony_ci		if (parent == NULL)
39262306a36Sopenharmony_ci			return -EINVAL;
39362306a36Sopenharmony_ci		snprintf(adapter->name, sizeof(adapter->name), "%pOFn %d",
39462306a36Sopenharmony_ci			 parent,
39562306a36Sopenharmony_ci			 pmac_i2c_get_channel(bus));
39662306a36Sopenharmony_ci		of_node_put(parent);
39762306a36Sopenharmony_ci		break;
39862306a36Sopenharmony_ci	case pmac_i2c_bus_pmu:
39962306a36Sopenharmony_ci		snprintf(adapter->name, sizeof(adapter->name), "pmu %d",
40062306a36Sopenharmony_ci			 pmac_i2c_get_channel(bus));
40162306a36Sopenharmony_ci		break;
40262306a36Sopenharmony_ci	case pmac_i2c_bus_smu:
40362306a36Sopenharmony_ci		/* This is not what we used to do but I'm fixing drivers at
40462306a36Sopenharmony_ci		 * the same time as this change
40562306a36Sopenharmony_ci		 */
40662306a36Sopenharmony_ci		snprintf(adapter->name, sizeof(adapter->name), "smu %d",
40762306a36Sopenharmony_ci			 pmac_i2c_get_channel(bus));
40862306a36Sopenharmony_ci		break;
40962306a36Sopenharmony_ci	default:
41062306a36Sopenharmony_ci		return -EINVAL;
41162306a36Sopenharmony_ci	}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	platform_set_drvdata(dev, adapter);
41462306a36Sopenharmony_ci	adapter->algo = &i2c_powermac_algorithm;
41562306a36Sopenharmony_ci	adapter->quirks = &i2c_powermac_quirks;
41662306a36Sopenharmony_ci	i2c_set_adapdata(adapter, bus);
41762306a36Sopenharmony_ci	adapter->dev.parent = &dev->dev;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	/* Clear of_node to skip automatic registration of i2c child nodes */
42062306a36Sopenharmony_ci	adapter->dev.of_node = NULL;
42162306a36Sopenharmony_ci	rc = i2c_add_adapter(adapter);
42262306a36Sopenharmony_ci	if (rc) {
42362306a36Sopenharmony_ci		printk(KERN_ERR "i2c-powermac: Adapter %s registration "
42462306a36Sopenharmony_ci		       "failed\n", adapter->name);
42562306a36Sopenharmony_ci		memset(adapter, 0, sizeof(*adapter));
42662306a36Sopenharmony_ci		return rc;
42762306a36Sopenharmony_ci	}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name);
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	/* Use custom child registration due to Apple device-tree funkyness */
43262306a36Sopenharmony_ci	adapter->dev.of_node = dev->dev.of_node;
43362306a36Sopenharmony_ci	i2c_powermac_register_devices(adapter, bus);
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	return 0;
43662306a36Sopenharmony_ci}
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_cistatic struct platform_driver i2c_powermac_driver = {
43962306a36Sopenharmony_ci	.probe = i2c_powermac_probe,
44062306a36Sopenharmony_ci	.remove_new = i2c_powermac_remove,
44162306a36Sopenharmony_ci	.driver = {
44262306a36Sopenharmony_ci		.name = "i2c-powermac",
44362306a36Sopenharmony_ci		.bus = &platform_bus_type,
44462306a36Sopenharmony_ci	},
44562306a36Sopenharmony_ci};
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_cimodule_platform_driver(i2c_powermac_driver);
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ciMODULE_ALIAS("platform:i2c-powermac");
450