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/busses/i2c-omap.c | |
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/busses/i2c-omap.c')
-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); |