diff options
Diffstat (limited to 'drivers/i2c/busses')
47 files changed, 438 insertions, 258 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 9c6170cd9aa..87ab0568bb0 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -564,7 +564,7 @@ config I2C_STU300 config I2C_VERSATILE tristate "ARM Versatile/Realview I2C bus support" - depends on ARCH_VERSATILE || ARCH_REALVIEW + depends on ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS select I2C_ALGOBIT help Say yes if you want to support the I2C serial bus on ARMs Versatile diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index bd8f1e4d9e6..906a3ca50db 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -60,7 +60,7 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/acpi.h> -#include <asm/io.h> +#include <linux/io.h> /* ALI1535 SMBus address offsets */ diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 659f63f5e4a..b14f6d68221 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -67,7 +67,7 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/acpi.h> -#include <asm/io.h> +#include <linux/io.h> /* ALI15X3 SMBus address offsets */ #define SMBHSTSTS (0 + ali15x3_smba) diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index c5a9fa488e7..03bcd07c469 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c @@ -43,7 +43,7 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/acpi.h> -#include <asm/io.h> +#include <linux/io.h> /* AMD756 SMBus address offsets */ #define SMB_ADDR_OFFSET 0xE0 diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index 2fbef27b6cd..af1e5e254b7 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c @@ -18,7 +18,7 @@ #include <linux/delay.h> #include <linux/acpi.h> #include <linux/slab.h> -#include <asm/io.h> +#include <linux/io.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR ("Vojtech Pavlik <vojtech@suse.cz>"); diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 06e1ecb4919..305c07504f7 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -23,8 +23,7 @@ #include <linux/init.h> #include <linux/clk.h> #include <linux/platform_device.h> - -#include <asm/io.h> +#include <linux/io.h> #include <mach/at91_twi.h> #include <mach/board.h> diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index f1e14dd590c..fb26e5c6751 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -25,8 +25,6 @@ #include <asm/portmux.h> #include <asm/irq.h> -#define POLL_TIMEOUT (2 * HZ) - /* SMBus mode*/ #define TWI_I2C_MODE_STANDARD 1 #define TWI_I2C_MODE_STANDARDSUB 2 @@ -44,8 +42,6 @@ struct bfin_twi_iface { int cur_mode; int manual_stop; int result; - int timeout_count; - struct timer_list timeout_timer; struct i2c_adapter adap; struct completion complete; struct i2c_msg *pmsg; @@ -85,14 +81,15 @@ static const u16 pin_req[2][3] = { {P_TWI1_SCL, P_TWI1_SDA, 0}, }; -static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) +static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface, + unsigned short twi_int_status) { - unsigned short twi_int_status = read_INT_STAT(iface); unsigned short mast_stat = read_MASTER_STAT(iface); if (twi_int_status & XMTSERV) { /* Transmit next data */ if (iface->writeNum > 0) { + SSYNC(); write_XMT_DATA8(iface, *(iface->transPtr++)); iface->writeNum--; } @@ -114,10 +111,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) write_MASTER_CTL(iface, (read_MASTER_CTL(iface) | RSTART) & ~MDIR); } - SSYNC(); - /* Clear status */ - write_INT_STAT(iface, XMTSERV); - SSYNC(); } if (twi_int_status & RCVSERV) { if (iface->readNum > 0) { @@ -139,7 +132,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) } else if (iface->manual_stop) { write_MASTER_CTL(iface, read_MASTER_CTL(iface) | STOP); - SSYNC(); } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && iface->cur_msg + 1 < iface->msg_num) { if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) @@ -148,44 +140,37 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) else write_MASTER_CTL(iface, (read_MASTER_CTL(iface) | RSTART) & ~MDIR); - SSYNC(); } - /* Clear interrupt source */ - write_INT_STAT(iface, RCVSERV); - SSYNC(); } if (twi_int_status & MERR) { - write_INT_STAT(iface, MERR); write_INT_MASK(iface, 0); write_MASTER_STAT(iface, 0x3e); write_MASTER_CTL(iface, 0); - SSYNC(); iface->result = -EIO; - /* if both err and complete int stats are set, return proper - * results. + + if (mast_stat & LOSTARB) + dev_dbg(&iface->adap.dev, "Lost Arbitration\n"); + if (mast_stat & ANAK) + dev_dbg(&iface->adap.dev, "Address Not Acknowledged\n"); + if (mast_stat & DNAK) + dev_dbg(&iface->adap.dev, "Data Not Acknowledged\n"); + if (mast_stat & BUFRDERR) + dev_dbg(&iface->adap.dev, "Buffer Read Error\n"); + if (mast_stat & BUFWRERR) + dev_dbg(&iface->adap.dev, "Buffer Write Error\n"); + + /* If it is a quick transfer, only address without data, + * not an err, return 1. */ - if (twi_int_status & MCOMP) { - write_INT_STAT(iface, MCOMP); - write_INT_MASK(iface, 0); - write_MASTER_CTL(iface, 0); - SSYNC(); - /* If it is a quick transfer, only address bug no data, - * not an err, return 1. - */ - if (iface->writeNum == 0 && (mast_stat & BUFRDERR)) - iface->result = 1; - /* If address not acknowledged return -1, - * else return 0. - */ - else if (!(mast_stat & ANAK)) - iface->result = 0; - } + if (iface->cur_mode == TWI_I2C_MODE_STANDARD && + iface->transPtr == NULL && + (twi_int_status & MCOMP) && (mast_stat & DNAK)) + iface->result = 1; + complete(&iface->complete); return; } if (twi_int_status & MCOMP) { - write_INT_STAT(iface, MCOMP); - SSYNC(); if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { if (iface->readNum == 0) { /* set the read number to 1 and ask for manual @@ -207,7 +192,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) /* remove restart bit and enable master receive */ write_MASTER_CTL(iface, read_MASTER_CTL(iface) & ~RSTART); - SSYNC(); } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && iface->cur_msg+1 < iface->msg_num) { iface->cur_msg++; @@ -226,7 +210,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) write_XMT_DATA8(iface, *(iface->transPtr++)); iface->writeNum--; - SSYNC(); } } @@ -244,15 +227,13 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) /* remove restart bit and enable master receive */ write_MASTER_CTL(iface, read_MASTER_CTL(iface) & ~RSTART); - SSYNC(); } else { iface->result = 1; write_INT_MASK(iface, 0); write_MASTER_CTL(iface, 0); - SSYNC(); - complete(&iface->complete); } } + complete(&iface->complete); } /* Interrupt handler */ @@ -260,38 +241,26 @@ static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id) { struct bfin_twi_iface *iface = dev_id; unsigned long flags; + unsigned short twi_int_status; spin_lock_irqsave(&iface->lock, flags); - del_timer(&iface->timeout_timer); - bfin_twi_handle_interrupt(iface); - spin_unlock_irqrestore(&iface->lock, flags); - return IRQ_HANDLED; -} - -static void bfin_twi_timeout(unsigned long data) -{ - struct bfin_twi_iface *iface = (struct bfin_twi_iface *)data; - unsigned long flags; - - spin_lock_irqsave(&iface->lock, flags); - bfin_twi_handle_interrupt(iface); - if (iface->result == 0) { - iface->timeout_count--; - if (iface->timeout_count > 0) { - iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; - add_timer(&iface->timeout_timer); - } else { - iface->result = -1; - complete(&iface->complete); - } + while (1) { + twi_int_status = read_INT_STAT(iface); + if (!twi_int_status) + break; + /* Clear interrupt status */ + write_INT_STAT(iface, twi_int_status); + bfin_twi_handle_interrupt(iface, twi_int_status); + SSYNC(); } spin_unlock_irqrestore(&iface->lock, flags); + return IRQ_HANDLED; } /* - * Generic i2c master transfer entrypoint + * One i2c master transfer */ -static int bfin_twi_master_xfer(struct i2c_adapter *adap, +static int bfin_twi_do_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { struct bfin_twi_iface *iface = adap->algo_data; @@ -319,7 +288,6 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap, iface->transPtr = pmsg->buf; iface->writeNum = iface->readNum = pmsg->len; iface->result = 0; - iface->timeout_count = 10; init_completion(&(iface->complete)); /* Set Transmit device address */ write_MASTER_ADDR(iface, pmsg->addr); @@ -358,30 +326,41 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap, iface->manual_stop = 1; } - iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; - add_timer(&iface->timeout_timer); - /* Master enable */ write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); SSYNC(); - wait_for_completion(&iface->complete); - - rc = iface->result; + while (!iface->result) { + if (!wait_for_completion_timeout(&iface->complete, + adap->timeout)) { + iface->result = -1; + dev_err(&adap->dev, "master transfer timeout\n"); + } + } - if (rc == 1) - return num; + if (iface->result == 1) + rc = iface->cur_msg + 1; else - return rc; + rc = iface->result; + + return rc; } /* - * SMBus type transfer entrypoint + * Generic i2c master transfer entrypoint */ +static int bfin_twi_master_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + return bfin_twi_do_master_xfer(adap, msgs, num); +} -int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, +/* + * One I2C SMBus transfer + */ +int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { @@ -469,7 +448,6 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, iface->manual_stop = 0; iface->read_write = read_write; iface->command = command; - iface->timeout_count = 10; init_completion(&(iface->complete)); /* FIFO Initiation. Data in FIFO should be discarded before @@ -486,9 +464,6 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, write_MASTER_ADDR(iface, addr); SSYNC(); - iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; - add_timer(&iface->timeout_timer); - switch (iface->cur_mode) { case TWI_I2C_MODE_STANDARDSUB: write_XMT_DATA8(iface, iface->command); @@ -550,10 +525,8 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, else if (iface->readNum > 255) { write_MASTER_CTL(iface, 0xff << 6); iface->manual_stop = 1; - } else { - del_timer(&iface->timeout_timer); + } else break; - } } } write_INT_MASK(iface, MCOMP | MERR | @@ -569,7 +542,13 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, } SSYNC(); - wait_for_completion(&iface->complete); + while (!iface->result) { + if (!wait_for_completion_timeout(&iface->complete, + adap->timeout)) { + iface->result = -1; + dev_err(&adap->dev, "smbus transfer timeout\n"); + } + } rc = (iface->result >= 0) ? 0 : -1; @@ -577,6 +556,17 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, } /* + * Generic I2C SMBus transfer entrypoint + */ +int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data) +{ + return bfin_twi_do_smbus_xfer(adap, addr, flags, + read_write, command, size, data); +} + +/* * Return what the adapter supports */ static u32 bfin_twi_functionality(struct i2c_adapter *adap) @@ -667,10 +657,6 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) goto out_error_no_irq; } - init_timer(&(iface->timeout_timer)); - iface->timeout_timer.function = bfin_twi_timeout; - iface->timeout_timer.data = (unsigned long)iface; - p_adap = &iface->adap; p_adap->nr = pdev->id; strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name)); @@ -678,6 +664,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) p_adap->algo_data = iface; p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; p_adap->dev.parent = &pdev->dev; + p_adap->timeout = 5 * HZ; + p_adap->retries = 3; rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi"); if (rc) { diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 7637e123414..b02b4533651 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -441,7 +441,7 @@ static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) init_waitqueue_head(&cpm->i2c_wait); cpm->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); - if (cpm->irq == NO_IRQ) + if (!cpm->irq) return -EINVAL; /* Install interrupt handler. */ diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c index 612255614a6..e5b1a3bf5b8 100644 --- a/drivers/i2c/busses/i2c-elektor.c +++ b/drivers/i2c/busses/i2c-elektor.c @@ -37,8 +37,8 @@ #include <linux/isa.h> #include <linux/i2c.h> #include <linux/i2c-algo-pcf.h> +#include <linux/io.h> -#include <asm/io.h> #include <asm/irq.h> #include "../algos/i2c-algo-pcf.h" diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index c21077d248a..d9aa9a649e3 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -211,7 +211,7 @@ static int __init i2c_gpio_init(void) return ret; } -module_init(i2c_gpio_init); +subsys_initcall(i2c_gpio_init); static void __exit i2c_gpio_exit(void) { diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c index ce87a902c94..3df1bc80f37 100644 --- a/drivers/i2c/busses/i2c-highlander.c +++ b/drivers/i2c/busses/i2c-highlander.c @@ -282,7 +282,6 @@ static int highlander_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, union i2c_smbus_data *data) { struct highlander_i2c_dev *dev = i2c_get_adapdata(adap); - int read = read_write & I2C_SMBUS_READ; u16 tmp; init_completion(&dev->cmd_complete); @@ -337,11 +336,11 @@ static int highlander_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, highlander_i2c_done(dev); /* Set slave address */ - iowrite16((addr << 1) | read, dev->base + SMSMADR); + iowrite16((addr << 1) | read_write, dev->base + SMSMADR); highlander_i2c_command(dev, command, dev->buf_len); - if (read) + if (read_write == I2C_SMBUS_READ) return highlander_i2c_read(dev); else return highlander_i2c_write(dev); diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c index c767295ad1f..9ff1695d845 100644 --- a/drivers/i2c/busses/i2c-hydra.c +++ b/drivers/i2c/busses/i2c-hydra.c @@ -28,7 +28,7 @@ #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> #include <linux/init.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/hydra.h> diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 299b918455a..f4b21f2bb8e 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -138,6 +138,17 @@ static struct pci_dev *I801_dev; #define FEATURE_I2C_BLOCK_READ (1 << 3) static unsigned int i801_features; +static const char *i801_feature_names[] = { + "SMBus PEC", + "Block buffer", + "Block process call", + "I2C block read", +}; + +static unsigned int disable_features; +module_param(disable_features, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(disable_features, "Disable selected driver features"); + /* Make sure the SMBus host is ready to start transmitting. Return 0 if it is, -EBUSY if it is not. */ static int i801_check_pre(void) @@ -341,9 +352,8 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, do { msleep(1); status = inb_p(SMBHSTSTS); - } - while ((!(status & SMBHSTSTS_BYTE_DONE)) - && (timeout++ < MAX_TIMEOUT)); + } while ((!(status & SMBHSTSTS_BYTE_DONE)) + && (timeout++ < MAX_TIMEOUT)); result = i801_check_post(status, timeout > MAX_TIMEOUT); if (result < 0) @@ -440,9 +450,9 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, } /* Return negative errno on error. */ -static s32 i801_access(struct i2c_adapter * adap, u16 addr, +static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data * data) + int size, union i2c_smbus_data *data) { int hwpec; int block = 0; @@ -511,7 +521,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, else outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL); - if(block) + if (block) ret = i801_block_transaction(data, read_write, size, hwpec); else ret = i801_transaction(xact | ENABLE_INT9); @@ -523,9 +533,9 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL); - if(block) + if (block) return ret; - if(ret) + if (ret) return ret; if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) return 0; @@ -585,7 +595,7 @@ static const struct pci_device_id i801_ids[] = { { 0, } }; -MODULE_DEVICE_TABLE (pci, i801_ids); +MODULE_DEVICE_TABLE(pci, i801_ids); #if defined CONFIG_INPUT_APANEL || defined CONFIG_INPUT_APANEL_MODULE static unsigned char apanel_addr; @@ -689,10 +699,11 @@ static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm, } #endif -static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int __devinit i801_probe(struct pci_dev *dev, + const struct pci_device_id *id) { unsigned char temp; - int err; + int err, i; #if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE const char *vendor; #endif @@ -700,26 +711,28 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id I801_dev = dev; i801_features = 0; switch (dev->device) { - case PCI_DEVICE_ID_INTEL_82801EB_3: - case PCI_DEVICE_ID_INTEL_ESB_4: - case PCI_DEVICE_ID_INTEL_ICH6_16: - case PCI_DEVICE_ID_INTEL_ICH7_17: - case PCI_DEVICE_ID_INTEL_ESB2_17: - case PCI_DEVICE_ID_INTEL_ICH8_5: - case PCI_DEVICE_ID_INTEL_ICH9_6: - case PCI_DEVICE_ID_INTEL_TOLAPAI_1: - case PCI_DEVICE_ID_INTEL_ICH10_4: - case PCI_DEVICE_ID_INTEL_ICH10_5: - case PCI_DEVICE_ID_INTEL_PCH_SMBUS: - case PCI_DEVICE_ID_INTEL_CPT_SMBUS: + default: i801_features |= FEATURE_I2C_BLOCK_READ; /* fall through */ case PCI_DEVICE_ID_INTEL_82801DB_3: i801_features |= FEATURE_SMBUS_PEC; i801_features |= FEATURE_BLOCK_BUFFER; + /* fall through */ + case PCI_DEVICE_ID_INTEL_82801CA_3: + case PCI_DEVICE_ID_INTEL_82801BA_2: + case PCI_DEVICE_ID_INTEL_82801AB_3: + case PCI_DEVICE_ID_INTEL_82801AA_3: break; } + /* Disable features on user request */ + for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) { + if (i801_features & disable_features & (1 << i)) + dev_notice(&dev->dev, "%s disabled by user\n", + i801_feature_names[i]); + } + i801_features &= ~disable_features; + err = pci_enable_device(dev); if (err) { dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n", diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 3876f993fe7..bf344135647 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -39,7 +39,7 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <asm/irq.h> -#include <asm/io.h> +#include <linux/io.h> #include <linux/i2c.h> #include <linux/i2c-id.h> #include <linux/of_platform.h> @@ -668,12 +668,12 @@ static int __devinit iic_request_irq(struct of_device *ofdev, int irq; if (iic_force_poll) - return NO_IRQ; + return 0; irq = irq_of_parse_and_map(np, 0); - if (irq == NO_IRQ) { + if (!irq) { dev_err(&ofdev->dev, "irq_of_parse_and_map failed\n"); - return NO_IRQ; + return 0; } /* Disable interrupts until we finish initialization, assumes @@ -683,7 +683,7 @@ static int __devinit iic_request_irq(struct of_device *ofdev, if (request_irq(irq, iic_handler, 0, "IBM IIC", dev)) { dev_err(&ofdev->dev, "request_irq %d failed\n", irq); /* Fallback to the polling mode */ - return NO_IRQ; + return 0; } return irq; @@ -719,7 +719,7 @@ static int __devinit iic_probe(struct of_device *ofdev, init_waitqueue_head(&dev->wq); dev->irq = iic_request_irq(ofdev, dev); - if (dev->irq == NO_IRQ) + if (!dev->irq) dev_warn(&ofdev->dev, "using polling mode\n"); /* Board specific settings */ @@ -766,7 +766,7 @@ static int __devinit iic_probe(struct of_device *ofdev, return 0; error_cleanup: - if (dev->irq != NO_IRQ) { + if (dev->irq) { iic_interrupt_mode(dev, 0); free_irq(dev->irq, dev); } @@ -790,7 +790,7 @@ static int __devexit iic_remove(struct of_device *ofdev) i2c_del_adapter(&dev->adap); - if (dev->irq != NO_IRQ) { + if (dev->irq) { iic_interrupt_mode(dev, 0); free_irq(dev->irq, dev); } diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index f7e27b70237..d1ff9408dc1 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -146,10 +146,10 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) "<%s> I2C Interrupted\n", __func__); return -EINTR; } - if (time_after(jiffies, orig_jiffies + HZ / 1000)) { + if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C bus is busy\n", __func__); - return -EIO; + return -ETIMEDOUT; } schedule(); } @@ -444,6 +444,8 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, result = i2c_imx_read(i2c_imx, &msgs[i]); else result = i2c_imx_write(i2c_imx, &msgs[i]); + if (result) + goto fail0; } fail0: diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index 5901707fc66..112c61f7b8c 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -38,8 +38,7 @@ #include <linux/errno.h> #include <linux/platform_device.h> #include <linux/i2c.h> - -#include <asm/io.h> +#include <linux/io.h> #include "i2c-iop3xx.h" diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 791b71f46f7..df00eb1f11f 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -118,7 +118,7 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) u32 x; int result = 0; - if (i2c->irq == NO_IRQ) { + if (!i2c->irq) { while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) { schedule(); if (time_after(jiffies, orig_jiffies + timeout)) { @@ -568,7 +568,7 @@ static int __devinit fsl_i2c_probe(struct of_device *op, } i2c->irq = irq_of_parse_and_map(op->dev.of_node, 0); - if (i2c->irq != NO_IRQ) { /* i2c->irq = NO_IRQ implies polling */ + if (i2c->irq) { /* no i2c->irq implies polling */ result = request_irq(i2c->irq, mpc_i2c_isr, IRQF_SHARED, "i2c-mpc", i2c); if (result < 0) { @@ -628,7 +628,7 @@ static int __devexit fsl_i2c_remove(struct of_device *op) i2c_del_adapter(&i2c->adap); dev_set_drvdata(&op->dev, NULL); - if (i2c->irq != NO_IRQ) + if (i2c->irq) free_irq(i2c->irq, i2c); irq_dispose_mapping(i2c->irq); diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 3623a449908..16242063144 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -17,8 +17,7 @@ #include <linux/interrupt.h> #include <linux/mv643xx_i2c.h> #include <linux/platform_device.h> - -#include <asm/io.h> +#include <linux/io.h> /* Register defines */ #define MV64XXX_I2C_REG_SLAVE_ADDR 0x00 diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 4a48dd4ef78..a605a5029cf 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -57,7 +57,7 @@ #include <linux/dmi.h> #include <linux/acpi.h> #include <linux/slab.h> -#include <asm/io.h> +#include <linux/io.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@gmx.net>"); @@ -404,10 +404,9 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_ /* SMBus adapter 1 */ res1 = nforce2_probe_smb(dev, 4, NFORCE_PCI_SMB1, &smbuses[0], "SMB1"); - if (res1 < 0) { - dev_err(&dev->dev, "Error probing SMB1.\n"); + if (res1 < 0) smbuses[0].base = 0; /* to have a check value */ - } + /* SMBus adapter 2 */ if (dmi_check_system(nforce2_dmi_blacklist2)) { dev_err(&dev->dev, "Disabling SMB2 for safety reasons.\n"); @@ -416,11 +415,10 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_ } else { res2 = nforce2_probe_smb(dev, 5, NFORCE_PCI_SMB2, &smbuses[1], "SMB2"); - if (res2 < 0) { - dev_err(&dev->dev, "Error probing SMB2.\n"); + if (res2 < 0) smbuses[1].base = 0; /* to have a check value */ - } } + if ((res1 < 0) && (res2 < 0)) { /* we did not find even one of the SMBuses, so we give up */ kfree(smbuses); diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index a4f8d33fa38..73de8ade10b 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -704,7 +704,8 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) case I2C_IT_MTD: case I2C_IT_MTDWS: if (dev->cli.operation == I2C_READ) { - while (!readl(dev->virtbase + I2C_RISR) & I2C_IT_RXFE) { + while (!(readl(dev->virtbase + I2C_RISR) + & I2C_IT_RXFE)) { if (dev->cli.count == 0) break; *dev->cli.buffer = @@ -914,6 +915,7 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) static int __devexit nmk_i2c_remove(struct platform_device *pdev) { + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct nmk_i2c_dev *dev = platform_get_drvdata(pdev); i2c_del_adapter(&dev->adap); @@ -924,6 +926,8 @@ static int __devexit nmk_i2c_remove(struct platform_device *pdev) i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE); free_irq(dev->irq, dev); iounmap(dev->virtbase); + if (res) + release_mem_region(res->start, resource_size(res)); clk_disable(dev->clk); clk_put(dev->clk); platform_set_drvdata(pdev, NULL); diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index b4ed4ca802e..0070371b29f 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -19,7 +19,7 @@ #include <linux/wait.h> #include <linux/i2c-ocores.h> #include <linux/slab.h> -#include <asm/io.h> +#include <linux/io.h> struct ocores_i2c { void __iomem *base; diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index a2481f40ea1..0e9f85d0a83 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -447,7 +447,7 @@ static struct i2c_adapter octeon_i2c_ops = { /** * octeon_i2c_setclock - Calculate and set clock divisors. */ -static int __init octeon_i2c_setclock(struct octeon_i2c *i2c) +static int __devinit octeon_i2c_setclock(struct octeon_i2c *i2c) { int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff; int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000; @@ -490,7 +490,7 @@ static int __init octeon_i2c_setclock(struct octeon_i2c *i2c) return 0; } -static int __init octeon_i2c_initlowlevel(struct octeon_i2c *i2c) +static int __devinit octeon_i2c_initlowlevel(struct octeon_i2c *i2c) { u8 status; int tries; diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 6bd0f19cd45..7674efb5537 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -38,6 +38,7 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/slab.h> +#include <linux/i2c-omap.h> /* I2C controller revisions */ #define OMAP_I2C_REV_2 0x20 @@ -45,29 +46,37 @@ /* I2C controller revisions present on specific hardware */ #define OMAP_I2C_REV_ON_2430 0x36 #define OMAP_I2C_REV_ON_3430 0x3C +#define OMAP_I2C_REV_ON_4430 0x40 /* timeout waiting for the controller to respond */ #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) -#define OMAP_I2C_REV_REG 0x00 -#define OMAP_I2C_IE_REG 0x01 -#define OMAP_I2C_STAT_REG 0x02 -#define OMAP_I2C_IV_REG 0x03 /* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */ -#define OMAP_I2C_WE_REG 0x03 -#define OMAP_I2C_SYSS_REG 0x04 -#define OMAP_I2C_BUF_REG 0x05 -#define OMAP_I2C_CNT_REG 0x06 -#define OMAP_I2C_DATA_REG 0x07 -#define OMAP_I2C_SYSC_REG 0x08 -#define OMAP_I2C_CON_REG 0x09 -#define OMAP_I2C_OA_REG 0x0a -#define OMAP_I2C_SA_REG 0x0b -#define OMAP_I2C_PSC_REG 0x0c -#define OMAP_I2C_SCLL_REG 0x0d -#define OMAP_I2C_SCLH_REG 0x0e -#define OMAP_I2C_SYSTEST_REG 0x0f -#define OMAP_I2C_BUFSTAT_REG 0x10 +enum { + OMAP_I2C_REV_REG = 0, + OMAP_I2C_IE_REG, + OMAP_I2C_STAT_REG, + OMAP_I2C_IV_REG, + OMAP_I2C_WE_REG, + OMAP_I2C_SYSS_REG, + OMAP_I2C_BUF_REG, + OMAP_I2C_CNT_REG, + OMAP_I2C_DATA_REG, + OMAP_I2C_SYSC_REG, + OMAP_I2C_CON_REG, + OMAP_I2C_OA_REG, + OMAP_I2C_SA_REG, + OMAP_I2C_PSC_REG, + OMAP_I2C_SCLL_REG, + OMAP_I2C_SCLH_REG, + OMAP_I2C_SYSTEST_REG, + OMAP_I2C_BUFSTAT_REG, + OMAP_I2C_REVNB_LO, + OMAP_I2C_REVNB_HI, + OMAP_I2C_IRQSTATUS_RAW, + OMAP_I2C_IRQENABLE_SET, + OMAP_I2C_IRQENABLE_CLR, +}; /* I2C Interrupt Enable Register (OMAP_I2C_IE): */ #define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */ @@ -157,6 +166,9 @@ #define SYSC_IDLEMODE_SMART 0x2 #define SYSC_CLOCKACTIVITY_FCLK 0x2 +/* Errata definitions */ +#define I2C_OMAP_ERRATA_I207 (1 << 0) +#define I2C_OMAP3_1P153 (1 << 1) struct omap_i2c_dev { struct device *dev; @@ -167,9 +179,13 @@ struct omap_i2c_dev { struct clk *fclk; /* Functional clock */ struct completion cmd_complete; struct resource *ioarea; + u32 latency; /* maximum mpu wkup latency */ + void (*set_mpu_wkup_lat)(struct device *dev, + long latency); u32 speed; /* Speed of bus in Khz */ u16 cmd_err; u8 *buf; + u8 *regs; size_t buf_len; struct i2c_adapter adapter; u8 fifo_size; /* use as flag and value @@ -186,17 +202,67 @@ struct omap_i2c_dev { u16 bufstate; u16 syscstate; u16 westate; + u16 errata; +}; + +const static u8 reg_map[] = { + [OMAP_I2C_REV_REG] = 0x00, + [OMAP_I2C_IE_REG] = 0x01, + [OMAP_I2C_STAT_REG] = 0x02, + [OMAP_I2C_IV_REG] = 0x03, + [OMAP_I2C_WE_REG] = 0x03, + [OMAP_I2C_SYSS_REG] = 0x04, + [OMAP_I2C_BUF_REG] = 0x05, + [OMAP_I2C_CNT_REG] = 0x06, + [OMAP_I2C_DATA_REG] = 0x07, + [OMAP_I2C_SYSC_REG] = 0x08, + [OMAP_I2C_CON_REG] = 0x09, + [OMAP_I2C_OA_REG] = 0x0a, + [OMAP_I2C_SA_REG] = 0x0b, + [OMAP_I2C_PSC_REG] = 0x0c, + [OMAP_I2C_SCLL_REG] = 0x0d, + [OMAP_I2C_SCLH_REG] = 0x0e, + [OMAP_I2C_SYSTEST_REG] = 0x0f, + [OMAP_I2C_BUFSTAT_REG] = 0x10, +}; + +const static u8 omap4_reg_map[] = { + [OMAP_I2C_REV_REG] = 0x04, + [OMAP_I2C_IE_REG] = 0x2c, + [OMAP_I2C_STAT_REG] = 0x28, + [OMAP_I2C_IV_REG] = 0x34, + [OMAP_I2C_WE_REG] = 0x34, + [OMAP_I2C_SYSS_REG] = 0x90, + [OMAP_I2C_BUF_REG] = 0x94, + [OMAP_I2C_CNT_REG] = 0x98, + [OMAP_I2C_DATA_REG] = 0x9c, + [OMAP_I2C_SYSC_REG] = 0x20, + [OMAP_I2C_CON_REG] = 0xa4, + [OMAP_I2C_OA_REG] = 0xa8, + [OMAP_I2C_SA_REG] = 0xac, + [OMAP_I2C_PSC_REG] = 0xb0, + [OMAP_I2C_SCLL_REG] = 0xb4, + [OMAP_I2C_SCLH_REG] = 0xb8, + [OMAP_I2C_SYSTEST_REG] = 0xbC, + [OMAP_I2C_BUFSTAT_REG] = 0xc0, + [OMAP_I2C_REVNB_LO] = 0x00, + [OMAP_I2C_REVNB_HI] = 0x04, + [OMAP_I2C_IRQSTATUS_RAW] = 0x24, + [OMAP_I2C_IRQENABLE_SET] = 0x2c, + [OMAP_I2C_IRQENABLE_CLR] = 0x30, }; static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, int reg, u16 val) { - __raw_writew(val, i2c_dev->base + (reg << i2c_dev->reg_shift)); + __raw_writew(val, i2c_dev->base + + (i2c_dev->regs[reg] << i2c_dev->reg_shift)); } static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) { - return __raw_readw(i2c_dev->base + (reg << i2c_dev->reg_shift)); + return __raw_readw(i2c_dev->base + + (i2c_dev->regs[reg] << i2c_dev->reg_shift)); } static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev) @@ -265,7 +331,11 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev) WARN_ON(dev->idle); dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); - omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); + if (dev->rev >= OMAP_I2C_REV_ON_4430) + omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1); + else + omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); + if (dev->rev < OMAP_I2C_REV_2) { iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */ } else { @@ -330,7 +400,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) * REVISIT: Some wkup sources might not be needed. */ dev->westate = OMAP_I2C_WE_ALL; - omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); + if (dev->rev < OMAP_I2C_REV_ON_4430) + omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, + dev->westate); } } omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); @@ -357,7 +429,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) psc = fclk_rate / 12000000; } - if (cpu_is_omap2430() || cpu_is_omap34xx()) { + if (!(cpu_class_is_omap1() || cpu_is_omap2420())) { /* * HSI2C controller internal clk rate should be 19.2 Mhz for @@ -430,6 +502,11 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) /* Take the I2C module out of reset: */ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); + dev->errata = 0; + + if (cpu_is_omap2430() || cpu_is_omap34xx()) + dev->errata |= I2C_OMAP_ERRATA_I207; + /* Enable interrupts */ dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | @@ -539,8 +616,12 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, * REVISIT: We should abort the transfer on signals, but the bus goes * into arbitration and we're currently unable to recover from it. */ + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, dev->latency); r = wait_for_completion_timeout(&dev->cmd_complete, OMAP_I2C_TIMEOUT); + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, -1); dev->buf_len = 0; if (r < 0) return r; @@ -623,6 +704,34 @@ omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat) omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); } +static inline void i2c_omap_errata_i207(struct omap_i2c_dev *dev, u16 stat) +{ + /* + * I2C Errata(Errata Nos. OMAP2: 1.67, OMAP3: 1.8) + * Not applicable for OMAP4. + * Under certain rare conditions, RDR could be set again + * when the bus is busy, then ignore the interrupt and + * clear the interrupt. + */ + if (stat & OMAP_I2C_STAT_RDR) { + /* Step 1: If RDR is set, clear it */ + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); + + /* Step 2: */ + if (!(omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) + & OMAP_I2C_STAT_BB)) { + + /* Step 3: */ + if (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) + & OMAP_I2C_STAT_RDR) { + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); + dev_dbg(dev->dev, "RDR when bus is busy.\n"); + } + + } + } +} + /* rev1 devices are apparently only on some 15xx */ #ifdef CONFIG_ARCH_OMAP15XX @@ -684,6 +793,35 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id) #define omap_i2c_rev1_isr NULL #endif +/* + * OMAP3430 Errata 1.153: When an XRDY/XDR is hit, wait for XUDF before writing + * data to DATA_REG. Otherwise some data bytes can be lost while transferring + * them from the memory to the I2C interface. + */ +static int errata_omap3_1p153(struct omap_i2c_dev *dev, u16 *stat, int *err) +{ + unsigned long timeout = 10000; + + while (--timeout && !(*stat & OMAP_I2C_STAT_XUDF)) { + if (*stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) { + omap_i2c_ack_stat(dev, *stat & (OMAP_I2C_STAT_XRDY | + OMAP_I2C_STAT_XDR)); + *err |= OMAP_I2C_STAT_XUDF; + return -ETIMEDOUT; + } + + cpu_relax(); + *stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); + } + + if (!timeout) { + dev_err(dev->dev, "timeout waiting on XUDF bit\n"); + return 0; + } + + return 0; +} + static irqreturn_t omap_i2c_isr(int this_irq, void *dev_id) { @@ -733,6 +871,10 @@ complete: } if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) { u8 num_bytes = 1; + + if (dev->errata & I2C_OMAP_ERRATA_I207) + i2c_omap_errata_i207(dev, stat); + if (dev->fifo_size) { if (stat & OMAP_I2C_STAT_RRDY) num_bytes = dev->fifo_size; @@ -747,9 +889,12 @@ complete: if (dev->buf_len) { *dev->buf++ = w; dev->buf_len--; - /* Data reg from 2430 is 8 bit wide */ - if (!cpu_is_omap2430() && - !cpu_is_omap34xx()) { + /* + * Data reg in 2430, omap3 and + * omap4 is 8 bit wide + */ + if (cpu_class_is_omap1() || + cpu_is_omap2420()) { if (dev->buf_len) { *dev->buf++ = w >> 8; dev->buf_len--; @@ -787,9 +932,12 @@ complete: if (dev->buf_len) { w = *dev->buf++; dev->buf_len--; - /* Data reg from 2430 is 8 bit wide */ - if (!cpu_is_omap2430() && - !cpu_is_omap34xx()) { + /* + * Data reg in 2430, omap3 and + * omap4 is 8 bit wide + */ + if (cpu_class_is_omap1() || + cpu_is_omap2420()) { if (dev->buf_len) { w |= *dev->buf++ << 8; dev->buf_len--; @@ -807,25 +955,9 @@ complete: break; } - /* - * OMAP3430 Errata 1.153: When an XRDY/XDR - * is hit, wait for XUDF before writing data - * to DATA_REG. Otherwise some data bytes can - * be lost while transferring them from the - * memory to the I2C interface. - */ - - if (dev->rev <= OMAP_I2C_REV_ON_3430) { - while (!(stat & OMAP_I2C_STAT_XUDF)) { - if (stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) { - omap_i2c_ack_stat(dev, stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)); - err |= OMAP_I2C_STAT_XUDF; - goto complete; - } - cpu_relax(); - stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); - } - } + if ((dev->errata & I2C_OMAP3_1P153) && + errata_omap3_1p153(dev, &stat, &err)) + goto complete; omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); } @@ -857,6 +989,7 @@ omap_i2c_probe(struct platform_device *pdev) struct omap_i2c_dev *dev; struct i2c_adapter *adap; struct resource *mem, *irq, *ioarea; + struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data; irq_handler_t isr; int r; u32 speed = 0; @@ -886,10 +1019,13 @@ omap_i2c_probe(struct platform_device *pdev) goto err_release_region; } - if (pdev->dev.platform_data != NULL) - speed = *(u32 *)pdev->dev.platform_data; - else - speed = 100; /* Defualt speed */ + if (pdata != NULL) { + speed = pdata->clkrate; + dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; + } else { + speed = 100; /* Default speed */ + dev->set_mpu_wkup_lat = NULL; + } dev->speed = speed; dev->idle = 1; @@ -903,14 +1039,29 @@ omap_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); + if (cpu_is_omap7xx()) + dev->reg_shift = 1; + else if (cpu_is_omap44xx()) + dev->reg_shift = 0; + else + dev->reg_shift = 2; + if ((r = omap_i2c_get_clocks(dev)) != 0) goto err_iounmap; + if (cpu_is_omap44xx()) + dev->regs = (u8 *) omap4_reg_map; + else + dev->regs = (u8 *) reg_map; + omap_i2c_unidle(dev); dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; - if (cpu_is_omap2430() || cpu_is_omap34xx()) { + if (dev->rev <= OMAP_I2C_REV_ON_3430) + dev->errata |= I2C_OMAP3_1P153; + + if (!(cpu_class_is_omap1() || cpu_is_omap2420())) { u16 s; /* Set up the fifo size - Get total size */ @@ -922,15 +1073,19 @@ omap_i2c_probe(struct platform_device *pdev) * size. This is to ensure that we can handle the status on int * call back latencies. */ - dev->fifo_size = (dev->fifo_size / 2); - dev->b_hw = 1; /* Enable hardware fixes */ + if (dev->rev >= OMAP_I2C_REV_ON_4430) { + dev->fifo_size = 0; + dev->b_hw = 0; /* Disable hardware fixes */ + } else { + dev->fifo_size = (dev->fifo_size / 2); + dev->b_hw = 1; /* Enable hardware fixes */ + } + /* calculate wakeup latency constraint for MPU */ + if (dev->set_mpu_wkup_lat != NULL) + dev->latency = (1000000 * dev->fifo_size) / + (1000 * speed / 8); } - if (cpu_is_omap7xx()) - dev->reg_shift = 1; - else - dev->reg_shift = 2; - /* reset ASAP, clearing any IRQs */ omap_i2c_init(dev); diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c index 5f41ec0f72d..fc5fbd1012c 100644 --- a/drivers/i2c/busses/i2c-parport-light.c +++ b/drivers/i2c/busses/i2c-parport-light.c @@ -33,7 +33,7 @@ #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> #include <linux/i2c-smbus.h> -#include <asm/io.h> +#include <linux/io.h> #include "i2c-parport.h" #define DEFAULT_BASE 0x378 diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c index 846583ed476..0eb1515541e 100644 --- a/drivers/i2c/busses/i2c-parport.c +++ b/drivers/i2c/busses/i2c-parport.c @@ -137,7 +137,7 @@ static int parport_getsda(void *data) copied. The attaching code will set getscl to NULL for adapters that cannot read SCL back, and will also make the data field point to the parallel port structure. */ -static struct i2c_algo_bit_data parport_algo_data = { +static const struct i2c_algo_bit_data parport_algo_data = { .setsda = parport_setsda, .setscl = parport_setscl, .getsda = parport_getsda, diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index d3d4a4b43a1..4174101660c 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -25,7 +25,7 @@ #include <linux/i2c.h> #include <linux/delay.h> #include <linux/slab.h> -#include <asm/io.h> +#include <linux/io.h> static struct pci_driver pasemi_smb_driver; diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index f7346a9bd95..bbd77603a41 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -30,8 +30,8 @@ #include <linux/isa.h> #include <linux/i2c.h> #include <linux/i2c-algo-pca.h> +#include <linux/io.h> -#include <asm/io.h> #include <asm/irq.h> #define DRIVER "i2c-pca-isa" diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 5b2213df5ed..ef5c78487eb 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -23,9 +23,9 @@ #include <linux/i2c-algo-pca.h> #include <linux/i2c-pca-platform.h> #include <linux/gpio.h> +#include <linux/io.h> #include <asm/irq.h> -#include <asm/io.h> struct i2c_pca_pf_data { void __iomem *reg_base; diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index ee9da6fcf69..6d14ac2e3c4 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -39,7 +39,7 @@ #include <linux/init.h> #include <linux/dmi.h> #include <linux/acpi.h> -#include <asm/io.h> +#include <linux/io.h> /* PIIX4 SMBus address offsets */ diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index 7b57d5f267e..dfa7ae9c1b8 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c @@ -33,7 +33,7 @@ #include <linux/completion.h> #include <linux/mutex.h> #include <linux/delay.h> -#include <asm/io.h> +#include <linux/io.h> #define DRV_NAME "pmcmsptwi" diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 247103372a0..a97e3fec814 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -173,6 +173,9 @@ static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data) /* We still have something to talk about... */ val = *alg_data->mif.buf++; + if (alg_data->mif.len == 1) + val |= stop_bit; + alg_data->mif.len--; iowrite32(val, I2C_REG_TX(alg_data)); @@ -246,6 +249,9 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data) __func__); if (alg_data->mif.len == 1) { + /* Last byte, do not acknowledge next rcv. */ + val |= stop_bit; + /* * Enable interrupt RFDAIE (data in Rx fifo), * and disable DRMIE (need data for Tx) @@ -633,6 +639,8 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) */ tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2; + if (tmp > 0x3FF) + tmp = 0x3FF; iowrite32(tmp, I2C_REG_CKH(alg_data)); iowrite32(tmp, I2C_REG_CKL(alg_data)); diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 14d249f5ed3..020ff23d762 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -34,9 +34,9 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/slab.h> +#include <linux/io.h> #include <asm/irq.h> -#include <asm/io.h> #include <plat/i2c.h> /* @@ -209,18 +209,6 @@ static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname) } #define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __func__) -#else -#define i2c_debug 0 - -#define show_state(i2c) do { } while (0) -#define decode_ISR(val) do { } while (0) -#define decode_ICR(val) do { } while (0) -#endif - -#define eedbg(lvl, x...) do { if ((lvl) < 1) { printk(KERN_DEBUG "" x); } } while(0) - -static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret); -static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id); static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why) { @@ -236,6 +224,20 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why) printk("\n"); } +#else /* ifdef DEBUG */ + +#define i2c_debug 0 + +#define show_state(i2c) do { } while (0) +#define decode_ISR(val) do { } while (0) +#define decode_ICR(val) do { } while (0) +#define i2c_pxa_scream_blue_murder(i2c, why) do { } while (0) + +#endif /* ifdef DEBUG / else */ + +static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret); +static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id); + static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c) { return !(readl(_ICR(i2c)) & ICR_SCLE); diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index d27072b2249..72902e0bbfa 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -35,9 +35,9 @@ #include <linux/clk.h> #include <linux/cpufreq.h> #include <linux/slab.h> +#include <linux/io.h> #include <asm/irq.h> -#include <asm/io.h> #include <plat/regs-iic.h> #include <plat/iic.h> @@ -482,7 +482,8 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num) { - unsigned long timeout; + unsigned long iicstat, timeout; + int spins = 20; int ret; if (i2c->suspended) @@ -521,7 +522,21 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, /* ensure the stop has been through the bus */ - msleep(1); + dev_dbg(i2c->dev, "waiting for bus idle\n"); + + /* first, try busy waiting briefly */ + do { + iicstat = readl(i2c->regs + S3C2410_IICSTAT); + } while ((iicstat & S3C2410_IICSTAT_START) && --spins); + + /* if that timed out sleep */ + if (!spins) { + msleep(1); + iicstat = readl(i2c->regs + S3C2410_IICSTAT); + } + + if (iicstat & S3C2410_IICSTAT_START) + dev_warn(i2c->dev, "timeout waiting for bus idle\n"); out: return ret; diff --git a/drivers/i2c/busses/i2c-s6000.c b/drivers/i2c/busses/i2c-s6000.c index c91359f4965..cadc0216e02 100644 --- a/drivers/i2c/busses/i2c-s6000.c +++ b/drivers/i2c/busses/i2c-s6000.c @@ -36,8 +36,8 @@ #include <linux/completion.h> #include <linux/interrupt.h> #include <linux/platform_device.h> +#include <linux/io.h> -#include <asm/io.h> #include "i2c-s6000.h" #define DRV_NAME "i2c-s6000" diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c index b9680f50f54..4f93da31d3a 100644 --- a/drivers/i2c/busses/i2c-sh7760.c +++ b/drivers/i2c/busses/i2c-sh7760.c @@ -16,10 +16,10 @@ #include <linux/ioport.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/io.h> #include <asm/clock.h> #include <asm/i2c-sh7760.h> -#include <asm/io.h> /* register offsets */ #define I2CSCR 0x0 /* slave ctrl */ diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c index 98b1ec48915..3d76a188e42 100644 --- a/drivers/i2c/busses/i2c-sibyte.c +++ b/drivers/i2c/busses/i2c-sibyte.c @@ -22,7 +22,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/i2c.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/sibyte/sb1250_regs.h> #include <asm/sibyte/sb1250_smbus.h> diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c index 78b06107342..2fc08fbf67a 100644 --- a/drivers/i2c/busses/i2c-simtec.c +++ b/drivers/i2c/busses/i2c-simtec.c @@ -24,12 +24,11 @@ #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/io.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> -#include <asm/io.h> - struct simtec_i2c_data { struct resource *ioarea; void __iomem *reg; diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c index 55a71370c79..437586611d4 100644 --- a/drivers/i2c/busses/i2c-sis5595.c +++ b/drivers/i2c/busses/i2c-sis5595.c @@ -61,7 +61,7 @@ #include <linux/init.h> #include <linux/i2c.h> #include <linux/acpi.h> -#include <asm/io.h> +#include <linux/io.h> static int blacklist[] = { PCI_DEVICE_ID_SI_540, diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 2309c7f1bde..e6f539e26f6 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c @@ -53,7 +53,7 @@ #include <linux/init.h> #include <linux/i2c.h> #include <linux/acpi.h> -#include <asm/io.h> +#include <linux/io.h> /* SIS630 SMBus registers */ #define SMB_STS 0x80 /* status */ diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c index d43d8f8943d..86837f0c4cb 100644 --- a/drivers/i2c/busses/i2c-sis96x.c +++ b/drivers/i2c/busses/i2c-sis96x.c @@ -38,7 +38,7 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/acpi.h> -#include <asm/io.h> +#include <linux/io.h> /* base address register in PCI config space */ #define SIS96x_BAR 0x04 diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c index 1f5b38be73b..495be451d32 100644 --- a/drivers/i2c/busses/i2c-stu300.c +++ b/drivers/i2c/busses/i2c-stu300.c @@ -498,7 +498,7 @@ static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate) int i = 0; /* Locate the apropriate clock setting */ - while (i < ARRAY_SIZE(stu300_clktable) && + while (i < ARRAY_SIZE(stu300_clktable) - 1 && stu300_clktable[i].rate < clkrate) i++; diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c index 0c770eabe85..b1b3447942c 100644 --- a/drivers/i2c/busses/i2c-stub.c +++ b/drivers/i2c/busses/i2c-stub.c @@ -29,13 +29,16 @@ #include <linux/i2c.h> #define MAX_CHIPS 10 +#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \ + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \ + I2C_FUNC_SMBUS_I2C_BLOCK) static unsigned short chip_addr[MAX_CHIPS]; module_param_array(chip_addr, ushort, NULL, S_IRUGO); MODULE_PARM_DESC(chip_addr, "Chip addresses (up to 10, between 0x03 and 0x77)"); -static unsigned long functionality = ~0UL; +static unsigned long functionality = STUB_FUNC; module_param(functionality, ulong, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(functionality, "Override functionality bitfield"); @@ -156,9 +159,7 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, static u32 stub_func(struct i2c_adapter *adapter) { - return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_I2C_BLOCK) & functionality; + return STUB_FUNC & functionality; } static const struct i2c_algorithm smbus_algorithm = { diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c index 5c473833d94..60556012312 100644 --- a/drivers/i2c/busses/i2c-versatile.c +++ b/drivers/i2c/busses/i2c-versatile.c @@ -15,8 +15,7 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/slab.h> - -#include <asm/io.h> +#include <linux/io.h> #define I2C_CONTROL 0x00 #define I2C_CONTROLS 0x00 diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c index de78283bddb..7799fe5bda8 100644 --- a/drivers/i2c/busses/i2c-via.c +++ b/drivers/i2c/busses/i2c-via.c @@ -25,7 +25,7 @@ #include <linux/init.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> -#include <asm/io.h> +#include <linux/io.h> /* Power management registers */ #define PM_CFG_REVID 0x08 /* silicon revision code */ diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index d57292e5dae..4c6fff5f330 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -51,7 +51,7 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/acpi.h> -#include <asm/io.h> +#include <linux/io.h> static struct pci_dev *vt596_pdev; diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 684395b6f3e..4cb4bb00995 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -32,7 +32,7 @@ #include <linux/delay.h> #include <linux/mutex.h> #include <linux/slab.h> -#include <asm/io.h> +#include <linux/io.h> #include <linux/scx200.h> @@ -552,7 +552,7 @@ static int __init scx200_create_isa(const char *text, unsigned long base, * the name and the BAR where the I/O address resource is located. ISA * devices are flagged with a bar value of -1 */ -static struct pci_device_id scx200_pci[] = { +static const struct pci_device_id scx200_pci[] __initconst = { { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE), .driver_data = 0 }, { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE), diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c index 42df0eca43d..7ee0d502cea 100644 --- a/drivers/i2c/busses/scx200_i2c.c +++ b/drivers/i2c/busses/scx200_i2c.c @@ -27,7 +27,7 @@ #include <linux/init.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> -#include <asm/io.h> +#include <linux/io.h> #include <linux/scx200_gpio.h> |