diff options
| author | Rajendra Nayak <rnayak@ti.com> | 2010-09-28 11:32:58 -0400 |
|---|---|---|
| committer | Kevin Hilman <khilman@deeprootsystems.com> | 2010-11-09 12:31:10 -0500 |
| commit | 27b1fec2caa668c162cd1a862c69e087df277fae (patch) | |
| tree | 4e14adc83c89ece061ef2a76b6470f87e4bcc57a /drivers/i2c | |
| parent | 4d17aeb1c5b2375769446d13012a98e6d265ec13 (diff) | |
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>
Diffstat (limited to 'drivers/i2c')
| -rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 69 |
1 files changed, 23 insertions, 46 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index b33c78586bfc..760b8be6975f 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <linux/io.h> | 39 | #include <linux/io.h> |
| 40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
| 41 | #include <linux/i2c-omap.h> | 41 | #include <linux/i2c-omap.h> |
| 42 | #include <linux/pm_runtime.h> | ||
| 42 | 43 | ||
| 43 | /* I2C controller revisions */ | 44 | /* I2C controller revisions */ |
| 44 | #define OMAP_I2C_REV_2 0x20 | 45 | #define OMAP_I2C_REV_2 0x20 |
| @@ -175,8 +176,6 @@ struct omap_i2c_dev { | |||
| 175 | void __iomem *base; /* virtual */ | 176 | void __iomem *base; /* virtual */ |
| 176 | int irq; | 177 | int irq; |
| 177 | int reg_shift; /* bit shift for I2C register addresses */ | 178 | int reg_shift; /* bit shift for I2C register addresses */ |
| 178 | struct clk *iclk; /* Interface clock */ | ||
| 179 | struct clk *fclk; /* Functional clock */ | ||
| 180 | struct completion cmd_complete; | 179 | struct completion cmd_complete; |
| 181 | struct resource *ioarea; | 180 | struct resource *ioarea; |
| 182 | u32 latency; /* maximum mpu wkup latency */ | 181 | 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) | |||
| 265 | (i2c_dev->regs[reg] << i2c_dev->reg_shift)); | 264 | (i2c_dev->regs[reg] << i2c_dev->reg_shift)); |
| 266 | } | 265 | } |
| 267 | 266 | ||
| 268 | static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev) | 267 | static void omap_i2c_unidle(struct omap_i2c_dev *dev) |
| 269 | { | 268 | { |
| 270 | int ret; | 269 | struct platform_device *pdev; |
| 270 | struct omap_i2c_bus_platform_data *pdata; | ||
| 271 | 271 | ||
| 272 | dev->iclk = clk_get(dev->dev, "ick"); | 272 | WARN_ON(!dev->idle); |
| 273 | if (IS_ERR(dev->iclk)) { | ||
| 274 | ret = PTR_ERR(dev->iclk); | ||
| 275 | dev->iclk = NULL; | ||
| 276 | return ret; | ||
| 277 | } | ||
| 278 | 273 | ||
| 279 | dev->fclk = clk_get(dev->dev, "fck"); | 274 | pdev = to_platform_device(dev->dev); |
| 280 | if (IS_ERR(dev->fclk)) { | 275 | pdata = pdev->dev.platform_data; |
| 281 | ret = PTR_ERR(dev->fclk); | ||
| 282 | if (dev->iclk != NULL) { | ||
| 283 | clk_put(dev->iclk); | ||
| 284 | dev->iclk = NULL; | ||
| 285 | } | ||
| 286 | dev->fclk = NULL; | ||
| 287 | return ret; | ||
| 288 | } | ||
| 289 | 276 | ||
| 290 | return 0; | 277 | pm_runtime_get_sync(&pdev->dev); |
| 291 | } | ||
| 292 | 278 | ||
| 293 | static void omap_i2c_put_clocks(struct omap_i2c_dev *dev) | ||
| 294 | { | ||
| 295 | clk_put(dev->fclk); | ||
| 296 | dev->fclk = NULL; | ||
| 297 | clk_put(dev->iclk); | ||
| 298 | dev->iclk = NULL; | ||
| 299 | } | ||
| 300 | |||
| 301 | static void omap_i2c_unidle(struct omap_i2c_dev *dev) | ||
| 302 | { | ||
| 303 | WARN_ON(!dev->idle); | ||
| 304 | |||
| 305 | clk_enable(dev->iclk); | ||
| 306 | clk_enable(dev->fclk); | ||
| 307 | if (cpu_is_omap34xx()) { | 279 | if (cpu_is_omap34xx()) { |
| 308 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 280 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
| 309 | omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate); | 281 | 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) | |||
| 326 | 298 | ||
| 327 | static void omap_i2c_idle(struct omap_i2c_dev *dev) | 299 | static void omap_i2c_idle(struct omap_i2c_dev *dev) |
| 328 | { | 300 | { |
| 301 | struct platform_device *pdev; | ||
| 302 | struct omap_i2c_bus_platform_data *pdata; | ||
| 329 | u16 iv; | 303 | u16 iv; |
| 330 | 304 | ||
| 331 | WARN_ON(dev->idle); | 305 | WARN_ON(dev->idle); |
| 332 | 306 | ||
| 307 | pdev = to_platform_device(dev->dev); | ||
| 308 | pdata = pdev->dev.platform_data; | ||
| 309 | |||
| 333 | dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); | 310 | dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); |
| 334 | if (dev->rev >= OMAP_I2C_REV_ON_4430) | 311 | if (dev->rev >= OMAP_I2C_REV_ON_4430) |
| 335 | omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1); | 312 | omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1); |
| @@ -345,8 +322,8 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev) | |||
| 345 | omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); | 322 | omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); |
| 346 | } | 323 | } |
| 347 | dev->idle = 1; | 324 | dev->idle = 1; |
| 348 | clk_disable(dev->fclk); | 325 | |
| 349 | clk_disable(dev->iclk); | 326 | pm_runtime_put_sync(&pdev->dev); |
| 350 | } | 327 | } |
| 351 | 328 | ||
| 352 | static int omap_i2c_init(struct omap_i2c_dev *dev) | 329 | static int omap_i2c_init(struct omap_i2c_dev *dev) |
| @@ -356,6 +333,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
| 356 | unsigned long fclk_rate = 12000000; | 333 | unsigned long fclk_rate = 12000000; |
| 357 | unsigned long timeout; | 334 | unsigned long timeout; |
| 358 | unsigned long internal_clk = 0; | 335 | unsigned long internal_clk = 0; |
| 336 | struct clk *fclk; | ||
| 359 | 337 | ||
| 360 | if (dev->rev >= OMAP_I2C_REV_2) { | 338 | if (dev->rev >= OMAP_I2C_REV_2) { |
| 361 | /* Disable I2C controller before soft reset */ | 339 | /* Disable I2C controller before soft reset */ |
| @@ -414,7 +392,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
| 414 | * always returns 12MHz for the functional clock, we can | 392 | * always returns 12MHz for the functional clock, we can |
| 415 | * do this bit unconditionally. | 393 | * do this bit unconditionally. |
| 416 | */ | 394 | */ |
| 417 | fclk_rate = clk_get_rate(dev->fclk); | 395 | fclk = clk_get(dev->dev, "fck"); |
| 396 | fclk_rate = clk_get_rate(fclk); | ||
| 397 | clk_put(fclk); | ||
| 418 | 398 | ||
| 419 | /* TRM for 5912 says the I2C clock must be prescaled to be | 399 | /* TRM for 5912 says the I2C clock must be prescaled to be |
| 420 | * between 7 - 12 MHz. The XOR input clock is typically | 400 | * between 7 - 12 MHz. The XOR input clock is typically |
| @@ -443,7 +423,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
| 443 | internal_clk = 9600; | 423 | internal_clk = 9600; |
| 444 | else | 424 | else |
| 445 | internal_clk = 4000; | 425 | internal_clk = 4000; |
| 446 | fclk_rate = clk_get_rate(dev->fclk) / 1000; | 426 | fclk = clk_get(dev->dev, "fck"); |
| 427 | fclk_rate = clk_get_rate(fclk) / 1000; | ||
| 428 | clk_put(fclk); | ||
| 447 | 429 | ||
| 448 | /* Compute prescaler divisor */ | 430 | /* Compute prescaler divisor */ |
| 449 | psc = fclk_rate / internal_clk; | 431 | psc = fclk_rate / internal_clk; |
| @@ -1048,14 +1030,12 @@ omap_i2c_probe(struct platform_device *pdev) | |||
| 1048 | else | 1030 | else |
| 1049 | dev->reg_shift = 2; | 1031 | dev->reg_shift = 2; |
| 1050 | 1032 | ||
| 1051 | if ((r = omap_i2c_get_clocks(dev)) != 0) | ||
| 1052 | goto err_iounmap; | ||
| 1053 | |||
| 1054 | if (cpu_is_omap44xx()) | 1033 | if (cpu_is_omap44xx()) |
| 1055 | dev->regs = (u8 *) omap4_reg_map; | 1034 | dev->regs = (u8 *) omap4_reg_map; |
| 1056 | else | 1035 | else |
| 1057 | dev->regs = (u8 *) reg_map; | 1036 | dev->regs = (u8 *) reg_map; |
| 1058 | 1037 | ||
| 1038 | pm_runtime_enable(&pdev->dev); | ||
| 1059 | omap_i2c_unidle(dev); | 1039 | omap_i2c_unidle(dev); |
| 1060 | 1040 | ||
| 1061 | dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; | 1041 | dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; |
| @@ -1127,8 +1107,6 @@ err_free_irq: | |||
| 1127 | err_unuse_clocks: | 1107 | err_unuse_clocks: |
| 1128 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 1108 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
| 1129 | omap_i2c_idle(dev); | 1109 | omap_i2c_idle(dev); |
| 1130 | omap_i2c_put_clocks(dev); | ||
| 1131 | err_iounmap: | ||
| 1132 | iounmap(dev->base); | 1110 | iounmap(dev->base); |
| 1133 | err_free_mem: | 1111 | err_free_mem: |
| 1134 | platform_set_drvdata(pdev, NULL); | 1112 | platform_set_drvdata(pdev, NULL); |
| @@ -1150,7 +1128,6 @@ omap_i2c_remove(struct platform_device *pdev) | |||
| 1150 | free_irq(dev->irq, dev); | 1128 | free_irq(dev->irq, dev); |
| 1151 | i2c_del_adapter(&dev->adapter); | 1129 | i2c_del_adapter(&dev->adapter); |
| 1152 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 1130 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
| 1153 | omap_i2c_put_clocks(dev); | ||
| 1154 | iounmap(dev->base); | 1131 | iounmap(dev->base); |
| 1155 | kfree(dev); | 1132 | kfree(dev); |
| 1156 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1133 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
