diff options
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r-- | drivers/i2c/busses/Kconfig | 11 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-ali1535.c | 4 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-amd756-s4882.c | 13 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-frodo.c | 85 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-iop3xx.c | 9 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-isa.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-ite.c | 4 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-ixp4xx.c | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mpc.c | 5 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mv64xxx.c | 4 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-piix4.c | 4 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-pxa.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/scx200_acb.c | 283 |
13 files changed, 175 insertions, 252 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index ff92735c7c8..089c6f5b24d 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -168,12 +168,14 @@ config I2C_PIIX4 help If you say yes to this option, support will be included for the Intel PIIX4 family of mainboard I2C interfaces. Specifically, the following - versions of the chipset are supported: + versions of the chipset are supported (note that Serverworks is part + of Broadcom): Intel PIIX4 Intel 440MX Serverworks OSB4 Serverworks CSB5 Serverworks CSB6 + Serverworks HT-1000 SMSC Victory66 This driver can also be built as a module. If so, the module @@ -389,10 +391,11 @@ config SCx200_I2C_SDA also be specified with a module parameter. config SCx200_ACB - tristate "NatSemi SCx200 ACCESS.bus" - depends on I2C && PCI + tristate "Geode ACCESS.bus support" + depends on X86_32 && I2C && PCI help - Enable the use of the ACCESS.bus controllers of a SCx200 processor. + Enable the use of the ACCESS.bus controllers on the Geode SCx200 and + SC1100 processors and the CS5535 and CS5536 Geode companion devices. If you don't know what to do here, say N. diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 3eb47890db4..d3ef46aeeb3 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -63,7 +63,6 @@ #include <linux/i2c.h> #include <linux/init.h> #include <asm/io.h> -#include <asm/semaphore.h> /* ALI1535 SMBus address offsets */ @@ -136,7 +135,6 @@ static struct pci_driver ali1535_driver; static unsigned short ali1535_smba; -static DECLARE_MUTEX(i2c_ali1535_sem); /* Detect whether a ALI1535 can be found, and initialize it, where necessary. Note the differences between kernels with the old PCI BIOS interface and @@ -345,7 +343,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, int timeout; s32 result = 0; - down(&i2c_ali1535_sem); /* make sure SMBus is idle */ temp = inb_p(SMBHSTSTS); for (timeout = 0; @@ -460,7 +457,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, break; } EXIT: - up(&i2c_ali1535_sem); return result; } diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c index 56c7d987590..08e915730ca 100644 --- a/drivers/i2c/busses/i2c-amd756-s4882.c +++ b/drivers/i2c/busses/i2c-amd756-s4882.c @@ -38,6 +38,7 @@ #include <linux/slab.h> #include <linux/init.h> #include <linux/i2c.h> +#include <linux/mutex.h> extern struct i2c_adapter amd756_smbus; @@ -45,7 +46,7 @@ static struct i2c_adapter *s4882_adapter; static struct i2c_algorithm *s4882_algo; /* Wrapper access functions for multiplexed SMBus */ -static struct semaphore amd756_lock; +static DEFINE_MUTEX(amd756_lock); static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, @@ -59,12 +60,12 @@ static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, || addr == 0x18) return -1; - down(&amd756_lock); + mutex_lock(&amd756_lock); error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write, command, size, data); - up(&amd756_lock); + mutex_unlock(&amd756_lock); return error; } @@ -87,7 +88,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr, if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) return -1; - down(&amd756_lock); + mutex_lock(&amd756_lock); if (last_channels != channels) { union i2c_smbus_data mplxdata; @@ -105,7 +106,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr, command, size, data); UNLOCK: - up(&amd756_lock); + mutex_unlock(&amd756_lock); return error; } @@ -166,8 +167,6 @@ static int __init amd756_s4882_init(void) } printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n"); - init_MUTEX(&amd756_lock); - /* Define the 5 virtual adapters and algorithms structures */ if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter), GFP_KERNEL))) { diff --git a/drivers/i2c/busses/i2c-frodo.c b/drivers/i2c/busses/i2c-frodo.c deleted file mode 100644 index b6f52f5a413..00000000000 --- a/drivers/i2c/busses/i2c-frodo.c +++ /dev/null @@ -1,85 +0,0 @@ - -/* - * linux/drivers/i2c/i2c-frodo.c - * - * Author: Abraham van der Merwe <abraham@2d3d.co.za> - * - * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110 - * Development board (Frodo). - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <asm/hardware.h> - - -static void frodo_setsda (void *data,int state) -{ - if (state) - FRODO_CPLD_I2C |= FRODO_I2C_SDA_OUT; - else - FRODO_CPLD_I2C &= ~FRODO_I2C_SDA_OUT; -} - -static void frodo_setscl (void *data,int state) -{ - if (state) - FRODO_CPLD_I2C |= FRODO_I2C_SCL_OUT; - else - FRODO_CPLD_I2C &= ~FRODO_I2C_SCL_OUT; -} - -static int frodo_getsda (void *data) -{ - return ((FRODO_CPLD_I2C & FRODO_I2C_SDA_IN) != 0); -} - -static int frodo_getscl (void *data) -{ - return ((FRODO_CPLD_I2C & FRODO_I2C_SCL_IN) != 0); -} - -static struct i2c_algo_bit_data bit_frodo_data = { - .setsda = frodo_setsda, - .setscl = frodo_setscl, - .getsda = frodo_getsda, - .getscl = frodo_getscl, - .udelay = 80, - .mdelay = 80, - .timeout = HZ -}; - -static struct i2c_adapter frodo_ops = { - .owner = THIS_MODULE, - .id = I2C_HW_B_FRODO, - .algo_data = &bit_frodo_data, - .dev = { - .name = "Frodo adapter driver", - }, -}; - -static int __init i2c_frodo_init (void) -{ - return i2c_bit_add_bus(&frodo_ops); -} - -static void __exit i2c_frodo_exit (void) -{ - i2c_bit_del_bus(&frodo_ops); -} - -MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>"); -MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo"); -MODULE_LICENSE ("GPL"); - -module_init (i2c_frodo_init); -module_exit (i2c_frodo_exit); - diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index 1414851a17b..d00a02fc23e 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -434,7 +434,7 @@ static int iop3xx_i2c_probe(struct platform_device *pdev) { struct resource *res; - int ret; + int ret, irq; struct i2c_adapter *new_adapter; struct i2c_algo_iop3xx_data *adapter_data; @@ -470,7 +470,12 @@ iop3xx_i2c_probe(struct platform_device *pdev) goto release_region; } - ret = request_irq(platform_get_irq(pdev, 0), iop3xx_i2c_irq_handler, 0, + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + ret = -ENXIO; + goto unmap; + } + ret = request_irq(irq, iop3xx_i2c_irq_handler, 0, pdev->name, adapter_data); if (ret) { diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c index 4344ae6b1fc..c3e1d3e888d 100644 --- a/drivers/i2c/busses/i2c-isa.c +++ b/drivers/i2c/busses/i2c-isa.c @@ -125,7 +125,7 @@ int i2c_isa_del_driver(struct i2c_driver *driver) static int __init i2c_isa_init(void) { - init_MUTEX(&isa_adapter.clist_lock); + mutex_init(&isa_adapter.clist_lock); INIT_LIST_HEAD(&isa_adapter.clients); isa_adapter.nr = ANY_I2C_ISA_BUS; diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c index 5f5d2944808..d82e6dae840 100644 --- a/drivers/i2c/busses/i2c-ite.c +++ b/drivers/i2c/busses/i2c-ite.c @@ -200,9 +200,7 @@ static struct i2c_adapter iic_ite_ops = { .owner = THIS_MODULE, .id = I2C_HW_I_IIC, .algo_data = &iic_ite_data, - .dev = { - .name = "ITE IIC adapter", - }, + .name = "ITE IIC adapter", }; /* Called when the module is loaded. This function starts the diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c index e422d8b2d4d..2ed07112d68 100644 --- a/drivers/i2c/busses/i2c-ixp4xx.c +++ b/drivers/i2c/busses/i2c-ixp4xx.c @@ -126,6 +126,7 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev) drv_data->algo_data.timeout = 100; drv_data->adapter.id = I2C_HW_B_IXP4XX; + drv_data->adapter.class = I2C_CLASS_HWMON; strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, I2C_NAME_SIZE); drv_data->adapter.algo_data = &drv_data->algo_data; diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 5ccd338a9dc..2721e4c8184 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -302,6 +302,10 @@ static int fsl_i2c_probe(struct platform_device *pdev) } i2c->irq = platform_get_irq(pdev, 0); + if (i2c->irq < 0) { + result = -ENXIO; + goto fail_get_irq; + } i2c->flags = pdata->device_flags; init_waitqueue_head(&i2c->queue); @@ -340,6 +344,7 @@ static int fsl_i2c_probe(struct platform_device *pdev) fail_irq: iounmap(i2c->base); fail_map: + fail_get_irq: kfree(i2c); return result; }; diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 22781d84f79..ac5cde1bbd2 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -516,6 +516,10 @@ mv64xxx_i2c_probe(struct platform_device *pd) drv_data->freq_m = pdata->freq_m; drv_data->freq_n = pdata->freq_n; drv_data->irq = platform_get_irq(pd, 0); + if (drv_data->irq < 0) { + rc = -ENXIO; + goto exit_unmap_regs; + } drv_data->adapter.id = I2C_HW_MV64XXX; drv_data->adapter.algo = &mv64xxx_i2c_algo; drv_data->adapter.owner = THIS_MODULE; diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 692f4734548..d9c7c00e71f 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -22,7 +22,7 @@ /* Supports: Intel PIIX4, 440MX - Serverworks OSB4, CSB5, CSB6 + Serverworks OSB4, CSB5, CSB6, HT-1000 SMSC Victory66 Note: we assume there can only be one device, with one SMBus interface. @@ -419,6 +419,8 @@ static struct pci_device_id piix4_ids[] = { .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6), .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB), + .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), diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 7579f4b256a..5155010b455 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -647,7 +647,7 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c) } /* - * We are protected by the adapter bus semaphore. + * We are protected by the adapter bus mutex. */ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) { diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index d3478e08452..8bd305e47f0 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -1,27 +1,26 @@ -/* linux/drivers/i2c/scx200_acb.c - +/* Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> National Semiconductor SCx200 ACCESS.bus support - + Also supports the AMD CS5535 and AMD CS5536 + Based on i2c-keywest.c which is: Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org> Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.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; 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> @@ -32,7 +31,9 @@ #include <linux/smp_lock.h> #include <linux/pci.h> #include <linux/delay.h> +#include <linux/mutex.h> #include <asm/io.h> +#include <asm/msr.h> #include <linux/scx200.h> @@ -47,16 +48,7 @@ static int base[MAX_DEVICES] = { 0x820, 0x840 }; module_param_array(base, int, NULL, 0); MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers"); -#ifdef DEBUG -#define DBG(x...) printk(KERN_DEBUG NAME ": " x) -#else -#define DBG(x...) -#endif - -/* The hardware supports interrupt driven mode too, but I haven't - implemented that. */ -#define POLLED_MODE 1 -#define POLL_TIMEOUT (HZ) +#define POLL_TIMEOUT (HZ/5) enum scx200_acb_state { state_idle, @@ -79,12 +71,11 @@ static const char *scx200_acb_state_name[] = { }; /* Physical interface */ -struct scx200_acb_iface -{ +struct scx200_acb_iface { struct scx200_acb_iface *next; struct i2c_adapter adapter; unsigned base; - struct semaphore sem; + struct mutex mutex; /* State machine data */ enum scx200_acb_state state; @@ -100,7 +91,7 @@ struct scx200_acb_iface #define ACBSDA (iface->base + 0) #define ACBST (iface->base + 1) #define ACBST_SDAST 0x40 /* SDA Status */ -#define ACBST_BER 0x20 +#define ACBST_BER 0x20 #define ACBST_NEGACK 0x10 /* Negative Acknowledge */ #define ACBST_STASTR 0x08 /* Stall After Start */ #define ACBST_MASTER 0x02 @@ -109,9 +100,9 @@ struct scx200_acb_iface #define ACBCTL1 (iface->base + 3) #define ACBCTL1_STASTRE 0x80 #define ACBCTL1_NMINTE 0x40 -#define ACBCTL1_ACK 0x10 -#define ACBCTL1_STOP 0x02 -#define ACBCTL1_START 0x01 +#define ACBCTL1_ACK 0x10 +#define ACBCTL1_STOP 0x02 +#define ACBCTL1_START 0x01 #define ACBADDR (iface->base + 4) #define ACBCTL2 (iface->base + 5) #define ACBCTL2_ENABLE 0x01 @@ -122,8 +113,8 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) { const char *errmsg; - DBG("state %s, status = 0x%02x\n", - scx200_acb_state_name[iface->state], status); + dev_dbg(&iface->adapter.dev, "state %s, status = 0x%02x\n", + scx200_acb_state_name[iface->state], status); if (status & ACBST_BER) { errmsg = "bus error"; @@ -133,8 +124,17 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) errmsg = "not master"; goto error; } - if (status & ACBST_NEGACK) - goto negack; + if (status & ACBST_NEGACK) { + dev_dbg(&iface->adapter.dev, "negative ack in state %s\n", + scx200_acb_state_name[iface->state]); + + iface->state = state_idle; + iface->result = -ENXIO; + + outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); + outb(ACBST_STASTR | ACBST_NEGACK, ACBST); + return; + } switch (iface->state) { case state_idle: @@ -160,10 +160,10 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) case state_repeat_start: outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); /* fallthrough */ - + case state_quick: if (iface->address_byte & 1) { - if (iface->len == 1) + if (iface->len == 1) outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); else outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); @@ -202,26 +202,15 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); break; } - + outb(*iface->ptr++, ACBSDA); --iface->len; - + break; } return; - negack: - DBG("negative acknowledge in state %s\n", - scx200_acb_state_name[iface->state]); - - iface->state = state_idle; - iface->result = -ENXIO; - - outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); - outb(ACBST_STASTR | ACBST_NEGACK, ACBST); - return; - error: dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg, scx200_acb_state_name[iface->state]); @@ -231,20 +220,9 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) iface->needs_reset = 1; } -static void scx200_acb_timeout(struct scx200_acb_iface *iface) -{ - dev_err(&iface->adapter.dev, "timeout in state %s\n", - scx200_acb_state_name[iface->state]); - - iface->state = state_idle; - iface->result = -EIO; - iface->needs_reset = 1; -} - -#ifdef POLLED_MODE static void scx200_acb_poll(struct scx200_acb_iface *iface) { - u8 status = 0; + u8 status; unsigned long timeout; timeout = jiffies + POLL_TIMEOUT; @@ -254,17 +232,21 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) scx200_acb_machine(iface, status); return; } - msleep(10); + yield(); } - scx200_acb_timeout(iface); + dev_err(&iface->adapter.dev, "timeout in state %s\n", + scx200_acb_state_name[iface->state]); + + iface->state = state_idle; + iface->result = -EIO; + iface->needs_reset = 1; } -#endif /* POLLED_MODE */ static void scx200_acb_reset(struct scx200_acb_iface *iface) { /* Disable the ACCESS.bus device and Configure the SCL - frequency: 16 clock cycles */ + frequency: 16 clock cycles */ outb(0x70, ACBCTL2); /* Polling mode */ outb(0, ACBCTL1); @@ -283,9 +265,9 @@ static void scx200_acb_reset(struct scx200_acb_iface *iface) } static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, - u16 address, unsigned short flags, - char rw, u8 command, int size, - union i2c_smbus_data *data) + u16 address, unsigned short flags, + char rw, u8 command, int size, + union i2c_smbus_data *data) { struct scx200_acb_iface *iface = i2c_get_adapdata(adapter); int len; @@ -295,53 +277,47 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, switch (size) { case I2C_SMBUS_QUICK: - len = 0; - buffer = NULL; - break; + len = 0; + buffer = NULL; + break; + case I2C_SMBUS_BYTE: - if (rw == I2C_SMBUS_READ) { - len = 1; - buffer = &data->byte; - } else { - len = 1; - buffer = &command; - } - break; + len = 1; + buffer = rw ? &data->byte : &command; + break; + case I2C_SMBUS_BYTE_DATA: - len = 1; - buffer = &data->byte; - break; + len = 1; + buffer = &data->byte; + break; + case I2C_SMBUS_WORD_DATA: len = 2; - cur_word = cpu_to_le16(data->word); - buffer = (u8 *)&cur_word; + cur_word = cpu_to_le16(data->word); + buffer = (u8 *)&cur_word; break; + case I2C_SMBUS_BLOCK_DATA: - len = data->block[0]; - buffer = &data->block[1]; + len = data->block[0]; + buffer = &data->block[1]; break; + default: - return -EINVAL; + return -EINVAL; } - DBG("size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", - size, address, command, len, rw == I2C_SMBUS_READ); + dev_dbg(&adapter->dev, + "size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", + size, address, command, len, rw); if (!len && rw == I2C_SMBUS_READ) { - dev_warn(&adapter->dev, "zero length read\n"); + dev_dbg(&adapter->dev, "zero length read\n"); return -EINVAL; } - if (len && !buffer) { - dev_warn(&adapter->dev, "nonzero length but no buffer\n"); - return -EFAULT; - } - - down(&iface->sem); + mutex_lock(&iface->mutex); - iface->address_byte = address<<1; - if (rw == I2C_SMBUS_READ) - iface->address_byte |= 1; + iface->address_byte = (address << 1) | rw; iface->command = command; iface->ptr = buffer; iface->len = len; @@ -355,25 +331,21 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, else iface->state = state_address; -#ifdef POLLED_MODE while (iface->state != state_idle) scx200_acb_poll(iface); -#else /* POLLED_MODE */ -#error Interrupt driven mode not implemented -#endif /* POLLED_MODE */ if (iface->needs_reset) scx200_acb_reset(iface); rc = iface->result; - up(&iface->sem); + mutex_unlock(&iface->mutex); if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ) - data->word = le16_to_cpu(cur_word); + data->word = le16_to_cpu(cur_word); #ifdef DEBUG - DBG(": transfer done, result: %d", rc); + dev_dbg(&adapter->dev, "transfer done, result: %d", rc); if (buffer) { int i; printk(" data:"); @@ -400,17 +372,18 @@ static struct i2c_algorithm scx200_acb_algorithm = { }; static struct scx200_acb_iface *scx200_acb_list; +static DECLARE_MUTEX(scx200_acb_list_mutex); static int scx200_acb_probe(struct scx200_acb_iface *iface) { u8 val; /* Disable the ACCESS.bus device and Configure the SCL - frequency: 16 clock cycles */ + frequency: 16 clock cycles */ outb(0x70, ACBCTL2); if (inb(ACBCTL2) != 0x70) { - DBG("ACBCTL2 readback failed\n"); + pr_debug(NAME ": ACBCTL2 readback failed\n"); return -ENXIO; } @@ -418,7 +391,8 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface) val = inb(ACBCTL1); if (val) { - DBG("disabled, but ACBCTL1=0x%02x\n", val); + pr_debug(NAME ": disabled, but ACBCTL1=0x%02x\n", + val); return -ENXIO; } @@ -428,18 +402,19 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface) val = inb(ACBCTL1); if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) { - DBG("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n", val); + pr_debug(NAME ": enabled, but NMINTE won't be set, " + "ACBCTL1=0x%02x\n", val); return -ENXIO; } return 0; } -static int __init scx200_acb_create(int base, int index) +static int __init scx200_acb_create(const char *text, int base, int index) { struct scx200_acb_iface *iface; struct i2c_adapter *adapter; - int rc = 0; + int rc; char description[64]; iface = kzalloc(sizeof(*iface), GFP_KERNEL); @@ -451,50 +426,51 @@ static int __init scx200_acb_create(int base, int index) adapter = &iface->adapter; i2c_set_adapdata(adapter, iface); - snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index); + snprintf(adapter->name, I2C_NAME_SIZE, "%s ACB%d", text, index); adapter->owner = THIS_MODULE; adapter->id = I2C_HW_SMBUS_SCX200; adapter->algo = &scx200_acb_algorithm; adapter->class = I2C_CLASS_HWMON; - init_MUTEX(&iface->sem); + mutex_init(&iface->mutex); + + snprintf(description, sizeof(description), "%s ACCESS.bus [%s]", + text, adapter->name); - snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->name); if (request_region(base, 8, description) == 0) { - dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n", + printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n", base, base + 8-1); rc = -EBUSY; - goto errout; + goto errout_free; } iface->base = base; rc = scx200_acb_probe(iface); if (rc) { - dev_warn(&adapter->dev, "probe failed\n"); - goto errout; + printk(KERN_WARNING NAME ": probe failed\n"); + goto errout_release; } scx200_acb_reset(iface); if (i2c_add_adapter(adapter) < 0) { - dev_err(&adapter->dev, "failed to register\n"); + printk(KERN_ERR NAME ": failed to register\n"); rc = -ENODEV; - goto errout; + goto errout_release; } - lock_kernel(); + down(&scx200_acb_list_mutex); iface->next = scx200_acb_list; scx200_acb_list = iface; - unlock_kernel(); + up(&scx200_acb_list_mutex); return 0; + errout_release: + release_region(iface->base, 8); + errout_free: + kfree(iface); errout: - if (iface) { - if (iface->base) - release_region(iface->base, 8); - kfree(iface); - } return rc; } @@ -504,50 +480,69 @@ static struct pci_device_id scx200[] = { { }, }; +static struct pci_device_id divil_pci[] = { + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, + { } /* NULL entry */ +}; + +#define MSR_LBAR_SMB 0x5140000B + +static int scx200_add_cs553x(void) +{ + u32 low, hi; + u32 smb_base; + + /* Grab & reserve the SMB I/O range */ + rdmsr(MSR_LBAR_SMB, low, hi); + + /* Check the IO mask and whether SMB is enabled */ + if (hi != 0x0000F001) { + printk(KERN_WARNING NAME ": SMBus not enabled\n"); + return -ENODEV; + } + + /* SMBus IO size is 8 bytes */ + smb_base = low & 0x0000FFF8; + + return scx200_acb_create("CS5535", smb_base, 0); +} + static int __init scx200_acb_init(void) { int i; - int rc; + int rc = -ENODEV; pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); /* Verify that this really is a SCx200 processor */ - if (pci_dev_present(scx200) == 0) - return -ENODEV; + if (pci_dev_present(scx200)) { + for (i = 0; i < MAX_DEVICES; ++i) { + if (base[i] > 0) + rc = scx200_acb_create("SCx200", base[i], i); + } + } else if (pci_dev_present(divil_pci)) + rc = scx200_add_cs553x(); - rc = -ENXIO; - for (i = 0; i < MAX_DEVICES; ++i) { - if (base[i] > 0) - rc = scx200_acb_create(base[i], i); - } - if (scx200_acb_list) - return 0; return rc; } static void __exit scx200_acb_cleanup(void) { struct scx200_acb_iface *iface; - lock_kernel(); + + down(&scx200_acb_list_mutex); while ((iface = scx200_acb_list) != NULL) { scx200_acb_list = iface->next; - unlock_kernel(); + up(&scx200_acb_list_mutex); i2c_del_adapter(&iface->adapter); release_region(iface->base, 8); kfree(iface); - lock_kernel(); + down(&scx200_acb_list_mutex); } - unlock_kernel(); + up(&scx200_acb_list_mutex); } module_init(scx200_acb_init); module_exit(scx200_acb_cleanup); - -/* - Local variables: - compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules" - c-basic-offset: 8 - End: -*/ - |