RTL83xx-based switches typically have a large number of LEDs due to each switch port requiring at least one LED, which typically is bi-color (Green for 1000MBit, Yellow for 100/10MBit) or even tri-color (fail status or PoE). Some switches have two separate LEDs per port, others only one multi-colored LED. For controlling these LEDs, this however does not make any difference. In order to control so many different LEDs, normally a serial bus with PINs LED_CLK (122 on the RTL838x) and LED_DAT (123) is used for the port status LEDs, while a few other LEDs can be controlled directly by the SoC. In particular on the RTL838x SoCs with their very few available GPIOs, this is normally only the System LED. The power led is normally not SoC controllable.
There are several different ways how the LEDs can be controlled by this serial bus. The bus itself can be in SCAN mode (with different LED numbers) or SERIAL mode. In any case the serial information needs to be converted in order to drive the respective LED. There are two different converters found on the RTL83xx boards: 74HC164 shift registers and RTL8231 GPIO expanders. The shift-registers only work with the serial mode, whereas the RTL8231 supports both serial and scan mode. The scan-mode actually is an I2C-like mode, called SMI mode by Realtek.
For the RTL SoCs, the port LEDs are typically automatically controlled by the SoC (ASIC) using the serial bus. The configuration is partially defined by strapping pins, and by several LED control registers. On the RTL839x, the serial interface is initially configured by strapping pins 156 and 157:
The setup of the LED configuration is normally done by U-Boot and does not need to be changed by Linux, unless manual control of the LEDs is necessary, for example if some of the port-LEDs have special purposes. U-Boot configures the LEDs in board/Realtek/switch/rtk/mac/rtl8380/rtl8380_init.c
. The configuration values for different boards can be found in boot/u-boot-2011.12/board/Realtek/switch/rtk/conf/
.
Both the RTL838x and the RTL839x have a LED control register, named RTL83XX_LED_GLB_CTRL
, which allows to enable and configure the serial LED interface and control the system LED.
Manual control seems necessary in case where serially connected LEDs are not used as port-leds (such as additional status LEDs for PoE, "cloud connection" and the like). In that case it appears that the setup of all the serial LEDs is too complex to be controlled by the SoC alone. The user needs to disable SoC control over all the serially connected LEDs in that case. On both the RTL839x and RTL838x, software control is enabled by setting the respective bits in the RTL83XX_LED_SW_P_EN_CTRL(port)
register. One of these registers holds the settings for 10 ports and 3 bits define the state of the LED:
It is unclear why 2 bits would not be sufficient for this.
The power LED can be set to different blinking modes with register RTL8380_LED_MODE_SEL (0xBB001004)
, bits 2 and 3. Bits 0 and 1 seem to be controlled by strapping and define the way the Power LED is controlled.
These registers are at a base address of 0xBB00A000
.
Offset | Name | Description |
---|---|---|
0x00 | LED_GLB_CTRL | |
0x04 | LED_MODE_CTRL | |
0x08 | LED_P_EN_CTRL | Bit mask indicating which LEDs are ASIC controlled. Bit position corresponds to the MAC/phy number. Set to 1 to enable the LED output for this phy. |
0x0C | LED_SW_CTRL | |
0x10+4×n | LED_n_SW_P_EN_CTRL | LED index n = {0, 1, 2}. Bit mask indicating which LEDs are controlled by the user. Bit position corresponds to the MAC/phy number. Set to 0 for automatic control, 1 for manual control. The corresponding bit in LED_P_EN_CTRL must also be set for this setting to be effective. |
0x1C+4×p | LED_SW_P_p_CTRL | Port index p = {0, .., 27} |
0x8C + 4×i | EXT_GPIO_DIR_i_CTRL | i = floor(index/32), index = {0, .., 54} |
0x94 + 4×i | EXT_GPIO_DATA_i_CTRL | i = floor(index/32), index = {0, .., 54} |
0x9C | EXT_GPIO_INDIRECT_ACCESS | |
0xA0 | LED_LOAD_LV1 | |
0xA4 | LED_LOAD_LV2 | |
0xA8 | LED_LOAD_LV3 | |
0xAC+4×k | LED0_LO_STSk_CTRL | Low ports LED0 status control |
0xB8+4×k | LED1_LO_STSk_CTRL | Low ports LED1 status control |
0xC4+4×k | LED2_LO_STSk_CTRL | Low ports LED2 status control |
0xD0 | LED0_HI_STS_CTRL | High ports LED0 status control |
0xD4 | LED1_HI_STS_CTRL | High ports LED1 status control |
0xD8 | LED2_HI_STS_CTRL | High ports LED2 status control |
0xDC | LED_RTCT_CTRL | (To confirm) Realtek Cable Test control register |
0xE0 | EXTRA_GPIO_CTRL | |
0xE4 | EXTRA_GPIO_DIR0 | |
0xE8 | EXTRA_GPIO_DIR1 | |
0xEC | EXTRA_GPIO_DATA0 | |
0xF0 | EXTRA_GPIO_DATA1 |
The SoCs have been designed with the RTL8231 LED expanders in mind as a first-class citizen. A hardware peripheral is present that can keep track of the state of one (or two on RTL93xx) RTL8231 chip(s). The SoC's have dedicated pins and controllers for this task. For rtl930x C1 `LED_MDC` and C2 `LED_MDIO` For rtl931x, AL18 `LED_MDC` and AK18 `LED_MDIO`. This does require the RTL8231 connected to only function as a LED expander. This should not be confused with the dedicated `EXT_GPIO_MDxx` pins!
Main control register for hardware accelerated LEDs and RTL8231 access.
Bits | Field description |
---|---|
0-2 | Low port LED mask. Activate an LED output for ports 0-23 by setting the respective bit. 0: no LEDs, 0x1: one LED, 0x3: two active LEDs, 0x7: three active LEDs. LEDs must be activated from LSB to MSB, using e.g. 0x5 to enable LED2 and LED0 may confuse the LED controller. |
3-5 | High port LED mask. Activate an LED output for ports 24-27 by setting the respective bit. 0: no LEDs, 0x1: one LED, 0x3: two active LEDs, 0x7: three active LEDs. Should have the same value as the low-port configuration, even if the ports aren't used. |
6 | MDIO-clock duty cycle for LED interface |
7-8 | Combo Port mode. For board RTL8382M_8218B_INTPHY_8218B_2FIB_1G_DEMO cleared to 0, for all others set to 0x2 |
9-11 | STEP1 Power on LED 2..0 |
12-14 | STEP2 Power on LED 2..0 |
15 | Enable system status LED. Will use GPIO0 (A0) as an output |
16-17 | System LED mode. 0: off, 1: blink rate 64ms, 2: blink rate 1024ms, 3: on |
18 | LED Load enable |
19-21 | External 8231 GPIO enable 2..0 |
22-23 | RTL8231 LED blink time bits 1..0. See also bit 30. |
24 | RTL8231 buzzer enable |
25-27 | RTL8231 buzzer frequency selection |
28 | Buzzer CMD |
29 | Config 8231 |
30 | RTL8231 LED blink time bit 2 |
Set the LED mode for the low and high ports. Field values can be 0-31 and indicate a state matching condition. "Link" will turn the LED on, "Act" will briefly toggle the LED on link activity, with the default state depending on a "Link" specifier. Any speed specifier will narrow the match down to only those speeds. Activity matches only the link the LED is associated with.
Bits | Field description |
---|---|
0-4 | LED0 mode for port 0-23 |
5-9 | LED1 mode for port 0-23 |
1-14 | LED2 mode for port 0-23 |
15-19 | LED0 mode for port 24-27 |
20-24 | LED1 mode for port 24-27 |
25-29 | LED2 mode for port 24-27 |
28 registers, at offsets (0x1C + 4×port).
Bits | Field description | Field values |
---|---|---|
0-2 | LED0 control | 0: off 1: toggle every 32ms 2: toggle every 64ms 3: toggle every 128ms 4: toggle every 512ms 5: on 6: toggle every 1024ms 7: toggle every 512ms |
3-5 | LED1 control | |
6-8 | LED2 control |
Usually described as the "indirect access" register EXT_GPIO_INDIRECT_ACCESS, at offset 0x9C. Used to send and receive SMI data frames to an external device. Note that there is no indication of command failure, this has to be determined from the register values.
Bits | Field desciption |
---|---|
31-16 | Frame data. For write commands, this is the data to be sent when executing the command. For read commands, this is the received data after command execution finishes. |
11-7 | Number of the register to be accessed. |
6-2 | Device address. Address of the device to be accessed. |
1 | Operation bit. Set to 0 for read requests, 1 for write requests. |
0 | Execute bit. Set to 1 to perform the request. Will self-clear after the command is completed or times out. |
Up to five 3-bit status fields are packed into half-words. For LED0 for example, MAC 0-19 are in the first two registers (0xAC, 0xB0), MAC 20-23 in third (0xB4), and MAC 24-31 in the fourth/high register (0xD0). The high register divides the eight MAC evenly over both half words, putting four (24-27) in the lowest 16 bit, and four (28-31) in the highest 16 bit.
Bits | MAC LED status |
---|---|
0-2 | MAC 16*n + 0 for (n < 3) |
3-5 | MAC 16*n + 1 for (n < 3) |
6-8 | MAC 16*n + 2 for (n < 3) |
9-11 | MAC 16*n + 3 for (n < 3) |
12-14 | MAC 16*n + 4 for (n < 2) |
15 | reserved |
16-18 | MAC 16*n + 5 for (n < 2), MAC 16*n + 4 for (n = 3) |
19-21 | MAC 16*n + 6 for (n < 2), MAC 16*n + 5 for (n = 3) |
22-24 | MAC 16*n + 7 for (n < 2), MAC 16*n + 6 for (n = 3) |
25-27 | MAC 16*n + 8 for (n < 2), MAC 16*n + 7 for (n = 3) |
28-30 | MAC 16*n + 9 for (n < 2) |
31 | reserved |
On the RTL839x RTL8390_LED_GLB_CTRL
has the following bits:
pModel→led.led_if_sel
:LED_IF_SEL_SERIAL
: 0LED_IF_SEL_SINGLE_COLOR_SCAN
: 1LED_IF_SEL_BI_COLOR_SCAN
: 2pModel→led.num
pModel→led.led_if_sel
, LED_IF_SEL_SERIAL is active low, all other active high
Configuration of the automatic control of the LEDs is done on this SoC through defining the function of a port LED. 3 Sets of registers define whether a Port has a Led indicating Copper functionality, Fibre or Combo port. The registers are big endian 2x32 bit registers, named RTL8390_LED_COPR_PMASK_CTRL
, RTL8390_LED_FIB_PMASK_CTRL
, RTL8390_LED_COMBO_PMASK_CTRL
. U-Boot sets them up by copying the following configuration values over (example from a 52 port switch with 4 fibre ports, rtl8393m_demo_board.c):
.led.led_if_sel = LED_IF_SEL_SERIAL, .led.num = 2, .led.copr_pmask[0] = 0xFFFFFFFF, .led.copr_pmask[1] = 0x000FFFFF, .led.fib_pmask[0] = 0x00000000, .led.fib_pmask[1] = 0x000F0000, .led.led_combo[0] = 0x00000000, /* LED definition - set 0 */ .led.led_definition_set[0].led[0] = 0xA, /* 10/100Mbps link/act */ .led.led_definition_set[0].led[1] = 0xF, /* 1000Mbps link/act */ .led.led_definition_set[0].led[2] = 0x6, /* duplex mode */ /* LED definition selection (per-port) */ .led.led_copr_set_psel_bit0_pmask[0] = 0x00000000, .led.led_copr_set_psel_bit1_pmask[0] = 0x00000000, .led.led_copr_set_psel_bit0_pmask[1] = 0x00000000, .led.led_copr_set_psel_bit1_pmask[1] = 0x00000000, .led.led_fib_set_psel_bit0_pmask[0] = 0x00000000, .led.led_fib_set_psel_bit1_pmask[0] = 0x00000000, .led.led_fib_set_psel_bit0_pmask[1] = 0x00000000, .led.led_fib_set_psel_bit1_pmask[1] = 0x00000000,
Register base address is 0xBB000000.
Offset | Name | Description |
---|---|---|
0x0E4 | LEB_GLB_CTRL | |
0x0E8 | LED_SET_2_3_CTRL | |
0x0EC | LED_SET_0_1_CTRL | |
0x0F0 + 4×k | LED_COPR_SET_k_SEL_CTRL | k = floor(port/16), port = 0-51 |
0x100 + 4×k | LED_FIB_SET_k_SEL_CTRL | k = floor(port/16), port = 0-51 |
0x110 + 4×k | LED_COPR_PMASK_k_CTRL | k = floor(port/32), port = 0-51 |
0x118 + 4×k | LED_FIB_PMASK_k_CTRL | k = floor(port/32), port = 0-51 |
0x120 + 4×k | LED_COMBO_k_CTRL | k = floor(port/32), port = 0-51 |
0x128 | LED_SW_CTRL | |
0x12C + 4×n | LED_SW_P_EN_n_CTRL | n = floor(port/10), port = 0-51 |
0x144 + 4×p | LED_SW_P_p_CTRL | p = 0-51 |
0x214 + 4×i | EXT_GPIO_DIR_i_CTRL | i = floor(index/32), index = 0-56 |
0x21C + 4×i | EXT_GPIO_DATA_i_CTRL | i = floor(index/32), index = 0-56 |
0x224 | EXT_GPIO_INDIRECT_ACCESS | |
0x228 | LED_LOAD_LV1_10G | |
0x22C | LED_LOAD_LV2_10G | |
0x230 | LED_LOAD_LV3_10G | |
0x234 | LED_LOAD_LV1_1G | |
0x238 | LED_LOAD_LV2_1G | |
0x23C | LED_LOAD_LV3_1G | |
0x240 | LED_LOAD_LV1_100M | |
0x244 | LED_LOAD_LV2_100M | |
0x248 | LED_LOAD_LV3_100M | |
0x24C | LED_LOAD_LV1_10M | |
0x250 | LED_LOAD_LV2_10M | |
0x254 | LED_LOAD_LV3_10M | |
0x258 | LED_P_LOAD_CTRL | |
0x25C | BUZZER_CTRL | RTL8231 buzzer settings shadow register |
52 registers, at offsets (0x144 + 4×port). After making modifications to the registers, the new configuration need to be committed by writing 0x1 to LED_SW_CTRL. This sets the SW_LED_LOAD bit, updates the output, and self-clears afterwards.
Bits | Field description | Field values |
---|---|---|
0-2 | LED0 (cop0) control | 0: off 1: toggle every 32ms 2: toggle every 64ms 3: toggle every 128ms 4: toggle every 256ms 5: toggle every 512ms 6: toggle every 1024ms 7: on |
3-5 | LED1 (cop1) control | |
6-8 | LED2 (cop2) control | |
9-11 | LED3 (fib0) control | |
12-14 | LED4 (fib1) control | |
15-17 | LED5 (fib2) control |
These registers are at a base address of 0xBB00C400
.
Offset | Name | Description |
---|---|---|
0x00 | LED_GLB_CTRL | |
0x04 | LED_PORT_NUM_CTR(port) | port: 0-27, 2 bits per port |
0x0C | LED_SET_3_CTRL | |
0x10 | LED_SET_2_CTRL | |
0x14 | LED_SET_1_CTRL | |
0x18 | LED_SET_0_CTRL | |
0x1C | LED_PORT_COPR_SET_SEL_CTRL(port) | port = 0-27, 2 bits per port |
0x24 | LED_PORT_FIB_SEL_CTRL(port) | port = 0-27, 2 bits per port |
0x2C | LED_PORT_COPR_MASK_CTRL(port) | port = 0-27, 2 bits per port |
0x30 | LED_PORT_FIB_MASK_CTRL(port) | port = 0-27, 2 bits per port |
0x34 | LED_PORT_COMBO_MASK_CTRL(port) | port = 0-27, 1 bit per port |
0x38 | LED_SW_LED_LOAD | |
0x3c | LED_PORT_SW_EN_CTRL(port) | port = 0-27, 4 bits per port |
0x4c | LED_PORT_SW_CTRL(port) | port = 0-27, 1 register per port |
0xbc | LED_INDRT_ACCESS_CTRL | standard SMI access register |
0xc0 | LED_LOAD_LV1_10G | |
0xc4 | LED_LOAD_LV2_10G | |
0xc8 | LED_LOAD_LV3_10G | |
0xcc | LED_LOAD_LV1_2P5G | |
0xd0 | LED_LOAD_LV2_2P5G | |
0xd4 | LED_LOAD_LV3_2P5G | |
0xd8 | LED_LOAD_LV1_1G | |
0xdc | LED_LOAD_LV2_1G | |
0xe0 | LED_LOAD_LV3_1G | |
0xe4 | LED_LOAD_LV1_500M | |
0xe8 | LED_LOAD_LV2_500M | |
0xec | LED_LOAD_LV3_500M | |
0xf0 | LED_LOAD_LV1_100M | |
0xf4 | LED_LOAD_LV2_100M | |
0xf8 | LED_LOAD_LV3_100M | |
0xfc | LED_LOAD_LV1_10M | |
0x100 | LED_LOAD_LV2_10M | |
0x104 | LED_LOAD_LV3_10M | |
0x108 | LED_P_LOAD_CTRL |
The extra GPIO block starts at a base address of 0xBB00BE00
:
Offset | Name | Description |
---|---|---|
0x00 | EXT_GPIO_GLB_CTRL | |
0x04 | EXT_GPIO_TRIG_CTRL | |
0x08 | EXT_GPIO_DIR_CTRL_1 | |
0x0c | EXT_GPIO_DIR_CTRL_2 | |
0x10 | EXT_GPIO_DIR_CTRL_3 | |
0x14 | EXT_GPIO_DATA_CTRL_1 | |
0x18 | EXT_GPIO_DATA_CTRL_2 | |
0x1c | EXT_GPIO_DATA_CTRL_3 | |
0x20 | EXT_GPIO_INDRT_ACCESS_CTRL | standard SMI access register |