Representing an unusual I2C controller

From: Chris Packham
Date: Fri Sep 13 2024 - 00:27:31 EST


Hi I2C Enthusiasts,

I'm starting to look at supporting the I2C controller on the Realtek RTL9300 and I'm struggling a little bit to figure out how to represent it. It's a bit odd in that there are basically two I2C controllers which have a SCL pin each but then there are 8 common SDA pins that can be split between the two controllers to give a level of muxing and/or concurrency.

Basically I can have: SDA[0:7] + SCL8 or SDA[0:7] + SCL17 or any of the possible permutations. I could be accessing SDA0+SCL8 and SCL1+SDA17 concurrently but if the hardware were connected as SDA0+SCL8 and SCL1+SDA8 I'd have to make those mutually exclusive.

I think it might just make sense to represent the two entities that own the SCL pins as separate controllers but then it'd be hard to enforce the fact that the individual SDA pins can only belong to one controller. Complicating things a bit further there is a common register that says whether the pins are being used for SDA or as GPIO (that can probably just be handled with pinctrl).

So I was thinking something like

i2c@36c {
  reg = <0x36c 0x14>
  compatible = "realtek,rtl9300-i2c";
  scl-pin = <8>;

  i2c@0 {
      sda-pin = <0>; // could use reg instead of scl-pin
  }
  i2c@1 {
      sda-pin = <1>;
  }
};

i2c@388 {
  reg = <0x388 0x14>
  scl-pin = <17>;
  compatible = "realtek,rtl9300-i2c";

  i2c@2 {
      sda-pin = <2>;
  }
  i2c@3 {
      sda-pin = <3>;
  }
};

Does that make sense? I'm not entirely sure how I can have those root controllers as something the I2C framework knows about without them being adapters in their own right (they can't have any devices attached directly that'd need to be done on one of the channels).

There are drivers for this in openwrt[1][2] but they ignore the fact that there are multiple controllers and the muxing is done separately. I was planning on using them for a bit of inspiration.

[1] - https://git.openwrt.org/?p=openwrt/openwrt.git;a=blob;f=target/linux/realtek/files-5.15/drivers/i2c/busses/i2c-rtl9300.c
[2] - https://git.openwrt.org/?p=openwrt/openwrt.git;a=blob;f=target/linux/realtek/files-5.15/drivers/i2c/muxes/i2c-mux-rtl9300.c

Thanks,
Chris