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
This commit is contained in:
diijkstra
2026-02-01 12:58:16 +01:00
parent 2c200417b5
commit 7d62b24a42
7 changed files with 129 additions and 35 deletions
+98 -6
View File
@@ -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);