diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-pca-platform.c')
-rw-r--r-- | drivers/i2c/busses/i2c-pca-platform.c | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 6bb15ad0a6b6..7b23891b7d59 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/jiffies.h> | ||
18 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
19 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
@@ -81,24 +82,23 @@ static void i2c_pca_pf_writebyte32(void *pd, int reg, int val) | |||
81 | static int i2c_pca_pf_waitforcompletion(void *pd) | 82 | static int i2c_pca_pf_waitforcompletion(void *pd) |
82 | { | 83 | { |
83 | struct i2c_pca_pf_data *i2c = pd; | 84 | struct i2c_pca_pf_data *i2c = pd; |
84 | int ret = 0; | 85 | long ret = ~0; |
86 | unsigned long timeout; | ||
85 | 87 | ||
86 | if (i2c->irq) { | 88 | if (i2c->irq) { |
87 | ret = wait_event_interruptible(i2c->wait, | 89 | ret = wait_event_interruptible_timeout(i2c->wait, |
88 | i2c->algo_data.read_byte(i2c, I2C_PCA_CON) | 90 | i2c->algo_data.read_byte(i2c, I2C_PCA_CON) |
89 | & I2C_PCA_CON_SI); | 91 | & I2C_PCA_CON_SI, i2c->adap.timeout); |
90 | } else { | 92 | } else { |
91 | /* | 93 | /* Do polling */ |
92 | * Do polling... | 94 | timeout = jiffies + i2c->adap.timeout; |
93 | * XXX: Could get stuck in extreme cases! | 95 | while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) |
94 | * Maybe add timeout, but using irqs is preferred anyhow. | ||
95 | */ | ||
96 | while ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) | ||
97 | & I2C_PCA_CON_SI) == 0) | 96 | & I2C_PCA_CON_SI) == 0) |
97 | && (ret = time_before(jiffies, timeout))) | ||
98 | udelay(100); | 98 | udelay(100); |
99 | } | 99 | } |
100 | 100 | ||
101 | return ret; | 101 | return ret > 0; |
102 | } | 102 | } |
103 | 103 | ||
104 | static void i2c_pca_pf_dummyreset(void *pd) | 104 | static void i2c_pca_pf_dummyreset(void *pd) |
@@ -172,14 +172,25 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) | |||
172 | 172 | ||
173 | i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0; | 173 | i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0; |
174 | i2c->adap.owner = THIS_MODULE; | 174 | i2c->adap.owner = THIS_MODULE; |
175 | snprintf(i2c->adap.name, sizeof(i2c->adap.name), "PCA9564 at 0x%08lx", | 175 | snprintf(i2c->adap.name, sizeof(i2c->adap.name), |
176 | (unsigned long) res->start); | 176 | "PCA9564/PCA9665 at 0x%08lx", |
177 | (unsigned long) res->start); | ||
177 | i2c->adap.algo_data = &i2c->algo_data; | 178 | i2c->adap.algo_data = &i2c->algo_data; |
178 | i2c->adap.dev.parent = &pdev->dev; | 179 | i2c->adap.dev.parent = &pdev->dev; |
179 | i2c->adap.timeout = platform_data->timeout; | ||
180 | 180 | ||
181 | i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed; | 181 | if (platform_data) { |
182 | i2c->adap.timeout = platform_data->timeout; | ||
183 | i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed; | ||
184 | i2c->gpio = platform_data->gpio; | ||
185 | } else { | ||
186 | i2c->adap.timeout = HZ; | ||
187 | i2c->algo_data.i2c_clock = 59000; | ||
188 | i2c->gpio = -1; | ||
189 | } | ||
190 | |||
182 | i2c->algo_data.data = i2c; | 191 | i2c->algo_data.data = i2c; |
192 | i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion; | ||
193 | i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset; | ||
183 | 194 | ||
184 | switch (res->flags & IORESOURCE_MEM_TYPE_MASK) { | 195 | switch (res->flags & IORESOURCE_MEM_TYPE_MASK) { |
185 | case IORESOURCE_MEM_32BIT: | 196 | case IORESOURCE_MEM_32BIT: |
@@ -197,11 +208,6 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) | |||
197 | break; | 208 | break; |
198 | } | 209 | } |
199 | 210 | ||
200 | i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion; | ||
201 | |||
202 | i2c->gpio = platform_data->gpio; | ||
203 | i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset; | ||
204 | |||
205 | /* Use gpio_is_valid() when in mainline */ | 211 | /* Use gpio_is_valid() when in mainline */ |
206 | if (i2c->gpio > -1) { | 212 | if (i2c->gpio > -1) { |
207 | ret = gpio_request(i2c->gpio, i2c->adap.name); | 213 | ret = gpio_request(i2c->gpio, i2c->adap.name); |
@@ -246,7 +252,7 @@ e_remap: | |||
246 | e_alloc: | 252 | e_alloc: |
247 | release_mem_region(res->start, res_len(res)); | 253 | release_mem_region(res->start, res_len(res)); |
248 | e_print: | 254 | e_print: |
249 | printk(KERN_ERR "Registering PCA9564 FAILED! (%d)\n", ret); | 255 | printk(KERN_ERR "Registering PCA9564/PCA9665 FAILED! (%d)\n", ret); |
250 | return ret; | 256 | return ret; |
251 | } | 257 | } |
252 | 258 | ||
@@ -290,7 +296,7 @@ static void __exit i2c_pca_pf_exit(void) | |||
290 | } | 296 | } |
291 | 297 | ||
292 | MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); | 298 | MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); |
293 | MODULE_DESCRIPTION("I2C-PCA9564 platform driver"); | 299 | MODULE_DESCRIPTION("I2C-PCA9564/PCA9665 platform driver"); |
294 | MODULE_LICENSE("GPL"); | 300 | MODULE_LICENSE("GPL"); |
295 | 301 | ||
296 | module_init(i2c_pca_pf_init); | 302 | module_init(i2c_pca_pf_init); |