aboutsummaryrefslogtreecommitdiff
path: root/drivers/i2c
diff options
context:
space:
mode:
authorMian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>2010-10-18 14:30:18 +0200
committerMian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>2010-10-23 13:29:31 +0200
commit54601118d5d8f0e10759761161571c28847ed59b (patch)
tree9f5913137e8760fc0ba8c23911414132b4e61c84 /drivers/i2c
parent4c7e90205e735659cc27d24ebc1296732624798b (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.c48
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);