diff options
author | Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> | 2010-10-18 14:30:18 +0200 |
---|---|---|
committer | Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> | 2010-10-23 13:29:31 +0200 |
commit | 54601118d5d8f0e10759761161571c28847ed59b (patch) | |
tree | 9f5913137e8760fc0ba8c23911414132b4e61c84 /drivers/i2c | |
parent | 4c7e90205e735659cc27d24ebc1296732624798b (diff) |
i2c: nomadic-i2c driver updates for clock and power
This patch is based on the follwoing work:
i2c: I2C now always releases the VAPE power domain
ST-Ericsson ID: AP 272787
Author: Rickard Andersson <rickard.andersson@stericsson.com>
i2c: Using regulator framework to handle power domains
Author: Daniel WILLERUD <daniel.willerud@stericsson.com>
Moreover, driver documentation is added in DocBook
Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-nomadik.c | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 73de8ade10b..49a8674070b 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -22,6 +22,7 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/regulator/consumer.h> #include <plat/i2c.h> @@ -103,6 +104,9 @@ /* maximum threshold value */ #define MAX_I2C_FIFO_THRESHOLD 15 +/* delay for i2c transfers */ +#define I2C_DELAY 150 + enum i2c_status { I2C_NOP, I2C_ON_GOING, @@ -118,7 +122,7 @@ enum i2c_operation { }; /* controller response timeout in ms */ -#define I2C_TIMEOUT_MS 500 +#define I2C_TIMEOUT_MS 2000 /** * struct i2c_nmk_client - client specific data @@ -160,6 +164,7 @@ struct nmk_i2c_dev { int stop; struct completion xfer_complete; int result; + struct regulator *regulator; }; /* controller's abort causes */ @@ -250,6 +255,8 @@ static int init_hw(struct nmk_i2c_dev *dev) { int stat; + clk_enable(dev->clk); + stat = flush_i2c_fifo(dev); if (stat) return stat; @@ -263,6 +270,9 @@ static int init_hw(struct nmk_i2c_dev *dev) dev->cli.operation = I2C_NO_OPERATION; + clk_disable(dev->clk); + + udelay(I2C_DELAY); return 0; } @@ -559,6 +569,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, if (status) return status; + if (dev->regulator) + regulator_enable(dev->regulator); + + clk_enable(dev->clk); + /* setup the i2c controller */ setup_i2c_controller(dev); @@ -566,7 +581,9 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, if (unlikely(msgs[i].flags & I2C_M_TEN)) { dev_err(&dev->pdev->dev, "10 bit addressing" "not supported\n"); - return -EINVAL; + + status = -EINVAL; + goto out; } dev->cli.slave_adr = msgs[i].addr; dev->cli.buffer = msgs[i].buf; @@ -591,10 +608,18 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, dev_err(&dev->pdev->dev, "%s\n", cause >= ARRAY_SIZE(abort_causes) ? "unknown reason" : abort_causes[cause]); - return status; + + goto out; } - mdelay(1); + udelay(I2C_DELAY); } + +out: + clk_disable(dev->clk); + + if (dev->regulator) + regulator_disable(dev->regulator); + /* return the no. messages processed */ if (status) return status; @@ -850,6 +875,14 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) goto err_irq; } + dev->regulator = regulator_get(&pdev->dev, "v-i2c"); + if (IS_ERR(dev->regulator)) { + dev_err(&pdev->dev, "could not get i2c regulator\n"); + ret = PTR_ERR(dev->regulator); + dev->regulator = NULL; + goto err_no_regulator; + } + dev->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) { dev_err(&pdev->dev, "could not get i2c clock\n"); @@ -857,8 +890,6 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) goto err_no_clk; } - clk_enable(dev->clk); - adap = &dev->adap; adap->dev.parent = &pdev->dev; adap->owner = THIS_MODULE; @@ -895,10 +926,11 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) return 0; err_init_hw: - clk_disable(dev->clk); err_add_adap: clk_put(dev->clk); err_no_clk: + regulator_put(dev->regulator); + err_no_regulator: free_irq(dev->irq, dev); err_irq: iounmap(dev->virtbase); @@ -928,8 +960,8 @@ static int __devexit nmk_i2c_remove(struct platform_device *pdev) iounmap(dev->virtbase); if (res) release_mem_region(res->start, resource_size(res)); - clk_disable(dev->clk); clk_put(dev->clk); + regulator_put(dev->regulator); platform_set_drvdata(pdev, NULL); kfree(dev); |