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); 111*d7d838a6SJean Delvare if (rc) { 112*d7d838a6SJean Delvare dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc); 11302864d58SJean Delvare return rc; 114*d7d838a6SJean Delvare } 11502864d58SJean Delvare 11602864d58SJean Delvare rc = pmac_i2c_setmode(bus, mode); 117*d7d838a6SJean Delvare if (rc) { 118*d7d838a6SJean Delvare dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n", 119*d7d838a6SJean Delvare mode, rc); 12002864d58SJean Delvare goto bail; 121*d7d838a6SJean Delvare } 12202864d58SJean Delvare 12302864d58SJean Delvare rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len); 124*d7d838a6SJean Delvare if (rc) { 125*d7d838a6SJean Delvare dev_err(&adap->dev, 126*d7d838a6SJean Delvare "I2C transfer at 0x%02x failed, size %d, err %d\n", 127*d7d838a6SJean Delvare addrdir >> 1, size, rc); 12802864d58SJean Delvare goto bail; 129*d7d838a6SJean Delvare } 13002864d58SJean Delvare 13102864d58SJean Delvare if (size == I2C_SMBUS_WORD_DATA && read) { 13202864d58SJean Delvare data->word = ((u16)local[1]) << 8; 13302864d58SJean Delvare data->word |= local[0]; 13402864d58SJean Delvare } 13502864d58SJean Delvare 136a28d3af2SBenjamin Herrenschmidt bail: 137a28d3af2SBenjamin Herrenschmidt pmac_i2c_close(bus); 138a28d3af2SBenjamin Herrenschmidt return rc; 139a28d3af2SBenjamin Herrenschmidt } 140a28d3af2SBenjamin Herrenschmidt 141a28d3af2SBenjamin Herrenschmidt /* 142a28d3af2SBenjamin Herrenschmidt * Generic i2c master transfer entrypoint. This driver only support single 143a28d3af2SBenjamin Herrenschmidt * messages (for "lame i2c" transfers). Anything else should use the smbus 144a28d3af2SBenjamin Herrenschmidt * entry point 145a28d3af2SBenjamin Herrenschmidt */ 146a28d3af2SBenjamin Herrenschmidt static int i2c_powermac_master_xfer( struct i2c_adapter *adap, 147a28d3af2SBenjamin Herrenschmidt struct i2c_msg *msgs, 148a28d3af2SBenjamin Herrenschmidt int num) 149a28d3af2SBenjamin Herrenschmidt { 150a28d3af2SBenjamin Herrenschmidt struct pmac_i2c_bus *bus = i2c_get_adapdata(adap); 151a28d3af2SBenjamin Herrenschmidt int rc = 0; 152a28d3af2SBenjamin Herrenschmidt int read; 153a28d3af2SBenjamin Herrenschmidt int addrdir; 154a28d3af2SBenjamin Herrenschmidt 1556f7e549fSJean Delvare if (num != 1) { 1566f7e549fSJean Delvare dev_err(&adap->dev, 1576f7e549fSJean Delvare "Multi-message I2C transactions not supported\n"); 1586f7e549fSJean Delvare return -EOPNOTSUPP; 1596f7e549fSJean Delvare } 1606f7e549fSJean Delvare 161a28d3af2SBenjamin Herrenschmidt if (msgs->flags & I2C_M_TEN) 162a28d3af2SBenjamin Herrenschmidt return -EINVAL; 163a28d3af2SBenjamin Herrenschmidt read = (msgs->flags & I2C_M_RD) != 0; 164a28d3af2SBenjamin Herrenschmidt addrdir = (msgs->addr << 1) | read; 165a28d3af2SBenjamin Herrenschmidt if (msgs->flags & I2C_M_REV_DIR_ADDR) 166a28d3af2SBenjamin Herrenschmidt addrdir ^= 1; 167a28d3af2SBenjamin Herrenschmidt 168a28d3af2SBenjamin Herrenschmidt rc = pmac_i2c_open(bus, 0); 169*d7d838a6SJean Delvare if (rc) { 170*d7d838a6SJean Delvare dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc); 171a28d3af2SBenjamin Herrenschmidt return rc; 172*d7d838a6SJean Delvare } 173a28d3af2SBenjamin Herrenschmidt rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); 174*d7d838a6SJean Delvare if (rc) { 175*d7d838a6SJean Delvare dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n", 176*d7d838a6SJean Delvare pmac_i2c_mode_std, rc); 177a28d3af2SBenjamin Herrenschmidt goto bail; 178*d7d838a6SJean Delvare } 179a28d3af2SBenjamin Herrenschmidt rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len); 180*d7d838a6SJean Delvare if (rc < 0) 181*d7d838a6SJean Delvare dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n", 182*d7d838a6SJean Delvare addrdir & 1 ? "read from" : "write to", addrdir >> 1, 183*d7d838a6SJean Delvare rc); 184a28d3af2SBenjamin Herrenschmidt bail: 185a28d3af2SBenjamin Herrenschmidt pmac_i2c_close(bus); 1868ced8eeeSJean Delvare return rc < 0 ? rc : 1; 187a28d3af2SBenjamin Herrenschmidt } 188a28d3af2SBenjamin Herrenschmidt 189a28d3af2SBenjamin Herrenschmidt static u32 i2c_powermac_func(struct i2c_adapter * adapter) 190a28d3af2SBenjamin Herrenschmidt { 191a28d3af2SBenjamin Herrenschmidt return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | 192a28d3af2SBenjamin Herrenschmidt I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | 193a28d3af2SBenjamin Herrenschmidt I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_I2C; 194a28d3af2SBenjamin Herrenschmidt } 195a28d3af2SBenjamin Herrenschmidt 196a28d3af2SBenjamin Herrenschmidt /* For now, we only handle smbus */ 1978f9082c5SJean Delvare static const struct i2c_algorithm i2c_powermac_algorithm = { 198a28d3af2SBenjamin Herrenschmidt .smbus_xfer = i2c_powermac_smbus_xfer, 199a28d3af2SBenjamin Herrenschmidt .master_xfer = i2c_powermac_master_xfer, 200a28d3af2SBenjamin Herrenschmidt .functionality = i2c_powermac_func, 201a28d3af2SBenjamin Herrenschmidt }; 202a28d3af2SBenjamin Herrenschmidt 203a28d3af2SBenjamin Herrenschmidt 2044ebb52d3SUwe Kleine-Koenig static int __devexit i2c_powermac_remove(struct platform_device *dev) 205a28d3af2SBenjamin Herrenschmidt { 2069f2545c1SBenjamin Herrenschmidt struct i2c_adapter *adapter = platform_get_drvdata(dev); 207a28d3af2SBenjamin Herrenschmidt struct pmac_i2c_bus *bus = i2c_get_adapdata(adapter); 208a28d3af2SBenjamin Herrenschmidt int rc; 209a28d3af2SBenjamin Herrenschmidt 210a28d3af2SBenjamin Herrenschmidt rc = i2c_del_adapter(adapter); 211a28d3af2SBenjamin Herrenschmidt pmac_i2c_detach_adapter(bus, adapter); 212a28d3af2SBenjamin Herrenschmidt i2c_set_adapdata(adapter, NULL); 213a28d3af2SBenjamin Herrenschmidt /* We aren't that prepared to deal with this... */ 214a28d3af2SBenjamin Herrenschmidt if (rc) 215154d22b0SFrank Seidel printk(KERN_WARNING 216154d22b0SFrank Seidel "i2c-powermac.c: Failed to remove bus %s !\n", 217a28d3af2SBenjamin Herrenschmidt adapter->name); 2189f2545c1SBenjamin Herrenschmidt platform_set_drvdata(dev, NULL); 219a28d3af2SBenjamin Herrenschmidt kfree(adapter); 220a28d3af2SBenjamin Herrenschmidt 221a28d3af2SBenjamin Herrenschmidt return 0; 222a28d3af2SBenjamin Herrenschmidt } 223a28d3af2SBenjamin Herrenschmidt 224a28d3af2SBenjamin Herrenschmidt 2254ebb52d3SUwe Kleine-Koenig static int __devinit i2c_powermac_probe(struct platform_device *dev) 226a28d3af2SBenjamin Herrenschmidt { 2279f2545c1SBenjamin Herrenschmidt struct pmac_i2c_bus *bus = dev->dev.platform_data; 228a28d3af2SBenjamin Herrenschmidt struct device_node *parent = NULL; 229a28d3af2SBenjamin Herrenschmidt struct i2c_adapter *adapter; 230018a3d1dSJeremy Kerr char name[32]; 231018a3d1dSJeremy Kerr const char *basename; 232a28d3af2SBenjamin Herrenschmidt int rc; 233a28d3af2SBenjamin Herrenschmidt 234a28d3af2SBenjamin Herrenschmidt if (bus == NULL) 235a28d3af2SBenjamin Herrenschmidt return -EINVAL; 236a28d3af2SBenjamin Herrenschmidt 237a28d3af2SBenjamin Herrenschmidt /* Ok, now we need to make up a name for the interface that will 238a28d3af2SBenjamin Herrenschmidt * match what we used to do in the past, that is basically the 239a28d3af2SBenjamin Herrenschmidt * controller's parent device node for keywest. PMU didn't have a 240a28d3af2SBenjamin Herrenschmidt * naming convention and SMU has a different one 241a28d3af2SBenjamin Herrenschmidt */ 242a28d3af2SBenjamin Herrenschmidt switch(pmac_i2c_get_type(bus)) { 243a28d3af2SBenjamin Herrenschmidt case pmac_i2c_bus_keywest: 244a28d3af2SBenjamin Herrenschmidt parent = of_get_parent(pmac_i2c_get_controller(bus)); 245a28d3af2SBenjamin Herrenschmidt if (parent == NULL) 246a28d3af2SBenjamin Herrenschmidt return -EINVAL; 247a28d3af2SBenjamin Herrenschmidt basename = parent->name; 248a28d3af2SBenjamin Herrenschmidt break; 249a28d3af2SBenjamin Herrenschmidt case pmac_i2c_bus_pmu: 250a28d3af2SBenjamin Herrenschmidt basename = "pmu"; 251a28d3af2SBenjamin Herrenschmidt break; 252a28d3af2SBenjamin Herrenschmidt case pmac_i2c_bus_smu: 253a28d3af2SBenjamin Herrenschmidt /* This is not what we used to do but I'm fixing drivers at 254a28d3af2SBenjamin Herrenschmidt * the same time as this change 255a28d3af2SBenjamin Herrenschmidt */ 256a28d3af2SBenjamin Herrenschmidt basename = "smu"; 257a28d3af2SBenjamin Herrenschmidt break; 258a28d3af2SBenjamin Herrenschmidt default: 259a28d3af2SBenjamin Herrenschmidt return -EINVAL; 260a28d3af2SBenjamin Herrenschmidt } 261a28d3af2SBenjamin Herrenschmidt snprintf(name, 32, "%s %d", basename, pmac_i2c_get_channel(bus)); 262a28d3af2SBenjamin Herrenschmidt of_node_put(parent); 263a28d3af2SBenjamin Herrenschmidt 264a28d3af2SBenjamin Herrenschmidt adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); 265a28d3af2SBenjamin Herrenschmidt if (adapter == NULL) { 266a28d3af2SBenjamin Herrenschmidt printk(KERN_ERR "i2c-powermac: can't allocate inteface !\n"); 267a28d3af2SBenjamin Herrenschmidt return -ENOMEM; 268a28d3af2SBenjamin Herrenschmidt } 2699f2545c1SBenjamin Herrenschmidt platform_set_drvdata(dev, adapter); 270a28d3af2SBenjamin Herrenschmidt strcpy(adapter->name, name); 271a28d3af2SBenjamin Herrenschmidt adapter->algo = &i2c_powermac_algorithm; 272a28d3af2SBenjamin Herrenschmidt i2c_set_adapdata(adapter, bus); 2739f2545c1SBenjamin Herrenschmidt adapter->dev.parent = &dev->dev; 274a28d3af2SBenjamin Herrenschmidt pmac_i2c_attach_adapter(bus, adapter); 275a28d3af2SBenjamin Herrenschmidt rc = i2c_add_adapter(adapter); 276a28d3af2SBenjamin Herrenschmidt if (rc) { 277a28d3af2SBenjamin Herrenschmidt printk(KERN_ERR "i2c-powermac: Adapter %s registration " 278a28d3af2SBenjamin Herrenschmidt "failed\n", name); 279a28d3af2SBenjamin Herrenschmidt i2c_set_adapdata(adapter, NULL); 280a28d3af2SBenjamin Herrenschmidt pmac_i2c_detach_adapter(bus, adapter); 281a28d3af2SBenjamin Herrenschmidt } 282a28d3af2SBenjamin Herrenschmidt 283a28d3af2SBenjamin Herrenschmidt printk(KERN_INFO "PowerMac i2c bus %s registered\n", name); 284810ad7b6SJean Delvare 285810ad7b6SJean Delvare if (!strncmp(basename, "uni-n", 5)) { 286810ad7b6SJean Delvare struct device_node *np; 287810ad7b6SJean Delvare const u32 *prop; 288810ad7b6SJean Delvare struct i2c_board_info info; 289810ad7b6SJean Delvare 290810ad7b6SJean Delvare /* Instantiate I2C motion sensor if present */ 291810ad7b6SJean Delvare np = of_find_node_by_name(NULL, "accelerometer"); 292810ad7b6SJean Delvare if (np && of_device_is_compatible(np, "AAPL,accelerometer_1") && 293810ad7b6SJean Delvare (prop = of_get_property(np, "reg", NULL))) { 294810ad7b6SJean Delvare int i2c_bus; 295810ad7b6SJean Delvare const char *tmp_bus; 296810ad7b6SJean Delvare 297810ad7b6SJean Delvare /* look for bus either using "reg" or by path */ 298810ad7b6SJean Delvare tmp_bus = strstr(np->full_name, "/i2c-bus@"); 299810ad7b6SJean Delvare if (tmp_bus) 300810ad7b6SJean Delvare i2c_bus = *(tmp_bus + 9) - '0'; 301810ad7b6SJean Delvare else 302810ad7b6SJean Delvare i2c_bus = ((*prop) >> 8) & 0x0f; 303810ad7b6SJean Delvare 304810ad7b6SJean Delvare if (pmac_i2c_get_channel(bus) == i2c_bus) { 305810ad7b6SJean Delvare memset(&info, 0, sizeof(struct i2c_board_info)); 306810ad7b6SJean Delvare info.addr = ((*prop) & 0xff) >> 1; 307810ad7b6SJean Delvare strlcpy(info.type, "ams", I2C_NAME_SIZE); 308810ad7b6SJean Delvare i2c_new_device(adapter, &info); 309810ad7b6SJean Delvare } 310810ad7b6SJean Delvare } 311810ad7b6SJean Delvare } 312810ad7b6SJean Delvare 313a28d3af2SBenjamin Herrenschmidt return rc; 314a28d3af2SBenjamin Herrenschmidt } 315a28d3af2SBenjamin Herrenschmidt 316a28d3af2SBenjamin Herrenschmidt 317add8eda7SKay Sievers /* work with hotplug and coldplug */ 318add8eda7SKay Sievers MODULE_ALIAS("platform:i2c-powermac"); 319add8eda7SKay Sievers 3209f2545c1SBenjamin Herrenschmidt static struct platform_driver i2c_powermac_driver = { 3219f2545c1SBenjamin Herrenschmidt .probe = i2c_powermac_probe, 3229f2545c1SBenjamin Herrenschmidt .remove = __devexit_p(i2c_powermac_remove), 3239f2545c1SBenjamin Herrenschmidt .driver = { 324a28d3af2SBenjamin Herrenschmidt .name = "i2c-powermac", 325a28d3af2SBenjamin Herrenschmidt .bus = &platform_bus_type, 3269f2545c1SBenjamin Herrenschmidt }, 327a28d3af2SBenjamin Herrenschmidt }; 328a28d3af2SBenjamin Herrenschmidt 329a28d3af2SBenjamin Herrenschmidt static int __init i2c_powermac_init(void) 330a28d3af2SBenjamin Herrenschmidt { 3319f2545c1SBenjamin Herrenschmidt platform_driver_register(&i2c_powermac_driver); 332a28d3af2SBenjamin Herrenschmidt return 0; 333a28d3af2SBenjamin Herrenschmidt } 334a28d3af2SBenjamin Herrenschmidt 335a28d3af2SBenjamin Herrenschmidt 336a28d3af2SBenjamin Herrenschmidt static void __exit i2c_powermac_cleanup(void) 337a28d3af2SBenjamin Herrenschmidt { 3389f2545c1SBenjamin Herrenschmidt platform_driver_unregister(&i2c_powermac_driver); 339a28d3af2SBenjamin Herrenschmidt } 340a28d3af2SBenjamin Herrenschmidt 341a28d3af2SBenjamin Herrenschmidt module_init(i2c_powermac_init); 342a28d3af2SBenjamin Herrenschmidt module_exit(i2c_powermac_cleanup); 343