* PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c
@ 2008-09-19 14:22 Marco Aurelio da Costa
[not found] ` <48D3B5B7.1060402-nrw9SyMmU14AvxtiuMwx3w@public.gmane.org>
0 siblings, 1 reply; 13+ messages in thread
From: Marco Aurelio da Costa @ 2008-09-19 14:22 UTC (permalink / raw)
To: i2c-GZX6beZjE8VD60Wz+7aTrA
[-- Attachment #1: Type: text/plain, Size: 116 bytes --]
Hi Wolfram,
Here is the patch against 2.6.26.5.
Please tell me if I did something very wrong ;)
Regards,
Marco
[-- Attachment #2: pca9665-support.patch --]
[-- Type: text/x-patch, Size: 11211 bytes --]
diff -ur linux-2.6.26.5/drivers/i2c/algos/i2c-algo-pca.c linux-2.6.26.5-new/drivers/i2c/algos/i2c-algo-pca.c
--- linux-2.6.26.5/drivers/i2c/algos/i2c-algo-pca.c 2008-09-08 14:40:20.000000000 -0300
+++ linux-2.6.26.5-new/drivers/i2c/algos/i2c-algo-pca.c 2008-09-19 10:29:33.000000000 -0300
@@ -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 <icampbell-2sJRl1BP9u0AvxtiuMwx3w@public.gmane.org>, "
"Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>");
-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.c linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-isa.c
--- linux-2.6.26.5/drivers/i2c/busses/i2c-pca-isa.c 2008-09-08 14:40:20.000000000 -0300
+++ linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-isa.c 2008-09-19 10:59:33.000000000 -0300
@@ -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 <icampbell-2sJRl1BP9u0AvxtiuMwx3w@public.gmane.org>");
-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);
diff -ur linux-2.6.26.5/drivers/i2c/busses/i2c-pca-platform.c linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-platform.c
--- linux-2.6.26.5/drivers/i2c/busses/i2c-pca-platform.c 2008-09-08 14:40:20.000000000 -0300
+++ linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-platform.c 2008-09-19 10:11:02.000000000 -0300
@@ -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 <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>");
-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
--- linux-2.6.26.5/drivers/i2c/busses/Kconfig 2008-09-08 14:40:20.000000000 -0300
+++ linux-2.6.26.5-new/drivers/i2c/busses/Kconfig 2008-09-19 10:33:35.000000000 -0300
@@ -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
diff -ur linux-2.6.26.5/include/linux/i2c-algo-pca.h linux-2.6.26.5-new/include/linux/i2c-algo-pca.h
--- linux-2.6.26.5/include/linux/i2c-algo-pca.h 2008-09-08 14:40:20.000000000 -0300
+++ linux-2.6.26.5-new/include/linux/i2c-algo-pca.h 2008-09-19 11:13:21.000000000 -0300
@@ -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 *);
[-- Attachment #3: Type: text/plain, Size: 157 bytes --]
_______________________________________________
i2c mailing list
i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org
http://lists.lm-sensors.org/mailman/listinfo/i2c
^ permalink raw reply [flat|nested] 13+ messages in thread[parent not found: <48D3B5B7.1060402-nrw9SyMmU14AvxtiuMwx3w@public.gmane.org>]
* Re: PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c [not found] ` <48D3B5B7.1060402-nrw9SyMmU14AvxtiuMwx3w@public.gmane.org> @ 2008-09-19 14:55 ` Wolfram Sang [not found] ` <20080919145500.GH4307-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> 0 siblings, 1 reply; 13+ messages in thread From: Wolfram Sang @ 2008-09-19 14:55 UTC (permalink / raw) To: Marco Aurelio da Costa; +Cc: i2c-GZX6beZjE8VD60Wz+7aTrA [-- Attachment #1.1: Type: text/plain, Size: 1002 bytes --] > 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... > +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)... > + 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. > + Trailing whitespaces here (and in some other places). > + int minTLow, minTHi; This style of naming is at least unusual in kernel. Maybe min_tlow? So much for now, more later... Wolfram -- Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 157 bytes --] _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 13+ messages in thread
[parent not found: <20080919145500.GH4307-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>]
* Re: PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c [not found] ` <20080919145500.GH4307-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> @ 2008-09-19 15:37 ` Marco Aurelio da Costa [not found] ` <48D3C74E.1050801-nrw9SyMmU14AvxtiuMwx3w@public.gmane.org> 0 siblings, 1 reply; 13+ messages in thread From: Marco Aurelio da Costa @ 2008-09-19 15:37 UTC (permalink / raw) To: i2c-GZX6beZjE8VD60Wz+7aTrA [-- Attachment #1: Type: text/plain, Size: 239 bytes --] Hi Wolfram. Wolfram Sang wrote: > 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 [-- Attachment #2: pca9665-support.patch --] [-- Type: text/x-patch, Size: 9152 bytes --] diff -ur linux-2.6.26.5/drivers/i2c/algos/i2c-algo-pca.c linux-2.6.26.5-new/drivers/i2c/algos/i2c-algo-pca.c --- linux-2.6.26.5/drivers/i2c/algos/i2c-algo-pca.c 2008-09-08 14:40:20.000000000 -0300 +++ linux-2.6.26.5-new/drivers/i2c/algos/i2c-algo-pca.c 2008-09-19 12:33:48.000000000 -0300 @@ -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 <icampbell-2sJRl1BP9u0AvxtiuMwx3w@public.gmane.org>, " "Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>"); -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.c linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-isa.c --- linux-2.6.26.5/drivers/i2c/busses/i2c-pca-isa.c 2008-09-08 14:40:20.000000000 -0300 +++ linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-isa.c 2008-09-19 12:27:51.000000000 -0300 @@ -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 <icampbell-2sJRl1BP9u0AvxtiuMwx3w@public.gmane.org>"); -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.c linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-platform.c --- linux-2.6.26.5/drivers/i2c/busses/i2c-pca-platform.c 2008-09-08 14:40:20.000000000 -0300 +++ linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-platform.c 2008-09-19 12:28:36.000000000 -0300 @@ -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 <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>"); -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 --- linux-2.6.26.5/drivers/i2c/busses/Kconfig 2008-09-08 14:40:20.000000000 -0300 +++ linux-2.6.26.5-new/drivers/i2c/busses/Kconfig 2008-09-19 10:33:35.000000000 -0300 @@ -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 [-- Attachment #3: Type: text/plain, Size: 157 bytes --] _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 13+ messages in thread
[parent not found: <48D3C74E.1050801-nrw9SyMmU14AvxtiuMwx3w@public.gmane.org>]
* Re: PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c [not found] ` <48D3C74E.1050801-nrw9SyMmU14AvxtiuMwx3w@public.gmane.org> @ 2008-09-20 7:21 ` Wolfram Sang [not found] ` <20080920072131.GB12497-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> 0 siblings, 1 reply; 13+ messages in thread From: Wolfram Sang @ 2008-09-20 7:21 UTC (permalink / raw) To: Marco Aurelio da Costa; +Cc: i2c-GZX6beZjE8VD60Wz+7aTrA [-- Attachment #1.1: Type: text/plain, Size: 10384 bytes --] Hi Marco, > 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. > + 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. > + 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); Please mention what the default is. > + 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 */ 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. > > - 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; 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. > + } 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) > + > + 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) > + > + 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 <icampbell-2sJRl1BP9u0AvxtiuMwx3w@public.gmane.org>, " > "Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>"); > -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.c linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-isa.c > --- linux-2.6.26.5/drivers/i2c/busses/i2c-pca-isa.c 2008-09-08 14:40:20.000000000 -0300 > +++ linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-isa.c 2008-09-19 12:27:51.000000000 -0300 > @@ -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 <icampbell-2sJRl1BP9u0AvxtiuMwx3w@public.gmane.org>"); > -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.c linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-platform.c > --- linux-2.6.26.5/drivers/i2c/busses/i2c-pca-platform.c 2008-09-08 14:40:20.000000000 -0300 > +++ linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-platform.c 2008-09-19 12:28:36.000000000 -0300 > @@ -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? > + (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 <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>"); > -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 > --- linux-2.6.26.5/drivers/i2c/busses/Kconfig 2008-09-08 14:40:20.000000000 -0300 > +++ linux-2.6.26.5-new/drivers/i2c/busses/Kconfig 2008-09-19 10:33:35.000000000 -0300 > @@ -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 > i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org > 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 -- Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 197 bytes --] [-- Attachment #2: Type: text/plain, Size: 157 bytes --] _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 13+ messages in thread
[parent not found: <20080920072131.GB12497-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>]
* Re: PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c [not found] ` <20080920072131.GB12497-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> @ 2008-09-20 11:09 ` Marco Aurelio da Costa [not found] ` <c76dcaf00809200409r7e0420c9rcb83a654d40e217a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 13+ messages in thread From: Marco Aurelio da Costa @ 2008-09-20 11:09 UTC (permalink / raw) To: i2c-GZX6beZjE8VD60Wz+7aTrA Hi Wolfram On Sat, Sep 20, 2008 at 4:21 AM, Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> wrote: >> + 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. You are right. Done. >> + default: >> + printk(KERN_WARNING >> + "%s: Invalid I2C clock speed selected." >> + "Trying default.\n", adap->name); > > Please mention what the default is. Done. >> + 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. >> + 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. Done. >> - 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 i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 13+ messages in thread
[parent not found: <c76dcaf00809200409r7e0420c9rcb83a654d40e217a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c [not found] ` <c76dcaf00809200409r7e0420c9rcb83a654d40e217a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2008-09-20 12:10 ` Marco Aurelio da Costa [not found] ` <c76dcaf00809200510k7e6b4648v630dc33bf6401cca-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 13+ messages in thread From: Marco Aurelio da Costa @ 2008-09-20 12:10 UTC (permalink / raw) To: i2c-GZX6beZjE8VD60Wz+7aTrA [-- Attachment #1: Type: text/plain, Size: 323 bytes --] Hi Wolfram. On Sat, Sep 20, 2008 at 8:09 AM, Marco Aurelio da Costa <costa-nrw9SyMmU14AvxtiuMwx3w@public.gmane.org> wrote: > 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 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: pca9665-support.patch --] [-- Type: text/x-patch; name=pca9665-support.patch, Size: 12365 bytes --] diff -ur linux-2.6.26.5/drivers/i2c/algos/i2c-algo-pca.c linux-2.6.26.5-new/drivers/i2c/algos/i2c-algo-pca.c --- linux-2.6.26.5/drivers/i2c/algos/i2c-algo-pca.c 2008-09-08 14:40:20.000000000 -0300 +++ linux-2.6.26.5-new/drivers/i2c/algos/i2c-algo-pca.c 2008-09-20 09:07:35.000000000 -0300 @@ -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 <icampbell@arcom.com>, " "Wolfram Sang <w.sang@pengutronix.de>"); -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.c linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-isa.c --- linux-2.6.26.5/drivers/i2c/busses/i2c-pca-isa.c 2008-09-08 14:40:20.000000000 -0300 +++ linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-isa.c 2008-09-20 08:53:59.000000000 -0300 @@ -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 <icampbell@arcom.com>"); -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.c linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-platform.c --- linux-2.6.26.5/drivers/i2c/busses/i2c-pca-platform.c 2008-09-08 14:40:20.000000000 -0300 +++ linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-platform.c 2008-09-20 08:25:37.000000000 -0300 @@ -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 <w.sang@pengutronix.de>"); -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 --- linux-2.6.26.5/drivers/i2c/busses/Kconfig 2008-09-08 14:40:20.000000000 -0300 +++ linux-2.6.26.5-new/drivers/i2c/busses/Kconfig 2008-09-19 10:33:35.000000000 -0300 @@ -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 diff -ur linux-2.6.26.5/include/linux/i2c-algo-pca.h linux-2.6.26.5-new/include/linux/i2c-algo-pca.h --- linux-2.6.26.5/include/linux/i2c-algo-pca.h 2008-09-08 14:40:20.000000000 -0300 +++ linux-2.6.26.5-new/include/linux/i2c-algo-pca.h 2008-09-20 08:56:11.000000000 -0300 @@ -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; }; [-- Attachment #3: Type: text/plain, Size: 157 bytes --] _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 13+ messages in thread
[parent not found: <c76dcaf00809200510k7e6b4648v630dc33bf6401cca-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c [not found] ` <c76dcaf00809200510k7e6b4648v630dc33bf6401cca-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2008-09-24 12:45 ` Marco Aurelio da Costa [not found] ` <c76dcaf00809240545k4b7daf53ydbf374a88a5d686a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2008-10-01 17:39 ` Wolfram Sang 1 sibling, 1 reply; 13+ messages in thread From: Marco Aurelio da Costa @ 2008-09-24 12:45 UTC (permalink / raw) To: i2c-GZX6beZjE8VD60Wz+7aTrA Hi Wolfram. Did you have time to look into the patch I sent? Thank you in advance, Marco On Sat, Sep 20, 2008 at 9:10 AM, Marco Aurelio da Costa <costa-nrw9SyMmU14AvxtiuMwx3w@public.gmane.org> wrote: > Hi Wolfram. > > On Sat, Sep 20, 2008 at 8:09 AM, Marco Aurelio da Costa <costa-nrw9SyMmU14AvxtiuMwx3w@public.gmane.org> wrote: >> 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 > _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 13+ messages in thread
[parent not found: <c76dcaf00809240545k4b7daf53ydbf374a88a5d686a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c [not found] ` <c76dcaf00809240545k4b7daf53ydbf374a88a5d686a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2008-09-24 12:57 ` Wolfram Sang 0 siblings, 0 replies; 13+ messages in thread From: Wolfram Sang @ 2008-09-24 12:57 UTC (permalink / raw) To: Marco Aurelio da Costa; +Cc: i2c-GZX6beZjE8VD60Wz+7aTrA [-- Attachment #1.1: Type: text/plain, Size: 495 bytes --] Hi Marco, On Wed, Sep 24, 2008 at 09:45:06AM -0300, Marco Aurelio da Costa wrote: > 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 -- Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 157 bytes --] _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c [not found] ` <c76dcaf00809200510k7e6b4648v630dc33bf6401cca-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2008-09-24 12:45 ` Marco Aurelio da Costa @ 2008-10-01 17:39 ` Wolfram Sang [not found] ` <20081001173909.GG17953-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> 1 sibling, 1 reply; 13+ messages in thread From: Wolfram Sang @ 2008-10-01 17:39 UTC (permalink / raw) To: Marco Aurelio da Costa; +Cc: i2c-GZX6beZjE8VD60Wz+7aTrA [-- Attachment #1.1: Type: text/plain, Size: 15215 bytes --] 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. Reviewed-by: Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> On Sat, Sep 20, 2008 at 09:10:12AM -0300, Marco Aurelio da Costa wrote: > Hi Wolfram. > > On Sat, Sep 20, 2008 at 8:09 AM, Marco Aurelio da Costa <costa-nrw9SyMmU14AvxtiuMwx3w@public.gmane.org> wrote: > > 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.c linux-2.6.26.5-new/drivers/i2c/algos/i2c-algo-pca.c > --- linux-2.6.26.5/drivers/i2c/algos/i2c-algo-pca.c 2008-09-08 14:40:20.000000000 -0300 > +++ linux-2.6.26.5-new/drivers/i2c/algos/i2c-algo-pca.c 2008-09-20 09:07:35.000000000 -0300 > @@ -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.", "\n" is missing. Also, the whole printk should fit into one line. > adap->name); > - pca_data->i2c_clock = I2C_PCA_CON_59kHz; > + return I2C_PCA_CHIP_9665; > + } else { > + printk(KERN_INFO > + "%s: PCA9564 detected.", Here, too. > + 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); Space before "Using". > + 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; Spaces around operators. > > - 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 <icampbell-2sJRl1BP9u0AvxtiuMwx3w@public.gmane.org>, " > "Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>"); > -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.c linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-isa.c > --- linux-2.6.26.5/drivers/i2c/busses/i2c-pca-isa.c 2008-09-08 14:40:20.000000000 -0300 > +++ linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-isa.c 2008-09-20 08:53:59.000000000 -0300 > @@ -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 <icampbell-2sJRl1BP9u0AvxtiuMwx3w@public.gmane.org>"); > -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.c linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-platform.c > --- linux-2.6.26.5/drivers/i2c/busses/i2c-pca-platform.c 2008-09-08 14:40:20.000000000 -0300 > +++ linux-2.6.26.5-new/drivers/i2c/busses/i2c-pca-platform.c 2008-09-20 08:25:37.000000000 -0300 > @@ -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 <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>"); > -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 > --- linux-2.6.26.5/drivers/i2c/busses/Kconfig 2008-09-08 14:40:20.000000000 -0300 > +++ linux-2.6.26.5-new/drivers/i2c/busses/Kconfig 2008-09-19 10:33:35.000000000 -0300 > @@ -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 > diff -ur linux-2.6.26.5/include/linux/i2c-algo-pca.h linux-2.6.26.5-new/include/linux/i2c-algo-pca.h > --- linux-2.6.26.5/include/linux/i2c-algo-pca.h 2008-09-08 14:40:20.000000000 -0300 > +++ linux-2.6.26.5-new/include/linux/i2c-algo-pca.h 2008-09-20 08:56:11.000000000 -0300 > @@ -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: Typo: Not 9964, but 9564 > + * 330000, 288000, 217000, 146000, 88000, 59000, 44000, 36000 > + * For PCA9665, use the frequency you want here. */ > unsigned int i2c_clock; > }; > > _______________________________________________ > i2c mailing list > i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org > http://lists.lm-sensors.org/mailman/listinfo/i2c All the best and thanks for the patch! Wolfram -- Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 197 bytes --] [-- Attachment #2: Type: text/plain, Size: 157 bytes --] _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 13+ messages in thread
[parent not found: <20081001173909.GG17953-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>]
* Re: PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c [not found] ` <20081001173909.GG17953-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> @ 2008-10-02 23:27 ` Marco Aurelio da Costa [not found] ` <c76dcaf00810021627y561e8dbdv5e85b1bc503d1f0b-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 13+ messages in thread From: Marco Aurelio da Costa @ 2008-10-02 23:27 UTC (permalink / raw) To: Wolfram Sang; +Cc: i2c-GZX6beZjE8VD60Wz+7aTrA Hi Wolfram. On Wed, Oct 1, 2008 at 2:39 PM, Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> wrote: > 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. > > 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 i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 13+ messages in thread
[parent not found: <c76dcaf00810021627y561e8dbdv5e85b1bc503d1f0b-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c [not found] ` <c76dcaf00810021627y561e8dbdv5e85b1bc503d1f0b-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2008-10-14 13:08 ` Wolfram Sang [not found] ` <c76dcaf00810140614i28e49f27xb9d4c503144606b0@mail.gmail.com> 0 siblings, 1 reply; 13+ messages in thread From: Wolfram Sang @ 2008-10-14 13:08 UTC (permalink / raw) To: Marco Aurelio da Costa; +Cc: i2c-GZX6beZjE8VD60Wz+7aTrA [-- Attachment #1.1: Type: text/plain, Size: 400 bytes --] Hi Marco, On Thu, Oct 02, 2008 at 08:27:05PM -0300, Marco Aurelio da Costa wrote: > 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 -- Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 197 bytes --] [-- Attachment #2: Type: text/plain, Size: 157 bytes --] _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 13+ messages in thread
[parent not found: <c76dcaf00810140614i28e49f27xb9d4c503144606b0@mail.gmail.com>]
[parent not found: <c76dcaf00810140614i28e49f27xb9d4c503144606b0-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [i2c] PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c [not found] ` <c76dcaf00810140614i28e49f27xb9d4c503144606b0-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2008-12-17 11:39 ` Wolfram Sang [not found] ` <20081217113940.GE3382-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> 0 siblings, 1 reply; 13+ messages in thread From: Wolfram Sang @ 2008-12-17 11:39 UTC (permalink / raw) To: Marco Aurelio da Costa; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA [-- Attachment #1: Type: text/plain, Size: 428 bytes --] Hi Marco, On Tue, Oct 14, 2008 at 10:14:03AM -0300, Marco Aurelio da Costa wrote: > > 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 -- Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 197 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
[parent not found: <20081217113940.GE3382-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>]
* Re: [i2c] PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c [not found] ` <20081217113940.GE3382-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> @ 2009-01-14 19:39 ` Wolfram Sang 0 siblings, 0 replies; 13+ messages in thread From: Wolfram Sang @ 2009-01-14 19:39 UTC (permalink / raw) To: Marco Aurelio da Costa; +Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA [-- Attachment #1: Type: text/plain, Size: 534 bytes --] On Wed, Dec 17, 2008 at 12:39:40PM +0100, Wolfram Sang wrote: > Hi Marco, > > On Tue, Oct 14, 2008 at 10:14:03AM -0300, Marco Aurelio da Costa wrote: > > > > 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 -- Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de Pengutronix - Linux Solutions for Science and Industry [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 197 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2009-01-14 19:39 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-19 14:22 PCA9665 support added to i2c-algo-pca and i2c-pca-isa.c Marco Aurelio da Costa
[not found] ` <48D3B5B7.1060402-nrw9SyMmU14AvxtiuMwx3w@public.gmane.org>
2008-09-19 14:55 ` Wolfram Sang
[not found] ` <20080919145500.GH4307-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2008-09-19 15:37 ` Marco Aurelio da Costa
[not found] ` <48D3C74E.1050801-nrw9SyMmU14AvxtiuMwx3w@public.gmane.org>
2008-09-20 7:21 ` Wolfram Sang
[not found] ` <20080920072131.GB12497-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2008-09-20 11:09 ` Marco Aurelio da Costa
[not found] ` <c76dcaf00809200409r7e0420c9rcb83a654d40e217a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-09-20 12:10 ` Marco Aurelio da Costa
[not found] ` <c76dcaf00809200510k7e6b4648v630dc33bf6401cca-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-09-24 12:45 ` Marco Aurelio da Costa
[not found] ` <c76dcaf00809240545k4b7daf53ydbf374a88a5d686a-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-09-24 12:57 ` Wolfram Sang
2008-10-01 17:39 ` Wolfram Sang
[not found] ` <20081001173909.GG17953-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2008-10-02 23:27 ` Marco Aurelio da Costa
[not found] ` <c76dcaf00810021627y561e8dbdv5e85b1bc503d1f0b-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-10-14 13:08 ` Wolfram Sang
[not found] ` <c76dcaf00810140614i28e49f27xb9d4c503144606b0@mail.gmail.com>
[not found] ` <c76dcaf00810140614i28e49f27xb9d4c503144606b0-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-12-17 11:39 ` [i2c] " Wolfram Sang
[not found] ` <20081217113940.GE3382-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
2009-01-14 19:39 ` Wolfram Sang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox