Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 27b1fec2 authored by Rajendra Nayak's avatar Rajendra Nayak Committed by Kevin Hilman
Browse files

OMAP: I2C: Convert i2c driver to use PM runtime api's



This patch converts the i2c driver to use PM runtime apis

Signed-off-by: default avatarRajendra Nayak <rnayak@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Jean Delvare <khali@linux-fr.org>
Acked-by: default avatarBen Dooks <ben-linux@fluff.org>
Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent 4d17aeb1
Loading
Loading
Loading
Loading
+23 −46
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -1127,8 +1107,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);
@@ -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);