mirror of
https://github.com/libretro/Lakka-LibreELEC.git
synced 2025-02-08 01:39:53 +00:00
149 lines
4.6 KiB
Diff
149 lines
4.6 KiB
Diff
From fc57e8bef80bbfaba1ce0554f3b3c8df825e30b9 Mon Sep 17 00:00:00 2001
|
|
From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
|
|
Date: Wed, 1 Jan 2025 18:16:32 +0200
|
|
Subject: [PATCH 37/41] wifi: rtw88: Add USB PHY configuration
|
|
|
|
Add some extra configuration for USB devices. Currently only RTL8822BU
|
|
version (cut) D needs this. The new code makes use of the existing
|
|
usb3_param_8822b array from rtw8822b.c.
|
|
|
|
A user reported that TP-Link Archer T3U in USB 3 mode was randomly
|
|
disconnecting from USB:
|
|
|
|
[ 26.036502] usb 2-2: new SuperSpeed USB device number 3 using xhci_hcd
|
|
...
|
|
[ 27.576491] usb 2-2: USB disconnect, device number 3
|
|
[ 28.621528] usb 2-2: new SuperSpeed USB device number 4 using xhci_hcd
|
|
...
|
|
[ 45.984521] usb 2-2: USB disconnect, device number 4
|
|
...
|
|
[ 46.845585] usb 2-2: new SuperSpeed USB device number 5 using xhci_hcd
|
|
...
|
|
[ 94.400380] usb 2-2: USB disconnect, device number 5
|
|
...
|
|
[ 95.590421] usb 2-2: new SuperSpeed USB device number 6 using xhci_hcd
|
|
|
|
This patch fixes that.
|
|
|
|
Link: https://github.com/lwfinger/rtw88/issues/262
|
|
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
|
|
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
|
|
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
|
|
Link: https://patch.msgid.link/9d312b14-0146-4be8-9c50-ef432234db50@gmail.com
|
|
---
|
|
drivers/net/wireless/realtek/rtw88/reg.h | 10 ++++
|
|
drivers/net/wireless/realtek/rtw88/usb.c | 68 ++++++++++++++++++++++++
|
|
2 files changed, 78 insertions(+)
|
|
|
|
diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
|
|
index e4d506cf9c33..95a39ae74cd3 100644
|
|
--- a/drivers/net/wireless/realtek/rtw88/reg.h
|
|
+++ b/drivers/net/wireless/realtek/rtw88/reg.h
|
|
@@ -871,7 +871,17 @@
|
|
|
|
#define REG_USB_MOD 0xf008
|
|
#define REG_USB3_RXITV 0xf050
|
|
+#define REG_USB2_PHY_ADR 0xfe40
|
|
+#define REG_USB2_PHY_DAT 0xfe41
|
|
+#define REG_USB2_PHY_CMD 0xfe42
|
|
+#define BIT_USB2_PHY_CMD_TRG 0x81
|
|
#define REG_USB_HRPWM 0xfe58
|
|
+#define REG_USB3_PHY_ADR 0xff0c
|
|
+#define REG_USB3_PHY_DAT_L 0xff0d
|
|
+#define REG_USB3_PHY_DAT_H 0xff0e
|
|
+#define BIT_USB3_PHY_ADR_WR BIT(7)
|
|
+#define BIT_USB3_PHY_ADR_RD BIT(6)
|
|
+#define BIT_USB3_PHY_ADR_MASK GENMASK(5, 0)
|
|
|
|
#define RF_MODE 0x00
|
|
#define RF_MODOPT 0x01
|
|
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
|
|
index 1572b61cf877..c4908db4ff0e 100644
|
|
--- a/drivers/net/wireless/realtek/rtw88/usb.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
|
|
@@ -1128,6 +1128,71 @@ static int rtw_usb_switch_mode(struct rtw_dev *rtwdev)
|
|
return rtw_usb_switch_mode_new(rtwdev);
|
|
}
|
|
|
|
+#define USB_REG_PAGE 0xf4
|
|
+#define USB_PHY_PAGE0 0x9b
|
|
+#define USB_PHY_PAGE1 0xbb
|
|
+
|
|
+static void rtw_usb_phy_write(struct rtw_dev *rtwdev, u8 addr, u16 data,
|
|
+ enum usb_device_speed speed)
|
|
+{
|
|
+ if (speed == USB_SPEED_SUPER) {
|
|
+ rtw_write8(rtwdev, REG_USB3_PHY_DAT_L, data & 0xff);
|
|
+ rtw_write8(rtwdev, REG_USB3_PHY_DAT_H, data >> 8);
|
|
+ rtw_write8(rtwdev, REG_USB3_PHY_ADR, addr | BIT_USB3_PHY_ADR_WR);
|
|
+ } else if (speed == USB_SPEED_HIGH) {
|
|
+ rtw_write8(rtwdev, REG_USB2_PHY_DAT, data);
|
|
+ rtw_write8(rtwdev, REG_USB2_PHY_ADR, addr);
|
|
+ rtw_write8(rtwdev, REG_USB2_PHY_CMD, BIT_USB2_PHY_CMD_TRG);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void rtw_usb_page_switch(struct rtw_dev *rtwdev,
|
|
+ enum usb_device_speed speed, u8 page)
|
|
+{
|
|
+ if (speed == USB_SPEED_SUPER)
|
|
+ return;
|
|
+
|
|
+ rtw_usb_phy_write(rtwdev, USB_REG_PAGE, page, speed);
|
|
+}
|
|
+
|
|
+static void rtw_usb_phy_cfg(struct rtw_dev *rtwdev,
|
|
+ enum usb_device_speed speed)
|
|
+{
|
|
+ const struct rtw_intf_phy_para *para = NULL;
|
|
+ u16 offset;
|
|
+
|
|
+ if (!rtwdev->chip->intf_table)
|
|
+ return;
|
|
+
|
|
+ if (speed == USB_SPEED_SUPER)
|
|
+ para = rtwdev->chip->intf_table->usb3_para;
|
|
+ else if (speed == USB_SPEED_HIGH)
|
|
+ para = rtwdev->chip->intf_table->usb2_para;
|
|
+
|
|
+ if (!para)
|
|
+ return;
|
|
+
|
|
+ for ( ; para->offset != 0xffff; para++) {
|
|
+ if (!(para->cut_mask & BIT(rtwdev->hal.cut_version)))
|
|
+ continue;
|
|
+
|
|
+ offset = para->offset;
|
|
+
|
|
+ if (para->ip_sel == RTW_IP_SEL_MAC) {
|
|
+ rtw_write8(rtwdev, offset, para->value);
|
|
+ } else {
|
|
+ if (offset > 0x100)
|
|
+ rtw_usb_page_switch(rtwdev, speed, USB_PHY_PAGE1);
|
|
+ else
|
|
+ rtw_usb_page_switch(rtwdev, speed, USB_PHY_PAGE0);
|
|
+
|
|
+ offset &= 0xff;
|
|
+
|
|
+ rtw_usb_phy_write(rtwdev, offset, para->value, speed);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|
{
|
|
struct rtw_dev *rtwdev;
|
|
@@ -1183,6 +1248,9 @@ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|
goto err_destroy_rxwq;
|
|
}
|
|
|
|
+ rtw_usb_phy_cfg(rtwdev, USB_SPEED_HIGH);
|
|
+ rtw_usb_phy_cfg(rtwdev, USB_SPEED_SUPER);
|
|
+
|
|
ret = rtw_usb_switch_mode(rtwdev);
|
|
if (ret) {
|
|
/* Not a fail, but we do need to skip rtw_register_hw. */
|
|
--
|
|
2.43.0
|
|
|