[SOLVED] I2C driver is not loading

Hello all,

I am having troubles with I2C driver. The problem is that Linux is not loading the driver. Here are some facts and tryouts:

  • I am using custom design board based on Enclustra Mercury SA1 SoM.
  • I2C is properly enabled in Quartus, I am using I2C0 (which should be shared with EEPROM and RTC on Enclustra module).
  • During boot U-boot reports I2C: ready.
  • Linux kernel is Linux 4.7.0 armv7l GNU/Linux - Altera’s linux-socfpga branch rel_socfpga-4.7_16.09.03_pr (I have tried with 15.09.03 also)
  • Linux is compiled on Ubuntu 16.04
  • rootfs is based on busybox buildroot 2016.08
  • toolchain is gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf (I have tried with gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux also)
  • I2C is enabled in kernel configuration:
    • Device Drivers
      * <>I2C support
      * [
      ] I2C device interface
      * I2C Hardware Bus support -->
      * <*> Synopsys DesignWare Platform
  • During Linux boot I can see the line i2c /dev entries driver

When I check in /dev/ folder, there is no i2c-dev or anything like that. I2C tools returns following:

i2cdetect 0
Error: Could not open file `/dev/i2c-0' or `/dev/i2c/0': No such file or directory

There is no/lib/modules folder, where I assume that module should be stored, or /lib/modules.d

When I try to search i2c in the system, I get the following:

# find . -name *i2c*
./sys/bus/i2c
./sys/bus/i2c/drivers/i2c-slave-eeprom
./sys/bus/platform/drivers/i2c_designware
./sys/class/i2c-dev
./sys/class/i2c-adapter
./sys/firmware/devicetree/base/sopc@0/i2c@0xffc04000
./sys/firmware/devicetree/base/sopc@0/i2c@0xffc04000/i2c-scl-falling-time-ns
./sys/firmware/devicetree/base/sopc@0/i2c@0xffc04000/i2c-sda-falling-time-ns
./sys/firmware/devicetree/base/sopc@0/i2c@0xffc05000
./sys/firmware/devicetree/base/sopc@0/i2c@0xffc06000
./sys/firmware/devicetree/base/sopc@0/i2c@0xffc07000
./usr/sbin/i2cget
./usr/sbin/i2cdump
./usr/sbin/i2cdetect
./usr/sbin/i2cset

Modprobe returns following:
# modprobe i2c-dev modprobe: can't change directory to '/lib/modules': No such file or directory

Does anyone knows where could be the problem. I’m struggling with this for quite some time now, and I have been searching and trying different solutions, but with no success. I am relatively new to Linux, so any help would be much appreciated.

Is there an entry in your device tree for the I2C, with the proper compatible string? If not, the driver won’t know there’s an I2C device to use. Check out https://rocketboards.org/foswiki/view/Documentation/GSRDV151DeviceTreeGenerator for a decent overview of the device tree and how to generate one.

-Tim

Hello Tim,

this is the entry for I2C in my device tree (.dts). The device tree was automatically generated by Quartus, I haven’t modified it so far:

hps_0_i2c0: i2c@0xffc04000 {
		compatible = "snps,designware-i2c-16.0", "snps,designware-i2c";
		reg = <0xffc04000 0x00000100>;
		interrupt-parent = <&hps_0_arm_gic_0>;
		interrupts = <0 158 4>;
		clocks = <&l4_sp_clk>;
		emptyfifo_hold_master = <1>;	/* embeddedsw.dts.params.emptyfifo_hold_master type NUMBER */
		status = "okay";	/* embeddedsw.dts.params.status type STRING */
		#address-cells = <1>;
		#size-cells = <0>;
		speed-mode = <0>;	/* appended from boardinfo */
		i2c-sda-falling-time-ns = <5000>;	/* appended from boardinfo */
		i2c-scl-falling-time-ns = <5000>;	/* appended from boardinfo */

		lcd: newhaven,nhd-0216k3z-nsw-bbw@0x28 {
			compatible = "newhaven,nhd-0216k3z-nsw-bbw";
			reg = <0x00000028>;
			height = <2>;	/* appended from boardinfo */
			width = <16>;	/* appended from boardinfo */
			brightness = <8>;	/* appended from boardinfo */
		}; //end newhaven,nhd-0216k3z-nsw-bbw@0x28 (lcd)

		eeprom: atmel,24c32@0x51 {
			compatible = "atmel,24c32";
			reg = <0x00000051>;
			pagesize = <32>;	/* appended from boardinfo */
		}; //end atmel,24c32@0x51 (eeprom)

		rtc: dallas,ds1339@0x68 {
			compatible = "dallas,ds1339";
			reg = <0x00000068>;
		}; //end dallas,ds1339@0x68 (rtc)
	}; //end i2c@0xffc04000 (hps_0_i2c0)

I’m a hardware guy, so my driver debug chops are lacking for sure, but…

Do you have the devices listed in the tree on your board: lcd, eeprom, rtc? If so, the easiest one to try is the rtc. If hwclock at the linux prompt works, your I2C bus is working. A line similar to this:

[ 1.963425] rtc-ds1307 0-0068: rtc core: registered ds1339 as rtc0

should show up in your kernel boot spew if the rtc driver is installed and finding the rtc device.

You might also try setting the kernel message log level to debug and see if there’s any additional information in the spew.

I’m not familiar with the Mercury SoM, but is your board close enough to the default configuration you could load a demo kernel, and root fs for that board, keeping your FPGA load and device tree? This might help determine whether the problem is FPGA/device tree or kernel/driver.

-tim

Hi Tim,

Thanks for your support.

Actually, I have tried to add another driver file name in device tree. As you can see from my first post, find command did found designware driver, but named i2c_designware. In device tree it is says designware-i2c. So adding new compatible driver name did load the driver now. I get i2c-0 in /dev/. I’m still not clear why is this name automatically generated.

But, as you suggested, I’m still not able to get rtc working:
[ 1.165974] rtc-ds1307: probe of 0-0068 failed with error -5

And weird thing is that RTC line is just before this:
[ 1.171694] i2c /dev entries driver

I’ve again tried i2ctools, it scans but doesn’t detect any devices (and skips devices declared in device tree). When I checked the bus with oscilloscope, I didn’t record any activity during scan. And scan is finished instantly.

I will try your other recommendations and let you know.

Darko.

Hmmm… my device tree has the compatible line
compatible = "snps,designware-i2c";
as well, and I don’t have issues. I’m running kernel 4.4 from linux-fpga in altera-opensource on github. Perhaps the driver in 4.7 has changed the compatible name? You can check the driver source in the kernel tree and see.

U-boot has I2C tools as well (if they’re compiled in) which you can use to see if the bus is active at all.

Hold down a key during boot from power-up or reset, and at the u-boot prompt enter help to see if there are I2C tools built-in. In the command list you should see a line that looks like this:

i2c - I2C sub-system

If it’s there, enter i2c help for a list of commands for the I2C subsystem. If you try i2c probe it will list the I2C devices it can reach.

u-boot ->i2c probe Valid chip addresses: 17 1F 28 29 2C 55 68

Essentially it sends a read to all the 7 bit I2C addresses and looks for ack/nack from each. Those with an ack get listed. It’s not perfect, as i have a device on my board that it doesn’t see, even though the device is working fine. It will, however talk to the device if I use the i2c md or i2c mw commands.

Try reading from the rtc device and see if you can get a response, that should at least eliminate board & device problems.

-Tim

I have tried I2C tools from U-boot, probing and reading from specific device - no results.

Maybe I need to enable something extra in I2C controller during boot? I had to do similar thing for Ethernet controller in u-boot script, but this was to enable external PHY through gpio:

mw.l 0xFF709000 0x8000 2
mw.l 0xFF709000 0x8000 1
mw.l 0xFF709004 0x8000 1

I have looked through Technical Reference Manual, but I’m not sure for I2C… Do you have something extra in your u-boot script?

And regarding kernel version, I have been running 4.1 before, and had same problem.

Darko

If you know the device is there, and should be working, it’s probably a pre-loader issue if u-boot can’t find it. Do you see scl/sda toggling with a scope when you try probing with u-boot? If not, it’s almost certainly a pre-loader issue. Make sure the pre-loader is generated with the output from your design, and that your BSEL pins are pointing to the right place to get it.

-Tim

Great point Tim!

I have played around with u-boot, and noticed that I2C was held in reset. All I2C registers were set to 0.
Then I manually de-asserted it, and got good values in registers. But still after I2C probing there was nothing on oscilloscope.

In the meantime you posted reply with pre-loader issue, and after re-compiling the pre-loader, now I can see transmission on scope, as well as:

SOCFPGA_CYCLONE5 # i2c probe
Valid chip addresses: 57 5C 6F

Linux has booted, and now shows
[ 1.142516] rtc-ds1307 0-006f: rtc core: registered ds1339 as rtc0

and i2c tools:

# i2cdetect -y -r 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- 57 -- -- -- -- UU -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- UU
70: -- -- -- -- -- -- -- --

So, to sum up: At first I had my system running without I2C enabled in Qsys, and later I enabled it. I did generate new device tree, but left the old pre-loader, which caused all the problems.

Thank you again for your time and help!

Darko

1 Like

Awesome! Glad to be of help.

-Tim