Support for RTL838x based managed switches

That might be entirely possible.

Now I understand the issue, thanks. Yes boardmodel is RTL8382M_8218B_INTPHY_8218B_8214QF_DEMO and it matches the SFP PHY on board.

Neither does the gpl source of the T1600-28TSv3 have that exact board file:

rtl8328l_8212b_demo_board.c
rtl8328l_8212b_serial_led_demo_board.c
rtl8328m_8212f_demo_board.c
rtl8328m_8214fb_demo_board.c
rtl8328m_8214f_demo_board.c
rtl8328s_2sfp_demo_board.c
rtl8330m_intphy_2fib_1g_demo_board.c
rtl8330m_intphy_8212b_demo_board.c
rtl8330m_intphy_8212b_sgmii_demo_board.c
rtl8332m_8208l_8208l_8214b_qa_board.c
rtl8332m_8208l_intphy_8208l_8212b_demo_board.c
rtl8332m_8208l_intphy_8208l_8214b_demo_board.c
rtl8353m_14b_demo_board.c
rtl8353m_demo_board.c
rtl8353m_qa_board.c
rtl8380m_intphy_2fib_1g_demo_board.c
rtl8382m_8218b_8218fb_demo_board.c
rtl8382m_8218b_intphy_8218b_2fib_1g_demo_board.c
rtl8382m_8218b_intphy_8218b_8214b_demo_board.c
rtl8382m_8218b_intphy_8218b_8214fc_demo_board.c
rtl8382m_8218b_intphy_8218fb_demo_board.c
rtl8391m_8218c_demo_board.c
rtl8391m_demo_board.c
rtl8392m_8218c_demo_board.c
rtl8392m_demo_board.c
rtl8392m_qa_board.c
rtl8393m_8218b_8218fb_2sfp.c
rtl8393m_8218c_demo_board.c
rtl8393m_demo_board.c
rtl8393m_qa_board.c
rtl8396m_8218c_demo_board.c
rtl8396m_demo2_board.c
rtl8396m_demo_board.c

Path is: /t1600g-28ts_gpl/ldk_realtek/realtek-V2.1.6.pre2/u-boot-2011.12/board/Realtek/switch/rtk/conf

Yep, the mdio decoder from sigrock works great and seems to decode usefull register/value combinations. Link on Port 8 or 9 was up during capture and I remember seening non 0x00 values written to register 0x0A.

My suspicion is that the RTL8214QF is a newer version of the RTL8214FC and we somehow do not have any u-boot source from TPLink for this relatively new switch. For OpenWRT support this does not matter, because we have all the code in newer released SDKs, but it would explain the issues why the full u-boot and the original firmware in combination have issues patching the PHY. Note that patching is actually a mere configuration for optimum values, one can use the PHYs nevertheless, but the PHYs probably don't get activated when the patching fails.

Got it, would it be beneficial to ask at tplink for the missing board conf file or a newer gpl source?

Would it be possible to recreate the information in that file from the stock uboot i dumped from my flash?

Nah, I think we want to get OpenWRT to run on this device, and I don't think we need more GPL sources. In any case our drivers in OpenWRT should be able to initialize the device independent of the state in which u-boot leaves it. It is interesting that both the stock firmware and our drivers complain about the same things: the PHYs cannot be patched. The only reason I am aware off why this would happen is when the PHYs are actively polled by the SoC for their status. But both the driver and the stock firmware switch this off, so that's not the reason here.
Could you try to switch the network off again in u-boot before you start the image. I.e. issue "rtk network off" before doing "bootm"?

RTL838x# # rtk network off
Disable network
Force port28 link down

RTL838x# # bootm

Starting kernel ...


port 0 patch ready fail 0
port 1 patch ready fail 0
...

Has no effect.

I have to admit I am at a loss: something in the full u-boot messes up the phys. Maybe puts a write protect on them? But I have used that approach on the T2500G successfully. We'll probably need to dig through the u-boot sources to see what is going on.

Just submitted a GitHub merge request for the Negear S350 series GS308T and GS310TP. This has been tested on both devices with exception of SFP support on the GS310TP. I don't currently have unused SFP modules to test with.

1 Like

The commands toggle port LED 8.1, so that's probably port 9.

The data trace actually has commands for three RTL8231 expanders, but only one appears present (although there are no reads from phy address 0). Expanders at addresses 1 and 2 are set up (almost) exclusively for GPIO use, while the one at address 0 appears dedicated to LED usage.

It's bit hard to tell which LEDs are actually used though, since the driver appears to write all LED values and all GPIO values that are valid with the configured pin settings.

That matches my amateurish observations.

Just for my understanding of the bigger picture:

  • This RTL8231 is hooked up via MDIO bus to the main SoC, this is reflected by the following device tree entry in target/linux/realtek/dts/rtl838x.dtsi:
        gpio1: rtl8231-gpio {
                status = "disabled";
                compatible = "realtek,rtl8231-gpio";
                #gpio-cells = <2>;
                indirect-access-bus-id = <0>;
                gpio-controller;
        };
  • This labeled entry is intended to be overwritten in the board specific device tree file with status="okay" to actually be used. However the actual version of the driver would wrongly configure it in GPIO mode, which is not how it is used on the T1600-28TSv3.
  • That means, it requires a new driver capable of configuring the RTL8231 for scan LED mode (or integrated into the existing one)?
  • The correct driver is found by the kernel via the compatibility string rtl8231-gpio matching the following driver target/linux/realtek/files-5.4/drivers/gpio/gpio-rtl8231.c
  • How does the kernel know on which pin's this MDIO bus is run on?
  • A scan LED variant of the driver would still expose the individual LED's as GPIO's? Hooking up the LAN port LED's would then happen similar to the SYS LED in the leds section of the device tree file roughly looking like this?
        leds {
                compatible = "gpio-leds";

                led_lan1: lan1 {
                        label = "green:lan1";
                        gpios = <&gpio1 <GIPIONUMBER> GPIO_ACTIVE_HIGH>;
                };
        };

I think I'm not capable of writing/extending such a driver. However, in the case I would want to get my feet wet I suppose the simplest way to do so is:

  • Copy gpio-rtl8231.c and swapping out the compatibility string to a new one
  • Alter the board device tree file to use this new driver
  • Strip it down only keeping a probe, init and register write function
  • Calling the register write function from the init function with observed values in capture
  • Capturing data if it is sent on the MDIO bus by the driver
  • If I get lucky writing the right values to the right registers I might light up a LED?

Finally, this raises another question. How does developing/debugging such a driver look like in general from a workflow perspective? Building a whole image, flashing it, testing it seems a bit cumbersome or can the driver be loaded/unloaded dynamically with insmod/rmmod once the device tree is set up?

I'm actually in the process of writing a new (upstream) driver for the RTL8231. The goal is to have an MDIO device driver that supports the different functions of the device: pin controller, GPIO controller, and LED controller.

The LEDs would be exposed as LED devices, not GPIOs. That means you could use a reference like led_lan1 in your example, but this would just be under the RTL8231's LED node. For example:

rtl8231@0 {
    compatible = "realtek,rtl8231", "syscon";
    reg = <0>;
    ...
    
    leds {
        compatible = "realtek,rtl8231-leds";
        realtek,scan-single-color;
        #address-cells = <2>;
        #size-cells = <0>;

        led_lan8_gig: lan@8.1 {
            reg = <8 1>;
            color = ...;
            function = ...;
        };
    };
};

Edit:

The current RTL8231 driver in OpenWrt assumes the role of both the MDIO bus and GPIO controller. This MDIO bus is muxed on GPIO lines A2 and A3. To test my new driver, I usually just mux these pins back to their GPIO functions and use virtual,mdio-gpio to provide an "actual" (to the kernel at least) MDIO bus.

To use the hard MDIO bus from the SoC, an additional (small) driver will be required to expose the required functionality.

1 Like

Thanks for your time and elaboration, filling in more and more blank spots in my understanding of the inner workings.

Nice, I was somehow assuming that.

Well I keep goofing around a bit with the device and try to familiarize myself more in the meantime.

Edit: Because I still had the front panel MIDO lines hooked up to the logic analyzer I just noticed that there is already traffic on it, even when the device is halted in bootloader prompt.


To be more precise the first traffic on powerup is already observed 4.18ms before the flash is addressed for the first time. Who put this on the bus?

2 Likes

So the things is, the RTL8231 is really tightly integrated with the switch SoCs. These SoCs have support for shadowing the registers of one expander, or even two expanders in the case of RTL931x. It's possible that on boot-up, the SoC defaults to shadowing an RTL8231 at phy address 0. That means it will continuously sync the shadowed register values with the registers on the RTL8231.

See https://svanheule.net/realtek/maple/feature/led for the relevant registers.

2 Likes

As a next step I took a more detailed look at the virgin uboot dumped from the device and compared it to the one I built from the GPL sources. Some anomalies I noticed give or take:

Appears just in the gpl uboot:

Fatal error: Failed to free inner item in image info.
Info: wait a moment...
Error: Verifing productID error, image name is %s.
POE get respone but key is not correct.! 
poe Power Consumption %d, Calculated Power %d
poe fail to get total power.
poe Firmware version %d.%d

Appears just in the virgin uboot:

rtk ledtest-bank [round]
        - led back on/off test
rtk txportpkt [port-id] [round]
        - tx packet from CPU to specific port test
rtk ldps [port] [ on | off ]
        - Enable/Disable link-down power saving (LDPS) of PHY
rtk green [port] [ on | off ]
        - Enable/Disable green feature of PHY
rtk cross-over [port] [ auto | mdi | mdix ]
        - Configure cross-over mode as Auto, Force-MDI, or Force-MDIX of PHY.

*pChip_index=%8x
MAC driver not found! 
Port %d not exist!
port %d feature not support
rtk_board_probe: board_model=%s

RTL8382M_8218B_INTPHY_8218B_8214QF_DEMO
RTL8382M_8218D_INTPHY_8218D_8214FC_DEMO
RTL8381M_INTPHY_8214FC_2FIB_1G_DEMO
RTL8381M_INTPHY_8214C_2FIB_1G_DEMO
RTL8332M_8208L_INTPHY_8208L_8214C_DEMO

**** RTL8218D config - MAC ID = %d ****
8218D phy port %d not ready! patchready:0x%x
Unable to find base MAC ID of the PHY!
Port %d driver error!
### RTL8214C config - MAC ID = %d ###
Invalid MAC id %d %d
Invalid PHY index %d
(Err%x)%s,%d : unit %u macId %u S%u %u.%u
### RTL8295R config - MAC ID = %d ###
### RTL8214QF config - MAC ID = %d ###

Interestingly tftpboot related strings are found in both version: tftpboot 0x%0x %s 0x%0x 0x%0x and Please put the uimage.img into the tftpserver directory

Summing up:

  • Virgin uboot has more rtk commands (ledtest-bank, ldps, green, cross-over, txportpkt) and includes some PHY configuration output
  • GPL uboot contains POE related things, productId verfication stuff, uboot upload features and backup image deletion.
  • The boardname of the T1600G-28TSv3 is only found in the virgin uboot.

So TP-Link clearly stripped some parts from their GPL released bootloader (or did not release their latest one containing full support for this board).

Have now been able to confirm that SFP ports on the Netgear GS310TP are functional with a 1G SFP Transceiver - Copper RJ-45 from StarTech.

5 Likes

The tight integration between the SoC and the RTL peripherials also applies to the PHYs, btw. SoC and PHYs talk SMI instead of MDIO which doubles the PHY addresses. Instead of using some IRQ-line driven mechanism to detect Link or Media changes, the PHYs are constantly polled by the SoC, which allows for the SoCs to again directly drive the LEDs in unmanaged switches without any software.

BTW: let me take the opportunity to point to svanheule's amazing website for documenting the SoC features: https://www.svanheule.net/realtek/
From SoCs without any documentation they are on the way to being the ones best documented. There is a weathlth of info about the LEDs and hardware monitoring, if you go to the L3_PREFIX_ROUTE_* tables you can see how the Layer 3 routing on the 93xx works and it seems some L3 routing and also netfilter offload is also possible on the RTL8380 https://www.svanheule.net/realtek/maple/table/iacl, which we always saw advertised in the Datasheet, but did not understand.

1 Like

Great! Can you also set speed and duplex to different settings and verify that it works? It should, as long as you can talk to the phy in the sfp. But good to verify that.

Although connecting a 100MB device (a raspberry pi 2) allows me to ssh to the rpi, the link in ethtool lan10 shows as:

Settings for lan10:
        Supported ports: [ MII ]
        Supported link modes:   1000baseT/Full 
        Supported pause frame use: Symmetric Receive-only
        Supports auto-negotiation: No
        Supported FEC modes: Not reported
        Advertised link modes:  1000baseT/Full 
        Advertised pause frame use: Symmetric Receive-only
        Advertised auto-negotiation: No
        Advertised FEC modes: Not reported
        Speed: 1000Mb/s
        Duplex: Full
        Port: MII
        PHYAD: 0
        Transceiver: internal
        Auto-negotiation: on
        Supports Wake-on: d
        Wake-on: d
        Link detected: yes

But I expect this is because the DTS is using the SWITCH_SFP_PORT macro which is defined as follows:

#define SWITCH_SFP_PORT(n, s, m) \
	port@##n { \
		reg = <##n>; \
		label = SWITCH_PORT_LABEL(s) ; \
		phy-handle = <&phy##n>; \
		phy-mode = #m ; \
		fixed-link { \
			speed = <1000>; \
			full-duplex; \
		}; \
	};

Note the fixed-link. This would be the same on the DGS-1210-10P as it uses the same syntax. Perhaps SWITCH_SFP_PORT is unnecessary and we should just use SWITCH_PORT?

Right. Or rather, that is wrong :slight_smile:

Take a look at the zyxel gs1900-10hp dts. That's the correct way to specify the ports. But was this the switch with shared i2c clock between the two slots? If so, then we can probably only make one of those ports work for now. You need i2c to talk to the phy in the SFP.

This was the switch with the "multiplexed" I2C buses which is why I used the same pattern as used on the DGS-1210-10P and not the Zyxel GS1900-10HP.

====== Fiber =================
Fiber Port Number: 2

------------ Fiber Detect
LPort  Present  MediaChg  OE Status              LOS Status
------ -------- --------- ---------------------- ----------------------
8      OE       OE        Enabled  (GPIO:EXT_14) Enabled  (GPIO:EXT_7 )
9      OE       OE        Enabled  (GPIO:EXT_13) Enabled  (GPIO:EXT_6 )

------------ Fiber Optical
LPort  I2C DEV  I2C TYPE  ID    Delay   SCK    SDA
------ -------- --------- ----- ------- ------ ------
8      0        8 BITS    0x50  1000    EXT_36 EXT_28
9      1        8 BITS    0x50  1000    EXT_36 EXT_27

------------ Fiber TX Disable
LPort  Method
------ ------
8      GPIO(EXT_28)

Note that EXT_36 and EXT_28 are used for multiple functions! If you have a suggestion for i2c and sfp nodes that might work with this I'm willing to test it.