#define S3C2440_IICINT_BUSHOLD_CLEAR (1 << 8)
+#define S3C2410_NEED_REG_INIT (1 << 0)
+#define S3C2410_NEED_BUS_INIT (2 << 0)
+#define S3C2410_NEED_FULL_INIT (3 << 0)
+
/* Treat S3C2410 as baseline hardware, anything else is supported via quirks */
#define QUIRK_S3C2440 (1 << 0)
#define QUIRK_HDMIPHY (1 << 1)
ret = s3c24xx_i2c_set_master(i2c);
if (ret != 0) {
dev_err(i2c->dev, "cannot get bus (error %d)\n", ret);
+ i2c->need_hw_init = S3C2410_NEED_FULL_INIT;
ret = -EAGAIN;
goto out;
}
if (ret)
return ret;
- if (i2c->need_hw_init)
- s3c24xx_i2c_init(i2c);
for (retry = 0; retry < adap->retries; retry++) {
+ if (i2c->need_hw_init & S3C2410_NEED_FULL_INIT)
+ s3c24xx_i2c_init(i2c);
+
ret = s3c24xx_i2c_doxfer(i2c, msgs, num);
if (ret != -EAGAIN) {
static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
{
struct s3c2410_platform_i2c *pdata;
+ unsigned long iicstat = readl(i2c->regs + S3C2410_IICSTAT);
unsigned int freq;
/* get the plafrom data */
pdata = i2c->pdata;
- /* write slave address */
+ if (i2c->need_hw_init & S3C2410_NEED_BUS_INIT) {
+ /* reset i2c bus to recover from "cannot get bus" */
+ iicstat &= ~S3C2410_IICSTAT_TXRXEN;
+ writel(iicstat, i2c->regs + S3C2410_IICSTAT);
+ }
+ /* write slave address */
writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD);
dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr);
switch (cmd) {
case LPA_EXIT:
list_for_each_entry(i2c, &drvdata_list, node)
- i2c->need_hw_init = 1;
+ i2c->need_hw_init = S3C2410_NEED_REG_INIT;
break;
}
return -EINVAL;
}
- i2c->need_hw_init = 1;
+ i2c->need_hw_init = S3C2410_NEED_REG_INIT;
/* find the IRQ for this unit (note, this relies on the init call to
* ensure no current IRQs pending
int ret;
i2c->suspended = 0;
- i2c->need_hw_init = 1;
+ i2c->need_hw_init = S3C2410_NEED_REG_INIT;
return 0;
}
struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
if (i2c->quirks & QUIRK_FIMC_I2C)
- i2c->need_hw_init = 1;
+ i2c->need_hw_init = S3C2410_NEED_REG_INIT;
return 0;
}