]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtw88: usb: Support USB 3 with RTL8812AU
authorBitterblue Smith <rtl8821cerfe2@gmail.com>
Thu, 14 Nov 2024 15:46:08 +0000 (17:46 +0200)
committerPing-Ke Shih <pkshih@realtek.com>
Thu, 21 Nov 2024 00:45:16 +0000 (08:45 +0800)
Add the function to automatically switch the RTL8812AU into USB 3 mode.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/19cda72b-f1f1-4b69-8369-0e4376b646bf@gmail.com
drivers/net/wireless/realtek/rtw88/usb.c

index 8d6db68246f1dc868c780271f0443c08361ba70d..db1769a4b617b3f75c1fc9673bf4c169dbeeec27 100644 (file)
@@ -930,6 +930,32 @@ static void rtw_usb_intf_deinit(struct rtw_dev *rtwdev,
        usb_set_intfdata(intf, NULL);
 }
 
+static int rtw_usb_switch_mode_old(struct rtw_dev *rtwdev)
+{
+       struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+       enum usb_device_speed cur_speed = rtwusb->udev->speed;
+       u8 hci_opt;
+
+       if (cur_speed == USB_SPEED_HIGH) {
+               hci_opt = rtw_read8(rtwdev, REG_HCI_OPT_CTRL);
+
+               if ((hci_opt & (BIT(2) | BIT(3))) != BIT(3)) {
+                       rtw_write8(rtwdev, REG_HCI_OPT_CTRL, 0x8);
+                       rtw_write8(rtwdev, REG_SYS_SDIO_CTRL, 0x2);
+                       rtw_write8(rtwdev, REG_ACLK_MON, 0x1);
+                       rtw_write8(rtwdev, 0x3d, 0x3);
+                       /* usb disconnect */
+                       rtw_write8(rtwdev, REG_SYS_PW_CTRL + 1, 0x80);
+                       return 1;
+               }
+       } else if (cur_speed == USB_SPEED_SUPER) {
+               rtw_write8_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT(1));
+               rtw_write8_clr(rtwdev, REG_ACLK_MON, BIT(0));
+       }
+
+       return 0;
+}
+
 static int rtw_usb_switch_mode_new(struct rtw_dev *rtwdev)
 {
        enum usb_device_speed cur_speed;
@@ -979,11 +1005,22 @@ static int rtw_usb_switch_mode_new(struct rtw_dev *rtwdev)
        return 1;
 }
 
+static bool rtw_usb3_chip_old(u8 chip_id)
+{
+       return chip_id == RTW_CHIP_TYPE_8812A;
+}
+
+static bool rtw_usb3_chip_new(u8 chip_id)
+{
+       return chip_id == RTW_CHIP_TYPE_8822C ||
+              chip_id == RTW_CHIP_TYPE_8822B;
+}
+
 static int rtw_usb_switch_mode(struct rtw_dev *rtwdev)
 {
        u8 id = rtwdev->chip->id;
 
-       if (id != RTW_CHIP_TYPE_8822C && id != RTW_CHIP_TYPE_8822B)
+       if (!rtw_usb3_chip_new(id) && !rtw_usb3_chip_old(id))
                return 0;
 
        if (!rtwdev->efuse.usb_mode_switch) {
@@ -998,7 +1035,10 @@ static int rtw_usb_switch_mode(struct rtw_dev *rtwdev)
                return 0;
        }
 
-       return rtw_usb_switch_mode_new(rtwdev);
+       if (rtw_usb3_chip_old(id))
+               return rtw_usb_switch_mode_old(rtwdev);
+       else
+               return rtw_usb_switch_mode_new(rtwdev);
 }
 
 int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)