LED Control
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:
- 0b00 Serial LED mode
- 0b01: SCAN single mode
- 0b10: SCAN Bi-color mode
- 0b11: disable LED.
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:
- 0x0: SoC controls LED
- 0x1: One Single Color LED connected here
- 0x3: Bi-color LED
- 0x7: Tri-color LED
It is unclear why 2 bits would not be sufficient for this.
LEDs and GPIO expanders on the RTL838x
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.
RTL8380 external LED and GPIO registers
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 |
Global LED control
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 |
Port LED mode control
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.
- 0: Link/Act
- 1: Link
- 2: Act
- 3: Act Rx
- 4: Act Tx
- 7: Link 1G
- 8: Link 100M
- 9: Link 10M
- 10: Link/Act 1G
- 11: Link/Act 100M
- 12: Link/Act 10M
- 13: Link/Act 1G/100M
- 14: Link/Act 1G/10M
- 15: Link/Act 100M/10M
- 31: Off
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 |
Port LED user control
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 |
Extra GPIO command register
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. |
Port LED status registers
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 |
LEDs on the RTL839x
On the RTL839x RTL8390_LED_GLB_CTRL
has the following bits:
- Bits 0-1: Interface selection: Defined by board config variable
pModel→led.led_if_sel
:LED_IF_SEL_SERIAL
: 0LED_IF_SEL_SINGLE_COLOR_SCAN
: 1LED_IF_SEL_BI_COLOR_SCAN
: 2
- Bits 2-3: LED number selection: Number of LEDs per port, configured from
pModel→led.num
- Bit 4: LED MDIO-Clock duty (cycle?)
- Bit 5: Enable LEDs. This enables all leds controlled via the serial interface
- Bits 6-7: Power-On-Blink selection
- Bits 8-10: STEP1 Power on LED
- Bits 11-13: STEP2 Power on LED
- Bit 14: Enable System LED
- Bits 15 - 16: System LED blink mode
- Bit 17: Enable external GPIO (meaning the RTL8231 via the LED_CLK/DATA I2C-like interface, controlled by the SMI register)
- Bit 18-20: LED clock duty (cycle?): Probably refers to the duty cycle of the LED_CLK line
- Bit 22: Blink Time selection
- Bit 25: LED active (Low or high), Set by
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,
RTL8390 register overview
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 |
Port LED user control
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 |
LEDs on the RTL930x
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 |