PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c
Hi Wolfram,
Here is the patch against 2.6.26.5.
Please tell me if I did something very wrong ;)
Regards,
Marco
drivers/i2c/algos/i2c-algo-pca.c +128 -12
@@ -43,6 +43,14 @@#define pca_wait (adap) adap->wait_for_completion(adap->data)#define pca_reset (adap) adap->reset_chip(adap->data) +static void pca9665_reset (void *pd) +{ +struct i2c_algo_pca_data *adap = pd; +pca_outw (adap,I2C_PCA_INDPTR ,I2C_PCA_IPRESET ); +pca_outw (adap,I2C_PCA_IND ,0xA5 ); +pca_outw (adap,I2C_PCA_IND ,0x5A ); +} +/* * Generate a start condition on the i2c bus. *
@@ -332,24 +340,132 @@static int pca_init (struct i2c_adapter *adap) { -static int freqs[] = {330 ,288 ,217 ,146 ,88 ,59 ,44 ,36 }; -int clock;struct i2c_algo_pca_data *pca_data = adap->algo_data; -if (pca_data->i2c_clock >7 ) { -printk (KERN_WARNING "%s: Invalid I2C clock speed selected. Trying default.\n" , - adap->name); - pca_data->i2c_clock = I2C_PCA_CON_59kHz; + adap->algo = &pca_algo; + +if (pca_data->i2c_chip_type !=I2C_PCA_CHIP_9564 && pca_data->i2c_chip_type !=I2C_PCA_CHIP_9665 ) { +printk (KERN_WARNING "%s: Invalid chip selected. Assuming PCA9564.\n" , + adap->name); + pca_data->i2c_chip_type =I2C_PCA_CHIP_9564 ; } - adap->algo = &pca_algo; +if (pca_data->i2c_chip_type ==I2C_PCA_CHIP_9564 ) { +static int freqs[] = {330 ,288 ,217 ,146 ,88 ,59 ,44 ,36 }; +int clock; + +if (pca_data->i2c_clock >7 ) { +switch (pca_data->i2c_clock) { +case 330000 : + pca_data->i2c_clock = I2C_PCA_CON_330kHz; +break ; +case 288000 : + pca_data->i2c_clock = I2C_PCA_CON_288kHz; +break ; +case 217000 : + pca_data->i2c_clock = I2C_PCA_CON_217kHz; +break ; +case 146000 : + pca_data->i2c_clock = I2C_PCA_CON_146kHz; +break ; +case 88000 : + pca_data->i2c_clock = I2C_PCA_CON_88kHz; +break ; +case 59000 : + pca_data->i2c_clock = I2C_PCA_CON_59kHz; +break ; +case 44000 : + pca_data->i2c_clock = I2C_PCA_CON_44kHz; +break ; +case 36000 : + pca_data->i2c_clock = I2C_PCA_CON_36kHz; +break ; +default : +printk (KERN_WARNING "%s: Invalid I2C clock speed selected. Trying default.\n" , + adap->name); + pca_data->i2c_clock = I2C_PCA_CON_59kHz; + } + }else { +printk (KERN_WARNING "%s: Choosing the clock frequency based on index is deprecated. Use the nominal frequency.\n" , + adap->name); + } + +pca_reset (pca_data); + + clock =pca_clock (pca_data); +DEB1 (KERN_INFO "%s: Clock frequency is %dkHz\n" , adap->name, freqs[clock]); + +pca_set_con (pca_data,I2C_PCA_CON_ENSIO | clock); + }else { +int clock; +int mode; +int tlow, thigh; +int minTLow, minTHi; +int tRaiseFall; + +struct i2c_algo_pca_data *pca_data = adap->algo_data; + +/* Ignore the reset function from the module, we can use the parallel bus reset */ + pca_data->reset_chip = pca9665_reset; + +if (pca_data->i2c_clock >1265800 ) { +printk (KERN_WARNING "%s: I2C clock speed too high. Using 1265.8kHz.\n" , + adap->name); + pca_data->i2c_clock =1265800 ; + } + +if (pca_data->i2c_clock <60300 ) { +printk (KERN_WARNING "%s: I2C clock speed too low. Using 60.3kHz.\n" , + adap->name); + pca_data->i2c_clock =60300 ; + } + + clock =pca_clock (pca_data)/100 ;/* Hz*100 */ + + +if (pca_data->i2c_clock >10000 ) { + mode =I2C_PCA_MODE_TURBO ; + minTLow =14 ; + minTHi =5 ; + tRaiseFall =22 ;/* Raise 11e-8s, Fall 11e-8s */ + }else if (pca_data->i2c_clock >4000 ) { + mode =I2C_PCA_MODE_FASTP ; + minTLow =17 ; + minTHi =9 ; + tRaiseFall =22 ;/* Raise 11e-8s, Fall 11e-8s */ + }else if (pca_data->i2c_clock >1000 ) { + mode =I2C_PCA_MODE_FAST ; + minTLow =44 ; + minTHi =20 ; + tRaiseFall =58 ;/* Raise 29e-8s, Fall 29e-8s */ + }else { + mode =I2C_PCA_MODE_STD ; + minTLow =157 ; + minTHi =134 ; + tRaiseFall =127 ;/* Raise 29e-8s, Fall 98e-8s */ + } -pca_reset (pca_data); +if (clock <648 ) { + tlow =255 ; + thigh = (1000000 - clock*tRaiseFall)/(3 *clock)-tlow; + }else { + tlow = ((1000000 - clock*tRaiseFall)*minTLow)/(3 *clock*(minTHi+minTLow)); + thigh = tlow*minTHi/minTLow; + } + +pca_reset (pca_data); - clock =pca_clock (pca_data); -DEB1 (KERN_INFO "%s: Clock frequency is %dkHz\n" , adap->name, freqs[clock]); +DEB1 (KERN_INFO "%s: Clock frequency is %dHz\n" , adap->name, clock*100 ); -pca_set_con (pca_data,I2C_PCA_CON_ENSIO | clock); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_IMODE ); +pca_outw (pca_data,I2C_PCA_IND ,mode); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_ISCLL ); +pca_outw (pca_data,I2C_PCA_IND ,tlow); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_ISCLH ); +pca_outw (pca_data,I2C_PCA_IND ,thigh); + +pca_set_con (pca_data,I2C_PCA_CON_ENSIO ); + }udelay (500 );/* 500 us for oscilator to stabilise */ return 0 ;
@@ -384,7 +500,7 @@MODULE_AUTHOR ("Ian Campbell <[email protected]>, " "Wolfram Sang <[email protected]>" ); -MODULE_DESCRIPTION ("I2C-Bus PCA9564 algorithm" ); +MODULE_DESCRIPTION ("I2C-Bus PCA9564/PCA9665 algorithm" );MODULE_LICENSE ("GPL" );module_param (i2c_debug, int,0 );
drivers/i2c/busses/i2c-pca-isa.c +9 -3
@@ -42,6 +42,7 @@/* Data sheet recommends 59kHz for 100kHz operation due to variation * in the actual clock rate */ static int clock = I2C_PCA_CON_59kHz; +static int chip =I2C_PCA_CHIP_9564 ;static wait_queue_head_t pca_wait;
@@ -103,7 +104,7 @@ .owner = THIS_MODULE, .id = I2C_HW_A_ISA, .algo_data = &pca_isa_data, - .name = "PCA9564 ISA Adapter", + .name = "PCA9564/PCA9665 ISA Adapter", .timeout = 100, };
@@ -132,6 +133,7 @@ } } + pca_isa_data.i2c_chip_type = chip; pca_isa_data.i2c_clock = clock;if (i2c_pca_add_bus (&pca_isa_ops) <0 ) {dev_err (dev,"Failed to add i2c bus\n" );
@@ -182,7 +184,7 @@ }MODULE_AUTHOR ("Ian Campbell <[email protected]>" ); -MODULE_DESCRIPTION ("ISA base PCA9564 driver" ); +MODULE_DESCRIPTION ("ISA base PCA9564/PCA9665 driver" );MODULE_LICENSE ("GPL" );module_param (base, ulong,0 );
@@ -191,7 +193,11 @@module_param (irq, int,0 );MODULE_PARM_DESC (irq,"IRQ" );module_param (clock, int,0 ); -MODULE_PARM_DESC (clock,"Clock rate as described in table 1 of PCA9564 datasheet" ); +MODULE_PARM_DESC (clock,"Clock rate in hertz.\n\t\tFor PCA9564: 330000,288000,217000,146000,88000,59000,44000,36000\n" +"\t\tFor PCA9665:\tStandard: 60300 - 100099\n\t\t\t\tFast: 100100 - 400099\n\t\t\t\tFast+: 400100 - 10000099\n" +"\t\t\t\tTurbo: Up to 1265800" ); +module_param (chip, int,0 ); +MODULE_PARM_DESC (chip,"Chip type: 0 = PCA9564; 1 - PCA9665" );module_init (pca_isa_init);module_exit (pca_isa_exit);
drivers/i2c/busses/i2c-pca-platform.c +3 -3
@@ -172,7 +172,7 @@ i2c->adap.nr = pdev->id >=0 ? pdev->id :0 ; i2c->adap.owner =THIS_MODULE ; -snprintf (i2c->adap.name,sizeof (i2c->adap.name),"PCA9564 at 0x%08lx" , +snprintf (i2c->adap.name,sizeof (i2c->adap.name),"PCA9564/PCA9665 at 0x%08lx" , (unsigned long ) res->start); i2c->adap.algo_data = &i2c->algo_data; i2c->adap.dev.parent = &pdev->dev;
@@ -246,7 +246,7 @@ e_alloc:release_mem_region (res->start,res_len (res)); e_print: -printk (KERN_ERR "Registering PCA9564 FAILED! (%d)\n" , ret); +printk (KERN_ERR "Registering PCA9564/PCA9665 FAILED! (%d)\n" , ret);return ret; }
@@ -290,7 +290,7 @@ }MODULE_AUTHOR ("Wolfram Sang <[email protected]>" ); -MODULE_DESCRIPTION ("I2C-PCA9564 platform driver" ); +MODULE_DESCRIPTION ("I2C-PCA9564/PCA9665 platform driver" );MODULE_LICENSE ("GPL" );module_init (i2c_pca_pf_init);
drivers/i2c/busses/Kconfig +2 -2
@@ -630,7 +630,7 @@ will be called i2c-voodoo3. config I2C_PCA_ISA - tristate "PCA9564 on an ISA bus" + tristate "PCA9564/PCA9665 on an ISA bus" depends on ISA select I2C_ALGOPCA default n
@@ -647,7 +647,7 @@ time). If unsure, say N. config I2C_PCA_PLATFORM - tristate "PCA9564 as platform device" + tristate "PCA9564/PCA9665 as platform device" select I2C_ALGOPCA default n help
include/linux/i2c-algo-pca.h +29 -2
@@ -1,7 +1,11 @@#ifndef _LINUX_I2C_ALGO_PCA_H#define _LINUX_I2C_ALGO_PCA_H -/* Clock speeds for the bus */ +/* Chips known to the pca algo */ +#define I2C_PCA_CHIP_9564 0x00 +#define I2C_PCA_CHIP_9665 0x01 + +/* Clock speeds for the bus for PCA9564*/ #define I2C_PCA_CON_330kHz 0x00#define I2C_PCA_CON_288kHz 0x01#define I2C_PCA_CON_217kHz 0x02
@@ -18,6 +22,26 @@#define I2C_PCA_ADR 0x02/* OWN ADR Read/Write */ #define I2C_PCA_CON 0x03/* CONTROL Read/Write */ +/* PCA9665 registers */ +#define I2C_PCA_INDPTR 0x00/* INDIRECT Pointer Write Only */ +#define I2C_PCA_IND 0x02/* INDIRECT Read/Write */ + +/* PCA9665 indirect registers */ +#define I2C_PCA_ICOUNT 0x00/* Byte Count for buffered mode */ +#define I2C_PCA_IADR 0x01/* OWN ADR */ +#define I2C_PCA_ISCLL 0x02/* SCL LOW period */ +#define I2C_PCA_ISCLH 0x03/* SCL HIGH period */ +#define I2C_PCA_ITO 0x04/* TIMEOUT */ +#define I2C_PCA_IPRESET 0x05/* Parallel bus reset */ +#define I2C_PCA_IMODE 0x06/* I2C Bus mode */ + +/* PCA9665 I2C bus mode */ +#define I2C_PCA_MODE_STD 0x00/* Standard mode */ +#define I2C_PCA_MODE_FAST 0x01/* Fast mode */ +#define I2C_PCA_MODE_FASTP 0x02/* Fast Plus mode */ +#define I2C_PCA_MODE_TURBO 0x03/* Turbo mode */ + +#define I2C_PCA_CON_AA 0x80/* Assert Acknowledge */ #define I2C_PCA_CON_ENSIO 0x40/* Enable */ #define I2C_PCA_CON_STA 0x20/* Start */
@@ -31,8 +55,11 @@int (*read_byte) (void *data,int reg);int (*wait_for_completion) (void *data);void (*reset_chip) (void *data); -/* i2c_clock values are defined in linux/i2c-algo-pca.h */ +/* For PCA9964, use one of the predefined frequencies: +* 330000, 288000, 217000, 146000, 88000, 59000, 44000, 36000 +* For PCA9665, use the frequency you want here. */ unsigned int i2c_clock; +unsigned int i2c_chip_type; };int i2c_pca_add_bus (struct i2c_adapter *);
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
Quoted 3 lines
Here is the patch against 2.6.26.5.
Please tell me if I did something very wrong ;)
I'm just about to leave the office, so just the first notes. Will have a deeper look later this evening...
drivers/i2c/algos/i2c-algo-pca.c line 51
Quoted 6 lines
drivers/i2c/algos/i2c-algo-pca.c +6
-0+static void pca9665_reset (void *pd) +{ +struct i2c_algo_pca_data *adap = pd; +pca_outw (adap,I2C_PCA_INDPTR ,I2C_PCA_IPRESET ); +pca_outw (adap,I2C_PCA_IND ,0xA5 ); +pca_outw (adap,I2C_PCA_IND ,0x5A );
CodingStyle issues (space after comma)...
drivers/i2c/algos/i2c-algo-pca.c line 347
Quoted 1 line
drivers/i2c/algos/i2c-algo-pca.c +1
-0+if (pca_data->i2c_chip_type !=I2C_PCA_CHIP_9564 && pca_data->i2c_chip_type !=I2C_PCA_CHIP_9665 ) {
Line is longer than 80 chars. Please be sure to have run checkpatch.pl before submitting.
Review
Quoted 1 line
(quoted diff) +1
-0+
Trailing whitespaces here (and in some other places).
drivers/i2c/algos/i2c-algo-pca.c line 403
Quoted 1 line
drivers/i2c/algos/i2c-algo-pca.c +1
-0+int minTLow, minTHi;
This style of naming is at least unusual in kernel. Maybe min_tlow?
So much for now, more later...
Wolfram
Signature · 2 lines
Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
Hi Wolfram.
Quoted 3 lines · Wolfram Sang
I'm just about to leave the office, so just the first notes. Will have a deeper look later this evening...
I did the fixes you pointed out and run the script. This is the result.
Regards,
Marco
drivers/i2c/algos/i2c-algo-pca.c +136 -12
@@ -43,6 +43,14 @@#define pca_wait (adap) adap->wait_for_completion(adap->data)#define pca_reset (adap) adap->reset_chip(adap->data) +static void pca9665_reset (void *pd) +{ +struct i2c_algo_pca_data *adap = pd; +pca_outw (adap,I2C_PCA_INDPTR ,I2C_PCA_IPRESET ); +pca_outw (adap,I2C_PCA_IND ,0xA5 ); +pca_outw (adap,I2C_PCA_IND ,0x5A ); +} +/* * Generate a start condition on the i2c bus. *
@@ -332,24 +340,140 @@static int pca_init (struct i2c_adapter *adap) { -static int freqs[] = {330 ,288 ,217 ,146 ,88 ,59 ,44 ,36 }; -int clock;struct i2c_algo_pca_data *pca_data = adap->algo_data; -if (pca_data->i2c_clock >7 ) { -printk (KERN_WARNING "%s: Invalid I2C clock speed selected. Trying default.\n" , - adap->name); - pca_data->i2c_clock = I2C_PCA_CON_59kHz; + adap->algo = &pca_algo; + +if (pca_data->i2c_chip_type >I2C_PCA_CHIP_9665 ) { +printk (KERN_WARNING "%s: Invalid chip selected." +"Assuming PCA9564.\n" , adap->name); + pca_data->i2c_chip_type =I2C_PCA_CHIP_9564 ; } - adap->algo = &pca_algo; +if (pca_data->i2c_chip_type ==I2C_PCA_CHIP_9564 ) { +static int freqs[] = {330 ,288 ,217 ,146 ,88 ,59 ,44 ,36 }; +int clock; + +if (pca_data->i2c_clock >7 ) { +switch (pca_data->i2c_clock) { +case 330000 : + pca_data->i2c_clock = I2C_PCA_CON_330kHz; +break ; +case 288000 : + pca_data->i2c_clock = I2C_PCA_CON_288kHz; +break ; +case 217000 : + pca_data->i2c_clock = I2C_PCA_CON_217kHz; +break ; +case 146000 : + pca_data->i2c_clock = I2C_PCA_CON_146kHz; +break ; +case 88000 : + pca_data->i2c_clock = I2C_PCA_CON_88kHz; +break ; +case 59000 : + pca_data->i2c_clock = I2C_PCA_CON_59kHz; +break ; +case 44000 : + pca_data->i2c_clock = I2C_PCA_CON_44kHz; +break ; +case 36000 : + pca_data->i2c_clock = I2C_PCA_CON_36kHz; +break ; +default : +printk (KERN_WARNING +"%s: Invalid I2C clock speed selected." +"Trying default.\n" , adap->name); + pca_data->i2c_clock = I2C_PCA_CON_59kHz; + } + }else { +printk (KERN_WARNING "%s: " +"Choosing the clock frequency based on " +"index is deprecated." +" Use the nominal frequency.\n" , adap->name); + } + +pca_reset (pca_data); + + clock =pca_clock (pca_data); +DEB1 (KERN_INFO "%s: Clock frequency is %dkHz\n" , + adap->name, freqs[clock]); + +pca_set_con (pca_data,I2C_PCA_CON_ENSIO | clock); + }else { +int clock; +int mode; +int tlow, thigh; +int min_tlow, min_thigh; +int raise_fall_time; + +struct i2c_algo_pca_data *pca_data = adap->algo_data; + +/* Ignore the reset function from the module, +* we can use the parallel bus reset +*/ + pca_data->reset_chip = pca9665_reset; + +if (pca_data->i2c_clock >1265800 ) { +printk (KERN_WARNING "%s: I2C clock speed too high." +" Using 1265.8kHz.\n" , adap->name); + pca_data->i2c_clock =1265800 ; + } + +if (pca_data->i2c_clock <60300 ) { +printk (KERN_WARNING "%s: I2C clock speed too low." +" Using 60.3kHz.\n" , adap->name); + pca_data->i2c_clock =60300 ; + } + + clock =pca_clock (pca_data)/100 ;/* Hz*100 */ -pca_reset (pca_data); - clock =pca_clock (pca_data); -DEB1 (KERN_INFO "%s: Clock frequency is %dkHz\n" , adap->name, freqs[clock]); +if (pca_data->i2c_clock >10000 ) { + mode =I2C_PCA_MODE_TURBO ; + min_tlow =14 ; + min_thigh =5 ; + raise_fall_time =22 ;/* Raise 11e-8s, Fall 11e-8s */ + }else if (pca_data->i2c_clock >4000 ) { + mode =I2C_PCA_MODE_FASTP ; + min_tlow =17 ; + min_thigh =9 ; + raise_fall_time =22 ;/* Raise 11e-8s, Fall 11e-8s */ + }else if (pca_data->i2c_clock >1000 ) { + mode =I2C_PCA_MODE_FAST ; + min_tlow =44 ; + min_thigh =20 ; + raise_fall_time =58 ;/* Raise 29e-8s, Fall 29e-8s */ + }else { + mode =I2C_PCA_MODE_STD ; + min_tlow =157 ; + min_thigh =134 ; + raise_fall_time =127 ;/* Raise 29e-8s, Fall 98e-8s */ + } + +if (clock <648 ) { + tlow =255 ; + thigh = (1000000 -clock*raise_fall_time)/(3 *clock)-tlow; + }else { + tlow = ((1000000 -clock*raise_fall_time)*min_tlow); + tlow /= (3 *clock*(min_thigh+min_tlow)); + thigh = tlow*min_thigh/min_tlow; + } + +pca_reset (pca_data); -pca_set_con (pca_data,I2C_PCA_CON_ENSIO | clock); +DEB1 (KERN_INFO +"%s: Clock frequency is %dHz\n" , adap->name, clock*100 ); + +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_IMODE ); +pca_outw (pca_data,I2C_PCA_IND , mode); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_ISCLL ); +pca_outw (pca_data,I2C_PCA_IND , tlow); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_ISCLH ); +pca_outw (pca_data,I2C_PCA_IND , thigh); + +pca_set_con (pca_data,I2C_PCA_CON_ENSIO ); + }udelay (500 );/* 500 us for oscilator to stabilise */ return 0 ;
@@ -384,7 +508,7 @@MODULE_AUTHOR ("Ian Campbell <[email protected]>, " "Wolfram Sang <[email protected]>" ); -MODULE_DESCRIPTION ("I2C-Bus PCA9564 algorithm" ); +MODULE_DESCRIPTION ("I2C-Bus PCA9564/PCA9665 algorithm" );MODULE_LICENSE ("GPL" );module_param (i2c_debug, int,0 );
drivers/i2c/busses/i2c-pca-isa.c +14 -4
@@ -41,7 +41,8 @@/* Data sheet recommends 59kHz for 100kHz operation due to variation * in the actual clock rate */ -static int clock = I2C_PCA_CON_59kHz; +static int clock =59000 ; +static int chip =I2C_PCA_CHIP_9564 ;static wait_queue_head_t pca_wait;
@@ -103,7 +104,7 @@ .owner = THIS_MODULE, .id = I2C_HW_A_ISA, .algo_data = &pca_isa_data, - .name = "PCA9564 ISA Adapter", + .name = "PCA9564/PCA9665 ISA Adapter", .timeout = 100, };
@@ -132,6 +133,7 @@ } } + pca_isa_data.i2c_chip_type = chip; pca_isa_data.i2c_clock = clock;if (i2c_pca_add_bus (&pca_isa_ops) <0 ) {dev_err (dev,"Failed to add i2c bus\n" );
@@ -182,7 +184,7 @@ }MODULE_AUTHOR ("Ian Campbell <[email protected]>" ); -MODULE_DESCRIPTION ("ISA base PCA9564 driver" ); +MODULE_DESCRIPTION ("ISA base PCA9564/PCA9665 driver" );MODULE_LICENSE ("GPL" );module_param (base, ulong,0 );
@@ -191,7 +193,15 @@module_param (irq, int,0 );MODULE_PARM_DESC (irq,"IRQ" );module_param (clock, int,0 ); -MODULE_PARM_DESC (clock,"Clock rate as described in table 1 of PCA9564 datasheet" ); +MODULE_PARM_DESC (clock,"Clock rate in hertz.\n\t\t" +"For PCA9564: 330000,288000,217000,146000," +"88000,59000,44000,36000\n" +"\t\tFor PCA9665:\tStandard: 60300 - 100099\n" +"\t\t\t\tFast: 100100 - 400099\n" +"\t\t\t\tFast+: 400100 - 10000099\n" +"\t\t\t\tTurbo: Up to 1265800" ); +module_param (chip, int,0 ); +MODULE_PARM_DESC (chip,"Chip type: 0 = PCA9564; 1 - PCA9665" );module_init (pca_isa_init);module_exit (pca_isa_exit);
drivers/i2c/busses/i2c-pca-platform.c +5 -4
@@ -172,8 +172,9 @@ i2c->adap.nr = pdev->id >=0 ? pdev->id :0 ; i2c->adap.owner =THIS_MODULE ; -snprintf (i2c->adap.name,sizeof (i2c->adap.name),"PCA9564 at 0x%08lx" , - (unsigned long ) res->start); +snprintf (i2c->adap.name,sizeof (i2c->adap.name), +"PCA9564/PCA9665 at 0x%08lx" , + (unsigned long ) res->start); i2c->adap.algo_data = &i2c->algo_data; i2c->adap.dev.parent = &pdev->dev; i2c->adap.timeout = platform_data->timeout;
@@ -246,7 +247,7 @@ e_alloc:release_mem_region (res->start,res_len (res)); e_print: -printk (KERN_ERR "Registering PCA9564 FAILED! (%d)\n" , ret); +printk (KERN_ERR "Registering PCA9564/PCA9665 FAILED! (%d)\n" , ret);return ret; }
@@ -290,7 +291,7 @@ }MODULE_AUTHOR ("Wolfram Sang <[email protected]>" ); -MODULE_DESCRIPTION ("I2C-PCA9564 platform driver" ); +MODULE_DESCRIPTION ("I2C-PCA9564/PCA9665 platform driver" );MODULE_LICENSE ("GPL" );module_init (i2c_pca_pf_init);
drivers/i2c/busses/Kconfig +2 -2
@@ -630,7 +630,7 @@ will be called i2c-voodoo3. config I2C_PCA_ISA - tristate "PCA9564 on an ISA bus" + tristate "PCA9564/PCA9665 on an ISA bus" depends on ISA select I2C_ALGOPCA default n
@@ -647,7 +647,7 @@ time). If unsure, say N. config I2C_PCA_PLATFORM - tristate "PCA9564 as platform device" + tristate "PCA9564/PCA9665 as platform device" select I2C_ALGOPCA default n help
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
Hi Marco,
Quoted 2 lines
I did the fixes you pointed out and run the script. This is the result.
Thanks. This patch is somehow missing the i2c-algo-pca.h changes.
drivers/i2c/algos/i2c-algo-pca.c line 347
Quoted 3 lines
drivers/i2c/algos/i2c-algo-pca.c +3
-0+ adap->algo = &pca_algo; + +if (pca_data->i2c_chip_type >I2C_PCA_CHIP_9665 ) {
I wonder if something like I2C_PCA_CHIP_MAXVAL could be useful here. Then, if another chip will be added, you just need changes in the .h file.
Quoted 30 lines
drivers/i2c/algos/i2c-algo-pca.c +27
-1+printk (KERN_WARNING "%s: Invalid chip selected." +"Assuming PCA9564.\n" , adap->name); + pca_data->i2c_chip_type =I2C_PCA_CHIP_9564 ; } - adap->algo = &pca_algo; +if (pca_data->i2c_chip_type ==I2C_PCA_CHIP_9564 ) { +static int freqs[] = {330 ,288 ,217 ,146 ,88 ,59 ,44 ,36 }; +int clock; + +if (pca_data->i2c_clock >7 ) { +switch (pca_data->i2c_clock) { +case 330000 : + pca_data->i2c_clock = I2C_PCA_CON_330kHz; +break ; +case 288000 : + pca_data->i2c_clock = I2C_PCA_CON_288kHz; +break ; +case 217000 : + pca_data->i2c_clock = I2C_PCA_CON_217kHz; +break ; +case 146000 : + pca_data->i2c_clock = I2C_PCA_CON_146kHz; +break ; +case 88000 : + pca_data->i2c_clock = I2C_PCA_CON_88kHz; +break ; +case 59000 : + pca_data->i2c_clock = I2C_PCA_CON_59kHz; +break ;
drivers/i2c/algos/i2c-algo-pca.c line 386
Quoted 10 lines
drivers/i2c/algos/i2c-algo-pca.c +10
-0+case 44000 : + pca_data->i2c_clock = I2C_PCA_CON_44kHz; +break ; +case 36000 : + pca_data->i2c_clock = I2C_PCA_CON_36kHz; +break ; +default : +printk (KERN_WARNING +"%s: Invalid I2C clock speed selected." +"Trying default.\n" , adap->name);
Please mention what the default is.
Quoted 33 lines
drivers/i2c/algos/i2c-algo-pca.c +33
-0+ pca_data->i2c_clock = I2C_PCA_CON_59kHz; + } + }else { +printk (KERN_WARNING "%s: " +"Choosing the clock frequency based on " +"index is deprecated." +" Use the nominal frequency.\n" , adap->name); + } + +pca_reset (pca_data); + + clock =pca_clock (pca_data); +DEB1 (KERN_INFO "%s: Clock frequency is %dkHz\n" , + adap->name, freqs[clock]); + +pca_set_con (pca_data,I2C_PCA_CON_ENSIO | clock); + }else { +int clock; +int mode; +int tlow, thigh; +int min_tlow, min_thigh; +int raise_fall_time; + +struct i2c_algo_pca_data *pca_data = adap->algo_data; + +/* Ignore the reset function from the module, +* we can use the parallel bus reset +*/ + pca_data->reset_chip = pca9665_reset; + +if (pca_data->i2c_clock >1265800 ) { +printk (KERN_WARNING "%s: I2C clock speed too high." +" Using 1265.8kHz.\n" , adap->name);
drivers/i2c/algos/i2c-algo-pca.c line 429
Quoted 10 lines
drivers/i2c/algos/i2c-algo-pca.c +10
-0+ pca_data->i2c_clock =1265800 ; + } + +if (pca_data->i2c_clock <60300 ) { +printk (KERN_WARNING "%s: I2C clock speed too low." +" Using 60.3kHz.\n" , adap->name); + pca_data->i2c_clock =60300 ; + } + + clock =pca_clock (pca_data)/100 ;/* Hz*100 */
CodingStyle (no spaces around operators)
The comment is also a bit misleading as it is the opposite from the code. Please be a bit more detailed here.
Quoted 20 lines
drivers/i2c/algos/i2c-algo-pca.c +15
-3-pca_reset (pca_data); - clock =pca_clock (pca_data); -DEB1 (KERN_INFO "%s: Clock frequency is %dkHz\n" , adap->name, freqs[clock]); +if (pca_data->i2c_clock >10000 ) { + mode =I2C_PCA_MODE_TURBO ; + min_tlow =14 ; + min_thigh =5 ; + raise_fall_time =22 ;/* Raise 11e-8s, Fall 11e-8s */ + }else if (pca_data->i2c_clock >4000 ) { + mode =I2C_PCA_MODE_FASTP ; + min_tlow =17 ; + min_thigh =9 ; + raise_fall_time =22 ;/* Raise 11e-8s, Fall 11e-8s */ + }else if (pca_data->i2c_clock >1000 ) { + mode =I2C_PCA_MODE_FAST ; + min_tlow =44 ; + min_thigh =20 ; + raise_fall_time =58 ;/* Raise 29e-8s, Fall 29e-8s */
drivers/i2c/algos/i2c-algo-pca.c line 456
Quoted 10 lines
drivers/i2c/algos/i2c-algo-pca.c +10
-0+ }else { + mode =I2C_PCA_MODE_STD ; + min_tlow =157 ; + min_thigh =134 ; + raise_fall_time =127 ;/* Raise 29e-8s, Fall 98e-8s */ + } + +if (clock <648 ) { + tlow =255 ; + thigh = (1000000 -clock*raise_fall_time)/(3 *clock)-tlow;
CodingStyle (no spaces around operators)
The values look a bit magic. I could find min_t*-values in the spec, still a reference to the section of the spec will be helpful. I think you could elaborate a bit more on raise_fall_time and clock < 648, though.
drivers/i2c/algos/i2c-algo-pca.c line 461
Quoted 5 lines
drivers/i2c/algos/i2c-algo-pca.c +5
-0+ }else { + tlow = ((1000000 -clock*raise_fall_time)*min_tlow); + tlow /= (3 *clock*(min_thigh+min_tlow)); + thigh = tlow*min_thigh/min_tlow; + }
CodingStyle (no spaces around operators)
drivers/i2c/algos/i2c-algo-pca.c line 466
Quoted 6 lines
drivers/i2c/algos/i2c-algo-pca.c +4
-1+ +pca_reset (pca_data); -pca_set_con (pca_data,I2C_PCA_CON_ENSIO | clock); +DEB1 (KERN_INFO +"%s: Clock frequency is %dHz\n" , adap->name, clock*100 );
CodingStyle (no spaces around operators)
Quoted 82 lines
drivers/i2c/algos/i2c-algo-pca.c +11
-1+ +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_IMODE ); +pca_outw (pca_data,I2C_PCA_IND , mode); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_ISCLL ); +pca_outw (pca_data,I2C_PCA_IND , tlow); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_ISCLH ); +pca_outw (pca_data,I2C_PCA_IND , thigh); + +pca_set_con (pca_data,I2C_PCA_CON_ENSIO ); + }udelay (500 );/* 500 us for oscilator to stabilise */ return 0 ;@@ -384,7 +508,7 @@MODULE_AUTHOR ("Ian Campbell <[email protected]>, " "Wolfram Sang <[email protected]>" ); -MODULE_DESCRIPTION ("I2C-Bus PCA9564 algorithm" ); +MODULE_DESCRIPTION ("I2C-Bus PCA9564/PCA9665 algorithm" );MODULE_LICENSE ("GPL" );module_param (i2c_debug, int,0 );diff -ur
linux-2.6.26.5/drivers/i2c/busses/i2c-pca-isa.clinux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-isa.cdrivers/i2c/busses/i2c-pca-isa.c +14
-4@@ -41,7 +41,8 @@/* Data sheet recommends 59kHz for 100kHz operation due to variation * in the actual clock rate */ -static int clock = I2C_PCA_CON_59kHz; +static int clock =59000 ; +static int chip =I2C_PCA_CHIP_9564 ;static wait_queue_head_t pca_wait;@@ -103,7 +104,7 @@ .owner = THIS_MODULE, .id = I2C_HW_A_ISA, .algo_data = &pca_isa_data, - .name = "PCA9564 ISA Adapter", + .name = "PCA9564/PCA9665 ISA Adapter", .timeout = 100, };@@ -132,6 +133,7 @@ } } + pca_isa_data.i2c_chip_type = chip; pca_isa_data.i2c_clock = clock;if (i2c_pca_add_bus (&pca_isa_ops) <0 ) {dev_err (dev,"Failed to add i2c bus\n" );@@ -182,7 +184,7 @@ }MODULE_AUTHOR ("Ian Campbell <[email protected]>" ); -MODULE_DESCRIPTION ("ISA base PCA9564 driver" ); +MODULE_DESCRIPTION ("ISA base PCA9564/PCA9665 driver" );MODULE_LICENSE ("GPL" );module_param (base, ulong,0 );@@ -191,7 +193,15 @@module_param (irq, int,0 );MODULE_PARM_DESC (irq,"IRQ" );module_param (clock, int,0 ); -MODULE_PARM_DESC (clock,"Clock rate as described in table 1 of PCA9564 datasheet" ); +MODULE_PARM_DESC (clock,"Clock rate in hertz.\n\t\t" +"For PCA9564: 330000,288000,217000,146000," +"88000,59000,44000,36000\n" +"\t\tFor PCA9665:\tStandard: 60300 - 100099\n" +"\t\t\t\tFast: 100100 - 400099\n" +"\t\t\t\tFast+: 400100 - 10000099\n" +"\t\t\t\tTurbo: Up to 1265800" ); +module_param (chip, int,0 ); +MODULE_PARM_DESC (chip,"Chip type: 0 = PCA9564; 1 - PCA9665" );module_init (pca_isa_init);module_exit (pca_isa_exit);diff -ur
linux-2.6.26.5/drivers/i2c/busses/i2c-pca-platform.clinux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-platform.c
drivers/i2c/busses/i2c-pca-platform.c line 176
Quoted 7 lines
drivers/i2c/busses/i2c-pca-platform.c +2
-2@@ -172,8 +172,9 @@ i2c->adap.nr = pdev->id >=0 ? pdev->id :0 ; i2c->adap.owner =THIS_MODULE ; -snprintf (i2c->adap.name,sizeof (i2c->adap.name),"PCA9564 at 0x%08lx" , - (unsigned long ) res->start); + snprintf(i2c->adap.name, sizeof(i2c->adap.name), + "PCA9564/PCA9665 at 0x%08lx",
I think we could be precise here as we know the chip-type. I just got the idea: Do you think it is possible to detect the chip type at runtime? Perhaps by somehow checking the presence of the indirect register?
Quoted 44 lines
drivers/i2c/busses/i2c-pca-platform.c +3
-2+ (unsigned long) res->start); i2c->adap.algo_data = &i2c->algo_data; i2c->adap.dev.parent = &pdev->dev; i2c->adap.timeout = platform_data->timeout;@@ -246,7 +247,7 @@ e_alloc:release_mem_region (res->start,res_len (res)); e_print: -printk (KERN_ERR "Registering PCA9564 FAILED! (%d)\n" , ret); +printk (KERN_ERR "Registering PCA9564/PCA9665 FAILED! (%d)\n" , ret);return ret; }@@ -290,7 +291,7 @@ }MODULE_AUTHOR ("Wolfram Sang <[email protected]>" ); -MODULE_DESCRIPTION ("I2C-PCA9564 platform driver" ); +MODULE_DESCRIPTION ("I2C-PCA9564/PCA9665 platform driver" );MODULE_LICENSE ("GPL" );module_init (i2c_pca_pf_init);diff -ur linux-2.6.26.5/drivers/i2c/busses/Kconfig linux-2.6.26.5-new/drivers/i2c/busses/Kconfig
drivers/i2c/busses/Kconfig +2
-2@@ -630,7 +630,7 @@ will be called i2c-voodoo3. config I2C_PCA_ISA - tristate "PCA9564 on an ISA bus" + tristate "PCA9564/PCA9665 on an ISA bus" depends on ISA select I2C_ALGOPCA default n@@ -647,7 +647,7 @@ time). If unsure, say N. config I2C_PCA_PLATFORM - tristate "PCA9564 as platform device" + tristate "PCA9564/PCA9665 as platform device" select I2C_ALGOPCA default n help
Quoted 4 lines
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
I haven't really applied the patch yet. Will do on Monday when I have access to the PCA9564-equipped board.
All the best,
Wolfram
Signature · 2 lines
Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
Hi Wolfram
Quoted 5 lines · Wolfram Sang
Quoted 1 line
+ if (
pca_data->i2c_chip_type>I2C_PCA_CHIP_9665) {I wonder if something like
I2C_PCA_CHIP_MAXVALcould be useful here. Then, if another chip will be added, you just need changes in the .h file.
You are right. Done.
Quoted 6 lines
drivers/i2c/algos/i2c-algo-pca.c line 386
Quoted 4 lines
drivers/i2c/algos/i2c-algo-pca.c +4
-0+default : +printk (KERN_WARNING +"%s: Invalid I2C clock speed selected." +"Trying default.\n" , adap->name);Please mention what the default is.
Done.
Quoted 5 lines
Quoted 1 line
+ clock = pca_clock(pca_data)/100; /* Hz*100 */
CodingStyle (no spaces around operators)
The comment is also a bit misleading as it is the opposite from the code. Please be a bit more detailed here.
Done.
Quoted 9 lines
drivers/i2c/algos/i2c-algo-pca.c line 456
Quoted 3 lines
drivers/i2c/algos/i2c-algo-pca.c +3
-0+if (clock <648 ) { + tlow =255 ; + thigh = (1000000 -clock*raise_fall_time)/(3 *clock)-tlow;CodingStyle (no spaces around operators)
The values look a bit magic. I could find min_t*-values in the spec, still a reference to the section of the spec will be helpful. I think you could elaborate a bit more onraise_fall_timeand clock < 648, though.
Done.
Quoted 9 lines
drivers/i2c/busses/i2c-pca-platform.c line 176
Quoted 4 lines
drivers/i2c/busses/i2c-pca-platform.c +2
-2-snprintf (i2c->adap.name,sizeof (i2c->adap.name),"PCA9564 at 0x%08lx" , - (unsigned long ) res->start); + snprintf(i2c->adap.name, sizeof(i2c->adap.name), + "PCA9564/PCA9665 at 0x%08lx",I think we could be precise here as we know the chip-type. I just got the idea: Do you think it is possible to detect the chip type at runtime? Perhaps by somehow checking the presence of the indirect register?
I thought the same before, but I was afraid that it would be too much of a hack. As the user has to know which chip he has (there is no auto-detection at all for this), I thought that this is not really a necessity. I can do it if you think that it is a good idea.
I will send you the corrected patch after your comment on the auto-detection issue.
Best regards,
Marco
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
Hi Wolfram.
Quoted 3 lines · Marco Aurelio da Costa
I will send you the corrected patch after your comment on the auto-detection issue.
Actually, I changed my mind and implemented the auto-detection code. Here is the new patch.
Regards,
Marco
drivers/i2c/algos/i2c-algo-pca.c +170 -12
@@ -43,6 +43,14 @@#define pca_wait (adap) adap->wait_for_completion(adap->data)#define pca_reset (adap) adap->reset_chip(adap->data) +static void pca9665_reset (void *pd) +{ +struct i2c_algo_pca_data *adap = pd; +pca_outw (adap,I2C_PCA_INDPTR ,I2C_PCA_IPRESET ); +pca_outw (adap,I2C_PCA_IND ,0xA5 ); +pca_outw (adap,I2C_PCA_IND ,0x5A ); +} +/* * Generate a start condition on the i2c bus. *
@@ -330,26 +338,176 @@ .functionality = pca_func, }; -static int pca_init (struct i2c_adapter *adap) +static unsigned int pca_probe_chip (struct i2c_adapter *adap) { -static int freqs[] = {330 ,288 ,217 ,146 ,88 ,59 ,44 ,36 }; -int clock;struct i2c_algo_pca_data *pca_data = adap->algo_data; - -if (pca_data->i2c_clock >7 ) { -printk (KERN_WARNING "%s: Invalid I2C clock speed selected. Trying default.\n" , +/* The trick here is to check if there is an indirect register +* available. If there is one, we will read the value we first +* wrote on I2C_PCA_IADR. Otherwise, we will read the last value +* we wrote on I2C_PCA_ADR +*/ +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_IADR ); +pca_outw (pca_data,I2C_PCA_IND ,0xAA ); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_ITO ); +pca_outw (pca_data,I2C_PCA_IND ,0x00 ); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_IADR ); +if (pca_inw (pca_data,I2C_PCA_IND ) ==0xAA ) { +printk (KERN_INFO +"%s: PCA9665 detected." , adap->name); - pca_data->i2c_clock = I2C_PCA_CON_59kHz; +return I2C_PCA_CHIP_9665 ; + }else { +printk (KERN_INFO +"%s: PCA9564 detected." , + adap->name); +return I2C_PCA_CHIP_9564 ; } +} + +static int pca_init (struct i2c_adapter *adap) +{ +struct i2c_algo_pca_data *pca_data = adap->algo_data; adap->algo = &pca_algo; -pca_reset (pca_data); +if (pca_probe_chip (adap) ==I2C_PCA_CHIP_9564 ) { +static int freqs[] = {330 ,288 ,217 ,146 ,88 ,59 ,44 ,36 }; +int clock; + +if (pca_data->i2c_clock >7 ) { +switch (pca_data->i2c_clock) { +case 330000 : + pca_data->i2c_clock = I2C_PCA_CON_330kHz; +break ; +case 288000 : + pca_data->i2c_clock = I2C_PCA_CON_288kHz; +break ; +case 217000 : + pca_data->i2c_clock = I2C_PCA_CON_217kHz; +break ; +case 146000 : + pca_data->i2c_clock = I2C_PCA_CON_146kHz; +break ; +case 88000 : + pca_data->i2c_clock = I2C_PCA_CON_88kHz; +break ; +case 59000 : + pca_data->i2c_clock = I2C_PCA_CON_59kHz; +break ; +case 44000 : + pca_data->i2c_clock = I2C_PCA_CON_44kHz; +break ; +case 36000 : + pca_data->i2c_clock = I2C_PCA_CON_36kHz; +break ; +default : +printk (KERN_WARNING +"%s: Invalid I2C clock speed selected." +"Using default 59kHz.\n" , adap->name); + pca_data->i2c_clock = I2C_PCA_CON_59kHz; + } + }else { +printk (KERN_WARNING "%s: " +"Choosing the clock frequency based on " +"index is deprecated." +" Use the nominal frequency.\n" , adap->name); + } + +pca_reset (pca_data); + + clock =pca_clock (pca_data); +DEB1 (KERN_INFO "%s: Clock frequency is %dkHz\n" , + adap->name, freqs[clock]); + +pca_set_con (pca_data,I2C_PCA_CON_ENSIO | clock); + }else { +int clock; +int mode; +int tlow, thi; +/* Values can be found on PCA9665 datasheet section 7.3.2.6 */ +int min_tlow, min_thi; +/* These values are the maximum raise and fall values allowed +* by the I2C operation mode (Standard, Fast or Fast+) +* They are used (added) below to calculate the clock dividers +* of PCA9665. Note that they are slightly different of the +* real maximum, to allow the change on mode exactly on the +* maximum clock rate for each mode +*/ +int raise_fall_time; + +struct i2c_algo_pca_data *pca_data = adap->algo_data; + +/* Ignore the reset function from the module, +* we can use the parallel bus reset +*/ + pca_data->reset_chip = pca9665_reset; + +if (pca_data->i2c_clock >1265800 ) { +printk (KERN_WARNING "%s: I2C clock speed too high." +" Using 1265.8kHz.\n" , adap->name); + pca_data->i2c_clock =1265800 ; + } + +if (pca_data->i2c_clock <60300 ) { +printk (KERN_WARNING "%s: I2C clock speed too low." +" Using 60.3kHz.\n" , adap->name); + pca_data->i2c_clock =60300 ; + } + +/* To avoid integer overflow, use clock/100 for calculations */ + clock =pca_clock (pca_data)/100 ; - clock =pca_clock (pca_data); -DEB1 (KERN_INFO "%s: Clock frequency is %dkHz\n" , adap->name, freqs[clock]); -pca_set_con (pca_data,I2C_PCA_CON_ENSIO | clock); +if (pca_data->i2c_clock >10000 ) { + mode =I2C_PCA_MODE_TURBO ; + min_tlow =14 ; + min_thi =5 ; + raise_fall_time =22 ;/* Raise 11e-8s, Fall 11e-8s */ + }else if (pca_data->i2c_clock >4000 ) { + mode =I2C_PCA_MODE_FASTP ; + min_tlow =17 ; + min_thi =9 ; + raise_fall_time =22 ;/* Raise 11e-8s, Fall 11e-8s */ + }else if (pca_data->i2c_clock >1000 ) { + mode =I2C_PCA_MODE_FAST ; + min_tlow =44 ; + min_thi =20 ; + raise_fall_time =58 ;/* Raise 29e-8s, Fall 29e-8s */ + }else { + mode =I2C_PCA_MODE_STD ; + min_tlow =157 ; + min_thi =134 ; + raise_fall_time =127 ;/* Raise 29e-8s, Fall 98e-8s */ + } + +/* The minimum clock that respects the thi/tlow = 134/157 is +* 64800 Hz. Below that, we have to fix the tlow to 255 and +* calculate the thi factor. +*/ +if (clock <648 ) { + tlow =255 ; + thi =1000000 - clock * raise_fall_time; + thi /= (I2C_PCA_OSC_PER * clock) - tlow; + }else { + tlow = (1000000 - clock * raise_fall_time) * min_tlow; + tlow /=I2C_PCA_OSC_PER * clock * (min_thi + min_tlow); + thi = tlow * min_thi / min_tlow; + } + +pca_reset (pca_data); + +DEB1 (KERN_INFO +"%s: Clock frequency is %dHz\n" , adap->name, clock *100 ); + +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_IMODE ); +pca_outw (pca_data,I2C_PCA_IND , mode); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_ISCLL ); +pca_outw (pca_data,I2C_PCA_IND , tlow); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_ISCLH ); +pca_outw (pca_data,I2C_PCA_IND , thi); + +pca_set_con (pca_data,I2C_PCA_CON_ENSIO ); + }udelay (500 );/* 500 us for oscilator to stabilise */ return 0 ;
@@ -384,7 +542,7 @@MODULE_AUTHOR ("Ian Campbell <[email protected]>, " "Wolfram Sang <[email protected]>" ); -MODULE_DESCRIPTION ("I2C-Bus PCA9564 algorithm" ); +MODULE_DESCRIPTION ("I2C-Bus PCA9564/PCA9665 algorithm" );MODULE_LICENSE ("GPL" );module_param (i2c_debug, int,0 );
drivers/i2c/busses/i2c-pca-isa.c +10 -4
@@ -41,7 +41,7 @@/* Data sheet recommends 59kHz for 100kHz operation due to variation * in the actual clock rate */ -static int clock = I2C_PCA_CON_59kHz; +static int clock =59000 ;static wait_queue_head_t pca_wait;
@@ -103,7 +103,7 @@ .owner = THIS_MODULE, .id = I2C_HW_A_ISA, .algo_data = &pca_isa_data, - .name = "PCA9564 ISA Adapter", + .name = "PCA9564/PCA9665 ISA Adapter", .timeout = 100, };
@@ -182,7 +182,7 @@ }MODULE_AUTHOR ("Ian Campbell <[email protected]>" ); -MODULE_DESCRIPTION ("ISA base PCA9564 driver" ); +MODULE_DESCRIPTION ("ISA base PCA9564/PCA9665 driver" );MODULE_LICENSE ("GPL" );module_param (base, ulong,0 );
@@ -191,7 +191,13 @@module_param (irq, int,0 );MODULE_PARM_DESC (irq,"IRQ" );module_param (clock, int,0 ); -MODULE_PARM_DESC (clock,"Clock rate as described in table 1 of PCA9564 datasheet" ); +MODULE_PARM_DESC (clock,"Clock rate in hertz.\n\t\t" +"For PCA9564: 330000,288000,217000,146000," +"88000,59000,44000,36000\n" +"\t\tFor PCA9665:\tStandard: 60300 - 100099\n" +"\t\t\t\tFast: 100100 - 400099\n" +"\t\t\t\tFast+: 400100 - 10000099\n" +"\t\t\t\tTurbo: Up to 1265800" );module_init (pca_isa_init);module_exit (pca_isa_exit);
drivers/i2c/busses/i2c-pca-platform.c +5 -4
@@ -172,8 +172,9 @@ i2c->adap.nr = pdev->id >=0 ? pdev->id :0 ; i2c->adap.owner =THIS_MODULE ; -snprintf (i2c->adap.name,sizeof (i2c->adap.name),"PCA9564 at 0x%08lx" , - (unsigned long ) res->start); +snprintf (i2c->adap.name,sizeof (i2c->adap.name), +"PCA9564/PCA9665 at 0x%08lx" , + (unsigned long ) res->start); i2c->adap.algo_data = &i2c->algo_data; i2c->adap.dev.parent = &pdev->dev; i2c->adap.timeout = platform_data->timeout;
@@ -246,7 +247,7 @@ e_alloc:release_mem_region (res->start,res_len (res)); e_print: -printk (KERN_ERR "Registering PCA9564 FAILED! (%d)\n" , ret); +printk (KERN_ERR "Registering PCA9564/PCA9665 FAILED! (%d)\n" , ret);return ret; }
@@ -290,7 +291,7 @@ }MODULE_AUTHOR ("Wolfram Sang <[email protected]>" ); -MODULE_DESCRIPTION ("I2C-PCA9564 platform driver" ); +MODULE_DESCRIPTION ("I2C-PCA9564/PCA9665 platform driver" );MODULE_LICENSE ("GPL" );module_init (i2c_pca_pf_init);
drivers/i2c/busses/Kconfig +2 -2
@@ -630,7 +630,7 @@ will be called i2c-voodoo3. config I2C_PCA_ISA - tristate "PCA9564 on an ISA bus" + tristate "PCA9564/PCA9665 on an ISA bus" depends on ISA select I2C_ALGOPCA default n
@@ -647,7 +647,7 @@ time). If unsure, say N. config I2C_PCA_PLATFORM - tristate "PCA9564 as platform device" + tristate "PCA9564/PCA9665 as platform device" select I2C_ALGOPCA default n help
include/linux/i2c-algo-pca.h +31 -2
@@ -1,7 +1,14 @@#ifndef _LINUX_I2C_ALGO_PCA_H#define _LINUX_I2C_ALGO_PCA_H -/* Clock speeds for the bus */ +/* Chips known to the pca algo */ +#define I2C_PCA_CHIP_9564 0x00 +#define I2C_PCA_CHIP_9665 0x01 + +/* Internal period for PCA9665 oscilator */ +#define I2C_PCA_OSC_PER 3/* e10-8s */ + +/* Clock speeds for the bus for PCA9564*/ #define I2C_PCA_CON_330kHz 0x00#define I2C_PCA_CON_288kHz 0x01#define I2C_PCA_CON_217kHz 0x02
@@ -18,6 +25,26 @@#define I2C_PCA_ADR 0x02/* OWN ADR Read/Write */ #define I2C_PCA_CON 0x03/* CONTROL Read/Write */ +/* PCA9665 registers */ +#define I2C_PCA_INDPTR 0x00/* INDIRECT Pointer Write Only */ +#define I2C_PCA_IND 0x02/* INDIRECT Read/Write */ + +/* PCA9665 indirect registers */ +#define I2C_PCA_ICOUNT 0x00/* Byte Count for buffered mode */ +#define I2C_PCA_IADR 0x01/* OWN ADR */ +#define I2C_PCA_ISCLL 0x02/* SCL LOW period */ +#define I2C_PCA_ISCLH 0x03/* SCL HIGH period */ +#define I2C_PCA_ITO 0x04/* TIMEOUT */ +#define I2C_PCA_IPRESET 0x05/* Parallel bus reset */ +#define I2C_PCA_IMODE 0x06/* I2C Bus mode */ + +/* PCA9665 I2C bus mode */ +#define I2C_PCA_MODE_STD 0x00/* Standard mode */ +#define I2C_PCA_MODE_FAST 0x01/* Fast mode */ +#define I2C_PCA_MODE_FASTP 0x02/* Fast Plus mode */ +#define I2C_PCA_MODE_TURBO 0x03/* Turbo mode */ + +#define I2C_PCA_CON_AA 0x80/* Assert Acknowledge */ #define I2C_PCA_CON_ENSIO 0x40/* Enable */ #define I2C_PCA_CON_STA 0x20/* Start */
@@ -31,7 +58,9 @@int (*read_byte) (void *data,int reg);int (*wait_for_completion) (void *data);void (*reset_chip) (void *data); -/* i2c_clock values are defined in linux/i2c-algo-pca.h */ +/* For PCA9964, use one of the predefined frequencies: +* 330000, 288000, 217000, 146000, 88000, 59000, 44000, 36000 +* For PCA9665, use the frequency you want here. */ unsigned int i2c_clock; };
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
Hi Wolfram.
Did you have time to look into the patch I sent?
Thank you in advance,
Marco
Quoted 6 lines · Marco Aurelio da Costa
Hi Wolfram.
Quoted 3 lines · Marco Aurelio da Costa
I will send you the corrected patch after your comment on the auto-detection issue.
Quoted 7 lines
Actually, I changed my mind and implemented the auto-detection code. Here is the new patch.
Regards,
Marco
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
Hi Marco,
Quoted 1 line · Marco Aurelio da Costa
Did you have time to look into the patch I sent?
I had a look and found very minor issues only (spaces around operators), still I haven't had the time to actually test it on my pca9564-device. I haven't forgotten, but it is one of those weeks... :(
All the best,
Wolfram
Signature · 2 lines
Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
Wolfram Sang
Reviewed-byHi Marco,
finally I came around to setup my board with the PCA9564. Here are my
results: The algo detected the PCA9564 and moaned about the old style of supplying the frequency. I could easily change it to newstyle. In every case, I could still correctly read out the eeprom. So, everything worked flawlessly with a PCA9564. So, if the PCA9665 works for you and you just apply these minor suggestions below, I think the patch is ready for submission. For that, you should follow the canocical patch format (Documentation/SubmittingPatches, Chapter 15) when you post that version.
Quoted 47 lines · Marco Aurelio da Costa
Hi Wolfram.
Quoted 3 lines · Marco Aurelio da Costa
I will send you the corrected patch after your comment on the auto-detection issue.
Actually, I changed my mind and implemented the auto-detection code. Here is the new patch.
Regards,
Marco
diff -ur
linux-2.6.26.5/drivers/i2c/algos/i2c-algo-pca.clinux-2.6.26.5-new/drivers/i2c/algos/i2c-algo-pca.cdrivers/i2c/algos/i2c-algo-pca.c +12
-6@@ -43,6 +43,14 @@#define pca_wait (adap) adap->wait_for_completion(adap->data)#define pca_reset (adap) adap->reset_chip(adap->data) +static void pca9665_reset (void *pd) +{ +struct i2c_algo_pca_data *adap = pd; +pca_outw (adap,I2C_PCA_INDPTR ,I2C_PCA_IPRESET ); +pca_outw (adap,I2C_PCA_IND ,0xA5 ); +pca_outw (adap,I2C_PCA_IND ,0x5A ); +} +/* * Generate a start condition on the i2c bus. * @@ -330,26 +338,176 @@ .functionality = pca_func, }; -static int pca_init (struct i2c_adapter *adap) +static unsigned int pca_probe_chip (struct i2c_adapter *adap) { -static int freqs[] = {330 ,288 ,217 ,146 ,88 ,59 ,44 ,36 }; -int clock;struct i2c_algo_pca_data *pca_data = adap->algo_data; - -if (pca_data->i2c_clock >7 ) { - printk(KERN_WARNING "%s: Invalid I2C clock speed selected. Trying default.\n", +/* The trick here is to check if there is an indirect register +* available. If there is one, we will read the value we first +* wrote on I2C_PCA_IADR. Otherwise, we will read the last value
drivers/i2c/algos/i2c-algo-pca.c line 356
Quoted 10 lines
drivers/i2c/algos/i2c-algo-pca.c +10
-0+* we wrote on I2C_PCA_ADR +*/ +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_IADR ); +pca_outw (pca_data,I2C_PCA_IND ,0xAA ); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_ITO ); +pca_outw (pca_data,I2C_PCA_IND ,0x00 ); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_IADR ); +if (pca_inw (pca_data,I2C_PCA_IND ) ==0xAA ) { + printk(KERN_INFO + "%s: PCA9665 detected.",
"\n" is missing. Also, the whole printk should fit into one line.
drivers/i2c/algos/i2c-algo-pca.c line 361
Quoted 6 lines
drivers/i2c/algos/i2c-algo-pca.c +4
-1adap->name); - pca_data->i2c_clock = I2C_PCA_CON_59kHz; +return I2C_PCA_CHIP_9665 ; + }else { + printk(KERN_INFO + "%s: PCA9564 detected.",
Here, too.
Quoted 36 lines
drivers/i2c/algos/i2c-algo-pca.c +31
-1+ adap->name); +return I2C_PCA_CHIP_9564 ; } +} + +static int pca_init (struct i2c_adapter *adap) +{ +struct i2c_algo_pca_data *pca_data = adap->algo_data; adap->algo = &pca_algo; -pca_reset (pca_data); +if (pca_probe_chip (adap) ==I2C_PCA_CHIP_9564 ) { +static int freqs[] = {330 ,288 ,217 ,146 ,88 ,59 ,44 ,36 }; +int clock; + +if (pca_data->i2c_clock >7 ) { +switch (pca_data->i2c_clock) { +case 330000 : + pca_data->i2c_clock = I2C_PCA_CON_330kHz; +break ; +case 288000 : + pca_data->i2c_clock = I2C_PCA_CON_288kHz; +break ; +case 217000 : + pca_data->i2c_clock = I2C_PCA_CON_217kHz; +break ; +case 146000 : + pca_data->i2c_clock = I2C_PCA_CON_146kHz; +break ; +case 88000 : + pca_data->i2c_clock = I2C_PCA_CON_88kHz; +break ; +case 59000 : + pca_data->i2c_clock = I2C_PCA_CON_59kHz; +break ;
drivers/i2c/algos/i2c-algo-pca.c line 406
Quoted 10 lines
drivers/i2c/algos/i2c-algo-pca.c +10
-0+case 44000 : + pca_data->i2c_clock = I2C_PCA_CON_44kHz; +break ; +case 36000 : + pca_data->i2c_clock = I2C_PCA_CON_36kHz; +break ; +default : +printk (KERN_WARNING +"%s: Invalid I2C clock speed selected." +"Using default 59kHz.\n" , adap->name);
Space before "Using".
Quoted 42 lines
drivers/i2c/algos/i2c-algo-pca.c +42
-0+ pca_data->i2c_clock = I2C_PCA_CON_59kHz; + } + }else { +printk (KERN_WARNING "%s: " +"Choosing the clock frequency based on " +"index is deprecated." +" Use the nominal frequency.\n" , adap->name); + } + +pca_reset (pca_data); + + clock =pca_clock (pca_data); +DEB1 (KERN_INFO "%s: Clock frequency is %dkHz\n" , + adap->name, freqs[clock]); + +pca_set_con (pca_data,I2C_PCA_CON_ENSIO | clock); + }else { +int clock; +int mode; +int tlow, thi; +/* Values can be found on PCA9665 datasheet section 7.3.2.6 */ +int min_tlow, min_thi; +/* These values are the maximum raise and fall values allowed +* by the I2C operation mode (Standard, Fast or Fast+) +* They are used (added) below to calculate the clock dividers +* of PCA9665. Note that they are slightly different of the +* real maximum, to allow the change on mode exactly on the +* maximum clock rate for each mode +*/ +int raise_fall_time; + +struct i2c_algo_pca_data *pca_data = adap->algo_data; + +/* Ignore the reset function from the module, +* we can use the parallel bus reset +*/ + pca_data->reset_chip = pca9665_reset; + +if (pca_data->i2c_clock >1265800 ) { +printk (KERN_WARNING "%s: I2C clock speed too high." +" Using 1265.8kHz.\n" , adap->name); + pca_data->i2c_clock =1265800 ;
drivers/i2c/algos/i2c-algo-pca.c line 458
Quoted 10 lines
drivers/i2c/algos/i2c-algo-pca.c +10
-0+ } + +if (pca_data->i2c_clock <60300 ) { +printk (KERN_WARNING "%s: I2C clock speed too low." +" Using 60.3kHz.\n" , adap->name); + pca_data->i2c_clock =60300 ; + } + +/* To avoid integer overflow, use clock/100 for calculations */ + clock =pca_clock (pca_data)/100 ;
Spaces around operators.
Quoted 213 lines
drivers/i2c/algos/i2c-algo-pca.c +51
-4- clock =pca_clock (pca_data); -DEB1 (KERN_INFO "%s: Clock frequency is %dkHz\n" , adap->name, freqs[clock]); -pca_set_con (pca_data,I2C_PCA_CON_ENSIO | clock); +if (pca_data->i2c_clock >10000 ) { + mode =I2C_PCA_MODE_TURBO ; + min_tlow =14 ; + min_thi =5 ; + raise_fall_time =22 ;/* Raise 11e-8s, Fall 11e-8s */ + }else if (pca_data->i2c_clock >4000 ) { + mode =I2C_PCA_MODE_FASTP ; + min_tlow =17 ; + min_thi =9 ; + raise_fall_time =22 ;/* Raise 11e-8s, Fall 11e-8s */ + }else if (pca_data->i2c_clock >1000 ) { + mode =I2C_PCA_MODE_FAST ; + min_tlow =44 ; + min_thi =20 ; + raise_fall_time =58 ;/* Raise 29e-8s, Fall 29e-8s */ + }else { + mode =I2C_PCA_MODE_STD ; + min_tlow =157 ; + min_thi =134 ; + raise_fall_time =127 ;/* Raise 29e-8s, Fall 98e-8s */ + } + +/* The minimum clock that respects the thi/tlow = 134/157 is +* 64800 Hz. Below that, we have to fix the tlow to 255 and +* calculate the thi factor. +*/ +if (clock <648 ) { + tlow =255 ; + thi =1000000 - clock * raise_fall_time; + thi /= (I2C_PCA_OSC_PER * clock) - tlow; + }else { + tlow = (1000000 - clock * raise_fall_time) * min_tlow; + tlow /=I2C_PCA_OSC_PER * clock * (min_thi + min_tlow); + thi = tlow * min_thi / min_tlow; + } + +pca_reset (pca_data); + +DEB1 (KERN_INFO +"%s: Clock frequency is %dHz\n" , adap->name, clock *100 ); + +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_IMODE ); +pca_outw (pca_data,I2C_PCA_IND , mode); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_ISCLL ); +pca_outw (pca_data,I2C_PCA_IND , tlow); +pca_outw (pca_data,I2C_PCA_INDPTR ,I2C_PCA_ISCLH ); +pca_outw (pca_data,I2C_PCA_IND , thi); + +pca_set_con (pca_data,I2C_PCA_CON_ENSIO ); + }udelay (500 );/* 500 us for oscilator to stabilise */ return 0 ;@@ -384,7 +542,7 @@MODULE_AUTHOR ("Ian Campbell <[email protected]>, " "Wolfram Sang <[email protected]>" ); -MODULE_DESCRIPTION ("I2C-Bus PCA9564 algorithm" ); +MODULE_DESCRIPTION ("I2C-Bus PCA9564/PCA9665 algorithm" );MODULE_LICENSE ("GPL" );module_param (i2c_debug, int,0 );diff -ur
linux-2.6.26.5/drivers/i2c/busses/i2c-pca-isa.clinux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-isa.cdrivers/i2c/busses/i2c-pca-isa.c +10
-4@@ -41,7 +41,7 @@/* Data sheet recommends 59kHz for 100kHz operation due to variation * in the actual clock rate */ -static int clock = I2C_PCA_CON_59kHz; +static int clock =59000 ;static wait_queue_head_t pca_wait;@@ -103,7 +103,7 @@ .owner = THIS_MODULE, .id = I2C_HW_A_ISA, .algo_data = &pca_isa_data, - .name = "PCA9564 ISA Adapter", + .name = "PCA9564/PCA9665 ISA Adapter", .timeout = 100, };@@ -182,7 +182,7 @@ }MODULE_AUTHOR ("Ian Campbell <[email protected]>" ); -MODULE_DESCRIPTION ("ISA base PCA9564 driver" ); +MODULE_DESCRIPTION ("ISA base PCA9564/PCA9665 driver" );MODULE_LICENSE ("GPL" );module_param (base, ulong,0 );@@ -191,7 +191,13 @@module_param (irq, int,0 );MODULE_PARM_DESC (irq,"IRQ" );module_param (clock, int,0 ); -MODULE_PARM_DESC (clock,"Clock rate as described in table 1 of PCA9564 datasheet" ); +MODULE_PARM_DESC (clock,"Clock rate in hertz.\n\t\t" +"For PCA9564: 330000,288000,217000,146000," +"88000,59000,44000,36000\n" +"\t\tFor PCA9665:\tStandard: 60300 - 100099\n" +"\t\t\t\tFast: 100100 - 400099\n" +"\t\t\t\tFast+: 400100 - 10000099\n" +"\t\t\t\tTurbo: Up to 1265800" );module_init (pca_isa_init);module_exit (pca_isa_exit);diff -ur
linux-2.6.26.5/drivers/i2c/busses/i2c-pca-platform.clinux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-platform.cdrivers/i2c/busses/i2c-pca-platform.c +5
-4@@ -172,8 +172,9 @@ i2c->adap.nr = pdev->id >=0 ? pdev->id :0 ; i2c->adap.owner =THIS_MODULE ; -snprintf (i2c->adap.name,sizeof (i2c->adap.name),"PCA9564 at 0x%08lx" , - (unsigned long ) res->start); +snprintf (i2c->adap.name,sizeof (i2c->adap.name), +"PCA9564/PCA9665 at 0x%08lx" , + (unsigned long ) res->start); i2c->adap.algo_data = &i2c->algo_data; i2c->adap.dev.parent = &pdev->dev; i2c->adap.timeout = platform_data->timeout;@@ -246,7 +247,7 @@ e_alloc:release_mem_region (res->start,res_len (res)); e_print: -printk (KERN_ERR "Registering PCA9564 FAILED! (%d)\n" , ret); +printk (KERN_ERR "Registering PCA9564/PCA9665 FAILED! (%d)\n" , ret);return ret; }@@ -290,7 +291,7 @@ }MODULE_AUTHOR ("Wolfram Sang <[email protected]>" ); -MODULE_DESCRIPTION ("I2C-PCA9564 platform driver" ); +MODULE_DESCRIPTION ("I2C-PCA9564/PCA9665 platform driver" );MODULE_LICENSE ("GPL" );module_init (i2c_pca_pf_init);diff -ur linux-2.6.26.5/drivers/i2c/busses/Kconfig linux-2.6.26.5-new/drivers/i2c/busses/Kconfig
drivers/i2c/busses/Kconfig +2
-2@@ -630,7 +630,7 @@ will be called i2c-voodoo3. config I2C_PCA_ISA - tristate "PCA9564 on an ISA bus" + tristate "PCA9564/PCA9665 on an ISA bus" depends on ISA select I2C_ALGOPCA default n@@ -647,7 +647,7 @@ time). If unsure, say N. config I2C_PCA_PLATFORM - tristate "PCA9564 as platform device" + tristate "PCA9564/PCA9665 as platform device" select I2C_ALGOPCA default n helpdiff -ur
linux-2.6.26.5/include/linux/i2c-algo-pca.hlinux-2.6.26.5-new/include/linux/i2c-algo-pca.hinclude/linux/i2c-algo-pca.h +28
-1@@ -1,7 +1,14 @@#ifndef _LINUX_I2C_ALGO_PCA_H#define _LINUX_I2C_ALGO_PCA_H -/* Clock speeds for the bus */ +/* Chips known to the pca algo */ +#define I2C_PCA_CHIP_9564 0x00 +#define I2C_PCA_CHIP_9665 0x01 + +/* Internal period for PCA9665 oscilator */ +#define I2C_PCA_OSC_PER 3/* e10-8s */ + +/* Clock speeds for the bus for PCA9564*/ #define I2C_PCA_CON_330kHz 0x00#define I2C_PCA_CON_288kHz 0x01#define I2C_PCA_CON_217kHz 0x02@@ -18,6 +25,26 @@#define I2C_PCA_ADR 0x02/* OWN ADR Read/Write */ #define I2C_PCA_CON 0x03/* CONTROL Read/Write */ +/* PCA9665 registers */ +#define I2C_PCA_INDPTR 0x00/* INDIRECT Pointer Write Only */ +#define I2C_PCA_IND 0x02/* INDIRECT Read/Write */ + +/* PCA9665 indirect registers */ +#define I2C_PCA_ICOUNT 0x00/* Byte Count for buffered mode */ +#define I2C_PCA_IADR 0x01/* OWN ADR */ +#define I2C_PCA_ISCLL 0x02/* SCL LOW period */ +#define I2C_PCA_ISCLH 0x03/* SCL HIGH period */ +#define I2C_PCA_ITO 0x04/* TIMEOUT */ +#define I2C_PCA_IPRESET 0x05/* Parallel bus reset */ +#define I2C_PCA_IMODE 0x06/* I2C Bus mode */ + +/* PCA9665 I2C bus mode */ +#define I2C_PCA_MODE_STD 0x00/* Standard mode */ +#define I2C_PCA_MODE_FAST 0x01/* Fast mode */ +#define I2C_PCA_MODE_FASTP 0x02/* Fast Plus mode */ +#define I2C_PCA_MODE_TURBO 0x03/* Turbo mode */ + +#define I2C_PCA_CON_AA 0x80/* Assert Acknowledge */ #define I2C_PCA_CON_ENSIO 0x40/* Enable */ #define I2C_PCA_CON_STA 0x20/* Start */
include/linux/i2c-algo-pca.h line 61
Quoted 5 lines
include/linux/i2c-algo-pca.h +1
-1@@ -31,7 +58,9 @@int (*read_byte) (void *data,int reg);int (*wait_for_completion) (void *data);void (*reset_chip) (void *data); -/* i2c_clock values are defined in linux/i2c-algo-pca.h */ +/* For PCA9964, use one of the predefined frequencies:
Typo: Not 9964, but 9564
Quoted 10 lines
include/linux/i2c-algo-pca.h +2
-0+* 330000, 288000, 217000, 146000, 88000, 59000, 44000, 36000 +* For PCA9665, use the frequency you want here. */ unsigned int i2c_clock; };_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
All the best and thanks for the patch!
Wolfram
Signature · 2 lines
Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
Hi Wolfram.
Quoted 11 lines · Wolfram Sang
Hi Marco,
finally I came around to setup my board with the PCA9564. Here are my
results: The algo detected the PCA9564 and moaned about the old style of supplying the frequency. I could easily change it to newstyle. In every case, I could still correctly read out the eeprom. So, everything worked flawlessly with a PCA9564. So, if the PCA9665 works for you and you just apply these minor suggestions below, I think the patch is ready for submission. For that, you should follow the canocical patch format (Documentation/SubmittingPatches, Chapter 15) when you post that version.
Glad to hear! I will make the changes as you sugests and submit the patch as soon as possible. I am out of office for some time.
Quoted 3 lines
All the best and thanks for the patch!
The comunity helps me so much, It is just fair that I give something back.
Best regards,
Marco
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
Hi Marco,
Quoted 2 lines · Marco Aurelio da Costa
Glad to hear! I will make the changes as you sugests and submit the patch as soon as possible. I am out of office for some time.
Any news on your patch?
All the best,
Wolfram
Signature · 2 lines
Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
Hi Marco,
Quoted 5 lines · Marco Aurelio da Costa
Quoted 1 line
Any news on your patch?
Actually I am in Brazil. I will not be able to really test it until the end of November, when I go back to Germany.
I am sorry for the delay.
Bump ;)
Regards,
Wolfram
Signature · 2 lines
Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry
Quoted 9 lines · Wolfram Sang
Hi Marco,
Quoted 5 lines · Marco Aurelio da Costa
Quoted 1 line
Any news on your patch?
Actually I am in Brazil. I will not be able to really test it until the end of November, when I go back to Germany.
I am sorry for the delay.
Marco, are you back from Brazil?
Regards,
Wolfram
Signature · 2 lines
Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry