diff options
author | Kevin Hilman <khilman@ti.com> | 2011-05-17 10:31:38 -0400 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2011-10-29 04:37:09 -0400 |
commit | fab67afb543c734c23be0ebfc16f31814df2da79 (patch) | |
tree | 5cca96aa3534377043c7490c7851cbd963079ee3 /drivers/i2c | |
parent | 7f4b08eeeedd90d97c8c581d048074e0c2643bec (diff) |
I2C: OMAP: remove dev->idle, use usage counting provided by runtime PM
Current usage of runtime PM is not quite correct. The actual
idle/unidle of the I2C hardware should not happen until the runtime PM
callbacks are called. Therefore, change omap_i2c_[un]idle() functions
to only be called from the runtime PM callbacks (when usage count
transitions to/from zero.)
Also, the runtime PM core does usage counting and replaces
functionality currently managed by the dev->idle flag. Remove usage
of dev->idle in favor of using runtime PM, and checking status using
pm_runtime_suspended().
Signed-off-by: Kevin Hilman <khilman@ti.com>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index cddb29c15314..a43d0023446a 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
@@ -194,7 +194,6 @@ struct omap_i2c_dev { | |||
194 | */ | 194 | */ |
195 | u8 rev; | 195 | u8 rev; |
196 | unsigned b_hw:1; /* bad h/w fixes */ | 196 | unsigned b_hw:1; /* bad h/w fixes */ |
197 | unsigned idle:1; | ||
198 | u16 iestate; /* Saved interrupt register */ | 197 | u16 iestate; /* Saved interrupt register */ |
199 | u16 pscstate; | 198 | u16 pscstate; |
200 | u16 scllstate; | 199 | u16 scllstate; |
@@ -269,12 +268,8 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev) | |||
269 | { | 268 | { |
270 | struct omap_i2c_bus_platform_data *pdata; | 269 | struct omap_i2c_bus_platform_data *pdata; |
271 | 270 | ||
272 | WARN_ON(!dev->idle); | ||
273 | |||
274 | pdata = dev->dev->platform_data; | 271 | pdata = dev->dev->platform_data; |
275 | 272 | ||
276 | pm_runtime_get_sync(dev->dev); | ||
277 | |||
278 | if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { | 273 | if (pdata->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { |
279 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 274 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
280 | omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate); | 275 | omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate); |
@@ -285,7 +280,6 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev) | |||
285 | omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); | 280 | omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); |
286 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); | 281 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); |
287 | } | 282 | } |
288 | dev->idle = 0; | ||
289 | 283 | ||
290 | /* | 284 | /* |
291 | * Don't write to this register if the IE state is 0 as it can | 285 | * Don't write to this register if the IE state is 0 as it can |
@@ -300,8 +294,6 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev) | |||
300 | struct omap_i2c_bus_platform_data *pdata; | 294 | struct omap_i2c_bus_platform_data *pdata; |
301 | u16 iv; | 295 | u16 iv; |
302 | 296 | ||
303 | WARN_ON(dev->idle); | ||
304 | |||
305 | pdata = dev->dev->platform_data; | 297 | pdata = dev->dev->platform_data; |
306 | 298 | ||
307 | dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); | 299 | dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); |
@@ -315,12 +307,9 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev) | |||
315 | } else { | 307 | } else { |
316 | omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate); | 308 | omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate); |
317 | 309 | ||
318 | /* Flush posted write before the dev->idle store occurs */ | 310 | /* Flush posted write */ |
319 | omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); | 311 | omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); |
320 | } | 312 | } |
321 | dev->idle = 1; | ||
322 | |||
323 | pm_runtime_put_sync(dev->dev); | ||
324 | } | 313 | } |
325 | 314 | ||
326 | static int omap_i2c_init(struct omap_i2c_dev *dev) | 315 | static int omap_i2c_init(struct omap_i2c_dev *dev) |
@@ -644,7 +633,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | |||
644 | int i; | 633 | int i; |
645 | int r; | 634 | int r; |
646 | 635 | ||
647 | omap_i2c_unidle(dev); | 636 | pm_runtime_get_sync(dev->dev); |
648 | 637 | ||
649 | r = omap_i2c_wait_for_bb(dev); | 638 | r = omap_i2c_wait_for_bb(dev); |
650 | if (r < 0) | 639 | if (r < 0) |
@@ -667,7 +656,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | |||
667 | 656 | ||
668 | omap_i2c_wait_for_bb(dev); | 657 | omap_i2c_wait_for_bb(dev); |
669 | out: | 658 | out: |
670 | omap_i2c_idle(dev); | 659 | pm_runtime_put(dev->dev); |
671 | return r; | 660 | return r; |
672 | } | 661 | } |
673 | 662 | ||
@@ -727,7 +716,7 @@ omap_i2c_omap1_isr(int this_irq, void *dev_id) | |||
727 | struct omap_i2c_dev *dev = dev_id; | 716 | struct omap_i2c_dev *dev = dev_id; |
728 | u16 iv, w; | 717 | u16 iv, w; |
729 | 718 | ||
730 | if (dev->idle) | 719 | if (pm_runtime_suspended(dev->dev)) |
731 | return IRQ_NONE; | 720 | return IRQ_NONE; |
732 | 721 | ||
733 | iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); | 722 | iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); |
@@ -819,7 +808,7 @@ omap_i2c_isr(int this_irq, void *dev_id) | |||
819 | 808 | ||
820 | pdata = dev->dev->platform_data; | 809 | pdata = dev->dev->platform_data; |
821 | 810 | ||
822 | if (dev->idle) | 811 | if (pm_runtime_suspended(dev->dev)) |
823 | return IRQ_NONE; | 812 | return IRQ_NONE; |
824 | 813 | ||
825 | bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); | 814 | bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); |
@@ -1021,7 +1010,6 @@ omap_i2c_probe(struct platform_device *pdev) | |||
1021 | } | 1010 | } |
1022 | 1011 | ||
1023 | dev->speed = speed; | 1012 | dev->speed = speed; |
1024 | dev->idle = 1; | ||
1025 | dev->dev = &pdev->dev; | 1013 | dev->dev = &pdev->dev; |
1026 | dev->irq = irq->start; | 1014 | dev->irq = irq->start; |
1027 | dev->base = ioremap(mem->start, resource_size(mem)); | 1015 | dev->base = ioremap(mem->start, resource_size(mem)); |
@@ -1040,7 +1028,7 @@ omap_i2c_probe(struct platform_device *pdev) | |||
1040 | dev->regs = (u8 *)reg_map_ip_v1; | 1028 | dev->regs = (u8 *)reg_map_ip_v1; |
1041 | 1029 | ||
1042 | pm_runtime_enable(dev->dev); | 1030 | pm_runtime_enable(dev->dev); |
1043 | omap_i2c_unidle(dev); | 1031 | pm_runtime_get_sync(dev->dev); |
1044 | 1032 | ||
1045 | dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; | 1033 | dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; |
1046 | 1034 | ||
@@ -1087,7 +1075,7 @@ omap_i2c_probe(struct platform_device *pdev) | |||
1087 | dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id, | 1075 | dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id, |
1088 | pdata->rev, dev->rev >> 4, dev->rev & 0xf, dev->speed); | 1076 | pdata->rev, dev->rev >> 4, dev->rev & 0xf, dev->speed); |
1089 | 1077 | ||
1090 | omap_i2c_idle(dev); | 1078 | pm_runtime_put(dev->dev); |
1091 | 1079 | ||
1092 | adap = &dev->adapter; | 1080 | adap = &dev->adapter; |
1093 | i2c_set_adapdata(adap, dev); | 1081 | i2c_set_adapdata(adap, dev); |
@@ -1111,7 +1099,7 @@ err_free_irq: | |||
1111 | free_irq(dev->irq, dev); | 1099 | free_irq(dev->irq, dev); |
1112 | err_unuse_clocks: | 1100 | err_unuse_clocks: |
1113 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 1101 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
1114 | omap_i2c_idle(dev); | 1102 | pm_runtime_put(dev->dev); |
1115 | iounmap(dev->base); | 1103 | iounmap(dev->base); |
1116 | err_free_mem: | 1104 | err_free_mem: |
1117 | platform_set_drvdata(pdev, NULL); | 1105 | platform_set_drvdata(pdev, NULL); |
@@ -1140,12 +1128,43 @@ omap_i2c_remove(struct platform_device *pdev) | |||
1140 | return 0; | 1128 | return 0; |
1141 | } | 1129 | } |
1142 | 1130 | ||
1131 | #ifdef CONFIG_PM_RUNTIME | ||
1132 | static int omap_i2c_runtime_suspend(struct device *dev) | ||
1133 | { | ||
1134 | struct platform_device *pdev = to_platform_device(dev); | ||
1135 | struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); | ||
1136 | |||
1137 | omap_i2c_idle(_dev); | ||
1138 | |||
1139 | return 0; | ||
1140 | } | ||
1141 | |||
1142 | static int omap_i2c_runtime_resume(struct device *dev) | ||
1143 | { | ||
1144 | struct platform_device *pdev = to_platform_device(dev); | ||
1145 | struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); | ||
1146 | |||
1147 | omap_i2c_unidle(_dev); | ||
1148 | |||
1149 | return 0; | ||
1150 | } | ||
1151 | |||
1152 | static struct dev_pm_ops omap_i2c_pm_ops = { | ||
1153 | .runtime_suspend = omap_i2c_runtime_suspend, | ||
1154 | .runtime_resume = omap_i2c_runtime_resume, | ||
1155 | }; | ||
1156 | #define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops) | ||
1157 | #else | ||
1158 | #define OMAP_I2C_PM_OPS NULL | ||
1159 | #endif | ||
1160 | |||
1143 | static struct platform_driver omap_i2c_driver = { | 1161 | static struct platform_driver omap_i2c_driver = { |
1144 | .probe = omap_i2c_probe, | 1162 | .probe = omap_i2c_probe, |
1145 | .remove = omap_i2c_remove, | 1163 | .remove = omap_i2c_remove, |
1146 | .driver = { | 1164 | .driver = { |
1147 | .name = "omap_i2c", | 1165 | .name = "omap_i2c", |
1148 | .owner = THIS_MODULE, | 1166 | .owner = THIS_MODULE, |
1167 | .pm = OMAP_I2C_PM_OPS, | ||
1149 | }, | 1168 | }, |
1150 | }; | 1169 | }; |
1151 | 1170 | ||