From ea230615f91aadbc8fb9afd43431ba87618ebf15 Mon Sep 17 00:00:00 2001 From: logicog Date: Sat, 7 Feb 2026 18:05:23 +0100 Subject: [PATCH 01/15] Use a MAC address based on the SoC's UUID We use the SoC's UUID to generate a fixed MAC for a particular switch device. The MAC generated uses a Realtek prefix and then is followed by 3 bytes genertaed from the first 3 bytes of the UUID xored with the last byte in order to prevent being able to deduce the UUID from the public MAC. --- dhcp.c | 9 ++++----- httpd/page_impl.c | 1 - rtl837x_common.h | 1 + rtl837x_regs.h | 4 +++- rtl837x_stp.c | 8 ++++---- rtlplayground.c | 22 ++++++++++++++++++++-- uip/uip.c | 2 -- uip/uip_arp.c | 10 +++++----- uip/uip_arp.h | 2 -- 9 files changed, 37 insertions(+), 22 deletions(-) diff --git a/dhcp.c b/dhcp.c index ed49b5e..9febcca 100644 --- a/dhcp.c +++ b/dhcp.c @@ -12,7 +12,6 @@ #include "uip.h" #include "uip/uip.h" -extern __code struct uip_eth_addr uip_ethaddr; __xdata struct dhcp_state dhcp_state; __xdata uip_ipaddr_t server; @@ -104,7 +103,7 @@ void dhcp_prepare_request(void) DHCP_P->flags = 0; // Clear fields client_ip to bootp_file memset(DHCP_P->client_ip, 0, 224); - memcpyc(DHCP_P->client_addr, uip_ethaddr.addr, 6); + memcpy(DHCP_P->client_addr, uip_ethaddr.addr, 6); DHCP_P->cookie[0] = 0x63; DHCP_P->cookie[1] = 0x82; DHCP_P->cookie[2] = 0x53; @@ -117,7 +116,7 @@ void dhcp_addopt_client_id(void) DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID; DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID_LEN; DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_HW_TYPE_ETH; - memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 6); + memcpy(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 6); dhcp_state.opt_ptr += 6; } @@ -130,7 +129,7 @@ void dhcp_addopt_request_ip(void) DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[1]; DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[2]; DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[3]; - memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4); + memcpy(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4); } @@ -142,7 +141,7 @@ void dhcp_addopt_server_id(void) DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[1]; DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[2]; DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[3]; - memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4); + memcpy(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4); } diff --git a/httpd/page_impl.c b/httpd/page_impl.c index aa7e38f..f8d810b 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -29,7 +29,6 @@ extern __xdata uint16_t cont_len; extern __xdata uint32_t cont_addr; extern __code uint8_t * __code hex; extern __xdata uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask; -extern __code struct uip_eth_addr uip_ethaddr; extern __xdata uint8_t sfr_data[4]; extern __xdata uint8_t sfp_pins_last; diff --git a/rtl837x_common.h b/rtl837x_common.h index 3ff6fb8..6f02ed3 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -79,6 +79,7 @@ struct flash_region_t { }; extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE+2]; +extern __xdata struct uip_eth_addr uip_ethaddr; // Headers for calls in the common code area (HOME/BANK0) void print_string(__code char *p); diff --git a/rtl837x_regs.h b/rtl837x_regs.h index fcb2928..b6d0e54 100644 --- a/rtl837x_regs.h +++ b/rtl837x_regs.h @@ -2,7 +2,9 @@ #define _RTL837X_REGS_H_ #define RTL837X_REG_CHIP_ID 0x0004 -#define RTL837X_REG_CHIP_INFO 0x000c +#define RTL837X_REG_CHIP_INFO 0x000c +#define RTL837X_REG_CHIP_UUID 0x0010 +#define RTL837X_REG_CHIP_LOT_NO 0x0014 #define RTL837X_REG_RESET 0x0024 #define RESET_SOC_BIT 0 #define RESET_NIC_BIT 2 diff --git a/rtl837x_stp.c b/rtl837x_stp.c index e04be9a..33c29f1 100644 --- a/rtl837x_stp.c +++ b/rtl837x_stp.c @@ -17,7 +17,7 @@ extern __code struct machine machine; extern __xdata uint8_t sfr_data[4]; -extern __code struct uip_eth_addr uip_ethaddr; +extern __xdata struct uip_eth_addr uip_ethaddr; extern __xdata uint8_t uip_buf[UIP_CONF_BUFFER_SIZE + 2]; @@ -164,9 +164,9 @@ void stp_cnf_send(uint8_t port) STP_O->bpdu_type = 0x00; // Config STP_O->flags = 0x81; - memcpyc(STP_O->src_addr, uip_ethaddr.addr, 6); + memcpy(STP_O->src_addr, uip_ethaddr.addr, 6); memcpy(STP_O->root.mac, root_bridge.mac, 6); - memcpyc(STP_O->bridge.mac, uip_ethaddr.addr, 6); + memcpy(STP_O->bridge.mac, uip_ethaddr.addr, 6); STP_O->root.prio = root_bridge.prio; STP_O->root.ext = 0x00; @@ -221,7 +221,7 @@ void stp_setup(void) __banked root_bridge.prio = 0x80; // This corresponds to 32768 root_bridge.ext = 0x00; - memcpyc(root_bridge.mac, uip_ethaddr.addr, 6); + memcpy(root_bridge.mac, uip_ethaddr.addr, 6); } diff --git a/rtlplayground.c b/rtlplayground.c index cd468dc..129b8e7 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -76,10 +76,11 @@ void crc16(__xdata uint8_t *v) __naked; __xdata uint8_t idle_ready; __code uint8_t ownIP[] = { 192, 168, 2, 2 }; -__code struct uip_eth_addr uip_ethaddr = {{ 0x1c, 0x2a, 0xa3, 0x23, 0x00, 0x02 }}; __code uint8_t gatewayIP[] = { 192, 168, 2, 22}; __code uint8_t netmask[] = { 255, 255, 255, 0}; +__xdata struct uip_eth_addr uip_ethaddr; + volatile __xdata uint32_t ticks; volatile __xdata uint8_t sec_counter; volatile __xdata uint16_t sleep_ticks; @@ -1958,11 +1959,28 @@ void bootloader(void) uip_ipaddr(&uip_hostaddr, ownIP[0], ownIP[1], ownIP[2], ownIP[3]); uip_ipaddr(&uip_draddr, gatewayIP[0], gatewayIP[1], gatewayIP[2], gatewayIP[3]); uip_ipaddr(&uip_netmask, netmask[0], netmask[1], netmask[2], netmask[3]); + reg_read_m(RTL837X_REG_CHIP_UUID); +#ifdef DEBUG + print_string("SoC UUID: "); print_sfr_data(); +#endif + uip_ethaddr.addr[0] = 0x06; // LAA prefix + uip_ethaddr.addr[3] = sfr_data[0] ^ sfr_data[3]; + uip_ethaddr.addr[4] = sfr_data[1] ^ sfr_data[3]; + uip_ethaddr.addr[5] = sfr_data[2] ^ sfr_data[3]; + reg_read_m(RTL837X_REG_CHIP_LOT_NO); +#ifdef DEBUG + print_string(", LOT: "); print_sfr_data(); write_char(' '); +#endif + uip_ethaddr.addr[1] = sfr_data[0] ^ sfr_data[2]; + uip_ethaddr.addr[2] = sfr_data[1] ^ sfr_data[3]; + print_string("Setting MAC to: "); + print_byte(uip_ethaddr.addr[0]); write_char(':'); print_byte(uip_ethaddr.addr[1]); write_char(':'); + print_byte(uip_ethaddr.addr[2]); write_char(':'); print_byte(uip_ethaddr.addr[3]); write_char(':'); + print_byte(uip_ethaddr.addr[4]); write_char(':'); print_byte(uip_ethaddr.addr[5]); write_char('\n'); REG_SET(RTL837X_PIN_MUX_2, 0x0); // Disable pins for ACL init_smi(); - rtl8373_revision(); if (machine_detected.isRTL8373) rtl8373_init(); diff --git a/uip/uip.c b/uip/uip.c index f2d6767..40c018c 100644 --- a/uip/uip.c +++ b/uip/uip.c @@ -132,8 +132,6 @@ static __code const uip_ipaddr_t all_zeroes_addr = {0x0000,0x0000}; #endif /* UIP_CONF_IPV6 */ -extern __code struct uip_eth_addr uip_ethaddr; - #ifndef UIP_CONF_EXTERNAL_BUFFER u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains incoming packets. */ diff --git a/uip/uip_arp.c b/uip/uip_arp.c index 160dab1..8c9b2a8 100644 --- a/uip/uip_arp.c +++ b/uip/uip_arp.c @@ -306,8 +306,8 @@ uip_arp_arpin(void) __banked BUF_O->opcode = HTONS(2); memcpy(BUF_O->dhwaddr.addr, BUF->shwaddr.addr, 6); - memcpyc(BUF_O->shwaddr.addr, uip_ethaddr.addr, 6); - memcpyc(BUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(BUF_O->shwaddr.addr, uip_ethaddr.addr, 6); + memcpy(BUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6); memcpy(BUF_O->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); BUF_O->dipaddr[0] = BUF->sipaddr[0]; @@ -399,8 +399,8 @@ uip_arp_out(void) __banked memset(BUF_O->ethhdr.dest.addr, 0xff, 6); memset(BUF_O->dhwaddr.addr, 0x00, 6); - memcpyc(BUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6); - memcpyc(BUF_O->shwaddr.addr, uip_ethaddr.addr, 6); + memcpy(BUF_O->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(BUF_O->shwaddr.addr, uip_ethaddr.addr, 6); uip_ipaddr_copy(BUF_O->dipaddr, ipaddr); uip_ipaddr_copy(BUF_O->sipaddr, uip_hostaddr); @@ -420,7 +420,7 @@ uip_arp_out(void) __banked /* Build an ethernet header. */ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); } - memcpyc(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); diff --git a/uip/uip_arp.h b/uip/uip_arp.h index 6c8840b..833d7c2 100644 --- a/uip/uip_arp.h +++ b/uip/uip_arp.h @@ -55,8 +55,6 @@ #include "uip.h" #include "../rtl837x_common.h" -extern __code struct uip_eth_addr uip_ethaddr; - /** * The Ethernet header. */ From ecf152990fbed4b05145394a7c9619c7060047ce Mon Sep 17 00:00:00 2001 From: logicog Date: Sat, 31 Jan 2026 13:37:16 +0100 Subject: [PATCH 02/15] Fix MACHINE_KP_9000_6XHML_X2: the SDS ids were swapped --- machine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/machine.c b/machine.c index 59bf438..60aeac7 100644 --- a/machine.c +++ b/machine.c @@ -14,12 +14,12 @@ __code const struct machine machine = { .sfp_port[0].pin_detect = GPIO50_I2C_SCL2_UART1_TX, .sfp_port[0].pin_los = GPIO10_LED10, .sfp_port[0].pin_tx_disable = GPIO_NA, - .sfp_port[0].sds = 1, + .sfp_port[0].sds = 0, .sfp_port[0].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 }, .sfp_port[1].pin_detect = GPIO30_ACL_BIT3_EN, .sfp_port[1].pin_los = GPIO37, .sfp_port[1].pin_tx_disable = GPIO_NA, - .sfp_port[1].sds = 0, + .sfp_port[1].sds = 1, .sfp_port[1].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, .reset_pin = GPIO46_I2C_SCL0, }; From 4747eac9bf1b55e96fc579781b5cf04f84488494 Mon Sep 17 00:00:00 2001 From: logicog Date: Sat, 7 Feb 2026 09:43:38 +0100 Subject: [PATCH 03/15] Reduce DSEG usage for parameters used in port/vlan configuration Currently 5 Bytes are used by the port and vlan configuration: -------------------------------------------------------- ; internal ram data ;-------------------------------------------------------- .area DSEG (DATA) _port_ingress_filter_PARM_2: .ds 1 _vlan_create_PARM_2: .ds 2 _vlan_create_PARM_3: .ds 2 They are used for passing parameters. Use __xdata to pass the parameters instead. --- rtl837x_port.c | 28 +++++++++++++++++----------- rtl837x_port.h | 12 ++++++++++-- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/rtl837x_port.c b/rtl837x_port.c index 448431f..322e60d 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -28,6 +28,8 @@ extern __xdata struct machine_runtime machine_detected; __xdata uint32_t l2_head; +__xdata struct vlan_settings vlan_settings; + void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked { print_string("\nport_mirror_set called \n"); @@ -46,7 +48,7 @@ void port_mirror_del(void) __banked } -void port_ingress_filter(register uint8_t port, uint8_t type) __banked +void port_ingress_filter(__xdata uint8_t port, __xdata uint8_t type) __banked { if (type & 0x1) reg_bit_set(RTL837x_REG_INGRESS, port << 1); @@ -121,27 +123,31 @@ __xdata uint16_t vlan_name(register uint16_t vlan) __banked /* + * Create a VLAN + * The arguments are passed in global structure vlan_settings * A member that is not tagged, is untagged */ -void vlan_create(register uint16_t vlan, register uint16_t members, register uint16_t tagged) __banked +void vlan_create(void) __banked { // For now, the CPU-port is always a tagged member: - members |= 0x0200; // Set 10th bit - tagged |= 0x0200; - print_string("\nvlan_create called\nvlan: "); print_short(vlan); - print_string(", members: "); print_short(members); - print_string(", tagged: "); print_short(tagged); write_char('\n'); + vlan_settings.members |= 0x0200; // Set 10th bit + vlan_settings.tagged |= 0x0200; + + print_string("\nvlan_create called\nvlan: "); print_short(vlan_settings.vlan); + print_string(", members: "); print_short(vlan_settings.members); + print_string(", tagged: "); print_short(vlan_settings.tagged); write_char('\n'); + + uint16_t a = (~vlan_settings.members) ^ vlan_settings.tagged ^ vlan_settings.members; - uint16_t a = (~members) ^ tagged ^ members; // On RTL8372, port-bits 0-2 must be 0, although they are not members if (!machine_detected.isRTL8373) { a &= 0x1f8; - tagged &= 0x3f8; + vlan_settings.tagged &= 0x3f8; } // Initialize VLAN table with VLAN 1 - REG_WRITE(RTL837x_TBL_DATA_IN_A, 0x02, (a >> 6) & 0x0f, (a << 2) | (members >> 8), members); - REG_WRITE(RTL837X_TBL_CTRL, vlan >> 8, vlan, TBL_VLAN, TBL_WRITE | TBL_EXECUTE); + REG_WRITE(RTL837x_TBL_DATA_IN_A, 0x02, (a >> 6) & 0x0f, (a << 2) | (vlan_settings.members >> 8), vlan_settings.members); + REG_WRITE(RTL837X_TBL_CTRL, vlan_settings.vlan >> 8, vlan_settings.vlan, TBL_VLAN, TBL_WRITE | TBL_EXECUTE); do { reg_read_m(RTL837X_TBL_CTRL); } while (sfr_data[3] & TBL_EXECUTE); diff --git a/rtl837x_port.h b/rtl837x_port.h index 9049082..480f2e8 100644 --- a/rtl837x_port.h +++ b/rtl837x_port.h @@ -13,6 +13,14 @@ reg_read_m(RTL837X_STAT_GET); \ } while (sfr_data[3] & 0x1); +struct vlan_settings { + uint16_t vlan; + uint16_t members; + uint16_t tagged; +}; + +extern __xdata struct vlan_settings vlan_settings; + uint8_t port_l2_forget(void) __banked; void port_l2_learned(void) __banked; void port_stats_print(void) __banked; @@ -20,11 +28,11 @@ int8_t vlan_get(register uint16_t vlan) __banked; __xdata uint16_t vlan_name(register uint16_t vlan) __banked; void vlan_setup(void) __banked; void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked; -void vlan_create(register uint16_t vlan, register uint16_t members, register uint16_t tagged) __banked; +void vlan_create(void) __banked; void vlan_delete(uint16_t vlan) __banked; void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked; void port_mirror_del(void) __banked; -void port_ingress_filter(register uint8_t port, uint8_t type) __banked; +void port_ingress_filter(__xdata uint8_t port, __xdata 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; From 9d074166414b8197937a5d474268b7b67d4a12bb Mon Sep 17 00:00:00 2001 From: logicog Date: Sat, 7 Feb 2026 16:20:27 +0100 Subject: [PATCH 04/15] Convert phy_set_duplex phy_set_speed to use struct phy_settings --- rtl837x_phy.c | 100 +++++++++++++++++++++++++------------------------- rtl837x_phy.h | 12 +++++- 2 files changed, 61 insertions(+), 51 deletions(-) diff --git a/rtl837x_phy.c b/rtl837x_phy.c index 97a4909..306057d 100644 --- a/rtl837x_phy.c +++ b/rtl837x_phy.c @@ -24,6 +24,8 @@ extern __code uint16_t bit_mask[16]; extern __code const struct machine machine; extern __xdata struct machine_runtime machine_detected; +__xdata struct phy_settings phy_settings; + // SDS-settings for RTL8224 first SerDes which is connected to the RTL837x-SOC. // Array contrains register-value, and SDS-CMD, which already encodes (sds_index, page, reg). // This array is used in phy_config_8224(). @@ -186,106 +188,106 @@ void phy_config_8224(void) __banked * See e.g. RTL8221B datasheet * duplex: 0: half, 1: full, 2: both */ -void phy_set_speed(uint8_t port, uint8_t speed, uint8_t duplex) __banked +void phy_set_speed(void) __banked { uint16_t v; - phy_read(port, PHY_MMD31, 0xa610); + phy_read(phy_settings.port, PHY_MMD31, 0xa610); v = SFR_DATA_U16; - if (speed == PHY_OFF) { - phy_write(port, PHY_MMD31, 0xa610, v | 0x0800); + if (phy_settings.speed == PHY_OFF) { + phy_write(phy_settings.port, PHY_MMD31, 0xa610, v | 0x0800); return; } // Port is on, make sure of it: if (v & 0x0800) - phy_write(port, PHY_MMD31, 0xa610, v & 0xf7ff); + phy_write(phy_settings.port, PHY_MMD31, 0xa610, v & 0xf7ff); - if (speed == PHY_SPEED_AUTO) { + if (phy_settings.speed == PHY_SPEED_AUTO) { // AN Advertisement Register (MMD 7.0x0010) // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used - phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x15e1); + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x15e1); // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD - phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081); + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081); // GBCR (1000Base-T Control Register, MMD 31.0xA412) - phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200); // Loop timing enabled - phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x3200); // Restart AN + phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200); // Loop timing enabled + phy_write(phy_settings.port, PHY_MMD31, PHY_ANEG_CTRL, 0x3200); // Restart AN } else { // AN Control Register (MMD 7.0x0000) - phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13) - if (speed == PHY_SPEED_10M) { - phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001); - if (!duplex) - phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1421); - else if (duplex == 1) - phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1441); + phy_write(phy_settings.port, PHY_MMD31, PHY_ANEG_CTRL, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13) + if (phy_settings.speed == PHY_SPEED_10M) { + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001); + if (!phy_settings.duplex) + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1421); + else if (phy_settings.duplex == 1) + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1441); else - phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1461); - phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000); - } else if (speed == PHY_SPEED_100M) { - phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001); - if (!duplex) - phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1481); - if (duplex == 1) - phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1501); + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1461); + phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000); + } else if (phy_settings.speed == PHY_SPEED_100M) { + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001); + if (!phy_settings.duplex) + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1481); + if (phy_settings.duplex == 1) + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1501); else - phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1581); - phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000); + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1581); + phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000); } else { // AN Advertisement Register (MMD 7.0x0010) // bits 0-4: 0x1 (802.3 supported), Extended Next Page format used - phy_write(port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1001); - if (speed == PHY_SPEED_1G) { + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0x1001); + if (phy_settings.speed == PHY_SPEED_1G) { // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) // bit 14: SLAVE, bit 13: Multi-Port device, 1: LD Loop timin enableed - phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001); + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001); // GBCR (1000Base-T Control Register, MMD 31.0xA412) - phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200); - } else if (speed == PHY_SPEED_2G5) { + phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200); + } else if (phy_settings.speed == PHY_SPEED_2G5) { // Multi-GBASE-TBASE-T AN Control 1 Register (MMD 7.0x0020) // bit 14: SLAVE, bit 13: Multi-Port device, bit 8: 2.5GBit available, 1: LD Loop timin enableed - phy_write(port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081); + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081); // GBCR (1000Base-T Control Register, MMD 31.0xA412) - phy_modify(port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000); + phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000); } } - phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x3000); // Enable AN + phy_write(phy_settings.port, PHY_MMD31, PHY_ANEG_CTRL, 0x3000); // Enable AN } } -void phy_set_duplex(uint8_t port, uint8_t fullduplex) __banked +void phy_set_duplex(void) __banked { uint16_t v; - phy_read(port, PHY_MMD31, PHY_ANEG_CTRL); + phy_read(phy_settings.port, PHY_MMD31, PHY_ANEG_CTRL); v = SFR_DATA_U16; if (!(v & 0x1000)) { // AN disabled, we are in forced mode - phy_read(port, PHY_MMD31, PHY_MMD31_FEDCR); + phy_read(phy_settings.port, PHY_MMD31, PHY_MMD31_FEDCR); v = SFR_DATA_U16; - if (fullduplex) + if (phy_settings.duplex) v |= 0x0100; else v &= 0xfeff; - phy_write(port, PHY_MMD31, PHY_MMD31_FEDCR, v); + phy_write(phy_settings.port, PHY_MMD31, PHY_MMD31_FEDCR, v); return; } // Disable AN - phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x2000); - phy_read(port, PHY_MMD_AN, PHY_ANEG_ADV); + phy_write(phy_settings.port, PHY_MMD31, PHY_ANEG_CTRL, 0x2000); + phy_read(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV); v = SFR_DATA_U16; if (v & 0x0060) { - if (fullduplex) - phy_modify(port, PHY_MMD_AN, PHY_ANEG_ADV, 0xffbf, 0x0040); + if (phy_settings.duplex) + phy_modify(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0xffbf, 0x0040); else - phy_modify(port, PHY_MMD_AN, PHY_ANEG_ADV, 0xffdf, 0x0020); + phy_modify(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0xffdf, 0x0020); } if (v & 0x0180) { - if (fullduplex) - phy_modify(port, PHY_MMD_AN, PHY_ANEG_ADV, 0xfeff, 0x0100); + if (phy_settings.duplex) + phy_modify(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0xfeff, 0x0100); else - phy_modify(port, PHY_MMD_AN, PHY_ANEG_ADV, 0xff7f, 0x0080); + phy_modify(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0xff7f, 0x0080); } // Restart AN - phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x3000); + phy_write(phy_settings.port, PHY_MMD31, PHY_ANEG_CTRL, 0x3000); } diff --git a/rtl837x_phy.h b/rtl837x_phy.h index 0b01e45..84ab214 100644 --- a/rtl837x_phy.h +++ b/rtl837x_phy.h @@ -10,11 +10,19 @@ #define PHY_SPEED_AUTO 0x10 #define PHY_OFF 0xff +struct phy_settings { + uint8_t duplex; + uint8_t port; + uint8_t speed; +}; + +extern __xdata struct phy_settings phy_settings; + void rtl8224_phy_enable(void) __banked; void phy_config(uint8_t phy) __banked; void phy_config_8224(void) __banked; -void phy_set_speed(uint8_t port, uint8_t speed, uint8_t duplex) __banked; -void phy_set_duplex(uint8_t port, uint8_t fullduplex) __banked; +void phy_set_speed(void) __banked; +void phy_set_duplex(void) __banked; void phy_show(uint8_t port) __banked; void phy_reset(uint8_t port) __banked; void rtl8224_read_reg_u16(uint16_t reg) __banked; From 708b6b7f28d6c06030f4f98cf397072091c99f4a Mon Sep 17 00:00:00 2001 From: logicog Date: Sat, 7 Feb 2026 16:21:17 +0100 Subject: [PATCH 05/15] Use new signatures for vlan_create and phy-settings --- cmd_parser.c | 77 ++++++++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/cmd_parser.c b/cmd_parser.c index 21e1d1c..33e4101 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -282,17 +282,17 @@ void parse_lag_hash(void) void parse_vlan(void) { - __xdata uint16_t vlan; - __xdata uint16_t members = 0; - __xdata uint16_t tagged = 0; - if (!atoi_short(&vlan, cmd_words_b[1])) { + vlan_settings.vlan = 0; + vlan_settings.members = 0; + vlan_settings.tagged = 0; + if (!atoi_short(&vlan_settings.vlan, cmd_words_b[1])) { if (cmd_words_b[2] > 0 && cmd_buffer[cmd_words_b[2]] == 'd' && cmd_words_b[3] < 0) { - vlan_delete(vlan); + vlan_delete(vlan_settings.vlan); return; } if (cmd_words_b[2] > 0 && cmd_compare(2, "mgmt")) { - management_vlan = vlan; - if (!vlan) + management_vlan = vlan_settings.vlan; + if (!vlan_settings.vlan) print_string("Management VLAN disabled\n"); else print_string("Management VLAN set to "); print_short(management_vlan); write_char('\n'); @@ -301,9 +301,9 @@ void parse_vlan(void) uint8_t w = 2; if (cmd_words_b[w] > 0 && isletter(cmd_buffer[cmd_words_b[w]])) { register uint8_t i = 0; - vlan_names[vlan_ptr++] = hex[(vlan >> 8) & 0xf]; - vlan_names[vlan_ptr++] = hex[(vlan >> 4) & 0xf] ; - vlan_names[vlan_ptr++] = hex[vlan & 0xf]; + vlan_names[vlan_ptr++] = hex[(vlan_settings.vlan >> 8) & 0xf]; + vlan_names[vlan_ptr++] = hex[(vlan_settings.vlan >> 4) & 0xf] ; + vlan_names[vlan_ptr++] = hex[vlan_settings.vlan & 0xf]; while(cmd_buffer[cmd_words_b[w] + i] != ' ') { write_char(cmd_buffer[cmd_words_b[w] + i]); vlan_names[vlan_ptr++] = cmd_buffer[cmd_words_b[w] + i++]; @@ -313,25 +313,25 @@ void parse_vlan(void) print_string("<\n"); } while (cmd_words_b[w] > 0) { - uint8_t port; + __xdata uint8_t port; if (isnumber(cmd_buffer[cmd_words_b[w]])) { port = cmd_buffer[cmd_words_b[w]] - '1'; if (isnumber(cmd_buffer[cmd_words_b[w] + 1])) { port = (port + 1) * 10 + cmd_buffer[cmd_words_b[w] + 1] - '1'; if (cmd_buffer[cmd_words_b[w] + 2] == 't') - tagged |= ((uint16_t)1) << port; + vlan_settings.tagged |= ((uint16_t)1) << port; } else { port = machine.phys_to_log_port[port]; if (cmd_buffer[cmd_words_b[w] + 1] == 't') - tagged |= ((uint16_t)1) << port; + vlan_settings.tagged |= ((uint16_t)1) << port; } if (port > machine.max_port) goto err; - members |= ((uint16_t)1) << port; + vlan_settings.members |= ((uint16_t)1) << port; } w++; } - vlan_create(vlan, members, tagged); + vlan_create(); } if (cmd_words_b[2] > 0 && isletter(cmd_buffer[cmd_words_b[2]])) { print_string("vlan_ptr "); print_short(vlan_ptr); write_char(':'); @@ -422,10 +422,10 @@ void parse_mirror(void) void parse_port(void) { print_string("\nPORT "); - uint8_t p = cmd_buffer[cmd_words_b[1]] - '1'; - p = machine.phys_to_log_port[p]; - print_byte(p); - if (machine.is_sfp[p]) { + phy_settings.port = cmd_buffer[cmd_words_b[1]] - '1'; + phy_settings.port = machine.phys_to_log_port[phy_settings.port]; + print_byte(phy_settings.port); + if (machine.is_sfp[phy_settings.port]) { print_string(" is SFP no PHY information available.\n"); return; } @@ -433,46 +433,53 @@ void parse_port(void) print_string("\nport [show|on|off|10m|100m|1g|2g5] [half|full]"); return; } + phy_settings.duplex = PHY_DUPLEX_BOTH; if (cmd_compare(2, "10m")) { print_string(" 10M\n"); + phy_settings.speed = PHY_SPEED_10M; if (cmd_words_b[3] > 0 && cmd_compare(3, "half")) - phy_set_speed(p, PHY_SPEED_10M, PHY_DUPLEX_HALF); + phy_settings.duplex = PHY_DUPLEX_HALF; else if (cmd_words_b[3] > 0 && cmd_compare(3, "full")) - phy_set_speed(p, PHY_SPEED_10M, PHY_DUPLEX_FULL); - else - phy_set_speed(p, PHY_SPEED_10M, PHY_DUPLEX_BOTH); + phy_settings.duplex = PHY_DUPLEX_FULL; + phy_set_speed(); } else if (cmd_compare(2, "100m")) { print_string(" 100M\n"); + phy_settings.speed = PHY_SPEED_100M; if (cmd_words_b[3] > 0 && cmd_compare(3, "half")) - phy_set_speed(p, PHY_SPEED_100M, PHY_DUPLEX_HALF); + phy_settings.duplex = PHY_DUPLEX_HALF; else if (cmd_words_b[3] > 0 && cmd_compare(3, "full")) - phy_set_speed(p, PHY_SPEED_100M, PHY_DUPLEX_FULL); - else - phy_set_speed(p, PHY_SPEED_100M, PHY_DUPLEX_BOTH); + phy_settings.duplex = PHY_DUPLEX_FULL; + phy_set_speed(); } else if (cmd_compare(2, "2g5")) { print_string(" 2.5G\n"); - phy_set_speed(p, PHY_SPEED_2G5, PHY_DUPLEX_BOTH); + phy_settings.speed = PHY_SPEED_2G5; + phy_set_speed(); } else if (cmd_compare(2, "1g")) { print_string(" 1G\n"); - phy_set_speed(p, PHY_SPEED_1G, PHY_DUPLEX_BOTH); + phy_settings.speed = PHY_SPEED_1G; + phy_set_speed(); } else if (cmd_compare(2, "auto")) { print_string(" AUTO\n"); - phy_set_speed(p, PHY_SPEED_AUTO, PHY_DUPLEX_BOTH); + phy_settings.speed = PHY_SPEED_AUTO; + phy_set_speed(); } else if (cmd_compare(2, "off")) { print_string(" OFF\n"); - phy_set_speed(p, PHY_OFF, PHY_DUPLEX_BOTH); + phy_settings.speed = PHY_OFF; + phy_set_speed(); } else if (cmd_compare(2, "on")) { print_string(" ON\n"); - phy_set_speed(p, PHY_SPEED_AUTO, PHY_DUPLEX_BOTH); + phy_settings.speed = PHY_SPEED_AUTO; + phy_set_speed(); } else if (cmd_compare(2, "duplex")) { print_string(" DUPLEX\n"); if (cmd_words_b[3] > 0 && cmd_compare(3, "full")) - phy_set_duplex(p, PHY_DUPLEX_FULL); + phy_settings.speed = PHY_DUPLEX_FULL; else - phy_set_duplex(p, PHY_DUPLEX_HALF); + phy_settings.speed = PHY_DUPLEX_HALF; + phy_set_duplex(); } if (cmd_words_b[2] > 0 && cmd_compare(2, "show")) { - phy_show(p); + phy_show(phy_settings.port); } } From d83f91f9e8a992d081c936f65ad95c822ed46a1b Mon Sep 17 00:00:00 2001 From: logicog Date: Sat, 7 Feb 2026 16:24:58 +0100 Subject: [PATCH 06/15] Fix Auto-negotiation Commit 7f4c276 used the wrong MMD device for use with the auto-negotiation page: - phy_write(port, PHY_MMD_AN, 0x00, 0x3200); // Restart AN + phy_write(port, PHY_MMD31, PHY_ANEG_CTRL, 0x3200); // Restart AN Fix this. --- rtl837x_phy.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/rtl837x_phy.c b/rtl837x_phy.c index 306057d..b4e944a 100644 --- a/rtl837x_phy.c +++ b/rtl837x_phy.c @@ -210,10 +210,10 @@ void phy_set_speed(void) __banked phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6081); // GBCR (1000Base-T Control Register, MMD 31.0xA412) phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0000, 0x0200); // Loop timing enabled - phy_write(phy_settings.port, PHY_MMD31, PHY_ANEG_CTRL, 0x3200); // Restart AN + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x3200); // Restart AN } else { // AN Control Register (MMD 7.0x0000) - phy_write(phy_settings.port, PHY_MMD31, PHY_ANEG_CTRL, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13) + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x2000); // Clear bit 12: No Autoneg, Set Extended Pages (bit 13) if (phy_settings.speed == PHY_SPEED_10M) { phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_MGBASE_CTRL, 0x6001); if (!phy_settings.duplex) @@ -250,7 +250,7 @@ void phy_set_speed(void) __banked phy_modify(phy_settings.port, PHY_MMD31, PHY_MMD31_GBCR, 0x0200, 0x0000); } } - phy_write(phy_settings.port, PHY_MMD31, PHY_ANEG_CTRL, 0x3000); // Enable AN + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x3000); // Enable AN } } @@ -258,7 +258,7 @@ void phy_set_speed(void) __banked void phy_set_duplex(void) __banked { uint16_t v; - phy_read(phy_settings.port, PHY_MMD31, PHY_ANEG_CTRL); + phy_read(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL); v = SFR_DATA_U16; if (!(v & 0x1000)) { // AN disabled, we are in forced mode phy_read(phy_settings.port, PHY_MMD31, PHY_MMD31_FEDCR); @@ -271,7 +271,7 @@ void phy_set_duplex(void) __banked return; } // Disable AN - phy_write(phy_settings.port, PHY_MMD31, PHY_ANEG_CTRL, 0x2000); + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x2000); phy_read(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV); v = SFR_DATA_U16; if (v & 0x0060) { @@ -287,7 +287,7 @@ void phy_set_duplex(void) __banked phy_modify(phy_settings.port, PHY_MMD_AN, PHY_ANEG_ADV, 0xff7f, 0x0080); } // Restart AN - phy_write(phy_settings.port, PHY_MMD31, PHY_ANEG_CTRL, 0x3000); + phy_write(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL, 0x3000); } @@ -329,7 +329,7 @@ void phy_show(uint8_t port) __banked else print_string(" half duplex"); - phy_read(port, PHY_MMD31, PHY_ANEG_CTRL); + phy_read(port, PHY_MMD_AN, PHY_ANEG_CTRL); v = SFR_DATA_U16; if (!(v & 0x1000)) { // AN disabled, we are in forced mode phy_read(port, PHY_MMD_PMAPMD, 0); From 47878ac580262b9bf8e20338ef9d02fc7caf8e1f Mon Sep 17 00:00:00 2001 From: logicog Date: Sat, 7 Feb 2026 16:30:21 +0100 Subject: [PATCH 07/15] Add more printout --- rtl837x_phy.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/rtl837x_phy.c b/rtl837x_phy.c index b4e944a..0846e9c 100644 --- a/rtl837x_phy.c +++ b/rtl837x_phy.c @@ -191,6 +191,43 @@ void phy_config_8224(void) __banked void phy_set_speed(void) __banked { uint16_t v; + + print_string("Setting port "); write_char(machine.log_to_phys_port[phy_settings.port] + '0'); + if (phy_settings.speed == PHY_OFF) { + print_string(" to disabled"); + } else { + print_string(" to speed "); + switch(phy_settings.speed) { + case PHY_SPEED_AUTO: + print_string("auto"); + break; + case PHY_SPEED_10M: + print_string("10M"); + if (phy_settings.duplex) + print_string(" full duplex"); + else + print_string(" half duplex"); + break; + case PHY_SPEED_100M: + print_string("100M"); + if (phy_settings.duplex) + print_string(" full duplex"); + else + print_string(" half duplex"); + break; + case PHY_SPEED_1G: + print_string("1G"); + break; + case PHY_SPEED_2G5: + print_string("2G5"); + break; + default: + print_string("UNKNOWN"); + break; + } + } + write_char('\n'); + phy_read(phy_settings.port, PHY_MMD31, 0xa610); v = SFR_DATA_U16; if (phy_settings.speed == PHY_OFF) { @@ -258,6 +295,14 @@ void phy_set_speed(void) __banked void phy_set_duplex(void) __banked { uint16_t v; + + print_string("Setting port "); write_char(machine.log_to_phys_port[phy_settings.port] + '0'); + if (phy_settings.duplex) + print_string(" to full duplex"); + else + print_string(" to half duplex"); + write_char('\n'); + phy_read(phy_settings.port, PHY_MMD_AN, PHY_ANEG_CTRL); v = SFR_DATA_U16; if (!(v & 0x1000)) { // AN disabled, we are in forced mode From 7a57416e4c7287f1a41b2bdc828caeb8dd16e4e3 Mon Sep 17 00:00:00 2001 From: logicog Date: Thu, 29 Jan 2026 19:03:02 +0100 Subject: [PATCH 08/15] Add MACHINE_HG0402XG_V1_1 --- machine.c | 22 ++++++++++++++++++++++ machine.h | 2 +- rtl837x_regs.h | 1 + rtlplayground.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/machine.c b/machine.c index 60aeac7..aaa5303 100644 --- a/machine.c +++ b/machine.c @@ -83,6 +83,28 @@ __code const struct machine machine = { .reset_pin = GPIO36_PWM_OUT, }; +#elif defined MACHINE_HG0402XG_V1_1 +__code const struct machine machine = { + .machine_name = "HG0402XG V1.1", + .isRTL8373 = 0, + .min_port = 3, + .max_port = 8, + .n_sfp = 2, + .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, + .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 = 50, + .sfp_port[0].pin_los = 10, + .sfp_port[0].pin_tx_disable = 0xFF, + .sfp_port[0].sds = 1, + .sfp_port[0].i2c_bus ={ .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 }, + .sfp_port[1].pin_detect = 30, + .sfp_port[1].pin_los = 51, + .sfp_port[1].pin_tx_disable = 0xFF, + .sfp_port[1].sds = 0, + .sfp_port[1].i2c_bus = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, +}; + #elif defined DEFAULT_8C_1SFP __code const struct machine machine = { .machine_name = "8+1 SFP Port Switch", diff --git a/machine.h b/machine.h index 24de207..5bb02ce 100644 --- a/machine.h +++ b/machine.h @@ -12,7 +12,7 @@ // #define MACHINE_SWGT024_V2_0 // #define MACHINE_HORACO_ZX_SG4T2 // #define MACHINE_TRENDNET_TEG_S562 - +// #define MACHINE_HG0402XG_V1_1 // #define DEFAULT_8C_1SFP // #define DEFAULT_5C_1SFP diff --git a/rtl837x_regs.h b/rtl837x_regs.h index b6d0e54..473024a 100644 --- a/rtl837x_regs.h +++ b/rtl837x_regs.h @@ -24,6 +24,7 @@ // Blink rate is defined by setAsicRegBits(0x6520,0xe00000,rate); #define RTL837X_REG_LED_GLB_IO_EN 0x65DC #define RTL837X_REG_LED3_0_SET1 0x6528 +#define RTL837X_REG_LED1_0_SET1 0x6540 #define RTL837X_REG_LED3_2_SET0 0x6544 #define RTL837X_REG_LED1_0_SET0 0x6548 diff --git a/rtlplayground.c b/rtlplayground.c index 129b8e7..add7643 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -1500,6 +1500,44 @@ void set_sys_led_state(uint8_t state) reg_write_m(RTL837X_REG_LED_MODE); } + +#ifdef MACHINE_HG0402XG_V1_1 +void led_config(void) +{ + reg_read_m(RTL837X_REG_LED_MODE); + sfr_mask_data(2, 0xe0, 0x23); // Mask blink rate field (0xe0), set blink rate and LED to solid (set bit 1 = bit 17 overal + // Configure led-mode (serial?) + sfr_data[2] = 0xe6; + sfr_data[3] = 0xb0; + reg_write_m(RTL837X_REG_LED_MODE); + // Disable RLDP (Realtek Loop Detection Protocol) LEDs on loop detection + reg_read_m(RTL837X_REG_LED_RLDP_1); + sfr_mask_data(0, 0x03, 0); + reg_write_m(RTL837X_REG_LED_RLDP_1); + REG_SET(RTL837X_REG_LED_RLDP_2, 0xffff0000); // Ports 0-7 0x65fc + REG_SET(RTL837X_REG_LED_RLDP_3, 0x0000000f); // Port 8 + + reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 29); + reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 27); + reg_bit_set(RTL837X_PIN_MUX_0, 29); + reg_bit_set(RTL837X_PIN_MUX_0, 27); + + REG_SET(RTL837X_REG_LED1_0_SET0, 0x141); // 0x6548 + reg_read_m(RTL837X_REG_LED3_2_SET0); + sfr_data[2] = 0x01; + sfr_data[3] = 0x74; + reg_write_m(RTL837X_REG_LED3_2_SET0); + reg_read_m(RTL837X_REG_LED1_0_SET1); // 6540 + sfr_data[2] = 0x01; + sfr_data[3] = 0x7f; + reg_write_m(RTL837X_REG_LED1_0_SET1); + + reg_read_m(RTL837X_REG_LED3_0_SET1); + sfr_data[1] |= 0x0f; + reg_write_m(RTL837X_REG_LED3_0_SET1); +} + +#else void led_config(void) { // LED initialization @@ -1548,6 +1586,7 @@ void led_config(void) sfr_data[3] = 0x11; reg_write_m(RTL837X_REG_LED3_0_SET1); } +#endif void rtl8373_revision(void) { @@ -1992,7 +2031,7 @@ void bootloader(void) flash_region.addr = FIRMWARE_UPLOAD_START; flash_region.len = 0x100; flash_read_bulk(flash_buf); - +#ifndef MACHINE_HG0402XG_V1_1 if (flash_buf[0] == 0x00 && flash_buf[1] == 0x40) { __xdata uint32_t dest = 0x0; __xdata uint32_t source = FIRMWARE_UPLOAD_START; @@ -2063,7 +2102,7 @@ void bootloader(void) dest += 0x1000; } } - +#endif set_sys_led_state(SYS_LED_SLOW); #ifdef DEBUG From 9424aa3a3b0258e5976f86406b65e7ca7f9b5d86 Mon Sep 17 00:00:00 2001 From: logicog Date: Sat, 31 Jan 2026 13:41:02 +0100 Subject: [PATCH 09/15] LED configuration support --- Makefile | 2 +- rtl837x_leds.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++ rtl837x_leds.h | 7 +++ rtl837x_regs.h | 6 +++ rtlplayground.c | 2 + 5 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 rtl837x_leds.c create mode 100644 rtl837x_leds.h diff --git a/Makefile b/Makefile index fb02001..a6a2bf5 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)rtlplayground.bin create_build_dir: mkdir -p $(BUILDDIR) -SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c rtl837x_stp.c rtl837x_pins.c dhcp.c machine.c +SRCS = rtlplayground.c rtl837x_flash.c rtl837x_leds.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c rtl837x_stp.c rtl837x_pins.c dhcp.c machine.c OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel} OBJS += uip/$(BUILDDIR)/timer.rel uip/$(BUILDDIR)/uip-fw.rel uip/$(BUILDDIR)/uip-neighbor.rel uip/$(BUILDDIR)/uip-split.rel uip/$(BUILDDIR)/uip.rel uip/$(BUILDDIR)/uip_arp.rel uip/$(BUILDDIR)/uiplib.rel httpd/$(BUILDDIR)/httpd.rel httpd/$(BUILDDIR)/page_impl.rel diff --git a/rtl837x_leds.c b/rtl837x_leds.c new file mode 100644 index 0000000..4bf38e0 --- /dev/null +++ b/rtl837x_leds.c @@ -0,0 +1,130 @@ +/* + * This is a driver implementation for the IGMP features for the RTL827x platform + * This code is in the Public Domain + */ + +// #define REGDBG +// #define DEBUG + +#define IPMC_USES_L3MC + +#include +#include "rtl837x_common.h" +#include "rtl837x_sfr.h" +#include "rtl837x_regs.h" +#include "rtl837x_leds.h" +#include "machine.h" + +extern __code struct machine machine; + +#include "uip.h" + +#pragma codeseg BANK2 +#pragma constseg BANK2 + +extern __xdata uint8_t sfr_data[4]; + +void leds_dump(void) __banked +{ + print_string("RTL837X_REG_LED_GLB_IO_EN: "); print_reg(RTL837X_REG_LED_GLB_IO_EN); write_char('\n'); + print_string("RTL837X_REG_LED1_0_SET0: "); print_reg(RTL837X_REG_LED1_0_SET0); write_char('\n'); + print_string("RTL837X_REG_LED3_2_SET0: "); print_reg(RTL837X_REG_LED3_2_SET0); write_char('\n'); + print_string("RTL837X_REG_LED1_0_SET1: "); print_reg(RTL837X_REG_LED1_0_SET1); write_char('\n'); + print_string("RTL837X_REG_LED3_2_SET1: "); print_reg(RTL837X_REG_LED3_2_SET1); write_char('\n'); + print_string("RTL837X_REG_LED1_0_SET2: "); print_reg(RTL837X_REG_LED1_0_SET2); write_char('\n'); + print_string("RTL837X_REG_LED3_2_SET2: "); print_reg(RTL837X_REG_LED3_2_SET2); write_char('\n'); + print_string("RTL837X_REG_LED1_0_SET3: "); print_reg(RTL837X_REG_LED1_0_SET3); write_char('\n'); + print_string("RTL837X_REG_LED3_0_SET1: "); print_reg(RTL837X_REG_LED3_0_SET1); write_char('\n'); + print_string("RTL837X_REG_LED3_0_SET3: "); print_reg(RTL837X_REG_LED3_0_SET3); write_char('\n'); + print_string("RTL837X_LED_PORT_SET_SEL: "); print_reg(RTL837X_LED_PORT_SET_SEL); write_char('\n'); + print_string("LED Configuration:\n"); + print_string("LED-ID\t\t0\t\t1\t\t2\t\t3\n"); + for (uint8_t set = 0; set < 4; set++) { + print_string("SET "); write_char('0' + set); write_char(':'); + for (uint8_t ledid = 0; ledid < 4; ledid++) { + print_string("\t "); + uint8_t b; + if (set < 2) { + reg_read_m(RTL837X_REG_LED3_0_SET1); + b = sfr_data[3-((set << 1) + (ledid >> 1))]; + print_byte(ledid & 1 ? b >> 4 : b & 0xf); + } else { + reg_read_m(RTL837X_REG_LED3_0_SET3); + b = sfr_data[3-(((set-2) << 1) + (ledid >> 1))]; + print_byte(ledid & 1 ? b >> 4 : b & 0xf); + } + reg_read_m(RTL837X_REG_LED1_0_SET0 - set * 8 - ((ledid >> 1) * 4)); + if (! (ledid & 1)) { // LEDID 0, 2 + print_byte(sfr_data[2]); print_byte(sfr_data[3]); + } else { + print_byte(sfr_data[0]); print_byte(sfr_data[1]); + } + } + write_char('\n'); + } + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + reg_read_m(RTL837X_LED_PORT_SET_SEL); + uint8_t set = sfr_data[3 - (i >> 2)]; + set = (set >> ((i & 3) << 1)); + print_string("Port "); write_char('0' + i); print_string(": SET "); + write_char('0' + set); + print_string(": "); + for (uint8_t ledid = 0; ledid < 4; ledid++) { + write_char('('); + reg_read_m(RTL837X_REG_LED1_0_SET0 - set * 8 - ((ledid >> 1) * 4)); + if (ledid & 1) { // LEDID 1, 3 + sfr_data[2] = sfr_data[0]; + sfr_data[3] = sfr_data[1]; + } + if (sfr_data[3] & 0x01) + print_string(" 2G5"); + if (sfr_data[3] & 0x02) + print_string(" TWO_1G"); + if (sfr_data[3] & 0x04) + print_string(" 1G"); + if (sfr_data[3] & 0x08) + print_string(" 500M"); + if (sfr_data[3] & 0x10) + print_string(" 100M"); + if (sfr_data[3] & 0x20) + print_string(" 10M"); + if (sfr_data[3] & 0x40) + print_string(" LINK"); + if (sfr_data[3] & 0x80) + print_string(" LINK_FLASH"); + if (sfr_data[2] & 0x01) + print_string(" ACT"); + if (sfr_data[2] & 0x02) + print_string(" RX"); + if (sfr_data[2] & 0x04) + print_string(" TX"); + if (sfr_data[2] & 0x00) + print_string(" COL"); + if (sfr_data[2] & 0x10) + print_string(" DUPLEX"); + if (sfr_data[2] & 0x20) + print_string(" TRAINING"); + if (sfr_data[2] & 0x40) + print_string(" MASTER"); + uint8_t b; + if (set < 2) { + reg_read_m(RTL837X_REG_LED3_0_SET1); + b = sfr_data[3-((set << 1) + (ledid >> 1))]; + } else { + reg_read_m(RTL837X_REG_LED3_0_SET3); + b = sfr_data[3-(((set-2) << 1) + (ledid >> 1))]; + } + b = ledid & 1 ? b >> 4 : b & 0xf; + if (b & 0x1) + print_string(" 10G"); + if (b & 0x2) + print_string(" TWO_5G"); + if (b & 0x4) + print_string(" 5G"); + if (b & 0x8) + print_string(" TWO_2G5"); + print_string("), "); + } + write_char('\n'); + } +} diff --git a/rtl837x_leds.h b/rtl837x_leds.h new file mode 100644 index 0000000..e616c31 --- /dev/null +++ b/rtl837x_leds.h @@ -0,0 +1,7 @@ +#ifndef _RTL837X_LEDS_H_ +#define _RTL837X_LEDS_H_ + +#include +void leds_dump(void) __banked; + +#endif diff --git a/rtl837x_regs.h b/rtl837x_regs.h index 473024a..6232a42 100644 --- a/rtl837x_regs.h +++ b/rtl837x_regs.h @@ -23,10 +23,16 @@ // Bytes 0/1 hold the LED mode, e.g. serial, RTL8231? // Blink rate is defined by setAsicRegBits(0x6520,0xe00000,rate); #define RTL837X_REG_LED_GLB_IO_EN 0x65DC +#define RTL837X_REG_LED3_0_SET3 0x6524 #define RTL837X_REG_LED3_0_SET1 0x6528 +#define RTL837X_REG_LED1_0_SET3 0x6530 +#define RTL837X_REG_LED3_2_SET2 0x6534 +#define RTL837X_REG_LED1_0_SET2 0x6538 +#define RTL837X_REG_LED3_2_SET1 0x653C #define RTL837X_REG_LED1_0_SET1 0x6540 #define RTL837X_REG_LED3_2_SET0 0x6544 #define RTL837X_REG_LED1_0_SET0 0x6548 +#define RTL837X_LED_PORT_SET_SEL 0x654c // SMI control #define RTL837X_REG_SMI_PORT0_5_ADDR 0x644C diff --git a/rtlplayground.c b/rtlplayground.c index add7643..f0989fe 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -13,6 +13,7 @@ #include "rtl837x_port.h" #include "rtl837x_stp.h" #include "rtl837x_igmp.h" +#include "rtl837x_leds.h" #include "dhcp.h" #include "cmd_parser.h" #include "uip/uipopt.h" @@ -2104,6 +2105,7 @@ void bootloader(void) } #endif set_sys_led_state(SYS_LED_SLOW); + leds_dump(); #ifdef DEBUG // This register seems to work on the RTL8373 only if also the SDS From 196e430ec63df11726573a84aeefe56658be1933 Mon Sep 17 00:00:00 2001 From: logicog Date: Sat, 31 Jan 2026 13:09:06 +0100 Subject: [PATCH 10/15] Remove debug output --- rtl837x_igmp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rtl837x_igmp.c b/rtl837x_igmp.c index 21dadf4..e36dda6 100644 --- a/rtl837x_igmp.c +++ b/rtl837x_igmp.c @@ -118,11 +118,8 @@ void igmp_setup(void) __banked * For now the IGMP protocols are flooded (01), MLD which MAC-based is handled by ASIC * All messages are allowed and maximum MC group is 0xff */ - for (i = machine.min_port; i <= machine.max_port; i++) { - print_byte(i); write_char(':'); + for (i = machine.min_port; i <= machine.max_port; i++) REG_SET(RTL837X_IGMP_PORT_CFG + (i << 2), IGMP_MAX_GROUP | IGMP_PROTOCOL_ENABLE | IGMP_FLOOD); - write_char('\n'); - } /* // Allow all physical ports to be dynamic router ports reg_read_m(RTL837X_IGMP_ROUTER_PORT); From 9aaddcd9b9e55eba86e3841e58f752815586b887 Mon Sep 17 00:00:00 2001 From: logicog Date: Sun, 25 Jan 2026 10:36:03 +0100 Subject: [PATCH 11/15] Reduce DSEG usage as we need 1 OSEG byte --- cmd_parser.c | 4 ++-- rtlplayground.c | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/cmd_parser.c b/cmd_parser.c index 33e4101..afc1408 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -156,7 +156,7 @@ uint8_t atoi_hex(uint8_t idx) uint8_t atoi_short(register uint16_t *vlan, register uint8_t idx) { - uint8_t err = 1; + __xdata uint8_t err = 1; *vlan = 0; while (isnumber(cmd_buffer[idx])) { @@ -1018,7 +1018,7 @@ void execute_config(void) __banked flash_region.len = FLASH_READ_BURST_SIZE; flash_read_bulk(flash_buf); - uint8_t cfg_idx = 0; + __xdata uint8_t cfg_idx = 0; uint8_t c = 0; do { for (uint8_t cmd_idx = 0; cmd_idx < (SBUF_SIZE - 1); cmd_idx++) { diff --git a/rtlplayground.c b/rtlplayground.c index f0989fe..938928e 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -631,12 +631,14 @@ void print_reg(uint16_t reg) } +/* +// TODO: This uses 2 DSEG bytes and is not used! void print_sds_reg(uint8_t sds_id, uint8_t page, uint8_t reg) { sds_read(sds_id, page, reg); print_phy_data(); } - +*/ char cmp_4(__xdata uint8_t a[], __xdata uint8_t b[]) { From 8cae3f1212ebc22a4a2c3cff8d28479c19db62f1 Mon Sep 17 00:00:00 2001 From: logicog Date: Sun, 1 Feb 2026 11:42:16 +0100 Subject: [PATCH 12/15] Add generic LED configuration support --- rtl837x_leds.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++--- rtl837x_leds.h | 21 ++++++++++ 2 files changed, 124 insertions(+), 6 deletions(-) diff --git a/rtl837x_leds.c b/rtl837x_leds.c index 4bf38e0..c641af9 100644 --- a/rtl837x_leds.c +++ b/rtl837x_leds.c @@ -26,6 +26,7 @@ extern __xdata uint8_t sfr_data[4]; void leds_dump(void) __banked { + print_string("RTL837X_PIN_MUX_0: "); print_reg(RTL837X_PIN_MUX_0); write_char('\n'); print_string("RTL837X_REG_LED_GLB_IO_EN: "); print_reg(RTL837X_REG_LED_GLB_IO_EN); write_char('\n'); print_string("RTL837X_REG_LED1_0_SET0: "); print_reg(RTL837X_REG_LED1_0_SET0); write_char('\n'); print_string("RTL837X_REG_LED3_2_SET0: "); print_reg(RTL837X_REG_LED3_2_SET0); write_char('\n'); @@ -39,9 +40,9 @@ void leds_dump(void) __banked print_string("RTL837X_LED_PORT_SET_SEL: "); print_reg(RTL837X_LED_PORT_SET_SEL); write_char('\n'); print_string("LED Configuration:\n"); print_string("LED-ID\t\t0\t\t1\t\t2\t\t3\n"); - for (uint8_t set = 0; set < 4; set++) { + for (__xdata uint8_t set = 0; set < 4; set++) { print_string("SET "); write_char('0' + set); write_char(':'); - for (uint8_t ledid = 0; ledid < 4; ledid++) { + for (__xdata uint8_t ledid = 0; ledid < 4; ledid++) { print_string("\t "); uint8_t b; if (set < 2) { @@ -64,12 +65,12 @@ void leds_dump(void) __banked } for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { reg_read_m(RTL837X_LED_PORT_SET_SEL); - uint8_t set = sfr_data[3 - (i >> 2)]; + __xdata uint8_t set = sfr_data[3 - (i >> 2)]; set = (set >> ((i & 3) << 1)); print_string("Port "); write_char('0' + i); print_string(": SET "); write_char('0' + set); print_string(": "); - for (uint8_t ledid = 0; ledid < 4; ledid++) { + for (__xdata uint8_t ledid = 0; ledid < 4; ledid++) { write_char('('); reg_read_m(RTL837X_REG_LED1_0_SET0 - set * 8 - ((ledid >> 1) * 4)); if (ledid & 1) { // LEDID 1, 3 @@ -98,7 +99,7 @@ void leds_dump(void) __banked print_string(" RX"); if (sfr_data[2] & 0x04) print_string(" TX"); - if (sfr_data[2] & 0x00) + if (sfr_data[2] & 0x08) print_string(" COL"); if (sfr_data[2] & 0x10) print_string(" DUPLEX"); @@ -106,7 +107,7 @@ void leds_dump(void) __banked print_string(" TRAINING"); if (sfr_data[2] & 0x40) print_string(" MASTER"); - uint8_t b; + __xdata uint8_t b; if (set < 2) { reg_read_m(RTL837X_REG_LED3_0_SET1); b = sfr_data[3-((set << 1) + (ledid >> 1))]; @@ -128,3 +129,99 @@ void leds_dump(void) __banked write_char('\n'); } } + + +void leds_setup(void) __banked +{ + print_string("leds_setup called\n"); + REG_SET(RTL837X_REG_LED_MODE, 0x0021e6b0); + + // Disable RLDP (Realtek Loop Detection Protocol) LEDs on loop detection + reg_read_m(RTL837X_REG_LED_RLDP_1); + sfr_mask_data(0, 0x03, 0); + reg_write_m(RTL837X_REG_LED_RLDP_1); + + // Set up all Port-LEDs to belong to RLDP + sfr_data[3] = sfr_data[2] = sfr_data[1] = sfr_data[0] = 0; + for (uint8_t i = machine.min_port; i <= (machine.max_port > 7 ? 7 : machine.max_port); i++) + sfr_data[3 - (i >> 2)] |= i & 1 ? 0xf0 : 0x0f; + reg_write_m(RTL837X_REG_LED_RLDP_2); + if (machine.max_port == 8) + REG_SET(RTL837X_REG_LED_RLDP_3, 0x0000000f); // Port 8 + + // Configure high LEDs 27-29: mux and LED enable + if (machine.high_leds.mux & LED_27) + reg_bit_set(RTL837X_PIN_MUX_0, 27); + else + reg_bit_clear(RTL837X_PIN_MUX_0, 27); + + if (machine.high_leds.mux & LED_28) + reg_bit_set(RTL837X_PIN_MUX_0, 28); + else + reg_bit_clear(RTL837X_PIN_MUX_0, 28); + + if (machine.high_leds.mux & LED_29) + reg_bit_set(RTL837X_PIN_MUX_0, 29); + else + reg_bit_clear(RTL837X_PIN_MUX_0, 29); + + if (machine.high_leds.enable & LED_27) + reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 27); + else + reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 27); + + if (machine.high_leds.enable & LED_28) + reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 28); + else + reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 28); + + if (machine.high_leds.enable & LED_29) + reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 29); + else + reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 29); + + + // Configure the LED-set of a port + sfr_data[3] = sfr_data[2] = sfr_data[1] = sfr_data[0] = 0; + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) + sfr_data[3 - (i >> 2)] |= machine.port_led_set[i] << ((i & 3) << 1); + reg_write_m(RTL837X_LED_PORT_SET_SEL); + + // Configure the LED-sets + __code uint8_t * __xdata lptr = &machine.led_sets[0][0]; + for (__xdata uint8_t set = 0; set < 4; set++) { + sfr_data[0] = *(lptr + 5); + sfr_data[1] = *(lptr + 4); + sfr_data[2] = *(lptr + 1); + sfr_data[3] = *(lptr); + reg_write_m(RTL837X_REG_LED1_0_SET0 - set * 8); + + if (set < 2) { + reg_read_m(RTL837X_REG_LED3_0_SET1); + sfr_data[3 - (set << 1)] = (*(lptr + 6) << 4) | (*(lptr + 2)); + reg_write_m(RTL837X_REG_LED3_0_SET1); + } else { + reg_read_m(RTL837X_REG_LED3_0_SET3); + sfr_data[3 - (set << 1)] = (*(lptr + 6) << 4) | (*(lptr + 2)); + reg_write_m(RTL837X_REG_LED3_0_SET3); + } + lptr += 8; + sfr_data[0] = *(lptr + 5); + sfr_data[1] = *(lptr + 4); + sfr_data[2] = *(lptr + 1); + sfr_data[3] = *(lptr); + reg_write_m(RTL837X_REG_LED1_0_SET0 - set * 8 - 4); + + if (set < 2) { + reg_read_m(RTL837X_REG_LED3_0_SET1); + sfr_data[2 - (set << 1)] = (*(lptr + 6) << 4) | (*(lptr + 2)); + reg_write_m(RTL837X_REG_LED3_0_SET1); + } else { + reg_read_m(RTL837X_REG_LED3_0_SET3); + sfr_data[2 - (set << 1)] = (*(lptr + 6) << 4) | (*(lptr + 2)); + reg_write_m(RTL837X_REG_LED3_0_SET3); + } + lptr += 8; + } + print_string("leds_setup done\n"); +} diff --git a/rtl837x_leds.h b/rtl837x_leds.h index e616c31..0ca1d20 100644 --- a/rtl837x_leds.h +++ b/rtl837x_leds.h @@ -1,7 +1,28 @@ #ifndef _RTL837X_LEDS_H_ #define _RTL837X_LEDS_H_ +#define LEDS_2G5 0x00001 +#define LEDS_TWO_PAIR_1G 0x00002 +#define LEDS_1G 0x00004 +#define LEDS_500M 0x00008 +#define LEDS_100M 0x00010 +#define LEDS_10M 0x00020 +#define LEDS_LINK 0x00040 +#define LEDS_LINK_FLASH 0x00080 +#define LEDS_ACT 0x00100 +#define LEDS_RX 0x00200 +#define LEDS_TX 0x00400 +#define LEDS_COL 0x00800 +#define LEDS_DUPLEX 0x01000 +#define LEDS_TRAINING 0x02000 +#define LEDS_MASTER 0x04000 +#define LEDS_10G 0x10000 +#define LEDS_TWO_PAIR_5G 0x20000 +#define LEDS_5G 0x40000 +#define LEDS_TWO_PAIR_2G5 0x80000 + #include void leds_dump(void) __banked; +void leds_setup(void) __banked; #endif From 6af072eb2c5e382672d750115ffc02f330a5c9d6 Mon Sep 17 00:00:00 2001 From: logicog Date: Sun, 1 Feb 2026 11:42:43 +0100 Subject: [PATCH 13/15] Add LED configuration in machine profile --- machine.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ machine.h | 15 +++++++++++++ 2 files changed, 81 insertions(+) diff --git a/machine.c b/machine.c index aaa5303..0e93a68 100644 --- a/machine.c +++ b/machine.c @@ -1,5 +1,6 @@ #include "machine.h" #include "rtl837x_pins.h" +#include "rtl837x_leds.h" #ifdef MACHINE_KP_9000_6XHML_X2 __code const struct machine machine = { @@ -22,6 +23,18 @@ __code const struct machine machine = { .sfp_port[1].sds = 1, .sfp_port[1].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, .reset_pin = GPIO46_I2C_SCL0, + .high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 }, + .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* Conditions for LED on: + * dual led orange: ledset_0 & ledset_2 + * dual led green: ledset_2 & !ledset_0 + * single right led green: ledset_0 & !ledset_1 + */ + .led_sets = { { LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G, + LEDS_2G5 | LEDS_LINK | LEDS_10G, + LEDS_1G | LEDS_LINK, + 0 }, + }, }; #elif defined MACHINE_KP_9000_6XH_X __code const struct machine machine = { @@ -37,8 +50,19 @@ __code const struct machine machine = { .sfp_port[0].pin_los = GPIO37, .sfp_port[0].pin_tx_disable = GPIO_NA, .sfp_port[0].sds = 1, + .sfp_port[0].i2c_bus = { .sda = 4, .scl = 3 }, .sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, .reset_pin = GPIO_NA, + /* Conditions for LED on: + * dual led orange: ledset_0 & ledset_2 + * dual led green: ledset_2 & !ledset_0 + * single right led green: ledset_0 & !ledset_1 + */ + .led_sets = { { LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G, + LEDS_2G5 | LEDS_LINK | LEDS_10G, + LEDS_1G | LEDS_LINK, + 0 }, + }, }; #elif defined MACHINE_KP_9000_9XH_X_EU __code const struct machine machine = { @@ -56,6 +80,13 @@ __code const struct machine machine = { .sfp_port[0].sds = 1, .sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, .reset_pin = GPIO_NA, + .high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 }, + .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0}, + .led_sets = { { LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5, + LEDS_2G5 | LEDS_LINK, + LEDS_1G | LEDS_LINK, + LEDS_2G5 | LEDS_LINK | LEDS_ACT }, + }, }; #elif defined MACHINE_SWGT024_V2_0 @@ -81,6 +112,18 @@ __code const struct machine machine = { .sfp_port[1].sds = 0, .sfp_port[1].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 }, /* GPIO 40 */ .reset_pin = GPIO36_PWM_OUT, + .high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 }, + .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0}, + /* Conditions for LED on: + * dual led orange: ledset_0 & ledset_2 + * dual led green: ledset_2 & !ledset_0 + * single right led green: ledset_0 & !ledset_1 + */ + .led_sets = { { LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G, + LEDS_2G5 | LEDS_LINK | LEDS_10G, + LEDS_1G | LEDS_LINK, + 0 }, + }, }; #elif defined MACHINE_HG0402XG_V1_1 @@ -103,6 +146,22 @@ __code const struct machine machine = { .sfp_port[1].pin_tx_disable = 0xFF, .sfp_port[1].sds = 0, .sfp_port[1].i2c_bus = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, + .reset_pin = GPIO_NA, + .high_leds = { .mux = LED_27 , .enable = LED_27 | LED_29 }, + .port_led_set = { 0, 0, 0, 1, 0, 0, 0, 0, 1}, + /* The Ethernet ports have 1 amber LED (left) and 1 green LED (right) + * The SFP ports have also 1 amber LED and 1 green LED + * Ethernet ports use LED-set 0, SFP ports use LED-set 1 + */ + .led_sets = { { LEDS_10M | LEDS_LINK | LEDS_ACT, + LEDS_1G | LEDS_100M | LEDS_10M | LEDS_2G5 | LEDS_LINK | LEDS_ACT, + LEDS_2G5 | LEDS_LINK | LEDS_ACT, + 0 }, + { LEDS_100M | LEDS_10M | LEDS_LINK, + LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G, + LEDS_10G | LEDS_LINK, + 0 }, + }, }; #elif defined DEFAULT_8C_1SFP @@ -121,6 +180,13 @@ __code const struct machine machine = { .sfp_port[0].sds = 1, .sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, .reset_pin = GPIO_NA, + .high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 }, + .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0}, + .led_sets = { { LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5, + LEDS_2G5 | LEDS_LINK, + LEDS_1G | LEDS_LINK, + LEDS_2G5 | LEDS_LINK | LEDS_ACT }, + }, }; #elif defined MACHINE_TRENDNET_TEG_S562 __code const struct machine machine = { diff --git a/machine.h b/machine.h index 5bb02ce..2532797 100644 --- a/machine.h +++ b/machine.h @@ -23,6 +23,18 @@ typedef struct { uint8_t scl; } i2c_bus_t; + +#define LED_27 1 +#define LED_28 2 +#define LED_29 4 + +struct high_leds { + // Defines MUX and LED enabling for pins 27-29 + uint8_t mux : 3; + uint8_t enable : 3; + uint8_t reserved : 2; +}; + struct sfp_port { uint8_t pin_detect; // gpio number 0-63, 0xFF = don't have it? @@ -44,6 +56,9 @@ typedef struct machine { // sfp_port[0] is the first SFP-port from the left on the device, sfp_port[1] the next if present struct sfp_port sfp_port[2]; int8_t reset_pin; + struct high_leds high_leds; + uint8_t port_led_set[9]; + uint32_t led_sets[4][4]; }; typedef struct machine_runtime From 59894e68cbd51991d08947e39082ef9b67d31596 Mon Sep 17 00:00:00 2001 From: logicog Date: Tue, 3 Feb 2026 19:21:08 +0100 Subject: [PATCH 14/15] Add LED-pad mapping --- machine.c | 22 +++++++++++++++ machine.h | 4 +++ rtl837x_leds.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++- rtl837x_regs.h | 7 +++++ 4 files changed, 104 insertions(+), 1 deletion(-) diff --git a/machine.c b/machine.c index 0e93a68..08f16dc 100644 --- a/machine.c +++ b/machine.c @@ -1,6 +1,7 @@ #include "machine.h" #include "rtl837x_pins.h" #include "rtl837x_leds.h" +#include "rtl837x_regs.h" #ifdef MACHINE_KP_9000_6XHML_X2 __code const struct machine machine = { @@ -35,7 +36,13 @@ __code const struct machine machine = { LEDS_1G | LEDS_LINK, 0 }, }, + .led_mux_custom = 1, + .led_mux = {0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x0f, 0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, + 0x15, 0x16, 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x23 }, }; + +void machine_custom_init(void) { } + #elif defined MACHINE_KP_9000_6XH_X __code const struct machine machine = { .machine_name = "keepLink KP-9000-6XH-X", @@ -64,6 +71,9 @@ __code const struct machine machine = { 0 }, }, }; + +void machine_custom_init(void) { } + #elif defined MACHINE_KP_9000_9XH_X_EU __code const struct machine machine = { .machine_name = "keepLink KP-9000-6XH-X-EU", @@ -89,6 +99,8 @@ __code const struct machine machine = { }, }; +void machine_custom_init(void) { } + #elif defined MACHINE_SWGT024_V2_0 __code const struct machine machine = { .machine_name = "SWGT024 V2.0", @@ -126,6 +138,8 @@ __code const struct machine machine = { }, }; +void machine_custom_init(void) { } + #elif defined MACHINE_HG0402XG_V1_1 __code const struct machine machine = { .machine_name = "HG0402XG V1.1", @@ -164,6 +178,8 @@ __code const struct machine machine = { }, }; +void machine_custom_init(void) { } + #elif defined DEFAULT_8C_1SFP __code const struct machine machine = { .machine_name = "8+1 SFP Port Switch", @@ -188,6 +204,9 @@ __code const struct machine machine = { LEDS_2G5 | LEDS_LINK | LEDS_ACT }, }, }; + +void machine_custom_init(void) { } + #elif defined MACHINE_TRENDNET_TEG_S562 __code const struct machine machine = { .machine_name = "Trendnet TEG-S562", @@ -210,4 +229,7 @@ __code const struct machine machine = { .sfp_port[1].i2c = { .sda = GPIO49_I2C_SDA1, .scl = GPIO48_I2C_SCL1 }, .reset_pin = GPIO_NA, }; + +void machine_custom_init(void) { } + #endif diff --git a/machine.h b/machine.h index 2532797..cba1ac8 100644 --- a/machine.h +++ b/machine.h @@ -59,6 +59,8 @@ typedef struct machine { struct high_leds high_leds; uint8_t port_led_set[9]; uint32_t led_sets[4][4]; + uint8_t led_mux_custom; + uint8_t led_mux[28]; }; typedef struct machine_runtime @@ -67,4 +69,6 @@ typedef struct machine_runtime uint8_t isN : 1; }; +void machine_custom_init(void); + #endif diff --git a/rtl837x_leds.c b/rtl837x_leds.c index c641af9..4c68f82 100644 --- a/rtl837x_leds.c +++ b/rtl837x_leds.c @@ -38,7 +38,42 @@ void leds_dump(void) __banked print_string("RTL837X_REG_LED3_0_SET1: "); print_reg(RTL837X_REG_LED3_0_SET1); write_char('\n'); print_string("RTL837X_REG_LED3_0_SET3: "); print_reg(RTL837X_REG_LED3_0_SET3); write_char('\n'); print_string("RTL837X_LED_PORT_SET_SEL: "); print_reg(RTL837X_LED_PORT_SET_SEL); write_char('\n'); - print_string("LED Configuration:\n"); + print_string("RTL837X_REG_LED_GLB_MUX_1: "); print_reg(RTL837X_REG_LED_GLB_MUX_1); write_char('\n'); + print_string("RTL837X_REG_LED_GLB_MUX_2: "); print_reg(RTL837X_REG_LED_GLB_MUX_2); write_char('\n'); + print_string("RTL837X_REG_LED_GLB_MUX_3: "); print_reg(RTL837X_REG_LED_GLB_MUX_3); write_char('\n'); + print_string("RTL837X_REG_LED_GLB_MUX_4: "); print_reg(RTL837X_REG_LED_GLB_MUX_4); write_char('\n'); + print_string("RTL837X_REG_LED_GLB_MUX_5: "); print_reg(RTL837X_REG_LED_GLB_MUX_5); write_char('\n'); + print_string("RTL837X_REG_LED_GLB_MUX_6: "); print_reg(RTL837X_REG_LED_GLB_MUX_6); write_char('\n'); + print_string("RTL837X_REG_LED_GLB_ACTIVE: "); print_reg(RTL837X_REG_LED_GLB_ACTIVE); write_char('\n'); + print_string("LED pad Configuration:\n"); + for (uint8_t i = 0; i < 28; i++) { + print_byte(i); + write_char(' '); + } + write_char('\n'); + for (uint8_t i = 0; i < 28; i++) { + switch (i % 5) { + case 0: // 0 + reg_read_m(RTL837X_REG_LED_GLB_MUX_1 + (i / 5) * 4); + print_byte(sfr_data[3] & 0x3f); + break; + case 1: // 6 + print_byte(((sfr_data[3] >> 6) | (sfr_data[2] << 2)) & 0x3f); + break; + case 2: // 12 + print_byte(((sfr_data[1] << 4) | (sfr_data[2] >> 4)) & 0x3f); + break; + case 3: // 18 + print_byte((sfr_data[1] >> 2) & 0x3f); + break; + case 4: // 24 + print_byte(sfr_data[0] & 0x3f); + break; + } + write_char(' '); + } + write_char('\n'); + print_string("LED-set Configuration:\n"); print_string("LED-ID\t\t0\t\t1\t\t2\t\t3\n"); for (__xdata uint8_t set = 0; set < 4; set++) { print_string("SET "); write_char('0' + set); write_char(':'); @@ -181,6 +216,38 @@ void leds_setup(void) __banked reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 29); + // Configure the LED-mux + if (machine.led_mux_custom) { + print_string("Configuring custom LED-muxes: "); + for (uint8_t i = 0; i < 28; i++) { + switch (i % 5) { + case 0: // 0 + sfr_data[3] = machine.led_mux[i]; + break; + case 1: // 6 + sfr_data[3] |= machine.led_mux[i] << 6; + sfr_data[2] = machine.led_mux[i] >> 2; + break; + case 2: // 12 + sfr_data[2] |= machine.led_mux[i] << 4; + sfr_data[1] = machine.led_mux[i] >> 4; + break; + case 3: // 18 + sfr_data[1] |= machine.led_mux[i] << 2; + break; + case 4: // 24 + sfr_data[0] = machine.led_mux[i]; + print_sfr_data(); write_char(' '); + reg_write_m(RTL837X_REG_LED_GLB_MUX_1 + (i / 5) * 4); + break; + } + write_char(' '); + } + sfr_data[0] = 0; sfr_data[1] &= 0xf; + print_sfr_data(); write_char('\n'); + reg_write_m(RTL837X_REG_LED_GLB_MUX_6); + } + // Configure the LED-set of a port sfr_data[3] = sfr_data[2] = sfr_data[1] = sfr_data[0] = 0; for (uint8_t i = machine.min_port; i <= machine.max_port; i++) @@ -188,6 +255,9 @@ void leds_setup(void) __banked reg_write_m(RTL837X_LED_PORT_SET_SEL); // Configure the LED-sets + sfr_data[3] = sfr_data[2] = sfr_data[1] = sfr_data[0] = 0; + reg_write_m(RTL837X_REG_LED3_0_SET1); + reg_write_m(RTL837X_REG_LED3_0_SET3); __code uint8_t * __xdata lptr = &machine.led_sets[0][0]; for (__xdata uint8_t set = 0; set < 4; set++) { sfr_data[0] = *(lptr + 5); diff --git a/rtl837x_regs.h b/rtl837x_regs.h index 6232a42..32e7a98 100644 --- a/rtl837x_regs.h +++ b/rtl837x_regs.h @@ -22,6 +22,13 @@ // BIT 17 set: LED solid on // Bytes 0/1 hold the LED mode, e.g. serial, RTL8231? // Blink rate is defined by setAsicRegBits(0x6520,0xe00000,rate); +#define RTL837X_REG_LED_GLB_MUX_1 0x65E0 +#define RTL837X_REG_LED_GLB_MUX_2 0x65E4 +#define RTL837X_REG_LED_GLB_MUX_3 0x65E8 +#define RTL837X_REG_LED_GLB_MUX_4 0x65EC +#define RTL837X_REG_LED_GLB_MUX_5 0x65F0 +#define RTL837X_REG_LED_GLB_MUX_6 0x65F4 +#define RTL837X_REG_LED_GLB_ACTIVE 0x65D8 #define RTL837X_REG_LED_GLB_IO_EN 0x65DC #define RTL837X_REG_LED3_0_SET3 0x6524 #define RTL837X_REG_LED3_0_SET1 0x6528 From d29adafe3c277fc43fda67282f7ddeb514941a98 Mon Sep 17 00:00:00 2001 From: logicog Date: Sun, 1 Feb 2026 11:43:29 +0100 Subject: [PATCH 15/15] Use generic led configuration --- machine.c | 19 +++---- rtl837x_leds.c | 1 - rtlplayground.c | 143 +++--------------------------------------------- 3 files changed, 18 insertions(+), 145 deletions(-) diff --git a/machine.c b/machine.c index 08f16dc..460dae1 100644 --- a/machine.c +++ b/machine.c @@ -26,14 +26,14 @@ __code const struct machine machine = { .reset_pin = GPIO46_I2C_SCL0, .high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 }, .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0}, - /* Conditions for LED on: + /* Conditions for LED on: * dual led orange: ledset_0 & ledset_2 * dual led green: ledset_2 & !ledset_0 * single right led green: ledset_0 & !ledset_1 */ .led_sets = { { LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G, LEDS_2G5 | LEDS_LINK | LEDS_10G, - LEDS_1G | LEDS_LINK, + LEDS_1G | LEDS_LINK, 0 }, }, .led_mux_custom = 1, @@ -57,17 +57,16 @@ __code const struct machine machine = { .sfp_port[0].pin_los = GPIO37, .sfp_port[0].pin_tx_disable = GPIO_NA, .sfp_port[0].sds = 1, - .sfp_port[0].i2c_bus = { .sda = 4, .scl = 3 }, .sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, .reset_pin = GPIO_NA, - /* Conditions for LED on: + /* Conditions for LED on: * dual led orange: ledset_0 & ledset_2 * dual led green: ledset_2 & !ledset_0 * single right led green: ledset_0 & !ledset_1 */ .led_sets = { { LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G, LEDS_2G5 | LEDS_LINK | LEDS_10G, - LEDS_1G | LEDS_LINK, + LEDS_1G | LEDS_LINK, 0 }, }, }; @@ -126,14 +125,14 @@ __code const struct machine machine = { .reset_pin = GPIO36_PWM_OUT, .high_leds = { .mux = LED_27 | LED_29, .enable = LED_28 | LED_29 }, .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0}, - /* Conditions for LED on: + /* Conditions for LED on: * dual led orange: ledset_0 & ledset_2 * dual led green: ledset_2 & !ledset_0 * single right led green: ledset_0 & !ledset_1 */ .led_sets = { { LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G, LEDS_2G5 | LEDS_LINK | LEDS_10G, - LEDS_1G | LEDS_LINK, + LEDS_1G | LEDS_LINK, 0 }, }, }; @@ -169,11 +168,11 @@ __code const struct machine machine = { */ .led_sets = { { LEDS_10M | LEDS_LINK | LEDS_ACT, LEDS_1G | LEDS_100M | LEDS_10M | LEDS_2G5 | LEDS_LINK | LEDS_ACT, - LEDS_2G5 | LEDS_LINK | LEDS_ACT, + LEDS_2G5 | LEDS_LINK | LEDS_ACT, 0 }, { LEDS_100M | LEDS_10M | LEDS_LINK, LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_10M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G, - LEDS_10G | LEDS_LINK, + LEDS_10G | LEDS_LINK, 0 }, }, }; @@ -200,7 +199,7 @@ __code const struct machine machine = { .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 0}, .led_sets = { { LEDS_2G5 | LEDS_TWO_PAIR_1G | LEDS_1G | LEDS_500M | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT | LEDS_10G | LEDS_TWO_PAIR_5G | LEDS_5G | LEDS_TWO_PAIR_2G5, LEDS_2G5 | LEDS_LINK, - LEDS_1G | LEDS_LINK, + LEDS_1G | LEDS_LINK, LEDS_2G5 | LEDS_LINK | LEDS_ACT }, }, }; diff --git a/rtl837x_leds.c b/rtl837x_leds.c index 4c68f82..86e7f97 100644 --- a/rtl837x_leds.c +++ b/rtl837x_leds.c @@ -214,7 +214,6 @@ void leds_setup(void) __banked reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 29); else reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 29); - // Configure the LED-mux if (machine.led_mux_custom) { diff --git a/rtlplayground.c b/rtlplayground.c index 938928e..a694958 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -1456,46 +1456,6 @@ void sds_init(void) } -void led_config_9xh(void) -{ - // r65d8:3ffbedff R65d8-3ffbedff - reg_bit_set(0x65d8, 0x1d); - - // r6520:0021fdb0 R6520-0021e7b0 r6520:0021e7b0 R6520-0021e6b0 - reg_read_m(RTL837X_REG_LED_MODE); - sfr_mask_data(1, 0x1f, 0x6); - sfr_mask_data(0, 0xe0, 0xa0); - reg_write_m(RTL837X_REG_LED_MODE); - - // Set LED blink rate to slow during booting - set_sys_led_state(SYS_LED_SLOW); - - // Disable RLDP (Realtek Loop Detection Protocol) LEDs on loop detection - reg_read_m(RTL837X_REG_LED_RLDP_1); - sfr_mask_data(0, 0, 0x3); - reg_write_m(RTL837X_REG_LED_RLDP_1); - // Configure LED group for RLDP per port - REG_SET(RTL837X_REG_LED_RLDP_2, 0xffffffff); // Ports 0-7 - REG_SET(RTL837X_REG_LED_RLDP_3, 0x0000000f); // Port 8 - - reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 29); - reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 27); - - // GPIO 27 is LED - reg_bit_set(RTL837X_PIN_MUX_0, 27); - - // Configure LED_SET_0, ledid 0/1 - REG_SET(RTL837X_REG_LED1_0_SET0, 0x0041017f); - - // Configure LED_SET_0 ledid 2 - REG_SET(RTL837X_REG_LED3_2_SET0, 0x01410044); - - // r6528:00000000 R6528-0000000f - reg_read_m(RTL837X_REG_LED3_0_SET1); - sfr_mask_data(0, 0x0f, 0x0f); - reg_write_m(RTL837X_REG_LED3_0_SET1); -} - void set_sys_led_state(uint8_t state) { reg_read_m(RTL837X_REG_LED_MODE); @@ -1503,94 +1463,6 @@ void set_sys_led_state(uint8_t state) reg_write_m(RTL837X_REG_LED_MODE); } - -#ifdef MACHINE_HG0402XG_V1_1 -void led_config(void) -{ - reg_read_m(RTL837X_REG_LED_MODE); - sfr_mask_data(2, 0xe0, 0x23); // Mask blink rate field (0xe0), set blink rate and LED to solid (set bit 1 = bit 17 overal - // Configure led-mode (serial?) - sfr_data[2] = 0xe6; - sfr_data[3] = 0xb0; - reg_write_m(RTL837X_REG_LED_MODE); - // Disable RLDP (Realtek Loop Detection Protocol) LEDs on loop detection - reg_read_m(RTL837X_REG_LED_RLDP_1); - sfr_mask_data(0, 0x03, 0); - reg_write_m(RTL837X_REG_LED_RLDP_1); - REG_SET(RTL837X_REG_LED_RLDP_2, 0xffff0000); // Ports 0-7 0x65fc - REG_SET(RTL837X_REG_LED_RLDP_3, 0x0000000f); // Port 8 - - reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 29); - reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 27); - reg_bit_set(RTL837X_PIN_MUX_0, 29); - reg_bit_set(RTL837X_PIN_MUX_0, 27); - - REG_SET(RTL837X_REG_LED1_0_SET0, 0x141); // 0x6548 - reg_read_m(RTL837X_REG_LED3_2_SET0); - sfr_data[2] = 0x01; - sfr_data[3] = 0x74; - reg_write_m(RTL837X_REG_LED3_2_SET0); - reg_read_m(RTL837X_REG_LED1_0_SET1); // 6540 - sfr_data[2] = 0x01; - sfr_data[3] = 0x7f; - reg_write_m(RTL837X_REG_LED1_0_SET1); - - reg_read_m(RTL837X_REG_LED3_0_SET1); - sfr_data[1] |= 0x0f; - reg_write_m(RTL837X_REG_LED3_0_SET1); -} - -#else -void led_config(void) -{ - // LED initialization - // r6520:0021fdb0 R6520-0021e7b0 r6520:0021e7b0 R6520-0021e6b0 - reg_read_m(RTL837X_REG_LED_MODE); - sfr_mask_data(2, 0xe0, 0x23); // Mask blink rate field (0xe0), set blink rate and LED to solid (set bit 1 = bit 17 overall) - // Configure led-mode (serial?) - sfr_data[2] = 0xe6; - sfr_data[3] = 0xb0; - reg_write_m(RTL837X_REG_LED_MODE); - - // Disable RLDP (Realtek Loop Detection Protocol) LEDs on loop detection - reg_read_m(RTL837X_REG_LED_RLDP_1); - sfr_mask_data(0, 0x03, 0); - reg_write_m(RTL837X_REG_LED_RLDP_1); - // Configure LED group for RLDP per port - REG_SET(RTL837X_REG_LED_RLDP_2, 0xffffffff); // Ports 0-7 - REG_SET(RTL837X_REG_LED_RLDP_3, 0x0000000f); // Port 8 - - reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 29); - reg_bit_clear(RTL837X_REG_LED_GLB_IO_EN, 27); - - // Configure GPIO for LEDs 27-29 - if (machine.n_sfp == 2) { - reg_bit_set(RTL837X_PIN_MUX_0, 27); - reg_bit_clear(RTL837X_PIN_MUX_0, 28); - reg_bit_set(RTL837X_PIN_MUX_0, 29); - } else { - reg_bit_set(RTL837X_PIN_MUX_0, 27); - reg_bit_set(RTL837X_PIN_MUX_0, 28); - reg_bit_set(RTL837X_PIN_MUX_0, 29); - } - // LED setup - // r6520:0021fdb0 R6520-0021e7b0 r6520:0021e7b0 R6520-0021e6b0 r65f8:00000018 R65f8-00000018 R65fc-fffff000 r6600:00000000 R6600-0000000f r65dc:5fffff00 R65dc-7fffff00 r65dc:7fffff00 R65dc-77ffff00 - // r7f8c:30000000 R7f8c-30000000 r7f8c:30000000 R7f8c-38000000 R6548-00410175 r6544:01411000 R6544-01410044 r6528:00000000 R6528-00000011 - - // Configure LED_SET_0, ledid 0/1 - REG_SET(RTL837X_REG_LED1_0_SET0, 0x00410175); - - // Configure led-sets 2 and 3 - REG_SET(RTL837X_REG_LED3_2_SET0, 0x01410044); - - // Further configure LED_SET_0 - // r6528:00000000 R6528-00000011 - reg_read_m(RTL837X_REG_LED3_0_SET1); - sfr_data[3] = 0x11; - reg_write_m(RTL837X_REG_LED3_0_SET1); -} -#endif - void rtl8373_revision(void) { reg_read_m(RTL837X_REG_CHIP_INFO); @@ -1609,7 +1481,9 @@ void rtl8373_init(void) { print_string("\nrtl8373_init called\n"); - led_config_9xh(); + // r65d8:3ffbedff R65d8-3ffbedff + reg_bit_set(0x65d8, 0x1d); + sds_init(); // Disable all SERDES for configuration REG_SET(RTL837X_REG_SDS_MODES, 0x000037ff); @@ -1704,8 +1578,6 @@ void rtl8372_init(void) { print_string("\nrtl8372_init called\n"); - led_config(); - sds_init(); phy_config(8); // PHY configuration: External 8221B? phy_config(3); // PHY configuration: all internal PHYs? @@ -2024,6 +1896,12 @@ void bootloader(void) init_smi(); rtl8373_revision(); + + leds_setup(); + machine_custom_init(); + + leds_dump(); + if (machine_detected.isRTL8373) rtl8373_init(); else @@ -2034,7 +1912,6 @@ void bootloader(void) flash_region.addr = FIRMWARE_UPLOAD_START; flash_region.len = 0x100; flash_read_bulk(flash_buf); -#ifndef MACHINE_HG0402XG_V1_1 if (flash_buf[0] == 0x00 && flash_buf[1] == 0x40) { __xdata uint32_t dest = 0x0; __xdata uint32_t source = FIRMWARE_UPLOAD_START; @@ -2105,9 +1982,7 @@ void bootloader(void) dest += 0x1000; } } -#endif set_sys_led_state(SYS_LED_SLOW); - leds_dump(); #ifdef DEBUG // This register seems to work on the RTL8373 only if also the SDS