Support for Zyxel GS1920 series (GS1920-24HP)

Might this not be cause by reply is not being correctly initialized?

When using i2cget I need to specify slave address and register I want to read (where the register address is the first byte of the data written or read). While in realtek-poe reply is declared in poe_cmd_queue as unsigned char reply[12] but never actually initialized with the i2c register on the slave we want to read.

In the example I found at https://docs.kernel.org/i2c/dev-interface.html this seems to be circumvented by using the same buffer for both write and read?

Never mind. It seems your right. I added a usleep(1000); between write and read. Which makes it quite a bit more reliable. At least the received reply with bad checksum lines are gone.

root@OpenWrt:~# ./realtek-poe -d
realtek-poe: H3K filename: /dev/i2c-4
realtek-poe: Using I2C bus #4: /dev/i2c-4
realtek-poe: Setting I2C slave address to 20
realtek-poe: I2C TX -> 20 01 ff ff ff ff ff ff ff ff ff 18
realtek-poe: RX <- 20 01 02 18 00 e1 11 11 00 01 01 40
realtek-poe: I2C TX -> 17 02 02 ff ff ff ff ff ff ff ff 13
realtek-poe: RX <- 17 02 00 ff ff ff ff ff ff ff ff 11
realtek-poe: I2C TX -> 02 03 00 ff ff ff ff ff ff ff ff fd
realtek-poe: RX <- 02 03 00 ff ff ff ff ff ff ff ff fd
realtek-poe: I2C TX -> 18 04 00 07 08 00 b4 ff ff ff ff db
realtek-poe: RX <- 18 04 00 00 ff ff ff ff ff ff ff 15
realtek-poe: I2C TX -> 13 05 7f 02 ff ff ff ff ff ff ff 92
realtek-poe: RX <- 13 05 7f 00 ff ff ff ff ff ff ff 90
realtek-poe: I2C TX -> 10 06 7f 03 ff ff ff ff ff ff ff 91
realtek-poe: RX <- 10 06 7f 00 ff ff ff ff ff ff ff 8e
realtek-poe: I2C TX -> 1a 07 00 02 01 02 02 02 03 02 ff 2e
realtek-poe: RX <- 1a 07 00 00 01 00 02 00 03 00 ff 26
realtek-poe: I2C TX -> 1c 08 00 03 01 03 02 03 03 03 ff 35
realtek-poe: RX <- 1c 08 00 00 01 00 02 00 03 00 ff 29
realtek-poe: I2C TX -> 11 09 00 01 01 01 02 01 03 01 ff 23

Verified SerDes mapping of GS1920-24 (nonPOE)

		SWITCH_PORT_SDS(0, 1, 0, qsgmii)
		SWITCH_PORT_SDS(1, 2, 0, qsgmii)
		SWITCH_PORT_SDS(2, 3, 0, qsgmii)
		SWITCH_PORT_SDS(3, 4, 0, qsgmii)
		SWITCH_PORT_SDS(4, 5, 1, qsgmii)
		SWITCH_PORT_SDS(5, 6, 1, qsgmii)
		SWITCH_PORT_SDS(6, 7, 1, qsgmii)
		SWITCH_PORT_SDS(7, 8, 1, qsgmii)

		SWITCH_PORT_SDS(8, 9, 2, qsgmii)
		SWITCH_PORT_SDS(9, 10, 2, qsgmii)
		SWITCH_PORT_SDS(10, 11, 2, qsgmii)
		SWITCH_PORT_SDS(11, 12, 2, qsgmii)
		SWITCH_PORT_SDS(12, 13, 3, qsgmii)
		SWITCH_PORT_SDS(13, 14, 3, qsgmii)
		SWITCH_PORT_SDS(14, 15, 3, qsgmii)
		SWITCH_PORT_SDS(15, 16, 3, qsgmii)

		SWITCH_PORT_SDS(16, 17, 4, qsgmii)
		SWITCH_PORT_SDS(17, 18, 4, qsgmii)
		SWITCH_PORT_SDS(18, 19, 4, qsgmii)
		SWITCH_PORT_SDS(19, 20, 4, qsgmii)
		SWITCH_PORT_SDS(20, 21, 5, qsgmii)
		SWITCH_PORT_SDS(21, 22, 5, qsgmii)
		SWITCH_PORT_SDS(22, 23, 5, qsgmii)
		SWITCH_PORT_SDS(23, 24, 5, qsgmii)

		SWITCH_PORT_SDS(48, 25, 12, qsgmii)
		SWITCH_PORT_SDS(49, 26, 12, qsgmii)
		SWITCH_PORT_SDS(50, 27, 12, qsgmii)
		SWITCH_PORT_SDS(51, 28, 12, qsgmii)
1 Like

Totally forgot those unfinished fragments ... save them for posterity before dropping the build environment ...

Minimum RLT839x 10G SerDes initialization sequence to get QSGMII PHY link up and running and compensate for missing U-Boot.

	... somehwere early in the PCS driver ...

	if (sds != 8 && sds !=9 && sds != 12 && sds != 13)
		return;
	
	rtpcs_sds_write(ctrl, sds, 0x0a, 0x1c, 0x002a);
	rtpcs_sds_write(ctrl, sds, 0x0a, 0x1d, 0x0000);
	rtpcs_sds_write(ctrl, sds, 0x0a, 0x1e, 0xa052); /* changes to 0x0002 */
	rtpcs_sds_write(ctrl, sds, 0x0a, 0x1f, 0x9a00); /* changes to 0xbe00 */
	rtpcs_sds_write(ctrl, sds, 0x0b, 0x00, 0x00f5);
	rtpcs_sds_write(ctrl, sds, 0x0b, 0x01, 0xc480);
	rtpcs_sds_write(ctrl, sds, 0x0b, 0x05, 0x3340);
	rtpcs_sds_write(ctrl, sds, 0x0b, 0x08, 0x803f);
	rtpcs_sds_write(ctrl, sds, 0x0b, 0x0c, 0x2bff);
	rtpcs_sds_write(ctrl, sds, 0x0b, 0x0d, 0x2bff);
	rtpcs_sds_write(ctrl, sds, 0x0b, 0x11, 0x0000);
	
	if (even) {
		rtpcs_sds_write(ctrl, sds, 0x0a, 0x11, 0xf04a);
		rtpcs_sds_write(ctrl, sds, 0x0b, 0x04, 0x39ff);
		rtpcs_sds_write(ctrl, sds, 0x0b, 0x06, 0x40a2);
		rtpcs_sds_write(ctrl, sds, 0x0b, 0x0e, 0x4e10); /* changes to 0x0a10 */
	} else {
		rtpcs_sds_write(ctrl, sds, 0x0a, 0x11, 0xfdab);
		rtpcs_sds_write(ctrl, sds, 0x0b, 0x04, 0x93fa);
		rtpcs_sds_write(ctrl, sds, 0x0b, 0x06, 0x4280);
		rtpcs_sds_write(ctrl, sds, 0x0b, 0x0e, 0x4c50); /* changes to 0x0a10 */
	}

	/* Needs this function from RTK afterwards */
	rtl839x_serdes_reset(sds);

Minimum RTL8214FC initialization sequence to get network connectivity and to compensate for missing U-Boot. Should work on RTL838x too.

static int rtl8214fc_config_init(struct phy_device *phydev)
{
	static int regs[] = {16, 19, 20, 21};

	if (phydev->mdio.addr % 8)
		return 0;
	...
	for (port = 0; port < 4; port++)
		patchphy = get_package_phy(phydev, port);		

		phy_write(phydev, 0x1e, 0x8);
		/* setup basic fiber control in base phy and default to copper */
		phy_write_paged(phydev, 0x266, regs[port], 0x0f95};
		phy_write(phydev, 0x1e, 0x0);	

		phy_write(patchphy, 0x1e, 0x3);
		/* set fiber SerDes RX to negative edge */
		phy_modify_paged(patchphy, 0x8, 0x17, BIT(14), 0);
		/* auto negotiation disable link on */
		phy_modify_paged(patchphy, 0x8, 0x14, 0, BIT(2));
		/* disable fiber 100MBit */
		phy_modify_paged(patchphy, 0x8, 0x17, BIT(5), 0);
		phy_write(patchphy, 0x1e, 0x0);

		/* Disable EEE. 0xa5d/0x10 is the same as MDIO_MMD_AN / MDIO_AN_EEE_ADV */
		phy_write_paged(patchphy, 0xa5d, 0x10, 0x0000);
	}

	/* similar hardware, reuse for MAC SerDes init */
	rtl8218b_config_init(phydev); 
	...
2 Likes

Seems to work on the PoE model as well. I added it to my dts and created a PR at https://github.com/openwrt/openwrt/pull/20439

The LED situation on the RTL838x target hasn't changed, right? On my model, the PoE lights are active instead of the port LEDs.

2 Likes

I booted it on GS2210-8HP with added rtl8214fc_config_init.

It comes up with ports 1-8 as lan1-8 and port 9/10 as lan25,26

Connecting port 9/10 with RJ45 brings the link up. Connecting them with a DAC reads the EEPROM switches between RJ45/SFP, but checking with ethtool its not seeing the other end advertise capabilities.

1 Like

I had a look at this. RTL839x works similar to RTL93XX, using LED sets which define the LED behavior. I have a dirty patch for this, could clean it up and submit it in the next days.

But it doesn’t solve the behavior on the GS1920-24HP for now. Still have to figure out how to properly configure it then. On my v2, the front panel PCB has two RTL8231 in shift register mode, and three HC164 shift registers which are wired up in serial like “RTL8231 –> RTL8231 –> HC164 –> HC164 –> HC164”. I’m not sure yet how the LEDs are connected to this. At least configuring the LEDs with my patch, the LEDs with the correct port number light up although it’s currently both the LINK/ACT and PoE LEDs.
Important to note here is that the LEDs for the combo ports are not controlled by the SoC (and therefore have to be excluded from configuration). Instead they are managed by the RTL8214FC. Not sure if this needs to be configured too or should work by default.

Moreover, I worked on my GS1920-24HPv2 and figured out it’s quite more different than expected in the first place. Most important differences I’ve seen so far:

  • RTL8391M SoC (instead of RTL8392M)
  • 256MiB RAM, 32MiB Flash (definitely needs a separate recipe in OpenWrt)
  • RTL8214FC PHYs connected at port numbers 24-27 (instead of 48-51). Most likely due to the different SoC variant. I’m not sure if this only applies to the SMI address or also to the “MAC number”. In my case, the RTL8214FC PHYs are only recognized at these addresses right now but link isn’t detected.
  • Slightly different GPIOs for SFPs: cages 25 and 26 share SCL on GPIO3, cages 27 and 28 use different SCL GPIOs than v1
  • no ADT7468 fan controller, LM96000 on PCB
  • serial console: simple TTL UART, accessible without opening the case

Some progress!
With some help I was able to make a proper sniff/trace of the i2c communication during boot of my GS2210 using a logic analyzer at the local hackerspace. (And in the process documenting usage of that beast of an analyzer).

To test, I filtered all read/writes going to slave 0x20 and converted it to a script executing i2cget/set commands. After executing this script, I'm now looking at a running PoE powered Rasberry Pi running of my switch. :partying_face:

I'll try to upload and link the raw trace and resulting script I used somewhere. (Any suggestions where I can easily share these files? Can I share them via the forum somehow?)

The replay script I used
Pulseview session

6 Likes

My GS1920-24HPv2 has no serial connector on the outside. Are you talking about another switch?

It’s not directly outside on the switch. If you have the switch facing with the ports to you, look at it’s right side and you should find a rectangular opening within the regular honeycomb structure. Through that opening you should see a pin header. It’s a bit fiddly but doable without opening the case.

1 Like

similar to https://community.zyxel.com/en/discussion/comment/39133/#Comment_39133 ?

1 Like

Similar, just that on GS1920-24HPv2 it’s horizontal. But Zyxel seems to make serial available like that for most of their “newer” revisions of switches.

Is the GS1920-24HPv2 TTY level 3.3V or 5.6V? I’m just not sure which version the 5.6V was referring to.

It’s 3.3V. The ±5.6V is just for v1 because it uses RS232 instead of TTL.

2 Likes