diff --git a/cmd_parser.c b/cmd_parser.c
index 8097c2a..2dcdb87 100644
--- a/cmd_parser.c
+++ b/cmd_parser.c
@@ -633,6 +633,64 @@ void parse_passwd(void)
}
+void parse_eee(void)
+{
+ __xdata int8_t port = -1;
+ __xdata uint8_t speed = EEE_2G5;
+ __xdata uint8_t speed_word = 0;
+ // Check if word 2 is a speed (contains 'g' or 'm') or a port number
+ if (cmd_words_b[3] > 0) {
+ uint8_t idx = cmd_words_b[2];
+ // Skip digits to check if there's a letter after
+ while (isnumber(cmd_buffer[idx]))
+ idx++;
+ if (cmd_buffer[idx] == 'g' || cmd_buffer[idx] == 'm') {
+ // Word 2 is a speed (e.g., "2g5", "100m", "1g")
+ speed_word = 2;
+ } else if (cmd_buffer[idx] == ' ' || cmd_buffer[idx] == '\0') {
+ // Word 2 is a port number
+ port = cmd_buffer[cmd_words_b[2]] - '1';
+ port = machine.phys_to_log_port[port];
+ // Check if word 3 is a speed
+ if (cmd_words_b[4] > 0)
+ speed_word = 3;
+ }
+ }
+ // Parse speed if found
+ if (speed_word > 0) {
+ if (cmd_compare(speed_word, "100m"))
+ speed = EEE_100;
+ else if (cmd_compare(speed_word, "1g"))
+ speed = EEE_1000;
+ else if (cmd_compare(speed_word, "2g5"))
+ speed = EEE_2G5;
+ else
+ {
+ print_string("Speed word invalid, use: [100m|1g|2g5]\n");
+ return;
+ }
+ }
+ if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
+ if (port >= 0)
+ port_eee_enable(port, speed);
+ else
+ port_eee_enable_all(speed);
+ } else if (cmd_words_b[1] > 0 && cmd_compare(1, "off")) {
+ if (port >= 0)
+ port_eee_disable(port);
+ else
+ port_eee_disable_all();
+ } else if (cmd_words_b[1] > 0 && cmd_compare(1, "status")) {
+ if (port >= 0)
+ port_eee_status(port);
+ else
+ port_eee_status_all();
+ } else {
+ print_string("eee [on|off|status] [port] [100m|1g|2g5]\n");
+ }
+}
+
+
// Parse command into words
uint8_t cmd_tokenize(void) __banked
{
@@ -895,27 +953,7 @@ void cmd_parser(void) __banked
} else if (cmd_compare(0, "passwd")) {
parse_passwd();
} else if (cmd_compare(0, "eee")) {
- int8_t port = -1;
- if (cmd_words_b[3] > 0) {
- port = cmd_buffer[cmd_words_b[2]] - '1';
- port = machine.phys_to_log_port[port];
- }
- if (cmd_words_b[1] > 0 && cmd_compare(1, "on")) {
- if (port >= 0)
- port_eee_enable(port);
- else
- port_eee_enable_all();
- } else if (cmd_words_b[1] > 0 && cmd_compare(1, "off")) {
- if (port >= 0)
- port_eee_disable(port);
- else
- port_eee_disable_all();
- } else if (cmd_words_b[1] > 0 && cmd_compare(1, "status")) {
- if (port >= 0)
- port_eee_status(port);
- else
- port_eee_status_all();
- }
+ parse_eee();
} else if (cmd_compare(0, "version")) {
print_sw_version();
} else if (cmd_compare(0, "time")) {
diff --git a/doc/devices/TEG-S562.md b/doc/devices/TEG-S562.md
new file mode 100644
index 0000000..5122f4e
--- /dev/null
+++ b/doc/devices/TEG-S562.md
@@ -0,0 +1,175 @@
+# TrendNet TEG-S562
+
+Following is documentation for unmanaged switch marked as `TEG-S563/EU H/W: V1.0R`.
+
+Original software is running UART on 57600 baud rate. The software does not allow to
+do anything fancy via serial. There is `IP` configuration which can be printed as well.
+There might be also some flash upload procedure, but using SPI clamp in-board seems to
+be easier method.
+
+The memory chip is `Winbond W25Q16JV` with 16M-bit size.
+
+## What does work
+
+1. 2.5G ports on all advertised speeds.
+2. SFP+ communication.
+3. Serial, Web UI.
+
+## Known issues
+
+1. LEDs are not initialized properly.
+
+## PCB
+
+Manufacturer information be found [on the product page](https://www.trendnet.com/support/support-detail.asp?prod=105_TEG-S562).
+
+Top side
+
+
+
+Bottom
+
+
+
+## Connectors
+
+### Port overview
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ ┌──────────┐ ┌──────────┐ │
+│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ SFP │ │ SFP │ │
+│ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ RJ45 │ │ PORT 5 │ │ PORT 6 │ │
+│ │ PORT 1 │ │ PORT 2 │ │ PORT 3 │ │ PORT 4 │ │ MAC ? │ │ MAC ? │ │
+│ │ MAC 4 │ │ MAC 5 │ │ MAC 6 │ │ MAC 7 │ │ SerDes ? │ │ SerDes ? │ │
+│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └──────────┘ └──────────┘ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+### J2, serial console
+
+| `J2` pin | Signal |
+| -------- | ----------- |
+| 1 | 3V3 |
+| 2 | TX (Output) |
+| 3 | RX (Input) |
+| 4 | GND |
+
+Note: 1 pin is square shaped, towards the power input.
+
+### J5, power pass-thru
+
+| `J5` pin | Signal |
+| -------- | ------ |
+| 1 | 12V |
+| 2 | 12V |
+| 3 | GND |
+| 4 | GND |
+
+Note: 1 pin is square shaped.
+
+### U5, I2C eeprom placeholder
+
+| `J5` pin | Signal |
+| -------- | ------------- |
+| 1 | GND |
+| 2 | GND |
+| 3 | GND |
+| 4 | GND |
+| 5 | 3V3 |
+| 6 | ??? Logic Low |
+| 7 | SCL |
+| 8 | SDA |
+
+SOC I2C address is 0x5c.
+
+### SW1 GPIO switch?
+
+Not populated but looks like a switch for selecting
+GPIO level. Missing resistors in place.
+
+GPIO mapping unknown.
+
+### S2 Reset ciruit
+
+Not populated but looks like a button can be added on `S2` connector,
+requires additional `R571` resistor which will pull signal to ground.
+
+GPIO mapping unknown.
+
+### GPIO
+
+| HEX VAL. | GPIO | When | GPIO | When |
+| -------- | ------ | ----------------| ------ | -----------------------|
+| 00000001 | GPIO00 | | GPIO32 | |
+| 00000002 | GPIO01 | | GPIO33 | |
+| 00000004 | GPIO02 | | GPIO34 | Random changes |
+| 00000008 | GPIO03 | | GPIO35 | |
+| 00000010 | GPIO04 | | GPIO36 | SFP1 Present |
+| 00000020 | GPIO05 | | GPIO37 | SFP1 RX Los |
+| 00000040 | GPIO06 | | GPIO38 | SFP2 Present |
+| 00000080 | GPIO07 | | GPIO39 | |
+| 00000100 | GPIO08 | | GPIO40 | |
+| 00000200 | GPIO09 | | GPIO41 | |
+| 00000400 | GPIO10 | | GPIO42 | Random changes |
+| 00000800 | GPIO11 | | GPIO43 | |
+| 00001000 | GPIO12 | PORT1 Link | GPIO44 | |
+| 00002000 | GPIO13 | PORT1-LED-GREEN | GPIO45 | |
+| 00004000 | GPIO14 | PORT1-LED-AMBER | GPIO46 | SFP1 I2C CLK |
+| 00008000 | GPIO15 | PORT2 Link | GPIO47 | SFP1 I2C SDA |
+| 00010000 | GPIO16 | PORT2-LED-GREEN | GPIO48 | SFP2 I2C CLK |
+| 00020000 | GPIO17 | PORT2-LED-AMBER | GPIO49 | SFP2 I2C SDA |
+| 00040000 | GPIO18 | PORT3 Link | GPIO50 | SFP2 Rx LOS |
+| 00080000 | GPIO19 | PORT3-LED-GREEN | GPIO51 | SFP1 TX Disable |
+| 00100000 | GPIO20 | PORT4-LED-AMBER | GPIO52 | |
+| 00200000 | GPIO21 | PORT4 Link | GPIO53 | |
+| 00400000 | GPIO22 | PORT4-LED-GREEN | GPIO54 | SFP2 TX Disable |
+| 00800000 | GPIO23 | PORT4-LED-AMBER | GPIO55 | |
+| 01000000 | GPIO24 | | GPIO56 | |
+| 02000000 | GPIO25 | | GPIO57 | |
+| 04000000 | GPIO26 | | GPIO58 | |
+| 08000000 | GPIO27 | | GPIO59 | |
+| 10000000 | GPIO28 | | GPIO60 | |
+| 20000000 | GPIO29 | | GPIO61 | |
+| 40000000 | GPIO30 | | GPIO62 | |
+| 80000000 | GPIO31 | | GPIO63 | |
+
+## LEDs
+
+Leds are not yet working as in stock firmware. This will be handled later.
+
+Ports 1-4 are amber for 100M/1G links, Green for 2.5G.
+Port 5-6 are green for 10G/1G link. Both should flash on activity.
+
+| NAME | When active |
+| ---------------- | ---------------|
+| PWR | 3V3 |
+| SFP1 | |
+| SFP2 | |
+| PORT1-LED-GREEN | - |
+| PORT2-LED-GREEN | PORT2 2.5G |
+| PORT3-LED-GREEN | PORT3 2.5G |
+| PORT4-LED-GREEN | PORT4 2.5G |
+| PORT1-LED-AMBER | PORT1 1GB/100M |
+| PORT2-LED-AMBER | PORT2 1GB/100M |
+| PORT3-LED-AMBER | PORT3 1GB/100M |
+| PORT4-LED-AMBER | PORT4 1GB/100M |
+
+## Power supply
+
+Input power is delivered via barell plug, `12V 1A` adapter was provided.
+Board has two supply rails. `0.95` and `3.3` volt.
+
+### `0.95` Core Voltage
+
+Voltage is made by a `APW8713` (U3).
+
+### `3.3` Voltage
+
+Voltage is crated regulated by chip marke as `GoIAT` (U2).
+
+## SFP SPI
+
+There is separate clock and data lines for both SFP modules. MSDA/MSCK 0 and 1 need to be enabled.
+
+SFP1 slot is connected to SPI0. SFP2 slot is connected to SPI1.
diff --git a/doc/devices/photos/TEG-S562/TEG-S562-v1.0R-bottom.jpg b/doc/devices/photos/TEG-S562/TEG-S562-v1.0R-bottom.jpg
new file mode 100644
index 0000000..e38d515
Binary files /dev/null and b/doc/devices/photos/TEG-S562/TEG-S562-v1.0R-bottom.jpg differ
diff --git a/doc/devices/photos/TEG-S562/TEG-S562-v1.0R-top.jpg b/doc/devices/photos/TEG-S562/TEG-S562-v1.0R-top.jpg
new file mode 100644
index 0000000..e630fcb
Binary files /dev/null and b/doc/devices/photos/TEG-S562/TEG-S562-v1.0R-top.jpg differ
diff --git a/doc/supported_devices.md b/doc/supported_devices.md
index d1e66ed..3170160 100644
--- a/doc/supported_devices.md
+++ b/doc/supported_devices.md
@@ -8,6 +8,7 @@ The following devices have been tested and are fully working:
- Lianguo LG-SWTGW218AS (RTL8373 + RTL8224 PHY: 8x 2.5GBit + 1x 10GBit SFP+)
- No-Name ZX-SWTGW215AS, managed version of kp-9000-6hx-x, ordered on
AliExpress as keepLINK 5+1 port managed
+- TrendNet TEG-S562 (RTL8372: 4x 2.5GBit + 2x 10GBit SFP+)
Other device based on RTL8272/3 that may work are described here: [Up-N-Atoms 2.5 GBit RTL Switch hacking guide]
(https://github.com/up-n-atom/SWTG118AS)
diff --git a/machine.c b/machine.c
index 84f1d2c..59bf438 100644
--- a/machine.c
+++ b/machine.c
@@ -100,4 +100,26 @@ __code const struct machine machine = {
.sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 },
.reset_pin = GPIO_NA,
};
+#elif defined MACHINE_TRENDNET_TEG_S562
+__code const struct machine machine = {
+ .machine_name = "Trendnet TEG-S562",
+ .isRTL8373 = 0,
+ .min_port = 3,
+ .max_port = 8,
+ .n_sfp = 2,
+ .log_to_phys_port = {0, 0, 0, 6, 1, 2, 3, 4, 5},
+ .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0},
+ .is_sfp = {0, 0, 0, 2, 0, 0, 0, 0, 1},
+ .sfp_port[0].pin_detect = GPIO36_PWM_OUT,
+ .sfp_port[0].pin_los = GPIO37,
+ .sfp_port[0].pin_tx_disable = GPIO51_I2C_SDA2_UART1_RX,
+ .sfp_port[0].sds = 0,
+ .sfp_port[0].i2c = { .sda = GPIO47_I2C_SDA0, .scl = GPIO46_I2C_SCL0 },
+ .sfp_port[1].pin_detect = GPIO38,
+ .sfp_port[1].pin_los = GPIO50_I2C_SCL2_UART1_TX,
+ .sfp_port[1].pin_tx_disable = GPIO54_ACL_BIT2_EN,
+ .sfp_port[1].sds = 1,
+ .sfp_port[1].i2c = { .sda = GPIO49_I2C_SDA1, .scl = GPIO48_I2C_SCL1 },
+ .reset_pin = GPIO_NA,
+};
#endif
diff --git a/machine.h b/machine.h
index b1051b3..24de207 100644
--- a/machine.h
+++ b/machine.h
@@ -11,6 +11,7 @@
// #define MACHINE_KP_9000_9XH_X_EU
// #define MACHINE_SWGT024_V2_0
// #define MACHINE_HORACO_ZX_SG4T2
+// #define MACHINE_TRENDNET_TEG_S562
// #define DEFAULT_8C_1SFP
diff --git a/rtl837x_port.c b/rtl837x_port.c
index dbd1715..448431f 100644
--- a/rtl837x_port.c
+++ b/rtl837x_port.c
@@ -422,17 +422,49 @@ uint16_t port_isolation_get(register uint8_t port)
}
-void port_eee_enable(uint8_t port) __banked
+void port_eee_enable(__xdata uint8_t port,__xdata uint8_t speed) __banked
{
- if (machine.is_sfp[port])
- return;
- REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100 | EEE_1000 | EEE_2G5);
- // Enable EEE advertisement for 100/1000BASE-T via EEE Advertisement Reg
- phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, PHY_EEE_BIT_1G | PHY_EEE_BIT_100M);
- // Enable EEE advertisement for 2.5GBASE-T via EEE Advertisement Reg 2
- phy_write(port, PHY_MMD_AN, PHY_EEE_ADV2, PHY_EEE_BIT_2G5);
- phy_reset(port);
+ if (machine.is_sfp[port])
+ {
+ print_string("EEE can't be enabled for SFP port "); print_byte(port); print_string("\n");
+ return;
+ }
+
+ print_string("EEE on for "); print_byte(port); print_string(" speed ");
+ // Enable all speeds up to the specified speed
+ if ((speed & (EEE_100 | EEE_1000 | EEE_2G5)) == EEE_100) {
+ print_string("100m\n");
+ REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100);
+ // Enable EEE advertisement for 100BASE-T via EEE Advertisement Reg
+ phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, PHY_EEE_BIT_100M);
+ if (!(speed & EEE_NORESET))
+ phy_reset(port);
+ return;
+ }
+ if ((speed & (EEE_100 | EEE_1000 | EEE_2G5)) == EEE_1000) {
+ print_string("1g\n");
+ REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100 | EEE_1000);
+ // Disable EEE advertisement for 2.5GBASE-T via EEE Advertisement Reg 2
+ phy_write(port, PHY_MMD_AN, PHY_EEE_ADV2, 0);
+ // Enable EEE advertisement for 100/1000BASE-T via EEE Advertisement Reg
+ phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, PHY_EEE_BIT_1G | PHY_EEE_BIT_100M);
+ if (!(speed & EEE_NORESET))
+ phy_reset(port);
+ return;
+ }
+ if ((speed & (EEE_100 | EEE_1000 | EEE_2G5)) == EEE_2G5) {
+ print_string("2g5\n");
+ REG_SET(RTL8373_EEE_CTRL_BASE + (port << 2), EEE_100 | EEE_1000 | EEE_2G5);
+ // Enable EEE advertisement for 100/1000BASE-T via EEE Advertisement Reg
+ phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, PHY_EEE_BIT_1G | PHY_EEE_BIT_100M);
+ // Enable EEE advertisement for 2.5GBASE-T via EEE Advertisement Reg 2
+ phy_write(port, PHY_MMD_AN, PHY_EEE_ADV2, PHY_EEE_BIT_2G5);
+ if (!(speed & EEE_NORESET))
+ phy_reset(port);
+ return;
+ }
+
}
@@ -506,10 +538,10 @@ void port_eee_status(uint8_t port) __banked
}
-void port_eee_enable_all(void) __banked
+void port_eee_enable_all(__xdata uint8_t speed) __banked
{
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
- port_eee_enable(i);
+ port_eee_enable(i, speed);
}
}
diff --git a/rtl837x_port.h b/rtl837x_port.h
index 22ea1dd..9049082 100644
--- a/rtl837x_port.h
+++ b/rtl837x_port.h
@@ -28,10 +28,10 @@ void port_ingress_filter(register uint8_t port, uint8_t type) __banked;
void port_l2_setup(void) __banked;
void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banked;
void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash) __banked;
-void port_eee_enable_all(void) __banked;
+void port_eee_enable_all(__xdata uint8_t speed) __banked;
void port_eee_disable_all(void) __banked;
void port_eee_status_all(void) __banked;
-void port_eee_enable(uint8_t port) __banked;
+void port_eee_enable(__xdata uint8_t port, __xdata uint8_t speed) __banked;
void port_eee_disable(uint8_t port) __banked;
void port_eee_status(uint8_t port) __banked;
#endif
diff --git a/rtl837x_regs.h b/rtl837x_regs.h
index cd7a2eb..fcb2928 100644
--- a/rtl837x_regs.h
+++ b/rtl837x_regs.h
@@ -257,6 +257,7 @@
#define EEE_100 0x01
#define EEE_1000 0x04
#define EEE_2G5 0x10
+#define EEE_NORESET 0x80
/*
* RANDOM
diff --git a/rtlplayground.c b/rtlplayground.c
index ad0aa8c..cd468dc 100644
--- a/rtlplayground.c
+++ b/rtlplayground.c
@@ -1637,6 +1637,9 @@ void rtl8373_init(void)
reg_bit_set(RTL837X_REG_HW_CONF, 0);
+ // enable EEE for all ports at 2.5G and 10G, but don't reset the PHYs
+ port_eee_enable_all(EEE_2G5 | EEE_NORESET);
+
// TODO: patch the PHYs
// Re-enable PHY after configuration
@@ -1700,6 +1703,10 @@ void rtl8372_init(void)
reg_bit_set(RTL837X_REG_HW_CONF, 0);
+
+ // enable EEE for all ports at 2.5G and 10G, but don't reset the PHYs
+ port_eee_enable_all(EEE_2G5 | EEE_NORESET);
+
// TODO: patch the PHYs
// Re-enable PHY after configuration
@@ -1954,6 +1961,8 @@ void bootloader(void)
REG_SET(RTL837X_PIN_MUX_2, 0x0); // Disable pins for ACL
init_smi();
+
+
rtl8373_revision();
if (machine_detected.isRTL8373)
rtl8373_init();