Commit 531183e5d27312d68fab40352cd13426aa761473

Authored by Zhao Chenhui
Committed by Wolfram Sang
1 parent ad33707417

i2c-mpc: avoid I2C abnormal after resuming from deep sleep

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>

Showing 1 changed file with 30 additions and 0 deletions Side-by-side Diff

drivers/i2c/busses/i2c-mpc.c
... ... @@ -64,6 +64,9 @@
64 64 struct i2c_adapter adap;
65 65 int irq;
66 66 u32 real_clk;
  67 +#ifdef CONFIG_PM
  68 + u8 fdr, dfsrr;
  69 +#endif
67 70 };
68 71  
69 72 struct mpc_i2c_divider {
... ... @@ -703,6 +706,30 @@
703 706 return 0;
704 707 };
705 708  
  709 +#ifdef CONFIG_PM
  710 +static int mpc_i2c_suspend(struct device *dev)
  711 +{
  712 + struct mpc_i2c *i2c = dev_get_drvdata(dev);
  713 +
  714 + i2c->fdr = readb(i2c->base + MPC_I2C_FDR);
  715 + i2c->dfsrr = readb(i2c->base + MPC_I2C_DFSRR);
  716 +
  717 + return 0;
  718 +}
  719 +
  720 +static int mpc_i2c_resume(struct device *dev)
  721 +{
  722 + struct mpc_i2c *i2c = dev_get_drvdata(dev);
  723 +
  724 + writeb(i2c->fdr, i2c->base + MPC_I2C_FDR);
  725 + writeb(i2c->dfsrr, i2c->base + MPC_I2C_DFSRR);
  726 +
  727 + return 0;
  728 +}
  729 +
  730 +SIMPLE_DEV_PM_OPS(mpc_i2c_pm_ops, mpc_i2c_suspend, mpc_i2c_resume);
  731 +#endif
  732 +
706 733 static struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = {
707 734 .setup = mpc_i2c_setup_512x,
708 735 };
... ... @@ -747,6 +774,9 @@
747 774 .owner = THIS_MODULE,
748 775 .name = DRV_NAME,
749 776 .of_match_table = mpc_i2c_of_match,
  777 +#ifdef CONFIG_PM
  778 + .pm = &mpc_i2c_pm_ops,
  779 +#endif
750 780 },
751 781 };
752 782