diff options
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r-- | drivers/i2c/busses/Kconfig | 16 | ||||
-rw-r--r-- | drivers/i2c/busses/Makefile | 3 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-ali1535.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-ali15x3.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 3 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-iop3xx.c | 6 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mv64xxx.c | 3 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-pnx.c | 4 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-powermac.c | 139 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-sis5595.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-sis630.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-stub.c | 34 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-voodoo3.c | 248 |
13 files changed, 114 insertions, 350 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index e8fe7f169e25..5f318ce29770 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -640,22 +640,6 @@ config I2C_TINY_USB This driver can also be built as a module. If so, the module will be called i2c-tiny-usb. -comment "Graphics adapter I2C/DDC channel drivers" - depends on PCI - -config I2C_VOODOO3 - tristate "Voodoo 3 (DEPRECATED)" - depends on PCI - select I2C_ALGOBIT - help - If you say yes to this option, support will be included for the - Voodoo 3 I2C interface. This driver is deprecated and you should - use the tdfxfb driver instead, which additionally provides - framebuffer support. - - This driver can also be built as a module. If so, the module - will be called i2c-voodoo3. - comment "Other I2C/SMBus bus drivers" config I2C_ACORN diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index ff937ac69f5b..302c551977bb 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -61,9 +61,6 @@ obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o -# Graphics adapter I2C/DDC channel drivers -obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o - # Other I2C/SMBus bus drivers obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index d108450df064..8de7d7b87bb0 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -138,7 +138,7 @@ static unsigned short ali1535_smba; Note the differences between kernels with the old PCI BIOS interface and newer kernels with the real PCI interface. In compat.h some things are defined to make the transition easier. */ -static int ali1535_setup(struct pci_dev *dev) +static int __devinit ali1535_setup(struct pci_dev *dev) { int retval = -ENODEV; unsigned char temp; diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index d627fceb790b..e7e3205f1286 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -131,7 +131,7 @@ MODULE_PARM_DESC(force_addr, static struct pci_driver ali15x3_driver; static unsigned short ali15x3_smba; -static int ali15x3_setup(struct pci_dev *ALI15X3_dev) +static int __devinit ali15x3_setup(struct pci_dev *ALI15X3_dev) { u16 a; unsigned char temp; diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 55edcfe5b851..df6ab553f975 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -767,6 +767,9 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id /* set up the sysfs linkage to our parent device */ i801_adapter.dev.parent = &dev->dev; + /* Retry up to 3 times on lost arbitration */ + i801_adapter.retries = 3; + snprintf(i801_adapter.name, sizeof(i801_adapter.name), "SMBus I801 adapter at %04lx", i801_smba); err = i2c_add_adapter(&i801_adapter); diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index a75c75e77b92..5901707fc66a 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -56,12 +56,6 @@ iic_cook_addr(struct i2c_msg *msg) if (msg->flags & I2C_M_RD) addr |= 1; - /* - * Read or Write? - */ - if (msg->flags & I2C_M_REV_DIR_ADDR) - addr ^= 1; - return addr; } diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index bbab0e166630..ed387ffa4730 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -338,9 +338,6 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, if (msg->flags & I2C_M_RD) dir = 1; - if (msg->flags & I2C_M_REV_DIR_ADDR) - dir ^= 1; - if (msg->flags & I2C_M_TEN) { drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir; drv_data->addr2 = (u32)msg->addr & 0xff; diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 1fca59077949..fbab6846ae64 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -650,7 +650,7 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) return 0; out_irq: - free_irq(alg_data->irq, alg_data); + free_irq(alg_data->irq, i2c_pnx->adapter); out_clock: i2c_pnx->set_clock_stop(pdev); out_unmap: @@ -669,7 +669,7 @@ static int __devexit i2c_pnx_remove(struct platform_device *pdev) struct i2c_adapter *adap = i2c_pnx->adapter; struct i2c_pnx_algo_data *alg_data = adap->algo_data; - free_irq(alg_data->irq, alg_data); + free_irq(alg_data->irq, i2c_pnx->adapter); i2c_del_adapter(adap); i2c_pnx->set_clock_stop(pdev); iounmap((void *)alg_data->ioaddr); diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 3c9d71f60187..1c440a70ec61 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -49,48 +49,38 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap, int rc = 0; int read = (read_write == I2C_SMBUS_READ); int addrdir = (addr << 1) | read; + int mode, subsize, len; + u32 subaddr; + u8 *buf; u8 local[2]; - rc = pmac_i2c_open(bus, 0); - if (rc) - return rc; + if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) { + mode = pmac_i2c_mode_std; + subsize = 0; + subaddr = 0; + } else { + mode = read ? pmac_i2c_mode_combined : pmac_i2c_mode_stdsub; + subsize = 1; + subaddr = command; + } switch (size) { case I2C_SMBUS_QUICK: - rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); - if (rc) - goto bail; - rc = pmac_i2c_xfer(bus, addrdir, 0, 0, NULL, 0); + buf = NULL; + len = 0; break; case I2C_SMBUS_BYTE: - rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); - if (rc) - goto bail; - rc = pmac_i2c_xfer(bus, addrdir, 0, 0, &data->byte, 1); - break; case I2C_SMBUS_BYTE_DATA: - rc = pmac_i2c_setmode(bus, read ? - pmac_i2c_mode_combined : - pmac_i2c_mode_stdsub); - if (rc) - goto bail; - rc = pmac_i2c_xfer(bus, addrdir, 1, command, &data->byte, 1); + buf = &data->byte; + len = 1; break; case I2C_SMBUS_WORD_DATA: - rc = pmac_i2c_setmode(bus, read ? - pmac_i2c_mode_combined : - pmac_i2c_mode_stdsub); - if (rc) - goto bail; if (!read) { local[0] = data->word & 0xff; local[1] = (data->word >> 8) & 0xff; } - rc = pmac_i2c_xfer(bus, addrdir, 1, command, local, 2); - if (rc == 0 && read) { - data->word = ((u16)local[1]) << 8; - data->word |= local[0]; - } + buf = local; + len = 2; break; /* Note that these are broken vs. the expected smbus API where @@ -105,28 +95,44 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap, * a repeat start/addr phase (but not stop in between) */ case I2C_SMBUS_BLOCK_DATA: - rc = pmac_i2c_setmode(bus, read ? - pmac_i2c_mode_combined : - pmac_i2c_mode_stdsub); - if (rc) - goto bail; - rc = pmac_i2c_xfer(bus, addrdir, 1, command, data->block, - data->block[0] + 1); - + buf = data->block; + len = data->block[0] + 1; break; case I2C_SMBUS_I2C_BLOCK_DATA: - rc = pmac_i2c_setmode(bus, read ? - pmac_i2c_mode_combined : - pmac_i2c_mode_stdsub); - if (rc) - goto bail; - rc = pmac_i2c_xfer(bus, addrdir, 1, command, - &data->block[1], data->block[0]); + buf = &data->block[1]; + len = data->block[0]; break; default: - rc = -EINVAL; + return -EINVAL; + } + + rc = pmac_i2c_open(bus, 0); + if (rc) { + dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc); + return rc; + } + + rc = pmac_i2c_setmode(bus, mode); + if (rc) { + dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n", + mode, rc); + goto bail; } + + rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len); + if (rc) { + dev_err(&adap->dev, + "I2C transfer at 0x%02x failed, size %d, err %d\n", + addrdir >> 1, size, rc); + goto bail; + } + + if (size == I2C_SMBUS_WORD_DATA && read) { + data->word = ((u16)local[1]) << 8; + data->word |= local[0]; + } + bail: pmac_i2c_close(bus); return rc; @@ -146,20 +152,33 @@ static int i2c_powermac_master_xfer( struct i2c_adapter *adap, int read; int addrdir; + if (num != 1) { + dev_err(&adap->dev, + "Multi-message I2C transactions not supported\n"); + return -EOPNOTSUPP; + } + if (msgs->flags & I2C_M_TEN) return -EINVAL; read = (msgs->flags & I2C_M_RD) != 0; addrdir = (msgs->addr << 1) | read; - if (msgs->flags & I2C_M_REV_DIR_ADDR) - addrdir ^= 1; rc = pmac_i2c_open(bus, 0); - if (rc) + if (rc) { + dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc); return rc; + } rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); - if (rc) + if (rc) { + dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n", + pmac_i2c_mode_std, rc); goto bail; + } rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len); + if (rc < 0) + dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n", + addrdir & 1 ? "read from" : "write to", addrdir >> 1, + rc); bail: pmac_i2c_close(bus); return rc < 0 ? rc : 1; @@ -183,19 +202,16 @@ static const struct i2c_algorithm i2c_powermac_algorithm = { static int __devexit i2c_powermac_remove(struct platform_device *dev) { struct i2c_adapter *adapter = platform_get_drvdata(dev); - struct pmac_i2c_bus *bus = i2c_get_adapdata(adapter); int rc; rc = i2c_del_adapter(adapter); - pmac_i2c_detach_adapter(bus, adapter); - i2c_set_adapdata(adapter, NULL); /* We aren't that prepared to deal with this... */ if (rc) printk(KERN_WARNING "i2c-powermac.c: Failed to remove bus %s !\n", adapter->name); platform_set_drvdata(dev, NULL); - kfree(adapter); + memset(adapter, 0, sizeof(*adapter)); return 0; } @@ -206,12 +222,12 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev) struct pmac_i2c_bus *bus = dev->dev.platform_data; struct device_node *parent = NULL; struct i2c_adapter *adapter; - char name[32]; const char *basename; int rc; if (bus == NULL) return -EINVAL; + adapter = pmac_i2c_get_adapter(bus); /* Ok, now we need to make up a name for the interface that will * match what we used to do in the past, that is basically the @@ -237,29 +253,22 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev) default: return -EINVAL; } - snprintf(name, 32, "%s %d", basename, pmac_i2c_get_channel(bus)); + snprintf(adapter->name, sizeof(adapter->name), "%s %d", basename, + pmac_i2c_get_channel(bus)); of_node_put(parent); - adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); - if (adapter == NULL) { - printk(KERN_ERR "i2c-powermac: can't allocate inteface !\n"); - return -ENOMEM; - } platform_set_drvdata(dev, adapter); - strcpy(adapter->name, name); adapter->algo = &i2c_powermac_algorithm; i2c_set_adapdata(adapter, bus); adapter->dev.parent = &dev->dev; - pmac_i2c_attach_adapter(bus, adapter); rc = i2c_add_adapter(adapter); if (rc) { printk(KERN_ERR "i2c-powermac: Adapter %s registration " - "failed\n", name); - i2c_set_adapdata(adapter, NULL); - pmac_i2c_detach_adapter(bus, adapter); + "failed\n", adapter->name); + memset(adapter, 0, sizeof(*adapter)); } - printk(KERN_INFO "PowerMac i2c bus %s registered\n", name); + printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name); if (!strncmp(basename, "uni-n", 5)) { struct device_node *np; diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c index 139f0c7f12a4..844569f7d8b7 100644 --- a/drivers/i2c/busses/i2c-sis5595.c +++ b/drivers/i2c/busses/i2c-sis5595.c @@ -142,7 +142,7 @@ static void sis5595_write(u8 reg, u8 data) outb(data, sis5595_base + SMB_DAT); } -static int sis5595_setup(struct pci_dev *SIS5595_dev) +static int __devinit sis5595_setup(struct pci_dev *SIS5595_dev) { u16 a; u8 val; diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 70ca41e90e58..68cff7af7013 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c @@ -389,7 +389,7 @@ static u32 sis630_func(struct i2c_adapter *adapter) I2C_FUNC_SMBUS_BLOCK_DATA; } -static int sis630_setup(struct pci_dev *sis630_dev) +static int __devinit sis630_setup(struct pci_dev *sis630_dev) { unsigned char b; struct pci_dev *dummy = NULL; diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c index 1b7b2af94036..0c770eabe85e 100644 --- a/drivers/i2c/busses/i2c-stub.c +++ b/drivers/i2c/busses/i2c-stub.c @@ -35,6 +35,10 @@ module_param_array(chip_addr, ushort, NULL, S_IRUGO); MODULE_PARM_DESC(chip_addr, "Chip addresses (up to 10, between 0x03 and 0x77)"); +static unsigned long functionality = ~0UL; +module_param(functionality, ulong, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(functionality, "Override functionality bitfield"); + struct stub_chip { u8 pointer; u16 words[256]; /* Byte operations use the LSB as per SMBus @@ -48,7 +52,7 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data * data) { s32 ret; - int i; + int i, len; struct stub_chip *chip = NULL; /* Search for the right chip */ @@ -118,6 +122,29 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, ret = 0; break; + case I2C_SMBUS_I2C_BLOCK_DATA: + len = data->block[0]; + if (read_write == I2C_SMBUS_WRITE) { + for (i = 0; i < len; i++) { + chip->words[command + i] &= 0xff00; + chip->words[command + i] |= data->block[1 + i]; + } + dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " + "wrote %d bytes at 0x%02x.\n", + addr, len, command); + } else { + for (i = 0; i < len; i++) { + data->block[1 + i] = + chip->words[command + i] & 0xff; + } + dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " + "read %d bytes at 0x%02x.\n", + addr, len, command); + } + + ret = 0; + break; + default: dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n"); ret = -EOPNOTSUPP; @@ -129,8 +156,9 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, static u32 stub_func(struct i2c_adapter *adapter) { - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA; + return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK) & functionality; } static const struct i2c_algorithm smbus_algorithm = { diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c deleted file mode 100644 index 7663d57833a0..000000000000 --- a/drivers/i2c/busses/i2c-voodoo3.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>, - Philip Edelbrock <phil@netroedge.com>, - Ralph Metzler <rjkm@thp.uni-koeln.de>, and - Mark D. Studebaker <mdsxyz123@yahoo.com> - - Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and - Simon Vogl - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* This interfaces to the I2C bus of the Voodoo3 to gain access to - the BT869 and possibly other I2C devices. */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <asm/io.h> - -/* the only registers we use */ -#define REG 0x78 -#define REG2 0x70 - -/* bit locations in the register */ -#define DDC_ENAB 0x00040000 -#define DDC_SCL_OUT 0x00080000 -#define DDC_SDA_OUT 0x00100000 -#define DDC_SCL_IN 0x00200000 -#define DDC_SDA_IN 0x00400000 -#define I2C_ENAB 0x00800000 -#define I2C_SCL_OUT 0x01000000 -#define I2C_SDA_OUT 0x02000000 -#define I2C_SCL_IN 0x04000000 -#define I2C_SDA_IN 0x08000000 - -/* initialization states */ -#define INIT2 0x2 -#define INIT3 0x4 - -/* delays */ -#define CYCLE_DELAY 10 -#define TIMEOUT (HZ / 2) - - -static void __iomem *ioaddr; - -/* The voo GPIO registers don't have individual masks for each bit - so we always have to read before writing. */ - -static void bit_vooi2c_setscl(void *data, int val) -{ - unsigned int r; - r = readl(ioaddr + REG); - if (val) - r |= I2C_SCL_OUT; - else - r &= ~I2C_SCL_OUT; - writel(r, ioaddr + REG); - readl(ioaddr + REG); /* flush posted write */ -} - -static void bit_vooi2c_setsda(void *data, int val) -{ - unsigned int r; - r = readl(ioaddr + REG); - if (val) - r |= I2C_SDA_OUT; - else - r &= ~I2C_SDA_OUT; - writel(r, ioaddr + REG); - readl(ioaddr + REG); /* flush posted write */ -} - -/* The GPIO pins are open drain, so the pins always remain outputs. - We rely on the i2c-algo-bit routines to set the pins high before - reading the input from other chips. */ - -static int bit_vooi2c_getscl(void *data) -{ - return (0 != (readl(ioaddr + REG) & I2C_SCL_IN)); -} - -static int bit_vooi2c_getsda(void *data) -{ - return (0 != (readl(ioaddr + REG) & I2C_SDA_IN)); -} - -static void bit_vooddc_setscl(void *data, int val) -{ - unsigned int r; - r = readl(ioaddr + REG); - if (val) - r |= DDC_SCL_OUT; - else - r &= ~DDC_SCL_OUT; - writel(r, ioaddr + REG); - readl(ioaddr + REG); /* flush posted write */ -} - -static void bit_vooddc_setsda(void *data, int val) -{ - unsigned int r; - r = readl(ioaddr + REG); - if (val) - r |= DDC_SDA_OUT; - else - r &= ~DDC_SDA_OUT; - writel(r, ioaddr + REG); - readl(ioaddr + REG); /* flush posted write */ -} - -static int bit_vooddc_getscl(void *data) -{ - return (0 != (readl(ioaddr + REG) & DDC_SCL_IN)); -} - -static int bit_vooddc_getsda(void *data) -{ - return (0 != (readl(ioaddr + REG) & DDC_SDA_IN)); -} - -static int config_v3(struct pci_dev *dev) -{ - unsigned long cadr; - - /* map Voodoo3 memory */ - cadr = dev->resource[0].start; - cadr &= PCI_BASE_ADDRESS_MEM_MASK; - ioaddr = ioremap_nocache(cadr, 0x1000); - if (ioaddr) { - writel(0x8160, ioaddr + REG2); - writel(0xcffc0020, ioaddr + REG); - dev_info(&dev->dev, "Using Banshee/Voodoo3 I2C device at %p\n", ioaddr); - return 0; - } - return -ENODEV; -} - -static struct i2c_algo_bit_data voo_i2c_bit_data = { - .setsda = bit_vooi2c_setsda, - .setscl = bit_vooi2c_setscl, - .getsda = bit_vooi2c_getsda, - .getscl = bit_vooi2c_getscl, - .udelay = CYCLE_DELAY, - .timeout = TIMEOUT -}; - -static struct i2c_adapter voodoo3_i2c_adapter = { - .owner = THIS_MODULE, - .name = "I2C Voodoo3/Banshee adapter", - .algo_data = &voo_i2c_bit_data, -}; - -static struct i2c_algo_bit_data voo_ddc_bit_data = { - .setsda = bit_vooddc_setsda, - .setscl = bit_vooddc_setscl, - .getsda = bit_vooddc_getsda, - .getscl = bit_vooddc_getscl, - .udelay = CYCLE_DELAY, - .timeout = TIMEOUT -}; - -static struct i2c_adapter voodoo3_ddc_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_DDC, - .name = "DDC Voodoo3/Banshee adapter", - .algo_data = &voo_ddc_bit_data, -}; - -static struct pci_device_id voodoo3_ids[] __devinitdata = { - { PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3) }, - { PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE) }, - { 0, } -}; - -MODULE_DEVICE_TABLE (pci, voodoo3_ids); - -static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int retval; - - retval = config_v3(dev); - if (retval) - return retval; - - /* set up the sysfs linkage to our parent device */ - voodoo3_i2c_adapter.dev.parent = &dev->dev; - voodoo3_ddc_adapter.dev.parent = &dev->dev; - - retval = i2c_bit_add_bus(&voodoo3_i2c_adapter); - if (retval) - return retval; - retval = i2c_bit_add_bus(&voodoo3_ddc_adapter); - if (retval) - i2c_del_adapter(&voodoo3_i2c_adapter); - return retval; -} - -static void __devexit voodoo3_remove(struct pci_dev *dev) -{ - i2c_del_adapter(&voodoo3_i2c_adapter); - i2c_del_adapter(&voodoo3_ddc_adapter); - iounmap(ioaddr); -} - -static struct pci_driver voodoo3_driver = { - .name = "voodoo3_smbus", - .id_table = voodoo3_ids, - .probe = voodoo3_probe, - .remove = __devexit_p(voodoo3_remove), -}; - -static int __init i2c_voodoo3_init(void) -{ - return pci_register_driver(&voodoo3_driver); -} - -static void __exit i2c_voodoo3_exit(void) -{ - pci_unregister_driver(&voodoo3_driver); -} - - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " - "Philip Edelbrock <phil@netroedge.com>, " - "Ralph Metzler <rjkm@thp.uni-koeln.de>, " - "and Mark D. Studebaker <mdsxyz123@yahoo.com>"); -MODULE_DESCRIPTION("Voodoo3 I2C/SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_voodoo3_init); -module_exit(i2c_voodoo3_exit); |