diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-s3c2410.c')
-rw-r--r-- | drivers/i2c/busses/i2c-s3c2410.c | 52 |
1 files changed, 16 insertions, 36 deletions
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index f84a63c..b723b0b 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -469,6 +469,10 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) msleep(1); } + writel(iicstat & ~S3C2410_IICSTAT_TXRXEN, i2c->regs + S3C2410_IICSTAT); + if (!(readl(i2c->regs + S3C2410_IICSTAT) & S3C2410_IICSTAT_BUSBUSY)) + return 0; + return -ETIMEDOUT; } @@ -480,8 +484,7 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num) { - unsigned long iicstat, timeout; - int spins = 20; + unsigned long timeout; int ret; if (i2c->suspended) @@ -520,21 +523,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, /* ensure the stop has been through the bus */ - dev_dbg(i2c->dev, "waiting for bus idle\n"); - - /* first, try busy waiting briefly */ - do { - iicstat = readl(i2c->regs + S3C2410_IICSTAT); - } while ((iicstat & S3C2410_IICSTAT_START) && --spins); - - /* if that timed out sleep */ - if (!spins) { - msleep(1); - iicstat = readl(i2c->regs + S3C2410_IICSTAT); - } - - if (iicstat & S3C2410_IICSTAT_START) - dev_warn(i2c->dev, "timeout waiting for bus idle\n"); + udelay(10); out: return ret; @@ -661,23 +650,6 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) writel(iiccon, i2c->regs + S3C2410_IICCON); - if (s3c24xx_i2c_is2440(i2c)) { - unsigned long sda_delay; - - if (pdata->sda_delay) { - sda_delay = clkin * pdata->sda_delay; - sda_delay = DIV_ROUND_UP(sda_delay, 1000000); - sda_delay = DIV_ROUND_UP(sda_delay, 5); - if (sda_delay > 3) - sda_delay = 3; - sda_delay |= S3C2410_IICLC_FILTER_ON; - } else - sda_delay = 0; - - dev_dbg(i2c->dev, "IICLC=%08lx\n", sda_delay); - writel(sda_delay, i2c->regs + S3C2440_IICLC); - } - return 0; } @@ -694,6 +666,8 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb, int delta_f; int ret; + clk_enable(i2c->clk); + delta_f = clk_get_rate(i2c->clk) - i2c->clkrate; /* if we're post-change and the input clock has slowed down @@ -713,6 +687,8 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb, dev_info(i2c->dev, "setting freq %d\n", got); } + clk_disable(i2c->clk); + return 0; } @@ -765,7 +741,7 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD); - dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); + dev_dbg(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); writel(iicon, i2c->regs + S3C2410_IICCON); @@ -779,9 +755,12 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) /* todo - check that the i2c lines aren't being dragged anywhere */ - dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); + dev_dbg(i2c->dev, "bus frequency set to %d KHz\n", freq); dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); + dev_dbg(i2c->dev, "S3C2440_IICLC=%08x\n", pdata->sda_delay); + writel(pdata->sda_delay, i2c->regs + S3C2440_IICLC); + return 0; } @@ -823,6 +802,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) i2c->dev = &pdev->dev; i2c->clk = clk_get(&pdev->dev, "i2c"); + if (IS_ERR(i2c->clk)) { dev_err(&pdev->dev, "cannot get clock\n"); ret = -ENOENT; |