diff options
author | Greg Kroah-Hartman <greg@kroah.com> | 2005-01-09 19:36:46 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <greg@kroah.com> | 2005-01-09 19:36:46 -0800 |
commit | 6763ca6cd73f6f70eac2ebd12ba52ea872e133cc (patch) | |
tree | 1d21f3326544dd01516aba2f4b28a5df8604ce84 /drivers | |
parent | cf4a33ef7ef44ef97446527317254783d5f448de (diff) | |
parent | 1962e5c80990f9f766973676655b7c8bea091df4 (diff) | |
download | history-6763ca6cd73f6f70eac2ebd12ba52ea872e133cc.tar.gz |
Merge kroah.com:/home/greg/linux/BK/bleed-2.6
into kroah.com:/home/greg/linux/BK/i2c-2.6
Diffstat (limited to 'drivers')
41 files changed, 1376 insertions, 596 deletions
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig index cf9832bdc7463a..30408015d231fa 100644 --- a/drivers/i2c/algos/Kconfig +++ b/drivers/i2c/algos/Kconfig @@ -53,5 +53,18 @@ config I2C_ALGO8XX tristate "MPC8xx CPM I2C interface" depends on 8xx && I2C +config I2C_ALGO_SIBYTE + tristate "SiByte SMBus interface" + depends on SIBYTE_SB1xxx_SOC && I2C + help + Supports the SiByte SOC on-chip I2C interfaces (2 channels). + +config I2C_ALGO_SGI + tristate "I2C SGI interfaces" + depends on I2C && (SGI_IP22 || SGI_IP32 || X86_VISWS) + help + Supports the SGI interfaces like the ones found on SGI Indy VINO + or SGI O2 MACE. + endmenu diff --git a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile index 3545644be0f6a2..867fe1f67401c3 100644 --- a/drivers/i2c/algos/Makefile +++ b/drivers/i2c/algos/Makefile @@ -6,6 +6,8 @@ obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o obj-$(CONFIG_I2C_ALGOITE) += i2c-algo-ite.o +obj-$(CONFIG_I2C_ALGO_SIBYTE) += i2c-algo-sibyte.o +obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o ifeq ($(CONFIG_I2C_DEBUG_ALGO),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index 4ea4c7928b8e1b..fb5b732238ed81 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -511,8 +511,8 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, static u32 bit_func(struct i2c_adapter *adap) { - return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | - I2C_FUNC_PROTOCOL_MANGLING; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; } diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index aaad68602394d9..a8724ac9282d77 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -189,7 +189,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, state = pca_status(adap); if ( state != 0xF8 ) { - printk(KERN_ERR DRIVER ": bus is not idle. status is %#04x\n", state ); + dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state ); /* FIXME: what to do. Force stop ? */ return -EREMOTEIO; } @@ -328,7 +328,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, static u32 pca_func(struct i2c_adapter *adap) { - return I2C_FUNC_SMBUS_EMUL; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } static int pca_init(struct i2c_algo_pca_data *adap) diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index 6dc807abc157de..fbbe1d2bdcc422 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c @@ -414,8 +414,8 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap, static u32 pcf_func(struct i2c_adapter *adap) { - return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | - I2C_FUNC_PROTOCOL_MANGLING; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; } /* -----exported algorithm data: ------------------------------------- */ diff --git a/drivers/i2c/algos/i2c-algo-sgi.c b/drivers/i2c/algos/i2c-algo-sgi.c new file mode 100644 index 00000000000000..b4e0a065b78b27 --- /dev/null +++ b/drivers/i2c/algos/i2c-algo-sgi.c @@ -0,0 +1,189 @@ +/* + * i2c-algo-sgi.c: i2c driver algorithms for SGI adapters. + * + * This file is subject to the terms and conditions of the GNU General Public + * License version 2 as published by the Free Software Foundation. + * + * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/delay.h> + +#include <linux/i2c.h> +#include <linux/i2c-algo-sgi.h> + + +#define SGI_I2C_FORCE_IDLE (0 << 0) +#define SGI_I2C_NOT_IDLE (1 << 0) +#define SGI_I2C_WRITE (0 << 1) +#define SGI_I2C_READ (1 << 1) +#define SGI_I2C_RELEASE_BUS (0 << 2) +#define SGI_I2C_HOLD_BUS (1 << 2) +#define SGI_I2C_XFER_DONE (0 << 4) +#define SGI_I2C_XFER_BUSY (1 << 4) +#define SGI_I2C_ACK (0 << 5) +#define SGI_I2C_NACK (1 << 5) +#define SGI_I2C_BUS_OK (0 << 7) +#define SGI_I2C_BUS_ERR (1 << 7) + +#define get_control() adap->getctrl(adap->data) +#define set_control(val) adap->setctrl(adap->data, val) +#define read_data() adap->rdata(adap->data) +#define write_data(val) adap->wdata(adap->data, val) + + +static int wait_xfer_done(struct i2c_algo_sgi_data *adap) +{ + int i; + + for (i = 0; i < adap->xfer_timeout; i++) { + if ((get_control() & SGI_I2C_XFER_BUSY) == 0) + return 0; + udelay(1); + } + + return -ETIMEDOUT; +} + +static int wait_ack(struct i2c_algo_sgi_data *adap) +{ + int i; + + if (wait_xfer_done(adap)) + return -ETIMEDOUT; + for (i = 0; i < adap->ack_timeout; i++) { + if ((get_control() & SGI_I2C_NACK) == 0) + return 0; + udelay(1); + } + + return -ETIMEDOUT; +} + +static int force_idle(struct i2c_algo_sgi_data *adap) +{ + int i; + + set_control(SGI_I2C_FORCE_IDLE); + for (i = 0; i < adap->xfer_timeout; i++) { + if ((get_control() & SGI_I2C_NOT_IDLE) == 0) + goto out; + udelay(1); + } + return -ETIMEDOUT; +out: + if (get_control() & SGI_I2C_BUS_ERR) + return -EIO; + return 0; +} + +static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr, + int rd) +{ + if (rd) + set_control(SGI_I2C_NOT_IDLE); + /* Check if bus is idle, eventually force it to do so */ + if (get_control() & SGI_I2C_NOT_IDLE) + if (force_idle(adap)) + return -EIO; + /* Write out the i2c chip address and specify operation */ + set_control(SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE); + if (rd) + addr |= 1; + write_data(addr); + if (wait_ack(adap)) + return -EIO; + return 0; +} + +static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf, + unsigned int len) +{ + int i; + + set_control(SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE); + for (i = 0; i < len; i++) { + if (wait_xfer_done(adap)) + return -EIO; + buf[i] = read_data(); + } + set_control(SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE); + + return 0; + +} + +static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf, + unsigned int len) +{ + int i; + + /* We are already in write state */ + for (i = 0; i < len; i++) { + write_data(buf[i]); + if (wait_ack(adap)) + return -EIO; + } + return 0; +} + +static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], + int num) +{ + struct i2c_algo_sgi_data *adap = i2c_adap->algo_data; + struct i2c_msg *p; + int i, err = 0; + + for (i = 0; !err && i < num; i++) { + p = &msgs[i]; + err = do_address(adap, p->addr, p->flags & I2C_M_RD); + if (err || !p->len) + continue; + if (p->flags & I2C_M_RD) + err = i2c_read(adap, p->buf, p->len); + else + err = i2c_write(adap, p->buf, p->len); + } + + return err; +} + +static u32 sgi_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm sgi_algo = { + .name = "SGI algorithm", + .id = I2C_ALGO_SGI, + .master_xfer = sgi_xfer, + .functionality = sgi_func, +}; + +/* + * registering functions to load algorithms at runtime + */ +int i2c_sgi_add_bus(struct i2c_adapter *adap) +{ + adap->id |= sgi_algo.id; + adap->algo = &sgi_algo; + + return i2c_add_adapter(adap); +} + + +int i2c_sgi_del_bus(struct i2c_adapter *adap) +{ + return i2c_del_adapter(adap); +} + +EXPORT_SYMBOL(i2c_sgi_add_bus); +EXPORT_SYMBOL(i2c_sgi_del_bus); + +MODULE_AUTHOR("Ladislav Michl <ladis@linux-mips.org>"); +MODULE_DESCRIPTION("I2C-Bus SGI algorithm"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c new file mode 100644 index 00000000000000..e4d41caf0b26bc --- /dev/null +++ b/drivers/i2c/algos/i2c-algo-sibyte.c @@ -0,0 +1,231 @@ +/* ------------------------------------------------------------------------- */ +/* i2c-algo-sibyte.c i2c driver algorithms for bit-shift adapters */ +/* ------------------------------------------------------------------------- */ +/* Copyright (C) 2001,2002,2003 Broadcom Corporation + Copyright (C) 1995-2000 Simon G. 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. */ +/* ------------------------------------------------------------------------- */ + +/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even + Frodo Looijaard <frodol@dds.nl>. */ + +/* Ported for SiByte SOCs by Broadcom Corporation. */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> + +#include <asm/io.h> +#include <asm/sibyte/sb1250_regs.h> +#include <asm/sibyte/sb1250_smbus.h> + +#include <linux/i2c.h> +#include <linux/i2c-algo-sibyte.h> + +/* ----- global defines ----------------------------------------------- */ +#define SMB_CSR(a,r) ((long)(a->reg_base + r)) + +/* ----- global variables --------------------------------------------- */ + +/* module parameters: + */ +static int bit_scan=0; /* have a look at what's hanging 'round */ + + +static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data * data) +{ + struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data; + int data_bytes = 0; + int error; + + while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY) + ; + + switch (size) { + case I2C_SMBUS_QUICK: + csr_out32((V_SMB_ADDR(addr) | (read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) | + V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START)); + break; + case I2C_SMBUS_BYTE: + if (read_write == I2C_SMBUS_READ) { + csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE), + SMB_CSR(adap, R_SMB_START)); + data_bytes = 1; + } else { + csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD)); + csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE), + SMB_CSR(adap, R_SMB_START)); + } + break; + case I2C_SMBUS_BYTE_DATA: + csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD)); + if (read_write == I2C_SMBUS_READ) { + csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE), + SMB_CSR(adap, R_SMB_START)); + data_bytes = 1; + } else { + csr_out32(V_SMB_LB(data->byte), SMB_CSR(adap, R_SMB_DATA)); + csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE), + SMB_CSR(adap, R_SMB_START)); + } + break; + case I2C_SMBUS_WORD_DATA: + csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD)); + if (read_write == I2C_SMBUS_READ) { + csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE), + SMB_CSR(adap, R_SMB_START)); + data_bytes = 2; + } else { + csr_out32(V_SMB_LB(data->word & 0xff), SMB_CSR(adap, R_SMB_DATA)); + csr_out32(V_SMB_MB(data->word >> 8), SMB_CSR(adap, R_SMB_DATA)); + csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE), + SMB_CSR(adap, R_SMB_START)); + } + break; + default: + return -1; /* XXXKW better error code? */ + } + + while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY) + ; + + error = csr_in32(SMB_CSR(adap, R_SMB_STATUS)); + if (error & M_SMB_ERROR) { + /* Clear error bit by writing a 1 */ + csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS)); + return -1; /* XXXKW better error code? */ + } + + if (data_bytes == 1) + data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff; + if (data_bytes == 2) + data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff; + + return 0; +} + +static int algo_control(struct i2c_adapter *adapter, + unsigned int cmd, unsigned long arg) +{ + return 0; +} + +static u32 bit_func(struct i2c_adapter *adap) +{ + return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA); +} + + +/* -----exported algorithm data: ------------------------------------- */ + +static struct i2c_algorithm i2c_sibyte_algo = { + "SiByte algorithm", + I2C_ALGO_SIBYTE, + NULL, /* master_xfer */ + smbus_xfer, /* smbus_xfer */ + NULL, /* slave_xmit */ + NULL, /* slave_recv */ + algo_control, /* ioctl */ + bit_func, /* functionality */ +}; + +/* + * registering functions to load algorithms at runtime + */ +int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed) +{ + int i; + struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data; + + /* register new adapter to i2c module... */ + + i2c_adap->id |= i2c_sibyte_algo.id; + i2c_adap->algo = &i2c_sibyte_algo; + + /* Set the frequency to 100 kHz */ + csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ)); + csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL)); + + /* scan bus */ + if (bit_scan) { + union i2c_smbus_data data; + int rc; + printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n", + i2c_adap->name); + for (i = 0x00; i < 0x7f; i++) { + /* XXXKW is this a realistic probe? */ + rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0, + I2C_SMBUS_BYTE_DATA, &data); + if (!rc) { + printk("(%02x)",i); + } else + printk("."); + } + printk("\n"); + } + +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif + i2c_add_adapter(i2c_adap); + + return 0; +} + + +int i2c_sibyte_del_bus(struct i2c_adapter *adap) +{ + int res; + + if ((res = i2c_del_adapter(adap)) < 0) + return res; + +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif + return 0; +} + +int __init i2c_algo_sibyte_init (void) +{ + printk("i2c-algo-sibyte.o: i2c SiByte algorithm module\n"); + return 0; +} + + +EXPORT_SYMBOL(i2c_sibyte_add_bus); +EXPORT_SYMBOL(i2c_sibyte_del_bus); + +#ifdef MODULE +MODULE_AUTHOR("Kip Walker, Broadcom Corp."); +MODULE_DESCRIPTION("SiByte I2C-Bus algorithm"); +MODULE_PARM(bit_scan, "i"); +MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus"); +MODULE_LICENSE("GPL"); + +int init_module(void) +{ + return i2c_algo_sibyte_init(); +} + +void cleanup_module(void) +{ +} +#endif diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index d0e7da45523a23..9d44bd94b712e3 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -143,8 +143,14 @@ config I2C_IBM_IIC will be called i2c-ibm_iic. config I2C_IOP3XX - tristate "Intel XScale IOP3xx on-chip I2C interface" - depends on ARCH_IOP3XX && I2C + tristate "Intel IOP3xx and IXP4xx on-chip I2C interface" + depends on (ARCH_IOP3XX || ARCH_IXP4XX) && I2C + help + Say Y here if you want to use the IIC bus controller on + the Intel IOP3xx I/O Processors or IXP4xx Network Processors. + + This driver can also be built as a module. If so, the module + will be called i2c-iop3xx. config I2C_ISA tristate "ISA Bus support" @@ -323,6 +329,12 @@ config I2C_SAVAGE4 This driver can also be built as a module. If so, the module will be called i2c-savage4. +config I2C_SIBYTE + tristate "SiByte SMBus interface" + depends on SIBYTE_SB1xxx_SOC && I2C + help + Supports the SiByte SOC on-chip I2C interfaces (2 channels). + config SCx200_I2C tristate "NatSemi SCx200 I2C using GPIO pins" depends on SCx200_GPIO && I2C diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index e414a1d1ec7729..fd58b2e609a3b4 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o +obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index dcc9365676d0ca..b00cd409822192 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -487,12 +487,7 @@ static struct i2c_adapter ali1535_adapter = { }; static struct pci_device_id ali1535_ids[] = { - { - .vendor = PCI_VENDOR_ID_AL, - .device = PCI_DEVICE_ID_AL_M7101, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, + { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, { }, }; diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index b3ee9a812bee6f..35710818fe47cb 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c @@ -306,7 +306,7 @@ static void ali1563_enable(struct pci_dev * dev) pci_write_config_word(dev,ALI1563_SMBBA,ctrl); } -static int __init ali1563_setup(struct pci_dev * dev) +static int __devinit ali1563_setup(struct pci_dev * dev) { u16 ctrl; @@ -362,7 +362,7 @@ static struct i2c_adapter ali1563_adapter = { .algo = &ali1563_algorithm, }; -static int __init ali1563_probe(struct pci_dev * dev, +static int __devinit ali1563_probe(struct pci_dev * dev, const struct pci_device_id * id_table) { int error; @@ -378,19 +378,14 @@ static int __init ali1563_probe(struct pci_dev * dev, return error; } -static void __exit ali1563_remove(struct pci_dev * dev) +static void __devexit ali1563_remove(struct pci_dev * dev) { i2c_del_adapter(&ali1563_adapter); ali1563_shutdown(dev); } static struct pci_device_id __devinitdata ali1563_id_table[] = { - { - .vendor = PCI_VENDOR_ID_AL, - .device = PCI_DEVICE_ID_AL_M1563, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, + { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1563) }, {}, }; @@ -400,7 +395,7 @@ static struct pci_driver ali1563_pci_driver = { .name = "ali1563_i2c", .id_table = ali1563_id_table, .probe = ali1563_probe, - .remove = ali1563_remove, + .remove = __devexit_p(ali1563_remove), }; static int __init ali1563_init(void) diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 8e13b834197185..5bd6a4a77c1eec 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -477,12 +477,7 @@ static struct i2c_adapter ali15x3_adapter = { }; static struct pci_device_id ali15x3_ids[] = { - { - .vendor = PCI_VENDOR_ID_AL, - .device = PCI_DEVICE_ID_AL_M7101, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, + { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index 35a1835193c8c5..eca5ed3738b857 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c @@ -316,11 +316,16 @@ static const char* chipname[] = { }; static struct pci_device_id amd756_ids[] = { - {PCI_VENDOR_ID_AMD, 0x740B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD756 }, - {PCI_VENDOR_ID_AMD, 0x7413, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD766 }, - {PCI_VENDOR_ID_AMD, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768 }, - {PCI_VENDOR_ID_AMD, 0x746B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111 }, - {PCI_VENDOR_ID_NVIDIA, 0x01B4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B), + .driver_data = AMD756 }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413), + .driver_data = AMD766 }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7443), + .driver_data = AMD768 }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS), + .driver_data = AMD8111 }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS), + .driver_data = NFORCE }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index 5eb4d38bcf9d55..af22b401a38bb3 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c @@ -332,7 +332,7 @@ static struct i2c_algorithm smbus_algorithm = { static struct pci_device_id amd8111_ids[] = { - { 0x1022, 0x746a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS2) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c index 7480fd0b4e6945..e0cb3b0f92faba 100644 --- a/drivers/i2c/busses/i2c-hydra.c +++ b/drivers/i2c/busses/i2c-hydra.c @@ -111,12 +111,7 @@ static struct i2c_adapter hydra_adap = { }; static struct pci_device_id hydra_ids[] = { - { - .vendor = PCI_VENDOR_ID_APPLE, - .device = PCI_DEVICE_ID_APPLE_HYDRA, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, + { PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_HYDRA) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 8d6ec152573543..b4acf8891281d3 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -548,54 +548,14 @@ static struct i2c_adapter i801_adapter = { }; static struct pci_device_id i801_ids[] = { - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801AA_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801AB_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801BA_2, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801CA_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801DB_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801EB_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_ESB_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_ICH6_16, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index 844aa3e03256db..961241b19f8869 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -1,35 +1,30 @@ /* ------------------------------------------------------------------------- */ -/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx */ +/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx & IXP46x */ /* ------------------------------------------------------------------------- */ -/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd - * <Peter dot Milne at D hyphen TACQ dot com> - - 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, version 2. - - - 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. */ -/* ------------------------------------------------------------------------- */ -/* - With acknowledgements to i2c-algo-ibm_ocp.c by - Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com - - And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund: - - Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund - - And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>, - Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com> - - ---------------------------------------------------------------------------*/ +/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd + * <Peter dot Milne at D hyphen TACQ dot com> + * + * With acknowledgements to i2c-algo-ibm_ocp.c by + * Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com + * + * And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund: + * + * Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund + * + * And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>, + * Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com> + * + * Major cleanup by Deepak Saxena <dsaxena@plexity.net>, 01/2005: + * + * - Use driver model to pass per-chip info instead of hardcoding and #ifdefs + * - Use ioremap/__raw_readl/__raw_writel instead of direct dereference + * - Make it work with IXP46x chips + * - Cleanup function names, coding style, etc + * + * 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, version 2. + */ #include <linux/config.h> #include <linux/interrupt.h> @@ -40,24 +35,18 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/sched.h> +#include <linux/device.h> #include <linux/i2c.h> +#include <asm/io.h> -#include <asm/arch-iop3xx/iop321.h> -#include <asm/arch-iop3xx/iop321-irqs.h> #include "i2c-iop3xx.h" +/* global unit counter */ +static int i2c_id = 0; -/* ----- global defines ----------------------------------------------- */ -#define PASSERT(x) do { if (!(x) ) \ - printk(KERN_CRIT "PASSERT %s in %s:%d\n", #x, __FILE__, __LINE__ );\ - } while (0) - - -/* ----- global variables --------------------------------------------- */ - - -static inline unsigned char iic_cook_addr(struct i2c_msg *msg) +static inline unsigned char +iic_cook_addr(struct i2c_msg *msg) { unsigned char addr; @@ -66,103 +55,110 @@ static inline unsigned char iic_cook_addr(struct i2c_msg *msg) if (msg->flags & I2C_M_RD) addr |= 1; - /* PGM: what is M_REV_DIR_ADDR - do we need it ?? */ + /* + * Read or Write? + */ if (msg->flags & I2C_M_REV_DIR_ADDR) addr ^= 1; return addr; } - -static inline void iop3xx_adap_reset(struct i2c_algo_iop3xx_data *iop3xx_adap) +static void +iop3xx_i2c_reset(struct i2c_algo_iop3xx_data *iop3xx_adap) { /* Follows devman 9.3 */ - *iop3xx_adap->biu->CR = IOP321_ICR_UNIT_RESET; - *iop3xx_adap->biu->SR = IOP321_ISR_CLEARBITS; - *iop3xx_adap->biu->CR = 0; + __raw_writel(IOP3XX_ICR_UNIT_RESET, iop3xx_adap->ioaddr + CR_OFFSET); + __raw_writel(IOP3XX_ISR_CLEARBITS, iop3xx_adap->ioaddr + SR_OFFSET); + __raw_writel(0, iop3xx_adap->ioaddr + CR_OFFSET); } -static inline void iop3xx_adap_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap) +static void +iop3xx_i2c_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap) { - *iop3xx_adap->biu->SAR = MYSAR; + __raw_writel(MYSAR, iop3xx_adap->ioaddr + SAR_OFFSET); } -static inline void iop3xx_adap_enable(struct i2c_algo_iop3xx_data *iop3xx_adap) +static void +iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap) { - u32 cr = IOP321_ICR_GCD|IOP321_ICR_SCLEN|IOP321_ICR_UE; + u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE; + + /* + * Everytime unit enable is asserted, GPOD needs to be cleared + * on IOP321 to avoid data corruption on the bus. + */ +#ifdef CONFIG_ARCH_IOP321 +#define IOP321_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */ +#define IOP321_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */ + *IOP321_GPOD &= (iop3xx_adap->id == 0) ? ~IOP321_GPOD_I2C0 : + ~IOP321_GPOD_I2C1; +#endif /* NB SR bits not same position as CR IE bits :-( */ - iop3xx_adap->biu->SR_enabled = - IOP321_ISR_ALD | IOP321_ISR_BERRD | - IOP321_ISR_RXFULL | IOP321_ISR_TXEMPTY; + iop3xx_adap->SR_enabled = + IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD | + IOP3XX_ISR_RXFULL | IOP3XX_ISR_TXEMPTY; - cr |= IOP321_ICR_ALDIE | IOP321_ICR_BERRIE | - IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE; + cr |= IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE | + IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE; - *iop3xx_adap->biu->CR = cr; + __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); } -static void iop3xx_adap_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap) +static void +iop3xx_i2c_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap) { - unsigned cr = *iop3xx_adap->biu->CR; + unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); - cr &= ~(IOP321_ICR_MSTART | IOP321_ICR_TBYTE | - IOP321_ICR_MSTOP | IOP321_ICR_SCLEN); - *iop3xx_adap->biu->CR = cr; -} + cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE | + IOP3XX_ICR_MSTOP | IOP3XX_ICR_SCLEN); -static void iop3xx_adap_final_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap) -{ - unsigned cr = *iop3xx_adap->biu->CR; - - cr &= ~(IOP321_ICR_ALDIE | IOP321_ICR_BERRIE | - IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE); - iop3xx_adap->biu->SR_enabled = 0; - *iop3xx_adap->biu->CR = cr; + __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); } /* * NB: the handler has to clear the source of the interrupt! * Then it passes the SR flags of interest to BH via adap data */ -static irqreturn_t iop3xx_i2c_handler(int this_irq, - void *dev_id, - struct pt_regs *regs) +static irqreturn_t +iop3xx_i2c_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs) { struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id; + u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET); - u32 sr = *iop3xx_adap->biu->SR; - - if ((sr &= iop3xx_adap->biu->SR_enabled)) { - *iop3xx_adap->biu->SR = sr; - iop3xx_adap->biu->SR_received |= sr; + if ((sr &= iop3xx_adap->SR_enabled)) { + __raw_writel(sr, iop3xx_adap->ioaddr + SR_OFFSET); + iop3xx_adap->SR_received |= sr; wake_up_interruptible(&iop3xx_adap->waitq); } return IRQ_HANDLED; } /* check all error conditions, clear them , report most important */ -static int iop3xx_adap_error(u32 sr) +static int +iop3xx_i2c_error(u32 sr) { int rc = 0; - if ((sr&IOP321_ISR_BERRD)) { + if ((sr & IOP3XX_ISR_BERRD)) { if ( !rc ) rc = -I2C_ERR_BERR; } - if ((sr&IOP321_ISR_ALD)) { + if ((sr & IOP3XX_ISR_ALD)) { if ( !rc ) rc = -I2C_ERR_ALD; } return rc; } -static inline u32 get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap) +static inline u32 +iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap) { unsigned long flags; u32 sr; spin_lock_irqsave(&iop3xx_adap->lock, flags); - sr = iop3xx_adap->biu->SR_received; - iop3xx_adap->biu->SR_received = 0; + sr = iop3xx_adap->SR_received; + iop3xx_adap->SR_received = 0; spin_unlock_irqrestore(&iop3xx_adap->lock, flags); return sr; @@ -175,9 +171,10 @@ static inline u32 get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap) typedef int (* compare_func)(unsigned test, unsigned mask); /* returns 1 on correct comparison */ -static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap, - unsigned flags, unsigned* status, - compare_func compare) +static int +iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap, + unsigned flags, unsigned* status, + compare_func compare) { unsigned sr = 0; int interrupted; @@ -187,13 +184,13 @@ static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap, do { interrupted = wait_event_interruptible_timeout ( iop3xx_adap->waitq, - (done = compare( sr = get_srstat(iop3xx_adap),flags )), - iop3xx_adap->timeout + (done = compare( sr = iop3xx_i2c_get_srstat(iop3xx_adap) ,flags )), + 1 * HZ; ); - if ((rc = iop3xx_adap_error(sr)) < 0) { + if ((rc = iop3xx_i2c_error(sr)) < 0) { *status = sr; return rc; - }else if (!interrupted) { + } else if (!interrupted) { *status = sr; return -ETIMEDOUT; } @@ -207,141 +204,131 @@ static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap, /* * Concrete compare_funcs */ -static int all_bits_clear(unsigned test, unsigned mask) +static int +all_bits_clear(unsigned test, unsigned mask) { return (test & mask) == 0; } -static int any_bits_set(unsigned test, unsigned mask) + +static int +any_bits_set(unsigned test, unsigned mask) { return (test & mask) != 0; } -static int iop3xx_adap_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) +static int +iop3xx_i2c_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) { - return iop3xx_adap_wait_event( + return iop3xx_i2c_wait_event( iop3xx_adap, - IOP321_ISR_TXEMPTY|IOP321_ISR_ALD|IOP321_ISR_BERRD, + IOP3XX_ISR_TXEMPTY | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD, status, any_bits_set); } -static int iop3xx_adap_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) +static int +iop3xx_i2c_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) { - return iop3xx_adap_wait_event( + return iop3xx_i2c_wait_event( iop3xx_adap, - IOP321_ISR_RXFULL|IOP321_ISR_ALD|IOP321_ISR_BERRD, + IOP3XX_ISR_RXFULL | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD, status, any_bits_set); } -static int iop3xx_adap_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) -{ - return iop3xx_adap_wait_event( - iop3xx_adap, IOP321_ISR_UNITBUSY, status, all_bits_clear); -} - -/* - * Description: This performs the IOP3xx initialization sequence - * Valid for IOP321. Maybe valid for IOP310?. - */ -static int iop3xx_adap_init (struct i2c_algo_iop3xx_data *iop3xx_adap) +static int +iop3xx_i2c_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) { - *IOP321_GPOD &= ~(iop3xx_adap->channel==0 ? - IOP321_GPOD_I2C0: - IOP321_GPOD_I2C1); - - iop3xx_adap_reset(iop3xx_adap); - iop3xx_adap_set_slave_addr(iop3xx_adap); - iop3xx_adap_enable(iop3xx_adap); - - return 0; + return iop3xx_i2c_wait_event( + iop3xx_adap, IOP3XX_ISR_UNITBUSY, status, all_bits_clear); } -static int iop3xx_adap_send_target_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap, - struct i2c_msg* msg) +static int +iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap, + struct i2c_msg* msg) { - unsigned cr = *iop3xx_adap->biu->CR; + unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); int status; int rc; - *iop3xx_adap->biu->DBR = iic_cook_addr(msg); + __raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET); - cr &= ~(IOP321_ICR_MSTOP | IOP321_ICR_NACK); - cr |= IOP321_ICR_MSTART | IOP321_ICR_TBYTE; - - *iop3xx_adap->biu->CR = cr; - rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status); - /* this assert fires every time, contrary to IOP manual - PASSERT((status&IOP321_ISR_UNITBUSY)!=0); - */ - PASSERT((status&IOP321_ISR_RXREAD)==0); - + cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK); + cr |= IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE; + + __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); + rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status); + return rc; } -static int iop3xx_adap_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, int stop) +static int +iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, + int stop) { - unsigned cr = *iop3xx_adap->biu->CR; + unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); int status; int rc = 0; - *iop3xx_adap->biu->DBR = byte; - cr &= ~IOP321_ICR_MSTART; + __raw_writel(byte, iop3xx_adap->ioaddr + DBR_OFFSET); + cr &= ~IOP3XX_ICR_MSTART; if (stop) { - cr |= IOP321_ICR_MSTOP; + cr |= IOP3XX_ICR_MSTOP; } else { - cr &= ~IOP321_ICR_MSTOP; + cr &= ~IOP3XX_ICR_MSTOP; } - *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE; - rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status); + cr |= IOP3XX_ICR_TBYTE; + __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); + rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status); return rc; } -static int iop3xx_adap_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, - char* byte, int stop) +static int +iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte, + int stop) { - unsigned cr = *iop3xx_adap->biu->CR; + unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); int status; int rc = 0; - cr &= ~IOP321_ICR_MSTART; + cr &= ~IOP3XX_ICR_MSTART; if (stop) { - cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK; + cr |= IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK; } else { - cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK); + cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK); } - *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE; + cr |= IOP3XX_ICR_TBYTE; + __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); - rc = iop3xx_adap_wait_rx_done(iop3xx_adap, &status); + rc = iop3xx_i2c_wait_rx_done(iop3xx_adap, &status); - *byte = *iop3xx_adap->biu->DBR; + *byte = __raw_readl(iop3xx_adap->ioaddr + DBR_OFFSET); return rc; } -static int iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, - const char *buf, int count) +static int +iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, const char *buf, int count) { struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; int ii; int rc = 0; - for (ii = 0; rc == 0 && ii != count; ++ii) { - rc = iop3xx_adap_write_byte(iop3xx_adap, buf[ii], ii==count-1); - } + for (ii = 0; rc == 0 && ii != count; ++ii) + rc = iop3xx_i2c_write_byte(iop3xx_adap, buf[ii], ii==count-1); return rc; } -static int iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, - char *buf, int count) +static int +iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count) { struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; int ii; int rc = 0; - for (ii = 0; rc == 0 && ii != count; ++ii) { - rc = iop3xx_adap_read_byte(iop3xx_adap, &buf[ii], ii==count-1); - } + for (ii = 0; rc == 0 && ii != count; ++ii) + rc = iop3xx_i2c_read_byte(iop3xx_adap, &buf[ii], ii==count-1); + return rc; } @@ -352,12 +339,13 @@ static int iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, * Each transfer (i.e. a read or a write) is separated by a repeated start * condition. */ -static int iop3xx_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg) +static int +iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg) { struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; int rc; - rc = iop3xx_adap_send_target_slave_addr(iop3xx_adap, pmsg); + rc = iop3xx_i2c_send_target_addr(iop3xx_adap, pmsg); if (rc < 0) { return rc; } @@ -372,22 +360,24 @@ static int iop3xx_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg) /* * master_xfer() - main read/write entry */ -static int iop3xx_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) +static int +iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], + int num) { struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; int im = 0; int ret = 0; int status; - iop3xx_adap_wait_idle(iop3xx_adap, &status); - iop3xx_adap_reset(iop3xx_adap); - iop3xx_adap_enable(iop3xx_adap); + iop3xx_i2c_wait_idle(iop3xx_adap, &status); + iop3xx_i2c_reset(iop3xx_adap); + iop3xx_i2c_enable(iop3xx_adap); for (im = 0; ret == 0 && im != num; im++) { - ret = iop3xx_handle_msg(i2c_adap, &msgs[im]); + ret = iop3xx_i2c_handle_msg(i2c_adap, &msgs[im]); } - iop3xx_adap_transaction_cleanup(iop3xx_adap); + iop3xx_i2c_transaction_cleanup(iop3xx_adap); if(ret) return ret; @@ -395,136 +385,165 @@ static int iop3xx_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[ return im; } -static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, +static int +iop3xx_i2c_algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned long arg) { return 0; } -static u32 iic_func(struct i2c_adapter *adap) +static u32 +iop3xx_i2c_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } - -/* -----exported algorithm data: ------------------------------------- */ - -static struct i2c_algorithm iic_algo = { +static struct i2c_algorithm iop3xx_i2c_algo = { .name = "IOP3xx I2C algorithm", - .id = I2C_ALGO_OCP_IOP3XX, - .master_xfer = iop3xx_master_xfer, - .algo_control = algo_control, - .functionality = iic_func, + .id = I2C_ALGO_IOP3XX, + .master_xfer = iop3xx_i2c_master_xfer, + .algo_control = iop3xx_i2c_algo_control, + .functionality = iop3xx_i2c_func, }; -/* - * registering functions to load algorithms at runtime - */ -static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap) +static int +iop3xx_i2c_remove(struct device *device) { - struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data; + struct platform_device *pdev = to_platform_device(device); + struct i2c_adapter *padapter = dev_get_drvdata(&pdev->dev); + struct i2c_algo_iop3xx_data *adapter_data = + (struct i2c_algo_iop3xx_data *)padapter->algo_data; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + unsigned long cr = __raw_readl(adapter_data->ioaddr + CR_OFFSET); + + /* + * Disable the actual HW unit + */ + cr &= ~(IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE | + IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE); + __raw_writel(cr, adapter_data->ioaddr + CR_OFFSET); + + iounmap((void __iomem*)adapter_data->ioaddr); + release_mem_region(res->start, IOP3XX_I2C_IO_SIZE); + kfree(adapter_data); + kfree(padapter); + + dev_set_drvdata(&pdev->dev, NULL); + + return 0; +} - if (!request_region( REGION_START(iop3xx_adap), - REGION_LENGTH(iop3xx_adap), - iic_adap->name)) { - return -ENODEV; +static int +iop3xx_i2c_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct resource *res; + int ret; + struct i2c_adapter *new_adapter; + struct i2c_algo_iop3xx_data *adapter_data; + + new_adapter = kmalloc(sizeof(struct i2c_adapter), GFP_KERNEL); + if (!new_adapter) { + ret = -ENOMEM; + goto out; } + memset((void*)new_adapter, 0, sizeof(*new_adapter)); - init_waitqueue_head(&iop3xx_adap->waitq); - spin_lock_init(&iop3xx_adap->lock); + adapter_data = kmalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL); + if (!adapter_data) { + ret = -ENOMEM; + goto free_adapter; + } + memset((void*)adapter_data, 0, sizeof(*adapter_data)); - if (request_irq( - iop3xx_adap->biu->irq, - iop3xx_i2c_handler, - /* SA_SAMPLE_RANDOM */ 0, - iic_adap->name, - iop3xx_adap)) { - return -ENODEV; - } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENODEV; + goto free_both; + } - /* register new iic_adapter to i2c module... */ - iic_adap->id |= iic_algo.id; - iic_adap->algo = &iic_algo; + if (!request_mem_region(res->start, IOP3XX_I2C_IO_SIZE, pdev->name)) { + ret = -EBUSY; + goto free_both; + } - iic_adap->timeout = 100; /* default values, should */ - iic_adap->retries = 3; /* be replaced by defines */ + /* set the adapter enumeration # */ + adapter_data->id = i2c_id++; - iop3xx_adap_init(iic_adap->algo_data); - i2c_add_adapter(iic_adap); - return 0; -} + adapter_data->ioaddr = (u32)ioremap(res->start, IOP3XX_I2C_IO_SIZE); + if (!adapter_data->ioaddr) { + ret = -ENOMEM; + goto release_region; + } -static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap) -{ - struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data; + res = request_irq(platform_get_irq(pdev, 0), iop3xx_i2c_irq_handler, 0, + pdev->name, adapter_data); + if (res) { + ret = -EIO; + goto unmap; + } - iop3xx_adap_final_cleanup(iop3xx_adap); - free_irq(iop3xx_adap->biu->irq, iop3xx_adap); + memcpy(new_adapter->name, pdev->name, strlen(pdev->name)); + new_adapter->id = I2C_HW_IOP3XX; + new_adapter->owner = THIS_MODULE; + new_adapter->dev.parent = &pdev->dev; - release_region(REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap)); + /* + * Default values...should these come in from board code? + */ + new_adapter->timeout = 100; + new_adapter->retries = 3; + new_adapter->algo = &iop3xx_i2c_algo; - return i2c_del_adapter(iic_adap); -} + init_waitqueue_head(&adapter_data->waitq); + spin_lock_init(&adapter_data->lock); -#ifdef CONFIG_ARCH_IOP321 + iop3xx_i2c_reset(adapter_data); + iop3xx_i2c_set_slave_addr(adapter_data); + iop3xx_i2c_enable(adapter_data); -static struct iop3xx_biu biu0 = { - .CR = IOP321_ICR0, - .SR = IOP321_ISR0, - .SAR = IOP321_ISAR0, - .DBR = IOP321_IDBR0, - .BMR = IOP321_IBMR0, - .irq = IRQ_IOP321_I2C_0, -}; + dev_set_drvdata(&pdev->dev, new_adapter); + new_adapter->algo_data = adapter_data; -static struct iop3xx_biu biu1 = { - .CR = IOP321_ICR1, - .SR = IOP321_ISR1, - .SAR = IOP321_ISAR1, - .DBR = IOP321_IDBR1, - .BMR = IOP321_IBMR1, - .irq = IRQ_IOP321_I2C_1, -}; + i2c_add_adapter(new_adapter); -#define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter " -#else -#error Please define the BIU struct iop3xx_biu for your processor arch -#endif + return 0; -static struct i2c_algo_iop3xx_data algo_iop3xx_data0 = { - .channel = 0, - .biu = &biu0, - .timeout = 1*HZ, -}; -static struct i2c_algo_iop3xx_data algo_iop3xx_data1 = { - .channel = 1, - .biu = &biu1, - .timeout = 1*HZ, -}; +unmap: + iounmap((void __iomem*)adapter_data->ioaddr); -static struct i2c_adapter iop3xx_ops0 = { - .owner = THIS_MODULE, - .name = ADAPTER_NAME_ROOT "0", - .id = I2C_HW_IOP321, - .algo_data = &algo_iop3xx_data0, -}; -static struct i2c_adapter iop3xx_ops1 = { - .owner = THIS_MODULE, - .name = ADAPTER_NAME_ROOT "1", - .id = I2C_HW_IOP321, - .algo_data = &algo_iop3xx_data1, +release_region: + release_mem_region(res->start, IOP3XX_I2C_IO_SIZE); + +free_both: + kfree(adapter_data); + +free_adapter: + kfree(new_adapter); + +out: + return ret; +} + + +static struct device_driver iop3xx_i2c_driver = { + .name = "IOP3xx-I2C", + .bus = &platform_bus_type, + .probe = iop3xx_i2c_probe, + .remove = iop3xx_i2c_remove }; -static int __init i2c_iop3xx_init (void) +static int __init +i2c_iop3xx_init (void) { - return i2c_iop3xx_add_bus(&iop3xx_ops0) || - i2c_iop3xx_add_bus(&iop3xx_ops1); + return driver_register(&iop3xx_i2c_driver); } -static void __exit i2c_iop3xx_exit (void) +static void __exit +i2c_iop3xx_exit (void) { - i2c_iop3xx_del_bus(&iop3xx_ops0); - i2c_iop3xx_del_bus(&iop3xx_ops1); + driver_unregister(&iop3xx_i2c_driver); + return; } module_init (i2c_iop3xx_init); diff --git a/drivers/i2c/busses/i2c-iop3xx.h b/drivers/i2c/busses/i2c-iop3xx.h index f375881842a1a6..e46ebaea7b1edb 100644 --- a/drivers/i2c/busses/i2c-iop3xx.h +++ b/drivers/i2c/busses/i2c-iop3xx.h @@ -25,20 +25,20 @@ /* * iop321 hardware bit definitions */ -#define IOP321_ICR_FAST_MODE 0x8000 /* 1=400kBps, 0=100kBps */ -#define IOP321_ICR_UNIT_RESET 0x4000 /* 1=RESET */ -#define IOP321_ICR_SADIE 0x2000 /* 1=Slave Detect Interrupt Enable */ -#define IOP321_ICR_ALDIE 0x1000 /* 1=Arb Loss Detect Interrupt Enable */ -#define IOP321_ICR_SSDIE 0x0800 /* 1=Slave STOP Detect Interrupt Enable */ -#define IOP321_ICR_BERRIE 0x0400 /* 1=Bus Error Interrupt Enable */ -#define IOP321_ICR_RXFULLIE 0x0200 /* 1=Receive Full Interrupt Enable */ -#define IOP321_ICR_TXEMPTYIE 0x0100 /* 1=Transmit Empty Interrupt Enable */ -#define IOP321_ICR_GCD 0x0080 /* 1=General Call Disable */ +#define IOP3XX_ICR_FAST_MODE 0x8000 /* 1=400kBps, 0=100kBps */ +#define IOP3XX_ICR_UNIT_RESET 0x4000 /* 1=RESET */ +#define IOP3XX_ICR_SAD_IE 0x2000 /* 1=Slave Detect Interrupt Enable */ +#define IOP3XX_ICR_ALD_IE 0x1000 /* 1=Arb Loss Detect Interrupt Enable */ +#define IOP3XX_ICR_SSD_IE 0x0800 /* 1=Slave STOP Detect Interrupt Enable */ +#define IOP3XX_ICR_BERR_IE 0x0400 /* 1=Bus Error Interrupt Enable */ +#define IOP3XX_ICR_RXFULL_IE 0x0200 /* 1=Receive Full Interrupt Enable */ +#define IOP3XX_ICR_TXEMPTY_IE 0x0100 /* 1=Transmit Empty Interrupt Enable */ +#define IOP3XX_ICR_GCD 0x0080 /* 1=General Call Disable */ /* - * IOP321_ICR_GCD: 1 disables response as slave. "This bit must be set + * IOP3XX_ICR_GCD: 1 disables response as slave. "This bit must be set * when sending a master mode general call message from the I2C unit" */ -#define IOP321_ICR_UE 0x0040 /* 1=Unit Enable */ +#define IOP3XX_ICR_UE 0x0040 /* 1=Unit Enable */ /* * "NOTE: To avoid I2C bus integrity problems, * the user needs to ensure that the GPIO Output Data Register - @@ -47,38 +47,38 @@ * The user prepares to enable I2C port 0 and * I2C port 1 by clearing GPOD bits 7:6 and GPOD bits 5:4, respectively. */ -#define IOP321_ICR_SCLEN 0x0020 /* 1=SCL enable for master mode */ -#define IOP321_ICR_MABORT 0x0010 /* 1=Send a STOP with no data +#define IOP3XX_ICR_SCLEN 0x0020 /* 1=SCL enable for master mode */ +#define IOP3XX_ICR_MABORT 0x0010 /* 1=Send a STOP with no data * NB TBYTE must be clear */ -#define IOP321_ICR_TBYTE 0x0008 /* 1=Send/Receive a byte. i2c clears */ -#define IOP321_ICR_NACK 0x0004 /* 1=reply with NACK */ -#define IOP321_ICR_MSTOP 0x0002 /* 1=send a STOP after next data byte */ -#define IOP321_ICR_MSTART 0x0001 /* 1=initiate a START */ +#define IOP3XX_ICR_TBYTE 0x0008 /* 1=Send/Receive a byte. i2c clears */ +#define IOP3XX_ICR_NACK 0x0004 /* 1=reply with NACK */ +#define IOP3XX_ICR_MSTOP 0x0002 /* 1=send a STOP after next data byte */ +#define IOP3XX_ICR_MSTART 0x0001 /* 1=initiate a START */ -#define IOP321_ISR_BERRD 0x0400 /* 1=BUS ERROR Detected */ -#define IOP321_ISR_SAD 0x0200 /* 1=Slave ADdress Detected */ -#define IOP321_ISR_GCAD 0x0100 /* 1=General Call Address Detected */ -#define IOP321_ISR_RXFULL 0x0080 /* 1=Receive Full */ -#define IOP321_ISR_TXEMPTY 0x0040 /* 1=Transmit Empty */ -#define IOP321_ISR_ALD 0x0020 /* 1=Arbitration Loss Detected */ -#define IOP321_ISR_SSD 0x0010 /* 1=Slave STOP Detected */ -#define IOP321_ISR_BBUSY 0x0008 /* 1=Bus BUSY */ -#define IOP321_ISR_UNITBUSY 0x0004 /* 1=Unit Busy */ -#define IOP321_ISR_NACK 0x0002 /* 1=Unit Rx or Tx a NACK */ -#define IOP321_ISR_RXREAD 0x0001 /* 1=READ 0=WRITE (R/W bit of slave addr */ +#define IOP3XX_ISR_BERRD 0x0400 /* 1=BUS ERROR Detected */ +#define IOP3XX_ISR_SAD 0x0200 /* 1=Slave ADdress Detected */ +#define IOP3XX_ISR_GCAD 0x0100 /* 1=General Call Address Detected */ +#define IOP3XX_ISR_RXFULL 0x0080 /* 1=Receive Full */ +#define IOP3XX_ISR_TXEMPTY 0x0040 /* 1=Transmit Empty */ +#define IOP3XX_ISR_ALD 0x0020 /* 1=Arbitration Loss Detected */ +#define IOP3XX_ISR_SSD 0x0010 /* 1=Slave STOP Detected */ +#define IOP3XX_ISR_BBUSY 0x0008 /* 1=Bus BUSY */ +#define IOP3XX_ISR_UNITBUSY 0x0004 /* 1=Unit Busy */ +#define IOP3XX_ISR_NACK 0x0002 /* 1=Unit Rx or Tx a NACK */ +#define IOP3XX_ISR_RXREAD 0x0001 /* 1=READ 0=WRITE (R/W bit of slave addr */ -#define IOP321_ISR_CLEARBITS 0x07f0 +#define IOP3XX_ISR_CLEARBITS 0x07f0 -#define IOP321_ISAR_SAMASK 0x007f +#define IOP3XX_ISAR_SAMASK 0x007f -#define IOP321_IDBR_MASK 0x00ff +#define IOP3XX_IDBR_MASK 0x00ff -#define IOP321_IBMR_SCL 0x0002 -#define IOP321_IBMR_SDA 0x0001 +#define IOP3XX_IBMR_SCL 0x0002 +#define IOP3XX_IBMR_SDA 0x0001 -#define IOP321_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */ -#define IOP321_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */ +#define IOP3XX_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */ +#define IOP3XX_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */ #define MYSAR 0x02 /* SWAG a suitable slave address */ @@ -87,32 +87,21 @@ #define I2C_ERR_ALD (I2C_ERR+1) -struct iop3xx_biu { /* Bus Interface Unit - the hardware */ -/* physical hardware defs - regs*/ - u32 *CR; - u32 *SR; - u32 *SAR; - u32 *DBR; - u32 *BMR; -/* irq bit vector */ - u32 irq; -/* stored flags */ - u32 SR_enabled, SR_received; -}; +#define CR_OFFSET 0 +#define SR_OFFSET 0x4 +#define SAR_OFFSET 0x8 +#define DBR_OFFSET 0xc +#define CCR_OFFSET 0x10 +#define BMR_OFFSET 0x14 -struct i2c_algo_iop3xx_data { - int channel; +#define IOP3XX_I2C_IO_SIZE 0x18 +struct i2c_algo_iop3xx_data { + u32 ioaddr; wait_queue_head_t waitq; spinlock_t lock; - int timeout; - struct iop3xx_biu* biu; + u32 SR_enabled, SR_received; + int id; }; -#define REGION_START(adap) ((u32)((adap)->biu->CR)) -#define REGION_END(adap) ((u32)((adap)->biu->BMR+1)) -#define REGION_LENGTH(adap) (REGION_END(adap)-REGION_START(adap)) - -#define IRQ_STATUS_MASK(adap) (1<<adap->biu->irq) - #endif /* I2C_IOP3XX_H */ diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index cc7ab3143f9387..b2b6081327d88e 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -28,6 +28,7 @@ nForce2 MCP 0064 nForce2 Ultra 400 MCP 0084 nForce3 Pro150 MCP 00D4 + nForce3 250Gb MCP 00E4 This driver supports the 2 SMBuses that are included in the MCP2 of the nForce2 chipset. @@ -290,12 +291,10 @@ static u32 nforce2_func(struct i2c_adapter *adapter) static struct pci_device_id nforce2_ids[] = { - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) }, { 0 } }; diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 8bb467ade22299..646381b6b3bf9e 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -414,48 +414,18 @@ static struct i2c_adapter piix4_adapter = { }; static struct pci_device_id piix4_ids[] = { - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82371AB_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 3 - }, - { - .vendor = PCI_VENDOR_ID_SERVERWORKS, - .device = PCI_DEVICE_ID_SERVERWORKS_OSB4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { - .vendor = PCI_VENDOR_ID_SERVERWORKS, - .device = PCI_DEVICE_ID_SERVERWORKS_CSB5, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { - .vendor = PCI_VENDOR_ID_SERVERWORKS, - .device = PCI_DEVICE_ID_SERVERWORKS_CSB6, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82443MX_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 3, - }, - { - .vendor = PCI_VENDOR_ID_EFAR, - .device = PCI_DEVICE_ID_EFAR_SLC90E66_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3), + .driver_data = 3 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3), + .driver_data = 3 }, + { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3), + .driver_data = 0 }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c index f5804568b57df4..13d66289933b9b 100644 --- a/drivers/i2c/busses/i2c-prosavage.c +++ b/drivers/i2c/busses/i2c-prosavage.c @@ -96,13 +96,6 @@ struct s_i2c_chip { /* * S3/VIA 8365/8375 registers */ -#ifndef PCI_DEVICE_ID_S3_SAVAGE4 -#define PCI_DEVICE_ID_S3_SAVAGE4 0x8a25 -#endif -#ifndef PCI_DEVICE_ID_S3_PROSAVAGE8 -#define PCI_DEVICE_ID_S3_PROSAVAGE8 0x8d04 -#endif - #define VGA_CR_IX 0x3d4 #define VGA_CR_DATA 0x3d5 diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c new file mode 100644 index 00000000000000..e5dd90bdb04aaa --- /dev/null +++ b/drivers/i2c/busses/i2c-sibyte.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2004 Steven J. Hill + * Copyright (C) 2001,2002,2003 Broadcom Corporation + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/i2c-algo-sibyte.h> +#include <asm/sibyte/sb1250_regs.h> +#include <asm/sibyte/sb1250_smbus.h> + +static struct i2c_algo_sibyte_data sibyte_board_data[2] = { + { NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) }, + { NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) } +}; + +static struct i2c_adapter sibyte_board_adapter[2] = { + { + .owner = THIS_MODULE, + .id = I2C_HW_SIBYTE, + .class = I2C_CLASS_HWMON, + .algo = NULL, + .algo_data = &sibyte_board_data[0], + .name = "SiByte SMBus 0", + }, + { + .owner = THIS_MODULE, + .id = I2C_HW_SIBYTE, + .class = I2C_CLASS_HWMON, + .algo = NULL, + .algo_data = &sibyte_board_data[1], + .name = "SiByte SMBus 1", + }, +}; + +static int __init i2c_sibyte_init(void) +{ + printk("i2c-swarm.o: i2c SMBus adapter module for SiByte board\n"); + if (i2c_sibyte_add_bus(&sibyte_board_adapter[0], K_SMB_FREQ_100KHZ) < 0) + return -ENODEV; + if (i2c_sibyte_add_bus(&sibyte_board_adapter[1], K_SMB_FREQ_400KHZ) < 0) + return -ENODEV; + return 0; +} + +static void __exit i2c_sibyte_exit(void) +{ + i2c_sibyte_del_bus(&sibyte_board_adapter[0]); + i2c_sibyte_del_bus(&sibyte_board_adapter[1]); +} + +module_init(i2c_sibyte_init); +module_exit(i2c_sibyte_exit); + +MODULE_AUTHOR("Kip Walker <kwalker@broadcom.com>, Steven J. Hill <sjhill@realitydiluted.com>"); +MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c index 69a2e7d7e44e02..3cac6d43bce576 100644 --- a/drivers/i2c/busses/i2c-sis96x.c +++ b/drivers/i2c/busses/i2c-sis96x.c @@ -51,9 +51,6 @@ */ #define SIS96x_VERSION "1.0.0" -/* SiS96x SMBus PCI device ID */ -#define PCI_DEVICE_ID_SI_SMBUS 0x16 - /* base address register in PCI config space */ #define SIS96x_BAR 0x04 @@ -267,14 +264,7 @@ static struct i2c_adapter sis96x_adapter = { }; static struct pci_device_id sis96x_ids[] = { - - { - .vendor = PCI_VENDOR_ID_SI, - .device = PCI_DEVICE_ID_SI_SMBUS, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - + { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c index fec0bff2963d9f..19c805ead4d896 100644 --- a/drivers/i2c/busses/i2c-stub.c +++ b/drivers/i2c/busses/i2c-stub.c @@ -28,6 +28,7 @@ #include <linux/errno.h> #include <linux/i2c.h> +static u8 stub_pointer; static u8 stub_bytes[256]; static u16 stub_words[256]; @@ -44,6 +45,22 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, ret = 0; break; + case I2C_SMBUS_BYTE: + if (read_write == I2C_SMBUS_WRITE) { + stub_pointer = command; + dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " + "wrote 0x%02x.\n", + addr, command); + } else { + data->byte = stub_bytes[stub_pointer++]; + dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " + "read 0x%02x.\n", + addr, data->byte); + } + + ret = 0; + break; + case I2C_SMBUS_BYTE_DATA: if (read_write == I2C_SMBUS_WRITE) { stub_bytes[command] = data->byte; @@ -56,6 +73,7 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, "read 0x%02x at 0x%02x.\n", addr, data->byte, command); } + stub_pointer = command + 1; ret = 0; break; @@ -87,8 +105,8 @@ 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_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; } static struct i2c_algorithm smbus_algorithm = { diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index 83a77ba976b075..d86cdc6524e7b1 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -395,62 +395,22 @@ static void __devexit vt596_remove(struct pci_dev *pdev) } static struct pci_device_id vt596_ids[] = { - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_82C596_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA1, - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_82C596B_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA1, - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_82C686_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA1, - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8233_0, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA3 - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8233A, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA3, - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8235, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA3 - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8237, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA3 - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8231_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA1, - }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3), + .driver_data = SMBBA1 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3), + .driver_data = SMBBA1 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4), + .driver_data = SMBBA1 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_0), + .driver_data = SMBBA3 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233A), + .driver_data = SMBBA3 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235), + .driver_data = SMBBA3 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237), + .driver_data = SMBBA3 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4), + .driver_data = SMBBA1 }, { 0, } }; diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index f1f35409ab8dab..1c4ba561990871 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -239,6 +239,18 @@ config SENSORS_PC87360 This driver can also be built as a module. If so, the module will be called pc87360. +config SENSORS_SMSC47B397 + tristate "SMSC LPC47B397-NC" + depends on I2C && EXPERIMENTAL + select I2C_SENSOR + select I2C_ISA + help + If you say yes here you get support for the SMSC LPC47B397-NC + sensor chip. + + This driver can also be built as a module. If so, the module + will be called smsc47b397. + config SENSORS_SMSC47M1 tristate "SMSC LPC47M10x and compatibles" depends on I2C && EXPERIMENTAL diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index 90dd7dd0ca148e..74dd56873a8bdf 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o +obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o obj-$(CONFIG_SENSORS_VIA686A) += via686a.o obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o diff --git a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c index eba1584d731f53..7c6d896e96d799 100644 --- a/drivers/i2c/chips/asb100.c +++ b/drivers/i2c/chips/asb100.c @@ -56,8 +56,7 @@ #define ASB100_VERSION "1.0.0" /* I2C addresses to scan */ -static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, - 0x2e, 0x2f, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END }; /* ISA addresses to scan (none) */ static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index 94c8698ab11419..6da35c70f8b644 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c @@ -43,13 +43,6 @@ static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_1(eeprom); -static int checksum = 0; -module_param(checksum, bool, 0); -MODULE_PARM_DESC(checksum, "Only accept eeproms whose checksum is correct"); - - -/* EEPROM registers */ -#define EEPROM_REG_CHECKSUM 0x3f /* Size of EEPROM in bytes */ #define EEPROM_SIZE 256 @@ -168,7 +161,6 @@ static int eeprom_attach_adapter(struct i2c_adapter *adapter) /* This function is called by i2c_detect */ int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) { - int i, cs; struct i2c_client *new_client; struct eeprom_data *data; int err = 0; @@ -205,17 +197,6 @@ int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) /* prevent 24RF08 corruption */ i2c_smbus_write_quick(new_client, 0); - /* Now, we do the remaining detection. It is not there, unless you force - the checksum to work out. */ - if (checksum) { - cs = 0; - for (i = 0; i <= 0x3e; i++) - cs += i2c_smbus_read_byte_data(new_client, i); - cs &= 0xff; - if (i2c_smbus_read_byte_data (new_client, EEPROM_REG_CHECKSUM) != cs) - goto exit_kfree; - } - data->nature = UNKNOWN; /* Detect the Vaio nature of EEPROMs. We use the "PCG-" prefix as the signature. */ diff --git a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c index f41ab9fd62d668..f8e18c9ae84272 100644 --- a/drivers/i2c/chips/fscher.c +++ b/drivers/i2c/chips/fscher.c @@ -198,7 +198,7 @@ sysfs_r(kind, sub, 0, reg) \ static DEVICE_ATTR(kind, S_IRUGO, show_##kind##0##sub, NULL); #define sysfs_fan(offset, reg_status, reg_min, reg_ripple, reg_act) \ -sysfs_rw_n(fan, _pwm , offset, reg_min) \ +sysfs_rw_n(pwm, , offset, reg_min) \ sysfs_rw_n(fan, _status, offset, reg_status) \ sysfs_rw_n(fan, _div , offset, reg_ripple) \ sysfs_ro_n(fan, _input , offset, reg_act) @@ -247,7 +247,7 @@ sysfs_watchdog(FSCHER_REG_WDOG_CONTROL, FSCHER_REG_WDOG_STATE, FSCHER_REG_WDOG_P #define device_create_file_fan(client, offset) \ do { \ device_create_file(&client->dev, &dev_attr_fan##offset##_status); \ - device_create_file(&client->dev, &dev_attr_fan##offset##_pwm); \ + device_create_file(&client->dev, &dev_attr_pwm##offset); \ device_create_file(&client->dev, &dev_attr_fan##offset##_div); \ device_create_file(&client->dev, &dev_attr_fan##offset##_input); \ } while (0) @@ -483,16 +483,17 @@ static ssize_t show_fan_status(struct fscher_data *data, char *buf, int nr) return sprintf(buf, "%u\n", data->fan_status[FAN_INDEX_FROM_NUM(nr)] & 0x04); } -static ssize_t set_fan_pwm(struct i2c_client *client, struct fscher_data *data, +static ssize_t set_pwm(struct i2c_client *client, struct fscher_data *data, const char *buf, size_t count, int nr, int reg) { - data->fan_min[FAN_INDEX_FROM_NUM(nr)] = simple_strtoul(buf, NULL, 10) & 0xff; + unsigned long v = simple_strtoul(buf, NULL, 10); + data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v; fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]); return count; } -static ssize_t show_fan_pwm (struct fscher_data *data, char *buf, int nr) +static ssize_t show_pwm(struct fscher_data *data, char *buf, int nr) { return sprintf(buf, "%u\n", data->fan_min[FAN_INDEX_FROM_NUM(nr)]); } diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c index 11d0df3b00e658..d7fec78faca819 100644 --- a/drivers/i2c/chips/isp1301_omap.c +++ b/drivers/i2c/chips/isp1301_omap.c @@ -934,13 +934,14 @@ static void otg_unbind(struct isp1301 *isp) static void b_peripheral(struct isp1301 *isp) { - enable_vbus_draw(isp, 8); OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS; usb_gadget_vbus_connect(isp->otg.gadget); #ifdef CONFIG_USB_OTG + enable_vbus_draw(isp, 8); otg_update_isp(isp); #else + enable_vbus_draw(isp, 100); /* UDC driver just set OTG_BSESSVLD */ isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP); isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN); @@ -950,7 +951,7 @@ static void b_peripheral(struct isp1301 *isp) #endif } -static int isp_update_otg(struct isp1301 *isp, u8 stat) +static void isp_update_otg(struct isp1301 *isp, u8 stat) { u8 isp_stat, isp_bstat; enum usb_otg_state state = isp->otg.state; @@ -1489,12 +1490,10 @@ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind) if (the_transceiver) return 0; - isp = kmalloc(sizeof *isp, GFP_KERNEL); + isp = kcalloc(1, sizeof *isp, GFP_KERNEL); if (!isp) return 0; - memset(isp, 0, sizeof *isp); - INIT_WORK(&isp->work, isp1301_work, isp); init_timer(&isp->timer); isp->timer.function = isp1301_timer; diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c index 36d84634d70e5e..a285086a7196ee 100644 --- a/drivers/i2c/chips/it87.c +++ b/drivers/i2c/chips/it87.c @@ -624,7 +624,7 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind) /* Reserve the ISA region */ if (is_isa) - if (!request_region(address, IT87_EXTENT, name)) + if (!request_region(address, IT87_EXTENT, it87_driver.name)) goto ERROR0; /* Probe whether there is anything available on this address. Already diff --git a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c index a145346b3ff080..640aa01cd7903d 100644 --- a/drivers/i2c/chips/lm78.c +++ b/drivers/i2c/chips/lm78.c @@ -462,7 +462,7 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind) /* Reserve the ISA region */ if (is_isa) - if (!request_region(address, LM78_EXTENT, "lm78")) { + if (!request_region(address, LM78_EXTENT, lm78_driver.name)) { err = -EBUSY; goto ERROR0; } diff --git a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c index 0d2bf2311e2aa3..ba7c450e8874d6 100644 --- a/drivers/i2c/chips/lm90.c +++ b/drivers/i2c/chips/lm90.c @@ -35,12 +35,13 @@ * Among others, it has a higher accuracy than the LM90, much like the * LM86 does. * - * This driver also supports the MAX6657 and MAX6658, sensor chips made - * by Maxim. These chips are similar to the LM86. Complete datasheet - * can be obtained at Maxim's website at: + * This driver also supports the MAX6657, MAX6658 and MAX6659 sensor + * chips made by Maxim. These chips are similar to the LM86. Complete + * datasheet can be obtained at Maxim's website at: * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578 - * Note that there is no way to differenciate between both chips (but - * no need either). + * Note that there is no easy way to differenciate between the three + * variants. The extra address and features of the MAX6659 are not + * supported by this driver. * * Since the LM90 was the first chipset supported by this driver, most * comments will refer to this chipset, but are actually general and @@ -70,9 +71,11 @@ /* * Addresses to scan - * Address is fully defined internally and cannot be changed. + * Address is fully defined internally and cannot be changed except for + * MAX6659. * LM86, LM89, LM90, LM99, ADM1032, MAX6657 and MAX6658 have address 0x4c. * LM89-1, and LM99-1 have address 0x4d. + * MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported). */ static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END }; @@ -386,8 +389,17 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) } } else if (man_id == 0x4D) { /* Maxim */ - if (address == 0x4C - && (reg_config1 & 0x1F) == 0 + /* + * The Maxim variants do NOT have a chip_id register. + * Reading from that address will return the last read + * value, which in our case is those of the man_id + * register. Likewise, the config1 register seems to + * lack a low nibble, so the value will be those of the + * previous read, so in our case those of the man_id + * register. + */ + if (chip_id == man_id + && (reg_config1 & 0x1F) == (man_id & 0x0F) && reg_convrate <= 0x09) { kind = max6657; } diff --git a/drivers/i2c/chips/pc87360.c b/drivers/i2c/chips/pc87360.c index 3b1c0204a6c2b5..6ae814eaf338f5 100644 --- a/drivers/i2c/chips/pc87360.c +++ b/drivers/i2c/chips/pc87360.c @@ -756,7 +756,8 @@ int pc87360_detect(struct i2c_adapter *adapter, int address, int kind) for (i = 0; i < 3; i++) { if (((data->address[i] = extra_isa[i])) - && !request_region(extra_isa[i], PC87360_EXTENT, "pc87360")) { + && !request_region(extra_isa[i], PC87360_EXTENT, + pc87360_driver.name)) { dev_err(&new_client->dev, "Region 0x%x-0x%x already " "in use!\n", extra_isa[i], extra_isa[i]+PC87360_EXTENT-1); diff --git a/drivers/i2c/chips/smsc47b397.c b/drivers/i2c/chips/smsc47b397.c new file mode 100644 index 00000000000000..aab9f246d7e2a3 --- /dev/null +++ b/drivers/i2c/chips/smsc47b397.c @@ -0,0 +1,353 @@ +/* + smsc47b397.c - Part of lm_sensors, Linux kernel modules + for hardware monitoring + + Supports the SMSC LPC47B397-NC Super-I/O chip. + + Author/Maintainer: Mark M. Hoffman <mhoffman@lightlink.com> + Copyright (C) 2004 Utilitek Systems, Inc. + + derived in part from smsc47m1.c: + Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> + Copyright (C) 2004 Jean Delvare <khali@linux-fr.org> + + 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. +*/ + +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/ioport.h> +#include <linux/i2c.h> +#include <linux/i2c-sensor.h> +#include <linux/init.h> +#include <asm/io.h> + +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; +/* Address is autodetected, there is no default value */ +static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END }; +static struct i2c_force_data forces[] = {{NULL}}; + +enum chips { any_chip, smsc47b397 }; +static struct i2c_address_data addr_data = { + .normal_i2c = normal_i2c, + .normal_isa = normal_isa, + .probe = normal_i2c, /* cheat */ + .ignore = normal_i2c, /* cheat */ + .forces = forces, +}; + +/* Super-I/0 registers and commands */ + +#define REG 0x2e /* The register to read/write */ +#define VAL 0x2f /* The value to read/write */ + +static inline void superio_outb(int reg, int val) +{ + outb(reg, REG); + outb(val, VAL); +} + +static inline int superio_inb(int reg) +{ + outb(reg, REG); + return inb(VAL); +} + +/* select superio logical device */ +static inline void superio_select(int ld) +{ + superio_outb(0x07, ld); +} + +static inline void superio_enter(void) +{ + outb(0x55, REG); +} + +static inline void superio_exit(void) +{ + outb(0xAA, REG); +} + +#define SUPERIO_REG_DEVID 0x20 +#define SUPERIO_REG_DEVREV 0x21 +#define SUPERIO_REG_BASE_MSB 0x60 +#define SUPERIO_REG_BASE_LSB 0x61 +#define SUPERIO_REG_LD8 0x08 + +#define SMSC_EXTENT 0x02 + +/* 0 <= nr <= 3 */ +static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80}; +#define SMSC47B397_REG_TEMP(nr) (smsc47b397_reg_temp[(nr)]) + +/* 0 <= nr <= 3 */ +#define SMSC47B397_REG_FAN_LSB(nr) (0x28 + 2 * (nr)) +#define SMSC47B397_REG_FAN_MSB(nr) (0x29 + 2 * (nr)) + +struct smsc47b397_data { + struct i2c_client client; + struct semaphore lock; + + struct semaphore update_lock; + unsigned long last_updated; /* in jiffies */ + int valid; + + /* register values */ + u16 fan[4]; + u8 temp[4]; +}; + +static int smsc47b397_read_value(struct i2c_client *client, u8 reg) +{ + struct smsc47b397_data *data = i2c_get_clientdata(client); + int res; + + down(&data->lock); + outb(reg, client->addr); + res = inb_p(client->addr + 1); + up(&data->lock); + return res; +} + +static struct smsc47b397_data *smsc47b397_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct smsc47b397_data *data = i2c_get_clientdata(client); + int i; + + down(&data->update_lock); + + if (time_after(jiffies - data->last_updated, (unsigned long)HZ) + || time_before(jiffies, data->last_updated) || !data->valid) { + + dev_dbg(&client->dev, "starting device update...\n"); + + /* 4 temperature inputs, 4 fan inputs */ + for (i = 0; i < 4; i++) { + data->temp[i] = smsc47b397_read_value(client, + SMSC47B397_REG_TEMP(i)); + + /* must read LSB first */ + data->fan[i] = smsc47b397_read_value(client, + SMSC47B397_REG_FAN_LSB(i)); + data->fan[i] |= smsc47b397_read_value(client, + SMSC47B397_REG_FAN_MSB(i)) << 8; + } + + data->last_updated = jiffies; + data->valid = 1; + + dev_dbg(&client->dev, "... device update complete\n"); + } + + up(&data->update_lock); + + return data; +} + +/* TEMP: 0.001C/bit (-128C to +127C) + REG: 1C/bit, two's complement */ +static int temp_from_reg(u8 reg) +{ + return (s8)reg * 1000; +} + +/* 0 <= nr <= 3 */ +static ssize_t show_temp(struct device *dev, char *buf, int nr) +{ + struct smsc47b397_data *data = smsc47b397_update_device(dev); + return sprintf(buf, "%d\n", temp_from_reg(data->temp[nr])); +} + +#define sysfs_temp(num) \ +static ssize_t show_temp##num(struct device *dev, char *buf) \ +{ \ + return show_temp(dev, buf, num-1); \ +} \ +static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL) + +sysfs_temp(1); +sysfs_temp(2); +sysfs_temp(3); +sysfs_temp(4); + +#define device_create_file_temp(client, num) \ + device_create_file(&client->dev, &dev_attr_temp##num##_input) + +/* FAN: 1 RPM/bit + REG: count of 90kHz pulses / revolution */ +static int fan_from_reg(u16 reg) +{ + return 90000 * 60 / reg; +} + +/* 0 <= nr <= 3 */ +static ssize_t show_fan(struct device *dev, char *buf, int nr) +{ + struct smsc47b397_data *data = smsc47b397_update_device(dev); + return sprintf(buf, "%d\n", fan_from_reg(data->fan[nr])); +} + +#define sysfs_fan(num) \ +static ssize_t show_fan##num(struct device *dev, char *buf) \ +{ \ + return show_fan(dev, buf, num-1); \ +} \ +static DEVICE_ATTR(fan##num##_input, S_IRUGO, show_fan##num, NULL) + +sysfs_fan(1); +sysfs_fan(2); +sysfs_fan(3); +sysfs_fan(4); + +#define device_create_file_fan(client, num) \ + device_create_file(&client->dev, &dev_attr_fan##num##_input) + +static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind); + +static int smsc47b397_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_detect(adapter, &addr_data, smsc47b397_detect); +} + +static int smsc47b397_detach_client(struct i2c_client *client) +{ + int err; + + if ((err = i2c_detach_client(client))) { + dev_err(&client->dev, "Client deregistration failed, " + "client not detached.\n"); + return err; + } + + release_region(client->addr, SMSC_EXTENT); + kfree(i2c_get_clientdata(client)); + + return 0; +} + +static struct i2c_driver smsc47b397_driver = { + .owner = THIS_MODULE, + .name = "smsc47b397", + .id = I2C_DRIVERID_SMSC47B397, + .flags = I2C_DF_NOTIFY, + .attach_adapter = smsc47b397_attach_adapter, + .detach_client = smsc47b397_detach_client, +}; + +static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind) +{ + struct i2c_client *new_client; + struct smsc47b397_data *data; + int err = 0; + + if (!i2c_is_isa_adapter(adapter)) { + return 0; + } + + if (!request_region(addr, SMSC_EXTENT, smsc47b397_driver.name)) { + dev_err(&adapter->dev, "Region 0x%x already in use!\n", addr); + return -EBUSY; + } + + if (!(data = kmalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) { + err = -ENOMEM; + goto error_release; + } + memset(data, 0x00, sizeof(struct smsc47b397_data)); + + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = addr; + init_MUTEX(&data->lock); + new_client->adapter = adapter; + new_client->driver = &smsc47b397_driver; + new_client->flags = 0; + + strlcpy(new_client->name, "smsc47b397", I2C_NAME_SIZE); + + init_MUTEX(&data->update_lock); + + if ((err = i2c_attach_client(new_client))) + goto error_free; + + device_create_file_temp(new_client, 1); + device_create_file_temp(new_client, 2); + device_create_file_temp(new_client, 3); + device_create_file_temp(new_client, 4); + + device_create_file_fan(new_client, 1); + device_create_file_fan(new_client, 2); + device_create_file_fan(new_client, 3); + device_create_file_fan(new_client, 4); + + return 0; + +error_free: + kfree(new_client); +error_release: + release_region(addr, SMSC_EXTENT); + return err; +} + +static int __init smsc47b397_find(unsigned int *addr) +{ + u8 id, rev; + + superio_enter(); + id = superio_inb(SUPERIO_REG_DEVID); + + if (id != 0x6f) { + superio_exit(); + return -ENODEV; + } + + rev = superio_inb(SUPERIO_REG_DEVREV); + + superio_select(SUPERIO_REG_LD8); + *addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8) + | superio_inb(SUPERIO_REG_BASE_LSB); + + printk(KERN_INFO "smsc47b397: found SMSC LPC47B397-NC " + "(base address 0x%04x, revision %u)\n", *addr, rev); + + superio_exit(); + return 0; +} + +static int __init smsc47b397_init(void) +{ + int ret; + + if ((ret = smsc47b397_find(normal_isa))) + return ret; + + return i2c_add_driver(&smsc47b397_driver); +} + +static void __exit smsc47b397_exit(void) +{ + i2c_del_driver(&smsc47b397_driver); +} + +MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>"); +MODULE_DESCRIPTION("SMSC LPC47B397 driver"); +MODULE_LICENSE("GPL"); + +module_init(smsc47b397_init); +module_exit(smsc47b397_exit); diff --git a/drivers/i2c/chips/smsc47m1.c b/drivers/i2c/chips/smsc47m1.c index 39c6871bdf1636..c9f0d2b5c967ac 100644 --- a/drivers/i2c/chips/smsc47m1.c +++ b/drivers/i2c/chips/smsc47m1.c @@ -400,7 +400,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind) return 0; } - if (!request_region(address, SMSC_EXTENT, "smsc47m1")) { + if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) { dev_err(&adapter->dev, "Region 0x%x already in use!\n", address); return -EBUSY; } diff --git a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c index d4938fa32ac914..f2e889702c56be 100644 --- a/drivers/i2c/chips/via686a.c +++ b/drivers/i2c/chips/via686a.c @@ -613,7 +613,7 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind) } /* Reserve the ISA region */ - if (!request_region(address, VIA686A_EXTENT, "via686a-sensor")) { + if (!request_region(address, VIA686A_EXTENT, via686a_driver.name)) { dev_err(&adapter->dev,"region 0x%x already in use!\n", address); return -ENODEV; diff --git a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c index cf9e88749ec8d0..697cd438237749 100644 --- a/drivers/i2c/chips/w83627hf.c +++ b/drivers/i2c/chips/w83627hf.c @@ -67,9 +67,9 @@ module_param(init, bool, 0); MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); /* modified from kernel/include/traps.c */ -#define REG 0x2e /* The register to read/write */ +static int REG; /* The register to read/write */ #define DEV 0x07 /* Register: Logical device select */ -#define VAL 0x2f /* The value to read/write */ +static int VAL; /* The value to read/write */ /* logical device numbers for superio_select (below) */ #define W83627HF_LD_FDC 0x00 @@ -90,9 +90,9 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); #define DEVID 0x20 /* Register: Device ID */ +#define W83627THF_GPIO5_EN 0x30 /* w83627thf only */ #define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */ #define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */ -#define W83627THF_GPIO5_INVR 0xf5 /* w83627thf only */ static inline void superio_outb(int reg, int val) @@ -938,10 +938,13 @@ static int w83627hf_attach_adapter(struct i2c_adapter *adapter) return i2c_detect(adapter, &addr_data, w83627hf_detect); } -static int w83627hf_find(int *address) +static int w83627hf_find(int sioaddr, int *address) { u16 val; + REG = sioaddr; + VAL = sioaddr + 1; + superio_enter(); val= superio_inb(DEVID); if(val != W627_DEVID && @@ -984,7 +987,7 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address, if(force_addr) address = force_addr & ~(WINB_EXTENT - 1); - if (!request_region(address, WINB_EXTENT, "w83627hf")) { + if (!request_region(address, WINB_EXTENT, w83627hf_driver.name)) { err = -EBUSY; goto ERROR0; } @@ -1187,16 +1190,31 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg) static int w83627thf_read_gpio5(struct i2c_client *client) { - struct w83627hf_data *data = i2c_get_clientdata(client); - int res, inv; + int res = 0xff, sel; - down(&data->lock); superio_enter(); superio_select(W83627HF_LD_GPIO5); - res = superio_inb(W83627THF_GPIO5_DR); - inv = superio_inb(W83627THF_GPIO5_INVR); + + /* Make sure these GPIO pins are enabled */ + if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) { + dev_dbg(&client->dev, "GPIO5 disabled, no VID function\n"); + goto exit; + } + + /* Make sure the pins are configured for input + There must be at least five (VRM 9), and possibly 6 (VRM 10) */ + sel = superio_inb(W83627THF_GPIO5_IOSR); + if ((sel & 0x1f) != 0x1f) { + dev_dbg(&client->dev, "GPIO5 not configured for VID " + "function\n"); + goto exit; + } + + dev_info(&client->dev, "Reading VID from GPIO5\n"); + res = superio_inb(W83627THF_GPIO5_DR) & sel; + +exit: superio_exit(); - up(&data->lock); return res; } @@ -1269,7 +1287,7 @@ static void w83627hf_init_client(struct i2c_client *client) int hi = w83627hf_read_value(client, W83781D_REG_CHIPID); data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); } else if (w83627thf == data->type) { - data->vid = w83627thf_read_gpio5(client) & 0x1f; + data->vid = w83627thf_read_gpio5(client) & 0x3f; } /* Read VRM & OVT Config only once */ @@ -1422,7 +1440,8 @@ static int __init sensors_w83627hf_init(void) { int addr; - if (w83627hf_find(&addr)) { + if (w83627hf_find(0x2e, &addr) + && w83627hf_find(0x4e, &addr)) { return -ENODEV; } normal_isa[0] = addr; diff --git a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c index 3a44fe9e54362e..35c523e4b30bc1 100644 --- a/drivers/i2c/chips/w83781d.c +++ b/drivers/i2c/chips/w83781d.c @@ -1065,7 +1065,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) } if (is_isa) - if (!request_region(address, W83781D_EXTENT, "w83781d")) { + if (!request_region(address, W83781D_EXTENT, + w83781d_driver.name)) { dev_dbg(&adapter->dev, "Request of region " "0x%x-0x%x for w83781d failed\n", address, address + W83781D_EXTENT - 1); diff --git a/drivers/i2c/i2c-sensor-vid.c b/drivers/i2c/i2c-sensor-vid.c index 017dcc5c6bf8b2..922e22f054bb28 100644 --- a/drivers/i2c/i2c-sensor-vid.c +++ b/drivers/i2c/i2c-sensor-vid.c @@ -36,8 +36,7 @@ struct vrm_model { static struct vrm_model vrm_models[] = { {X86_VENDOR_AMD, 0x6, ANY, 90}, /* Athlon Duron etc */ - {X86_VENDOR_AMD, 0xF, 0x4, 90}, /* Athlon 64 */ - {X86_VENDOR_AMD, 0xF, 0x5, 24}, /* Opteron */ + {X86_VENDOR_AMD, 0xF, ANY, 24}, /* Athlon 64, Opteron */ {X86_VENDOR_INTEL, 0x6, 0x9, 85}, /* 0.13um too */ {X86_VENDOR_INTEL, 0x6, 0xB, 85}, /* 0xB Tualatin */ {X86_VENDOR_INTEL, 0x6, ANY, 82}, /* any P6 */ @@ -87,7 +86,7 @@ int i2c_which_vrm(void) return vrm_ret; } -/* and now something completely different for Non-x86 world*/ +/* and now for something completely different for Non-x86 world*/ #else int i2c_which_vrm(void) { |