diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-pxa.c | 55 |
1 files changed, 39 insertions, 16 deletions
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 44d838410f15..8b38ed0379d5 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -60,19 +60,21 @@ struct pxa_i2c { | |||
60 | u32 icrlog[32]; | 60 | u32 icrlog[32]; |
61 | 61 | ||
62 | void __iomem *reg_base; | 62 | void __iomem *reg_base; |
63 | unsigned int reg_shift; | ||
63 | 64 | ||
64 | unsigned long iobase; | 65 | unsigned long iobase; |
65 | unsigned long iosize; | 66 | unsigned long iosize; |
66 | 67 | ||
67 | int irq; | 68 | int irq; |
68 | int use_pio; | 69 | unsigned int use_pio :1; |
70 | unsigned int fast_mode :1; | ||
69 | }; | 71 | }; |
70 | 72 | ||
71 | #define _IBMR(i2c) ((i2c)->reg_base + 0) | 73 | #define _IBMR(i2c) ((i2c)->reg_base + (0x0 << (i2c)->reg_shift)) |
72 | #define _IDBR(i2c) ((i2c)->reg_base + 8) | 74 | #define _IDBR(i2c) ((i2c)->reg_base + (0x4 << (i2c)->reg_shift)) |
73 | #define _ICR(i2c) ((i2c)->reg_base + 0x10) | 75 | #define _ICR(i2c) ((i2c)->reg_base + (0x8 << (i2c)->reg_shift)) |
74 | #define _ISR(i2c) ((i2c)->reg_base + 0x18) | 76 | #define _ISR(i2c) ((i2c)->reg_base + (0xc << (i2c)->reg_shift)) |
75 | #define _ISAR(i2c) ((i2c)->reg_base + 0x20) | 77 | #define _ISAR(i2c) ((i2c)->reg_base + (0x10 << (i2c)->reg_shift)) |
76 | 78 | ||
77 | /* | 79 | /* |
78 | * I2C Slave mode address | 80 | * I2C Slave mode address |
@@ -188,14 +190,14 @@ static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c) | |||
188 | 190 | ||
189 | static void i2c_pxa_abort(struct pxa_i2c *i2c) | 191 | static void i2c_pxa_abort(struct pxa_i2c *i2c) |
190 | { | 192 | { |
191 | unsigned long timeout = jiffies + HZ/4; | 193 | int i = 250; |
192 | 194 | ||
193 | if (i2c_pxa_is_slavemode(i2c)) { | 195 | if (i2c_pxa_is_slavemode(i2c)) { |
194 | dev_dbg(&i2c->adap.dev, "%s: called in slave mode\n", __func__); | 196 | dev_dbg(&i2c->adap.dev, "%s: called in slave mode\n", __func__); |
195 | return; | 197 | return; |
196 | } | 198 | } |
197 | 199 | ||
198 | while (time_before(jiffies, timeout) && (readl(_IBMR(i2c)) & 0x1) == 0) { | 200 | while ((i > 0) && (readl(_IBMR(i2c)) & 0x1) == 0) { |
199 | unsigned long icr = readl(_ICR(i2c)); | 201 | unsigned long icr = readl(_ICR(i2c)); |
200 | 202 | ||
201 | icr &= ~ICR_START; | 203 | icr &= ~ICR_START; |
@@ -205,7 +207,8 @@ static void i2c_pxa_abort(struct pxa_i2c *i2c) | |||
205 | 207 | ||
206 | show_state(i2c); | 208 | show_state(i2c); |
207 | 209 | ||
208 | msleep(1); | 210 | mdelay(1); |
211 | i --; | ||
209 | } | 212 | } |
210 | 213 | ||
211 | writel(readl(_ICR(i2c)) & ~(ICR_MA | ICR_START | ICR_STOP), | 214 | writel(readl(_ICR(i2c)) & ~(ICR_MA | ICR_START | ICR_STOP), |
@@ -364,7 +367,7 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c) | |||
364 | writel(i2c->slave_addr, _ISAR(i2c)); | 367 | writel(i2c->slave_addr, _ISAR(i2c)); |
365 | 368 | ||
366 | /* set control register values */ | 369 | /* set control register values */ |
367 | writel(I2C_ICR_INIT, _ICR(i2c)); | 370 | writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c)); |
368 | 371 | ||
369 | #ifdef CONFIG_I2C_PXA_SLAVE | 372 | #ifdef CONFIG_I2C_PXA_SLAVE |
370 | dev_info(&i2c->adap.dev, "Enabling slave mode\n"); | 373 | dev_info(&i2c->adap.dev, "Enabling slave mode\n"); |
@@ -907,12 +910,6 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num | |||
907 | struct pxa_i2c *i2c = adap->algo_data; | 910 | struct pxa_i2c *i2c = adap->algo_data; |
908 | int ret, i; | 911 | int ret, i; |
909 | 912 | ||
910 | /* If the I2C controller is disabled we need to reset it (probably due | ||
911 | to a suspend/resume destroying state). We do this here as we can then | ||
912 | avoid worrying about resuming the controller before its users. */ | ||
913 | if (!(readl(_ICR(i2c)) & ICR_IUE)) | ||
914 | i2c_pxa_reset(i2c); | ||
915 | |||
916 | for (i = adap->retries; i >= 0; i--) { | 913 | for (i = adap->retries; i >= 0; i--) { |
917 | ret = i2c_pxa_do_xfer(i2c, msgs, num); | 914 | ret = i2c_pxa_do_xfer(i2c, msgs, num); |
918 | if (ret != I2C_RETRY) | 915 | if (ret != I2C_RETRY) |
@@ -993,6 +990,7 @@ static int i2c_pxa_probe(struct platform_device *dev) | |||
993 | ret = -EIO; | 990 | ret = -EIO; |
994 | goto eremap; | 991 | goto eremap; |
995 | } | 992 | } |
993 | i2c->reg_shift = (cpu_is_pxa3xx() && (dev->id == 1)) ? 0 : 1; | ||
996 | 994 | ||
997 | i2c->iobase = res->start; | 995 | i2c->iobase = res->start; |
998 | i2c->iosize = res_len(res); | 996 | i2c->iosize = res_len(res); |
@@ -1013,6 +1011,7 @@ static int i2c_pxa_probe(struct platform_device *dev) | |||
1013 | if (plat) { | 1011 | if (plat) { |
1014 | i2c->adap.class = plat->class; | 1012 | i2c->adap.class = plat->class; |
1015 | i2c->use_pio = plat->use_pio; | 1013 | i2c->use_pio = plat->use_pio; |
1014 | i2c->fast_mode = plat->fast_mode; | ||
1016 | } | 1015 | } |
1017 | 1016 | ||
1018 | if (i2c->use_pio) { | 1017 | if (i2c->use_pio) { |
@@ -1082,9 +1081,33 @@ static int __exit i2c_pxa_remove(struct platform_device *dev) | |||
1082 | return 0; | 1081 | return 0; |
1083 | } | 1082 | } |
1084 | 1083 | ||
1084 | #ifdef CONFIG_PM | ||
1085 | static int i2c_pxa_suspend_late(struct platform_device *dev, pm_message_t state) | ||
1086 | { | ||
1087 | struct pxa_i2c *i2c = platform_get_drvdata(dev); | ||
1088 | clk_disable(i2c->clk); | ||
1089 | return 0; | ||
1090 | } | ||
1091 | |||
1092 | static int i2c_pxa_resume_early(struct platform_device *dev) | ||
1093 | { | ||
1094 | struct pxa_i2c *i2c = platform_get_drvdata(dev); | ||
1095 | |||
1096 | clk_enable(i2c->clk); | ||
1097 | i2c_pxa_reset(i2c); | ||
1098 | |||
1099 | return 0; | ||
1100 | } | ||
1101 | #else | ||
1102 | #define i2c_pxa_suspend_late NULL | ||
1103 | #define i2c_pxa_resume_early NULL | ||
1104 | #endif | ||
1105 | |||
1085 | static struct platform_driver i2c_pxa_driver = { | 1106 | static struct platform_driver i2c_pxa_driver = { |
1086 | .probe = i2c_pxa_probe, | 1107 | .probe = i2c_pxa_probe, |
1087 | .remove = __exit_p(i2c_pxa_remove), | 1108 | .remove = __exit_p(i2c_pxa_remove), |
1109 | .suspend_late = i2c_pxa_suspend_late, | ||
1110 | .resume_early = i2c_pxa_resume_early, | ||
1088 | .driver = { | 1111 | .driver = { |
1089 | .name = "pxa2xx-i2c", | 1112 | .name = "pxa2xx-i2c", |
1090 | .owner = THIS_MODULE, | 1113 | .owner = THIS_MODULE, |