aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorThomas Kavanagh <tkavanagh@juniper.net>2012-09-20 23:20:46 -0400
committerWolfram Sang <w.sang@pengutronix.de>2012-10-06 07:14:36 -0400
commita76e7c6821b5dddf69db9d76ec282819545f5b73 (patch)
treeb86ced7ed1c3187cf1757e0f4b5acd68b423d8a4 /drivers/i2c
parent0c25aefa35c2fb5592895615f77d9f6fa36a849d (diff)
i2c: algo: pca: Fix chip reset function for PCA9665
The parameter passed to pca9665_reset is adap->data (which is bus driver specific), not i2c_algp_pca_data *adap. pca9665_reset expects it to be i2c_algp_pca_data *adap. All other wrappers from the algo call back to the bus driver, which knows to handle its custom data. Only pca9665_reset resides inside the algorithm code and does not know how to handle a custom data structure. This can result in a kernel crash. Fix by re-factoring pca_reset() from a macro to a function handling chip specific code, and only call adap->reset_chip() if the chip is not PCA9665. Signed-off-by: Thomas Kavanagh <tkavanagh@juniper.net> Signed-off-by: Guenter Roeck <groeck@juniper.net> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index 73133b1063f0..07ccbef6cc14 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -46,14 +46,19 @@ static int i2c_debug;
46#define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val) 46#define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val)
47#define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON) 47#define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON)
48#define pca_wait(adap) adap->wait_for_completion(adap->data) 48#define pca_wait(adap) adap->wait_for_completion(adap->data)
49#define pca_reset(adap) adap->reset_chip(adap->data)
50 49
51static void pca9665_reset(void *pd) 50static void pca_reset(struct i2c_algo_pca_data *adap)
52{ 51{
53 struct i2c_algo_pca_data *adap = pd; 52 if (adap->chip == I2C_PCA_CHIP_9665) {
54 pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IPRESET); 53 /* Ignore the reset function from the module,
55 pca_outw(adap, I2C_PCA_IND, 0xA5); 54 * we can use the parallel bus reset.
56 pca_outw(adap, I2C_PCA_IND, 0x5A); 55 */
56 pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IPRESET);
57 pca_outw(adap, I2C_PCA_IND, 0xA5);
58 pca_outw(adap, I2C_PCA_IND, 0x5A);
59 } else {
60 adap->reset_chip(adap->data);
61 }
57} 62}
58 63
59/* 64/*
@@ -378,11 +383,12 @@ static unsigned int pca_probe_chip(struct i2c_adapter *adap)
378 pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IADR); 383 pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IADR);
379 if (pca_inw(pca_data, I2C_PCA_IND) == 0xAA) { 384 if (pca_inw(pca_data, I2C_PCA_IND) == 0xAA) {
380 printk(KERN_INFO "%s: PCA9665 detected.\n", adap->name); 385 printk(KERN_INFO "%s: PCA9665 detected.\n", adap->name);
381 return I2C_PCA_CHIP_9665; 386 pca_data->chip = I2C_PCA_CHIP_9665;
382 } else { 387 } else {
383 printk(KERN_INFO "%s: PCA9564 detected.\n", adap->name); 388 printk(KERN_INFO "%s: PCA9564 detected.\n", adap->name);
384 return I2C_PCA_CHIP_9564; 389 pca_data->chip = I2C_PCA_CHIP_9564;
385 } 390 }
391 return pca_data->chip;
386} 392}
387 393
388static int pca_init(struct i2c_adapter *adap) 394static int pca_init(struct i2c_adapter *adap)
@@ -456,11 +462,6 @@ static int pca_init(struct i2c_adapter *adap)
456 */ 462 */
457 int raise_fall_time; 463 int raise_fall_time;
458 464
459 /* Ignore the reset function from the module,
460 * we can use the parallel bus reset
461 */
462 pca_data->reset_chip = pca9665_reset;
463
464 if (pca_data->i2c_clock > 1265800) { 465 if (pca_data->i2c_clock > 1265800) {
465 printk(KERN_WARNING "%s: I2C clock speed too high." 466 printk(KERN_WARNING "%s: I2C clock speed too high."
466 " Using 1265.8kHz.\n", adap->name); 467 " Using 1265.8kHz.\n", adap->name);