aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2014-02-07 03:54:09 -0500
committerWolfram Sang <wsa@the-dreams.de>2014-03-12 15:45:17 -0400
commit069a9502dd7c51cf2f9031cd86d88774c696101c (patch)
tree977b660ce1462272b49828ed4fdd89d36a3cd484 /drivers/i2c
parent5304032c9ebe5ed8a6dcac328bb399fb87c5c9af (diff)
i2c: s3c2410: Leave the bus disabled unless it is in use
There is a rather odd feature of the exynos i2c controller that if it is left enabled, it can lock itself up with the clk line held low. This makes the bus unusable. Unfortunately, the s3c24xx_i2c_set_master() function does not notice this, and reports a timeout. From then on the bus cannot be used until the AP is rebooted. The problem happens when any sort of interrupt occurs (e.g. due to a bus transition) when we are not in the middle of a transaction. We have seen many instances of this when U-Boot leaves the bus apparently happy, but Linux cannot access it. The current code is therefore pretty fragile. This fixes things by leaving the bus disabled unless we are actually in a transaction. We enable the bus at the start of the transaction and disable it at the end. That way we won't get interrupts and will not lock up the bus. It might be possible to clear pending interrupts on start-up, but this seems to be a more robust solution. We can't service interrupts when we are not in a transaction, and anyway would rather not lock up the bus while we try. Signed-off-by: Simon Glass <sjg@chromium.org> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com> Acked-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 8162901ff753..ae4491062e41 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -601,6 +601,31 @@ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
601 return IRQ_HANDLED; 601 return IRQ_HANDLED;
602} 602}
603 603
604/*
605 * Disable the bus so that we won't get any interrupts from now on, or try
606 * to drive any lines. This is the default state when we don't have
607 * anything to send/receive.
608 *
609 * If there is an event on the bus, or we have a pre-existing event at
610 * kernel boot time, we may not notice the event and the I2C controller
611 * will lock the bus with the I2C clock line low indefinitely.
612 */
613static inline void s3c24xx_i2c_disable_bus(struct s3c24xx_i2c *i2c)
614{
615 unsigned long tmp;
616
617 /* Stop driving the I2C pins */
618 tmp = readl(i2c->regs + S3C2410_IICSTAT);
619 tmp &= ~S3C2410_IICSTAT_TXRXEN;
620 writel(tmp, i2c->regs + S3C2410_IICSTAT);
621
622 /* We don't expect any interrupts now, and don't want send acks */
623 tmp = readl(i2c->regs + S3C2410_IICCON);
624 tmp &= ~(S3C2410_IICCON_IRQEN | S3C2410_IICCON_IRQPEND |
625 S3C2410_IICCON_ACKEN);
626 writel(tmp, i2c->regs + S3C2410_IICCON);
627}
628
604 629
605/* s3c24xx_i2c_set_master 630/* s3c24xx_i2c_set_master
606 * 631 *
@@ -735,7 +760,11 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
735 760
736 s3c24xx_i2c_wait_idle(i2c); 761 s3c24xx_i2c_wait_idle(i2c);
737 762
763 s3c24xx_i2c_disable_bus(i2c);
764
738 out: 765 out:
766 i2c->state = STATE_IDLE;
767
739 return ret; 768 return ret;
740} 769}
741 770
@@ -1004,7 +1033,6 @@ static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
1004 1033
1005static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) 1034static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
1006{ 1035{
1007 unsigned long iicon = S3C2410_IICCON_IRQEN | S3C2410_IICCON_ACKEN;
1008 struct s3c2410_platform_i2c *pdata; 1036 struct s3c2410_platform_i2c *pdata;
1009 unsigned int freq; 1037 unsigned int freq;
1010 1038
@@ -1018,12 +1046,12 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
1018 1046
1019 dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); 1047 dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr);
1020 1048
1021 writel(iicon, i2c->regs + S3C2410_IICCON); 1049 writel(0, i2c->regs + S3C2410_IICCON);
1050 writel(0, i2c->regs + S3C2410_IICSTAT);
1022 1051
1023 /* we need to work out the divisors for the clock... */ 1052 /* we need to work out the divisors for the clock... */
1024 1053
1025 if (s3c24xx_i2c_clockrate(i2c, &freq) != 0) { 1054 if (s3c24xx_i2c_clockrate(i2c, &freq) != 0) {
1026 writel(0, i2c->regs + S3C2410_IICCON);
1027 dev_err(i2c->dev, "cannot meet bus frequency required\n"); 1055 dev_err(i2c->dev, "cannot meet bus frequency required\n");
1028 return -EINVAL; 1056 return -EINVAL;
1029 } 1057 }
@@ -1031,7 +1059,8 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
1031 /* todo - check that the i2c lines aren't being dragged anywhere */ 1059 /* todo - check that the i2c lines aren't being dragged anywhere */
1032 1060
1033 dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); 1061 dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq);
1034 dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); 1062 dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02x\n",
1063 readl(i2c->regs + S3C2410_IICCON));
1035 1064
1036 return 0; 1065 return 0;
1037} 1066}