Raspberry Pi compute 4 - add I2C to device tree (solved)

Hi
My issue is that the i2c1 is not seen on my device in nixos.
I have tried adding the overlay to the tree but it does not add the overlay it compiles with some warnings, and adds my uart3 and uart5 the mdio fix and the emmc fix and adds ads1113 device.
The objective is to turn on the i2c and get access to the adc i2c chip.
here is my config based in the dwc2 fix.
I also tried splitting out into a seperate i2c.nix file with exactly the same results.

  boot.kernelPackages = pkgs.linuxPackages_rpi4;
  hardware.deviceTree.enable = true;
  hardware.deviceTree.filter = "bcm2711-rpi-*.dtb";
  hardware.raspberry-pi."4".dwc2.enable = true; #  also enable uart3 ,uart5, mdio ,emmc Wave share io board.
  hardware.raspberry-pi."4".dwc2.dr_mode = "host";
  hardware.i2c.enable=true;
    # Required for the Wireless firmware
  hardware.enableRedistributableFirmware = true;

and the dwc2.nix that hangs it all together.

{ config, lib, pkgs, ... }:

let
  cfg = config.hardware.raspberry-pi."4".dwc2;
in
{
  options.hardware = {
    raspberry-pi."4".dwc2 = {
      enable = lib.mkEnableOption ''
        Enable the UDC controller to support USB OTG gadget functions.

        In order to verify that this works, connect the Raspberry Pi with
        another computer via the USB C cable, and then do one of:

        - `modprobe g_serial`
        - `modprobe g_mass_storage file=/path/to/some/iso-file.iso`

        On the Raspberry Pi, `dmesg` should then show success-indicating output
        that is related to the dwc2 and g_serial/g_mass_storage modules.
        On the other computer, a serial/mass-storage device should pop up in
        the system logs.

        For more information about what gadget functions exist along with handy
        guides on how to test them, please refer to:
        https://www.kernel.org/doc/Documentation/usb/gadget-testing.txt
      '';
      dr_mode = lib.mkOption {
        type = lib.types.enum [ "host" "peripheral" "otg" ];
        default = "otg";
        description = ''
          Dual role mode setting for the dwc2 USB controller driver.
        '';
      };
    };
  };

  config = lib.mkIf cfg.enable {
    # Configure for modesetting in the device tree
    hardware.deviceTree = {
      overlays = [
        # this *should* be equivalent to (which doesn't work):
        # https://github.com/raspberrypi/linux/blob/bad3872df40dd9a4ba7ff239c17288a7a84a80f9/arch/arm/boot/dts/overlays/dwc2-overlay.dts
        # but actually it's obtained using
        # dtc -I dtb -O dts ${config.hardware.deviceTree.kernelPackage}/dtbs/overlays/dwc2.dtbo
        # (changes: modified top-level "compatible" field)
        # which is slightly different and works
        {
          name = "dwc2-overlay";
          dtsText = ''
            /dts-v1/;
            /plugin/;

            / {
              compatible = "brcm,bcm2711";

              fragment@0 {
                target = <&usb>;
                #address-cells = <0x01>;
                #size-cells = <0x01>;

                __overlay__ {
                  compatible = "brcm,bcm2835-usb";
                  dr_mode = "${cfg.dr_mode}";
                  g-np-tx-fifo-size = <0x20>;
                  g-rx-fifo-size = <0x22e>;
                  g-tx-fifo-size = <0x200 0x200 0x200 0x200 0x200 0x100 0x100>;
                  status = "okay";
                  phandle = <0x01>;
                };
              };
            };
          '';
        }
        { name = "uart3-overlay";
          dtsText = ''
            /dts-v1/;
            /plugin/;
            / {
              compatible = "brcm,bcm2711";

              fragment@0 {
                target = <0xffffffff>;

                __overlay__ {
                        pinctrl-names = "default";
                        pinctrl-0 = <0xffffffff>;
                        status = "okay";
                        };
              };

              fragment@1 {
                target = <0xffffffff>;

                __dormant__ {
                        brcm,pins = <0x04 0x05 0x06 0x07>;
                        brcm,pull = <0x00 0x02 0x02 0x00>;
                      };
              };

              __overrides__ {
                ctsrts = [00 00 00 00 3d 31 00];
              };

              __fixups__ {
                uart3 = "/fragment@0:target:0";
                uart3_pins = "/fragment@0/__overlay__:pinctrl-0:0\0/fragment@1:target:0";
              };
           };
           '';
        }
        { name = "uart5-overlay";
          dtsText = ''

            /dts-v1/;
            /plugin/;
            / {
                    compatible = "brcm,bcm2711";

                    fragment@0 {
                            target = <0xffffffff>;

                            __overlay__ {
                                    pinctrl-names = "default";
                                    pinctrl-0 = <0xffffffff>;
                                    status = "okay";
                            };
                    };

                    fragment@1 {
                            target = <0xffffffff>;

                            __dormant__ {
                                    brcm,pins = <0x0c 0x0d 0x0e 0x0f>;
                                    brcm,pull = <0x00 0x02 0x02 0x00>;
                            };
                    };

                    __overrides__ {
                            ctsrts = [00 00 00 00 3d 31 00];
                    };

                    __fixups__ {
                            uart5 = "/fragment@0:target:0";
                            uart5_pins = "/fragment@0/__overlay__:pinctrl-0:0\0/fragment@1:target:0";
                    };
            };
            '';

        }
        { name = "mdio-overlay";
          dtsText = ''

            /dts-v1/;
            /plugin/;
            / {
                    compatible = "brcm,bcm2711";

     
                    fragment@0 {
                             target = <&phy1>;

                             __overlay__ {
                                  reg = <0x00>;
                                };
                    			};    
             };
            '';

        }
        { name = "emmc-overlay";
          dtsText = ''

            /dts-v1/;
            /plugin/;
            / {
                    compatible = "brcm,bcm2711";

     
                    fragment@0 {
                            target = <&emmc2bus>;

                             __overlay__ {
                                  compatible = "simple-bus";
                                  dma-ranges = <0x00 0x00000000 0x00 0x00 0xfc000000>;
                                };
                    			};    
             };
            '';

        }
        { name ="i2c1-overlay";
        dtsText =''
        /dts-v1/;
        /plugin/;

        / {
                compatible = "brcm,bcm2835";

                fragment@0 {
                        target = <0xffffffff>;

                        __overlay__ {
                                status = "okay";
                                pinctrl-names = "default";
                                pinctrl-0 = <0xffffffff>;
                        };
                };

                fragment@1 {
                        target = <0xffffffff>;

                        __overlay__ {
                                brcm,pins = <0x02 0x03>;
                                brcm,function = <0x04>;
                                phandle = <0x01>;
                        };
                };

                fragment@2 {
                        target = <0xffffffff>;

                        __dormant__ {
                                brcm,pins = <0x2c 0x2d>;
                                brcm,function = <0x06>;
                                phandle = <0x02>;
                        };
                };

                fragment@3 {
                        target = <0xffffffff>;

                        __dormant__ {
                                compatible = "brcm,bcm2708-i2c";
                        };
                };

                __overrides__ {
                        pins_2_3 = [00 00 00 00 3d 31 21 32 00];
                        pins_44_45 = [00 00 00 00 21 31 3d 32 00];
                        combine = [00 00 00 00 21 33 00];
                };

                __symbols__ {
                        pins1 = "/fragment@1/__overlay__";
                        pins2 = "/fragment@2/__dormant__";
                };

                __fixups__ {
                        i2c1 = "/fragment@0:target:0\0/fragment@3:target:0";
                        i2c1_pins = "/fragment@0/__overlay__:pinctrl-0:0\0/fragment@1:target:0\0/fragment@2:target:0";
                };
            };
             '';
        }
        { name = "ads1113-overlay";
          dtsText = ''

          /dts-v1/;
          /plugin/;
          / {
                  compatible = "brcm,bcm2835";

                  fragment@0 {
                          target = < 0xffffffff >;

                          __overlay__ {
                                  #address-cells = < 0x01 >;
                                  #size-cells = < 0x00 >;
                                  status = "okay";

                                  ads1115 {
                                          compatible = "ti,ads1113";
                                          status = "okay";
                                          #address-cells = < 0x01 >;
                                          #size-cells = < 0x00 >;
                                          reg = < 0x48 >;
                                          phandle = < 0x01 >;
                                  };
                          };
                  };

                  fragment@1 {
                          target = < 0x01 >;

                          __dormant__ {
                                  #address-cells = < 0x01 >;
                                  #size-cells = < 0x00 >;

                                  channel_a {
                                          reg = < 0x04 >;
                                          ti,gain = < 0x01 >;
                                          ti,datarate = < 0x07 >;
                                          phandle = < 0x02 >;
                                  };
                          };
                  };

                  fragment@2 {
                          target = < 0x01 >;

                          __dormant__ {
                                  #address-cells = < 0x01 >;
                                  #size-cells = < 0x00 >;

                                  channel_b {
                                          reg = < 0x05 >;
                                          ti,gain = < 0x01 >;
                                          ti,datarate = < 0x07 >;
                                          phandle = < 0x03 >;
                                  };
                          };
                  };

                  fragment@3 {
                          target = < 0x01 >;

                          __dormant__ {
                                  #address-cells = < 0x01 >;
                                  #size-cells = < 0x00 >;

                                  channel_c {
                                          reg = < 0x06 >;
                                          ti,gain = < 0x01 >;
                                          ti,datarate = < 0x07 >;
                                          phandle = < 0x04 >;
                                  };
                          };
                  };

                  fragment@4 {
                          target = < 0x01 >;

                          __dormant__ {
                                  #address-cells = < 0x01 >;
                                  #size-cells = < 0x00 >;

                                  channel_d {
                                          reg = < 0x07 >;
                                          ti,gain = < 0x01 >;
                                          ti,datarate = < 0x07 >;
                                          phandle = < 0x05 >;
                                  };
                          };
                  };

                  __overrides__ {
                          addr = [ 00 00 00 01 72 65 67 3a 30 00 ];
                          cha_enable = [ 00 00 00 00 3d 31 00 ];
                          cha_cfg = [ 00 00 00 02 72 65 67 3a 30 00 ];
                          cha_gain = [ 00 00 00 02 74 69 2c 67 61 69 6e 3a 30 00 ];
                          cha_datarate = [ 00 00 00 02 74 69 2c 64 61 74 61 72 61 74 65 3a 30 00 ];
                          chb_enable = [ 00 00 00 00 3d 32 00 ];
                          chb_cfg = [ 00 00 00 03 72 65 67 3a 30 00 ];
                          chb_gain = [ 00 00 00 03 74 69 2c 67 61 69 6e 3a 30 00 ];
                          chb_datarate = [ 00 00 00 03 74 69 2c 64 61 74 61 72 61 74 65 3a 30 00 ];
                          chc_enable = [ 00 00 00 00 3d 33 00 ];
                          chc_cfg = [ 00 00 00 04 72 65 67 3a 30 00 ];
                          chc_gain = [ 00 00 00 04 74 69 2c 67 61 69 6e 3a 30 00 ];
                          chc_datarate = [ 00 00 00 04 74 69 2c 64 61 74 61 72 61 74 65 3a 30 00 ];
                          chd_enable = [ 00 00 00 00 3d 34 00 ];
                          chd_cfg = [ 00 00 00 05 72 65 67 3a 30 00 ];
                          chd_gain = [ 00 00 00 05 74 69 2c 67 61 69 6e 3a 30 00 ];
                          chd_datarate = [ 00 00 00 05 74 69 2c 64 61 74 61 72 61 74 65 3a 30 00 ];
                  };

                  __symbols__ {
                          ads1113 = "/fragment@0/__overlay__/ads1113";
                          channel_a = "/fragment@1/__dormant__/channel_a";
                          channel_b = "/fragment@2/__dormant__/channel_b";
                          channel_c = "/fragment@3/__dormant__/channel_c";
                          channel_d = "/fragment@4/__dormant__/channel_d";
                  };

                  __fixups__ {
                          i2c_arm = "/fragment@0:target:0";
                  };

                  __local_fixups__ {

                          fragment@1 {
                                  target = < 0x00 >;
                          };

                          fragment@2 {
                                  target = < 0x00 >;
                          };

                          fragment@3 {
                                  target = < 0x00 >;
                          };

                          fragment@4 {
                                  target = < 0x00 >;
                          };

                          __overrides__ {
                                  addr = < 0x00 >;
                                  cha_cfg = < 0x00 >;
                                  cha_gain = < 0x00 >;
                                  cha_datarate = < 0x00 >;
                                  chb_cfg = < 0x00 >;
                                  chb_gain = < 0x00 >;
                                  chb_datarate = < 0x00 >;
                                  chc_cfg = < 0x00 >;
                                  chc_gain = < 0x00 >;
                                  chc_datarate = < 0x00 >;
                                  chd_cfg = < 0x00 >;
                                  chd_gain = < 0x00 >;
                                  chd_datarate = < 0x00 >;
                          };
                  };
        
            };
          '';
        }
      ];
    };
  };
}

Hi! :wave:

Try with compatible = "brcm,bcm2711"; at the root of the overlay.

Our tooling may be needlessly strict about the compatible strings when applying overlays. This is something that needs to be investigated properly.

I also have to assume ads1113-overlay didn’t work.

        { name ="i2c1-overlay";
        dtsText =''
        /dts-v1/;
        /plugin/;

        / {
-                compatible = "brcm,bcm2835";
+                compatible = "brcm,bcm2711";

                fragment@0 {
                        target

You can check if the overlay applied (assuming you nixos-rebuild switch’d) by using:

 $ dtc /run/current-system/dtbs/broadcom/bcm2711-rpi-4-b.dtb

dtc automatically decompiles a dtb input. And our overlays are pre-applied on the dtb file.

You can also use dtc on the full path to the .dtb file for the system build if you nixos-rebuild build with a path like result/dtbs/....

Using the above change gives me this error. And yes the ads1113-overlay does not work in the initial example. same issue FDT_ERR_NOTFOUND if I remove the I2C overlay.

building '/nix/store/9vkj0y3hk3m5v0j0qk0fk9546zb28cna-device-tree-overlays.drv'...
./broadcom -> /nix/store/vjpd76l972w3masflb4f8wpiarpwjya8-device-tree-overlays/./broadcom
'./broadcom/bcm2711-rpi-4-b.dtb' -> '/nix/store/vjpd76l972w3masflb4f8wpiarpwjya8-device-tree-overlays/./broadcom/bcm2711-rpi-4-b.dtb'
'./broadcom/bcm2711-rpi-cm4.dtb' -> '/nix/store/vjpd76l972w3masflb4f8wpiarpwjya8-device-tree-overlays/./broadcom/bcm2711-rpi-cm4.dtb'
'./broadcom/bcm2711-rpi-400.dtb' -> '/nix/store/vjpd76l972w3masflb4f8wpiarpwjya8-device-tree-overlays/./broadcom/bcm2711-rpi-400.dtb'
Applying overlay dwc2-overlay to bcm2711-rpi-4-b.dtb
Applying overlay uart3-overlay to bcm2711-rpi-4-b.dtb
Applying overlay uart5-overlay to bcm2711-rpi-4-b.dtb
Applying overlay mdio-overlay to bcm2711-rpi-4-b.dtb
Applying overlay emmc-overlay to bcm2711-rpi-4-b.dtb
Applying overlay i2c1-overlay to bcm2711-rpi-4-b.dtb
 
Failed to apply '/nix/store/zybd0kb2gcv1k46sw2abiiqxyv27v7y2-i2c1-overlay-dtbo': FDT_ERR_NOTFOUND
dtc /run/current-system/dtbs/broadcom/bcm2711-rpi-4-b.dtb | grep i2c1
gives me the following from my initial build using bcm2835 which I see is an alias of bcm2711 
<stdout>: Warning (gpios_property): /__symbols__:gpio: property size (19) is invalid, expected multiple of 4
                i2c1 = "/soc/i2c@7e804000";
                i2c10 = "/soc/i2c0mux/i2c@1";
                        i2c1_gpio2 {
                        i2c1_gpio44 {
                        i2c1_gpio46 {
                        i2c1 {
                i2c1 = "\0\0\05status";
                i2c1_baudrate = "\0\0\05clock-frequency:0";
                i2c1_gpio2 = "/soc/gpio@7e200000/i2c1_gpio2";
                i2c1_gpio44 = "/soc/gpio@7e200000/i2c1_gpio44";
                i2c1_gpio46 = "/soc/gpio@7e200000/i2c1_gpio46";
                i2c1_pins = "/soc/gpio@7e200000/i2c1";
                i2c1 = "/soc/i2c@7e804000";

I should have looked more closely to what you shared!

This is part of your i2c1 overlay. This is most likely wrong. It’s trying to apply the overaly on the node 0xffffffff, rather than a logically-named node. I am willing to bet 0xffffffff is not i2c1

Rather than the snippet of unknown origin you’re using, copy the contents of the original source, and replace the compatible = part for bcm2711, like I said previously.

The FDT_ERR_NOTFOUND error in this use case generally means that the target of the overlay wasn’t found in the dtb file being overlaid. And use of 0xffffffff instead of whatever the symbols actually point to is likely the reason.

As for the ads1113 stuff, you’ll probably need to find the origin of the overlay. I don’t see it in the raspberry pi linux fork.

The vendor might help?

Same issue with this description. :frowning:

        { name ="i2c1-overlay";
        dtsText =''
        /dts-v1/;
        /plugin/;

        / {
                compatible = "brcm,bcm2711";

                fragment@0 {
                       target = <&i2c1>;

                        __overlay__ {
                                status = "okay";
                                pinctrl-names = "default";
                                pinctrl-0 = <0xffffffff>;
                        };
                };

                fragment@1 {
                        target = <&i2c1_pins>;

                        __overlay__ {
                                brcm,pins = <0x02 0x03>;
                                brcm,function = <0x04>;
                                phandle = <0x01>;
                        };
                };

                fragment@2 {
                        target = <&i2c1_pins>;

                        __dormant__ {
                                brcm,pins = <0x2c 0x2d>;
                                brcm,function = <0x06>;
                                phandle = <0x02>;
                        };
                };

                fragment@3 {
                        target = <&i2c1>;

                        __dormant__ {
                                compatible = "brcm,bcm2708-i2c";
                        };
                };

                __overrides__ {
                        pins_2_3 = [00 00 00 00 3d 31 21 32 00];
                        pins_44_45 = [00 00 00 00 21 31 3d 32 00];
                        combine = [00 00 00 00 21 33 00];
                };

                __symbols__ {
                        pins1 = "/fragment@1/__overlay__";
                        pins2 = "/fragment@2/__dormant__";
                };

                __fixups__ {
                        i2c1 = "/fragment@0:target:0\0/fragment@3:target:0";
                        i2c1_pins = "/fragment@0/__overlay__:pinctrl-0:0\0/fragment@1:target:0\0/fragment@2:target:0";
                };
            };
             '';
        }
these derivations will be built:
  /nix/store/zrjp3l4zkgfwiix4d2rkdngwm3nljrbp-dts.drv
  /nix/store/09naxpibhlcx089gdkh4yl9jnx6i6nrx-i2c1-overlay-dtbo.drv
  /nix/store/4fk432qn5sz3c8hw157l0wy3vrvdq3az-device-tree-overlays.drv
  /nix/store/pn27ym4wr5dza8k2rsa0qs25y4iq9d6l-nixos-system-daves-dev-compute4-01-21.05pre295466.f0869b1a2c0.drv
  /nix/store/xmhdsvnansw86cz7w49apqbp2psqgllx-nixops-machines.drv
building '/nix/store/zrjp3l4zkgfwiix4d2rkdngwm3nljrbp-dts.drv'...
building '/nix/store/09naxpibhlcx089gdkh4yl9jnx6i6nrx-i2c1-overlay-dtbo.drv'...
/nix/store/h8jsh3vkfq07cm3cq75mm6j1w5s8yq15-dts:27.20-35.11: Warning (unit_address_vs_reg): /fragment@2: node has a unit name, but no reg property
/nix/store/h8jsh3vkfq07cm3cq75mm6j1w5s8yq15-dts:37.20-43.11: Warning (unit_address_vs_reg): /fragment@3: node has a unit name, but no reg property
building '/nix/store/4fk432qn5sz3c8hw157l0wy3vrvdq3az-device-tree-overlays.drv'...
./broadcom -> /nix/store/jma7hm9jzb1k5miimj2j6f6jzxiic2w6-device-tree-overlays/./broadcom
'./broadcom/bcm2711-rpi-4-b.dtb' -> '/nix/store/jma7hm9jzb1k5miimj2j6f6jzxiic2w6-device-tree-overlays/./broadcom/bcm2711-rpi-4-b.dtb'
'./broadcom/bcm2711-rpi-cm4.dtb' -> '/nix/store/jma7hm9jzb1k5miimj2j6f6jzxiic2w6-device-tree-overlays/./broadcom/bcm2711-rpi-cm4.dtb'
'./broadcom/bcm2711-rpi-400.dtb' -> '/nix/store/jma7hm9jzb1k5miimj2j6f6jzxiic2w6-device-tree-overlays/./broadcom/bcm2711-rpi-400.dtb'
Applying overlay dwc2-overlay to bcm2711-rpi-4-b.dtb
Applying overlay uart3-overlay to bcm2711-rpi-4-b.dtb
Applying overlay uart5-overlay to bcm2711-rpi-4-b.dtb
Applying overlay mdio-overlay to bcm2711-rpi-4-b.dtb
Applying overlay emmc-overlay to bcm2711-rpi-4-b.dtb
Applying overlay i2c1-overlay to bcm2711-rpi-4-b.dtb
 
Failed to apply '/nix/store/pp13kynrzx2w73ybiqj0x0s079svmxvv-i2c1-overlay-dtbo': FDT_ERR_NOTFOUND

I don’t think you’ve used the entire source in your last attempt. It seems you only partially merged the changes. There are still “broken” values, e.g. pinctrl-0 = <0xffffffff>; instead of pinctrl-0 = <&i2c1_pins>;, and pins_2_3 = [00 00 00 00 3d 31 21 32 00]; instead of pins_2_3 = <0>,"=1!2"; (though that last one is less likely to matter).

Any reference written out as <0xffffffff> is not going to be found in the device tree when applying the overlay.

Other values could differ in unexpected ways, but at a glance it looks like only references differ in a breaking manner.

I think I have solved the i2c part, all you need to do is set the status to ok. The git repo compute4 device tree already has the i2c1 channel setup it is just turned off.
I believe setting it to okay enables it. I am working on the ads1113 device tree now to get access to the device.

        { name ="i2c1-overlay";
        dtsText =''
        /dts-v1/;
        /plugin/;

        / {
                compatible = "brcm,bcm2711";

                fragment@0 {
                       target = <&i2c1>;

                        __overlay__ {
                                status = "okay";
                        };
                };


            };
             '';
        }

/dev/i2c-1 now exists.

ads1113 now available by adding.
pkgs.python39Packages.smbus-cffi to the build inputs.