/******************************************************************************
|
*
|
* Copyright(c) 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 "mac_ax.h"
|
|
#define CHIP_ID_HW_DEF_8852A 0x50
|
#define CHIP_ID_HW_DEF_8852B 0x51
|
#define CHIP_ID_HW_DEF_8852C 0x52
|
#define CHIP_ID_HW_DEF_8192XB 0x53
|
|
#define SDIO_WAIT_CNT 50
|
#if MAC_AX_SDIO_SUPPORT
|
static u8 r8_indir_cmd52_sdio(void *drv_adapter,
|
struct mac_ax_pltfm_cb *pltfm_cb, u32 adr);
|
#endif
|
|
#ifndef CONFIG_NEW_HALMAC_INTERFACE
|
static u8 chk_pltfm_cb(void *drv_adapter, enum mac_ax_intf intf,
|
struct mac_ax_pltfm_cb *pltfm_cb)
|
{
|
if (!pltfm_cb)
|
return MACSUCCESS;
|
|
if (!pltfm_cb->msg_print)
|
return MACSUCCESS;
|
|
#if MAC_AX_SDIO_SUPPORT
|
if (!pltfm_cb->sdio_cmd52_r8 || !pltfm_cb->sdio_cmd53_r8 ||
|
!pltfm_cb->sdio_cmd53_r16 || !pltfm_cb->sdio_cmd53_r32 ||
|
!pltfm_cb->sdio_cmd53_rn || !pltfm_cb->sdio_cmd52_w8 ||
|
!pltfm_cb->sdio_cmd53_w8 || !pltfm_cb->sdio_cmd53_w16 ||
|
!pltfm_cb->sdio_cmd53_w32 || !pltfm_cb->sdio_cmd53_wn ||
|
!pltfm_cb->sdio_cmd52_cia_r8) {
|
pltfm_cb->msg_print(drv_adapter, _PHL_ERR_, "[ERR]CB-SDIO\n");
|
return MACSUCCESS;
|
}
|
#endif
|
|
#if (MAC_AX_USB_SUPPORT || MAC_AX_PCIE_SUPPORT)
|
if (!pltfm_cb->reg_r8 || !pltfm_cb->reg_r16 ||
|
!pltfm_cb->reg_r32 || !pltfm_cb->reg_w8 ||
|
!pltfm_cb->reg_w16 || !pltfm_cb->reg_w32) {
|
pltfm_cb->msg_print(drv_adapter, _PHL_ERR_, "[ERR]CB-USB or PCIE\n");
|
return MACSUCCESS;
|
}
|
#endif
|
if (!pltfm_cb->rtl_free || !pltfm_cb->rtl_malloc ||
|
!pltfm_cb->rtl_memcpy || !pltfm_cb->rtl_memset ||
|
!pltfm_cb->rtl_delay_us || !pltfm_cb->rtl_delay_ms ||
|
!pltfm_cb->rtl_mutex_init || !pltfm_cb->rtl_mutex_deinit ||
|
!pltfm_cb->rtl_mutex_lock || !pltfm_cb->rtl_mutex_unlock ||
|
!pltfm_cb->event_notify) {
|
pltfm_cb->msg_print(drv_adapter, _PHL_ERR_, "[ERR]CB-OS\n");
|
return MACSUCCESS;
|
}
|
|
return MACPFCB;
|
}
|
#endif /*CONFIG_NEW_HALMAC_INTERFACE*/
|
|
static u8 chk_pltfm_endian(void)
|
{
|
u32 num = 1;
|
u8 *num_ptr = (u8 *)#
|
|
if (*num_ptr != PLATFOM_IS_LITTLE_ENDIAN)
|
return MACSUCCESS;
|
|
return MACPFCB;
|
}
|
|
#ifdef CONFIG_NEW_HALMAC_INTERFACE
|
#if MAC_AX_SDIO_SUPPORT
|
static u8 r8_indir_cmd52_sdio(void *drv_adapter,
|
struct mac_ax_pltfm_cb *pltfm_cb, u32 adr)
|
{
|
u8 tmp;
|
u32 cnt;
|
|
PLTFM_SDIO_CMD52_W8(R_AX_SDIO_INDIRECT_ADDR, (u8)adr);
|
PLTFM_SDIO_CMD52_W8(R_AX_SDIO_INDIRECT_ADDR + 1, (u8)(adr >> 8));
|
PLTFM_SDIO_CMD52_W8(R_AX_SDIO_INDIRECT_ADDR + 2, (u8)(adr >> 16));
|
PLTFM_SDIO_CMD52_W8(R_AX_SDIO_INDIRECT_ADDR + 3,
|
(u8)((adr | B_AX_INDIRECT_RDY) >> 24));
|
PLTFM_SDIO_CMD52_W8(R_AX_SDIO_INDIRECT_CTRL, (u8)B_AX_INDIRECT_REG_R);
|
|
cnt = SDIO_WAIT_CNT;
|
do {
|
tmp = PLTFM_SDIO_CMD52_R8(R_AX_SDIO_INDIRECT_ADDR + 3);
|
cnt--;
|
} while (((tmp & BIT(7)) == 0) && (cnt > 0));
|
|
if (((tmp & BIT(7)) == 0) && cnt == 0)
|
PLTFM_MSG_ERR("[ERR]sdio indirect CMD52 read\n");
|
|
return PLTFM_SDIO_CMD52_R8(R_AX_SDIO_INDIRECT_DATA);
|
}
|
#endif
|
static u32 get_chip_info(struct mac_ax_adapter *adapter,
|
struct mac_ax_pltfm_cb *pltfm_cb,
|
enum mac_ax_intf intf, u8 *id, u8 *cv)
|
{
|
u32 cv_temp;
|
u8 cur_id;
|
|
if (!cv || !id)
|
return MACNPTR;
|
|
switch (intf) {
|
#if MAC_AX_SDIO_SUPPORT
|
case MAC_AX_INTF_SDIO:
|
cur_id = r8_indir_cmd52_sdio(adapter, R_AX_SYS_CHIPINFO);
|
*cv = r8_indir_cmd52_sdio(adapter, R_AX_SYS_CFG1 + 1) >> 4;
|
break;
|
#endif
|
#if (MAC_AX_USB_SUPPORT || MAC_AX_PCIE_SUPPORT)
|
case MAC_AX_INTF_USB:
|
case MAC_AX_INTF_PCIE:
|
cur_id = PLTFM_REG_R8(R_AX_SYS_CHIPINFO);
|
*cv = PLTFM_REG_R8(R_AX_SYS_CFG1 + 1) >> 4;
|
|
if (cur_id == CHIP_ID_HW_DEF_8852A) {
|
if (*cv <= CBV) {
|
cv_temp = PLTFM_REG_R32(R_AX_GPIO0_7_FUNC_SEL);
|
if (cv_temp == 0xdeadbeef)
|
*cv = CAV;
|
else
|
*cv = CBV;
|
}
|
}
|
break;
|
#endif
|
default:
|
return MACINTF;
|
}
|
|
switch (cur_id) {
|
case CHIP_ID_HW_DEF_8852A:
|
*id = MAC_AX_CHIP_ID_8852A;
|
break;
|
case CHIP_ID_HW_DEF_8852B:
|
*id = MAC_AX_CHIP_ID_8852B;
|
break;
|
case CHIP_ID_HW_DEF_8852C:
|
*id = MAC_AX_CHIP_ID_8852C;
|
break;
|
default:
|
return MACCHIPID;
|
}
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_ax_ops_init_v1(void *phl_adapter, void *drv_adapter,
|
enum rtw_chip_id chip_id,
|
enum rtw_hci_type hci,
|
struct mac_ax_adapter **mac_adapter,
|
struct mac_ax_ops **mac_ops)
|
{
|
u32 ret;
|
u8 cv;
|
struct mac_ax_adapter *adapter;
|
enum mac_ax_intf intf = MAC_AX_INTF_INVALID;
|
|
if (!chk_pltfm_endian())
|
return MACPFED;
|
|
ret = 0;
|
|
if (hci == RTW_HCI_PCIE)
|
intf = MAC_AX_INTF_PCIE;
|
else if (hci == RTW_HCI_USB)
|
intf = MAC_AX_INTF_USB;
|
else if (hci == RTW_HCI_SDIO)
|
intf = MAC_AX_INTF_SDIO;
|
|
ret = get_chip_info(drv_adapter, NULL, intf, &chip_id, &cv);
|
if (ret)
|
return ret;
|
|
adapter = get_mac_ax_adapter(intf, chip_id, cv, phl_adapter,
|
drv_adapter, NULL);
|
if (!adapter) {
|
PLTFM_MSG_PRINT("[ERR]Get MAC adapter\n");
|
return MACADAPTER;
|
}
|
PLTFM_MSG_ALWAYS("MAC_AX_MAJOR_VER = %d\n"
|
"MAC_AX_PROTOTYPE_VER = %d\n"
|
"MAC_AX_SUB_VER = %d\n"
|
"MAC_AX_SUB_INDEX = %d\n",
|
MAC_AX_MAJOR_VER, MAC_AX_PROTOTYPE_VER,
|
MAC_AX_SUB_VER, MAC_AX_SUB_INDEX);
|
|
*mac_adapter = adapter;
|
*mac_ops = adapter->ops;
|
|
return MACSUCCESS;
|
}
|
|
#else
|
|
#if MAC_AX_SDIO_SUPPORT
|
static u8 r8_indir_cmd52_sdio(void *drv_adapter,
|
struct mac_ax_pltfm_cb *pltfm_cb, u32 adr)
|
{
|
u8 tmp;
|
u32 cnt;
|
|
pltfm_cb->sdio_cmd52_w8(drv_adapter, R_AX_SDIO_INDIRECT_ADDR,
|
(u8)adr);
|
pltfm_cb->sdio_cmd52_w8(drv_adapter, R_AX_SDIO_INDIRECT_ADDR + 1,
|
(u8)(adr >> 8));
|
pltfm_cb->sdio_cmd52_w8(drv_adapter, R_AX_SDIO_INDIRECT_ADDR + 2,
|
(u8)(adr >> 16));
|
pltfm_cb->sdio_cmd52_w8(drv_adapter, R_AX_SDIO_INDIRECT_ADDR + 3,
|
(u8)((adr | B_AX_INDIRECT_RDY) >> 24));
|
pltfm_cb->sdio_cmd52_w8(drv_adapter, R_AX_SDIO_INDIRECT_CTRL,
|
(u8)B_AX_INDIRECT_REG_R);
|
|
cnt = SDIO_WAIT_CNT;
|
do {
|
tmp = pltfm_cb->sdio_cmd52_r8(drv_adapter,
|
R_AX_SDIO_INDIRECT_ADDR + 3);
|
cnt--;
|
} while (((tmp & BIT(7)) == 0) && (cnt > 0));
|
|
if (((tmp & BIT(7)) == 0) && cnt == 0)
|
pltfm_cb->msg_print(drv_adapter, _PHL_ERR_,
|
"[ERR]sdio indirect CMD52 read\n");
|
|
return pltfm_cb->sdio_cmd52_r8(drv_adapter, R_AX_SDIO_INDIRECT_DATA);
|
}
|
#endif
|
static u32 get_chip_info(void *drv_adapter, struct mac_ax_pltfm_cb *pltfm_cb,
|
enum mac_ax_intf intf, u8 *id, u8 *cv)
|
{
|
u8 cur_id;
|
|
if (!cv || !id)
|
return MACNPTR;
|
|
switch (intf) {
|
#if MAC_AX_SDIO_SUPPORT
|
case MAC_AX_INTF_SDIO:
|
cur_id = r8_indir_cmd52_sdio(drv_adapter, pltfm_cb,
|
R_AX_SYS_CHIPINFO);
|
*cv = r8_indir_cmd52_sdio(drv_adapter, pltfm_cb,
|
R_AX_SYS_CFG1 + 1) >> 4;
|
if (cur_id == CHIP_ID_HW_DEF_8852A)
|
if (*cv <= CBV)
|
*cv = CBV;
|
|
break;
|
#endif
|
#if (MAC_AX_USB_SUPPORT || MAC_AX_PCIE_SUPPORT)
|
case MAC_AX_INTF_USB:
|
case MAC_AX_INTF_PCIE:
|
cur_id = pltfm_cb->reg_r8(drv_adapter, R_AX_SYS_CHIPINFO);
|
*cv = pltfm_cb->reg_r8(drv_adapter, R_AX_SYS_CFG1 + 1) >> 4;
|
if (cur_id == CHIP_ID_HW_DEF_8852A)
|
if (*cv <= CBV)
|
*cv = CBV;
|
|
break;
|
#endif
|
default:
|
return MACINTF;
|
}
|
|
switch (cur_id) {
|
case CHIP_ID_HW_DEF_8852A:
|
*id = MAC_AX_CHIP_ID_8852A;
|
break;
|
case CHIP_ID_HW_DEF_8852B:
|
*id = MAC_AX_CHIP_ID_8852B;
|
break;
|
case CHIP_ID_HW_DEF_8852C:
|
*id = MAC_AX_CHIP_ID_8852C;
|
break;
|
case CHIP_ID_HW_DEF_8192XB:
|
*id = MAC_AX_CHIP_ID_8192XB;
|
break;
|
default:
|
return MACCHIPID;
|
}
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_ax_ops_init(void *drv_adapter, struct mac_ax_pltfm_cb *pltfm_cb,
|
enum mac_ax_intf intf,
|
struct mac_ax_adapter **mac_adapter,
|
struct mac_ax_ops **mac_ops)
|
{
|
u32 ret;
|
u8 chip_id = 0;
|
u8 cv = 0;
|
struct mac_ax_adapter *adapter;
|
|
if (!chk_pltfm_cb(drv_adapter, intf, pltfm_cb))
|
return MACPFCB;
|
|
if (!chk_pltfm_endian())
|
return MACPFED;
|
|
pltfm_cb->msg_print(drv_adapter, _PHL_ERR_,
|
"MAC_AX_MAJOR_VER = %d\n"
|
"MAC_AX_PROTOTYPE_VER = %d\n"
|
"MAC_AX_SUB_VER = %d\n"
|
"MAC_AX_SUB_INDEX = %d\n",
|
MAC_AX_MAJOR_VER, MAC_AX_PROTOTYPE_VER,
|
MAC_AX_SUB_VER, MAC_AX_SUB_INDEX);
|
|
ret = get_chip_info(drv_adapter, pltfm_cb, intf, &chip_id, &cv);
|
if (ret)
|
return ret;
|
|
adapter = get_mac_ax_adapter(intf, chip_id, cv, drv_adapter,
|
pltfm_cb);
|
if (!adapter) {
|
pltfm_cb->msg_print(drv_adapter, _PHL_ERR_, "[ERR]Get MAC adapter\n");
|
return MACADAPTER;
|
}
|
|
*mac_adapter = adapter;
|
*mac_ops = adapter->ops;
|
|
#if MAC_AX_FEATURE_HV
|
adapter->hv_ops = get_hv_ax_ops(adapter);
|
#endif
|
|
#if MAC_AX_PHL_H2C
|
|
#else
|
ret = h2cb_init(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]h2cb init %d\n", ret);
|
return ret;
|
}
|
#endif
|
|
ret = role_tbl_init(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]role tbl init %d\n", ret);
|
return ret;
|
}
|
|
ret = sec_info_tbl_init(adapter, SEC_CAM_NORMAL);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]sec info tbl init %d\n", ret);
|
return ret;
|
}
|
|
ret = efuse_tbl_init(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]efuse tbl init %d\n", ret);
|
return ret;
|
}
|
|
ret = p2p_info_init(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]p2p info init %d\n", ret);
|
return ret;
|
}
|
|
ret = mport_info_init(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]mpinfo info init %d\n", ret);
|
return ret;
|
}
|
|
ret = mix_info_init(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]mix info init %d\n", ret);
|
return ret;
|
}
|
|
#if MAC_AX_SDIO_SUPPORT
|
ret = sdio_tbl_init(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]sdio tbl init %d\n", ret);
|
return ret;
|
}
|
#endif
|
|
ret = hfc_info_init(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]hfc info init %d\n", ret);
|
return ret;
|
}
|
|
ret = dbcc_info_init(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]dbcc info init %d\n", ret);
|
return ret;
|
}
|
|
return MACSUCCESS;
|
}
|
#endif /*CONFIG_NEW_HALMAC_INTERFACE*/
|
|
#if MAC_AX_PHL_H2C
|
u32 mac_ax_phl_init(void *phl_adapter, struct mac_ax_adapter *mac_adapter)
|
{
|
struct mac_ax_adapter *adapter = mac_adapter;
|
|
adapter->phl_adapter = phl_adapter;
|
|
return MACSUCCESS;
|
}
|
#endif
|
u32 mac_ax_ops_exit(struct mac_ax_adapter *adapter)
|
{
|
u32 ret;
|
struct mac_ax_efuse_param *efuse_param = &adapter->efuse_param;
|
struct scan_chinfo_list *scan_list;
|
|
ret = h2cb_exit(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]h2c buffer exit %d\n", ret);
|
return ret;
|
}
|
|
ret = free_sec_info_tbl(adapter, SEC_CAM_NORMAL);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]sec table exit %d\n", ret);
|
return ret;
|
}
|
|
ret = role_tbl_exit(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]role table exit %d\n", ret);
|
return ret;
|
}
|
|
ret = efuse_tbl_exit(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]efuse table exit %d\n", ret);
|
return ret;
|
}
|
|
ret = p2p_info_exit(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]p2p info exit %d\n", ret);
|
return ret;
|
}
|
|
ret = mport_info_exit(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]mpinfo info exit %d\n", ret);
|
return ret;
|
}
|
|
ret = mix_info_exit(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]mix info exit %d\n", ret);
|
return ret;
|
}
|
|
#if MAC_AX_SDIO_SUPPORT
|
ret = sdio_tbl_exit(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]efuse table exit %d\n", ret);
|
return ret;
|
}
|
#endif
|
|
ret = hfc_info_exit(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]hfc info exit %d\n", ret);
|
return ret;
|
}
|
|
ret = free_aoac_report(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]free aoac report %d\n", ret);
|
return ret;
|
}
|
|
ret = dbcc_info_exit(adapter);
|
if (ret != MACSUCCESS) {
|
PLTFM_MSG_ERR("[ERR]dbcc info exit %d\n", ret);
|
return ret;
|
}
|
|
if (efuse_param->efuse_map) {
|
PLTFM_FREE(efuse_param->efuse_map,
|
adapter->hw_info->efuse_size);
|
efuse_param->efuse_map = (u8 *)NULL;
|
}
|
|
if (efuse_param->bt_efuse_map) {
|
PLTFM_FREE(efuse_param->bt_efuse_map,
|
adapter->hw_info->bt_efuse_size);
|
efuse_param->bt_efuse_map = (u8 *)NULL;
|
}
|
|
if (efuse_param->log_efuse_map) {
|
PLTFM_FREE(efuse_param->log_efuse_map,
|
adapter->hw_info->log_efuse_size);
|
efuse_param->log_efuse_map = (u8 *)NULL;
|
}
|
|
if (efuse_param->bt_log_efuse_map) {
|
PLTFM_FREE(efuse_param->bt_log_efuse_map,
|
adapter->hw_info->bt_log_efuse_size);
|
efuse_param->bt_log_efuse_map = (u8 *)NULL;
|
}
|
|
if (efuse_param->dav_efuse_map) {
|
PLTFM_FREE(efuse_param->dav_efuse_map,
|
adapter->hw_info->dav_efuse_size);
|
efuse_param->dav_efuse_map = (u8 *)NULL;
|
}
|
|
if (efuse_param->dav_log_efuse_map) {
|
PLTFM_FREE(efuse_param->dav_log_efuse_map,
|
adapter->hw_info->dav_log_efuse_size);
|
efuse_param->dav_log_efuse_map = (u8 *)NULL;
|
}
|
|
scan_list = adapter->scanofld_info.list;
|
if (scan_list) {
|
mac_scanofld_ch_list_clear(adapter, scan_list);
|
PLTFM_FREE((u8 *)scan_list, sizeof(struct scan_chinfo_list));
|
adapter->scanofld_info.list = NULL;
|
}
|
|
PLTFM_FREE(adapter->hw_info, sizeof(struct mac_ax_hw_info));
|
|
PLTFM_FREE(adapter, sizeof(struct mac_ax_adapter));
|
return MACSUCCESS;
|
}
|
|
u32 is_chip_id(struct mac_ax_adapter *adapter, enum mac_ax_chip_id id)
|
{
|
return (id == adapter->hw_info->chip_id ? 1 : 0);
|
}
|
|
u32 is_cv(struct mac_ax_adapter *adapter, enum rtw_cv cv)
|
{
|
return (cv == adapter->hw_info->cv ? 1 : 0);
|
}
|