diff options
Diffstat (limited to 'drivers/i2c')
32 files changed, 2185 insertions, 782 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index f1c6ca7e285..8206442fbab 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -211,7 +211,7 @@ config I2C_VIA will be called i2c-via. config I2C_VIAPRO - tristate "VIA VT82C596/82C686/82xx and CX700/VX800/VX820" + tristate "VIA VT82C596/82C686/82xx and CX700/VX8xx" depends on PCI help If you say yes to this option, support will be included for the VIA @@ -225,8 +225,8 @@ config I2C_VIAPRO VT8237R/A/S VT8251 CX700 - VX800 - VX820 + VX800/VX820 + VX855/VX875 This driver can also be built as a module. If so, the module will be called i2c-viapro. @@ -298,7 +298,7 @@ config I2C_BLACKFIN_TWI config I2C_BLACKFIN_TWI_CLK_KHZ int "Blackfin TWI I2C clock (kHz)" depends on I2C_BLACKFIN_TWI - range 10 400 + range 21 400 default 50 help The unit of the TWI clock is kHz. @@ -326,6 +326,16 @@ config I2C_DAVINCI devices such as DaVinci NIC. For details please see http://www.ti.com/davinci +config I2C_DESIGNWARE + tristate "Synopsys DesignWare" + depends on HAVE_CLK + help + If you say yes to this option, support will be included for the + Synopsys DesignWare I2C adapter. Only master mode is supported. + + This driver can also be built as a module. If so, the module + will be called i2c-designware. + config I2C_GPIO tristate "GPIO-based bitbanging I2C" depends on GENERIC_GPIO @@ -513,6 +523,19 @@ config I2C_SIMTEC This driver can also be built as a module. If so, the module will be called i2c-simtec. +config I2C_STU300 + tristate "ST Microelectronics DDC I2C interface" + depends on MACH_U300 + default y if MACH_U300 + help + If you say yes to this option, support will be included for the + I2C interface from ST Microelectronics simply called "DDC I2C" + supporting both I2C and DDC, used in e.g. the U300 series + mobile platforms. + + This driver can also be built as a module. If so, the module + will be called i2c-stu300. + config I2C_VERSATILE tristate "ARM Versatile/Realview I2C bus support" depends on ARCH_VERSATILE || ARCH_REALVIEW diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 776acb6403a..e654263bfc0 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o +obj-$(CONFIG_I2C_DESIGNWARE) += i2c-designware.o obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o @@ -48,6 +49,7 @@ obj-$(CONFIG_I2C_S6000) += i2c-s6000.o obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o +obj-$(CONFIG_I2C_STU300) += i2c-stu300.o obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o # External I2C/SMBus adapter drivers diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 67d9dc5b351..06e1ecb4919 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -200,10 +200,10 @@ static int __devinit at91_i2c_probe(struct platform_device *pdev) if (!res) return -ENXIO; - if (!request_mem_region(res->start, res->end - res->start + 1, "at91_i2c")) + if (!request_mem_region(res->start, resource_size(res), "at91_i2c")) return -EBUSY; - twi_base = ioremap(res->start, res->end - res->start + 1); + twi_base = ioremap(res->start, resource_size(res)); if (!twi_base) { rc = -ENOMEM; goto fail0; @@ -252,7 +252,7 @@ fail2: fail1: iounmap(twi_base); fail0: - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); return rc; } @@ -268,7 +268,7 @@ static int __devexit at91_i2c_remove(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); iounmap(twi_base); - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); clk_disable(twi_clk); /* disable peripheral clock */ clk_put(twi_clk); diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c index f78ce523e3d..532828bc50e 100644 --- a/drivers/i2c/busses/i2c-au1550.c +++ b/drivers/i2c/busses/i2c-au1550.c @@ -389,7 +389,7 @@ i2c_au1550_probe(struct platform_device *pdev) goto out; } - priv->ioarea = request_mem_region(r->start, r->end - r->start + 1, + priv->ioarea = request_mem_region(r->start, resource_size(r), pdev->name); if (!priv->ioarea) { ret = -EBUSY; diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index fc548b3d002..b309ac2c3d5 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -12,6 +12,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/i2c.h> +#include <linux/io.h> #include <linux/mm.h> #include <linux/timer.h> #include <linux/spinlock.h> @@ -104,9 +105,14 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) write_MASTER_CTL(iface, read_MASTER_CTL(iface) | STOP); else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && - iface->cur_msg+1 < iface->msg_num) - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | RSTART); + iface->cur_msg + 1 < iface->msg_num) { + if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) + write_MASTER_CTL(iface, + read_MASTER_CTL(iface) | RSTART | MDIR); + else + write_MASTER_CTL(iface, + (read_MASTER_CTL(iface) | RSTART) & ~MDIR); + } SSYNC(); /* Clear status */ write_INT_STAT(iface, XMTSERV); @@ -134,9 +140,13 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) read_MASTER_CTL(iface) | STOP); SSYNC(); } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && - iface->cur_msg+1 < iface->msg_num) { - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | RSTART); + iface->cur_msg + 1 < iface->msg_num) { + if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) + write_MASTER_CTL(iface, + read_MASTER_CTL(iface) | RSTART | MDIR); + else + write_MASTER_CTL(iface, + (read_MASTER_CTL(iface) | RSTART) & ~MDIR); SSYNC(); } /* Clear interrupt source */ @@ -196,8 +206,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); - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | MEN | MDIR); SSYNC(); } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && iface->cur_msg+1 < iface->msg_num) { @@ -222,18 +230,19 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) } if (iface->pmsg[iface->cur_msg].len <= 255) - write_MASTER_CTL(iface, - iface->pmsg[iface->cur_msg].len << 6); + write_MASTER_CTL(iface, + (read_MASTER_CTL(iface) & + (~(0xff << 6))) | + (iface->pmsg[iface->cur_msg].len << 6)); else { - write_MASTER_CTL(iface, 0xff << 6); + write_MASTER_CTL(iface, + (read_MASTER_CTL(iface) | + (0xff << 6))); iface->manual_stop = 1; } /* remove restart bit and enable master receive */ write_MASTER_CTL(iface, read_MASTER_CTL(iface) & ~RSTART); - write_MASTER_CTL(iface, read_MASTER_CTL(iface) | - MEN | ((iface->read_write == I2C_SMBUS_READ) ? - MDIR : 0)); SSYNC(); } else { iface->result = 1; @@ -441,6 +450,16 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, } iface->transPtr = data->block; break; + case I2C_SMBUS_I2C_BLOCK_DATA: + if (read_write == I2C_SMBUS_READ) { + iface->readNum = data->block[0]; + iface->cur_mode = TWI_I2C_MODE_COMBINED; + } else { + iface->writeNum = data->block[0]; + iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; + } + iface->transPtr = (u8 *)&data->block[1]; + break; default: return -1; } @@ -564,7 +583,7 @@ static u32 bfin_twi_functionality(struct i2c_adapter *adap) return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL | - I2C_FUNC_I2C; + I2C_FUNC_I2C | I2C_FUNC_SMBUS_I2C_BLOCK; } static struct i2c_algorithm bfin_twi_algorithm = { @@ -614,6 +633,7 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) struct i2c_adapter *p_adap; struct resource *res; int rc; + unsigned int clkhilow; iface = kzalloc(sizeof(struct bfin_twi_iface), GFP_KERNEL); if (!iface) { @@ -632,7 +652,7 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) goto out_error_get_res; } - iface->regs_base = ioremap(res->start, res->end - res->start + 1); + iface->regs_base = ioremap(res->start, resource_size(res)); if (iface->regs_base == NULL) { dev_err(&pdev->dev, "Cannot map IO\n"); rc = -ENXIO; @@ -675,10 +695,14 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) /* Set TWI internal clock as 10MHz */ write_CONTROL(iface, ((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F); + /* + * We will not end up with a CLKDIV=0 because no one will specify + * 20kHz SCL or less in Kconfig now. (5 * 1024 / 20 = 0x100) + */ + clkhilow = 5 * 1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ; + /* Set Twi interface clock as specified */ - write_CLKDIV(iface, ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ) - << 8) | ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ) - & 0xFF)); + write_CLKDIV(iface, (clkhilow << 8) | clkhilow); /* Enable TWI */ write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA); diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index b5db8b88361..9c2e10082b7 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -140,7 +140,7 @@ static irqreturn_t cpm_i2c_interrupt(int irq, void *dev_id) dev_dbg(&adap->dev, "Interrupt: %x\n", i); - wake_up_interruptible(&cpm->i2c_wait); + wake_up(&cpm->i2c_wait); return i ? IRQ_HANDLED : IRQ_NONE; } @@ -364,12 +364,12 @@ static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) dev_dbg(&adap->dev, "test ready.\n"); pmsg = &msgs[tptr]; if (pmsg->flags & I2C_M_RD) - ret = wait_event_interruptible_timeout(cpm->i2c_wait, + ret = wait_event_timeout(cpm->i2c_wait, (in_be16(&tbdf[tptr].cbd_sc) & BD_SC_NAK) || !(in_be16(&rbdf[rptr].cbd_sc) & BD_SC_EMPTY), 1 * HZ); else - ret = wait_event_interruptible_timeout(cpm->i2c_wait, + ret = wait_event_timeout(cpm->i2c_wait, !(in_be16(&tbdf[tptr].cbd_sc) & BD_SC_READY), 1 * HZ); if (ret == 0) { diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 3fae3a91ce5..c89687a1083 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -187,6 +187,11 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); + /* Respond at reserved "SMBus Host" slave address" (and zero); + * we seem to have no option to not respond... + */ + davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08); + dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk); dev_dbg(dev->dev, "PSC = %d\n", davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); @@ -387,7 +392,7 @@ static void terminate_write(struct davinci_i2c_dev *dev) davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); if (!dev->terminate) - dev_err(dev->dev, "TDR IRQ while no data to send\n"); + dev_dbg(dev->dev, "TDR IRQ while no data to send\n"); } /* @@ -473,9 +478,14 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) break; case DAVINCI_I2C_IVR_AAS: - dev_warn(dev->dev, "Address as slave interrupt\n"); - }/* switch */ - }/* while */ + dev_dbg(dev->dev, "Address as slave interrupt\n"); + break; + + default: + dev_warn(dev->dev, "Unrecognized irq stat %d\n", stat); + break; + } + } return count ? IRQ_HANDLED : IRQ_NONE; } @@ -505,7 +515,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) return -ENODEV; } - ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1, + ioarea = request_mem_region(mem->start, resource_size(mem), pdev->name); if (!ioarea) { dev_err(&pdev->dev, "I2C region already claimed\n"); @@ -523,7 +533,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) dev->irq = irq->start; platform_set_drvdata(pdev, dev); - dev->clk = clk_get(&pdev->dev, "I2CCLK"); + dev->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) { r = -ENODEV; goto err_free_mem; @@ -568,7 +578,7 @@ err_free_mem: put_device(&pdev->dev); kfree(dev); err_release_region: - release_mem_region(mem->start, (mem->end - mem->start) + 1); + release_mem_region(mem->start, resource_size(mem)); return r; } @@ -591,7 +601,7 @@ static int davinci_i2c_remove(struct platform_device *pdev) kfree(dev); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(mem->start, (mem->end - mem->start) + 1); + release_mem_region(mem->start, resource_size(mem)); return 0; } diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c new file mode 100644 index 00000000000..b444762e9b9 --- /dev/null +++ b/drivers/i2c/busses/i2c-designware.c @@ -0,0 +1,624 @@ +/* + * Synopsys Designware I2C adapter driver (master only). + * + * Based on the TI DAVINCI I2C adapter driver. + * + * Copyright (C) 2006 Texas Instruments. + * Copyright (C) 2007 MontaVista Software Inc. + * Copyright (C) 2009 Provigent Ltd. + * + * ---------------------------------------------------------------------------- + * + * 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/kernel.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/clk.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +/* + * Registers offset + */ +#define DW_IC_CON 0x0 +#define DW_IC_TAR 0x4 +#define DW_IC_DATA_CMD 0x10 +#define DW_IC_SS_SCL_HCNT 0x14 +#define DW_IC_SS_SCL_LCNT 0x18 +#define DW_IC_FS_SCL_HCNT 0x1c +#define DW_IC_FS_SCL_LCNT 0x20 +#define DW_IC_INTR_STAT 0x2c +#define DW_IC_INTR_MASK 0x30 +#define DW_IC_CLR_INTR 0x40 +#define DW_IC_ENABLE 0x6c +#define DW_IC_STATUS 0x70 +#define DW_IC_TXFLR 0x74 +#define DW_IC_RXFLR 0x78 +#define DW_IC_COMP_PARAM_1 0xf4 +#define DW_IC_TX_ABRT_SOURCE 0x80 + +#define DW_IC_CON_MASTER 0x1 +#define DW_IC_CON_SPEED_STD 0x2 +#define DW_IC_CON_SPEED_FAST 0x4 +#define DW_IC_CON_10BITADDR_MASTER 0x10 +#define DW_IC_CON_RESTART_EN 0x20 +#define DW_IC_CON_SLAVE_DISABLE 0x40 + +#define DW_IC_INTR_TX_EMPTY 0x10 +#define DW_IC_INTR_TX_ABRT 0x40 +#define DW_IC_INTR_STOP_DET 0x200 + +#define DW_IC_STATUS_ACTIVITY 0x1 + +#define DW_IC_ERR_TX_ABRT 0x1 + +/* + * status codes + */ +#define STATUS_IDLE 0x0 +#define STATUS_WRITE_IN_PROGRESS 0x1 +#define STATUS_READ_IN_PROGRESS 0x2 + +#define TIMEOUT 20 /* ms */ + +/* + * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register + * + * only expected abort codes are listed here + * refer to the datasheet for the full list + */ +#define ABRT_7B_ADDR_NOACK 0 +#define ABRT_10ADDR1_NOACK 1 +#define ABRT_10ADDR2_NOACK 2 +#define ABRT_TXDATA_NOACK 3 +#define ABRT_GCALL_NOACK 4 +#define ABRT_GCALL_READ 5 +#define ABRT_SBYTE_ACKDET 7 +#define ABRT_SBYTE_NORSTRT 9 +#define ABRT_10B_RD_NORSTRT 10 +#define ARB_MASTER_DIS 11 +#define ARB_LOST 12 + +static char *abort_sources[] = { + [ABRT_7B_ADDR_NOACK] = + "slave address not acknowledged (7bit mode)", + [ABRT_10ADDR1_NOACK] = + "first address byte not acknowledged (10bit mode)", + [ABRT_10ADDR2_NOACK] = + "second address byte not acknowledged (10bit mode)", + [ABRT_TXDATA_NOACK] = + "data not acknowledged", + [ABRT_GCALL_NOACK] = + "no acknowledgement for a general call", + [ABRT_GCALL_READ] = + "read after general call", + [ABRT_SBYTE_ACKDET] = + "start byte acknowledged", + [ABRT_SBYTE_NORSTRT] = + "trying to send start byte when restart is disabled", + [ABRT_10B_RD_NORSTRT] = + "trying to read when restart is disabled (10bit mode)", + [ARB_MASTER_DIS] = + "trying to use disabled adapter", + [ARB_LOST] = + "lost arbitration", +}; + +/** + * struct dw_i2c_dev - private i2c-designware data + * @dev: driver model device node + * @base: IO registers pointer + * @cmd_complete: tx completion indicator + * @pump_msg: continue in progress transfers + * @lock: protect this struct and IO registers + * @clk: input reference clock + * @cmd_err: run time hadware error code + * @msgs: points to an array of messages currently being transfered + * @msgs_num: the number of elements in msgs + * @msg_write_idx: the element index of the current tx message in the msgs + * array + * @tx_buf_len: the length of the current tx buffer + * @tx_buf: the current tx buffer + * @msg_read_idx: the element index of the current rx message in the msgs + * array + * @rx_buf_len: the length of the current rx buffer + * @rx_buf: the current rx buffer + * @msg_err: error status of the current transfer + * @status: i2c master status, one of STATUS_* + * @abort_source: copy of the TX_ABRT_SOURCE register + * @irq: interrupt number for the i2c master + * @adapter: i2c subsystem adapter node + * @tx_fifo_depth: depth of the hardware tx fifo + * @rx_fifo_depth: depth of the hardware rx fifo + */ +struct dw_i2c_dev { + struct device *dev; + void __iomem *base; + struct completion cmd_complete; + struct tasklet_struct pump_msg; + struct mutex lock; + struct clk *clk; + int cmd_err; + struct i2c_msg *msgs; + int msgs_num; + int msg_write_idx; + u16 tx_buf_len; + u8 *tx_buf; + int msg_read_idx; + u16 rx_buf_len; + u8 *rx_buf; + int msg_err; + unsigned int status; + u16 abort_source; + int irq; + struct i2c_adapter adapter; + unsigned int tx_fifo_depth; + unsigned int rx_fifo_depth; +}; + +/** + * i2c_dw_init() - initialize the designware i2c master hardware + * @dev: device private data + * + * This functions configures and enables the I2C master. + * This function is called during I2C init function, and in case of timeout at + * run time. + */ +static void i2c_dw_init(struct dw_i2c_dev *dev) +{ + u32 input_clock_khz = clk_get_rate(dev->clk) / 1000; + u16 ic_con; + + /* Disable the adapter */ + writeb(0, dev->base + DW_IC_ENABLE); + + /* set standard and fast speed deviders for high/low periods */ + writew((input_clock_khz * 40 / 10000)+1, /* std speed high, 4us */ + dev->base + DW_IC_SS_SCL_HCNT); + writew((input_clock_khz * 47 / 10000)+1, /* std speed low, 4.7us */ + dev->base + DW_IC_SS_SCL_LCNT); + writew((input_clock_khz * 6 / 10000)+1, /* fast speed high, 0.6us */ + dev->base + DW_IC_FS_SCL_HCNT); + writew((input_clock_khz * 13 / 10000)+1, /* fast speed low, 1.3us */ + dev->base + DW_IC_FS_SCL_LCNT); + + /* configure the i2c master */ + ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | + DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST; + writew(ic_con, dev->base + DW_IC_CON); +} + +/* + * Waiting for bus not busy + */ +static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev) +{ + int timeout = TIMEOUT; + + while (readb(dev->base + DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) { + if (timeout <= 0) { + dev_warn(dev->dev, "timeout waiting for bus ready\n"); + return -ETIMEDOUT; + } + timeout--; + mdelay(1); + } + + return 0; +} + +/* + * Initiate low level master read/write transaction. + * This function is called from i2c_dw_xfer when starting a transfer. + * This function is also called from dw_i2c_pump_msg to continue a transfer + * that is longer than the size of the TX FIFO. + */ +static void +i2c_dw_xfer_msg(struct i2c_adapter *adap) +{ + struct dw_i2c_dev *dev = i2c_get_adapdata(adap); + struct i2c_msg *msgs = dev->msgs; + int num = dev->msgs_num; + u16 ic_con, intr_mask; + int tx_limit = dev->tx_fifo_depth - readb(dev->base + DW_IC_TXFLR); + int rx_limit = dev->rx_fifo_depth - readb(dev->base + DW_IC_RXFLR); + u16 addr = msgs[dev->msg_write_idx].addr; + u16 buf_len = dev->tx_buf_len; + + if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { + /* Disable the adapter */ + writeb(0, dev->base + DW_IC_ENABLE); + + /* set the slave (target) address */ + writew(msgs[dev->msg_write_idx].addr, dev->base + DW_IC_TAR); + + /* if the slave address is ten bit address, enable 10BITADDR */ + ic_con = readw(dev->base + DW_IC_CON); + if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) + ic_con |= DW_IC_CON_10BITADDR_MASTER; + else + ic_con &= ~DW_IC_CON_10BITADDR_MASTER; + writew(ic_con, dev->base + DW_IC_CON); + + /* Enable the adapter */ + writeb(1, dev->base + DW_IC_ENABLE); + } + + for (; dev->msg_write_idx < num; dev->msg_write_idx++) { + /* if target address has changed, we need to + * reprogram the target address in the i2c + * adapter when we are done with this transfer + */ + if (msgs[dev->msg_write_idx].addr != addr) + return; + + if (msgs[dev->msg_write_idx].len == 0) { + dev_err(dev->dev, + "%s: invalid message length\n", __func__); + dev->msg_err = -EINVAL; + return; + } + + if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { + /* new i2c_msg */ + dev->tx_buf = msgs[dev->msg_write_idx].buf; + buf_len = msgs[dev->msg_write_idx].len; + } + + while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { + if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { + writew(0x100, dev->base + DW_IC_DATA_CMD); + rx_limit--; + } else + writew(*(dev->tx_buf++), + dev->base + DW_IC_DATA_CMD); + tx_limit--; buf_len--; + } + } + + intr_mask = DW_IC_INTR_STOP_DET | DW_IC_INTR_TX_ABRT; + if (buf_len > 0) { /* more bytes to be written */ + intr_mask |= DW_IC_INTR_TX_EMPTY; + dev->status |= STATUS_WRITE_IN_PROGRESS; + } else + dev->status &= ~STATUS_WRITE_IN_PROGRESS; + writew(intr_mask, dev->base + DW_IC_INTR_MASK); + + dev->tx_buf_len = buf_len; +} + +static void +i2c_dw_read(struct i2c_adapter *adap) +{ + struct dw_i2c_dev *dev = i2c_get_adapdata(adap); + struct i2c_msg *msgs = dev->msgs; + int num = dev->msgs_num; + u16 addr = msgs[dev->msg_read_idx].addr; + int rx_valid = readw(dev->base + DW_IC_RXFLR); + + for (; dev->msg_read_idx < num; dev->msg_read_idx++) { + u16 len; + u8 *buf; + + if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD)) + continue; + + /* different i2c client, reprogram the i2c adapter */ + if (msgs[dev->msg_read_idx].addr != addr) + return; + + if (!(dev->status & STATUS_READ_IN_PROGRESS)) { + len = msgs[dev->msg_read_idx].len; + buf = msgs[dev->msg_read_idx].buf; + } else { + len = dev->rx_buf_len; + buf = dev->rx_buf; + } + + for (; len > 0 && rx_valid > 0; len--, rx_valid--) + *buf++ = readb(dev->base + DW_IC_DATA_CMD); + + if (len > 0) { + dev->status |= STATUS_READ_IN_PROGRESS; + dev->rx_buf_len = len; + dev->rx_buf = buf; + return; + } else + dev->status &= ~STATUS_READ_IN_PROGRESS; + } +} + +/* + * Prepare controller for a transaction and call i2c_dw_xfer_msg + */ +static int +i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) +{ + struct dw_i2c_dev *dev = i2c_get_adapdata(adap); + int ret; + + dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); + + mutex_lock(&dev->lock); + + INIT_COMPLETION(dev->cmd_complete); + dev->msgs = msgs; + dev->msgs_num = num; + dev->cmd_err = 0; + dev->msg_write_idx = 0; + dev->msg_read_idx = 0; + dev->msg_err = 0; + dev->status = STATUS_IDLE; + + ret = i2c_dw_wait_bus_not_busy(dev); + if (ret < 0) + goto done; + + /* start the transfers */ + i2c_dw_xfer_msg(adap); + + /* wait for tx to complete */ + ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ); + if (ret == 0) { + dev_err(dev->dev, "controller timed out\n"); + i2c_dw_init(dev); + ret = -ETIMEDOUT; + goto done; + } else if (ret < 0) + goto done; + + if (dev->msg_err) { + ret = dev->msg_err; + goto done; + } + + /* no error */ + if (likely(!dev->cmd_err)) { + /* read rx fifo, and disable the adapter */ + do { + i2c_dw_read(adap); + } while (dev->status & STATUS_READ_IN_PROGRESS); + writeb(0, dev->base + DW_IC_ENABLE); + ret = num; + goto done; + } + + /* We have an error */ + if (dev->cmd_err == DW_IC_ERR_TX_ABRT) { + unsigned long abort_source = dev->abort_source; + int i; + + for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) { + dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]); + } + } + ret = -EIO; + +done: + mutex_unlock(&dev->lock); + + return ret; +} + +static u32 i2c_dw_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; +} + +static void dw_i2c_pump_msg(unsigned long data) +{ + struct dw_i2c_dev *dev = (struct dw_i2c_dev *) data; + u16 intr_mask; + + i2c_dw_read(&dev->adapter); + i2c_dw_xfer_msg(&dev->adapter); + + intr_mask = DW_IC_INTR_STOP_DET | DW_IC_INTR_TX_ABRT; + if (dev->status & STATUS_WRITE_IN_PROGRESS) + intr_mask |= DW_IC_INTR_TX_EMPTY; + writew(intr_mask, dev->base + DW_IC_INTR_MASK); +} + +/* + * Interrupt service routine. This gets called whenever an I2C interrupt + * occurs. + */ +static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) +{ + struct dw_i2c_dev *dev = dev_id; + u16 stat; + + stat = readw(dev->base + DW_IC_INTR_STAT); + dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat); + if (stat & DW_IC_INTR_TX_ABRT) { + dev->abort_source = readw(dev->base + DW_IC_TX_ABRT_SOURCE); + dev->cmd_err |= DW_IC_ERR_TX_ABRT; + dev->status = STATUS_IDLE; + } else if (stat & DW_IC_INTR_TX_EMPTY) + tasklet_schedule(&dev->pump_msg); + + readb(dev->base + DW_IC_CLR_INTR); /* clear interrupts */ + writew(0, dev->base + DW_IC_INTR_MASK); /* disable interrupts */ + if (stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) + complete(&dev->cmd_complete); + + return IRQ_HANDLED; +} + +static struct i2c_algorithm i2c_dw_algo = { + .master_xfer = i2c_dw_xfer, + .functionality = i2c_dw_func, +}; + +static int __devinit dw_i2c_probe(struct platform_device *pdev) +{ + struct dw_i2c_dev *dev; + struct i2c_adapter *adap; + struct resource *mem, *irq, *ioarea; + int r; + + /* NOTE: driver uses the static register mapping */ + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) { + dev_err(&pdev->dev, "no mem resource?\n"); + return -EINVAL; + } + + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq) { + dev_err(&pdev->dev, "no irq resource?\n"); + return -EINVAL; + } + + ioarea = request_mem_region(mem->start, resource_size(mem), + pdev->name); + if (!ioarea) { + dev_err(&pdev->dev, "I2C region already claimed\n"); + return -EBUSY; + } + + dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL); + if (!dev) { + r = -ENOMEM; + goto err_release_region; + } + + init_completion(&dev->cmd_complete); + tasklet_init(&dev->pump_msg, dw_i2c_pump_msg, (unsigned long) dev); + mutex_init(&dev->lock); + dev->dev = get_device(&pdev->dev); + dev->irq = irq->start; + platform_set_drvdata(pdev, dev); + + dev->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(dev->clk)) { + r = -ENODEV; + goto err_free_mem; + } + clk_enable(dev->clk); + + dev->base = ioremap(mem->start, resource_size(mem)); + if (dev->base == NULL) { + dev_err(&pdev->dev, "failure mapping io resources\n"); + r = -EBUSY; + goto err_unuse_clocks; + } + { + u32 param1 = readl(dev->base + DW_IC_COMP_PARAM_1); + + dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1; + dev->rx_fifo_depth = ((param1 >> 8) & 0xff) + 1; + } + i2c_dw_init(dev); + + writew(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */ + r = request_irq(dev->irq, i2c_dw_isr, 0, pdev->name, dev); + if (r) { + dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); + goto err_iounmap; + } + + adap = &dev->adapter; + i2c_set_adapdata(adap, dev); + adap->owner = THIS_MODULE; + adap->class = I2C_CLASS_HWMON; + strlcpy(adap->name, "Synopsys DesignWare I2C adapter", + sizeof(adap->name)); + adap->algo = &i2c_dw_algo; + adap->dev.parent = &pdev->dev; + + adap->nr = pdev->id; + r = i2c_add_numbered_adapter(adap); + if (r) { + dev_err(&pdev->dev, "failure adding adapter\n"); + goto err_free_irq; + } + + return 0; + +err_free_irq: + free_irq(dev->irq, dev); +err_iounmap: + iounmap(dev->base); +err_unuse_clocks: + clk_disable(dev->clk); + clk_put(dev->clk); + dev->clk = NULL; +err_free_mem: + platform_set_drvdata(pdev, NULL); + put_device(&pdev->dev); + kfree(dev); +err_release_region: + release_mem_region(mem->start, resource_size(mem)); + + return r; +} + +static int __devexit dw_i2c_remove(struct platform_device *pdev) +{ + struct dw_i2c_dev *dev = platform_get_drvdata(pdev); + struct resource *mem; + + platform_set_drvdata(pdev, NULL); + i2c_del_adapter(&dev->adapter); + put_device(&pdev->dev); + + clk_disable(dev->clk); + clk_put(dev->clk); + dev->clk = NULL; + + writeb(0, dev->base + DW_IC_ENABLE); + free_irq(dev->irq, dev); + kfree(dev); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(mem->start, resource_size(mem)); + return 0; +} + +/* work with hotplug and coldplug */ +MODULE_ALIAS("platform:i2c_designware"); + +static struct platform_driver dw_i2c_driver = { + .remove = __devexit_p(dw_i2c_remove), + .driver = { + .name = "i2c_designware", + .owner = THIS_MODULE, + }, +}; + +static int __init dw_i2c_init_driver(void) +{ + return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe); +} +module_init(dw_i2c_init_driver); + +static void __exit dw_i2c_exit_driver(void) +{ + platform_driver_unregister(&dw_i2c_driver); +} +module_exit(dw_i2c_exit_driver); + +MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); +MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c index e5a8dae4a28..87ecace415d 100644 --- a/drivers/i2c/busses/i2c-highlander.c +++ b/drivers/i2c/busses/i2c-highlander.c @@ -373,7 +373,7 @@ static int __devinit highlander_i2c_probe(struct platform_device *pdev) if (unlikely(!dev)) return -ENOMEM; - dev->base = ioremap_nocache(res->start, res->end - res->start + 1); + dev->base = ioremap_nocache(res->start, resource_size(res)); if (unlikely(!dev->base)) { ret = -ENXIO; goto err; diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 8b92a4666e0..b1bc6e277d2 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -85,10 +85,11 @@ static void dump_iic_regs(const char* header, struct ibm_iic_private* dev) { volatile struct iic_regs __iomem *iic = dev->vaddr; printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header); - printk(KERN_DEBUG " cntl = 0x%02x, mdcntl = 0x%02x\n" - KERN_DEBUG " sts = 0x%02x, extsts = 0x%02x\n" - KERN_DEBUG " clkdiv = 0x%02x, xfrcnt = 0x%02x\n" - KERN_DEBUG " xtcntlss = 0x%02x, directcntl = 0x%02x\n", + printk(KERN_DEBUG + " cntl = 0x%02x, mdcntl = 0x%02x\n" + " sts = 0x%02x, extsts = 0x%02x\n" + " clkdiv = 0x%02x, xfrcnt = 0x%02x\n" + " xtcntlss = 0x%02x, directcntl = 0x%02x\n", in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts), in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt), in_8(&iic->xtcntlss), in_8(&iic->directcntl)); @@ -756,12 +757,12 @@ static int __devinit iic_probe(struct of_device *ofdev, goto error_cleanup; } - /* Now register all the child nodes */ - of_register_i2c_devices(adap, np); - dev_info(&ofdev->dev, "using %s mode\n", dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); + /* Now register all the child nodes */ + of_register_i2c_devices(adap, np); + return 0; error_cleanup: diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index dd778d7ae04..d325e86e310 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -197,7 +197,7 @@ int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, int prescaler) return -EINVAL; /* Determine divider value */ - divider = mpc52xx_find_ipb_freq(node) / clock; + divider = mpc5xxx_get_bus_frequency(node) / clock; /* * We want to choose an FDR/DFSR that generates an I2C bus speed that diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 5a4945d1dba..c3869d94ad4 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -469,7 +469,7 @@ mv64xxx_i2c_map_regs(struct platform_device *pd, if (!r) return -ENODEV; - size = r->end - r->start + 1; + size = resource_size(r); if (!request_mem_region(r->start, size, drv_data->adapter.name)) return -EBUSY; diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index e5193bf7548..0dabe643ec5 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -216,6 +216,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) struct ocores_i2c_platform_data *pdata; struct resource *res, *res2; int ret; + int i; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) @@ -233,14 +234,14 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) if (!i2c) return -ENOMEM; - if (!request_mem_region(res->start, res->end - res->start + 1, + if (!request_mem_region(res->start, resource_size(res), pdev->name)) { dev_err(&pdev->dev, "Memory region busy\n"); ret = -EBUSY; goto request_mem_failed; } - i2c->base = ioremap(res->start, res->end - res->start + 1); + i2c->base = ioremap(res->start, resource_size(res)); if (!i2c->base) { dev_err(&pdev->dev, "Unable to map registers\n"); ret = -EIO; @@ -271,6 +272,10 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) goto add_adapter_failed; } + /* add in known devices to the bus */ + for (i = 0; i < pdata->num_devices; i++) + i2c_new_device(&i2c->adap, pdata->devices + i); + return 0; add_adapter_failed: @@ -278,7 +283,7 @@ add_adapter_failed: request_irq_failed: iounmap(i2c->base); map_failed: - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); request_mem_failed: kfree(i2c); @@ -306,7 +311,7 @@ static int __devexit ocores_i2c_remove(struct platform_device* pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res) - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); kfree(i2c); diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index ece0125a1ee..827da085813 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -333,8 +333,18 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) if (cpu_is_omap2430() || cpu_is_omap34xx()) { - /* HSI2C controller internal clk rate should be 19.2 Mhz */ - internal_clk = 19200; + /* + * HSI2C controller internal clk rate should be 19.2 Mhz for + * HS and for all modes on 2430. On 34xx we can use lower rate + * to get longer filter period for better noise suppression. + * The filter is iclk (fclk for HS) period. + */ + if (dev->speed > 400 || cpu_is_omap2430()) + internal_clk = 19200; + else if (dev->speed > 100) + internal_clk = 9600; + else + internal_clk = 4000; fclk_rate = clk_get_rate(dev->fclk) / 1000; /* Compute prescaler divisor */ @@ -343,17 +353,28 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) /* If configured for High Speed */ if (dev->speed > 400) { + unsigned long scl; + /* For first phase of HS mode */ - fsscll = internal_clk / (400 * 2) - 6; - fssclh = internal_clk / (400 * 2) - 6; + scl = internal_clk / 400; + fsscll = scl - (scl / 3) - 7; + fssclh = (scl / 3) - 5; /* For second phase of HS mode */ - hsscll = fclk_rate / (dev->speed * 2) - 6; - hssclh = fclk_rate / (dev->speed * 2) - 6; + scl = fclk_rate / dev->speed; + hsscll = scl - (scl / 3) - 7; + hssclh = (scl / 3) - 5; + } else if (dev->speed > 100) { + unsigned long scl; + + /* Fast mode */ + scl = internal_clk / dev->speed; + fsscll = scl - (scl / 3) - 7; + fssclh = (scl / 3) - 5; } else { - /* To handle F/S modes */ - fsscll = internal_clk / (dev->speed * 2) - 6; - fssclh = internal_clk / (dev->speed * 2) - 6; + /* Standard mode */ + fsscll = internal_clk / (dev->speed * 2) - 7; + fssclh = internal_clk / (dev->speed * 2) - 5; } scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll; sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh; @@ -651,9 +672,17 @@ omap_i2c_isr(int this_irq, void *dev_id) break; } - omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); - err = 0; +complete: + /* + * Ack the stat in one go, but [R/X]DR and [R/X]RDY should be + * acked after the data operation is complete. + * Ref: TRM SWPU114Q Figure 18-31 + */ + omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat & + ~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR | + OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)); + if (stat & OMAP_I2C_STAT_NACK) { err |= OMAP_I2C_STAT_NACK; omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, @@ -664,16 +693,22 @@ omap_i2c_isr(int this_irq, void *dev_id) err |= OMAP_I2C_STAT_AL; } if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK | - OMAP_I2C_STAT_AL)) + OMAP_I2C_STAT_AL)) { + omap_i2c_ack_stat(dev, stat & + (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR | + OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)); omap_i2c_complete_cmd(dev, err); + return IRQ_HANDLED; + } if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) { u8 num_bytes = 1; if (dev->fifo_size) { if (stat & OMAP_I2C_STAT_RRDY) num_bytes = dev->fifo_size; - else - num_bytes = omap_i2c_read_reg(dev, - OMAP_I2C_BUFSTAT_REG); + else /* read RXSTAT on RDR interrupt */ + num_bytes = (omap_i2c_read_reg(dev, + OMAP_I2C_BUFSTAT_REG) + >> 8) & 0x3F; } while (num_bytes) { num_bytes--; @@ -710,9 +745,10 @@ omap_i2c_isr(int this_irq, void *dev_id) if (dev->fifo_size) { if (stat & OMAP_I2C_STAT_XRDY) num_bytes = dev->fifo_size; - else + else /* read TXSTAT on XDR interrupt */ num_bytes = omap_i2c_read_reg(dev, - OMAP_I2C_BUFSTAT_REG); + OMAP_I2C_BUFSTAT_REG) + & 0x3F; } while (num_bytes) { num_bytes--; @@ -739,6 +775,27 @@ omap_i2c_isr(int this_irq, void *dev_id) "data to send\n"); 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); + } + } + omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); } omap_i2c_ack_stat(dev, @@ -785,7 +842,7 @@ omap_i2c_probe(struct platform_device *pdev) return -ENODEV; } - ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1, + ioarea = request_mem_region(mem->start, resource_size(mem), pdev->name); if (!ioarea) { dev_err(&pdev->dev, "I2C region already claimed\n"); @@ -807,7 +864,7 @@ omap_i2c_probe(struct platform_device *pdev) dev->idle = 1; dev->dev = &pdev->dev; dev->irq = irq->start; - dev->base = ioremap(mem->start, mem->end - mem->start + 1); + dev->base = ioremap(mem->start, resource_size(mem)); if (!dev->base) { r = -ENOMEM; goto err_free_mem; @@ -858,7 +915,7 @@ omap_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(adap, dev); adap->owner = THIS_MODULE; adap->class = I2C_CLASS_HWMON; - strncpy(adap->name, "OMAP I2C adapter", sizeof(adap->name)); + strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name)); adap->algo = &omap_i2c_algo; adap->dev.parent = &pdev->dev; @@ -884,7 +941,7 @@ err_free_mem: platform_set_drvdata(pdev, NULL); kfree(dev); err_release_region: - release_mem_region(mem->start, (mem->end - mem->start) + 1); + release_mem_region(mem->start, resource_size(mem)); return r; } @@ -904,7 +961,7 @@ omap_i2c_remove(struct platform_device *pdev) iounmap(dev->base); kfree(dev); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(mem->start, (mem->end - mem->start) + 1); + release_mem_region(mem->start, resource_size(mem)); return 0; } diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 7b23891b7d5..c4df9d411cd 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -27,8 +27,6 @@ #include <asm/irq.h> #include <asm/io.h> -#define res_len(r) ((r)->end - (r)->start + 1) - struct i2c_pca_pf_data { void __iomem *reg_base; int irq; /* if 0, use polling */ @@ -148,7 +146,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) goto e_print; } - if (!request_mem_region(res->start, res_len(res), res->name)) { + if (!request_mem_region(res->start, resource_size(res), res->name)) { ret = -ENOMEM; goto e_print; } @@ -161,13 +159,13 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) init_waitqueue_head(&i2c->wait); - i2c->reg_base = ioremap(res->start, res_len(res)); + i2c->reg_base = ioremap(res->start, resource_size(res)); if (!i2c->reg_base) { ret = -ENOMEM; goto e_remap; } i2c->io_base = res->start; - i2c->io_size = res_len(res); + i2c->io_size = resource_size(res); i2c->irq = irq; i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0; @@ -250,7 +248,7 @@ e_reqirq: e_remap: kfree(i2c); e_alloc: - release_mem_region(res->start, res_len(res)); + release_mem_region(res->start, resource_size(res)); e_print: printk(KERN_ERR "Registering PCA9564/PCA9665 FAILED! (%d)\n", ret); return ret; diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index 0bdb2d7f057..7b57d5f267e 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c @@ -283,7 +283,7 @@ static int __devinit pmcmsptwi_probe(struct platform_device *pldev) } /* reserve the memory region */ - if (!request_mem_region(res->start, res->end - res->start + 1, + if (!request_mem_region(res->start, resource_size(res), pldev->name)) { dev_err(&pldev->dev, "Unable to get memory/io address region 0x%08x\n", @@ -294,7 +294,7 @@ static int __devinit pmcmsptwi_probe(struct platform_device *pldev) /* remap the memory */ pmcmsptwi_data.iobase = ioremap_nocache(res->start, - res->end - res->start + 1); + resource_size(res)); if (!pmcmsptwi_data.iobase) { dev_err(&pldev->dev, "Unable to ioremap address 0x%08x\n", res->start); @@ -360,7 +360,7 @@ ret_unmap: iounmap(pmcmsptwi_data.iobase); ret_unreserve: - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); ret_err: return rc; @@ -385,7 +385,7 @@ static int __devexit pmcmsptwi_remove(struct platform_device *pldev) iounmap(pmcmsptwi_data.iobase); res = platform_get_resource(pldev, IORESOURCE_MEM, 0); - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); return 0; } diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index acc7143d965..762e1e53088 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -34,10 +34,24 @@ #include <linux/err.h> #include <linux/clk.h> -#include <mach/hardware.h> #include <asm/irq.h> #include <asm/io.h> -#include <mach/i2c.h> +#include <plat/i2c.h> + +/* + * I2C register offsets will be shifted 0 or 1 bit left, depending on + * different SoCs + */ +#define REG_SHIFT_0 (0 << 0) +#define REG_SHIFT_1 (1 << 0) +#define REG_SHIFT(d) ((d) & 0x1) + +static const struct platform_device_id i2c_pxa_id_table[] = { + { "pxa2xx-i2c", REG_SHIFT_1 }, + { "pxa3xx-pwri2c", REG_SHIFT_0 }, + { }, +}; +MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table); /* * I2C registers and bit definitions @@ -979,12 +993,12 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = { .functionality = i2c_pxa_functionality, }; -#define res_len(r) ((r)->end - (r)->start + 1) static int i2c_pxa_probe(struct platform_device *dev) { struct pxa_i2c *i2c; struct resource *res; struct i2c_pxa_platform_data *plat = dev->dev.platform_data; + struct platform_device_id *id = platform_get_device_id(dev); int ret; int irq; @@ -993,7 +1007,7 @@ static int i2c_pxa_probe(struct platform_device *dev) if (res == NULL || irq < 0) return -ENODEV; - if (!request_mem_region(res->start, res_len(res), res->name)) + if (!request_mem_region(res->start, resource_size(res), res->name)) return -ENOMEM; i2c = kzalloc(sizeof(struct pxa_i2c), GFP_KERNEL); @@ -1023,15 +1037,15 @@ static int i2c_pxa_probe(struct platform_device *dev) goto eclk; } - i2c->reg_base = ioremap(res->start, res_len(res)); + i2c->reg_base = ioremap(res->start, resource_size(res)); if (!i2c->reg_base) { ret = -EIO; goto eremap; } - i2c->reg_shift = (cpu_is_pxa3xx() && (dev->id == 1)) ? 0 : 1; + i2c->reg_shift = REG_SHIFT(id->driver_data); i2c->iobase = res->start; - i2c->iosize = res_len(res); + i2c->iosize = resource_size(res); i2c->irq = irq; @@ -1095,7 +1109,7 @@ eremap: eclk: kfree(i2c); emalloc: - release_mem_region(res->start, res_len(res)); + release_mem_region(res->start, resource_size(res)); return ret; } @@ -1150,6 +1164,7 @@ static struct platform_driver i2c_pxa_driver = { .name = "pxa2xx-i2c", .owner = THIS_MODULE, }, + .id_table = i2c_pxa_id_table, }; static int __init i2c_adap_pxa_init(void) diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 1691ef0f1ee..20bb0ceb027 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -51,6 +51,11 @@ enum s3c24xx_i2c_state { STATE_STOP }; +enum s3c24xx_i2c_type { + TYPE_S3C2410, + TYPE_S3C2440, +}; + struct s3c24xx_i2c { spinlock_t lock; wait_queue_head_t wait; @@ -88,8 +93,10 @@ struct s3c24xx_i2c { static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c) { struct platform_device *pdev = to_platform_device(i2c->dev); + enum s3c24xx_i2c_type type; - return !strcmp(pdev->name, "s3c2440-i2c"); + type = platform_get_device_id(pdev)->driver_data; + return type == TYPE_S3C2440; } /* s3c24xx_i2c_master_complete @@ -756,11 +763,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); - /* check for s3c2440 i2c controller */ - - if (s3c24xx_i2c_is2440(i2c)) - writel(0x0, i2c->regs + S3C2440_IICLC); - return 0; } @@ -821,7 +823,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) goto err_clk; } - i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1, + i2c->ioarea = request_mem_region(res->start, resource_size(res), pdev->name); if (i2c->ioarea == NULL) { @@ -830,7 +832,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) goto err_clk; } - i2c->regs = ioremap(res->start, (res->end-res->start)+1); + i2c->regs = ioremap(res->start, resource_size(res)); if (i2c->regs == NULL) { dev_err(&pdev->dev, "cannot map IO\n"); @@ -969,52 +971,41 @@ static int s3c24xx_i2c_resume(struct platform_device *dev) /* device driver for platform bus bits */ -static struct platform_driver s3c2410_i2c_driver = { - .probe = s3c24xx_i2c_probe, - .remove = s3c24xx_i2c_remove, - .suspend_late = s3c24xx_i2c_suspend_late, - .resume = s3c24xx_i2c_resume, - .driver = { - .owner = THIS_MODULE, - .name = "s3c2410-i2c", - }, +static struct platform_device_id s3c24xx_driver_ids[] = { + { + .name = "s3c2410-i2c", + .driver_data = TYPE_S3C2410, + }, { + .name = "s3c2440-i2c", + .driver_data = TYPE_S3C2440, + }, { }, }; +MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); -static struct platform_driver s3c2440_i2c_driver = { +static struct platform_driver s3c24xx_i2c_driver = { .probe = s3c24xx_i2c_probe, .remove = s3c24xx_i2c_remove, .suspend_late = s3c24xx_i2c_suspend_late, .resume = s3c24xx_i2c_resume, + .id_table = s3c24xx_driver_ids, .driver = { .owner = THIS_MODULE, - .name = "s3c2440-i2c", + .name = "s3c-i2c", }, }; static int __init i2c_adap_s3c_init(void) { - int ret; - - ret = platform_driver_register(&s3c2410_i2c_driver); - if (ret == 0) { - ret = platform_driver_register(&s3c2440_i2c_driver); - if (ret) - platform_driver_unregister(&s3c2410_i2c_driver); - } - - return ret; + return platform_driver_register(&s3c24xx_i2c_driver); } subsys_initcall(i2c_adap_s3c_init); static void __exit i2c_adap_s3c_exit(void) { - platform_driver_unregister(&s3c2410_i2c_driver); - platform_driver_unregister(&s3c2440_i2c_driver); + platform_driver_unregister(&s3c24xx_i2c_driver); } module_exit(i2c_adap_s3c_exit); MODULE_DESCRIPTION("S3C24XX I2C Bus driver"); MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:s3c2410-i2c"); -MODULE_ALIAS("platform:s3c2440-i2c"); diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c index baa28b73ae4..b9680f50f54 100644 --- a/drivers/i2c/busses/i2c-sh7760.c +++ b/drivers/i2c/busses/i2c-sh7760.c @@ -396,7 +396,7 @@ static int __devinit calc_CCR(unsigned long scl_hz) signed char cdf, cdfm; int scgd, scgdm, scgds; - mclk = clk_get(NULL, "module_clk"); + mclk = clk_get(NULL, "peripheral_clk"); if (IS_ERR(mclk)) { return PTR_ERR(mclk); } else { diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 1c01083b01b..820487d0d5c 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -563,7 +563,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) goto err_irq; } - size = (res->end - res->start) + 1; + size = resource_size(res); pd->reg = ioremap(res->start, size); if (pd->reg == NULL) { @@ -637,7 +637,7 @@ static void __exit sh_mobile_i2c_adap_exit(void) platform_driver_unregister(&sh_mobile_i2c_driver); } -module_init(sh_mobile_i2c_adap_init); +subsys_initcall(sh_mobile_i2c_adap_init); module_exit(sh_mobile_i2c_adap_exit); MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver"); diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c index 042fda295f3..6407f47bda8 100644 --- a/drivers/i2c/busses/i2c-simtec.c +++ b/drivers/i2c/busses/i2c-simtec.c @@ -92,7 +92,7 @@ static int simtec_i2c_probe(struct platform_device *dev) goto err; } - size = (res->end-res->start)+1; + size = resource_size(res); pd->ioarea = request_mem_region(res->start, size, dev->name); if (pd->ioarea == NULL) { diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c new file mode 100644 index 00000000000..d2728a28a8d --- /dev/null +++ b/drivers/i2c/busses/i2c-stu300.c @@ -0,0 +1,1056 @@ +/* + * Copyright (C) 2007-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * ST DDC I2C master mode driver, used in e.g. U300 series platforms. + * Author: Linus Walleij <linus.walleij@stericsson.com> + * Author: Jonas Aaberg <jonas.aberg@stericsson.com> + */ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/spinlock.h> +#include <linux/completion.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/clk.h> +#include <linux/io.h> + +/* the name of this kernel module */ +#define NAME "stu300" + +/* CR (Control Register) 8bit (R/W) */ +#define I2C_CR (0x00000000) +#define I2C_CR_RESET_VALUE (0x00) +#define I2C_CR_RESET_UMASK (0x00) +#define I2C_CR_DDC1_ENABLE (0x80) +#define I2C_CR_TRANS_ENABLE (0x40) +#define I2C_CR_PERIPHERAL_ENABLE (0x20) +#define I2C_CR_DDC2B_ENABLE (0x10) +#define I2C_CR_START_ENABLE (0x08) +#define I2C_CR_ACK_ENABLE (0x04) +#define I2C_CR_STOP_ENABLE (0x02) +#define I2C_CR_INTERRUPT_ENABLE (0x01) +/* SR1 (Status Register 1) 8bit (R/-) */ +#define I2C_SR1 (0x00000004) +#define I2C_SR1_RESET_VALUE (0x00) +#define I2C_SR1_RESET_UMASK (0x00) +#define I2C_SR1_EVF_IND (0x80) +#define I2C_SR1_ADD10_IND (0x40) +#define I2C_SR1_TRA_IND (0x20) +#define I2C_SR1_BUSY_IND (0x10) +#define I2C_SR1_BTF_IND (0x08) +#define I2C_SR1_ADSL_IND (0x04) +#define I2C_SR1_MSL_IND (0x02) +#define I2C_SR1_SB_IND (0x01) +/* SR2 (Status Register 2) 8bit (R/-) */ +#define I2C_SR2 (0x00000008) +#define I2C_SR2_RESET_VALUE (0x00) +#define I2C_SR2_RESET_UMASK (0x40) +#define I2C_SR2_MASK (0xBF) +#define I2C_SR2_SCLFAL_IND (0x80) +#define I2C_SR2_ENDAD_IND (0x20) +#define I2C_SR2_AF_IND (0x10) +#define I2C_SR2_STOPF_IND (0x08) +#define I2C_SR2_ARLO_IND (0x04) +#define I2C_SR2_BERR_IND (0x02) +#define I2C_SR2_DDC2BF_IND (0x01) +/* CCR (Clock Control Register) 8bit (R/W) */ +#define I2C_CCR (0x0000000C) +#define I2C_CCR_RESET_VALUE (0x00) +#define I2C_CCR_RESET_UMASK (0x00) +#define I2C_CCR_MASK (0xFF) +#define I2C_CCR_FMSM (0x80) +#define I2C_CCR_CC_MASK (0x7F) +/* OAR1 (Own Address Register 1) 8bit (R/W) */ +#define I2C_OAR1 (0x00000010) +#define I2C_OAR1_RESET_VALUE (0x00) +#define I2C_OAR1_RESET_UMASK (0x00) +#define I2C_OAR1_ADD_MASK (0xFF) +/* OAR2 (Own Address Register 2) 8bit (R/W) */ +#define I2C_OAR2 (0x00000014) +#define I2C_OAR2_RESET_VALUE (0x40) +#define I2C_OAR2_RESET_UMASK (0x19) +#define I2C_OAR2_MASK (0xE6) +#define I2C_OAR2_FR_25_10MHZ (0x00) +#define I2C_OAR2_FR_10_1667MHZ (0x20) +#define I2C_OAR2_FR_1667_2667MHZ (0x40) +#define I2C_OAR2_FR_2667_40MHZ (0x60) +#define I2C_OAR2_FR_40_5333MHZ (0x80) +#define I2C_OAR2_FR_5333_66MHZ (0xA0) +#define I2C_OAR2_FR_66_80MHZ (0xC0) +#define I2C_OAR2_FR_80_100MHZ (0xE0) +#define I2C_OAR2_FR_MASK (0xE0) +#define I2C_OAR2_ADD_MASK (0x06) +/* DR (Data Register) 8bit (R/W) */ +#define I2C_DR (0x00000018) +#define I2C_DR_RESET_VALUE (0x00) +#define I2C_DR_RESET_UMASK (0xFF) +#define I2C_DR_D_MASK (0xFF) +/* ECCR (Extended Clock Control Register) 8bit (R/W) */ +#define I2C_ECCR (0x0000001C) +#define I2C_ECCR_RESET_VALUE (0x00) +#define I2C_ECCR_RESET_UMASK (0xE0) +#define I2C_ECCR_MASK (0x1F) +#define I2C_ECCR_CC_MASK (0x1F) + +/* + * These events are more or less responses to commands + * sent into the hardware, presumably reflecting the state + * of an internal state machine. + */ +enum stu300_event { + STU300_EVENT_NONE = 0, + STU300_EVENT_1, + STU300_EVENT_2, + STU300_EVENT_3, + STU300_EVENT_4, + STU300_EVENT_5, + STU300_EVENT_6, + STU300_EVENT_7, + STU300_EVENT_8, + STU300_EVENT_9 +}; + +enum stu300_error { + STU300_ERROR_NONE = 0, + STU300_ERROR_ACKNOWLEDGE_FAILURE, + STU300_ERROR_BUS_ERROR, + STU300_ERROR_ARBITRATION_LOST, + STU300_ERROR_UNKNOWN +}; + +/* timeout waiting for the controller to respond */ +#define STU300_TIMEOUT (msecs_to_jiffies(1000)) + +/* + * The number of address send athemps tried before giving up. + * If the first one failes it seems like 5 to 8 attempts are required. + */ +#define NUM_ADDR_RESEND_ATTEMPTS 12 + +/* I2C clock speed, in Hz 0-400kHz*/ +static unsigned int scl_frequency = 100000; +module_param(scl_frequency, uint, 0644); + +/** + * struct stu300_dev - the stu300 driver state holder + * @pdev: parent platform device + * @adapter: corresponding I2C adapter + * @phybase: location of I/O area in memory + * @physize: size of I/O area in memory + * @clk: hardware block clock + * @irq: assigned interrupt line + * @cmd_issue_lock: this locks the following cmd_ variables + * @cmd_complete: acknowledge completion for an I2C command + * @cmd_event: expected event coming in as a response to a command + * @cmd_err: error code as response to a command + * @speed: current bus speed in Hz + * @msg_index: index of current message + * @msg_len: length of current message + */ + +struct stu300_dev { + struct platform_device *pdev; + struct i2c_adapter adapter; + resource_size_t phybase; + resource_size_t physize; + void __iomem *virtbase; + struct clk *clk; + int irq; + spinlock_t cmd_issue_lock; + struct completion cmd_complete; + enum stu300_event cmd_event; + enum stu300_error cmd_err; + unsigned int speed; + int msg_index; + int msg_len; +}; + +/* Local forward function declarations */ +static int stu300_init_hw(struct stu300_dev *dev); + +/* + * The block needs writes in both MSW and LSW in order + * for all data lines to reach their destination. + */ +static inline void stu300_wr8(u32 value, void __iomem *address) +{ + writel((value << 16) | value, address); +} + +/* + * This merely masks off the duplicates which appear + * in bytes 1-3. You _MUST_ use 32-bit bus access on this + * device, else it will not work. + */ +static inline u32 stu300_r8(void __iomem *address) +{ + return readl(address) & 0x000000FFU; +} + +static void stu300_irq_enable(struct stu300_dev *dev) +{ + u32 val; + val = stu300_r8(dev->virtbase + I2C_CR); + val |= I2C_CR_INTERRUPT_ENABLE; + /* Twice paranoia (possible HW glitch) */ + stu300_wr8(val, dev->virtbase + I2C_CR); + stu300_wr8(val, dev->virtbase + I2C_CR); +} + +static void stu300_irq_disable(struct stu300_dev *dev) +{ + u32 val; + val = stu300_r8(dev->virtbase + I2C_CR); + val &= ~I2C_CR_INTERRUPT_ENABLE; + /* Twice paranoia (possible HW glitch) */ + stu300_wr8(val, dev->virtbase + I2C_CR); + stu300_wr8(val, dev->virtbase + I2C_CR); +} + + +/* + * Tells whether a certain event or events occurred in + * response to a command. The events represent states in + * the internal state machine of the hardware. The events + * are not very well described in the hardware + * documentation and can only be treated as abstract state + * machine states. + * + * @ret 0 = event has not occurred or unknown error, any + * other value means the correct event occurred or an error. + */ + +static int stu300_event_occurred(struct stu300_dev *dev, + enum stu300_event mr_event) { + u32 status1; + u32 status2; + + /* What event happened? */ + status1 = stu300_r8(dev->virtbase + I2C_SR1); + + if (!(status1 & I2C_SR1_EVF_IND)) + /* No event at all */ + return 0; + + status2 = stu300_r8(dev->virtbase + I2C_SR2); + + /* Block any multiple interrupts */ + stu300_irq_disable(dev); + + /* Check for errors first */ + if (status2 & I2C_SR2_AF_IND) { + dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE; + return 1; + } else if (status2 & I2C_SR2_BERR_IND) { + dev->cmd_err = STU300_ERROR_BUS_ERROR; + return 1; + } else if (status2 & I2C_SR2_ARLO_IND) { + dev->cmd_err = STU300_ERROR_ARBITRATION_LOST; + return 1; + } + + switch (mr_event) { + case STU300_EVENT_1: + if (status1 & I2C_SR1_ADSL_IND) + return 1; + break; + case STU300_EVENT_2: + case STU300_EVENT_3: + case STU300_EVENT_7: + case STU300_EVENT_8: + if (status1 & I2C_SR1_BTF_IND) { + return 1; + } + break; + case STU300_EVENT_4: + if (status2 & I2C_SR2_STOPF_IND) + return 1; + break; + case STU300_EVENT_5: + if (status1 & I2C_SR1_SB_IND) + /* Clear start bit */ + return 1; + break; + case STU300_EVENT_6: + if (status2 & I2C_SR2_ENDAD_IND) { + /* First check for any errors */ + return 1; + } + break; + case STU300_EVENT_9: + if (status1 & I2C_SR1_ADD10_IND) + return 1; + break; + default: + break; + } + /* If we get here, we're on thin ice. + * Here we are in a status where we have + * gotten a response that does not match + * what we requested. + */ + dev->cmd_err = STU300_ERROR_UNKNOWN; + dev_err(&dev->pdev->dev, + "Unhandled interrupt! %d sr1: 0x%x sr2: 0x%x\n", + mr_event, status1, status2); + return 0; +} + +static irqreturn_t stu300_irh(int irq, void *data) +{ + struct stu300_dev *dev = data; + int res; + + /* Just make sure that the block is clocked */ + clk_enable(dev->clk); + + /* See if this was what we were waiting for */ + spin_lock(&dev->cmd_issue_lock); + + res = stu300_event_occurred(dev, dev->cmd_event); + if (res || dev->cmd_err != STU300_ERROR_NONE) + complete(&dev->cmd_complete); + + spin_unlock(&dev->cmd_issue_lock); + + clk_disable(dev->clk); + + return IRQ_HANDLED; +} + +/* + * Sends a command and then waits for the bits masked by *flagmask* + * to go high or low by IRQ awaiting. + */ +static int stu300_start_and_await_event(struct stu300_dev *dev, + u8 cr_value, + enum stu300_event mr_event) +{ + int ret; + + if (unlikely(irqs_disabled())) { + /* TODO: implement polling for this case if need be. */ + WARN(1, "irqs are disabled, cannot poll for event\n"); + return -EIO; + } + + /* Lock command issue, fill in an event we wait for */ + spin_lock_irq(&dev->cmd_issue_lock); + init_completion(&dev->cmd_complete); + dev->cmd_err = STU300_ERROR_NONE; + dev->cmd_event = mr_event; + spin_unlock_irq(&dev->cmd_issue_lock); + + /* Turn on interrupt, send command and wait. */ + cr_value |= I2C_CR_INTERRUPT_ENABLE; + stu300_wr8(cr_value, dev->virtbase + I2C_CR); + ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, + STU300_TIMEOUT); + if (ret < 0) { + dev_err(&dev->pdev->dev, + "wait_for_completion_interruptible_timeout() " + "returned %d waiting for event %04x\n", ret, mr_event); + return ret; + } + + if (ret == 0) { + dev_err(&dev->pdev->dev, "controller timed out " + "waiting for event %d, reinit hardware\n", mr_event); + (void) stu300_init_hw(dev); + return -ETIMEDOUT; + } + + if (dev->cmd_err != STU300_ERROR_NONE) { + dev_err(&dev->pdev->dev, "controller (start) " + "error %d waiting for event %d, reinit hardware\n", + dev->cmd_err, mr_event); + (void) stu300_init_hw(dev); + return -EIO; + } + + return 0; +} + +/* + * This waits for a flag to be set, if it is not set on entry, an interrupt is + * configured to wait for the flag using a completion. + */ +static int stu300_await_event(struct stu300_dev *dev, + enum stu300_event mr_event) +{ + int ret; + + if (unlikely(irqs_disabled())) { + /* TODO: implement polling for this case if need be. */ + dev_err(&dev->pdev->dev, "irqs are disabled on this " + "system!\n"); + return -EIO; + } + + /* Is it already here? */ + spin_lock_irq(&dev->cmd_issue_lock); + dev->cmd_err = STU300_ERROR_NONE; + dev->cmd_event = mr_event; + + init_completion(&dev->cmd_complete); + + /* Turn on the I2C interrupt for current operation */ + stu300_irq_enable(dev); + + /* Unlock the command block and wait for the event to occur */ + spin_unlock_irq(&dev->cmd_issue_lock); + + ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, + STU300_TIMEOUT); + if (ret < 0) { + dev_err(&dev->pdev->dev, + "wait_for_completion_interruptible_timeout()" + "returned %d waiting for event %04x\n", ret, mr_event); + return ret; + } + + if (ret == 0) { + if (mr_event != STU300_EVENT_6) { + dev_err(&dev->pdev->dev, "controller " + "timed out waiting for event %d, reinit " + "hardware\n", mr_event); + (void) stu300_init_hw(dev); + } + return -ETIMEDOUT; + } + + if (dev->cmd_err != STU300_ERROR_NONE) { + if (mr_event != STU300_EVENT_6) { + dev_err(&dev->pdev->dev, "controller " + "error (await_event) %d waiting for event %d, " + "reinit hardware\n", dev->cmd_err, mr_event); + (void) stu300_init_hw(dev); + } + return -EIO; + } + + return 0; +} + +/* + * Waits for the busy bit to go low by repeated polling. + */ +#define BUSY_RELEASE_ATTEMPTS 10 +static int stu300_wait_while_busy(struct stu300_dev *dev) +{ + unsigned long timeout; + int i; + + for (i = 0; i < BUSY_RELEASE_ATTEMPTS; i++) { + timeout = jiffies + STU300_TIMEOUT; + + while (!time_after(jiffies, timeout)) { + /* Is not busy? */ + if ((stu300_r8(dev->virtbase + I2C_SR1) & + I2C_SR1_BUSY_IND) == 0) + return 0; + msleep(1); + } + + dev_err(&dev->pdev->dev, "transaction timed out " + "waiting for device to be free (not busy). " + "Attempt: %d\n", i+1); + + dev_err(&dev->pdev->dev, "base address = " + "0x%08x, reinit hardware\n", (u32) dev->virtbase); + + (void) stu300_init_hw(dev); + } + + dev_err(&dev->pdev->dev, "giving up after %d attempts " + "to reset the bus.\n", BUSY_RELEASE_ATTEMPTS); + + return -ETIMEDOUT; +} + +struct stu300_clkset { + unsigned long rate; + u32 setting; +}; + +static const struct stu300_clkset stu300_clktable[] = { + { 0, 0xFFU }, + { 2500000, I2C_OAR2_FR_25_10MHZ }, + { 10000000, I2C_OAR2_FR_10_1667MHZ }, + { 16670000, I2C_OAR2_FR_1667_2667MHZ }, + { 26670000, I2C_OAR2_FR_2667_40MHZ }, + { 40000000, I2C_OAR2_FR_40_5333MHZ }, + { 53330000, I2C_OAR2_FR_5333_66MHZ }, + { 66000000, I2C_OAR2_FR_66_80MHZ }, + { 80000000, I2C_OAR2_FR_80_100MHZ }, + { 100000000, 0xFFU }, +}; + + +static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate) +{ + + u32 val; + int i = 0; + + /* Locate the apropriate clock setting */ + while (i < ARRAY_SIZE(stu300_clktable) && + stu300_clktable[i].rate < clkrate) + i++; + + if (stu300_clktable[i].setting == 0xFFU) { + dev_err(&dev->pdev->dev, "too %s clock rate requested " + "(%lu Hz).\n", i ? "high" : "low", clkrate); + return -EINVAL; + } + + stu300_wr8(stu300_clktable[i].setting, + dev->virtbase + I2C_OAR2); + + dev_dbg(&dev->pdev->dev, "Clock rate %lu Hz, I2C bus speed %d Hz " + "virtbase %p\n", clkrate, dev->speed, dev->virtbase); + + if (dev->speed > 100000) + /* Fast Mode I2C */ + val = ((clkrate/dev->speed) - 9)/3 + 1; + else + /* Standard Mode I2C */ + val = ((clkrate/dev->speed) - 7)/2 + 1; + + /* According to spec the divider must be > 2 */ + if (val < 0x002) { + dev_err(&dev->pdev->dev, "too low clock rate (%lu Hz).\n", + clkrate); + return -EINVAL; + } + + /* We have 12 bits clock divider only! */ + if (val & 0xFFFFF000U) { + dev_err(&dev->pdev->dev, "too high clock rate (%lu Hz).\n", + clkrate); + return -EINVAL; + } + + if (dev->speed > 100000) { + /* CC6..CC0 */ + stu300_wr8((val & I2C_CCR_CC_MASK) | I2C_CCR_FMSM, + dev->virtbase + I2C_CCR); + dev_dbg(&dev->pdev->dev, "set clock divider to 0x%08x, " + "Fast Mode I2C\n", val); + } else { + /* CC6..CC0 */ + stu300_wr8((val & I2C_CCR_CC_MASK), + dev->virtbase + I2C_CCR); + dev_dbg(&dev->pdev->dev, "set clock divider to " + "0x%08x, Standard Mode I2C\n", val); + } + + /* CC11..CC7 */ + stu300_wr8(((val >> 7) & 0x1F), + dev->virtbase + I2C_ECCR); + + return 0; +} + + +static int stu300_init_hw(struct stu300_dev *dev) +{ + u32 dummy; + unsigned long clkrate; + int ret; + + /* Disable controller */ + stu300_wr8(0x00, dev->virtbase + I2C_CR); + /* + * Set own address to some default value (0x00). + * We do not support slave mode anyway. + */ + stu300_wr8(0x00, dev->virtbase + I2C_OAR1); + /* + * The I2C controller only operates properly in 26 MHz but we + * program this driver as if we didn't know. This will also set the two + * high bits of the own address to zero as well. + * There is no known hardware issue with running in 13 MHz + * However, speeds over 200 kHz are not used. + */ + clkrate = clk_get_rate(dev->clk); + ret = stu300_set_clk(dev, clkrate); + + if (ret) + return ret; + /* + * Enable block, do it TWICE (hardware glitch) + * Setting bit 7 can enable DDC mode. (Not used currently.) + */ + stu300_wr8(I2C_CR_PERIPHERAL_ENABLE, + dev->virtbase + I2C_CR); + stu300_wr8(I2C_CR_PERIPHERAL_ENABLE, + dev->virtbase + I2C_CR); + /* Make a dummy read of the status register SR1 & SR2 */ + dummy = stu300_r8(dev->virtbase + I2C_SR2); + dummy = stu300_r8(dev->virtbase + I2C_SR1); + + return 0; +} + + + +/* Send slave address. */ +static int stu300_send_address(struct stu300_dev *dev, + struct i2c_msg *msg, int resend) +{ + u32 val; + int ret; + + if (msg->flags & I2C_M_TEN) + /* This is probably how 10 bit addresses look */ + val = (0xf0 | (((u32) msg->addr & 0x300) >> 7)) & + I2C_DR_D_MASK; + else + val = ((msg->addr << 1) & I2C_DR_D_MASK); + + if (msg->flags & I2C_M_RD) { + /* This is the direction bit */ + val |= 0x01; + if (resend) + dev_dbg(&dev->pdev->dev, "read resend\n"); + } else if (resend) + dev_dbg(&dev->pdev->dev, "write resend\n"); + stu300_wr8(val, dev->virtbase + I2C_DR); + + /* For 10bit addressing, await 10bit request (EVENT 9) */ + if (msg->flags & I2C_M_TEN) { + ret = stu300_await_event(dev, STU300_EVENT_9); + /* + * The slave device wants a 10bit address, send the rest + * of the bits (the LSBits) + */ + val = msg->addr & I2C_DR_D_MASK; + /* This clears "event 9" */ + stu300_wr8(val, dev->virtbase + I2C_DR); + if (ret != 0) + return ret; + } + /* FIXME: Why no else here? two events for 10bit? + * Await event 6 (normal) or event 9 (10bit) + */ + + if (resend) + dev_dbg(&dev->pdev->dev, "await event 6\n"); + ret = stu300_await_event(dev, STU300_EVENT_6); + + /* + * Clear any pending EVENT 6 no matter what happend during + * await_event. + */ + val = stu300_r8(dev->virtbase + I2C_CR); + val |= I2C_CR_PERIPHERAL_ENABLE; + stu300_wr8(val, dev->virtbase + I2C_CR); + + return ret; +} + +static int stu300_xfer_msg(struct i2c_adapter *adap, + struct i2c_msg *msg, int stop) +{ + u32 cr; + u32 val; + u32 i; + int ret; + int attempts = 0; + struct stu300_dev *dev = i2c_get_adapdata(adap); + + clk_enable(dev->clk); + + /* Remove this if (0) to trace each and every message. */ + if (0) { + dev_dbg(&dev->pdev->dev, "I2C message to: 0x%04x, len: %d, " + "flags: 0x%04x, stop: %d\n", + msg->addr, msg->len, msg->flags, stop); + } + + /* Zero-length messages are not supported by this hardware */ + if (msg->len == 0) { + ret = -EINVAL; + goto exit_disable; + } + + /* + * For some reason, sending the address sometimes fails when running + * on the 13 MHz clock. No interrupt arrives. This is a work around, + * which tries to restart and send the address up to 10 times before + * really giving up. Usually 5 to 8 attempts are enough. + */ + do { + if (attempts) + dev_dbg(&dev->pdev->dev, "wait while busy\n"); + /* Check that the bus is free, or wait until some timeout */ + ret = stu300_wait_while_busy(dev); + if (ret != 0) + goto exit_disable; + + if (attempts) + dev_dbg(&dev->pdev->dev, "re-int hw\n"); + /* + * According to ST, there is no problem if the clock is + * changed between 13 and 26 MHz during a transfer. + */ + ret = stu300_init_hw(dev); + if (ret) + goto exit_disable; + + /* Send a start condition */ + cr = I2C_CR_PERIPHERAL_ENABLE; + /* Setting the START bit puts the block in master mode */ + if (!(msg->flags & I2C_M_NOSTART)) + cr |= I2C_CR_START_ENABLE; + if ((msg->flags & I2C_M_RD) && (msg->len > 1)) + /* On read more than 1 byte, we need ack. */ + cr |= I2C_CR_ACK_ENABLE; + /* Check that it gets through */ + if (!(msg->flags & I2C_M_NOSTART)) { + if (attempts) + dev_dbg(&dev->pdev->dev, "send start event\n"); + ret = stu300_start_and_await_event(dev, cr, + STU300_EVENT_5); + } + + if (attempts) + dev_dbg(&dev->pdev->dev, "send address\n"); + + if (ret == 0) + /* Send address */ + ret = stu300_send_address(dev, msg, attempts != 0); + + if (ret != 0) { + attempts++; + dev_dbg(&dev->pdev->dev, "failed sending address, " + "retrying. Attempt: %d msg_index: %d/%d\n", + attempts, dev->msg_index, dev->msg_len); + } + + } while (ret != 0 && attempts < NUM_ADDR_RESEND_ATTEMPTS); + + if (attempts < NUM_ADDR_RESEND_ATTEMPTS && attempts > 0) { + dev_dbg(&dev->pdev->dev, "managed to get address " + "through after %d attempts\n", attempts); + } else if (attempts == NUM_ADDR_RESEND_ATTEMPTS) { + dev_dbg(&dev->pdev->dev, "I give up, tried %d times " + "to resend address.\n", + NUM_ADDR_RESEND_ATTEMPTS); + goto exit_disable; + } + + + if (msg->flags & I2C_M_RD) { + /* READ: we read the actual bytes one at a time */ + for (i = 0; i < msg->len; i++) { + if (i == msg->len-1) { + /* + * Disable ACK and set STOP condition before + * reading last byte + */ + val = I2C_CR_PERIPHERAL_ENABLE; + + if (stop) + val |= I2C_CR_STOP_ENABLE; + + stu300_wr8(val, + dev->virtbase + I2C_CR); + } + /* Wait for this byte... */ + ret = stu300_await_event(dev, STU300_EVENT_7); + if (ret != 0) + goto exit_disable; + /* This clears event 7 */ + msg->buf[i] = (u8) stu300_r8(dev->virtbase + I2C_DR); + } + } else { + /* WRITE: we send the actual bytes one at a time */ + for (i = 0; i < msg->len; i++) { + /* Write the byte */ + stu300_wr8(msg->buf[i], + dev->virtbase + I2C_DR); + /* Check status */ + ret = stu300_await_event(dev, STU300_EVENT_8); + /* Next write to DR will clear event 8 */ + if (ret != 0) { + dev_err(&dev->pdev->dev, "error awaiting " + "event 8 (%d)\n", ret); + goto exit_disable; + } + } + /* Check NAK */ + if (!(msg->flags & I2C_M_IGNORE_NAK)) { + if (stu300_r8(dev->virtbase + I2C_SR2) & + I2C_SR2_AF_IND) { + dev_err(&dev->pdev->dev, "I2C payload " + "send returned NAK!\n"); + ret = -EIO; + goto exit_disable; + } + } + if (stop) { + /* Send stop condition */ + val = I2C_CR_PERIPHERAL_ENABLE; + val |= I2C_CR_STOP_ENABLE; + stu300_wr8(val, dev->virtbase + I2C_CR); + } + } + + /* Check that the bus is free, or wait until some timeout occurs */ + ret = stu300_wait_while_busy(dev); + if (ret != 0) { + dev_err(&dev->pdev->dev, "timout waiting for transfer " + "to commence.\n"); + goto exit_disable; + } + + /* Dummy read status registers */ + val = stu300_r8(dev->virtbase + I2C_SR2); + val = stu300_r8(dev->virtbase + I2C_SR1); + ret = 0; + + exit_disable: + /* Disable controller */ + stu300_wr8(0x00, dev->virtbase + I2C_CR); + clk_disable(dev->clk); + return ret; +} + +static int stu300_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num) +{ + int ret = -1; + int i; + + struct stu300_dev *dev = i2c_get_adapdata(adap); + dev->msg_len = num; + + for (i = 0; i < num; i++) { + /* + * Another driver appears to send stop for each message, + * here we only do that for the last message. Possibly some + * peripherals require this behaviour, then their drivers + * have to send single messages in order to get "stop" for + * each message. + */ + dev->msg_index = i; + + ret = stu300_xfer_msg(adap, &msgs[i], (i == (num - 1))); + + if (ret != 0) { + num = ret; + break; + } + } + + return num; +} + +static u32 stu300_func(struct i2c_adapter *adap) +{ + /* This is the simplest thing you can think of... */ + return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; +} + +static const struct i2c_algorithm stu300_algo = { + .master_xfer = stu300_xfer, + .functionality = stu300_func, +}; + +static int __init +stu300_probe(struct platform_device *pdev) +{ + struct stu300_dev *dev; + struct i2c_adapter *adap; + struct resource *res; + int bus_nr; + int ret = 0; + char clk_name[] = "I2C0"; + + dev = kzalloc(sizeof(struct stu300_dev), GFP_KERNEL); + if (!dev) { + dev_err(&pdev->dev, "could not allocate device struct\n"); + ret = -ENOMEM; + goto err_no_devmem; + } + + bus_nr = pdev->id; + clk_name[3] += (char)bus_nr; + dev->clk = clk_get(&pdev->dev, clk_name); + if (IS_ERR(dev->clk)) { + ret = PTR_ERR(dev->clk); + dev_err(&pdev->dev, "could not retrieve i2c bus clock\n"); + goto err_no_clk; + } + + dev->pdev = pdev; + platform_set_drvdata(pdev, dev); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENOENT; + goto err_no_resource; + } + + dev->phybase = res->start; + dev->physize = resource_size(res); + + if (request_mem_region(dev->phybase, dev->physize, + NAME " I/O Area") == NULL) { + ret = -EBUSY; + goto err_no_ioregion; + } + + dev->virtbase = ioremap(dev->phybase, dev->physize); + dev_dbg(&pdev->dev, "initialize bus device I2C%d on virtual " + "base %p\n", bus_nr, dev->virtbase); + if (!dev->virtbase) { + ret = -ENOMEM; + goto err_no_ioremap; + } + + dev->irq = platform_get_irq(pdev, 0); + if (request_irq(dev->irq, stu300_irh, IRQF_DISABLED, + NAME, dev)) { + ret = -EIO; + goto err_no_irq; + } + + dev->speed = scl_frequency; + + clk_enable(dev->clk); + ret = stu300_init_hw(dev); + clk_disable(dev->clk); + + if (ret != 0) { + dev_err(&dev->pdev->dev, "error initializing hardware.\n"); + goto err_init_hw; + } + + /* IRQ event handling initialization */ + spin_lock_init(&dev->cmd_issue_lock); + dev->cmd_event = STU300_EVENT_NONE; + dev->cmd_err = STU300_ERROR_NONE; + + adap = &dev->adapter; + adap->owner = THIS_MODULE; + /* DDC class but actually often used for more generic I2C */ + adap->class = I2C_CLASS_DDC; + strncpy(adap->name, "ST Microelectronics DDC I2C adapter", + sizeof(adap->name)); + adap->nr = bus_nr; + adap->algo = &stu300_algo; + adap->dev.parent = &pdev->dev; + i2c_set_adapdata(adap, dev); + + /* i2c device drivers may be active on return from add_adapter() */ + ret = i2c_add_numbered_adapter(adap); + if (ret) { + dev_err(&dev->pdev->dev, "failure adding ST Micro DDC " + "I2C adapter\n"); + goto err_add_adapter; + } + return 0; + + err_add_adapter: + err_init_hw: + free_irq(dev->irq, dev); + err_no_irq: + iounmap(dev->virtbase); + err_no_ioremap: + release_mem_region(dev->phybase, dev->physize); + err_no_ioregion: + platform_set_drvdata(pdev, NULL); + err_no_resource: + clk_put(dev->clk); + err_no_clk: + kfree(dev); + err_no_devmem: + dev_err(&pdev->dev, "failed to add " NAME " adapter: %d\n", + pdev->id); + return ret; +} + +#ifdef CONFIG_PM +static int stu300_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct stu300_dev *dev = platform_get_drvdata(pdev); + + /* Turn off everything */ + stu300_wr8(0x00, dev->virtbase + I2C_CR); + return 0; +} + +static int stu300_resume(struct platform_device *pdev) +{ + int ret = 0; + struct stu300_dev *dev = platform_get_drvdata(pdev); + + clk_enable(dev->clk); + ret = stu300_init_hw(dev); + clk_disable(dev->clk); + + if (ret != 0) + dev_err(&pdev->dev, "error re-initializing hardware.\n"); + return ret; +} +#else +#define stu300_suspend NULL +#define stu300_resume NULL +#endif + +static int __exit +stu300_remove(struct platform_device *pdev) +{ + struct stu300_dev *dev = platform_get_drvdata(pdev); + + i2c_del_adapter(&dev->adapter); + /* Turn off everything */ + stu300_wr8(0x00, dev->virtbase + I2C_CR); + free_irq(dev->irq, dev); + iounmap(dev->virtbase); + release_mem_region(dev->phybase, dev->physize); + clk_put(dev->clk); + platform_set_drvdata(pdev, NULL); + kfree(dev); + return 0; +} + +static struct platform_driver stu300_i2c_driver = { + .driver = { + .name = NAME, + .owner = THIS_MODULE, + }, + .remove = __exit_p(stu300_remove), + .suspend = stu300_suspend, + .resume = stu300_resume, + +}; + +static int __init stu300_init(void) +{ + return platform_driver_probe(&stu300_i2c_driver, stu300_probe); +} + +static void __exit stu300_exit(void) +{ + platform_driver_unregister(&stu300_i2c_driver); +} + +/* + * The systems using this bus often have very basic devices such + * as regulators on the I2C bus, so this needs to be loaded early. + * Therefore it is registered in the subsys_initcall(). + */ +subsys_initcall(stu300_init); +module_exit(stu300_exit); + +MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); +MODULE_DESCRIPTION("ST Micro DDC I2C adapter (" NAME ")"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" NAME); diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c index fede619ba22..70de8216346 100644 --- a/drivers/i2c/busses/i2c-versatile.c +++ b/drivers/i2c/busses/i2c-versatile.c @@ -76,7 +76,7 @@ static int i2c_versatile_probe(struct platform_device *dev) goto err_out; } - if (!request_mem_region(r->start, r->end - r->start + 1, "versatile-i2c")) { + if (!request_mem_region(r->start, resource_size(r), "versatile-i2c")) { ret = -EBUSY; goto err_out; } @@ -87,7 +87,7 @@ static int i2c_versatile_probe(struct platform_device *dev) goto err_release; } - i2c->base = ioremap(r->start, r->end - r->start + 1); + i2c->base = ioremap(r->start, resource_size(r)); if (!i2c->base) { ret = -ENOMEM; goto err_free; @@ -118,7 +118,7 @@ static int i2c_versatile_probe(struct platform_device *dev) err_free: kfree(i2c); err_release: - release_mem_region(r->start, r->end - r->start + 1); + release_mem_region(r->start, resource_size(r)); err_out: return ret; } diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index 02e6f724b05..54d810a4d00 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -37,6 +37,7 @@ VT8251 0x3287 yes CX700 0x8324 yes VX800/VX820 0x8353 yes + VX855/VX875 0x8409 yes Note: we assume there can only be one device, with one SMBus interface. */ @@ -404,6 +405,7 @@ found: switch (pdev->device) { case PCI_DEVICE_ID_VIA_CX700: case PCI_DEVICE_ID_VIA_VX800: + case PCI_DEVICE_ID_VIA_VX855: case PCI_DEVICE_ID_VIA_8251: case PCI_DEVICE_ID_VIA_8237: case PCI_DEVICE_ID_VIA_8237A: @@ -469,6 +471,8 @@ static struct pci_device_id vt596_ids[] = { .driver_data = SMBBA3 }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800), .driver_data = SMBBA3 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855), + .driver_data = SMBBA3 }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c index 1a474acc0dd..7663d57833a 100644 --- a/drivers/i2c/busses/i2c-voodoo3.c +++ b/drivers/i2c/busses/i2c-voodoo3.c @@ -163,7 +163,6 @@ static struct i2c_algo_bit_data voo_i2c_bit_data = { static struct i2c_adapter voodoo3_i2c_adapter = { .owner = THIS_MODULE, - .class = I2C_CLASS_TV_ANALOG, .name = "I2C Voodoo3/Banshee adapter", .algo_data = &voo_i2c_bit_data, }; diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 8f8c81eb0ae..02d746c9c47 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -64,21 +64,6 @@ config SENSORS_PCA9539 This driver is deprecated and will be dropped soon. Use drivers/gpio/pca953x.c instead. -config SENSORS_MAX6875 - tristate "Maxim MAX6875 Power supply supervisor" - depends on EXPERIMENTAL - help - If you say yes here you get support for the Maxim MAX6875 - EEPROM-programmable, quad power-supply sequencer/supervisor. - - This provides an interface to program the EEPROM and reset the chip. - - This driver also supports the Maxim MAX6874 hex power-supply - sequencer/supervisor if found at a compatible address. - - This driver can also be built as a module. If so, the module - will be called max6875. - config SENSORS_TSL2550 tristate "Taos TSL2550 ambient light sensor" depends on EXPERIMENTAL diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index 55a37603718..f4680d16ee3 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile @@ -11,7 +11,6 @@ # obj-$(CONFIG_DS1682) += ds1682.o -obj-$(CONFIG_SENSORS_MAX6875) += max6875.o obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_PCF8575) += pcf8575.o diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c deleted file mode 100644 index 033d9d81ec8..00000000000 --- a/drivers/i2c/chips/max6875.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - max6875.c - driver for MAX6874/MAX6875 - - Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> - - Based on i2c/chips/eeprom.c - - The MAX6875 has a bank of registers and two banks of EEPROM. - Address ranges are defined as follows: - * 0x0000 - 0x0046 = configuration registers - * 0x8000 - 0x8046 = configuration EEPROM - * 0x8100 - 0x82FF = user EEPROM - - This driver makes the user EEPROM available for read. - - The registers & config EEPROM should be accessed via i2c-dev. - - The MAX6875 ignores the lowest address bit, so each chip responds to - two addresses - 0x50/0x51 and 0x52/0x53. - - Note that the MAX6875 uses i2c_smbus_write_byte_data() to set the read - address, so this driver is destructive if loaded for the wrong EEPROM chip. - - 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 of the License. -*/ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/mutex.h> - -/* Do not scan - the MAX6875 access method will write to some EEPROM chips */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; - -/* Insmod parameters */ -I2C_CLIENT_INSMOD_1(max6875); - -/* The MAX6875 can only read/write 16 bytes at a time */ -#define SLICE_SIZE 16 -#define SLICE_BITS 4 - -/* USER EEPROM is at addresses 0x8100 - 0x82FF */ -#define USER_EEPROM_BASE 0x8100 -#define USER_EEPROM_SIZE 0x0200 -#define USER_EEPROM_SLICES 32 - -/* MAX6875 commands */ -#define MAX6875_CMD_BLK_READ 0x84 - -/* Each client has this additional data */ -struct max6875_data { - struct i2c_client *fake_client; - struct mutex update_lock; - - u32 valid; - u8 data[USER_EEPROM_SIZE]; - unsigned long last_updated[USER_EEPROM_SLICES]; -}; - -static void max6875_update_slice(struct i2c_client *client, int slice) -{ - struct max6875_data *data = i2c_get_clientdata(client); - int i, j, addr; - u8 *buf; - - if (slice >= USER_EEPROM_SLICES) - return; - - mutex_lock(&data->update_lock); - - buf = &data->data[slice << SLICE_BITS]; - - if (!(data->valid & (1 << slice)) || - time_after(jiffies, data->last_updated[slice])) { - - dev_dbg(&client->dev, "Starting update of slice %u\n", slice); - - data->valid &= ~(1 << slice); - - addr = USER_EEPROM_BASE + (slice << SLICE_BITS); - - /* select the eeprom address */ - if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) { - dev_err(&client->dev, "address set failed\n"); - goto exit_up; - } - - if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - if (i2c_smbus_read_i2c_block_data(client, - MAX6875_CMD_BLK_READ, - SLICE_SIZE, - buf) != SLICE_SIZE) { - goto exit_up; - } - } else { - for (i = 0; i < SLICE_SIZE; i++) { - j = i2c_smbus_read_byte(client); - if (j < 0) { - goto exit_up; - } - buf[i] = j; - } - } - data->last_updated[slice] = jiffies; - data->valid |= (1 << slice); - } -exit_up: - mutex_unlock(&data->update_lock); -} - -static ssize_t max6875_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct i2c_client *client = kobj_to_i2c_client(kobj); - struct max6875_data *data = i2c_get_clientdata(client); - int slice, max_slice; - - if (off > USER_EEPROM_SIZE) - return 0; - - if (off + count > USER_EEPROM_SIZE) - count = USER_EEPROM_SIZE - off; - - /* refresh slices which contain requested bytes */ - max_slice = (off + count - 1) >> SLICE_BITS; - for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++) - max6875_update_slice(client, slice); - - memcpy(buf, &data->data[off], count); - - return count; -} - -static struct bin_attribute user_eeprom_attr = { - .attr = { - .name = "eeprom", - .mode = S_IRUGO, - }, - .size = USER_EEPROM_SIZE, - .read = max6875_read, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int max6875_detect(struct i2c_client *client, int kind, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA - | I2C_FUNC_SMBUS_READ_BYTE)) - return -ENODEV; - - /* Only check even addresses */ - if (client->addr & 1) - return -ENODEV; - - strlcpy(info->type, "max6875", I2C_NAME_SIZE); - - return 0; -} - -static int max6875_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct max6875_data *data; - int err; - - if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL))) - return -ENOMEM; - - /* A fake client is created on the odd address */ - data->fake_client = i2c_new_dummy(client->adapter, client->addr + 1); - if (!data->fake_client) { - err = -ENOMEM; - goto exit_kfree; - } - - /* Init real i2c_client */ - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - err = sysfs_create_bin_file(&client->dev.kobj, &user_eeprom_attr); - if (err) - goto exit_remove_fake; - - return 0; - -exit_remove_fake: - i2c_unregister_device(data->fake_client); -exit_kfree: - kfree(data); - return err; -} - -static int max6875_remove(struct i2c_client *client) -{ - struct max6875_data *data = i2c_get_clientdata(client); - - i2c_unregister_device(data->fake_client); - - sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr); - kfree(data); - - return 0; -} - -static const struct i2c_device_id max6875_id[] = { - { "max6875", 0 }, - { } -}; - -static struct i2c_driver max6875_driver = { - .driver = { - .name = "max6875", - }, - .probe = max6875_probe, - .remove = max6875_remove, - .id_table = max6875_id, - - .detect = max6875_detect, - .address_data = &addr_data, -}; - -static int __init max6875_init(void) -{ - return i2c_add_driver(&max6875_driver); -} - -static void __exit max6875_exit(void) -{ - i2c_del_driver(&max6875_driver); -} - - -MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>"); -MODULE_DESCRIPTION("MAX6875 driver"); -MODULE_LICENSE("GPL"); - -module_init(max6875_init); -module_exit(max6875_exit); diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c index 1a9cc135219..b96f3025e58 100644 --- a/drivers/i2c/chips/tsl2550.c +++ b/drivers/i2c/chips/tsl2550.c @@ -27,7 +27,7 @@ #include <linux/delay.h> #define TSL2550_DRV_NAME "tsl2550" -#define DRIVER_VERSION "1.1.1" +#define DRIVER_VERSION "1.1.2" /* * Defines @@ -189,13 +189,16 @@ static int tsl2550_calculate_lux(u8 ch0, u8 ch1) u8 r = 128; /* Avoid division by 0 and count 1 cannot be greater than count 0 */ - if (c0 && (c1 <= c0)) - r = c1 * 128 / c0; + if (c1 <= c0) + if (c0) { + r = c1 * 128 / c0; + + /* Calculate LUX */ + lux = ((c0 - c1) * ratio_lut[r]) / 256; + } else + lux = 0; else - return -1; - - /* Calculate LUX */ - lux = ((c0 - c1) * ratio_lut[r]) / 256; + return -EAGAIN; /* LUX range check */ return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux; diff --git a/drivers/i2c/i2c-boardinfo.c b/drivers/i2c/i2c-boardinfo.c index ffb35f09df0..a26a34a0664 100644 --- a/drivers/i2c/i2c-boardinfo.c +++ b/drivers/i2c/i2c-boardinfo.c @@ -18,6 +18,7 @@ #include <linux/kernel.h> #include <linux/i2c.h> +#include <linux/rwsem.h> #include "i2c-core.h" @@ -25,7 +26,7 @@ /* These symbols are exported ONLY FOR the i2c core. * No other users will be supported. */ -DEFINE_MUTEX(__i2c_board_lock); +DECLARE_RWSEM(__i2c_board_lock); EXPORT_SYMBOL_GPL(__i2c_board_lock); LIST_HEAD(__i2c_board_list); @@ -63,7 +64,7 @@ i2c_register_board_info(int busnum, { int status; - mutex_lock(&__i2c_board_lock); + down_write(&__i2c_board_lock); /* dynamic bus numbers will be assigned after the last static one */ if (busnum >= __i2c_first_dynamic_bus_num) @@ -84,7 +85,7 @@ i2c_register_board_info(int busnum, list_add_tail(&devinfo->list, &__i2c_board_list); } - mutex_unlock(&__i2c_board_lock); + up_write(&__i2c_board_lock); return status; } diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 85e2e919d1c..0e45c296d3d 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -29,21 +29,24 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/idr.h> -#include <linux/platform_device.h> #include <linux/mutex.h> #include <linux/completion.h> #include <linux/hardirq.h> #include <linux/irqflags.h> +#include <linux/rwsem.h> #include <asm/uaccess.h> #include "i2c-core.h" +/* core_lock protects i2c_adapter_idr, userspace_devices, and guarantees + that device detection, deletion of detected devices, and attach_adapter + and detach_adapter calls are serialized */ static DEFINE_MUTEX(core_lock); static DEFINE_IDR(i2c_adapter_idr); +static LIST_HEAD(userspace_devices); -#define is_newstyle_driver(d) ((d)->probe || (d)->remove || (d)->detect) - +static int i2c_check_addr(struct i2c_adapter *adapter, int addr); static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); /* ------------------------------------------------------------------------- */ @@ -64,12 +67,6 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv) struct i2c_client *client = to_i2c_client(dev); struct i2c_driver *driver = to_i2c_driver(drv); - /* make legacy i2c drivers bypass driver model probing entirely; - * such drivers scan each i2c adapter/bus themselves. - */ - if (!is_newstyle_driver(driver)) - return 0; - /* match on an id table if there is one */ if (driver->id_table) return i2c_match_id(driver->id_table, client) != NULL; @@ -84,10 +81,6 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) { struct i2c_client *client = to_i2c_client(dev); - /* by definition, legacy drivers can't hotplug */ - if (dev->driver) - return 0; - if (add_uevent_var(env, "MODALIAS=%s%s", I2C_MODULE_PREFIX, client->name)) return -ENOMEM; @@ -176,12 +169,6 @@ static int i2c_device_resume(struct device *dev) return driver->resume(to_i2c_client(dev)); } -static void i2c_client_release(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - complete(&client->released); -} - static void i2c_client_dev_release(struct device *dev) { kfree(to_i2c_client(dev)); @@ -241,15 +228,17 @@ EXPORT_SYMBOL(i2c_verify_client); /** - * i2c_new_device - instantiate an i2c device for use with a new style driver + * i2c_new_device - instantiate an i2c device * @adap: the adapter managing the device * @info: describes one I2C device; bus_num is ignored * Context: can sleep * - * Create a device to work with a new style i2c driver, where binding is - * handled through driver model probe()/remove() methods. This call is not - * appropriate for use by mainboad initialization logic, which usually runs - * during an arch_initcall() long before any i2c_adapter could exist. + * Create an i2c device. Binding is handled through driver model + * probe()/remove() methods. A driver may be bound to this device when we + * return from this function, or any later moment (e.g. maybe hotplugging will + * load the driver module). This call is not appropriate for use by mainboard + * initialization logic, which usually runs during an arch_initcall() long + * before any i2c_adapter could exist. * * This returns the new i2c client, which may be saved for later use with * i2c_unregister_device(); or NULL to indicate an error. @@ -277,17 +266,31 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) strlcpy(client->name, info->type, sizeof(client->name)); - /* a new style driver may be bound to this device when we - * return from this function, or any later moment (e.g. maybe - * hotplugging will load the driver module). and the device - * refcount model is the standard driver model one. - */ - status = i2c_attach_client(client); - if (status < 0) { - kfree(client); - client = NULL; - } + /* Check for address business */ + status = i2c_check_addr(adap, client->addr); + if (status) + goto out_err; + + client->dev.parent = &client->adapter->dev; + client->dev.bus = &i2c_bus_type; + client->dev.release = i2c_client_dev_release; + + dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), + client->addr); + status = device_register(&client->dev); + if (status) + goto out_err; + + dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n", + client->name, dev_name(&client->dev)); + return client; + +out_err: + dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x " + "(%d)\n", client->name, client->addr, status); + kfree(client); + return NULL; } EXPORT_SYMBOL_GPL(i2c_new_device); @@ -299,28 +302,6 @@ EXPORT_SYMBOL_GPL(i2c_new_device); */ void i2c_unregister_device(struct i2c_client *client) { - struct i2c_adapter *adapter = client->adapter; - struct i2c_driver *driver = client->driver; - - if (driver && !is_newstyle_driver(driver)) { - dev_err(&client->dev, "can't unregister devices " - "with legacy drivers\n"); - WARN_ON(1); - return; - } - - if (adapter->client_unregister) { - if (adapter->client_unregister(client)) { - dev_warn(&client->dev, - "client_unregister [%s] failed\n", - client->name); - } - } - - mutex_lock(&adapter->clist_lock); - list_del(&client->list); - mutex_unlock(&adapter->clist_lock); - device_unregister(&client->dev); } EXPORT_SYMBOL_GPL(i2c_unregister_device); @@ -394,8 +375,128 @@ show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf) return sprintf(buf, "%s\n", adap->name); } +/* + * Let users instantiate I2C devices through sysfs. This can be used when + * platform initialization code doesn't contain the proper data for + * whatever reason. Also useful for drivers that do device detection and + * detection fails, either because the device uses an unexpected address, + * or this is a compatible device with different ID register values. + * + * Parameter checking may look overzealous, but we really don't want + * the user to provide incorrect parameters. + */ +static ssize_t +i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_adapter *adap = to_i2c_adapter(dev); + struct i2c_board_info info; + struct i2c_client *client; + char *blank, end; + int res; + + dev_warn(dev, "The new_device interface is still experimental " + "and may change in a near future\n"); + memset(&info, 0, sizeof(struct i2c_board_info)); + + blank = strchr(buf, ' '); + if (!blank) { + dev_err(dev, "%s: Missing parameters\n", "new_device"); + return -EINVAL; + } + if (blank - buf > I2C_NAME_SIZE - 1) { + dev_err(dev, "%s: Invalid device name\n", "new_device"); + return -EINVAL; + } + memcpy(info.type, buf, blank - buf); + + /* Parse remaining parameters, reject extra parameters */ + res = sscanf(++blank, "%hi%c", &info.addr, &end); + if (res < 1) { + dev_err(dev, "%s: Can't parse I2C address\n", "new_device"); + return -EINVAL; + } + if (res > 1 && end != '\n') { + dev_err(dev, "%s: Extra parameters\n", "new_device"); + return -EINVAL; + } + + if (info.addr < 0x03 || info.addr > 0x77) { + dev_err(dev, "%s: Invalid I2C address 0x%hx\n", "new_device", + info.addr); + return -EINVAL; + } + + client = i2c_new_device(adap, &info); + if (!client) + return -EEXIST; + + /* Keep track of the added device */ + mutex_lock(&core_lock); + list_add_tail(&client->detected, &userspace_devices); + mutex_unlock(&core_lock); + dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device", + info.type, info.addr); + + return count; +} + +/* + * And of course let the users delete the devices they instantiated, if + * they got it wrong. This interface can only be used to delete devices + * instantiated by i2c_sysfs_new_device above. This guarantees that we + * don't delete devices to which some kernel code still has references. + * + * Parameter checking may look overzealous, but we really don't want + * the user to delete the wrong device. + */ +static ssize_t +i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_adapter *adap = to_i2c_adapter(dev); + struct i2c_client *client, *next; + unsigned short addr; + char end; + int res; + + /* Parse parameters, reject extra parameters */ + res = sscanf(buf, "%hi%c", &addr, &end); + if (res < 1) { + dev_err(dev, "%s: Can't parse I2C address\n", "delete_device"); + return -EINVAL; + } + if (res > 1 && end != '\n') { + dev_err(dev, "%s: Extra parameters\n", "delete_device"); + return -EINVAL; + } + + /* Make sure the device was added through sysfs */ + res = -ENOENT; + mutex_lock(&core_lock); + list_for_each_entry_safe(client, next, &userspace_devices, detected) { + if (client->addr == addr && client->adapter == adap) { + dev_info(dev, "%s: Deleting device %s at 0x%02hx\n", + "delete_device", client->name, client->addr); + + list_del(&client->detected); + i2c_unregister_device(client); + res = count; + break; + } + } + mutex_unlock(&core_lock); + + if (res < 0) + dev_err(dev, "%s: Can't find device in list\n", + "delete_device"); + return res; +} + static struct device_attribute i2c_adapter_attrs[] = { __ATTR(name, S_IRUGO, show_adapter_name, NULL), + __ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device), + __ATTR(delete_device, S_IWUSR, NULL, i2c_sysfs_delete_device), { }, }; @@ -409,7 +510,7 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter) { struct i2c_devinfo *devinfo; - mutex_lock(&__i2c_board_lock); + down_read(&__i2c_board_lock); list_for_each_entry(devinfo, &__i2c_board_list, list) { if (devinfo->busnum == adapter->nr && !i2c_new_device(adapter, @@ -418,7 +519,7 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter) "Can't create device at 0x%02x\n", devinfo->board_info.addr); } - mutex_unlock(&__i2c_board_lock); + up_read(&__i2c_board_lock); } static int i2c_do_add_adapter(struct device_driver *d, void *data) @@ -442,24 +543,12 @@ static int i2c_register_adapter(struct i2c_adapter *adap) int res = 0, dummy; /* Can't register until after driver model init */ - if (unlikely(WARN_ON(!i2c_bus_type.p))) - return -EAGAIN; + if (unlikely(WARN_ON(!i2c_bus_type.p))) { + res = -EAGAIN; + goto out_list; + } mutex_init(&adap->bus_lock); - mutex_init(&adap->clist_lock); - INIT_LIST_HEAD(&adap->clients); - - mutex_lock(&core_lock); - - /* Add the adapter to the driver core. - * If the parent pointer is not set up, - * we add this adapter to the host bus. - */ - if (adap->dev.parent == NULL) { - adap->dev.parent = &platform_bus; - pr_debug("I2C adapter driver [%s] forgot to specify " - "physical device\n", adap->name); - } /* Set default timeout to 1 second if not already set */ if (adap->timeout == 0) @@ -474,21 +563,23 @@ static int i2c_register_adapter(struct i2c_adapter *adap) dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); - /* create pre-declared device nodes for new-style drivers */ + /* create pre-declared device nodes */ if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); /* Notify drivers */ + mutex_lock(&core_lock); dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap, i2c_do_add_adapter); - -out_unlock: mutex_unlock(&core_lock); - return res; + + return 0; out_list: + mutex_lock(&core_lock); idr_remove(&i2c_adapter_idr, adap->nr); - goto out_unlock; + mutex_unlock(&core_lock); + return res; } /** @@ -607,6 +698,14 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data) return res; } +static int __unregister_client(struct device *dev, void *dummy) +{ + struct i2c_client *client = i2c_verify_client(dev); + if (client) + i2c_unregister_device(client); + return 0; +} + /** * i2c_del_adapter - unregister I2C adapter * @adap: the adapter being unregistered @@ -617,46 +716,30 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data) */ int i2c_del_adapter(struct i2c_adapter *adap) { - struct i2c_client *client, *_n; int res = 0; - - mutex_lock(&core_lock); + struct i2c_adapter *found; /* First make sure that this adapter was ever added */ - if (idr_find(&i2c_adapter_idr, adap->nr) != adap) { + mutex_lock(&core_lock); + found = idr_find(&i2c_adapter_idr, adap->nr); + mutex_unlock(&core_lock); + if (found != adap) { pr_debug("i2c-core: attempting to delete unregistered " "adapter [%s]\n", adap->name); - res = -EINVAL; - goto out_unlock; + return -EINVAL; } /* Tell drivers about this removal */ + mutex_lock(&core_lock); res = bus_for_each_drv(&i2c_bus_type, NULL, adap, i2c_do_del_adapter); + mutex_unlock(&core_lock); if (res) - goto out_unlock; - - /* detach any active clients. This must be done first, because - * it can fail; in which case we give up. */ - list_for_each_entry_safe_reverse(client, _n, &adap->clients, list) { - struct i2c_driver *driver; - - driver = client->driver; - - /* new style, follow standard driver model */ - if (!driver || is_newstyle_driver(driver)) { - i2c_unregister_device(client); - continue; - } + return res; - /* legacy drivers create and remove clients themselves */ - if ((res = driver->detach_client(client))) { - dev_err(&adap->dev, "detach_client failed for client " - "[%s] at address 0x%02x\n", client->name, - client->addr); - goto out_unlock; - } - } + /* Detach any active clients. This can't fail, thus we do not + checking the returned value. */ + res = device_for_each_child(&adap->dev, NULL, __unregister_client); /* clean up the sysfs representation */ init_completion(&adap->dev_released); @@ -666,7 +749,9 @@ int i2c_del_adapter(struct i2c_adapter *adap) wait_for_completion(&adap->dev_released); /* free bus id */ + mutex_lock(&core_lock); idr_remove(&i2c_adapter_idr, adap->nr); + mutex_unlock(&core_lock); dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); @@ -674,9 +759,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) added again */ memset(&adap->dev, 0, sizeof(adap->dev)); - out_unlock: - mutex_unlock(&core_lock); - return res; + return 0; } EXPORT_SYMBOL(i2c_del_adapter); @@ -699,11 +782,7 @@ static int __attach_adapter(struct device *dev, void *data) /* * An i2c_driver is used with one or more i2c_client (device) nodes to access - * i2c slave chips, on a bus instance associated with some i2c_adapter. There - * are two models for binding the driver to its device: "new style" drivers - * follow the standard Linux driver model and just respond to probe() calls - * issued if the driver core sees they match(); "legacy" drivers create device - * nodes themselves. + * i2c slave chips, on a bus instance associated with some i2c_adapter. */ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) @@ -714,37 +793,26 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) if (unlikely(WARN_ON(!i2c_bus_type.p))) return -EAGAIN; - /* new style driver methods can't mix with legacy ones */ - if (is_newstyle_driver(driver)) { - if (driver->detach_adapter || driver->detach_client) { - printk(KERN_WARNING - "i2c-core: driver [%s] is confused\n", - driver->driver.name); - return -EINVAL; - } - } - /* add the driver to the list of i2c drivers in the driver core */ driver->driver.owner = owner; driver->driver.bus = &i2c_bus_type; - /* for new style drivers, when registration returns the driver core + /* When registration returns, the driver core * will have called probe() for all matching-but-unbound devices. */ res = driver_register(&driver->driver); if (res) return res; - mutex_lock(&core_lock); - pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); INIT_LIST_HEAD(&driver->clients); /* Walk the adapters that are already present */ + mutex_lock(&core_lock); class_for_each_device(&i2c_adapter_class, NULL, driver, __attach_adapter); - mutex_unlock(&core_lock); + return 0; } EXPORT_SYMBOL(i2c_register_driver); @@ -764,32 +832,11 @@ static int __detach_adapter(struct device *dev, void *data) i2c_unregister_device(client); } - if (is_newstyle_driver(driver)) - return 0; - - /* Have a look at each adapter, if clients of this driver are still - * attached. If so, detach them to be able to kill the driver - * afterwards. - */ if (driver->detach_adapter) { if (driver->detach_adapter(adapter)) dev_err(&adapter->dev, "detach_adapter failed for driver [%s]\n", driver->driver.name); - } else { - struct i2c_client *client, *_n; - - list_for_each_entry_safe(client, _n, &adapter->clients, list) { - if (client->driver != driver) - continue; - dev_dbg(&adapter->dev, - "detaching client [%s] at 0x%02x\n", - client->name, client->addr); - if (driver->detach_client(client)) - dev_err(&adapter->dev, "detach_client " - "failed for client [%s] at 0x%02x\n", - client->name, client->addr); - } } return 0; @@ -803,14 +850,12 @@ static int __detach_adapter(struct device *dev, void *data) void i2c_del_driver(struct i2c_driver *driver) { mutex_lock(&core_lock); - class_for_each_device(&i2c_adapter_class, NULL, driver, __detach_adapter); + mutex_unlock(&core_lock); driver_unregister(&driver->driver); pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); - - mutex_unlock(&core_lock); } EXPORT_SYMBOL(i2c_del_driver); @@ -831,86 +876,6 @@ static int i2c_check_addr(struct i2c_adapter *adapter, int addr) return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr); } -int i2c_attach_client(struct i2c_client *client) -{ - struct i2c_adapter *adapter = client->adapter; - int res; - - /* Check for address business */ - res = i2c_check_addr(adapter, client->addr); - if (res) - return res; - - client->dev.parent = &client->adapter->dev; - client->dev.bus = &i2c_bus_type; - - if (client->driver) - client->dev.driver = &client->driver->driver; - - if (client->driver && !is_newstyle_driver(client->driver)) { - client->dev.release = i2c_client_release; - dev_set_uevent_suppress(&client->dev, 1); - } else - client->dev.release = i2c_client_dev_release; - - dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adapter), - client->addr); - res = device_register(&client->dev); - if (res) - goto out_err; - - mutex_lock(&adapter->clist_lock); - list_add_tail(&client->list, &adapter->clients); - mutex_unlock(&adapter->clist_lock); - - dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n", - client->name, dev_name(&client->dev)); - - if (adapter->client_register) { - if (adapter->client_register(client)) { - dev_dbg(&adapter->dev, "client_register " - "failed for client [%s] at 0x%02x\n", - client->name, client->addr); - } - } - - return 0; - -out_err: - dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x " - "(%d)\n", client->name, client->addr, res); - return res; -} -EXPORT_SYMBOL(i2c_attach_client); - -int i2c_detach_client(struct i2c_client *client) -{ - struct i2c_adapter *adapter = client->adapter; - int res = 0; - - if (adapter->client_unregister) { - res = adapter->client_unregister(client); - if (res) { - dev_err(&client->dev, - "client_unregister [%s] failed, " - "client not detached\n", client->name); - goto out; - } - } - - mutex_lock(&adapter->clist_lock); - list_del(&client->list); - mutex_unlock(&adapter->clist_lock); - - init_completion(&client->released); - device_unregister(&client->dev); - wait_for_completion(&client->released); - - out: - return res; -} -EXPORT_SYMBOL(i2c_detach_client); - /** * i2c_use_client - increments the reference count of the i2c client structure * @client: the client being referenced @@ -1022,7 +987,8 @@ module_exit(i2c_exit); */ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { - int ret; + unsigned long orig_jiffies; + int ret, try; /* REVISIT the fault reporting model here is weak: * @@ -1060,7 +1026,15 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) mutex_lock_nested(&adap->bus_lock, adap->level); } - ret = adap->algo->master_xfer(adap,msgs,num); + /* Retry automatically on arbitration loss */ + orig_jiffies = jiffies; + for (ret = 0, try = 0; try <= adap->retries; try++) { + ret = adap->algo->master_xfer(adap, msgs, num); + if (ret != -EAGAIN) + break; + if (time_after(jiffies, orig_jiffies + adap->timeout)) + break; + } mutex_unlock(&adap->bus_lock); return ret; @@ -1131,144 +1105,7 @@ EXPORT_SYMBOL(i2c_master_recv); * Will not work for 10-bit addresses! * ---------------------------------------------------- */ -static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind, - int (*found_proc) (struct i2c_adapter *, int, int)) -{ - int err; - - /* Make sure the address is valid */ - if (addr < 0x03 || addr > 0x77) { - dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n", - addr); - return -EINVAL; - } - - /* Skip if already in use */ - if (i2c_check_addr(adapter, addr)) - return 0; - - /* Make sure there is something at this address, unless forced */ - if (kind < 0) { - if (i2c_smbus_xfer(adapter, addr, 0, 0, 0, - I2C_SMBUS_QUICK, NULL) < 0) - return 0; - - /* prevent 24RF08 corruption */ - if ((addr & ~0x0f) == 0x50) - i2c_smbus_xfer(adapter, addr, 0, 0, 0, - I2C_SMBUS_QUICK, NULL); - } - - /* Finally call the custom detection function */ - err = found_proc(adapter, addr, kind); - /* -ENODEV can be returned if there is a chip at the given address - but it isn't supported by this chip driver. We catch it here as - this isn't an error. */ - if (err == -ENODEV) - err = 0; - - if (err) - dev_warn(&adapter->dev, "Client creation failed at 0x%x (%d)\n", - addr, err); - return err; -} - -int i2c_probe(struct i2c_adapter *adapter, - const struct i2c_client_address_data *address_data, - int (*found_proc) (struct i2c_adapter *, int, int)) -{ - int i, err; - int adap_id = i2c_adapter_id(adapter); - /* Force entries are done first, and are not affected by ignore - entries */ - if (address_data->forces) { - const unsigned short * const *forces = address_data->forces; - int kind; - - for (kind = 0; forces[kind]; kind++) { - for (i = 0; forces[kind][i] != I2C_CLIENT_END; - i += 2) { - if (forces[kind][i] == adap_id - || forces[kind][i] == ANY_I2C_BUS) { - dev_dbg(&adapter->dev, "found force " - "parameter for adapter %d, " - "addr 0x%02x, kind %d\n", - adap_id, forces[kind][i + 1], - kind); - err = i2c_probe_address(adapter, - forces[kind][i + 1], - kind, found_proc); - if (err) - return err; - } - } - } - } - - /* Stop here if we can't use SMBUS_QUICK */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) { - if (address_data->probe[0] == I2C_CLIENT_END - && address_data->normal_i2c[0] == I2C_CLIENT_END) - return 0; - - dev_dbg(&adapter->dev, "SMBus Quick command not supported, " - "can't probe for chips\n"); - return -EOPNOTSUPP; - } - - /* Probe entries are done second, and are not affected by ignore - entries either */ - for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) { - if (address_data->probe[i] == adap_id - || address_data->probe[i] == ANY_I2C_BUS) { - dev_dbg(&adapter->dev, "found probe parameter for " - "adapter %d, addr 0x%02x\n", adap_id, - address_data->probe[i + 1]); - err = i2c_probe_address(adapter, - address_data->probe[i + 1], - -1, found_proc); - if (err) - return err; - } - } - - /* Normal entries are done last, unless shadowed by an ignore entry */ - for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) { - int j, ignore; - - ignore = 0; - for (j = 0; address_data->ignore[j] != I2C_CLIENT_END; - j += 2) { - if ((address_data->ignore[j] == adap_id || - address_data->ignore[j] == ANY_I2C_BUS) - && address_data->ignore[j + 1] - == address_data->normal_i2c[i]) { - dev_dbg(&adapter->dev, "found ignore " - "parameter for adapter %d, " - "addr 0x%02x\n", adap_id, - address_data->ignore[j + 1]); - ignore = 1; - break; - } - } - if (ignore) - continue; - - dev_dbg(&adapter->dev, "found normal entry for adapter %d, " - "addr 0x%02x\n", adap_id, - address_data->normal_i2c[i]); - err = i2c_probe_address(adapter, address_data->normal_i2c[i], - -1, found_proc); - if (err) - return err; - } - - return 0; -} -EXPORT_SYMBOL(i2c_probe); - -/* Separate detection function for new-style drivers */ static int i2c_detect_address(struct i2c_client *temp_client, int kind, struct i2c_driver *driver) { @@ -1509,7 +1346,7 @@ struct i2c_adapter* i2c_get_adapter(int id) struct i2c_adapter *adapter; mutex_lock(&core_lock); - adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); + adapter = idr_find(&i2c_adapter_idr, id); if (adapter && !try_module_get(adapter->owner)) adapter = NULL; @@ -1995,14 +1832,27 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, char read_write, u8 command, int protocol, union i2c_smbus_data *data) { + unsigned long orig_jiffies; + int try; s32 res; flags &= I2C_M_TEN | I2C_CLIENT_PEC; if (adapter->algo->smbus_xfer) { mutex_lock(&adapter->bus_lock); - res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, - command, protocol, data); + + /* Retry automatically on arbitration loss */ + orig_jiffies = jiffies; + for (res = 0, try = 0; try <= adapter->retries; try++) { + res = adapter->algo->smbus_xfer(adapter, addr, flags, + read_write, command, + protocol, data); + if (res != -EAGAIN) + break; + if (time_after(jiffies, + orig_jiffies + adapter->timeout)) + break; + } mutex_unlock(&adapter->bus_lock); } else res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h index cd5bff87485..9f9c57ff670 100644 --- a/drivers/i2c/i2c-core.h +++ b/drivers/i2c/i2c-core.h @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/rwsem.h> + struct i2c_devinfo { struct list_head list; int busnum; @@ -25,7 +27,7 @@ struct i2c_devinfo { /* board_lock protects board_list and first_dynamic_bus_num. * only i2c core components are allowed to use these symbols. */ -extern struct mutex __i2c_board_lock; +extern struct rw_semaphore __i2c_board_lock; extern struct list_head __i2c_board_list; extern int __i2c_first_dynamic_bus_num; |