nakato / nixos-sbc

Nix Flake to make managing Single Board Computers easy and repeatable.
MIT License
26 stars 7 forks source link

RaspberryPi 4 has a lot of i2c enabled #28

Closed tbaumann closed 3 weeks ago

tbaumann commented 3 weeks ago

I'm probably holding it wrong. But perhaps someone has an idea...

I need to somehow disable the first two i2c busses in DT.

tilli@nas ~> sudo i2cdetect -l
i2c-0   i2c         fef04500.i2c                        I2C adapter
i2c-1   i2c         fef09500.i2c                        I2C adapter
i2c-2   i2c         bcm2835 (i2c@7e205000)              I2C adapter
i2c-3   i2c         bcm2835 (i2c@7e804000)              I2C adapter

Only i2c-2 and i2c-3 have useful devices added. And the software I use only probes for devices on the first two busses.

I guess if I can disable the fef04500 ones I'm good.

https://github.com/nakato/nixos-sbc/blob/d9500e6a4ea8c4209ff9d195e45bed669edc2ca3/modules/boards/raspberrypi/rpi4/default.nix#L21 seems to disable a bus. How is the naming consistent with what I see?

tbaumann commented 3 weeks ago

I just upgraded, now I have even more busses :exploding_head:

tilli@nas ~> sudo i2cdetect -l
i2c-0   i2c         fef04500.i2c                        I2C adapter
i2c-1   i2c         fef09500.i2c                        I2C adapter
i2c-2   i2c         bcm2835 (i2c@7e205000)              I2C adapter
i2c-3   i2c         i2c-2-mux (chan_id 0)               I2C adapter
i2c-4   i2c         bcm2835 (i2c@7e804000)              I2C adapter
i2c-5   i2c         i2c-2-mux (chan_id 1)               I2C adapter
nakato commented 3 weeks ago

How is the naming consistent with what I see?

The names are the names in the device tree, runtime numbering of the devices /dev are different as they get created without any input from the authoritative hardware description the device tree provides. I believe it's probe order that determines the numbering there. (Just like how ethernet when they were called eth0, eth1 and so on could flip-flop between boots, but probe order of this sort of hardware tends to be more consistent).

The DT for the RPi4 starts at arch/arm/boot/dts/broadcom/bcm2711-rpi-4-b.dts

You can also look in /sys/firmware/devicetree/base/aliases for the names.


config.sbc.board.*.devices.*.status are either "okay", "disabled", or "always".

"okay" and "disabled" are the state of the device in the device tree by default.

"always" is an imagined state for something that cannot be hardware disabled, such as the RTC in the Pine64 Rock64, which doesn't exist in the device tree, but needs to be defined as a device so it can be controlled by the user and have sensible defaults set.

config.sbc.board.*.devices.*.enable handles the setting of the state, defaulting to "true" if the device tree default is "okay" or "false" if it is "disabled".

So in this case the config.sbc.board.i2c.devices.i2c1.status = "disabled" is recording the default state of the device based on the device tree. (Which I've gotten wrong it seems)


i2c-4 i2c bcm2835 (i2c@7e804000) I2C adapter

That is what is called i2c1 in the device-tree, as denoted by i2c@7e804000.

Example:

# cat /sys/firmware/devicetree/base/aliases/i2c1
/i2c@7e804000

I thought that was disabled by default, as I didn't see anything setting its status to "okay", but clearly I was wrong about that, as decompiling the dtb produced by an upstream kernel I can find its status is "okay"; so that will need to change.

The reason someone might want to disabled i2c1 is it occupies GPIO pins 3 and 5, so if they wanted to use those as generic GPIO that would have to be disabled.

As far as I know i2c1 is the only i2c bus exposed via any user-usable pins, and all other i2c buses defined in the device tree are either used internally or simply not connected to anything)


As for fef04500, that memory address seems odd, all the BCM2711 hardware appears to be in the 0x7e###### memory range, and I cannot find reference to that in the device tree. ~I don't have the RPi4b provisioned right now due to lack of SD cards, so please forgive my questions.~

~Is there extra hardware plugged in?~

~Have any additional device tree overlay been added?~

~Have any changes been made to the rpi firmware config? (Anything in the FAT partition)~

I've gotten my Pi4B running, I see those interfaces as well.

What problem is the i2c with memory address fef04500 causing?

nakato commented 3 weeks ago

I just upgraded, now I have even more busses 🤯

That has come from i2c-mux-pinctrl being added to the device tree in ARM: dts: bcm2711-rpi: Add pinctrl-based multiplexing for I2C0. That's i2c0, so it is kind of exposed to the user.

The commit message says it best, but it's multiplexing via pinctrl the single i2c device over two i2c buses. GPIO 0/1 at pin 27/28 of the 40-pin header, and on the MIPI CSI/DSI connector.

And wow that feels messy.

# i2cdetect -l  
i2c-2   i2c         bcm2835 (i2c@7e205000)              I2C adapter
i2c-3   i2c         i2c-2-mux (chan_id 0)               I2C adapter
i2c-4   i2c         i2c-2-mux (chan_id 1)               I2C adapter
# i2cdetect -y 4
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
# i2cdetect -y 2
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
# i2cdetect -y 3
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --                      
# i2cdetect -y 2
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

How i2c0 (2) responds depends on the last mux accessed via the mux interfaces(3/4). (I do actually have an eeprom sitting off GPIO0/1 in this case, so that's what hanging off of 0x50.)


Now for the other two.

i2c-0   i2c         fef04500.i2c                        I2C adapter
i2c-1   i2c         fef09500.i2c                        I2C adapter
[    0.589327] brcmstb-i2c fef04500.i2c:  @97500hz registered in polling mode
[    0.589805] brcmstb-i2c fef09500.i2c:  @97500hz registered in polling mode

I fairly certain that these are actually i2c@7ef04500 and i2c@7ef09500; their symbols are ddc0 and ddc1 respectively.

These are used by the hdmi0 and hdmi1 devices to perform EDID detection, which is what lets the video source (RPi4) know what it is connected to and what that supports.

You can use this overlay to disable them and the hdmi hardware.

/dts-v1/;
/plugin/;

/ {
  compatible = "brcm,bcm2711";

  fragment@0 {
    target = <&ddc0>;
    __overlay__ {
      status = "disabled";
    };  
  };  
  fragment@1 {
    target = <&ddc1>;
    __overlay__ {
      status = "disabled";
    };  
  };  
  fragment@2 {
    target = <&hdmi0>;
    __overlay__ {
      status = "disabled";
    };  
  };  
  fragment@3 {
    target = <&hdmi1>;
    __overlay__ {
      status = "disabled";
    };  
  };  
};

If i2c on one of those is causing issues, maybe the problem is coming from the HDMI device plugged in?

tbaumann commented 3 weeks ago

Easy to test.

tilli@nas ~> sudo i2cdetect -y  0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         08 09 0a 0b 0c 0d 0e 0f 
10: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 
20: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 
30: -- -- -- -- -- -- -- 37 38 39 3a 3b 3c 3d 3e 3f 
40: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 
50: 50 -- -- -- 54 -- -- -- -- 59 -- -- -- -- -- -- 
60: 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 
70: 70 71 72 73 74 75 76 77       

With a monitor plugged in

tilli@nas ~> sudo i2cdetect -y  0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         08 09 0a 0b 0c 0d 0e 0f 
10: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 
20: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 
30: -- -- -- -- -- -- -- -- 38 39 3a 3b 3c 3d 3e 3f 
40: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 
70: 70 71 72 73 74 75 76 77                         

Jup. That's it.

I tried renaming it. But NAME can't be changed for devices, only network links.

SUBSYSTEM=="i2c-dev", ATTRS{name}=="fef04500*", NAME="ddc-%n" 
tbaumann commented 3 weeks ago

Easy to test.

tilli@nas ~> sudo i2cdetect -y  0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         08 09 0a 0b 0c 0d 0e 0f 
10: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 
20: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 
30: -- -- -- -- -- -- -- 37 38 39 3a 3b 3c 3d 3e 3f 
40: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 
50: 50 -- -- -- 54 -- -- -- -- 59 -- -- -- -- -- -- 
60: 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 
70: 70 71 72 73 74 75 76 77       

With a monitor plugged in

tilli@nas ~> sudo i2cdetect -y  0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         08 09 0a 0b 0c 0d 0e 0f 
10: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 
20: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 
30: -- -- -- -- -- -- -- -- 38 39 3a 3b 3c 3d 3e 3f 
40: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 
70: 70 71 72 73 74 75 76 77                         

Jup. That's it.

I tried renaming it. But NAME can't be changed for devices, only network links.

SUBSYSTEM=="i2c-dev", ATTRS{name}=="fef04500*", NAME="ddc-%n" 

I ended up just patching that software. It's messy. But it was bad design on their part in the first place.