aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-omap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-omap.c')
-rw-r--r--drivers/i2c/busses/i2c-omap.c36
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
133static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, 135static 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
177static void omap_i2c_enable_clocks(struct omap_i2c_dev *dev) 179static 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
184static void omap_i2c_disable_clocks(struct omap_i2c_dev *dev) 189static 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
191static int omap_i2c_init(struct omap_i2c_dev *dev) 205static 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;
376out: 390out:
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);
619err_unuse_clocks: 639err_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);
623err_free_mem: 643err_free_mem:
624 platform_set_drvdata(pdev, NULL); 644 platform_set_drvdata(pdev, NULL);