diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index da6639707ea3..7ba31770d773 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
@@ -128,6 +128,8 @@ struct omap_i2c_dev { | |||
128 | size_t buf_len; | 128 | size_t buf_len; |
129 | struct i2c_adapter adapter; | 129 | struct i2c_adapter adapter; |
130 | unsigned rev1:1; | 130 | unsigned rev1:1; |
131 | unsigned idle:1; | ||
132 | u16 iestate; /* Saved interrupt register */ | ||
131 | }; | 133 | }; |
132 | 134 | ||
133 | static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, | 135 | static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, |
@@ -174,18 +176,30 @@ static void omap_i2c_put_clocks(struct omap_i2c_dev *dev) | |||
174 | } | 176 | } |
175 | } | 177 | } |
176 | 178 | ||
177 | static void omap_i2c_enable_clocks(struct omap_i2c_dev *dev) | 179 | static void omap_i2c_unidle(struct omap_i2c_dev *dev) |
178 | { | 180 | { |
179 | if (dev->iclk != NULL) | 181 | if (dev->iclk != NULL) |
180 | clk_enable(dev->iclk); | 182 | clk_enable(dev->iclk); |
181 | clk_enable(dev->fclk); | 183 | clk_enable(dev->fclk); |
184 | if (dev->iestate) | ||
185 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); | ||
186 | dev->idle = 0; | ||
182 | } | 187 | } |
183 | 188 | ||
184 | static void omap_i2c_disable_clocks(struct omap_i2c_dev *dev) | 189 | static void omap_i2c_idle(struct omap_i2c_dev *dev) |
185 | { | 190 | { |
191 | u16 iv; | ||
192 | |||
193 | dev->idle = 1; | ||
194 | dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); | ||
195 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); | ||
196 | if (dev->rev1) | ||
197 | iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */ | ||
198 | else | ||
199 | omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate); | ||
200 | clk_disable(dev->fclk); | ||
186 | if (dev->iclk != NULL) | 201 | if (dev->iclk != NULL) |
187 | clk_disable(dev->iclk); | 202 | clk_disable(dev->iclk); |
188 | clk_disable(dev->fclk); | ||
189 | } | 203 | } |
190 | 204 | ||
191 | static int omap_i2c_init(struct omap_i2c_dev *dev) | 205 | static int omap_i2c_init(struct omap_i2c_dev *dev) |
@@ -360,7 +374,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | |||
360 | int i; | 374 | int i; |
361 | int r; | 375 | int r; |
362 | 376 | ||
363 | omap_i2c_enable_clocks(dev); | 377 | omap_i2c_unidle(dev); |
364 | 378 | ||
365 | if ((r = omap_i2c_wait_for_bb(dev)) < 0) | 379 | if ((r = omap_i2c_wait_for_bb(dev)) < 0) |
366 | goto out; | 380 | goto out; |
@@ -374,7 +388,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | |||
374 | if (r == 0) | 388 | if (r == 0) |
375 | r = num; | 389 | r = num; |
376 | out: | 390 | out: |
377 | omap_i2c_disable_clocks(dev); | 391 | omap_i2c_idle(dev); |
378 | return r; | 392 | return r; |
379 | } | 393 | } |
380 | 394 | ||
@@ -403,6 +417,9 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id) | |||
403 | struct omap_i2c_dev *dev = dev_id; | 417 | struct omap_i2c_dev *dev = dev_id; |
404 | u16 iv, w; | 418 | u16 iv, w; |
405 | 419 | ||
420 | if (dev->idle) | ||
421 | return IRQ_NONE; | ||
422 | |||
406 | iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); | 423 | iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); |
407 | switch (iv) { | 424 | switch (iv) { |
408 | case 0x00: /* None */ | 425 | case 0x00: /* None */ |
@@ -457,6 +474,9 @@ omap_i2c_isr(int this_irq, void *dev_id) | |||
457 | u16 stat, w; | 474 | u16 stat, w; |
458 | int count = 0; | 475 | int count = 0; |
459 | 476 | ||
477 | if (dev->idle) | ||
478 | return IRQ_NONE; | ||
479 | |||
460 | bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); | 480 | bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); |
461 | while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) { | 481 | while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) { |
462 | dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat); | 482 | dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat); |
@@ -575,7 +595,7 @@ omap_i2c_probe(struct platform_device *pdev) | |||
575 | if ((r = omap_i2c_get_clocks(dev)) != 0) | 595 | if ((r = omap_i2c_get_clocks(dev)) != 0) |
576 | goto err_free_mem; | 596 | goto err_free_mem; |
577 | 597 | ||
578 | omap_i2c_enable_clocks(dev); | 598 | omap_i2c_unidle(dev); |
579 | 599 | ||
580 | if (cpu_is_omap15xx()) | 600 | if (cpu_is_omap15xx()) |
581 | dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20; | 601 | dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20; |
@@ -610,7 +630,7 @@ omap_i2c_probe(struct platform_device *pdev) | |||
610 | goto err_free_irq; | 630 | goto err_free_irq; |
611 | } | 631 | } |
612 | 632 | ||
613 | omap_i2c_disable_clocks(dev); | 633 | omap_i2c_idle(dev); |
614 | 634 | ||
615 | return 0; | 635 | return 0; |
616 | 636 | ||
@@ -618,7 +638,7 @@ err_free_irq: | |||
618 | free_irq(dev->irq, dev); | 638 | free_irq(dev->irq, dev); |
619 | err_unuse_clocks: | 639 | err_unuse_clocks: |
620 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 640 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
621 | omap_i2c_disable_clocks(dev); | 641 | omap_i2c_idle(dev); |
622 | omap_i2c_put_clocks(dev); | 642 | omap_i2c_put_clocks(dev); |
623 | err_free_mem: | 643 | err_free_mem: |
624 | platform_set_drvdata(pdev, NULL); | 644 | platform_set_drvdata(pdev, NULL); |