From 7d62b24a42446ffe511b8a9fc15bfa1909fe1778 Mon Sep 17 00:00:00 2001 From: diijkstra <16804536+diijkstra@users.noreply.github.com> Date: Mon, 26 Jan 2026 20:19:51 +0100 Subject: [PATCH 1/3] Advanced I2C pin definition RTL has up to 3 SCL pins and up to 4 SDA pins. Lets allow configuring I2C with individual BUS numbers instead of 0/1 I2C. This enables support for devices where SCL line is not shared between SFP modules. MUX registry is now initialized depending on needed pin function. More over, some SFP pins require special MUX settings, lets initialize those depending on SFP configuration. This adds TX Disable pin, which right now is set to low at startup. Caveats: - We may still override MUX registry later - Not sure how to handle invalid bus definitions - Without SFP is it fine to *not* initialize anything? - Do to RAM limitation we do inititalize output GPIO to low --- httpd/page_impl.c | 2 +- machine.c | 24 +++++++---- machine.h | 11 ++++- rtl837x_common.h | 5 --- rtl837x_port.c | 16 ++----- rtlplayground.c | 104 +++++++++++++++++++++++++++++++++++++++++++--- uip/uip_arp.c | 2 +- 7 files changed, 129 insertions(+), 35 deletions(-) diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 288e4f4..363f96b 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -178,7 +178,7 @@ void sfp_send_data(uint8_t slot, uint8_t reg, uint8_t len) } reg_read_m(RTL837X_REG_I2C_CTRL); - sfr_mask_data(1, 0xfc, machine.sfp_port[slot].i2c == 0 ? SCL_PIN << 5 | SDA_PIN_0 << 2 : SCL_PIN << 5 | SDA_PIN_1 << 2 ); + sfr_mask_data(1, 0xfc, machine.sfp_port[slot].i2c_bus.scl << 5 | machine.sfp_port[slot].i2c_bus.sda << 2); reg_write_m(RTL837X_REG_I2C_CTRL); REG_WRITE(RTL837X_REG_I2C_IN, 0, 0, 0, reg); diff --git a/machine.c b/machine.c index fadd346..57ce9f6 100644 --- a/machine.c +++ b/machine.c @@ -12,12 +12,14 @@ __code const struct machine machine = { .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 = 1, + .sfp_port[0].i2c_bus = { .sda = 3, .scl = 3 }, .sfp_port[1].pin_detect = 30, .sfp_port[1].pin_los = 37, + .sfp_port[1].pin_tx_disable = 0xFF, .sfp_port[1].sds = 0, - .sfp_port[1].i2c = 0, + .sfp_port[1].i2c_bus = { .sda = 4, .scl = 3 }, .reset_pin = 46, }; #elif defined MACHINE_KP_9000_6XH_X @@ -32,8 +34,9 @@ __code const struct machine machine = { .is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1}, .sfp_port[0].pin_detect = 30, .sfp_port[0].pin_los = 37, + .sfp_port[0].pin_tx_disable = 0xFF, .sfp_port[0].sds = 1, - .sfp_port[0].i2c = 0, + .sfp_port[0].i2c_bus = { .sda = 4, .scl = 3 }, }; #elif defined MACHINE_KP_9000_9XH_X_EU __code const struct machine machine = { @@ -47,9 +50,11 @@ __code const struct machine machine = { .is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1}, .sfp_port[0].pin_detect = 30, .sfp_port[0].pin_los = 37, + .sfp_port[0].pin_tx_disable = 0xFF, .sfp_port[0].sds = 1, - .sfp_port[0].i2c = 0, + .sfp_port[0].i2c_bus = { .sda = 4, .scl = 3 }, }; + #elif defined MACHINE_SWGT024_V2_0 __code const struct machine machine = { .machine_name = "SWGT024 V2.0", @@ -63,15 +68,18 @@ __code const struct machine machine = { // Left SFP port (J4) .sfp_port[0].pin_detect = 30, .sfp_port[0].pin_los = 37, + .sfp_port[0].pin_tx_disable = 0xFF, .sfp_port[0].sds = 1, - .sfp_port[0].i2c = 0, /* GPIO 39 */ + .sfp_port[0].i2c_bus = { .sda = 4, .scl = 3 }, /* GPIO 39 */ // Right SFP port (J2) .sfp_port[1].pin_detect = 50, .sfp_port[1].pin_los = 51, + .sfp_port[1].pin_tx_disable = 0xFF, .sfp_port[1].sds = 0, - .sfp_port[1].i2c = 1, /* GPIO 40 */ + .sfp_port[1].i2c_bus = { .sda = 3, .scl = 3 }, /* GPIO 40 */ .reset_pin = 36, }; + #elif defined DEFAULT_8C_1SFP __code const struct machine machine = { .machine_name = "8+1 SFP Port Switch", @@ -84,8 +92,8 @@ __code const struct machine machine = { .is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1}, .sfp_port[0].pin_detect = 30, .sfp_port[0].pin_los = 37, + .sfp_port[0].pin_tx_disable = 0xFF, .sfp_port[0].sds = 1, - .sfp_port[0].i2c = 0, + .sfp_port[0].i2c_bus = { .sda = 4, .scl = 3 }, }; - #endif diff --git a/machine.h b/machine.h index d653d66..0c8176e 100644 --- a/machine.h +++ b/machine.h @@ -16,12 +16,21 @@ // #define DEFAULT_5C_1SFP +struct i2c_bus { + // These are I2C bus identifiers refer to GPIO MUX document + // for GPIO pin assignments for given bus numbers + uint8_t sda : 3; // SDA pin number 0-4 + uint8_t scl : 3; // SCL pin number 0-3 + uint8_t reserved : 2; +}; + struct sfp_port { uint8_t pin_detect; // gpio number 0-63, 0xFF = don't have it? uint8_t pin_los; // gpio number 0-63, 0xFF = don't have it? + uint8_t pin_tx_disable; // gpio number 0-63, 0xFF = not present uint8_t sds; - uint8_t i2c; + struct i2c_bus i2c_bus; }; typedef struct machine { diff --git a/rtl837x_common.h b/rtl837x_common.h index 0b0db2e..3ff6fb8 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -7,11 +7,6 @@ #define SYS_TICK_HZ 200 -// SCL and SDA pin numbers for SFP cage 0 and SFP cage 1 -#define SCL_PIN 3 -#define SDA_PIN_0 4 -#define SDA_PIN_1 3 - #define CPU_PORT 9 // Define Port-masks for 9-port devices and 6-port devices diff --git a/rtl837x_port.c b/rtl837x_port.c index c4b542c..dbd1715 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -356,20 +356,10 @@ void port_stats_print(void) __banked else print_string("Off\t"); } else { // An SFP Module - if (i != 3) { - reg_read_m(RTL837X_REG_GPIO_00_31_INPUT); - if (!(sfr_data[0] & 0x40)) { - print_string("SFP OK\t"); - } else { - print_string("NO SFP\t"); - } + if (!gpio_pin_test(machine.sfp_port[machine.is_sfp[i]-1].pin_detect)) { + print_string("SFP IN\t"); } else { - reg_read_m(RTL837X_REG_GPIO_32_63_INPUT); - if (!(sfr_data[1] & 0x04)) { - print_string("SFP OK\t"); - } else { - print_string("NO SFP\t"); - } + print_string("NO SFP\t"); } } diff --git a/rtlplayground.c b/rtlplayground.c index e9712b8..90deb1a 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -807,7 +807,7 @@ uint8_t sfp_read_reg(uint8_t slot, uint8_t reg) } reg_read_m(RTL837X_REG_I2C_CTRL); - sfr_mask_data(1, 0xfc, machine.sfp_port[slot].i2c == 0 ? SCL_PIN << 5 | SDA_PIN_0 << 2 : SCL_PIN << 5 | SDA_PIN_1 << 2 ); + sfr_mask_data(1, 0xfc, machine.sfp_port[slot].i2c_bus.scl << 5 | machine.sfp_port[slot].i2c_bus.sda << 2); reg_write_m(RTL837X_REG_I2C_CTRL); REG_WRITE(RTL837X_REG_I2C_IN, 0, 0, 0, reg); @@ -1009,6 +1009,59 @@ bool gpio_pin_test(uint8_t pin) return sfr_data[3-((pin >> 3) & 3)] & (1 << (pin & 7)); } +void gpio_mux_setup(uint8_t pin) +{ + // Some GPIOs require setting MUX registers to enable GPIO + if (pin == 36) { + reg_bit_set(RTL837X_PIN_MUX_1, 30); + } else if ( pin == 50 ) { + // Bit 15-16 0b00 -> GPIO + reg_read_m(RTL837X_PIN_MUX_1); + sfr_mask_data(1, 0x80, 0x00); + sfr_mask_data(2, 0x01, 0x00); + reg_write_m(RTL837X_PIN_MUX_1); + } else if ( pin == 51 ) { + // Bit 17-18 0b00 -> GPIO + reg_read_m(RTL837X_PIN_MUX_1); + sfr_mask_data(2, 0x06, 0x00); + reg_write_m(RTL837X_PIN_MUX_1); + } else if ( pin == 54 ) { + reg_bit_clear(RTL837X_PIN_MUX_2, 2); + } +} + +/* + * Setup a GPIO pin as input + * pin: GPIO pin number 0-63 + */ +void gpio_input_setup(uint8_t pin) { + gpio_mux_setup(pin); + reg_bit_clear(pin < 32 ? RTL837X_REG_GPIO_00_31_DIRECTION : RTL837X_REG_GPIO_32_63_DIRECTION, (pin % 32)); +} + + +/* + * Setup a GPIO pin as output + * pin: GPIO pin number 0-63 + */ +void gpio_output_setup(uint8_t pin) { + gpio_mux_setup(pin); + // Default output to low + reg_bit_clear(pin < 32 ? RTL837X_REG_GPIO_00_31_OUTPUT : RTL837X_REG_GPIO_32_63_OUTPUT, (pin % 32)); + reg_bit_set(pin < 32 ? RTL837X_REG_GPIO_00_31_DIRECTION : RTL837X_REG_GPIO_32_63_DIRECTION, (pin % 32)); +} + +/* Inititalize SFP GPIOs */ +void setup_sfp_gpio(void) +{ + for (uint8_t sfp = 0; sfp < machine.n_sfp; sfp++) { + gpio_input_setup(machine.sfp_port[sfp].pin_detect); + gpio_input_setup(machine.sfp_port[sfp].pin_los); + if (machine.sfp_port[sfp].pin_tx_disable != 0xFF) { + gpio_output_setup(machine.sfp_port[sfp].pin_tx_disable); + } + } +} void handle_sfp(void) { @@ -1538,7 +1591,6 @@ void led_config(void) reg_write_m(RTL837X_REG_LED3_0_SET1); } - void rtl8373_revision(void) { reg_read_m(RTL837X_REG_CHIP_INFO); @@ -1811,11 +1863,50 @@ void setup_i2c(void) REG_SET(RTL837X_REG_I2C_CTRL2, 0); - // HW Control register, enable I2C? + // HW Control register, enable I2C depending on PIN configuration reg_read_m(RTL837X_PIN_MUX_1); - sfr_mask_data(3, 0x20, 0x00); // Clear bit 29 - sfr_mask_data(0, 0x60, 0x40); // Set bits 5-6 to 0b10 - reg_write_m(RTL837X_PIN_MUX_1); + for (uint8_t sfp = 0; sfp < machine.n_sfp; sfp++) { + const uint8_t scl_bus = machine.sfp_port[sfp].i2c_bus.scl; + const uint8_t sda_bus = machine.sfp_port[sfp].i2c_bus.sda; + print_string("Configuring I2C for SFP idx="); print_byte(sfp); print_string(" SCL="); print_byte(scl_bus); print_string(", SDA="); print_byte(sda_bus); write_char('\n'); + if (scl_bus == 3) { + // Bit 5-6 0b10 -> SCL (implies enabled SDA on bus 3) + sfr_mask_data(0, 0x60, 0x40); + } else if (scl_bus == 2) { + // Bit 15-16 0b01 -> SCL + sfr_mask_data(1, 0x80, 0x80); + sfr_mask_data(2, 0x01, 0x00); + } else if (scl_bus == 1) { + // Bit 11-12 0b01 -> SCL + sfr_mask_data(1, 0x18, 0x08); + } else if (scl_bus == 0) { + // Bit 7-8 0b01 -> SCL + sfr_mask_data(0, 0x80, 0x80); + sfr_mask_data(1, 0x01, 0x00); + } else { + print_string("Invalid SCL bus number: "); print_byte(scl_bus); write_char('\n'); + } + + if (sda_bus == 4) { + // Bit 29 0b0 -> SDA + sfr_mask_data(3, 0x20, 0x00); + } else if (sda_bus == 3) { + // Bit 5-6 0b10 -> SDA (implies enabled SCL on bus 3) + sfr_mask_data(0, 0x60, 0x40); + } else if (sda_bus == 2) { + // Bit 17-18 0b01 -> SDA + sfr_mask_data(2, 0x06, 0x02); + } else if (sda_bus == 1) { + // Bit 13-14 0b01 -> SDA + sfr_mask_data(1, 0x60, 0x20); + } else if (sda_bus == 0) { + // Bit 9-10 0b01 -> SDA + sfr_mask_data(1, 0x06, 0x02); + } else { + print_string("Invalid SDA bus number: "); print_byte(sda_bus); write_char('\n'); + } + } + reg_write_m(RTL837X_PIN_MUX_1); } @@ -2009,6 +2100,7 @@ void bootloader(void) management_vlan = 0; // Disabled setup_i2c(); + setup_sfp_gpio(); print_string(greeting); diff --git a/uip/uip_arp.c b/uip/uip_arp.c index ca8ad1e..160dab1 100644 --- a/uip/uip_arp.c +++ b/uip/uip_arp.c @@ -142,7 +142,7 @@ static __xdata u8_t tmpage; void uip_arp_init(void) __banked { - print_string("uip_arp_init called"); + print_string("uip_arp_init called\n"); for(uint8_t i = 0; i < UIP_ARPTAB_SIZE; ++i) { memset(arp_table[i].ipaddr, 0, 4); } From 48455a57b262872b0c59b7a59ef645a4c772f1c5 Mon Sep 17 00:00:00 2001 From: diijkstra <16804536+diijkstra@users.noreply.github.com> Date: Sun, 1 Feb 2026 13:02:49 +0100 Subject: [PATCH 2/3] PIN module Added GPIO defines, moved GPIO MUX initialization to new module. Converted if/else to switch in GPIO initialization. --- Makefile | 2 +- httpd/page_impl.c | 3 +- machine.c | 57 ++++++++++---------- machine.h | 14 +++-- rtl837x_pins.c | 112 +++++++++++++++++++++++++++++++++++++++ rtl837x_pins.h | 93 ++++++++++++++++++++++++++++++++ rtlplayground.c | 131 +++++++++++++++++----------------------------- 7 files changed, 292 insertions(+), 120 deletions(-) create mode 100644 rtl837x_pins.c create mode 100644 rtl837x_pins.h diff --git a/Makefile b/Makefile index cb948f5..fb02001 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 dhcp.c machine.c +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 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/httpd/page_impl.c b/httpd/page_impl.c index 363f96b..aa7e38f 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -5,6 +5,7 @@ #include "rtl837x_regs.h" #include "rtl837x_port.h" #include "rtl837x_flash.h" +#include "rtl837x_pins.h" #include "uip.h" #include "html_data.h" #include @@ -178,7 +179,7 @@ void sfp_send_data(uint8_t slot, uint8_t reg, uint8_t len) } reg_read_m(RTL837X_REG_I2C_CTRL); - sfr_mask_data(1, 0xfc, machine.sfp_port[slot].i2c_bus.scl << 5 | machine.sfp_port[slot].i2c_bus.sda << 2); + sfr_mask_data(1, 0xfc, i2c_bus_from_scl_pin(machine.sfp_port[slot].i2c.scl) << 5 | i2c_bus_from_sda_pin(machine.sfp_port[slot].i2c.sda) << 2); reg_write_m(RTL837X_REG_I2C_CTRL); REG_WRITE(RTL837X_REG_I2C_IN, 0, 0, 0, reg); diff --git a/machine.c b/machine.c index 57ce9f6..8660bda 100644 --- a/machine.c +++ b/machine.c @@ -1,4 +1,5 @@ #include "machine.h" +#include "rtl837x_pins.h" #ifdef MACHINE_KP_9000_6XHML_X2 __code const struct machine machine = { @@ -10,16 +11,16 @@ __code const struct machine machine = { .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].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].i2c_bus = { .sda = 3, .scl = 3 }, - .sfp_port[1].pin_detect = 30, - .sfp_port[1].pin_los = 37, - .sfp_port[1].pin_tx_disable = 0xFF, + .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].i2c_bus = { .sda = 4, .scl = 3 }, + .sfp_port[1].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, .reset_pin = 46, }; #elif defined MACHINE_KP_9000_6XH_X @@ -32,11 +33,11 @@ __code const struct machine machine = { .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, 0, 0, 0, 0, 0, 1}, - .sfp_port[0].pin_detect = 30, - .sfp_port[0].pin_los = 37, - .sfp_port[0].pin_tx_disable = 0xFF, + .sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN, + .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 }, }; #elif defined MACHINE_KP_9000_9XH_X_EU __code const struct machine machine = { @@ -48,11 +49,11 @@ __code const struct machine machine = { .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, .is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1}, - .sfp_port[0].pin_detect = 30, - .sfp_port[0].pin_los = 37, - .sfp_port[0].pin_tx_disable = 0xFF, + .sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN, + .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 }, }; #elif defined MACHINE_SWGT024_V2_0 @@ -66,17 +67,17 @@ __code const struct machine machine = { .phys_to_log_port = {4, 5, 6, 7, 8, 3, 0, 0, 0}, .is_sfp= {0, 0, 0, 2, 0, 0, 0, 0, 1}, // Left SFP port (J4) - .sfp_port[0].pin_detect = 30, - .sfp_port[0].pin_los = 37, - .sfp_port[0].pin_tx_disable = 0xFF, + .sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN, + .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 }, /* GPIO 39 */ + .sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, /* GPIO 39 */ // Right SFP port (J2) - .sfp_port[1].pin_detect = 50, - .sfp_port[1].pin_los = 51, - .sfp_port[1].pin_tx_disable = 0xFF, + .sfp_port[1].pin_detect = GPIO50_I2C_SCL2_UART1_TX, + .sfp_port[1].pin_los = GPIO51_I2C_SDA2_UART1_RX, + .sfp_port[1].pin_tx_disable = GPIO_NA, .sfp_port[1].sds = 0, - .sfp_port[1].i2c_bus = { .sda = 3, .scl = 3 }, /* GPIO 40 */ + .sfp_port[1].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 }, /* GPIO 40 */ .reset_pin = 36, }; @@ -90,10 +91,10 @@ __code const struct machine machine = { .log_to_phys_port = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .phys_to_log_port = {0, 1, 2, 3, 4, 5, 6, 7, 8}, .is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1}, - .sfp_port[0].pin_detect = 30, - .sfp_port[0].pin_los = 37, - .sfp_port[0].pin_tx_disable = 0xFF, + .sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN, + .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 }, }; #endif diff --git a/machine.h b/machine.h index 0c8176e..b1051b3 100644 --- a/machine.h +++ b/machine.h @@ -16,13 +16,11 @@ // #define DEFAULT_5C_1SFP -struct i2c_bus { - // These are I2C bus identifiers refer to GPIO MUX document - // for GPIO pin assignments for given bus numbers - uint8_t sda : 3; // SDA pin number 0-4 - uint8_t scl : 3; // SCL pin number 0-3 - uint8_t reserved : 2; -}; +typedef struct { + // GPIO pins for SDA/SCL + uint8_t sda; + uint8_t scl; +} i2c_bus_t; struct sfp_port { @@ -30,7 +28,7 @@ struct sfp_port uint8_t pin_los; // gpio number 0-63, 0xFF = don't have it? uint8_t pin_tx_disable; // gpio number 0-63, 0xFF = not present uint8_t sds; - struct i2c_bus i2c_bus; + i2c_bus_t i2c; }; typedef struct machine { diff --git a/rtl837x_pins.c b/rtl837x_pins.c new file mode 100644 index 0000000..83a9adb --- /dev/null +++ b/rtl837x_pins.c @@ -0,0 +1,112 @@ +#include "rtl837x_pins.h" +#include "rtl837x_common.h" +#include "rtl837x_regs.h" + +uint8_t i2c_bus_from_sda_pin(uint8_t sda_pin) { + switch (sda_pin) { + case GPIO47_I2C_SDA0: + return 0; + case GPIO49_I2C_SDA1: + return 1; + case GPIO51_I2C_SDA2_UART1_RX: + return 2; + case GPIO41_I2C_SDA3_MDIO1: + return 3; + case GPIO39_I2C_SDA4: + return 4; + default: + return 0xFF; + } +} + +uint8_t i2c_bus_from_scl_pin(uint8_t scl_pin) { + switch (scl_pin) { + case GPIO46_I2C_SCL0: + return 0; + case GPIO48_I2C_SCL1: + return 1; + case GPIO50_I2C_SCL2_UART1_TX: + return 2; + case GPIO40_I2C_SCL3_MDC1: + return 3; + default: + return 0xFF; + } +} + +/* Returns RTL837X_REG_GPIO_XX_OUTPUT register address */ +static uint16_t gpio_output_reg(uint8_t pin) { + return pin < 32 ? RTL837X_REG_GPIO_00_31_OUTPUT : RTL837X_REG_GPIO_32_63_OUTPUT; +} + +/* Returns RTL837X_REG_GPIO_XX_DIRECTION register address */ +static uint16_t gpio_direction_reg(uint8_t pin) { + return pin < 32 ? RTL837X_REG_GPIO_00_31_DIRECTION : RTL837X_REG_GPIO_32_63_DIRECTION; +} + + +/* Enable GPIO functions for pin */ +static void gpio_mux_setup(uint8_t pin) +{ + // Some GPIOs require setting MUX registers to enable GPIO + switch (pin) { + case GPIO10_LED10: + reg_bit_clear(RTL837X_PIN_MUX_0, 10); + break; + case GPIO30_ACL_BIT3_EN: + reg_bit_clear(RTL837X_PIN_MUX_2, 3); + break; + case GPIO36_PWM_OUT: + reg_bit_set(RTL837X_PIN_MUX_1, 30); + break; + case GPIO37: + // Intentionally empty, always GPIO + break; + case GPIO50_I2C_SCL2_UART1_TX: + // Bit 15-16 0b00 -> GPIO + reg_read_m(RTL837X_PIN_MUX_1); + sfr_mask_data(1, 0x80, 0x00); + sfr_mask_data(2, 0x01, 0x00); + reg_write_m(RTL837X_PIN_MUX_1); + break; + case GPIO51_I2C_SDA2_UART1_RX: + // Bit 17-18 0b00 -> GPIO + reg_read_m(RTL837X_PIN_MUX_1); + sfr_mask_data(2, 0x06, 0x00); + reg_write_m(RTL837X_PIN_MUX_1); + break; + case GPIO54_ACL_BIT2_EN: + reg_bit_clear(RTL837X_PIN_MUX_2, 2); + break; + case GPIO_NA: + print_string("Attemped to assign GPIO function to N/A pin!"); + break; + default: + print_string("GPIO MUX setup not implemented for pin="); print_byte(pin); print_string("\n"); + } +} + +void gpio_input_setup(uint8_t pin) { + if (pin == GPIO_NA) { + return; + } + + gpio_mux_setup(pin); + reg_bit_clear(gpio_direction_reg(pin), (pin % 32)); +} + +void gpio_output_setup(uint8_t pin, __xdata uint8_t initial_val) { + if (pin == GPIO_NA) { + return; + } + gpio_mux_setup(pin); + + // We need to setup value before enabling output on PIN + if (initial_val) { + reg_bit_set(gpio_output_reg(pin), (pin % 32)); + } else { + reg_bit_clear(gpio_output_reg(pin), (pin % 32)); + } + + reg_bit_set(gpio_direction_reg(pin), (pin % 32)); +} diff --git a/rtl837x_pins.h b/rtl837x_pins.h new file mode 100644 index 0000000..b8768f7 --- /dev/null +++ b/rtl837x_pins.h @@ -0,0 +1,93 @@ +#ifndef _RTL837X_PINS_H_ +#define _RTL837X_PINS_H_ + +#include + +#define GPIO0_LED0 0 +#define GPIO1_LED1 1 +#define GPIO2_LED2 2 +#define GPIO3_LED3 3 +#define GPIO4_LED4 4 +#define GPIO5_LED5 5 +#define GPIO6_LED6 6 +#define GPIO7_LED7 7 +#define GPIO8_LED8 8 +#define GPIO9_LED9 9 +#define GPIO10_LED10 10 +#define GPIO11_LED11 11 +#define GPIO12_LED12 12 +#define GPIO13_LED13 13 +#define GPIO14_LED14 14 +#define GPIO15_LED15 15 +#define GPIO16_LED16 16 +#define GPIO17_LED17 17 +#define GPIO18_LED18 18 +#define GPIO19_LED19 19 +#define GPIO20_LED20 20 +#define GPIO21_LED21 21 +#define GPIO22_LED22 22 +#define GPIO23_LED23 23 +#define GPIO24_LED24 24 +#define GPIO25_LED25 25 +#define GPIO26_LED26 26 +#define GPIO27_LED27 27 +#define GPIO28_SYS_LED 28 +#define GPIO29_GLB_RLDP_LED_EN 29 +#define GPIO30_ACL_BIT3_EN 30 +#define GPIO31_UART0_TX 31 +#define GPIO32_UART0_RX 32 +#define GPIO33_INT 33 +#define GPIO34_MDC0 34 +#define GPIO35_MDIO0 35 +#define GPIO36_PWM_OUT 36 +#define GPIO37 37 +#define GPIO38 38 +#define GPIO39_I2C_SDA4 39 +#define GPIO40_I2C_SCL3_MDC1 40 +#define GPIO41_I2C_SDA3_MDIO1 41 +#define GPIO42_SPI 42 +#define GPIO43_SPI 43 +#define GPIO44_SPI 44 +#define GPIO45_SPI 45 +#define GPIO46_I2C_SCL0 46 +#define GPIO47_I2C_SDA0 47 +#define GPIO48_I2C_SCL1 48 +#define GPIO49_I2C_SDA1 49 +#define GPIO50_I2C_SCL2_UART1_TX 50 +#define GPIO51_I2C_SDA2_UART1_RX 51 +#define GPIO52_ACL_BIT0_EN 52 +#define GPIO53_ACL_BIT1_EN 53 +#define GPIO54_ACL_BIT2_EN 54 +#define GPIO55_PTP_CLK_IN 55 +#define GPIO56_PTP_CLK_OUT 56 +#define GPIO57_PTP_TOD_OUT 57 +#define GPIO58_PTP_PPS_OUT 58 +#define GPIO59_PTP_TOD_IN 59 +#define GPIO60_PTP_PPS_IN 60 +#define GPIO61_SYNCELOCK0 61 +#define GPIO62_SYNCELOCK1 62 +#define GPIO63_MDIO 63 + +/* Not available GPIO */ +#define GPIO_NA 0xFF + +/* Convert SDA PIN GPIO to I2C bus number */ +uint8_t i2c_bus_from_sda_pin(uint8_t sda_pin); + +/* Convert SCL PIN GPIO to I2C bus number */ +uint8_t i2c_bus_from_scl_pin(uint8_t scl_pin); + +/* + * Setup a GPIO pin as input + * pin: GPIO pin number 0-63 + */ +void gpio_input_setup(uint8_t pin); + +/* + * Setup a GPIO pin as output + * pin: GPIO pin number 0-63 + * initial_val: 1 for bit set in RTL837X_REG_GPIO_xx_OUTPUT, 0 for bit not set + */ +void gpio_output_setup(uint8_t pin, __xdata uint8_t initial_val); + +#endif diff --git a/rtlplayground.c b/rtlplayground.c index 90deb1a..b2bc882 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -8,6 +8,7 @@ #include "rtl837x_regs.h" #include "rtl837x_common.h" #include "rtl837x_flash.h" +#include "rtl837x_pins.h" #include "rtl837x_phy.h" #include "rtl837x_port.h" #include "rtl837x_stp.h" @@ -807,7 +808,7 @@ uint8_t sfp_read_reg(uint8_t slot, uint8_t reg) } reg_read_m(RTL837X_REG_I2C_CTRL); - sfr_mask_data(1, 0xfc, machine.sfp_port[slot].i2c_bus.scl << 5 | machine.sfp_port[slot].i2c_bus.sda << 2); + sfr_mask_data(1, 0xfc, i2c_bus_from_scl_pin(machine.sfp_port[slot].i2c.scl) << 5 | i2c_bus_from_sda_pin(machine.sfp_port[slot].i2c.sda) << 2); reg_write_m(RTL837X_REG_I2C_CTRL); REG_WRITE(RTL837X_REG_I2C_IN, 0, 0, 0, reg); @@ -1009,57 +1010,13 @@ bool gpio_pin_test(uint8_t pin) return sfr_data[3-((pin >> 3) & 3)] & (1 << (pin & 7)); } -void gpio_mux_setup(uint8_t pin) -{ - // Some GPIOs require setting MUX registers to enable GPIO - if (pin == 36) { - reg_bit_set(RTL837X_PIN_MUX_1, 30); - } else if ( pin == 50 ) { - // Bit 15-16 0b00 -> GPIO - reg_read_m(RTL837X_PIN_MUX_1); - sfr_mask_data(1, 0x80, 0x00); - sfr_mask_data(2, 0x01, 0x00); - reg_write_m(RTL837X_PIN_MUX_1); - } else if ( pin == 51 ) { - // Bit 17-18 0b00 -> GPIO - reg_read_m(RTL837X_PIN_MUX_1); - sfr_mask_data(2, 0x06, 0x00); - reg_write_m(RTL837X_PIN_MUX_1); - } else if ( pin == 54 ) { - reg_bit_clear(RTL837X_PIN_MUX_2, 2); - } -} - -/* - * Setup a GPIO pin as input - * pin: GPIO pin number 0-63 - */ -void gpio_input_setup(uint8_t pin) { - gpio_mux_setup(pin); - reg_bit_clear(pin < 32 ? RTL837X_REG_GPIO_00_31_DIRECTION : RTL837X_REG_GPIO_32_63_DIRECTION, (pin % 32)); -} - - -/* - * Setup a GPIO pin as output - * pin: GPIO pin number 0-63 - */ -void gpio_output_setup(uint8_t pin) { - gpio_mux_setup(pin); - // Default output to low - reg_bit_clear(pin < 32 ? RTL837X_REG_GPIO_00_31_OUTPUT : RTL837X_REG_GPIO_32_63_OUTPUT, (pin % 32)); - reg_bit_set(pin < 32 ? RTL837X_REG_GPIO_00_31_DIRECTION : RTL837X_REG_GPIO_32_63_DIRECTION, (pin % 32)); -} - /* Inititalize SFP GPIOs */ void setup_sfp_gpio(void) { for (uint8_t sfp = 0; sfp < machine.n_sfp; sfp++) { gpio_input_setup(machine.sfp_port[sfp].pin_detect); gpio_input_setup(machine.sfp_port[sfp].pin_los); - if (machine.sfp_port[sfp].pin_tx_disable != 0xFF) { - gpio_output_setup(machine.sfp_port[sfp].pin_tx_disable); - } + gpio_output_setup(machine.sfp_port[sfp].pin_tx_disable, 0); } } @@ -1866,44 +1823,55 @@ void setup_i2c(void) // HW Control register, enable I2C depending on PIN configuration reg_read_m(RTL837X_PIN_MUX_1); for (uint8_t sfp = 0; sfp < machine.n_sfp; sfp++) { - const uint8_t scl_bus = machine.sfp_port[sfp].i2c_bus.scl; - const uint8_t sda_bus = machine.sfp_port[sfp].i2c_bus.sda; + const uint8_t scl_bus = i2c_bus_from_scl_pin(machine.sfp_port[sfp].i2c.scl); + const uint8_t sda_bus = i2c_bus_from_sda_pin(machine.sfp_port[sfp].i2c.sda); print_string("Configuring I2C for SFP idx="); print_byte(sfp); print_string(" SCL="); print_byte(scl_bus); print_string(", SDA="); print_byte(sda_bus); write_char('\n'); - if (scl_bus == 3) { - // Bit 5-6 0b10 -> SCL (implies enabled SDA on bus 3) - sfr_mask_data(0, 0x60, 0x40); - } else if (scl_bus == 2) { - // Bit 15-16 0b01 -> SCL - sfr_mask_data(1, 0x80, 0x80); - sfr_mask_data(2, 0x01, 0x00); - } else if (scl_bus == 1) { - // Bit 11-12 0b01 -> SCL - sfr_mask_data(1, 0x18, 0x08); - } else if (scl_bus == 0) { - // Bit 7-8 0b01 -> SCL - sfr_mask_data(0, 0x80, 0x80); - sfr_mask_data(1, 0x01, 0x00); - } else { - print_string("Invalid SCL bus number: "); print_byte(scl_bus); write_char('\n'); + switch (scl_bus) { + case 3: + // Bit 5-6 0b10 -> SCL (implies enabled SDA on bus 3) + sfr_mask_data(0, 0x60, 0x40); + break; + case 2: + // Bit 15-16 0b01 -> SCL + sfr_mask_data(1, 0x80, 0x80); + sfr_mask_data(2, 0x01, 0x00); + break; + case 1: + // Bit 11-12 0b01 -> SCL + sfr_mask_data(1, 0x18, 0x08); + break; + case 0: + // Bit 7-8 0b01 -> SCL + sfr_mask_data(0, 0x80, 0x80); + sfr_mask_data(1, 0x01, 0x00); + break; + default: + print_string("Invalid SCL bus number: "); print_byte(scl_bus); write_char('\n'); } - if (sda_bus == 4) { - // Bit 29 0b0 -> SDA - sfr_mask_data(3, 0x20, 0x00); - } else if (sda_bus == 3) { - // Bit 5-6 0b10 -> SDA (implies enabled SCL on bus 3) - sfr_mask_data(0, 0x60, 0x40); - } else if (sda_bus == 2) { - // Bit 17-18 0b01 -> SDA - sfr_mask_data(2, 0x06, 0x02); - } else if (sda_bus == 1) { - // Bit 13-14 0b01 -> SDA - sfr_mask_data(1, 0x60, 0x20); - } else if (sda_bus == 0) { - // Bit 9-10 0b01 -> SDA - sfr_mask_data(1, 0x06, 0x02); - } else { - print_string("Invalid SDA bus number: "); print_byte(sda_bus); write_char('\n'); + switch (sda_bus) { + case 4: + // Bit 29 0b0 -> SDA + sfr_mask_data(3, 0x20, 0x00); + break; + case 3: + // Bit 5-6 0b10 -> SDA (implies enabled SCL on bus 3) + sfr_mask_data(0, 0x60, 0x40); + break; + case 2: + // Bit 17-18 0b01 -> SDA + sfr_mask_data(2, 0x06, 0x02); + break; + case 1: + // Bit 13-14 0b01 -> SDA + sfr_mask_data(1, 0x60, 0x20); + break; + case 0: + // Bit 9-10 0b01 -> SDA + sfr_mask_data(1, 0x06, 0x02); + break; + default: + print_string("Invalid SDA bus number: "); print_byte(sda_bus); write_char('\n'); } } reg_write_m(RTL837X_PIN_MUX_1); @@ -2100,7 +2068,6 @@ void bootloader(void) management_vlan = 0; // Disabled setup_i2c(); - setup_sfp_gpio(); print_string(greeting); From 620edc1ba3e18c900580f642f5d26f62f729812c Mon Sep 17 00:00:00 2001 From: diijkstra <16804536+diijkstra@users.noreply.github.com> Date: Sun, 1 Feb 2026 13:34:29 +0100 Subject: [PATCH 3/3] Initialize GPIOs with PIN defines + Support in MUX setup (not used thou) --- machine.c | 7 +++++-- rtl837x_pins.c | 8 ++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/machine.c b/machine.c index 8660bda..84f1d2c 100644 --- a/machine.c +++ b/machine.c @@ -21,7 +21,7 @@ __code const struct machine machine = { .sfp_port[1].pin_tx_disable = GPIO_NA, .sfp_port[1].sds = 0, .sfp_port[1].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, - .reset_pin = 46, + .reset_pin = GPIO46_I2C_SCL0, }; #elif defined MACHINE_KP_9000_6XH_X __code const struct machine machine = { @@ -38,6 +38,7 @@ __code const struct machine machine = { .sfp_port[0].pin_tx_disable = GPIO_NA, .sfp_port[0].sds = 1, .sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, + .reset_pin = GPIO_NA, }; #elif defined MACHINE_KP_9000_9XH_X_EU __code const struct machine machine = { @@ -54,6 +55,7 @@ __code const struct machine machine = { .sfp_port[0].pin_tx_disable = GPIO_NA, .sfp_port[0].sds = 1, .sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, + .reset_pin = GPIO_NA, }; #elif defined MACHINE_SWGT024_V2_0 @@ -78,7 +80,7 @@ __code const struct machine machine = { .sfp_port[1].pin_tx_disable = GPIO_NA, .sfp_port[1].sds = 0, .sfp_port[1].i2c = { .sda = GPIO41_I2C_SDA3_MDIO1, .scl = GPIO40_I2C_SCL3_MDC1 }, /* GPIO 40 */ - .reset_pin = 36, + .reset_pin = GPIO36_PWM_OUT, }; #elif defined DEFAULT_8C_1SFP @@ -96,5 +98,6 @@ __code const struct machine machine = { .sfp_port[0].pin_tx_disable = GPIO_NA, .sfp_port[0].sds = 1, .sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, + .reset_pin = GPIO_NA, }; #endif diff --git a/rtl837x_pins.c b/rtl837x_pins.c index 83a9adb..a6cbe06 100644 --- a/rtl837x_pins.c +++ b/rtl837x_pins.c @@ -60,8 +60,16 @@ static void gpio_mux_setup(uint8_t pin) reg_bit_set(RTL837X_PIN_MUX_1, 30); break; case GPIO37: + case GPIO38: // Intentionally empty, always GPIO break; + case GPIO46_I2C_SCL0: + // Bit 7-8 0b00 -> GPIO + reg_read_m(RTL837X_PIN_MUX_1); + sfr_mask_data(0, 0x80, 0x00); + sfr_mask_data(1, 0x01, 0x00); + reg_write_m(RTL837X_PIN_MUX_1); + break; case GPIO50_I2C_SCL2_UART1_TX: // Bit 15-16 0b00 -> GPIO reg_read_m(RTL837X_PIN_MUX_1);