Operating i2c at 100 kHz


I want to operate i2c at 100KHz. Right now the frequency is set at 400KHz. How can I change it to 100kHz.

Thanks in advance

I don’t know much about DTS-files but at least they seem to specify the i2c bus speeds:


Any idea about how to access the file? I am not able to find it.

DTS files are compiled into DTB files. This is part of the kernel source. Here’s an article which can get you started:

It should be better to overwrite the clock in “arch/arm/boot/dts/tegra124-jetson_tk1-pm375-000-c00-00.dts” than to modify in “arch/arm/boot/dts/tegra124.dtsi”.

I’ve found some pretty good instructions for modifying the i2c speeds using the dtb files. However, I’m curious whether there’s a way to set the I2C speeds by rmmod’ing a kernel module and reloading with a new speed setting…anyone know how that might be accomplished? The DTB files seem like a clunky way to test different speeds.

" The DTB files seem like a clunky way to test different speeds. "
Yes, from the perspective of trying different speeds yes it is frustrating. However, how often in a real world system does the I2C clock speed change?

FYI If you are finding the whole change/re-flash/test frustrating, you may find network booting quicker than flashing the eMMC. You can just change the dtb file on the netboot server and then re-boot the Jetson - much faster.

The concept of the Device Tree was explained to me :
instead of customising the drivers for each hardware platform, Linux drivers are now written to be generic. The hardware platform specifics are now contained in the DT (the DTB file) and when the system boots, it uses the DTB to enumerate the correct hardware. This stops all the hundreds of custom drivers needed for every hardware platform there is out there.

Unfortunately Nvidia have broken this concept in L4T but customising the drivers for Jetson. Really bad for someone like me, relatively new to Linux coding and still learning.

Interesting point about DTB. However, if you’ve ever played around with PC BIOS and DSDT tables, you’ll find they are similarly complex. On x86(-64), the ACPI tables generally enumerate device hardware for the OS. Intel releases iasl to compile DSDTs, whereas we use upstream dtc to compile our .dtb files.

DTB was a Linux Foundation-approved attempt to address all the various, exotic hardware in the many-vendor world of non x86 SoCs that run Linux. In order to run the same kernel with different onboard peripherals enabled/selected, DTB is necessary.

There are some ways to change the I2C clock, like mentioned before in this thread.

  1. DTS. Check the file @arch/arm/boot/dts/tegra124-soc.dtsi and the clock-frequency in i2cx part. that’s the general implementation in Linux kernel. (After changing the DTS and re-compiling the DTB file, it’s not necessary to re-flash the whole device. Just replace the corresponding dtb file in root-fs, reboot the device, and the new DTB will take effect.)
  2. Check the driver @ drivers/i2c/busses/i2c-tegra.c. ‘bus_clk_rate’ will be intialized in probe function, from platform_data, or DTB (if platform_data not available.) It’s not good to make i2c-adaptor as a loadable module for there are a lot I2C devices attached to the adaptor. (Also, replacing the updated zImage in root-fs is also a faster way to debug a new kernel than re-flashing the device.)

Hope it can help.


You can set a new speed at run time simply by echoing to /sys/bus/i2c/devices/i2c-/bus_clk_rate

echo 10000 > /sys/bus/i2c/devices/i2c-/bus_clk_rate

I added this line to our rc.local for some testing and to avoid having to touch the DTB.

@rtennill I tried to do echo… but i got “bash: /sys/bus/i2c/devices/i2c-1/bus_clk_rate: Permission denied” even with sudo. Any ideas?

1 Like