diff --git a/arch/arm64/boot/dts/rockchip/rk3588-recomputer-rk3588-devkit.dts b/arch/arm64/boot/dts/rockchip/rk3588-recomputer-rk3588-devkit.dts index 918c7c3430de1..90827ecf7ed62 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-recomputer-rk3588-devkit.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-recomputer-rk3588-devkit.dts @@ -893,6 +893,11 @@ /* phy1 - right ethernet port PCIE20_1_TXP */ &pcie2x1l0 { reset-gpios = <&gpio4 RK_PA5 GPIO_ACTIVE_HIGH>; + /* r8125 Ethernet LED configuration: + * LED0 (yellow): blink on traffic at all link speeds + * LED3 (green): solid on at all link speeds + */ + realtek,led-data = <0x18 0x022B 0x96 0x002B>; vpcie3v3-supply = <&vcc5v0_usb_eth>; status = "okay"; }; @@ -907,6 +912,11 @@ /* phy0 - left ethernet port PCIE20_0_TXP */ &pcie2x1l2 { reset-gpios = <&gpio3 RK_PD0 GPIO_ACTIVE_HIGH>; + /* r8125 Ethernet LED configuration: + * LED0 (yellow): blink on traffic at all link speeds + * LED3 (green): solid on at all link speeds + */ + realtek,led-data = <0x18 0x022B 0x96 0x002B>; vpcie3v3-supply = <&vcc5v0_usb_eth>; status = "okay"; }; diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 75836c0e91cf3..0122ab05c82ee 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -659,6 +660,8 @@ struct rtl8169_private { struct rtl_fw *rtl_fw; u32 ocp_base; + u32 *led_data; + int led_data_count; }; typedef void (*rtl_generic_fct)(struct rtl8169_private *tp); @@ -2564,6 +2567,53 @@ static void rtl_wol_enable_rx(struct rtl8169_private *tp) rtl_disable_rxdvgate(tp); } +/* Parse DT-based LED configuration for RTL8125, cache in tp. + * Walk up the device parent chain to find the PCIe platform + * device's of_node with the "realtek,led-data" property. + * Property format: realtek,led-data = ; + */ +static void rtl8125_parse_dt_led_config(struct rtl8169_private *tp) +{ + struct device_node *np = NULL; + struct device *d = &tp->pci_dev->dev; + int count; + + while (d && !np) { + np = d->of_node; + d = d->parent; + } + + if (!np) + return; + + count = of_property_count_u32_elems(np, "realtek,led-data"); + if (count < 2 || count % 2 != 0) + return; + + tp->led_data = kmalloc_array(count, sizeof(u32), GFP_KERNEL); + if (!tp->led_data) + return; + + if (of_property_read_u32_array(np, "realtek,led-data", tp->led_data, count)) { + kfree(tp->led_data); + tp->led_data = NULL; + return; + } + tp->led_data_count = count; +} + +/* Apply cached LED register/value pairs to hardware. */ +static void rtl8125_apply_dt_led_config(struct rtl8169_private *tp) +{ + int i; + + if (!tp->led_data) + return; + + for (i = 0; i < tp->led_data_count; i += 2) + RTL_W16(tp, tp->led_data[i], (u16)tp->led_data[i + 1]); +} + static void rtl_prepare_power_down(struct rtl8169_private *tp) { if (tp->dash_enabled) @@ -3690,6 +3740,7 @@ static void rtl_hw_start_8125_common(struct rtl8169_private *tp) rtl8125a_config_eee_mac(tp); rtl_disable_rxdvgate(tp); + rtl8125_apply_dt_led_config(tp); } static void rtl_hw_start_8125a_2(struct rtl8169_private *tp) @@ -5021,6 +5072,8 @@ static void rtl_remove_one(struct pci_dev *pdev) rtl_release_firmware(tp); + kfree(tp->led_data); + /* restore original MAC address */ rtl_rar_set(tp, tp->dev->perm_addr); } @@ -5488,6 +5541,8 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_dev_run_wake(pdev)) pm_runtime_put_sync(&pdev->dev); + rtl8125_parse_dt_led_config(tp); + return 0; }