I want to slow down my I2C bus. I have read in various places that it's ... hard, or impossible.

The default baudrate is 100kB; most devices accept up to 400kB, and some times more (up to 4MB). I want to slow down quiet much; down to 500Bauds.

I tried to do it the hard way: kernel hacking. After reading the driver source drivers/i2c/busses/i2c-bcm2708.c I have updated my kernel conf with

CONFIG_I2C_BCM2708_BAUDRATE=500

rebuild, and reboot.

Dmesg confirms that I have half a kilo:

[ 4.912334] bcm2708_i2c bcm2708_i2c.0: BSC0 Controller at 0x20205000 (irq 79) (baudrate 0k)

[ 5.280053] bcm2708_i2c bcm2708_i2c.1: BSC1 Controller at 0x20804000 (irq 79) (baudrate 0k)

0k is fine considering this:

dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %dk)\n",

pdev->id, (unsigned long)regs->start, irq, baudrate/1000);

0.5 is rounded by %d to 0. Fine for me. zcat config.gz confirms 500.

To me, at 500B, i2cdetect -y 1 should take at least 2.3s.

The problem is that it takes only 0.270s aprox. What is to me ... way too fast.

With default kernel at 100k, the average execution time is 0.045s.

So, with lower value, the scan takes only 5 more times, when it should take 200 more time. Changing the value obviously has an impact, but not big enough to me.

I don't have scope to check, and I don't think any LED would let me see such a small difference.

Is there a bug in the kernel ? did I hit the highest limit of the divider ?

cdiv = bus_hz / baudrate;

I have no clue what the bus freq is, or the cdiv accepted values.

### Re: Can not change I2C baud rate ?

This is quiet strange to me ...

definitely a bug ... somewhere.

And definitely gonna do my own 500B manually: bitbanging :/ again :/ once more :'(

root@raspberrypi1:~# for i in 100000 50000 33000 10000 5000 3300 1000 500 333 100 50 33 ; do rmmod i2c_bcm2708 ; sleep 1 ; modprobe i2c_bcm2708 baudrate=$i ; sleep 1 ; echo "* $i" ; for j in `seq 5` ; do { time i2cdetect -y 1 ; } 2>&1 >/dev/null | grep real ; done ; done

* 100000

real 0m0.034s

real 0m0.032s

real 0m0.030s

real 0m0.028s

real 0m0.035s

* 50000

real 0m0.045s

real 0m0.047s

real 0m0.049s

real 0m0.043s

real 0m0.043s

* 33000

real 0m0.062s

real 0m0.059s

real 0m0.057s

real 0m0.063s

real 0m0.059s

* 10000

real 0m0.160s

real 0m0.155s

real 0m0.159s

real 0m0.155s

real 0m0.159s

* 5000

real 0m0.297s

real 0m0.301s

real 0m0.296s

real 0m0.305s

real 0m0.300s

* 3300

real 0m0.075s

real 0m0.077s

real 0m0.079s

real 0m0.071s

real 0m0.071s

* 1000

real 0m0.320s

real 0m0.315s

real 0m0.317s

real 0m0.321s

real 0m0.317s

* 500

real 0m0.251s

real 0m0.246s

real 0m0.252s

real 0m0.249s

real 0m0.247s

* 333

real 0m0.187s

real 0m0.188s

real 0m0.189s

real 0m0.187s

real 0m0.185s

* 100

real 0m0.074s

real 0m0.071s

real 0m0.068s

real 0m0.068s

real 0m0.076s

* 50

real 0m0.122s

real 0m0.124s

real 0m0.126s

real 0m0.129s

real 0m0.130s

* 33

real 0m0.242s

real 0m0.234s

real 0m0.237s

real 0m0.240s

real 0m0.236s

root@raspberrypi1:~#

definitely a bug ... somewhere.

And definitely gonna do my own 500B manually: bitbanging :/ again :/ once more :'(

root@raspberrypi1:~# for i in 100000 50000 33000 10000 5000 3300 1000 500 333 100 50 33 ; do rmmod i2c_bcm2708 ; sleep 1 ; modprobe i2c_bcm2708 baudrate=$i ; sleep 1 ; echo "* $i" ; for j in `seq 5` ; do { time i2cdetect -y 1 ; } 2>&1 >/dev/null | grep real ; done ; done

* 100000

real 0m0.034s

real 0m0.032s

real 0m0.030s

real 0m0.028s

real 0m0.035s

* 50000

real 0m0.045s

real 0m0.047s

real 0m0.049s

real 0m0.043s

real 0m0.043s

* 33000

real 0m0.062s

real 0m0.059s

real 0m0.057s

real 0m0.063s

real 0m0.059s

* 10000

real 0m0.160s

real 0m0.155s

real 0m0.159s

real 0m0.155s

real 0m0.159s

* 5000

real 0m0.297s

real 0m0.301s

real 0m0.296s

real 0m0.305s

real 0m0.300s

* 3300

real 0m0.075s

real 0m0.077s

real 0m0.079s

real 0m0.071s

real 0m0.071s

* 1000

real 0m0.320s

real 0m0.315s

real 0m0.317s

real 0m0.321s

real 0m0.317s

* 500

real 0m0.251s

real 0m0.246s

real 0m0.252s

real 0m0.249s

real 0m0.247s

* 333

real 0m0.187s

real 0m0.188s

real 0m0.189s

real 0m0.187s

real 0m0.185s

* 100

real 0m0.074s

real 0m0.071s

real 0m0.068s

real 0m0.068s

real 0m0.076s

* 50

real 0m0.122s

real 0m0.124s

real 0m0.126s

real 0m0.129s

real 0m0.130s

* 33

real 0m0.242s

real 0m0.234s

real 0m0.237s

real 0m0.240s

real 0m0.236s

root@raspberrypi1:~#

### Re: Can not change I2C baud rate ?

* 3900

real 0m0.380s

real 0m0.377s

real 0m0.383s

real 0m0.377s

real 0m0.381s

* 3800

real 0m0.020s

real 0m0.016s

real 0m0.021s

real 0m0.015s

real 0m0.020s

* 3815

real 0m0.394s

real 0m0.385s

real 0m0.390s

real 0m0.385s

real 0m0.388s

* 3814

real 0m0.014s

real 0m0.018s

real 0m0.014s

real 0m0.018s

real 0m0.014s

real 0m0.380s

real 0m0.377s

real 0m0.383s

real 0m0.377s

real 0m0.381s

* 3800

real 0m0.020s

real 0m0.016s

real 0m0.021s

real 0m0.015s

real 0m0.020s

* 3815

real 0m0.394s

real 0m0.385s

real 0m0.390s

real 0m0.385s

real 0m0.388s

* 3814

real 0m0.014s

real 0m0.018s

real 0m0.014s

real 0m0.018s

real 0m0.014s

### Re: Can not change I2C baud rate ?

I am now checking signal with a scope:

3815 produces a good signal around expected frequency.

1.5M produces a good signal (baud duration has the expected time length). But ... there is a but. The frame is sent at the requested rate, but words are not consecutive at all: words are seperated by a long lenght of silence. The duration of silence is about 7 times the word length. With my scope with basetime at 5us/d, a word is a bit more than 1 square, and the distance between two words is 7 squares. So this speed is technically ok, but not usefull, not efficient. Still, this test was required for a few things. I have tried with MCP23017 and MCP23018, and they stopped answering ack between 1.65M and 1.85M depending on bus length (less than 10cm, ~4").

Above 2MB, the signal is electrically correct, but slower than expected. 3MB is only 15% faster than 1.5M ... instead of 50%.

At 500k, the distance between words is the same duration than the word itself. Same at 300k.

Below 200k, the distance between words is shorter than the word duration.

So, 1.5M and 200k have roughly the same information efficiency. And 200k is the highest reasonable and efficient value.

3815 is the smallest one, for slow lines.

3814 does produce a fast signal, but my scope can not properly soom and sync on it.

It is now obvious to me that values below 3815 trigger a kernel bug. Either in kernel, or in hardware, but I rather think about kernel issue.

To reach baud rates below this magical limit, I will have to write again bit banging manually.

I2C now has no more secret for any one around here

3815 produces a good signal around expected frequency.

1.5M produces a good signal (baud duration has the expected time length). But ... there is a but. The frame is sent at the requested rate, but words are not consecutive at all: words are seperated by a long lenght of silence. The duration of silence is about 7 times the word length. With my scope with basetime at 5us/d, a word is a bit more than 1 square, and the distance between two words is 7 squares. So this speed is technically ok, but not usefull, not efficient. Still, this test was required for a few things. I have tried with MCP23017 and MCP23018, and they stopped answering ack between 1.65M and 1.85M depending on bus length (less than 10cm, ~4").

Above 2MB, the signal is electrically correct, but slower than expected. 3MB is only 15% faster than 1.5M ... instead of 50%.

At 500k, the distance between words is the same duration than the word itself. Same at 300k.

Below 200k, the distance between words is shorter than the word duration.

So, 1.5M and 200k have roughly the same information efficiency. And 200k is the highest reasonable and efficient value.

3815 is the smallest one, for slow lines.

3814 does produce a fast signal, but my scope can not properly soom and sync on it.

It is now obvious to me that values below 3815 trigger a kernel bug. Either in kernel, or in hardware, but I rather think about kernel issue.

To reach baud rates below this magical limit, I will have to write again bit banging manually.

I2C now has no more secret for any one around here