Skip to content

Commit

Permalink
i2c-mpc: avoid I2C abnormal after resuming from deep sleep
Browse files Browse the repository at this point in the history
When entering deep sleep, the value in the registers I2CFDR and
I2CDFSRR are lost. This causes I2C access to fail after resuming.

Add suspend/resume routines to save/restore the registers
I2CFDR and I2CDFSRR.

Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
  • Loading branch information
Zhao Chenhui authored and Wolfram Sang committed May 12, 2012
1 parent ad33707 commit 531183e
Showing 1 changed file with 30 additions and 0 deletions.
30 changes: 30 additions & 0 deletions drivers/i2c/busses/i2c-mpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ struct mpc_i2c {
struct i2c_adapter adap;
int irq;
u32 real_clk;
#ifdef CONFIG_PM
u8 fdr, dfsrr;
#endif
};

struct mpc_i2c_divider {
Expand Down Expand Up @@ -703,6 +706,30 @@ static int __devexit fsl_i2c_remove(struct platform_device *op)
return 0;
};

#ifdef CONFIG_PM
static int mpc_i2c_suspend(struct device *dev)
{
struct mpc_i2c *i2c = dev_get_drvdata(dev);

i2c->fdr = readb(i2c->base + MPC_I2C_FDR);
i2c->dfsrr = readb(i2c->base + MPC_I2C_DFSRR);

return 0;
}

static int mpc_i2c_resume(struct device *dev)
{
struct mpc_i2c *i2c = dev_get_drvdata(dev);

writeb(i2c->fdr, i2c->base + MPC_I2C_FDR);
writeb(i2c->dfsrr, i2c->base + MPC_I2C_DFSRR);

return 0;
}

SIMPLE_DEV_PM_OPS(mpc_i2c_pm_ops, mpc_i2c_suspend, mpc_i2c_resume);
#endif

static struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = {
.setup = mpc_i2c_setup_512x,
};
Expand Down Expand Up @@ -747,6 +774,9 @@ static struct platform_driver mpc_i2c_driver = {
.owner = THIS_MODULE,
.name = DRV_NAME,
.of_match_table = mpc_i2c_of_match,
#ifdef CONFIG_PM
.pm = &mpc_i2c_pm_ops,
#endif
},
};

Expand Down

0 comments on commit 531183e

Please sign in to comment.