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; 5202864d58SJean Delvare int mode, subsize, len; 5302864d58SJean Delvare u32 subaddr; 5402864d58SJean Delvare u8 *buf; 55a28d3af2SBenjamin Herrenschmidt u8 local[2]; 56a28d3af2SBenjamin Herrenschmidt 5702864d58SJean Delvare if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) { 5802864d58SJean Delvare mode = pmac_i2c_mode_std; 5902864d58SJean Delvare subsize = 0; 6002864d58SJean Delvare subaddr = 0; 6102864d58SJean Delvare } else { 6202864d58SJean Delvare mode = read ? pmac_i2c_mode_combined : pmac_i2c_mode_stdsub; 6302864d58SJean Delvare subsize = 1; 6402864d58SJean Delvare subaddr = command; 6502864d58SJean Delvare } 66a28d3af2SBenjamin Herrenschmidt 67a28d3af2SBenjamin Herrenschmidt switch (size) { 68a28d3af2SBenjamin Herrenschmidt case I2C_SMBUS_QUICK: 6902864d58SJean Delvare buf = NULL; 7002864d58SJean Delvare len = 0; 71a28d3af2SBenjamin Herrenschmidt break; 72a28d3af2SBenjamin Herrenschmidt case I2C_SMBUS_BYTE: 73a28d3af2SBenjamin Herrenschmidt case I2C_SMBUS_BYTE_DATA: 7402864d58SJean Delvare buf = &data->byte; 7502864d58SJean Delvare len = 1; 76a28d3af2SBenjamin Herrenschmidt break; 77a28d3af2SBenjamin Herrenschmidt case I2C_SMBUS_WORD_DATA: 78a28d3af2SBenjamin Herrenschmidt if (!read) { 79a28d3af2SBenjamin Herrenschmidt local[0] = data->word & 0xff; 80a28d3af2SBenjamin Herrenschmidt local[1] = (data->word >> 8) & 0xff; 81a28d3af2SBenjamin Herrenschmidt } 8202864d58SJean Delvare buf = local; 8302864d58SJean Delvare len = 2; 84a28d3af2SBenjamin Herrenschmidt break; 85a28d3af2SBenjamin Herrenschmidt 86a28d3af2SBenjamin Herrenschmidt /* Note that these are broken vs. the expected smbus API where 8796acafe0SJoe Perches * on reads, the length is actually returned from the function, 88a28d3af2SBenjamin Herrenschmidt * but I think the current API makes no sense and I don't want 89a28d3af2SBenjamin Herrenschmidt * any driver that I haven't verified for correctness to go 90a28d3af2SBenjamin Herrenschmidt * anywhere near a pmac i2c bus anyway ... 91a28d3af2SBenjamin Herrenschmidt * 92a28d3af2SBenjamin Herrenschmidt * I'm also not completely sure what kind of phases to do between 93a28d3af2SBenjamin Herrenschmidt * the actual command and the data (what I am _supposed_ to do that 94a28d3af2SBenjamin Herrenschmidt * is). For now, I assume writes are a single stream and reads have 95a28d3af2SBenjamin Herrenschmidt * a repeat start/addr phase (but not stop in between) 96a28d3af2SBenjamin Herrenschmidt */ 97a28d3af2SBenjamin Herrenschmidt case I2C_SMBUS_BLOCK_DATA: 9802864d58SJean Delvare buf = data->block; 9902864d58SJean Delvare len = data->block[0] + 1; 100a28d3af2SBenjamin Herrenschmidt break; 101a28d3af2SBenjamin Herrenschmidt case I2C_SMBUS_I2C_BLOCK_DATA: 10202864d58SJean Delvare buf = &data->block[1]; 10302864d58SJean Delvare len = data->block[0]; 104a28d3af2SBenjamin Herrenschmidt break; 105a28d3af2SBenjamin Herrenschmidt 106a28d3af2SBenjamin Herrenschmidt default: 10702864d58SJean Delvare return -EINVAL; 108a28d3af2SBenjamin Herrenschmidt } 10902864d58SJean Delvare 11002864d58SJean Delvare rc = pmac_i2c_open(bus, 0); 111d7d838a6SJean Delvare if (rc) { 112d7d838a6SJean Delvare dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc); 11302864d58SJean Delvare return rc; 114d7d838a6SJean Delvare } 11502864d58SJean Delvare 11602864d58SJean Delvare rc = pmac_i2c_setmode(bus, mode); 117d7d838a6SJean Delvare if (rc) { 118d7d838a6SJean Delvare dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n", 119d7d838a6SJean Delvare mode, rc); 12002864d58SJean Delvare goto bail; 121d7d838a6SJean Delvare } 12202864d58SJean Delvare 12302864d58SJean Delvare rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len); 124d7d838a6SJean Delvare if (rc) { 1258e4b980cSJean Delvare if (rc == -ENXIO) 1268e4b980cSJean Delvare dev_dbg(&adap->dev, 1278e4b980cSJean Delvare "I2C transfer at 0x%02x failed, size %d, " 1288e4b980cSJean Delvare "err %d\n", addrdir >> 1, size, rc); 1298e4b980cSJean Delvare else 130d7d838a6SJean Delvare dev_err(&adap->dev, 1318e4b980cSJean Delvare "I2C transfer at 0x%02x failed, size %d, " 1328e4b980cSJean Delvare "err %d\n", addrdir >> 1, size, rc); 13302864d58SJean Delvare goto bail; 134d7d838a6SJean Delvare } 13502864d58SJean Delvare 13602864d58SJean Delvare if (size == I2C_SMBUS_WORD_DATA && read) { 13702864d58SJean Delvare data->word = ((u16)local[1]) << 8; 13802864d58SJean Delvare data->word |= local[0]; 13902864d58SJean Delvare } 14002864d58SJean Delvare 141a28d3af2SBenjamin Herrenschmidt bail: 142a28d3af2SBenjamin Herrenschmidt pmac_i2c_close(bus); 143a28d3af2SBenjamin Herrenschmidt return rc; 144a28d3af2SBenjamin Herrenschmidt } 145a28d3af2SBenjamin Herrenschmidt 146a28d3af2SBenjamin Herrenschmidt /* 147a28d3af2SBenjamin Herrenschmidt * Generic i2c master transfer entrypoint. This driver only support single 148a28d3af2SBenjamin Herrenschmidt * messages (for "lame i2c" transfers). Anything else should use the smbus 149a28d3af2SBenjamin Herrenschmidt * entry point 150a28d3af2SBenjamin Herrenschmidt */ 151a28d3af2SBenjamin Herrenschmidt static int i2c_powermac_master_xfer( struct i2c_adapter *adap, 152a28d3af2SBenjamin Herrenschmidt struct i2c_msg *msgs, 153a28d3af2SBenjamin Herrenschmidt int num) 154a28d3af2SBenjamin Herrenschmidt { 155a28d3af2SBenjamin Herrenschmidt struct pmac_i2c_bus *bus = i2c_get_adapdata(adap); 156a28d3af2SBenjamin Herrenschmidt int rc = 0; 157a28d3af2SBenjamin Herrenschmidt int read; 158a28d3af2SBenjamin Herrenschmidt int addrdir; 159a28d3af2SBenjamin Herrenschmidt 1606f7e549fSJean Delvare if (num != 1) { 1616f7e549fSJean Delvare dev_err(&adap->dev, 1626f7e549fSJean Delvare "Multi-message I2C transactions not supported\n"); 1636f7e549fSJean Delvare return -EOPNOTSUPP; 1646f7e549fSJean Delvare } 1656f7e549fSJean Delvare 166a28d3af2SBenjamin Herrenschmidt if (msgs->flags & I2C_M_TEN) 167a28d3af2SBenjamin Herrenschmidt return -EINVAL; 168a28d3af2SBenjamin Herrenschmidt read = (msgs->flags & I2C_M_RD) != 0; 169a28d3af2SBenjamin Herrenschmidt addrdir = (msgs->addr << 1) | read; 170a28d3af2SBenjamin Herrenschmidt 171a28d3af2SBenjamin Herrenschmidt rc = pmac_i2c_open(bus, 0); 172d7d838a6SJean Delvare if (rc) { 173d7d838a6SJean Delvare dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc); 174a28d3af2SBenjamin Herrenschmidt return rc; 175d7d838a6SJean Delvare } 176a28d3af2SBenjamin Herrenschmidt rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); 177d7d838a6SJean Delvare if (rc) { 178d7d838a6SJean Delvare dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n", 179d7d838a6SJean Delvare pmac_i2c_mode_std, rc); 180a28d3af2SBenjamin Herrenschmidt goto bail; 181d7d838a6SJean Delvare } 182a28d3af2SBenjamin Herrenschmidt rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len); 1838e4b980cSJean Delvare if (rc < 0) { 1848e4b980cSJean Delvare if (rc == -ENXIO) 1858e4b980cSJean Delvare dev_dbg(&adap->dev, "I2C %s 0x%02x failed, err %d\n", 1868e4b980cSJean Delvare addrdir & 1 ? "read from" : "write to", 1878e4b980cSJean Delvare addrdir >> 1, rc); 1888e4b980cSJean Delvare else 189d7d838a6SJean Delvare dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n", 1908e4b980cSJean Delvare addrdir & 1 ? "read from" : "write to", 1918e4b980cSJean Delvare addrdir >> 1, rc); 1928e4b980cSJean Delvare } 193a28d3af2SBenjamin Herrenschmidt bail: 194a28d3af2SBenjamin Herrenschmidt pmac_i2c_close(bus); 1958ced8eeeSJean Delvare return rc < 0 ? rc : 1; 196a28d3af2SBenjamin Herrenschmidt } 197a28d3af2SBenjamin Herrenschmidt 198a28d3af2SBenjamin Herrenschmidt static u32 i2c_powermac_func(struct i2c_adapter * adapter) 199a28d3af2SBenjamin Herrenschmidt { 200a28d3af2SBenjamin Herrenschmidt return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | 201a28d3af2SBenjamin Herrenschmidt I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | 202a28d3af2SBenjamin Herrenschmidt I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_I2C; 203a28d3af2SBenjamin Herrenschmidt } 204a28d3af2SBenjamin Herrenschmidt 205a28d3af2SBenjamin Herrenschmidt /* For now, we only handle smbus */ 2068f9082c5SJean Delvare static const struct i2c_algorithm i2c_powermac_algorithm = { 207a28d3af2SBenjamin Herrenschmidt .smbus_xfer = i2c_powermac_smbus_xfer, 208a28d3af2SBenjamin Herrenschmidt .master_xfer = i2c_powermac_master_xfer, 209a28d3af2SBenjamin Herrenschmidt .functionality = i2c_powermac_func, 210a28d3af2SBenjamin Herrenschmidt }; 211a28d3af2SBenjamin Herrenschmidt 212a28d3af2SBenjamin Herrenschmidt 2130b255e92SBill Pemberton static int i2c_powermac_remove(struct platform_device *dev) 214a28d3af2SBenjamin Herrenschmidt { 2159f2545c1SBenjamin Herrenschmidt struct i2c_adapter *adapter = platform_get_drvdata(dev); 216a28d3af2SBenjamin Herrenschmidt 217bf51a8c5SLars-Peter Clausen i2c_del_adapter(adapter); 2186dfa5ca3SJean Delvare memset(adapter, 0, sizeof(*adapter)); 219a28d3af2SBenjamin Herrenschmidt 220a28d3af2SBenjamin Herrenschmidt return 0; 221a28d3af2SBenjamin Herrenschmidt } 222a28d3af2SBenjamin Herrenschmidt 2230b255e92SBill Pemberton static u32 i2c_powermac_get_addr(struct i2c_adapter *adap, 2243a3dd018SBenjamin Herrenschmidt struct pmac_i2c_bus *bus, 2253a3dd018SBenjamin Herrenschmidt struct device_node *node) 22681e5d864SBenjamin Herrenschmidt { 2273a3dd018SBenjamin Herrenschmidt const __be32 *prop; 22881e5d864SBenjamin Herrenschmidt int len; 22981e5d864SBenjamin Herrenschmidt 2303a3dd018SBenjamin Herrenschmidt /* First check for valid "reg" */ 2313a3dd018SBenjamin Herrenschmidt prop = of_get_property(node, "reg", &len); 2323a3dd018SBenjamin Herrenschmidt if (prop && (len >= sizeof(int))) 2333a3dd018SBenjamin Herrenschmidt return (be32_to_cpup(prop) & 0xff) >> 1; 2343a3dd018SBenjamin Herrenschmidt 2353a3dd018SBenjamin Herrenschmidt /* Then check old-style "i2c-address" */ 2363a3dd018SBenjamin Herrenschmidt prop = of_get_property(node, "i2c-address", &len); 2373a3dd018SBenjamin Herrenschmidt if (prop && (len >= sizeof(int))) 2383a3dd018SBenjamin Herrenschmidt return (be32_to_cpup(prop) & 0xff) >> 1; 2393a3dd018SBenjamin Herrenschmidt 2403a3dd018SBenjamin Herrenschmidt /* Now handle some devices with missing "reg" properties */ 2413a3dd018SBenjamin Herrenschmidt if (!strcmp(node->name, "cereal")) 2423a3dd018SBenjamin Herrenschmidt return 0x60; 2433a3dd018SBenjamin Herrenschmidt else if (!strcmp(node->name, "deq")) 2443a3dd018SBenjamin Herrenschmidt return 0x34; 2453a3dd018SBenjamin Herrenschmidt 2463a3dd018SBenjamin Herrenschmidt dev_warn(&adap->dev, "No i2c address for %s\n", node->full_name); 2473a3dd018SBenjamin Herrenschmidt 2483a3dd018SBenjamin Herrenschmidt return 0xffffffff; 24981e5d864SBenjamin Herrenschmidt } 25081e5d864SBenjamin Herrenschmidt 2510b255e92SBill Pemberton static void i2c_powermac_create_one(struct i2c_adapter *adap, 2523a3dd018SBenjamin Herrenschmidt const char *type, 2533a3dd018SBenjamin Herrenschmidt u32 addr) 2543a3dd018SBenjamin Herrenschmidt { 2553a3dd018SBenjamin Herrenschmidt struct i2c_board_info info = {}; 2563a3dd018SBenjamin Herrenschmidt struct i2c_client *newdev; 25781e5d864SBenjamin Herrenschmidt 2583a3dd018SBenjamin Herrenschmidt strncpy(info.type, type, sizeof(info.type)); 2593a3dd018SBenjamin Herrenschmidt info.addr = addr; 2603a3dd018SBenjamin Herrenschmidt newdev = i2c_new_device(adap, &info); 2613a3dd018SBenjamin Herrenschmidt if (!newdev) 2623a3dd018SBenjamin Herrenschmidt dev_err(&adap->dev, 2633a3dd018SBenjamin Herrenschmidt "i2c-powermac: Failure to register missing %s\n", 2643a3dd018SBenjamin Herrenschmidt type); 2653a3dd018SBenjamin Herrenschmidt } 26681e5d864SBenjamin Herrenschmidt 2670b255e92SBill Pemberton static void i2c_powermac_add_missing(struct i2c_adapter *adap, 2683a3dd018SBenjamin Herrenschmidt struct pmac_i2c_bus *bus, 2693a3dd018SBenjamin Herrenschmidt bool found_onyx) 2703a3dd018SBenjamin Herrenschmidt { 2713a3dd018SBenjamin Herrenschmidt struct device_node *busnode = pmac_i2c_get_bus_node(bus); 2723a3dd018SBenjamin Herrenschmidt int rc; 2733a3dd018SBenjamin Herrenschmidt 2743a3dd018SBenjamin Herrenschmidt /* Check for the onyx audio codec */ 2753a3dd018SBenjamin Herrenschmidt #define ONYX_REG_CONTROL 67 2763a3dd018SBenjamin Herrenschmidt if (of_device_is_compatible(busnode, "k2-i2c") && !found_onyx) { 2773a3dd018SBenjamin Herrenschmidt union i2c_smbus_data data; 2783a3dd018SBenjamin Herrenschmidt 2793a3dd018SBenjamin Herrenschmidt rc = i2c_smbus_xfer(adap, 0x46, 0, I2C_SMBUS_READ, 2803a3dd018SBenjamin Herrenschmidt ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA, 2813a3dd018SBenjamin Herrenschmidt &data); 2823a3dd018SBenjamin Herrenschmidt if (rc >= 0) 2833a3dd018SBenjamin Herrenschmidt i2c_powermac_create_one(adap, "MAC,pcm3052", 0x46); 2843a3dd018SBenjamin Herrenschmidt 2853a3dd018SBenjamin Herrenschmidt rc = i2c_smbus_xfer(adap, 0x47, 0, I2C_SMBUS_READ, 2863a3dd018SBenjamin Herrenschmidt ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA, 2873a3dd018SBenjamin Herrenschmidt &data); 2883a3dd018SBenjamin Herrenschmidt if (rc >= 0) 2893a3dd018SBenjamin Herrenschmidt i2c_powermac_create_one(adap, "MAC,pcm3052", 0x47); 2903a3dd018SBenjamin Herrenschmidt } 2913a3dd018SBenjamin Herrenschmidt } 2923a3dd018SBenjamin Herrenschmidt 2930b255e92SBill Pemberton static bool i2c_powermac_get_type(struct i2c_adapter *adap, 2943a3dd018SBenjamin Herrenschmidt struct device_node *node, 2953a3dd018SBenjamin Herrenschmidt u32 addr, char *type, int type_size) 2963a3dd018SBenjamin Herrenschmidt { 2973a3dd018SBenjamin Herrenschmidt char tmp[16]; 2983a3dd018SBenjamin Herrenschmidt 2993a3dd018SBenjamin Herrenschmidt /* Note: we to _NOT_ want the standard 30081e5d864SBenjamin Herrenschmidt * i2c drivers to match with any of our powermac stuff 30181e5d864SBenjamin Herrenschmidt * unless they have been specifically modified to handle 30281e5d864SBenjamin Herrenschmidt * it on a case by case basis. For example, for thermal 30381e5d864SBenjamin Herrenschmidt * control, things like lm75 etc... shall match with their 30481e5d864SBenjamin Herrenschmidt * corresponding windfarm drivers, _NOT_ the generic ones, 30581e5d864SBenjamin Herrenschmidt * so we force a prefix of AAPL, onto the modalias to 30681e5d864SBenjamin Herrenschmidt * make that happen 30781e5d864SBenjamin Herrenschmidt */ 3083a3dd018SBenjamin Herrenschmidt 3093a3dd018SBenjamin Herrenschmidt /* First try proper modalias */ 3103a3dd018SBenjamin Herrenschmidt if (of_modalias_node(node, tmp, sizeof(tmp)) >= 0) { 3113a3dd018SBenjamin Herrenschmidt snprintf(type, type_size, "MAC,%s", tmp); 3123a3dd018SBenjamin Herrenschmidt return true; 3133a3dd018SBenjamin Herrenschmidt } 3143a3dd018SBenjamin Herrenschmidt 3153a3dd018SBenjamin Herrenschmidt /* Now look for known workarounds */ 3163a3dd018SBenjamin Herrenschmidt if (!strcmp(node->name, "deq")) { 3173a3dd018SBenjamin Herrenschmidt /* Apple uses address 0x34 for TAS3001 and 0x35 for TAS3004 */ 3183a3dd018SBenjamin Herrenschmidt if (addr == 0x34) { 3193a3dd018SBenjamin Herrenschmidt snprintf(type, type_size, "MAC,tas3001"); 3203a3dd018SBenjamin Herrenschmidt return true; 3213a3dd018SBenjamin Herrenschmidt } else if (addr == 0x35) { 3223a3dd018SBenjamin Herrenschmidt snprintf(type, type_size, "MAC,tas3004"); 3233a3dd018SBenjamin Herrenschmidt return true; 3243a3dd018SBenjamin Herrenschmidt } 3253a3dd018SBenjamin Herrenschmidt } 3263a3dd018SBenjamin Herrenschmidt 32781e5d864SBenjamin Herrenschmidt dev_err(&adap->dev, "i2c-powermac: modalias failure" 32881e5d864SBenjamin Herrenschmidt " on %s\n", node->full_name); 3293a3dd018SBenjamin Herrenschmidt return false; 3303a3dd018SBenjamin Herrenschmidt } 3313a3dd018SBenjamin Herrenschmidt 3320b255e92SBill Pemberton static void i2c_powermac_register_devices(struct i2c_adapter *adap, 3333a3dd018SBenjamin Herrenschmidt struct pmac_i2c_bus *bus) 3343a3dd018SBenjamin Herrenschmidt { 3353a3dd018SBenjamin Herrenschmidt struct i2c_client *newdev; 3363a3dd018SBenjamin Herrenschmidt struct device_node *node; 3373a3dd018SBenjamin Herrenschmidt bool found_onyx = 0; 3383a3dd018SBenjamin Herrenschmidt 3393a3dd018SBenjamin Herrenschmidt /* 3403a3dd018SBenjamin Herrenschmidt * In some cases we end up with the via-pmu node itself, in this 3413a3dd018SBenjamin Herrenschmidt * case we skip this function completely as the device-tree will 3423a3dd018SBenjamin Herrenschmidt * not contain anything useful. 3433a3dd018SBenjamin Herrenschmidt */ 3443a3dd018SBenjamin Herrenschmidt if (!strcmp(adap->dev.of_node->name, "via-pmu")) 3453a3dd018SBenjamin Herrenschmidt return; 3463a3dd018SBenjamin Herrenschmidt 3473a3dd018SBenjamin Herrenschmidt for_each_child_of_node(adap->dev.of_node, node) { 3483a3dd018SBenjamin Herrenschmidt struct i2c_board_info info = {}; 3493a3dd018SBenjamin Herrenschmidt u32 addr; 3503a3dd018SBenjamin Herrenschmidt 3513a3dd018SBenjamin Herrenschmidt /* Get address & channel */ 3523a3dd018SBenjamin Herrenschmidt addr = i2c_powermac_get_addr(adap, bus, node); 3533a3dd018SBenjamin Herrenschmidt if (addr == 0xffffffff) 3543a3dd018SBenjamin Herrenschmidt continue; 3553a3dd018SBenjamin Herrenschmidt 3563a3dd018SBenjamin Herrenschmidt /* Multibus setup, check channel */ 3573a3dd018SBenjamin Herrenschmidt if (!pmac_i2c_match_adapter(node, adap)) 3583a3dd018SBenjamin Herrenschmidt continue; 3593a3dd018SBenjamin Herrenschmidt 3603a3dd018SBenjamin Herrenschmidt dev_dbg(&adap->dev, "i2c-powermac: register %s\n", 3613a3dd018SBenjamin Herrenschmidt node->full_name); 3623a3dd018SBenjamin Herrenschmidt 3633a3dd018SBenjamin Herrenschmidt /* 3643a3dd018SBenjamin Herrenschmidt * Keep track of some device existence to handle 3653a3dd018SBenjamin Herrenschmidt * workarounds later. 3663a3dd018SBenjamin Herrenschmidt */ 3673a3dd018SBenjamin Herrenschmidt if (of_device_is_compatible(node, "pcm3052")) 3683a3dd018SBenjamin Herrenschmidt found_onyx = true; 3693a3dd018SBenjamin Herrenschmidt 3703a3dd018SBenjamin Herrenschmidt /* Make up a modalias */ 3713a3dd018SBenjamin Herrenschmidt if (!i2c_powermac_get_type(adap, node, addr, 3723a3dd018SBenjamin Herrenschmidt info.type, sizeof(info.type))) { 37381e5d864SBenjamin Herrenschmidt continue; 37481e5d864SBenjamin Herrenschmidt } 37581e5d864SBenjamin Herrenschmidt 37681e5d864SBenjamin Herrenschmidt /* Fill out the rest of the info structure */ 3773a3dd018SBenjamin Herrenschmidt info.addr = addr; 37881e5d864SBenjamin Herrenschmidt info.irq = irq_of_parse_and_map(node, 0); 37981e5d864SBenjamin Herrenschmidt info.of_node = of_node_get(node); 38081e5d864SBenjamin Herrenschmidt 38181e5d864SBenjamin Herrenschmidt newdev = i2c_new_device(adap, &info); 38281e5d864SBenjamin Herrenschmidt if (!newdev) { 38381e5d864SBenjamin Herrenschmidt dev_err(&adap->dev, "i2c-powermac: Failure to register" 38481e5d864SBenjamin Herrenschmidt " %s\n", node->full_name); 38581e5d864SBenjamin Herrenschmidt of_node_put(node); 38681e5d864SBenjamin Herrenschmidt /* We do not dispose of the interrupt mapping on 38781e5d864SBenjamin Herrenschmidt * purpose. It's not necessary (interrupt cannot be 38881e5d864SBenjamin Herrenschmidt * re-used) and somebody else might have grabbed it 38981e5d864SBenjamin Herrenschmidt * via direct DT lookup so let's not bother 39081e5d864SBenjamin Herrenschmidt */ 39181e5d864SBenjamin Herrenschmidt continue; 39281e5d864SBenjamin Herrenschmidt } 39381e5d864SBenjamin Herrenschmidt } 3943a3dd018SBenjamin Herrenschmidt 3953a3dd018SBenjamin Herrenschmidt /* Additional workarounds */ 3963a3dd018SBenjamin Herrenschmidt i2c_powermac_add_missing(adap, bus, found_onyx); 39781e5d864SBenjamin Herrenschmidt } 398a28d3af2SBenjamin Herrenschmidt 3990b255e92SBill Pemberton static int i2c_powermac_probe(struct platform_device *dev) 400a28d3af2SBenjamin Herrenschmidt { 4016d4028c6SJingoo Han struct pmac_i2c_bus *bus = dev_get_platdata(&dev->dev); 402a28d3af2SBenjamin Herrenschmidt struct device_node *parent = NULL; 403a28d3af2SBenjamin Herrenschmidt struct i2c_adapter *adapter; 404018a3d1dSJeremy Kerr const char *basename; 405a28d3af2SBenjamin Herrenschmidt int rc; 406a28d3af2SBenjamin Herrenschmidt 407a28d3af2SBenjamin Herrenschmidt if (bus == NULL) 408a28d3af2SBenjamin Herrenschmidt return -EINVAL; 409bc6286e5SJean Delvare adapter = pmac_i2c_get_adapter(bus); 410a28d3af2SBenjamin Herrenschmidt 411a28d3af2SBenjamin Herrenschmidt /* Ok, now we need to make up a name for the interface that will 412a28d3af2SBenjamin Herrenschmidt * match what we used to do in the past, that is basically the 413a28d3af2SBenjamin Herrenschmidt * controller's parent device node for keywest. PMU didn't have a 414a28d3af2SBenjamin Herrenschmidt * naming convention and SMU has a different one 415a28d3af2SBenjamin Herrenschmidt */ 416a28d3af2SBenjamin Herrenschmidt switch(pmac_i2c_get_type(bus)) { 417a28d3af2SBenjamin Herrenschmidt case pmac_i2c_bus_keywest: 418a28d3af2SBenjamin Herrenschmidt parent = of_get_parent(pmac_i2c_get_controller(bus)); 419a28d3af2SBenjamin Herrenschmidt if (parent == NULL) 420a28d3af2SBenjamin Herrenschmidt return -EINVAL; 421a28d3af2SBenjamin Herrenschmidt basename = parent->name; 422a28d3af2SBenjamin Herrenschmidt break; 423a28d3af2SBenjamin Herrenschmidt case pmac_i2c_bus_pmu: 424a28d3af2SBenjamin Herrenschmidt basename = "pmu"; 425a28d3af2SBenjamin Herrenschmidt break; 426a28d3af2SBenjamin Herrenschmidt case pmac_i2c_bus_smu: 427a28d3af2SBenjamin Herrenschmidt /* This is not what we used to do but I'm fixing drivers at 428a28d3af2SBenjamin Herrenschmidt * the same time as this change 429a28d3af2SBenjamin Herrenschmidt */ 430a28d3af2SBenjamin Herrenschmidt basename = "smu"; 431a28d3af2SBenjamin Herrenschmidt break; 432a28d3af2SBenjamin Herrenschmidt default: 433a28d3af2SBenjamin Herrenschmidt return -EINVAL; 434a28d3af2SBenjamin Herrenschmidt } 435bc6286e5SJean Delvare snprintf(adapter->name, sizeof(adapter->name), "%s %d", basename, 436bc6286e5SJean Delvare pmac_i2c_get_channel(bus)); 437a28d3af2SBenjamin Herrenschmidt of_node_put(parent); 438a28d3af2SBenjamin Herrenschmidt 4399f2545c1SBenjamin Herrenschmidt platform_set_drvdata(dev, adapter); 440a28d3af2SBenjamin Herrenschmidt adapter->algo = &i2c_powermac_algorithm; 441a28d3af2SBenjamin Herrenschmidt i2c_set_adapdata(adapter, bus); 4429f2545c1SBenjamin Herrenschmidt adapter->dev.parent = &dev->dev; 44381e5d864SBenjamin Herrenschmidt adapter->dev.of_node = dev->dev.of_node; 444a28d3af2SBenjamin Herrenschmidt rc = i2c_add_adapter(adapter); 445a28d3af2SBenjamin Herrenschmidt if (rc) { 446a28d3af2SBenjamin Herrenschmidt printk(KERN_ERR "i2c-powermac: Adapter %s registration " 447bc6286e5SJean Delvare "failed\n", adapter->name); 4486dfa5ca3SJean Delvare memset(adapter, 0, sizeof(*adapter)); 449*874e955bSWolfram Sang return rc; 450a28d3af2SBenjamin Herrenschmidt } 451a28d3af2SBenjamin Herrenschmidt 452bc6286e5SJean Delvare printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name); 453810ad7b6SJean Delvare 45481e5d864SBenjamin Herrenschmidt /* Cannot use of_i2c_register_devices() due to Apple device-tree 45581e5d864SBenjamin Herrenschmidt * funkyness 45681e5d864SBenjamin Herrenschmidt */ 45781e5d864SBenjamin Herrenschmidt i2c_powermac_register_devices(adapter, bus); 458810ad7b6SJean Delvare 459*874e955bSWolfram Sang return 0; 460a28d3af2SBenjamin Herrenschmidt } 461a28d3af2SBenjamin Herrenschmidt 4629f2545c1SBenjamin Herrenschmidt static struct platform_driver i2c_powermac_driver = { 4639f2545c1SBenjamin Herrenschmidt .probe = i2c_powermac_probe, 4640b255e92SBill Pemberton .remove = i2c_powermac_remove, 4659f2545c1SBenjamin Herrenschmidt .driver = { 466a28d3af2SBenjamin Herrenschmidt .name = "i2c-powermac", 467a28d3af2SBenjamin Herrenschmidt .bus = &platform_bus_type, 4689f2545c1SBenjamin Herrenschmidt }, 469a28d3af2SBenjamin Herrenschmidt }; 470a28d3af2SBenjamin Herrenschmidt 471a3664b51SAxel Lin module_platform_driver(i2c_powermac_driver); 472a28d3af2SBenjamin Herrenschmidt 473a3664b51SAxel Lin MODULE_ALIAS("platform:i2c-powermac"); 474