mirror of
https://github.com/RinCat/RTL88x2BU-Linux-Driver.git
synced 2024-11-14 03:02:50 +00:00
541 lines
14 KiB
C
541 lines
14 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright(c) 2016 - 2019 Realtek Corporation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#include "halmac_usb_88xx.h"
|
|
|
|
#if (HALMAC_88XX_SUPPORT && HALMAC_USB_SUPPORT)
|
|
|
|
enum usb_burst_size {
|
|
USB_BURST_SIZE_3_0 = 0x0,
|
|
USB_BURST_SIZE_2_0_HS = 0x1,
|
|
USB_BURST_SIZE_2_0_FS = 0x2,
|
|
USB_BURST_SIZE_2_0_OTHERS = 0x3,
|
|
USB_BURST_SIZE_UNDEFINE = 0x7F,
|
|
};
|
|
|
|
#define USB_PHY_PAGE0 0x9B
|
|
#define USB_PHY_PAGE1 0xBB
|
|
|
|
/**
|
|
* init_usb_cfg_88xx() - init USB
|
|
* @adapter : the adapter of halmac
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
init_usb_cfg_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
u8 value8 = 0;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
value8 |= (BIT_DMA_MODE | (0x3 << BIT_SHIFT_BURST_CNT));
|
|
|
|
if (HALMAC_REG_R8(REG_SYS_CFG2 + 3) == 0x20) {
|
|
/* usb3.0 */
|
|
value8 |= (USB_BURST_SIZE_3_0 << BIT_SHIFT_BURST_SIZE);
|
|
} else {
|
|
if ((HALMAC_REG_R8(REG_USB_USBSTAT) & 0x3) == 0x1)/* usb2.0 */
|
|
value8 |= USB_BURST_SIZE_2_0_HS << BIT_SHIFT_BURST_SIZE;
|
|
else /* usb1.1 */
|
|
value8 |= USB_BURST_SIZE_2_0_FS << BIT_SHIFT_BURST_SIZE;
|
|
}
|
|
|
|
HALMAC_REG_W8(REG_RXDMA_MODE, value8);
|
|
HALMAC_REG_W16_SET(REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN);
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* deinit_usb_cfg_88xx() - deinit USB
|
|
* @adapter : the adapter of halmac
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
deinit_usb_cfg_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* cfg_usb_rx_agg_88xx() - config rx aggregation
|
|
* @adapter : the adapter of halmac
|
|
* @halmac_rx_agg_mode
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
cfg_usb_rx_agg_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_rxagg_cfg *cfg)
|
|
{
|
|
u8 dma_usb_agg;
|
|
u8 size;
|
|
u8 timeout;
|
|
u8 agg_enable;
|
|
u32 value32;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
dma_usb_agg = HALMAC_REG_R8(REG_RXDMA_AGG_PG_TH + 3);
|
|
agg_enable = HALMAC_REG_R8(REG_TXDMA_PQ_MAP);
|
|
|
|
switch (cfg->mode) {
|
|
case HALMAC_RX_AGG_MODE_NONE:
|
|
agg_enable &= ~BIT_RXDMA_AGG_EN;
|
|
break;
|
|
case HALMAC_RX_AGG_MODE_DMA:
|
|
agg_enable |= BIT_RXDMA_AGG_EN;
|
|
dma_usb_agg |= BIT(7);
|
|
break;
|
|
|
|
case HALMAC_RX_AGG_MODE_USB:
|
|
agg_enable |= BIT_RXDMA_AGG_EN;
|
|
dma_usb_agg &= ~BIT(7);
|
|
break;
|
|
default:
|
|
PLTFM_MSG_ERR("[ERR]unsupported mode\n");
|
|
agg_enable &= ~BIT_RXDMA_AGG_EN;
|
|
break;
|
|
}
|
|
|
|
if (cfg->threshold.drv_define == 0) {
|
|
if (HALMAC_REG_R8(REG_SYS_CFG2 + 3) == 0x20) {
|
|
/* usb3.0 */
|
|
size = 0x5;
|
|
timeout = 0xA;
|
|
} else {
|
|
/* usb2.0 */
|
|
size = 0x5;
|
|
timeout = 0x20;
|
|
}
|
|
} else {
|
|
size = cfg->threshold.size;
|
|
timeout = cfg->threshold.timeout;
|
|
}
|
|
|
|
value32 = HALMAC_REG_R32(REG_RXDMA_AGG_PG_TH);
|
|
if (cfg->threshold.size_limit_en == 0)
|
|
HALMAC_REG_W32(REG_RXDMA_AGG_PG_TH, value32 & ~BIT_EN_PRE_CALC);
|
|
else
|
|
HALMAC_REG_W32(REG_RXDMA_AGG_PG_TH, value32 | BIT_EN_PRE_CALC);
|
|
|
|
HALMAC_REG_W8(REG_TXDMA_PQ_MAP, agg_enable);
|
|
HALMAC_REG_W8(REG_RXDMA_AGG_PG_TH + 3, dma_usb_agg);
|
|
HALMAC_REG_W16(REG_RXDMA_AGG_PG_TH,
|
|
(u16)(size | (timeout << BIT_SHIFT_DMA_AGG_TO_V1)));
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* reg_r8_usb_88xx() - read 1byte register
|
|
* @adapter : the adapter of halmac
|
|
* @offset : register offset
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
u8
|
|
reg_r8_usb_88xx(struct halmac_adapter *adapter, u32 offset)
|
|
{
|
|
return PLTFM_REG_R8(offset);
|
|
}
|
|
|
|
/**
|
|
* reg_w8_usb_88xx() - write 1byte register
|
|
* @adapter : the adapter of halmac
|
|
* @offset : register offset
|
|
* @value : register value
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
reg_w8_usb_88xx(struct halmac_adapter *adapter, u32 offset, u8 value)
|
|
{
|
|
PLTFM_REG_W8(offset, value);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* reg_r16_usb_88xx() - read 2byte register
|
|
* @adapter : the adapter of halmac
|
|
* @offset : register offset
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
u16
|
|
reg_r16_usb_88xx(struct halmac_adapter *adapter, u32 offset)
|
|
{
|
|
return PLTFM_REG_R16(offset);
|
|
}
|
|
|
|
/**
|
|
* reg_w16_usb_88xx() - write 2byte register
|
|
* @adapter : the adapter of halmac
|
|
* @offset : register offset
|
|
* @value : register value
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
reg_w16_usb_88xx(struct halmac_adapter *adapter, u32 offset, u16 value)
|
|
{
|
|
PLTFM_REG_W16(offset, value);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* reg_r32_usb_88xx() - read 4byte register
|
|
* @adapter : the adapter of halmac
|
|
* @offset : register offset
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
u32
|
|
reg_r32_usb_88xx(struct halmac_adapter *adapter, u32 offset)
|
|
{
|
|
return PLTFM_REG_R32(offset);
|
|
}
|
|
|
|
/**
|
|
* reg_w32_usb_88xx() - write 4byte register
|
|
* @adapter : the adapter of halmac
|
|
* @offset : register offset
|
|
* @value : register value
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
reg_w32_usb_88xx(struct halmac_adapter *adapter, u32 offset, u32 value)
|
|
{
|
|
PLTFM_REG_W32(offset, value);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* set_usb_bulkout_num_88xx() - inform bulk-out num
|
|
* @adapter : the adapter of halmac
|
|
* @bulkout_num : usb bulk-out number
|
|
* Author : KaiYuan Chang
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
set_usb_bulkout_num_88xx(struct halmac_adapter *adapter, u8 num)
|
|
{
|
|
adapter->bulkout_num = num;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* get_usb_bulkout_id_88xx() - get bulk out id for the TX packet
|
|
* @adapter : the adapter of halmac
|
|
* @buf : tx packet, include txdesc
|
|
* @size : tx packet size
|
|
* @id : usb bulk-out id
|
|
* Author : KaiYuan Chang
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
get_usb_bulkout_id_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size,
|
|
u8 *id)
|
|
{
|
|
enum halmac_qsel queue_sel;
|
|
enum halmac_dma_mapping dma_mapping;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (!buf) {
|
|
PLTFM_MSG_ERR("[ERR]buf is NULL!!\n");
|
|
return HALMAC_RET_DATA_BUF_NULL;
|
|
}
|
|
|
|
if (size == 0) {
|
|
PLTFM_MSG_ERR("[ERR]size is 0!!\n");
|
|
return HALMAC_RET_DATA_SIZE_INCORRECT;
|
|
}
|
|
|
|
queue_sel = (enum halmac_qsel)GET_TX_DESC_QSEL(buf);
|
|
|
|
switch (queue_sel) {
|
|
case HALMAC_QSEL_VO:
|
|
case HALMAC_QSEL_VO_V2:
|
|
dma_mapping = adapter->pq_map[HALMAC_PQ_MAP_VO];
|
|
break;
|
|
case HALMAC_QSEL_VI:
|
|
case HALMAC_QSEL_VI_V2:
|
|
dma_mapping = adapter->pq_map[HALMAC_PQ_MAP_VI];
|
|
break;
|
|
case HALMAC_QSEL_BE:
|
|
case HALMAC_QSEL_BE_V2:
|
|
dma_mapping = adapter->pq_map[HALMAC_PQ_MAP_BE];
|
|
break;
|
|
case HALMAC_QSEL_BK:
|
|
case HALMAC_QSEL_BK_V2:
|
|
dma_mapping = adapter->pq_map[HALMAC_PQ_MAP_BK];
|
|
break;
|
|
case HALMAC_QSEL_MGNT:
|
|
dma_mapping = adapter->pq_map[HALMAC_PQ_MAP_MG];
|
|
break;
|
|
case HALMAC_QSEL_HIGH:
|
|
case HALMAC_QSEL_BCN:
|
|
case HALMAC_QSEL_CMD:
|
|
dma_mapping = HALMAC_DMA_MAPPING_HIGH;
|
|
break;
|
|
default:
|
|
PLTFM_MSG_ERR("[ERR]Qsel is out of range\n");
|
|
return HALMAC_RET_QSEL_INCORRECT;
|
|
}
|
|
|
|
switch (dma_mapping) {
|
|
case HALMAC_DMA_MAPPING_HIGH:
|
|
*id = 0;
|
|
break;
|
|
case HALMAC_DMA_MAPPING_NORMAL:
|
|
*id = 1;
|
|
break;
|
|
case HALMAC_DMA_MAPPING_LOW:
|
|
*id = 2;
|
|
break;
|
|
case HALMAC_DMA_MAPPING_EXTRA:
|
|
*id = 3;
|
|
break;
|
|
default:
|
|
PLTFM_MSG_ERR("[ERR]out of range\n");
|
|
return HALMAC_RET_DMA_MAP_INCORRECT;
|
|
}
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* cfg_txagg_usb_align_88xx() -config sdio bus tx agg alignment
|
|
* @adapter : the adapter of halmac
|
|
* @enable : function enable(1)/disable(0)
|
|
* @align_size : sdio bus tx agg alignment size (2^n, n = 3~11)
|
|
* Author : Soar Tu
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
cfg_txagg_usb_align_88xx(struct halmac_adapter *adapter, u8 enable,
|
|
u16 align_size)
|
|
{
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
|
|
/**
|
|
* tx_allowed_usb_88xx() - check tx status
|
|
* @adapter : the adapter of halmac
|
|
* @buf : tx packet, include txdesc
|
|
* @size : tx packet size, include txdesc
|
|
* Author : Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
tx_allowed_usb_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
|
|
{
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
|
|
/**
|
|
* usb_indirect_reg_r32_88xx() - read MAC reg by SDIO reg
|
|
* @adapter : the adapter of halmac
|
|
* @offset : register offset
|
|
* Author : Soar
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
u32
|
|
usb_indirect_reg_r32_88xx(struct halmac_adapter *adapter, u32 offset)
|
|
{
|
|
return 0xFFFFFFFF;
|
|
}
|
|
|
|
/**
|
|
* usb_reg_rn_88xx() - read n byte register
|
|
* @adapter : the adapter of halmac
|
|
* @offset : register offset
|
|
* @size : register value size
|
|
* @value : register value
|
|
* Author : Soar
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
usb_reg_rn_88xx(struct halmac_adapter *adapter, u32 offset, u32 size,
|
|
u8 *value)
|
|
{
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
|
|
/**
|
|
* get_usb_tx_addr_88xx() - get CMD53 addr for the TX packet
|
|
* @adapter : the adapter of halmac
|
|
* @buf : tx packet, include txdesc
|
|
* @size : tx packet size
|
|
* @pcmd53_addr : cmd53 addr value
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
get_usb_tx_addr_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size,
|
|
u32 *cmd53_addr)
|
|
{
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
set_usb_mode_88xx(struct halmac_adapter *adapter, enum halmac_usb_mode mode)
|
|
{
|
|
u32 usb_tmp;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
enum halmac_usb_mode cur_mode;
|
|
|
|
cur_mode = (HALMAC_REG_R8(REG_SYS_CFG2 + 3) == 0x20) ?
|
|
HALMAC_USB_MODE_U3 : HALMAC_USB_MODE_U2;
|
|
|
|
/* check if HW supports usb2_usb3 switch */
|
|
usb_tmp = HALMAC_REG_R32(REG_PAD_CTRL2);
|
|
if (0 == (BIT_GET_USB23_SW_MODE_V1(usb_tmp) |
|
|
(usb_tmp & BIT_USB3_USB2_TRANSITION))) {
|
|
PLTFM_MSG_ERR("[ERR]u2/u3 switch\n");
|
|
return HALMAC_RET_USB2_3_SWITCH_UNSUPPORT;
|
|
}
|
|
|
|
if (mode == cur_mode) {
|
|
PLTFM_MSG_ERR("[ERR]u2/u3 unchange\n");
|
|
return HALMAC_RET_USB_MODE_UNCHANGE;
|
|
}
|
|
|
|
/* Enable IO wrapper timeout */
|
|
if (adapter->chip_id == HALMAC_CHIP_ID_8822B ||
|
|
adapter->chip_id == HALMAC_CHIP_ID_8821C)
|
|
HALMAC_REG_W8_CLR(REG_SW_MDIO + 3, BIT(0));
|
|
|
|
usb_tmp &= ~(BIT_USB23_SW_MODE_V1(0x3));
|
|
|
|
if (mode == HALMAC_USB_MODE_U2)
|
|
HALMAC_REG_W32(REG_PAD_CTRL2,
|
|
usb_tmp |
|
|
BIT_USB23_SW_MODE_V1(HALMAC_USB_MODE_U2) |
|
|
BIT_RSM_EN_V1);
|
|
else
|
|
HALMAC_REG_W32(REG_PAD_CTRL2,
|
|
usb_tmp |
|
|
BIT_USB23_SW_MODE_V1(HALMAC_USB_MODE_U3) |
|
|
BIT_RSM_EN_V1);
|
|
|
|
HALMAC_REG_W8(REG_PAD_CTRL2 + 1, 4);
|
|
HALMAC_REG_W16_SET(REG_SYS_PW_CTRL, BIT_APFM_OFFMAC);
|
|
PLTFM_DELAY_US(1000);
|
|
HALMAC_REG_W32_SET(REG_PAD_CTRL2, BIT_NO_PDN_CHIPOFF_V1);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
usbphy_write_88xx(struct halmac_adapter *adapter, u8 addr, u16 data, u8 speed)
|
|
{
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
if (speed == HAL_INTF_PHY_USB3) {
|
|
HALMAC_REG_W8(0xff0d, (u8)data);
|
|
HALMAC_REG_W8(0xff0e, (u8)(data >> 8));
|
|
HALMAC_REG_W8(0xff0c, addr | BIT(7));
|
|
} else if (speed == HAL_INTF_PHY_USB2) {
|
|
HALMAC_REG_W8(0xfe41, (u8)data);
|
|
HALMAC_REG_W8(0xfe40, addr);
|
|
HALMAC_REG_W8(0xfe42, 0x81);
|
|
} else {
|
|
PLTFM_MSG_ERR("[ERR]Error USB Speed !\n");
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
u16
|
|
usbphy_read_88xx(struct halmac_adapter *adapter, u8 addr, u8 speed)
|
|
{
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
u16 value = 0;
|
|
|
|
if (speed == HAL_INTF_PHY_USB3) {
|
|
HALMAC_REG_W8(0xff0c, addr | BIT(6));
|
|
value = (u16)(HALMAC_REG_R32(0xff0c) >> 8);
|
|
} else if (speed == HAL_INTF_PHY_USB2) {
|
|
if (addr >= 0xE0)
|
|
addr -= 0x20;
|
|
if (addr >= 0xC0 && addr <= 0xDF) {
|
|
HALMAC_REG_W8(0xfe40, addr);
|
|
HALMAC_REG_W8(0xfe42, 0x81);
|
|
value = HALMAC_REG_R8(0xfe43);
|
|
} else {
|
|
PLTFM_MSG_ERR("[ERR]phy offset\n");
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
} else {
|
|
PLTFM_MSG_ERR("[ERR]usb speed !\n");
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
en_ref_autok_usb_88xx(struct halmac_adapter *adapter, u8 en)
|
|
{
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
enum halmac_ret_status
|
|
usb_page_switch_88xx(struct halmac_adapter *adapter, u8 speed, u8 page)
|
|
{
|
|
if (speed == HAL_INTF_PHY_USB3)
|
|
return HALMAC_RET_SUCCESS;
|
|
if (page == 0)
|
|
usbphy_write_88xx(adapter, USB_REG_PAGE, USB_PHY_PAGE0, speed);
|
|
else
|
|
usbphy_write_88xx(adapter, USB_REG_PAGE, USB_PHY_PAGE1, speed);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
#endif /* HALMAC_88XX_SUPPORT */
|