* 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
* 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
* 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
* 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
* 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
* 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
* 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
* 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
* 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
* 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
* 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
* 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