diff options
Diffstat (limited to 'sys/contrib/dev/rtw88/usb.c')
| -rw-r--r-- | sys/contrib/dev/rtw88/usb.c | 65 | 
1 files changed, 60 insertions, 5 deletions
| diff --git a/sys/contrib/dev/rtw88/usb.c b/sys/contrib/dev/rtw88/usb.c index 6ce68c7c4d4a..9fe00af9fc0e 100644 --- a/sys/contrib/dev/rtw88/usb.c +++ b/sys/contrib/dev/rtw88/usb.c @@ -139,7 +139,7 @@ static void rtw_usb_write(struct rtw_dev *rtwdev, u32 addr, u32 val, int len)  	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),  			      RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE, -			      addr, 0, data, len, 30000); +			      addr, 0, data, len, 500);  	if (ret < 0 && ret != -ENODEV && count++ < 4)  		rtw_err(rtwdev, "write register 0x%x failed with %d\n",  			addr, ret); @@ -165,6 +165,60 @@ static void rtw_usb_write32(struct rtw_dev *rtwdev, u32 addr, u32 val)  	rtw_usb_write(rtwdev, addr, val, 4);  } +static void rtw_usb_write_firmware_page(struct rtw_dev *rtwdev, u32 page, +					const u8 *data, u32 size) +{ +	struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); +	struct usb_device *udev = rtwusb->udev; +	u32 addr = FW_START_ADDR_LEGACY; +	u8 *data_dup, *buf; +	u32 n, block_size; +	int ret; + +	switch (rtwdev->chip->id) { +	case RTW_CHIP_TYPE_8723D: +		block_size = 254; +		break; +	default: +		block_size = 196; +		break; +	} + +	data_dup = kmemdup(data, size, GFP_KERNEL); +	if (!data_dup) +		return; + +	buf = data_dup; + +	rtw_write32_mask(rtwdev, REG_MCUFW_CTRL, BIT_ROM_PGE, page); + +	while (size > 0) { +		if (size >= block_size) +			n = block_size; +		else if (size >= 8) +			n = 8; +		else +			n = 1; + +		ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), +				      RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE, +				      addr, 0, buf, n, 500); +		if (ret != n) { +			if (ret != -ENODEV) +				rtw_err(rtwdev, +					"write 0x%x len %d failed: %d\n", +					addr, n, ret); +			break; +		} + +		addr += n; +		buf += n; +		size -= n; +	} + +	kfree(data_dup); +} +  static int dma_mapping_to_ep(enum rtw_dma_mapping dma_mapping)  {  	switch (dma_mapping) { @@ -866,6 +920,7 @@ static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable)  	case RTW_CHIP_TYPE_8822C:  	case RTW_CHIP_TYPE_8822B:  	case RTW_CHIP_TYPE_8821C: +	case RTW_CHIP_TYPE_8814A:  		rtw_usb_dynamic_rx_agg_v1(rtwdev, enable);  		break;  	case RTW_CHIP_TYPE_8821A: @@ -881,7 +936,7 @@ static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable)  	}  } -static struct rtw_hci_ops rtw_usb_ops = { +static const struct rtw_hci_ops rtw_usb_ops = {  	.tx_write = rtw_usb_tx_write,  	.tx_kick_off = rtw_usb_tx_kick_off,  	.setup = rtw_usb_setup, @@ -891,6 +946,7 @@ static struct rtw_hci_ops rtw_usb_ops = {  	.link_ps = rtw_usb_link_ps,  	.interface_cfg = rtw_usb_interface_cfg,  	.dynamic_rx_agg = rtw_usb_dynamic_rx_agg, +	.write_firmware_page = rtw_usb_write_firmware_page,  	.write8  = rtw_usb_write8,  	.write16 = rtw_usb_write16, @@ -948,7 +1004,6 @@ static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev)  	skb_queue_purge(&rtwusb->rx_queue); -	flush_workqueue(rtwusb->rxwq);  	destroy_workqueue(rtwusb->rxwq);  	skb_queue_purge(&rtwusb->rx_free_queue); @@ -977,7 +1032,6 @@ static void rtw_usb_deinit_tx(struct rtw_dev *rtwdev)  {  	struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); -	flush_workqueue(rtwusb->txwq);  	destroy_workqueue(rtwusb->txwq);  	rtw_usb_tx_queue_purge(rtwusb);  } @@ -1094,7 +1148,8 @@ static int rtw_usb_switch_mode_new(struct rtw_dev *rtwdev)  static bool rtw_usb3_chip_old(u8 chip_id)  { -	return chip_id == RTW_CHIP_TYPE_8812A; +	return chip_id == RTW_CHIP_TYPE_8812A || +	       chip_id == RTW_CHIP_TYPE_8814A;  }  static bool rtw_usb3_chip_new(u8 chip_id) | 
