Skip to content

Commit

Permalink
wifi: rtw88: Add USB PHY configuration
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Bitterblue Smith authored and Ping-Ke Shih committed Jan 12, 2025
1 parent 456ad32 commit 5b1b954
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
10 changes: 10 additions & 0 deletions drivers/net/wireless/realtek/rtw88/reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
68 changes: 68 additions & 0 deletions drivers/net/wireless/realtek/rtw88/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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. */
Expand Down

0 comments on commit 5b1b954

Please sign in to comment.