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: 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>
This commit is contained in:
committed by
Kevin Hilman
parent
4d17aeb1c5
commit
27b1fec2ca
@@ -39,6 +39,7 @@
|
|||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/i2c-omap.h>
|
#include <linux/i2c-omap.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
/* I2C controller revisions */
|
/* I2C controller revisions */
|
||||||
#define OMAP_I2C_REV_2 0x20
|
#define OMAP_I2C_REV_2 0x20
|
||||||
@@ -175,8 +176,6 @@ struct omap_i2c_dev {
|
|||||||
void __iomem *base; /* virtual */
|
void __iomem *base; /* virtual */
|
||||||
int irq;
|
int irq;
|
||||||
int reg_shift; /* bit shift for I2C register addresses */
|
int reg_shift; /* bit shift for I2C register addresses */
|
||||||
struct clk *iclk; /* Interface clock */
|
|
||||||
struct clk *fclk; /* Functional clock */
|
|
||||||
struct completion cmd_complete;
|
struct completion cmd_complete;
|
||||||
struct resource *ioarea;
|
struct resource *ioarea;
|
||||||
u32 latency; /* maximum mpu wkup latency */
|
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));
|
(i2c_dev->regs[reg] << i2c_dev->reg_shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
dev->iclk = clk_get(dev->dev, "ick");
|
|
||||||
if (IS_ERR(dev->iclk)) {
|
|
||||||
ret = PTR_ERR(dev->iclk);
|
|
||||||
dev->iclk = NULL;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
static void omap_i2c_unidle(struct omap_i2c_dev *dev)
|
||||||
{
|
{
|
||||||
|
struct platform_device *pdev;
|
||||||
|
struct omap_i2c_bus_platform_data *pdata;
|
||||||
|
|
||||||
WARN_ON(!dev->idle);
|
WARN_ON(!dev->idle);
|
||||||
|
|
||||||
clk_enable(dev->iclk);
|
pdev = to_platform_device(dev->dev);
|
||||||
clk_enable(dev->fclk);
|
pdata = pdev->dev.platform_data;
|
||||||
|
|
||||||
|
pm_runtime_get_sync(&pdev->dev);
|
||||||
|
|
||||||
if (cpu_is_omap34xx()) {
|
if (cpu_is_omap34xx()) {
|
||||||
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
|
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
|
||||||
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
|
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)
|
static void omap_i2c_idle(struct omap_i2c_dev *dev)
|
||||||
{
|
{
|
||||||
|
struct platform_device *pdev;
|
||||||
|
struct omap_i2c_bus_platform_data *pdata;
|
||||||
u16 iv;
|
u16 iv;
|
||||||
|
|
||||||
WARN_ON(dev->idle);
|
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);
|
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
|
||||||
if (dev->rev >= OMAP_I2C_REV_ON_4430)
|
if (dev->rev >= OMAP_I2C_REV_ON_4430)
|
||||||
omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1);
|
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);
|
omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
|
||||||
}
|
}
|
||||||
dev->idle = 1;
|
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)
|
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 fclk_rate = 12000000;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
unsigned long internal_clk = 0;
|
unsigned long internal_clk = 0;
|
||||||
|
struct clk *fclk;
|
||||||
|
|
||||||
if (dev->rev >= OMAP_I2C_REV_2) {
|
if (dev->rev >= OMAP_I2C_REV_2) {
|
||||||
/* Disable I2C controller before soft reset */
|
/* 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
|
* always returns 12MHz for the functional clock, we can
|
||||||
* do this bit unconditionally.
|
* 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
|
/* TRM for 5912 says the I2C clock must be prescaled to be
|
||||||
* between 7 - 12 MHz. The XOR input clock is typically
|
* 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;
|
internal_clk = 9600;
|
||||||
else
|
else
|
||||||
internal_clk = 4000;
|
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 */
|
/* Compute prescaler divisor */
|
||||||
psc = fclk_rate / internal_clk;
|
psc = fclk_rate / internal_clk;
|
||||||
@@ -1048,14 +1030,12 @@ omap_i2c_probe(struct platform_device *pdev)
|
|||||||
else
|
else
|
||||||
dev->reg_shift = 2;
|
dev->reg_shift = 2;
|
||||||
|
|
||||||
if ((r = omap_i2c_get_clocks(dev)) != 0)
|
|
||||||
goto err_iounmap;
|
|
||||||
|
|
||||||
if (cpu_is_omap44xx())
|
if (cpu_is_omap44xx())
|
||||||
dev->regs = (u8 *) omap4_reg_map;
|
dev->regs = (u8 *) omap4_reg_map;
|
||||||
else
|
else
|
||||||
dev->regs = (u8 *) reg_map;
|
dev->regs = (u8 *) reg_map;
|
||||||
|
|
||||||
|
pm_runtime_enable(&pdev->dev);
|
||||||
omap_i2c_unidle(dev);
|
omap_i2c_unidle(dev);
|
||||||
|
|
||||||
dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
|
dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
|
||||||
@@ -1127,8 +1107,6 @@ err_free_irq:
|
|||||||
err_unuse_clocks:
|
err_unuse_clocks:
|
||||||
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
|
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
|
||||||
omap_i2c_idle(dev);
|
omap_i2c_idle(dev);
|
||||||
omap_i2c_put_clocks(dev);
|
|
||||||
err_iounmap:
|
|
||||||
iounmap(dev->base);
|
iounmap(dev->base);
|
||||||
err_free_mem:
|
err_free_mem:
|
||||||
platform_set_drvdata(pdev, NULL);
|
platform_set_drvdata(pdev, NULL);
|
||||||
@@ -1150,7 +1128,6 @@ omap_i2c_remove(struct platform_device *pdev)
|
|||||||
free_irq(dev->irq, dev);
|
free_irq(dev->irq, dev);
|
||||||
i2c_del_adapter(&dev->adapter);
|
i2c_del_adapter(&dev->adapter);
|
||||||
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
|
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
|
||||||
omap_i2c_put_clocks(dev);
|
|
||||||
iounmap(dev->base);
|
iounmap(dev->base);
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
Reference in New Issue
Block a user