diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-08-26 05:40:50 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-09-09 11:32:52 -0400 |
commit | e7d48fa2b5fbc7f74bb7ef4a8d7e080b0e831ef0 (patch) | |
tree | c90aeb47ebd226beb030cb655a55cf429039063d /drivers/i2c/busses/i2c-pxa.c | |
parent | 387fa6a5eca021ed5bef5454413b7cdfda74ba41 (diff) |
[I2C] pxa: provide late suspend and early resume hooks
Properly hook the I2C driver into the PM code; the previous fix for
this (ece5f7b3c4fde70a1ae4add7372ebca5c90bc34d) worked around the
platform where I2C is required to be available early during resume.
It has been found to be sufficient to use the early resume hook for
this function, so the original hack can die. Leave the hack in
place for the PIO transfer handler though.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/i2c/busses/i2c-pxa.c')
-rw-r--r-- | drivers/i2c/busses/i2c-pxa.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 57fbffd1ccc0..518b57c795c8 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -909,12 +909,6 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num | |||
909 | struct pxa_i2c *i2c = adap->algo_data; | 909 | struct pxa_i2c *i2c = adap->algo_data; |
910 | int ret, i; | 910 | int ret, i; |
911 | 911 | ||
912 | /* If the I2C controller is disabled we need to reset it (probably due | ||
913 | to a suspend/resume destroying state). We do this here as we can then | ||
914 | avoid worrying about resuming the controller before its users. */ | ||
915 | if (!(readl(_ICR(i2c)) & ICR_IUE)) | ||
916 | i2c_pxa_reset(i2c); | ||
917 | |||
918 | for (i = adap->retries; i >= 0; i--) { | 912 | for (i = adap->retries; i >= 0; i--) { |
919 | ret = i2c_pxa_do_xfer(i2c, msgs, num); | 913 | ret = i2c_pxa_do_xfer(i2c, msgs, num); |
920 | if (ret != I2C_RETRY) | 914 | if (ret != I2C_RETRY) |
@@ -1085,9 +1079,33 @@ static int __exit i2c_pxa_remove(struct platform_device *dev) | |||
1085 | return 0; | 1079 | return 0; |
1086 | } | 1080 | } |
1087 | 1081 | ||
1082 | #ifdef CONFIG_PM | ||
1083 | static int i2c_pxa_suspend_late(struct platform_device *dev, pm_message_t state) | ||
1084 | { | ||
1085 | struct pxa_i2c *i2c = platform_get_drvdata(dev); | ||
1086 | clk_disable(i2c->clk); | ||
1087 | return 0; | ||
1088 | } | ||
1089 | |||
1090 | static int i2c_pxa_resume_early(struct platform_device *dev) | ||
1091 | { | ||
1092 | struct pxa_i2c *i2c = platform_get_drvdata(dev); | ||
1093 | |||
1094 | clk_enable(i2c->clk); | ||
1095 | i2c_pxa_reset(i2c); | ||
1096 | |||
1097 | return 0; | ||
1098 | } | ||
1099 | #else | ||
1100 | #define i2c_pxa_suspend_late NULL | ||
1101 | #define i2c_pxa_resume_early NULL | ||
1102 | #endif | ||
1103 | |||
1088 | static struct platform_driver i2c_pxa_driver = { | 1104 | static struct platform_driver i2c_pxa_driver = { |
1089 | .probe = i2c_pxa_probe, | 1105 | .probe = i2c_pxa_probe, |
1090 | .remove = __exit_p(i2c_pxa_remove), | 1106 | .remove = __exit_p(i2c_pxa_remove), |
1107 | .suspend_late = i2c_pxa_suspend_late, | ||
1108 | .resume_early = i2c_pxa_resume_early, | ||
1091 | .driver = { | 1109 | .driver = { |
1092 | .name = "pxa2xx-i2c", | 1110 | .name = "pxa2xx-i2c", |
1093 | .owner = THIS_MODULE, | 1111 | .owner = THIS_MODULE, |