[PATCH net-next 8/8] r8152: support UPS for RTL8157 and RTL8159
From: Chih Kai Hsu
Date: Wed Sep 02 2026 - 05:24:41 EST
Add a new function, r8157_ups_en(), to support UPS for RTL8157 and
RTL8159, and also extend r8156_ups_flags().
Signed-off-by: Chih Kai Hsu <hsu.chih.kai@xxxxxxxxxxx>
---
drivers/net/usb/r8152.c | 109 +++++++++++++++++++++++++++++++++++-----
1 file changed, 97 insertions(+), 12 deletions(-)
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index b809317de74f7..96abd0447741a 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -619,6 +619,11 @@
#define UPS_FLAGS_250M_CKDIV BIT(2)
#define UPS_FLAGS_EN_ALDPS BIT(3)
#define UPS_FLAGS_CTAP_SHORT_DIS BIT(4)
+#define UPS_FLAGS_EN_100M_EEE BIT(9)
+#define UPS_FLAGS_EN_1000M_EEE BIT(10)
+#define UPS_FLAGS_EN_2500M_EEE BIT(11)
+#define UPS_FLAGS_EN_5000M_EEE BIT(12)
+#define UPS_FLAGS_EN_10G_EEE BIT(13)
#define UPS_FLAGS_SPEED_MASK (0xf << 16)
#define ups_flags_speed(x) ((x) << 16)
#define UPS_FLAGS_EN_EEE BIT(20)
@@ -4185,8 +4190,27 @@ static void r8156_ups_flags(struct r8152 *tp)
if (tp->ups_info.aldps)
ups_flags |= UPS_FLAGS_EN_ALDPS;
- if (tp->ups_info.eee)
- ups_flags |= UPS_FLAGS_EN_EEE;
+ if (tp->ups_info.eee) {
+ switch (tp->version) {
+ case RTL_VER_17_QFN68:
+ if (tp->eee_adv & MDIO_EEE_10GT)
+ ups_flags |= UPS_FLAGS_EN_10G_EEE;
+ fallthrough;
+ case RTL_VER_16:
+ if (tp->eee_adv & MDIO_EEE_100TX)
+ ups_flags |= UPS_FLAGS_EN_100M_EEE;
+ if (tp->eee_adv & MDIO_EEE_1000T)
+ ups_flags |= UPS_FLAGS_EN_1000M_EEE;
+ if (tp->eee_adv2 & MDIO_EEE_2_5GT)
+ ups_flags |= UPS_FLAGS_EN_2500M_EEE;
+ if (tp->eee_adv2 & MDIO_EEE_5GT)
+ ups_flags |= UPS_FLAGS_EN_5000M_EEE;
+ break;
+ default:
+ ups_flags |= UPS_FLAGS_EN_EEE;
+ break;
+ }
+ }
if (tp->ups_info.flow_control)
ups_flags |= UPS_FLAGS_EN_FLOW_CTR;
@@ -4237,20 +4261,33 @@ static void r8156_ups_flags(struct r8152 *tp)
case NWAY_2500M_FULL:
ups_flags |= ups_flags_speed(9);
break;
+ case NWAY_5000M_FULL:
+ ups_flags |= ups_flags_speed(10);
+ break;
+ case NWAY_10000M_FULL:
+ ups_flags |= ups_flags_speed(11);
+ break;
default:
break;
}
- switch (tp->ups_info.lite_mode) {
- case 1:
- ups_flags |= 0 << 5;
- break;
- case 2:
- ups_flags |= 2 << 5;
+ switch (tp->version) {
+ case RTL_VER_16:
+ case RTL_VER_17_QFN68:
break;
- case 0:
default:
- ups_flags |= 1 << 5;
+ switch (tp->ups_info.lite_mode) {
+ case 1:
+ ups_flags |= 0 << 5;
+ break;
+ case 2:
+ ups_flags |= 2 << 5;
+ break;
+ case 0:
+ default:
+ ups_flags |= 1 << 5;
+ break;
+ }
break;
}
@@ -4422,6 +4459,35 @@ static void r8156_ups_en(struct r8152 *tp, bool enable)
}
}
+static void r8157_ups_en(struct r8152 *tp, bool enable)
+{
+ if (enable) {
+ r8156_ups_flags(tp);
+
+ ocp_byte_set_bits(tp, MCU_TYPE_USB, USB_POWER_CUT,
+ UPS_EN | USP_PREWAKE | PHASE2_EN);
+
+ ocp_byte_set_bits(tp, MCU_TYPE_USB, USB_MISC_2,
+ UPS_FORCE_PWR_DOWN);
+ } else {
+ ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_POWER_CUT,
+ UPS_EN | USP_PREWAKE);
+
+ ocp_byte_clr_bits(tp, MCU_TYPE_USB, USB_MISC_2,
+ UPS_FORCE_PWR_DOWN);
+
+ if (ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0) & PCUT_STATUS) {
+ /* clear USB fw_ver_reg */
+ ocp_write_byte(tp, MCU_TYPE_USB, 0xcf07, 0);
+
+ tp->rtl_ops.hw_phy_cfg(tp);
+
+ rtl8152_set_speed(tp, tp->autoneg, tp->speed,
+ tp->duplex, tp->advertising);
+ }
+ }
+}
+
static void r8153_power_cut_en(struct r8152 *tp, bool enable)
{
if (enable)
@@ -4580,9 +4646,28 @@ static void rtl8157_runtime_enable(struct r8152 *tp, bool enable)
r8153b_u1u2en(tp, false);
r8157_u2p3en(tp, false);
rtl_runtime_suspend_enable(tp, true);
+
+ switch (tp->version) {
+ case RTL_VER_16:
+ case RTL_VER_17_QFN68:
+ r8157_ups_en(tp, true);
+ break;
+ default:
+ break;
+ }
} else {
r8153_queue_wake(tp, false);
rtl_runtime_suspend_enable(tp, false);
+
+ switch (tp->version) {
+ case RTL_VER_16:
+ case RTL_VER_17_QFN68:
+ r8157_ups_en(tp, false);
+ break;
+ default:
+ break;
+ }
+
r8157_u2p3en(tp, true);
if (tp->udev->speed >= USB_SPEED_SUPER)
r8153b_u1u2en(tp, true);
@@ -9077,7 +9162,7 @@ static void r8157_init(struct r8152 *tp)
ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
r8157_power_cut_en(tp, false);
- r8156_ups_en(tp, false);
+ r8157_ups_en(tp, false);
r8153_queue_wake(tp, false);
rtl_runtime_suspend_enable(tp, false);
@@ -9195,7 +9280,7 @@ static void r8159_init(struct r8152 *tp)
ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500);
r8157_power_cut_en(tp, false);
- r8156_ups_en(tp, false);
+ r8157_ups_en(tp, false);
r8153_queue_wake(tp, false);
rtl_runtime_suspend_enable(tp, false);
--
2.34.1