mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-06 08:46:46 +00:00
wifi: rtw88: 8821cu: Fix firmware upload fail
RTL8822CU, RTL8822BU, and RTL8821CU need an extra register write after
reading and writing certain addresses.
Without this, the firmware upload fails approximately more than 50% of
the time.
Tested with RTL8811CU (Tenda U9 V2.0) which is the same as RTL8821CU
but without Bluetooth.
Fixes: a82dfd33d1
("wifi: rtw88: Add common USB chip support")
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://msgid.link/f12ed39d-28e8-4b8b-8d22-447bcf295afc@gmail.com
This commit is contained in:
parent
b8a62478f3
commit
41a7acb7dd
1 changed files with 40 additions and 0 deletions
|
@ -33,6 +33,36 @@ static void rtw_usb_fill_tx_checksum(struct rtw_usb *rtwusb,
|
|||
rtw_tx_fill_txdesc_checksum(rtwdev, &pkt_info, skb->data);
|
||||
}
|
||||
|
||||
static void rtw_usb_reg_sec(struct rtw_dev *rtwdev, u32 addr, __le32 *data)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
struct usb_device *udev = rtwusb->udev;
|
||||
bool reg_on_section = false;
|
||||
u16 t_reg = 0x4e0;
|
||||
u8 t_len = 1;
|
||||
int status;
|
||||
|
||||
/* There are three sections:
|
||||
* 1. on (0x00~0xFF; 0x1000~0x10FF): this section is always powered on
|
||||
* 2. off (< 0xFE00, excluding "on" section): this section could be
|
||||
* powered off
|
||||
* 3. local (>= 0xFE00): usb specific registers section
|
||||
*/
|
||||
if (addr <= 0xff || (addr >= 0x1000 && addr <= 0x10ff))
|
||||
reg_on_section = true;
|
||||
|
||||
if (!reg_on_section)
|
||||
return;
|
||||
|
||||
status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
||||
RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE,
|
||||
t_reg, 0, data, t_len, 500);
|
||||
|
||||
if (status != t_len && status != -ENODEV)
|
||||
rtw_err(rtwdev, "%s: reg 0x%x, usb write %u fail, status: %d\n",
|
||||
__func__, t_reg, t_len, status);
|
||||
}
|
||||
|
||||
static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len)
|
||||
{
|
||||
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
|
||||
|
@ -58,6 +88,11 @@ static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len)
|
|||
rtw_err(rtwdev, "read register 0x%x failed with %d\n",
|
||||
addr, ret);
|
||||
|
||||
if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C ||
|
||||
rtwdev->chip->id == RTW_CHIP_TYPE_8822B ||
|
||||
rtwdev->chip->id == RTW_CHIP_TYPE_8821C)
|
||||
rtw_usb_reg_sec(rtwdev, addr, data);
|
||||
|
||||
return le32_to_cpu(*data);
|
||||
}
|
||||
|
||||
|
@ -102,6 +137,11 @@ static void rtw_usb_write(struct rtw_dev *rtwdev, u32 addr, u32 val, int len)
|
|||
if (ret < 0 && ret != -ENODEV && count++ < 4)
|
||||
rtw_err(rtwdev, "write register 0x%x failed with %d\n",
|
||||
addr, ret);
|
||||
|
||||
if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C ||
|
||||
rtwdev->chip->id == RTW_CHIP_TYPE_8822B ||
|
||||
rtwdev->chip->id == RTW_CHIP_TYPE_8821C)
|
||||
rtw_usb_reg_sec(rtwdev, addr, data);
|
||||
}
|
||||
|
||||
static void rtw_usb_write8(struct rtw_dev *rtwdev, u32 addr, u8 val)
|
||||
|
|
Loading…
Reference in a new issue