diff options
| -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); |
