Skip to content

Commit

Permalink
OMAP: I2C: Convert i2c driver to use PM runtime api's
Browse files Browse the repository at this point in the history
This patch converts the i2c driver to use PM runtime apis

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Jean Delvare <khali@linux-fr.org>
Acked-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
  • Loading branch information
Rajendra Nayak authored and Kevin Hilman committed Nov 9, 2010
1 parent 4d17aeb commit 27b1fec
Showing 1 changed file with 23 additions and 46 deletions.
69 changes: 23 additions & 46 deletions drivers/i2c/busses/i2c-omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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)
Expand All @@ -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 */
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1048,14 +1030,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;
Expand Down Expand Up @@ -1127,8 +1107,6 @@ omap_i2c_probe(struct platform_device *pdev)
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);
Expand All @@ -1150,7 +1128,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);
Expand Down

0 comments on commit 27b1fec

Please sign in to comment.