diff options
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mv64xxx.c | 45 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-nforce2.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 73 |
4 files changed, 65 insertions, 56 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 02835ce..7979aef7e 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -72,6 +72,7 @@ #include <linux/acpi.h> #include <linux/io.h> #include <linux/dmi.h> +#include <linux/slab.h> /* I801 SMBus address offsets */ #define SMBHSTSTS(p) (0 + (p)->smba) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 1624206..a9941c6 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -59,6 +59,7 @@ enum { MV64XXX_I2C_STATE_INVALID, MV64XXX_I2C_STATE_IDLE, MV64XXX_I2C_STATE_WAITING_FOR_START_COND, + MV64XXX_I2C_STATE_WAITING_FOR_RESTART, MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK, MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK, MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK, @@ -70,6 +71,7 @@ enum { MV64XXX_I2C_ACTION_INVALID, MV64XXX_I2C_ACTION_CONTINUE, MV64XXX_I2C_ACTION_SEND_START, + MV64XXX_I2C_ACTION_SEND_RESTART, MV64XXX_I2C_ACTION_SEND_ADDR_1, MV64XXX_I2C_ACTION_SEND_ADDR_2, MV64XXX_I2C_ACTION_SEND_DATA, @@ -91,6 +93,7 @@ struct mv64xxx_i2c_data { u32 addr2; u32 bytes_left; u32 byte_posn; + u32 send_stop; u32 block; int rc; u32 freq_m; @@ -159,8 +162,15 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) if ((drv_data->bytes_left == 0) || (drv_data->aborting && (drv_data->byte_posn != 0))) { - drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; - drv_data->state = MV64XXX_I2C_STATE_IDLE; + if (drv_data->send_stop) { + drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; + drv_data->state = MV64XXX_I2C_STATE_IDLE; + } else { + drv_data->action = + MV64XXX_I2C_ACTION_SEND_RESTART; + drv_data->state = + MV64XXX_I2C_STATE_WAITING_FOR_RESTART; + } } else { drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; drv_data->state = @@ -228,6 +238,15 @@ static void mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) { switch(drv_data->action) { + case MV64XXX_I2C_ACTION_SEND_RESTART: + drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START; + drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; + writel(drv_data->cntl_bits, + drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + drv_data->block = 0; + wake_up_interruptible(&drv_data->waitq); + break; + case MV64XXX_I2C_ACTION_CONTINUE: writel(drv_data->cntl_bits, drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); @@ -386,7 +405,8 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) } static int -mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg) +mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, + int is_first, int is_last) { unsigned long flags; @@ -406,10 +426,18 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg) drv_data->bytes_left--; } } else { - drv_data->action = MV64XXX_I2C_ACTION_SEND_START; - drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; + if (is_first) { + drv_data->action = MV64XXX_I2C_ACTION_SEND_START; + drv_data->state = + MV64XXX_I2C_STATE_WAITING_FOR_START_COND; + } else { + drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1; + drv_data->state = + MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK; + } } + drv_data->send_stop = is_last; drv_data->block = 1; mv64xxx_i2c_do_action(drv_data); spin_unlock_irqrestore(&drv_data->lock, flags); @@ -437,9 +465,12 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); int i, rc; - for (i=0; i<num; i++) - if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) < 0) + for (i = 0; i < num; i++) { + rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i], + i == 0, i + 1 == num); + if (rc < 0) return rc; + } return num; } diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index a605a50..ff1e127 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -432,7 +432,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_ static void __devexit nforce2_remove(struct pci_dev *dev) { - struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev); + struct nforce2_smbus *smbuses = pci_get_drvdata(dev); nforce2_set_reference(NULL); if (smbuses[0].base) { diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 3e9323e..b605ff3 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -39,6 +39,7 @@ #include <linux/io.h> #include <linux/slab.h> #include <linux/i2c-omap.h> +#include <linux/pm_runtime.h> /* I2C controller revisions */ #define OMAP_I2C_REV_2 0x20 @@ -175,8 +176,6 @@ struct omap_i2c_dev { void __iomem *base; /* virtual */ int irq; int reg_shift; /* bit shift for I2C register addresses */ - struct clk *iclk; /* Interface clock */ - struct clk *fclk; /* Functional clock */ struct completion cmd_complete; struct resource *ioarea; u32 latency; /* maximum mpu wkup latency */ @@ -265,45 +264,18 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) (i2c_dev->regs[reg] << i2c_dev->reg_shift)); } -static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev) +static void omap_i2c_unidle(struct omap_i2c_dev *dev) { - int ret; + struct platform_device *pdev; + struct omap_i2c_bus_platform_data *pdata; - dev->iclk = clk_get(dev->dev, "ick"); - if (IS_ERR(dev->iclk)) { - ret = PTR_ERR(dev->iclk); - dev->iclk = NULL; - return ret; - } + WARN_ON(!dev->idle); - dev->fclk = clk_get(dev->dev, "fck"); - if (IS_ERR(dev->fclk)) { - ret = PTR_ERR(dev->fclk); - if (dev->iclk != NULL) { - clk_put(dev->iclk); - dev->iclk = NULL; - } - dev->fclk = NULL; - return ret; - } + pdev = to_platform_device(dev->dev); + pdata = pdev->dev.platform_data; - return 0; -} + pm_runtime_get_sync(&pdev->dev); -static void omap_i2c_put_clocks(struct omap_i2c_dev *dev) -{ - clk_put(dev->fclk); - dev->fclk = NULL; - clk_put(dev->iclk); - dev->iclk = NULL; -} - -static void omap_i2c_unidle(struct omap_i2c_dev *dev) -{ - WARN_ON(!dev->idle); - - clk_enable(dev->iclk); - clk_enable(dev->fclk); if (cpu_is_omap34xx()) { omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate); @@ -326,10 +298,15 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev) static void omap_i2c_idle(struct omap_i2c_dev *dev) { + struct platform_device *pdev; + struct omap_i2c_bus_platform_data *pdata; u16 iv; WARN_ON(dev->idle); + pdev = to_platform_device(dev->dev); + pdata = pdev->dev.platform_data; + dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); if (dev->rev >= OMAP_I2C_REV_ON_4430) omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1); @@ -345,8 +322,8 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev) omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); } dev->idle = 1; - clk_disable(dev->fclk); - clk_disable(dev->iclk); + + pm_runtime_put_sync(&pdev->dev); } static int omap_i2c_init(struct omap_i2c_dev *dev) @@ -356,6 +333,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) unsigned long fclk_rate = 12000000; unsigned long timeout; unsigned long internal_clk = 0; + struct clk *fclk; if (dev->rev >= OMAP_I2C_REV_2) { /* Disable I2C controller before soft reset */ @@ -414,7 +392,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) * always returns 12MHz for the functional clock, we can * do this bit unconditionally. */ - fclk_rate = clk_get_rate(dev->fclk); + fclk = clk_get(dev->dev, "fck"); + fclk_rate = clk_get_rate(fclk); + clk_put(fclk); /* TRM for 5912 says the I2C clock must be prescaled to be * between 7 - 12 MHz. The XOR input clock is typically @@ -443,7 +423,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) internal_clk = 9600; else internal_clk = 4000; - fclk_rate = clk_get_rate(dev->fclk) / 1000; + fclk = clk_get(dev->dev, "fck"); + fclk_rate = clk_get_rate(fclk) / 1000; + clk_put(fclk); /* Compute prescaler divisor */ psc = fclk_rate / internal_clk; @@ -1050,14 +1032,12 @@ omap_i2c_probe(struct platform_device *pdev) else dev->reg_shift = 2; - if ((r = omap_i2c_get_clocks(dev)) != 0) - goto err_iounmap; - if (cpu_is_omap44xx()) dev->regs = (u8 *) omap4_reg_map; else dev->regs = (u8 *) reg_map; + pm_runtime_enable(&pdev->dev); omap_i2c_unidle(dev); dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; @@ -1129,8 +1109,6 @@ err_free_irq: err_unuse_clocks: omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); omap_i2c_idle(dev); - omap_i2c_put_clocks(dev); -err_iounmap: iounmap(dev->base); err_free_mem: platform_set_drvdata(pdev, NULL); @@ -1152,7 +1130,6 @@ omap_i2c_remove(struct platform_device *pdev) free_irq(dev->irq, dev); i2c_del_adapter(&dev->adapter); omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); - omap_i2c_put_clocks(dev); iounmap(dev->base); kfree(dev); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1164,7 +1141,7 @@ static struct platform_driver omap_i2c_driver = { .probe = omap_i2c_probe, .remove = omap_i2c_remove, .driver = { - .name = "i2c_omap", + .name = "omap_i2c", .owner = THIS_MODULE, }, }; @@ -1186,4 +1163,4 @@ module_exit(omap_i2c_exit_driver); MODULE_AUTHOR("MontaVista Software, Inc. (and others)"); MODULE_DESCRIPTION("TI OMAP I2C bus adapter"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:i2c_omap"); +MODULE_ALIAS("platform:omap_i2c"); |