diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-omap.c')
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 122 |
1 files changed, 66 insertions, 56 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index b33c78586bfc..58a58c7eaa17 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; |
271 | 270 | struct omap_i2c_bus_platform_data *pdata; | |
272 | dev->iclk = clk_get(dev->dev, "ick"); | ||
273 | if (IS_ERR(dev->iclk)) { | ||
274 | ret = PTR_ERR(dev->iclk); | ||
275 | dev->iclk = NULL; | ||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | dev->fclk = clk_get(dev->dev, "fck"); | ||
280 | if (IS_ERR(dev->fclk)) { | ||
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 | 271 | ||
290 | return 0; | 272 | WARN_ON(!dev->idle); |
291 | } | ||
292 | 273 | ||
293 | static void omap_i2c_put_clocks(struct omap_i2c_dev *dev) | 274 | pdev = to_platform_device(dev->dev); |
294 | { | 275 | pdata = pdev->dev.platform_data; |
295 | clk_put(dev->fclk); | ||
296 | dev->fclk = NULL; | ||
297 | clk_put(dev->iclk); | ||
298 | dev->iclk = NULL; | ||
299 | } | ||
300 | 276 | ||
301 | static void omap_i2c_unidle(struct omap_i2c_dev *dev) | 277 | pm_runtime_get_sync(&pdev->dev); |
302 | { | ||
303 | WARN_ON(!dev->idle); | ||
304 | 278 | ||
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 */ |
@@ -400,9 +378,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
400 | * REVISIT: Some wkup sources might not be needed. | 378 | * REVISIT: Some wkup sources might not be needed. |
401 | */ | 379 | */ |
402 | dev->westate = OMAP_I2C_WE_ALL; | 380 | dev->westate = OMAP_I2C_WE_ALL; |
403 | if (dev->rev < OMAP_I2C_REV_ON_4430) | 381 | omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); |
404 | omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, | ||
405 | dev->westate); | ||
406 | } | 382 | } |
407 | } | 383 | } |
408 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 384 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
@@ -414,7 +390,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
414 | * always returns 12MHz for the functional clock, we can | 390 | * always returns 12MHz for the functional clock, we can |
415 | * do this bit unconditionally. | 391 | * do this bit unconditionally. |
416 | */ | 392 | */ |
417 | fclk_rate = clk_get_rate(dev->fclk); | 393 | fclk = clk_get(dev->dev, "fck"); |
394 | fclk_rate = clk_get_rate(fclk); | ||
395 | clk_put(fclk); | ||
418 | 396 | ||
419 | /* TRM for 5912 says the I2C clock must be prescaled to be | 397 | /* TRM for 5912 says the I2C clock must be prescaled to be |
420 | * between 7 - 12 MHz. The XOR input clock is typically | 398 | * between 7 - 12 MHz. The XOR input clock is typically |
@@ -443,7 +421,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
443 | internal_clk = 9600; | 421 | internal_clk = 9600; |
444 | else | 422 | else |
445 | internal_clk = 4000; | 423 | internal_clk = 4000; |
446 | fclk_rate = clk_get_rate(dev->fclk) / 1000; | 424 | fclk = clk_get(dev->dev, "fck"); |
425 | fclk_rate = clk_get_rate(fclk) / 1000; | ||
426 | clk_put(fclk); | ||
447 | 427 | ||
448 | /* Compute prescaler divisor */ | 428 | /* Compute prescaler divisor */ |
449 | psc = fclk_rate / internal_clk; | 429 | psc = fclk_rate / internal_clk; |
@@ -616,12 +596,8 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, | |||
616 | * REVISIT: We should abort the transfer on signals, but the bus goes | 596 | * REVISIT: We should abort the transfer on signals, but the bus goes |
617 | * into arbitration and we're currently unable to recover from it. | 597 | * into arbitration and we're currently unable to recover from it. |
618 | */ | 598 | */ |
619 | if (dev->set_mpu_wkup_lat != NULL) | ||
620 | dev->set_mpu_wkup_lat(dev->dev, dev->latency); | ||
621 | r = wait_for_completion_timeout(&dev->cmd_complete, | 599 | r = wait_for_completion_timeout(&dev->cmd_complete, |
622 | OMAP_I2C_TIMEOUT); | 600 | OMAP_I2C_TIMEOUT); |
623 | if (dev->set_mpu_wkup_lat != NULL) | ||
624 | dev->set_mpu_wkup_lat(dev->dev, -1); | ||
625 | dev->buf_len = 0; | 601 | dev->buf_len = 0; |
626 | if (r < 0) | 602 | if (r < 0) |
627 | return r; | 603 | return r; |
@@ -672,12 +648,18 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | |||
672 | if (r < 0) | 648 | if (r < 0) |
673 | goto out; | 649 | goto out; |
674 | 650 | ||
651 | if (dev->set_mpu_wkup_lat != NULL) | ||
652 | dev->set_mpu_wkup_lat(dev->dev, dev->latency); | ||
653 | |||
675 | for (i = 0; i < num; i++) { | 654 | for (i = 0; i < num; i++) { |
676 | r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1))); | 655 | r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1))); |
677 | if (r != 0) | 656 | if (r != 0) |
678 | break; | 657 | break; |
679 | } | 658 | } |
680 | 659 | ||
660 | if (dev->set_mpu_wkup_lat != NULL) | ||
661 | dev->set_mpu_wkup_lat(dev->dev, -1); | ||
662 | |||
681 | if (r == 0) | 663 | if (r == 0) |
682 | r = num; | 664 | r = num; |
683 | 665 | ||
@@ -863,11 +845,15 @@ complete: | |||
863 | dev_err(dev->dev, "Arbitration lost\n"); | 845 | dev_err(dev->dev, "Arbitration lost\n"); |
864 | err |= OMAP_I2C_STAT_AL; | 846 | err |= OMAP_I2C_STAT_AL; |
865 | } | 847 | } |
848 | /* | ||
849 | * ProDB0017052: Clear ARDY bit twice | ||
850 | */ | ||
866 | if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK | | 851 | if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK | |
867 | OMAP_I2C_STAT_AL)) { | 852 | OMAP_I2C_STAT_AL)) { |
868 | omap_i2c_ack_stat(dev, stat & | 853 | omap_i2c_ack_stat(dev, stat & |
869 | (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR | | 854 | (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR | |
870 | OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)); | 855 | OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR | |
856 | OMAP_I2C_STAT_ARDY)); | ||
871 | omap_i2c_complete_cmd(dev, err); | 857 | omap_i2c_complete_cmd(dev, err); |
872 | return IRQ_HANDLED; | 858 | return IRQ_HANDLED; |
873 | } | 859 | } |
@@ -1048,14 +1034,12 @@ omap_i2c_probe(struct platform_device *pdev) | |||
1048 | else | 1034 | else |
1049 | dev->reg_shift = 2; | 1035 | dev->reg_shift = 2; |
1050 | 1036 | ||
1051 | if ((r = omap_i2c_get_clocks(dev)) != 0) | ||
1052 | goto err_iounmap; | ||
1053 | |||
1054 | if (cpu_is_omap44xx()) | 1037 | if (cpu_is_omap44xx()) |
1055 | dev->regs = (u8 *) omap4_reg_map; | 1038 | dev->regs = (u8 *) omap4_reg_map; |
1056 | else | 1039 | else |
1057 | dev->regs = (u8 *) reg_map; | 1040 | dev->regs = (u8 *) reg_map; |
1058 | 1041 | ||
1042 | pm_runtime_enable(&pdev->dev); | ||
1059 | omap_i2c_unidle(dev); | 1043 | omap_i2c_unidle(dev); |
1060 | 1044 | ||
1061 | dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; | 1045 | dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; |
@@ -1127,8 +1111,6 @@ err_free_irq: | |||
1127 | err_unuse_clocks: | 1111 | err_unuse_clocks: |
1128 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 1112 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
1129 | omap_i2c_idle(dev); | 1113 | omap_i2c_idle(dev); |
1130 | omap_i2c_put_clocks(dev); | ||
1131 | err_iounmap: | ||
1132 | iounmap(dev->base); | 1114 | iounmap(dev->base); |
1133 | err_free_mem: | 1115 | err_free_mem: |
1134 | platform_set_drvdata(pdev, NULL); | 1116 | platform_set_drvdata(pdev, NULL); |
@@ -1150,7 +1132,6 @@ omap_i2c_remove(struct platform_device *pdev) | |||
1150 | free_irq(dev->irq, dev); | 1132 | free_irq(dev->irq, dev); |
1151 | i2c_del_adapter(&dev->adapter); | 1133 | i2c_del_adapter(&dev->adapter); |
1152 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 1134 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
1153 | omap_i2c_put_clocks(dev); | ||
1154 | iounmap(dev->base); | 1135 | iounmap(dev->base); |
1155 | kfree(dev); | 1136 | kfree(dev); |
1156 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1137 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -1158,12 +1139,41 @@ omap_i2c_remove(struct platform_device *pdev) | |||
1158 | return 0; | 1139 | return 0; |
1159 | } | 1140 | } |
1160 | 1141 | ||
1142 | #ifdef CONFIG_SUSPEND | ||
1143 | static int omap_i2c_suspend(struct device *dev) | ||
1144 | { | ||
1145 | if (!pm_runtime_suspended(dev)) | ||
1146 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) | ||
1147 | dev->bus->pm->runtime_suspend(dev); | ||
1148 | |||
1149 | return 0; | ||
1150 | } | ||
1151 | |||
1152 | static int omap_i2c_resume(struct device *dev) | ||
1153 | { | ||
1154 | if (!pm_runtime_suspended(dev)) | ||
1155 | if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) | ||
1156 | dev->bus->pm->runtime_resume(dev); | ||
1157 | |||
1158 | return 0; | ||
1159 | } | ||
1160 | |||
1161 | static struct dev_pm_ops omap_i2c_pm_ops = { | ||
1162 | .suspend = omap_i2c_suspend, | ||
1163 | .resume = omap_i2c_resume, | ||
1164 | }; | ||
1165 | #define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops) | ||
1166 | #else | ||
1167 | #define OMAP_I2C_PM_OPS NULL | ||
1168 | #endif | ||
1169 | |||
1161 | static struct platform_driver omap_i2c_driver = { | 1170 | static struct platform_driver omap_i2c_driver = { |
1162 | .probe = omap_i2c_probe, | 1171 | .probe = omap_i2c_probe, |
1163 | .remove = omap_i2c_remove, | 1172 | .remove = omap_i2c_remove, |
1164 | .driver = { | 1173 | .driver = { |
1165 | .name = "i2c_omap", | 1174 | .name = "omap_i2c", |
1166 | .owner = THIS_MODULE, | 1175 | .owner = THIS_MODULE, |
1176 | .pm = OMAP_I2C_PM_OPS, | ||
1167 | }, | 1177 | }, |
1168 | }; | 1178 | }; |
1169 | 1179 | ||
@@ -1184,4 +1194,4 @@ module_exit(omap_i2c_exit_driver); | |||
1184 | MODULE_AUTHOR("MontaVista Software, Inc. (and others)"); | 1194 | MODULE_AUTHOR("MontaVista Software, Inc. (and others)"); |
1185 | MODULE_DESCRIPTION("TI OMAP I2C bus adapter"); | 1195 | MODULE_DESCRIPTION("TI OMAP I2C bus adapter"); |
1186 | MODULE_LICENSE("GPL"); | 1196 | MODULE_LICENSE("GPL"); |
1187 | MODULE_ALIAS("platform:i2c_omap"); | 1197 | MODULE_ALIAS("platform:omap_i2c"); |