rtl93xx:i2c_controller

The I2C controller on the rtl93xx is a bit odd, or flexible ;)

For starters, there are two master I2C controllers, each with 1 i2c clock output pin (pin 8 and pin 17). They have their own address space, but share share one register, to configure I2C open-drain, delays etc (per controller), this however can also be considered pinctrl functionality!

Further more, each master controller, can use any of the 8 SDA pins to send data. This allows muxing 8 SDA outputs on 1 i2c-clock/master controller.

In theory, it would be possible to have 16 I2C busses active, e.g. both master controllers can use sda 0, where i2c0 toggles the clock, and i2c1 keeps the clock low. The downside of this approach of course is that you limit the bandwith, as it is not possible to simultaneously transmit. Some smart logic could be used, to lock the bus if either peripherals is using the same SDA output however.

Question is still open, is it a true i2c controller, or a pure SMB controller? Next to the Address register, the I2C controller has two 'data' registers. The 4 obvious 32bit data registers, which can hold up to 16 bytes total. However, there's also a 'command' register, which can hold upto 3 bytes.

A reason these two are separated, could be be because of 'restart' behavior that SMBus seems to do after the device + command sequence, and thus the restart state is automatically inserted if the size is not 0.

This also could make it possible to support the other I2C functions, by simply skipping the cmd bytes.

Also curious if we can use the cmd bytes, to set the 10 bit address, where the actual address byte holds the '10 bit marker'.

Shared SDA lines

I2C master 1 and 2 can share SDA lines, as they do have individual SCL lines, this makes it possible to drive 16 I2C channels. The reason realtek did this, is very possibly to be able to easily address 16 SFP cages, with all standard device addresses.

Using 8 channels is easy, as we can do this on a single controller. Using 16 channels is harder, because we now need to avoid setting the muxer to the same channel, which would result in both I2C masters driving the same SDA channel (albeit with individual clocks). One way to solve this, is to use some sort of locking mechanism between the channels. Another option would be to see if we can use the i2c-demux-pinctrl driver, or create something similar. The i2c-demux-pinctrl driver probably does some load-balancing, which is not quite what we want, but the idea is not bad, demux the masters and instead of loadbalancing, just avoid locking.

  • rtl93xx/i2c_controller.txt
  • Last modified: 2023/03/18 09:48
  • by oliver