diff options
author | Bitterblue Smith <rtl8821cerfe2@gmail.com> | 2024-11-14 18:46:08 +0300 |
---|---|---|
committer | Ping-Ke Shih <pkshih@realtek.com> | 2024-11-21 03:45:16 +0300 |
commit | 82a35723a67c29f685d7b518962154a73b7163a2 (patch) | |
tree | 77248395386f11e07cd565ff907825250d1d4e97 /drivers/net/wireless/realtek/rtw88/usb.c | |
parent | 31be3175bd7be89e39c82b3973c9d4ff55a17583 (diff) | |
download | linux-82a35723a67c29f685d7b518962154a73b7163a2.tar.xz |
wifi: rtw88: usb: Support USB 3 with RTL8812AU
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
Diffstat (limited to 'drivers/net/wireless/realtek/rtw88/usb.c')
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/usb.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index 8d6db68246f1..db1769a4b617 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -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) |