Search code examples
linuxlinux-kernellinux-device-driveri2c

U-Boot i2c detects my device (70) but Linux i2c does not. Why?


I am in the process of migrating from Linux 3.10 to a slightly newer version, Linux 4.4.8. After the migration it seems that i2c can no longer see some of my hardware. The hardware itself has not changed whatsoever and works fine in the previous linux version (3.10).

The problem I am running into now is that my i2c commands are no longer working.

When trying to write to the device I get a failed write.

[]# i2cset -y 0 0x70 0 1 b
Error: Write failed

Then I decided to run the i2cdetect to determine what can be seen and this is the output i get

In Linux:

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

In U-Boot:

[u-boot]# i2c probe
Valid chip addresses: 20 21 64 70

What would be the reason that I can see my device in U-Boot but I can't see my device in Linux?

I suspect the device tree might need to be modified? But I checked the old dtsi files and nothing is different between the i2c0's in the two Linux versions...

i2cdump gives all X's for output

[]# i2cdump -y 0 0x70
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
10: XX XX XX XX XX XX XX XX XX XX...

i2c host controller: linux-4-4-8/drivers/i2c/busses/i2c-mv64xxx.c

Devices

0x20, 0x21: PCA9555 IO Port Expanders

0x70: PCA9548A i2c Multiplexer


Solution

  • The newer kernel has a different parent dtsi file that defines various mpp's for pinctrl

    The dts file I was using contained some Ethernet devices that were defined but were never used by us, we piggy backed off another team's device tree since our hardware was ALMOST identical. Those ethernet's used the following mdio

    mdio@72004 {
        pinctrl-names = "default";
        pinctrl-0 = <&mdio_pins>; //<==== This was the problem
    
        phy0: ethernet-phy@0 {
            reg = <0>;
        };
    };
    

    The mdio uses &mdio_pins and, in the newer kernel, is defined as

    mdio_pins: mdio-pins {
        marvell,pins = "mpp4", "mpp5";
        marvell,function = "ge";
    };
    

    It just so happens to be that the gpio reset for my device is mpp5.

    I changed the ethernet section of the device tree to the following

    ethernet@70000 {
        status = "disabled";
    };
    
    mdio@72004 {
        status = "disabled";
    };
    
    ethernet@30000 {
        status = "disabled";
    };
    

    This solved the problem of the device not showing up in i2cdetect and the hardware is working as before.

    It was my own fault for assuming the device tree I inherited was concrete in definition of the hardware being used.