/******************************************************************************
|
*
|
* Copyright(c) 2017 - 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_pcie_8822c.h"
|
#include "halmac_pwr_seq_8822c.h"
|
#include "../halmac_init_88xx.h"
|
#include "../halmac_common_88xx.h"
|
#include "../halmac_pcie_88xx.h"
|
#include "../halmac_88xx_cfg.h"
|
|
#if (HALMAC_8822C_SUPPORT && HALMAC_PCIE_SUPPORT)
|
|
/**
|
* mac_pwr_switch_pcie_8822c() - switch mac power
|
* @adapter : the adapter of halmac
|
* @pwr : power state
|
* Author : KaiYuan Chang
|
* Return : enum halmac_ret_status
|
* More details of status code can be found in prototype document
|
*/
|
|
#define INTF_INTGRA_MINREF_V1 90
|
#define INTF_INTGRA_HOSTREF_V1 100
|
|
static struct halmac_pcie_cfgspc_param pcie_cfgspc_param_def = {
|
0,
|
0,
|
HALMAC_DISABLE,
|
HALMAC_ENABLE,
|
HALMAC_ENABLE,
|
HALMAC_ENABLE,
|
HALMAC_IGNORE,
|
HALMAC_CLKDLY_0,
|
HALMAC_L0SDLY_7US,
|
HALMAC_L1DLY_16US,
|
};
|
|
enum pcie_clkdly_hw {
|
PCIE_CLKDLY_HW_0 = 0,
|
PCIE_CLKDLY_HW_30US = 0x1,
|
PCIE_CLKDLY_HW_50US = 0x2,
|
PCIE_CLKDLY_HW_100US = 0x3,
|
PCIE_CLKDLY_HW_150US = 0x4,
|
PCIE_CLKDLY_HW_200US = 0x5
|
};
|
|
enum pcie_l1dly_hw {
|
PCIE_L1DLY_HW_16US = 4,
|
PCIE_L1DLY_HW_32US = 5,
|
PCIE_L1DLY_HW_64US = 6,
|
PCIE_L1DLY_HW_INFI = 7
|
};
|
|
enum pcie_l0sdly_hw {
|
PCIE_L0SDLY_HW_1US = 0,
|
PCIE_L0SDLY_HW_3US = 2,
|
PCIE_L0SDLY_HW_5US = 4,
|
PCIE_L0SDLY_HW_7US = 6
|
};
|
|
#define GET_PCIE_FUNC_STUS(val, mask) \
|
((val & mask) ? HALMAC_ENABLE : HALMAC_DISABLE)
|
|
static u16
|
get_target(struct halmac_adapter *adapter);
|
|
static enum halmac_ret_status
|
pcie_cfgspc_write_8822c(struct halmac_adapter *adapter,
|
struct halmac_pcie_cfgspc_param *param);
|
|
static enum halmac_ret_status
|
pcie_cfgspc_read_8822c(struct halmac_adapter *adapter,
|
struct halmac_pcie_cfgspc_param *param);
|
|
static void
|
update_pcie_func_8822c(u8 *val, u8 bitmask, enum halmac_func_ctrl ctrl,
|
enum halmac_func_ctrl def_ctrl);
|
|
static u8
|
chk_stus_l1ss_8822c(struct halmac_adapter *adapter);
|
|
static enum halmac_ret_status
|
update_clkdly_8822c(struct halmac_adapter *adapter, u8 *val,
|
enum halmac_pcie_clkdly ctrl,
|
enum halmac_pcie_clkdly def_ctrl);
|
|
static enum halmac_ret_status
|
update_pcie_clk_8822c(struct halmac_adapter *adapter, u8 *val);
|
|
static enum halmac_ret_status
|
update_aspmdly_8822c(struct halmac_adapter *adapter, u8 *val,
|
struct halmac_pcie_cfgspc_param *param,
|
struct halmac_pcie_cfgspc_param *param_def);
|
|
enum halmac_ret_status
|
mac_pwr_switch_pcie_8822c(struct halmac_adapter *adapter,
|
enum halmac_mac_power pwr)
|
{
|
u8 value8;
|
u8 rpwm;
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
PLTFM_MSG_TRACE("[TRACE]pwr = %x\n", pwr);
|
PLTFM_MSG_TRACE("[TRACE]8822C pwr seq ver = %s\n",
|
HALMAC_8822C_PWR_SEQ_VER);
|
|
adapter->rpwm = HALMAC_REG_R8(REG_PCIE_HRPWM1_V1);
|
|
/* Check FW still exist or not */
|
if (HALMAC_REG_R16(REG_MCUFW_CTRL) == 0xC078) {
|
/* Leave 32K */
|
rpwm = (u8)((adapter->rpwm ^ BIT(7)) & 0x80);
|
HALMAC_REG_W8(REG_PCIE_HRPWM1_V1, rpwm);
|
}
|
|
value8 = HALMAC_REG_R8(REG_CR);
|
if (value8 == 0xEA)
|
adapter->halmac_state.mac_pwr = HALMAC_MAC_POWER_OFF;
|
else
|
adapter->halmac_state.mac_pwr = HALMAC_MAC_POWER_ON;
|
|
/* Check if power switch is needed */
|
if (pwr == HALMAC_MAC_POWER_ON &&
|
adapter->halmac_state.mac_pwr == HALMAC_MAC_POWER_ON) {
|
PLTFM_MSG_WARN("[WARN]power state unchange!!\n");
|
return HALMAC_RET_PWR_UNCHANGE;
|
}
|
|
if (pwr == HALMAC_MAC_POWER_OFF) {
|
if (pwr_seq_parser_88xx(adapter, card_dis_flow_8822c) !=
|
HALMAC_RET_SUCCESS) {
|
PLTFM_MSG_ERR("[ERR]Handle power off cmd error\n");
|
return HALMAC_RET_POWER_OFF_FAIL;
|
}
|
|
adapter->halmac_state.mac_pwr = HALMAC_MAC_POWER_OFF;
|
adapter->halmac_state.dlfw_state = HALMAC_DLFW_NONE;
|
init_adapter_dynamic_param_88xx(adapter);
|
} else {
|
if (pwr_seq_parser_88xx(adapter, card_en_flow_8822c) !=
|
HALMAC_RET_SUCCESS) {
|
PLTFM_MSG_ERR("[ERR]Handle power on cmd error\n");
|
return HALMAC_RET_POWER_ON_FAIL;
|
}
|
|
adapter->halmac_state.mac_pwr = HALMAC_MAC_POWER_ON;
|
}
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
return HALMAC_RET_SUCCESS;
|
}
|
|
/**
|
* halmac_pcie_switch_8822c() - pcie gen1/gen2 switch
|
* @adapter : the adapter of halmac
|
* @cfg : gen1/gen2 selection
|
* Author : KaiYuan Chang
|
* Return : enum halmac_ret_status
|
* More details of status code can be found in prototype document
|
*/
|
enum halmac_ret_status
|
pcie_switch_8822c(struct halmac_adapter *adapter, enum halmac_pcie_cfg cfg)
|
{
|
u8 value8;
|
u32 value32;
|
u8 speed = 0;
|
u32 cnt = 0;
|
enum halmac_ret_status status;
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
if (cfg == HALMAC_PCIE_GEN1) {
|
value8 = dbi_r8_88xx(adapter, LINK_CTRL2_REG_OFFSET) & 0xF0;
|
status = dbi_w8_88xx(adapter, LINK_CTRL2_REG_OFFSET,
|
value8 | BIT(0));
|
if (status != HALMAC_RET_SUCCESS) {
|
PLTFM_MSG_ERR("[ERR]DBI write 8 bits fail!\n");
|
return status;
|
}
|
|
value32 = dbi_r32_88xx(adapter, GEN2_CTRL_OFFSET);
|
status = dbi_w32_88xx(adapter, GEN2_CTRL_OFFSET,
|
value32 | BIT(17));
|
if (status != HALMAC_RET_SUCCESS) {
|
PLTFM_MSG_ERR("[ERR]DBI write 32 bits fail!\n");
|
return status;
|
}
|
|
speed = dbi_r8_88xx(adapter, LINK_STATUS_REG_OFFSET) & 0x0F;
|
cnt = 2000;
|
|
while ((speed != PCIE_GEN1_SPEED) && (cnt != 0)) {
|
PLTFM_DELAY_US(50);
|
speed = dbi_r8_88xx(adapter, LINK_STATUS_REG_OFFSET);
|
speed &= 0x0F;
|
cnt--;
|
}
|
|
if (speed != PCIE_GEN1_SPEED) {
|
PLTFM_MSG_ERR("[ERR]Speed change to GEN1 fail !\n");
|
return HALMAC_RET_FAIL;
|
}
|
|
} else if (cfg == HALMAC_PCIE_GEN2) {
|
value8 = dbi_r8_88xx(adapter, LINK_CTRL2_REG_OFFSET) & 0xF0;
|
status = dbi_w8_88xx(adapter, LINK_CTRL2_REG_OFFSET,
|
value8 | BIT(1));
|
if (status != HALMAC_RET_SUCCESS) {
|
PLTFM_MSG_ERR("[ERR]DBI write 8 bits fail!\n");
|
return status;
|
}
|
|
value32 = dbi_r32_88xx(adapter, GEN2_CTRL_OFFSET);
|
status = dbi_w32_88xx(adapter, GEN2_CTRL_OFFSET,
|
value32 | BIT(17));
|
if (status != HALMAC_RET_SUCCESS) {
|
PLTFM_MSG_ERR("[ERR]DBI write 32 bits fail!\n");
|
return status;
|
}
|
|
speed = dbi_r8_88xx(adapter, LINK_STATUS_REG_OFFSET) & 0x0F;
|
cnt = 2000;
|
|
while ((speed != PCIE_GEN2_SPEED) && (cnt != 0)) {
|
PLTFM_DELAY_US(50);
|
speed = dbi_r8_88xx(adapter, LINK_STATUS_REG_OFFSET);
|
speed &= 0x0F;
|
cnt--;
|
}
|
|
if (speed != PCIE_GEN2_SPEED) {
|
PLTFM_MSG_ERR("[ERR]Speed change to GEN1 fail !\n");
|
return HALMAC_RET_FAIL;
|
}
|
|
} else {
|
PLTFM_MSG_ERR("[ERR]Error Speed !\n");
|
return HALMAC_RET_FAIL;
|
}
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
return HALMAC_RET_SUCCESS;
|
}
|
|
/**
|
* phy_cfg_pcie_8822c() - phy config
|
* @adapter : the adapter of halmac
|
* Author : KaiYuan Chang
|
* Return : enum halmac_ret_status
|
* More details of status code can be found in prototype document
|
*/
|
enum halmac_ret_status
|
phy_cfg_pcie_8822c(struct halmac_adapter *adapter,
|
enum halmac_intf_phy_platform pltfm)
|
{
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
status = parse_intf_phy_88xx(adapter, pcie_gen1_phy_param_8822c, pltfm,
|
HAL_INTF_PHY_PCIE_GEN1);
|
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
|
status = parse_intf_phy_88xx(adapter, pcie_gen2_phy_param_8822c, pltfm,
|
HAL_INTF_PHY_PCIE_GEN2);
|
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
return HALMAC_RET_SUCCESS;
|
}
|
|
/**
|
* intf_tun_pcie_8822c() - pcie interface fine tuning
|
* @adapter : the adapter of halmac
|
* Author : Rick Liu
|
* Return : enum halmac_ret_status
|
* More details of status code can be found in prototype document
|
*/
|
enum halmac_ret_status
|
intf_tun_pcie_8822c(struct halmac_adapter *adapter)
|
{
|
return HALMAC_RET_SUCCESS;
|
}
|
|
/**
|
* cfgspc_set_pcie_8822c() - pcie configuration space setting
|
* @adapter : the adapter of halmac
|
* Author : Rick Liu
|
* Return : enum halmac_ret_status
|
* More details of status code can be found in prototype document
|
*/
|
enum halmac_ret_status
|
cfgspc_set_pcie_8822c(struct halmac_adapter *adapter,
|
struct halmac_pcie_cfgspc_param *param)
|
{
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
if (param->write == 1)
|
status = pcie_cfgspc_write_8822c(adapter, param);
|
|
if (param->read == 1)
|
status = pcie_cfgspc_read_8822c(adapter, param);
|
|
return status;
|
}
|
|
static enum halmac_ret_status
|
pcie_cfgspc_write_8822c(struct halmac_adapter *adapter,
|
struct halmac_pcie_cfgspc_param *param)
|
{
|
u8 l1_val;
|
u8 aspm_val;
|
u8 l1ss_val;
|
u8 clk_val;
|
struct halmac_pcie_cfgspc_param *param_def = &pcie_cfgspc_param_def;
|
enum halmac_ret_status status;
|
|
l1_val = dbi_r8_88xx(adapter, PCIE_L1_CTRL);
|
aspm_val = dbi_r8_88xx(adapter, PCIE_ASPM_CTRL);
|
l1ss_val = dbi_r8_88xx(adapter, PCIE_L1SS_CTRL);
|
clk_val = dbi_r8_88xx(adapter, PCIE_CLK_CTRL);
|
if (l1_val == 0xFF || aspm_val == 0xFF || l1ss_val == 0xFF ||
|
clk_val == 0xFF) {
|
PLTFM_MSG_ERR("[ERR] PCIE CFG reg read 0xFF!\n");
|
return HALMAC_RET_FAIL;
|
}
|
|
update_pcie_func_8822c(&aspm_val, PCIE_BIT_L0S,
|
param->l0s_ctrl, param_def->l0s_ctrl);
|
|
status = update_pcie_clk_8822c(adapter, &l1_val);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
|
update_pcie_func_8822c(&l1_val, PCIE_BIT_L1,
|
param->l1_ctrl, param_def->l1_ctrl);
|
update_pcie_func_8822c(&l1_val, PCIE_BIT_WAKE,
|
param->wake_ctrl, param_def->wake_ctrl);
|
if (chk_stus_l1ss_8822c(adapter) == 1)
|
update_pcie_func_8822c(&l1ss_val, PCIE_BIT_L1SS,
|
param->l1ss_ctrl, param_def->l1ss_ctrl);
|
status = update_clkdly_8822c(adapter, &clk_val,
|
param->clkdly_ctrl,
|
param_def->clkdly_ctrl);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
|
status = update_aspmdly_8822c(adapter, &aspm_val, param, param_def);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
|
if (param->l0s_ctrl != HALMAC_IGNORE ||
|
param->l1dly_ctrl != HALMAC_L1DLY_IGNORE ||
|
param->l0sdly_ctrl != HALMAC_L0SDLY_IGNORE) {
|
status = dbi_w8_88xx(adapter, PCIE_ASPM_CTRL, aspm_val);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
}
|
if (param->l1_ctrl != HALMAC_IGNORE ||
|
param->wake_ctrl != HALMAC_IGNORE) {
|
status = dbi_w8_88xx(adapter, PCIE_L1_CTRL, l1_val);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
}
|
if (param->l1ss_ctrl != HALMAC_IGNORE) {
|
status = dbi_w8_88xx(adapter, PCIE_L1SS_CTRL, l1ss_val);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
}
|
if (param->clkdly_ctrl != HALMAC_CLKDLY_IGNORE) {
|
status = dbi_w8_88xx(adapter, PCIE_CLK_CTRL, clk_val);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
}
|
|
return HALMAC_RET_SUCCESS;
|
}
|
|
static enum halmac_ret_status
|
pcie_cfgspc_read_8822c(struct halmac_adapter *adapter,
|
struct halmac_pcie_cfgspc_param *param)
|
{
|
u8 l1_val;
|
u8 aspm_val;
|
u8 l1ss_val;
|
u8 clk_val;
|
u8 l0smask;
|
u8 l1mask;
|
|
l1_val = dbi_r8_88xx(adapter, PCIE_L1_CTRL);
|
aspm_val = dbi_r8_88xx(adapter, PCIE_ASPM_CTRL);
|
l1ss_val = dbi_r8_88xx(adapter, PCIE_L1SS_CTRL);
|
clk_val = dbi_r8_88xx(adapter, PCIE_CLK_CTRL);
|
if (l1_val == 0xFF || aspm_val == 0xFF ||
|
l1ss_val == 0xFF || clk_val == 0xFF) {
|
PLTFM_MSG_ERR("[ERR] (2nd)PCIE CFG reg read 0xFF!\n");
|
return HALMAC_RET_FAIL;
|
}
|
|
param->l0s_ctrl = GET_PCIE_FUNC_STUS(aspm_val, PCIE_BIT_L0S);
|
param->l1_ctrl = GET_PCIE_FUNC_STUS(l1_val, PCIE_BIT_L1);
|
param->l1ss_ctrl = GET_PCIE_FUNC_STUS(l1ss_val, PCIE_BIT_L1SS);
|
param->wake_ctrl = GET_PCIE_FUNC_STUS(l1_val, PCIE_BIT_WAKE);
|
param->crq_ctrl = GET_PCIE_FUNC_STUS(l1_val, PCIE_BIT_CLK);
|
|
switch (clk_val) {
|
case PCIE_CLKDLY_HW_0:
|
param->clkdly_ctrl = HALMAC_CLKDLY_0;
|
break;
|
|
case PCIE_CLKDLY_HW_30US:
|
param->clkdly_ctrl = HALMAC_CLKDLY_30US;
|
break;
|
|
case PCIE_CLKDLY_HW_50US:
|
param->clkdly_ctrl = HALMAC_CLKDLY_50US;
|
break;
|
|
case PCIE_CLKDLY_HW_100US:
|
param->clkdly_ctrl = HALMAC_CLKDLY_100US;
|
break;
|
|
case PCIE_CLKDLY_HW_150US:
|
param->clkdly_ctrl = HALMAC_CLKDLY_150US;
|
break;
|
|
case PCIE_CLKDLY_HW_200US:
|
param->clkdly_ctrl = HALMAC_CLKDLY_200US;
|
break;
|
|
default:
|
param->clkdly_ctrl = HALMAC_CLKDLY_R_ERR;
|
break;
|
}
|
|
l0smask = PCIE_ASPMDLY_MASK << SHFT_L0SDLY;
|
l1mask = PCIE_ASPMDLY_MASK << SHFT_L1DLY;
|
|
switch ((aspm_val & l0smask) >> SHFT_L0SDLY) {
|
case PCIE_L0SDLY_HW_1US:
|
param->l0sdly_ctrl = HALMAC_L0SDLY_1US;
|
break;
|
|
case PCIE_L0SDLY_HW_3US:
|
param->l0sdly_ctrl = HALMAC_L0SDLY_3US;
|
break;
|
|
case PCIE_L0SDLY_HW_5US:
|
param->l0sdly_ctrl = HALMAC_L0SDLY_5US;
|
break;
|
|
case PCIE_L0SDLY_HW_7US:
|
param->l0sdly_ctrl = HALMAC_L0SDLY_7US;
|
break;
|
|
default:
|
param->l0sdly_ctrl = HALMAC_L0SDLY_R_ERR;
|
break;
|
}
|
|
switch ((aspm_val & l1mask) >> SHFT_L1DLY) {
|
case PCIE_L1DLY_HW_16US:
|
param->l1dly_ctrl = HALMAC_L1DLY_16US;
|
break;
|
|
case PCIE_L1DLY_HW_32US:
|
param->l1dly_ctrl = HALMAC_L1DLY_32US;
|
break;
|
|
case PCIE_L1DLY_HW_64US:
|
param->l1dly_ctrl = HALMAC_L1DLY_64US;
|
break;
|
|
case PCIE_L1DLY_HW_INFI:
|
param->l1dly_ctrl = HALMAC_L1DLY_INFI;
|
break;
|
|
default:
|
param->l1dly_ctrl = HALMAC_L1DLY_R_ERR;
|
break;
|
}
|
|
return HALMAC_RET_SUCCESS;
|
}
|
|
static void
|
update_pcie_func_8822c(u8 *val, u8 bitmask, enum halmac_func_ctrl ctrl,
|
enum halmac_func_ctrl def_ctrl)
|
{
|
if ((ctrl == HALMAC_DEFAULT &&
|
(def_ctrl == HALMAC_IGNORE || def_ctrl == HALMAC_DEFAULT)) ||
|
ctrl == HALMAC_IGNORE)
|
return;
|
|
if ((ctrl == HALMAC_DEFAULT && def_ctrl == HALMAC_DISABLE) ||
|
ctrl == HALMAC_DISABLE)
|
*val &= ~(bitmask);
|
else
|
*val |= bitmask;
|
}
|
|
static u8
|
chk_stus_l1ss_8822c(struct halmac_adapter *adapter)
|
{
|
u16 cap_val;
|
u8 stus_val;
|
u8 sup_val;
|
|
cap_val = (u16)((dbi_r8_88xx(adapter, PCIE_L1SS_CAP + 1) << 8) |
|
dbi_r8_88xx(adapter, PCIE_L1SS_CAP));
|
sup_val = dbi_r8_88xx(adapter, PCIE_L1SS_SUP);
|
stus_val = dbi_r8_88xx(adapter, PCIE_L1SS_STS);
|
|
if (cap_val == PCIE_L1SS_ID &&
|
(sup_val & PCIE_BIT_L1SSSUP) &&
|
(sup_val & PCIE_L1SS_MASK) != 0 &&
|
(stus_val & PCIE_L1SS_MASK) != 0)
|
return 1;
|
|
return 0;
|
}
|
|
static enum halmac_ret_status
|
update_clkdly_8822c(struct halmac_adapter *adapter, u8 *val,
|
enum halmac_pcie_clkdly ctrl,
|
enum halmac_pcie_clkdly def_ctrl)
|
{
|
u8 tmp;
|
|
if (ctrl == HALMAC_CLKDLY_IGNORE)
|
return HALMAC_RET_SUCCESS;
|
|
tmp = (ctrl == HALMAC_CLKDLY_DEF) ? def_ctrl : ctrl;
|
switch (tmp) {
|
case HALMAC_CLKDLY_0:
|
*val = PCIE_CLKDLY_HW_0;
|
break;
|
|
case HALMAC_CLKDLY_30US:
|
*val = PCIE_CLKDLY_HW_30US;
|
break;
|
|
case HALMAC_CLKDLY_50US:
|
*val = PCIE_CLKDLY_HW_50US;
|
break;
|
|
case HALMAC_CLKDLY_100US:
|
*val = PCIE_CLKDLY_HW_100US;
|
break;
|
|
case HALMAC_CLKDLY_150US:
|
*val = PCIE_CLKDLY_HW_150US;
|
break;
|
|
case HALMAC_CLKDLY_200US:
|
*val = PCIE_CLKDLY_HW_200US;
|
break;
|
|
default:
|
PLTFM_MSG_ERR("[ERR]CLKDLY wt val illegal!\n");
|
return HALMAC_RET_FAIL;
|
}
|
return HALMAC_RET_SUCCESS;
|
}
|
|
static enum halmac_ret_status
|
update_pcie_clk_8822c(struct halmac_adapter *adapter, u8 *val)
|
{
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
if (*val & PCIE_BIT_CLK)
|
return HALMAC_RET_SUCCESS;
|
|
if (*val & PCIE_BIT_L1) {
|
*val &= ~(PCIE_BIT_L1);
|
status = dbi_w8_88xx(adapter, PCIE_L1_CTRL, *val);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
*val |= PCIE_BIT_CLK;
|
status = dbi_w8_88xx(adapter, PCIE_L1_CTRL, *val);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
*val |= PCIE_BIT_L1;
|
status = dbi_w8_88xx(adapter, PCIE_L1_CTRL, *val);
|
PLTFM_MSG_WARN("[WARN] L1 enable & CLKREQ disable!\n");
|
} else {
|
*val |= PCIE_BIT_CLK;
|
status = dbi_w8_88xx(adapter, PCIE_L1_CTRL, *val);
|
}
|
|
return status;
|
}
|
|
static enum halmac_ret_status
|
update_aspmdly_8822c(struct halmac_adapter *adapter, u8 *val,
|
struct halmac_pcie_cfgspc_param *param,
|
struct halmac_pcie_cfgspc_param *param_def)
|
{
|
u8 l1mask = PCIE_ASPMDLY_MASK << SHFT_L1DLY;
|
u8 l0smask = PCIE_ASPMDLY_MASK << SHFT_L0SDLY;
|
u8 l1updval = param->l1dly_ctrl;
|
u8 l0supdval = param->l0sdly_ctrl;
|
u8 l1defval = param_def->l1dly_ctrl;
|
u8 l0sdefval = param_def->l0sdly_ctrl;
|
u8 tmp;
|
u8 hwval;
|
|
if (l1updval != HALMAC_L1DLY_IGNORE) {
|
tmp = (l1updval == HALMAC_L1DLY_DEF) ? l1defval : l1updval;
|
switch (tmp) {
|
case HALMAC_L1DLY_16US:
|
hwval = PCIE_L1DLY_HW_16US;
|
break;
|
|
case HALMAC_L1DLY_32US:
|
hwval = PCIE_L1DLY_HW_32US;
|
break;
|
|
case HALMAC_L1DLY_64US:
|
hwval = PCIE_L1DLY_HW_64US;
|
break;
|
|
case HALMAC_L1DLY_INFI:
|
hwval = PCIE_L1DLY_HW_INFI;
|
break;
|
|
default:
|
PLTFM_MSG_ERR("[ERR]L1DLY wt val illegal!\n");
|
return HALMAC_RET_FAIL;
|
}
|
|
tmp = (hwval << SHFT_L1DLY) & l1mask;
|
*val = (*val & ~(l1mask)) | tmp;
|
}
|
|
if (l0supdval != HALMAC_L0SDLY_IGNORE) {
|
tmp = (l0supdval == HALMAC_L0SDLY_DEF) ? l0sdefval : l0supdval;
|
switch (tmp) {
|
case HALMAC_L0SDLY_1US:
|
hwval = PCIE_L0SDLY_HW_1US;
|
break;
|
|
case HALMAC_L0SDLY_3US:
|
hwval = PCIE_L0SDLY_HW_3US;
|
break;
|
|
case HALMAC_L0SDLY_5US:
|
hwval = PCIE_L0SDLY_HW_5US;
|
break;
|
|
case HALMAC_L0SDLY_7US:
|
hwval = PCIE_L0SDLY_HW_7US;
|
break;
|
|
default:
|
PLTFM_MSG_ERR("[ERR]L0SDLY wt val illegal!\n");
|
return HALMAC_RET_FAIL;
|
}
|
tmp = (hwval << SHFT_L0SDLY) & l0smask;
|
*val = (*val & ~(l0smask)) | tmp;
|
}
|
|
return HALMAC_RET_SUCCESS;
|
}
|
|
enum halmac_ret_status
|
auto_refclk_cal_8822c_pcie(struct halmac_adapter *adapter)
|
{
|
u8 bdr_ori;
|
u16 tmp_u16;
|
u16 div_set;
|
u16 mgn_tmp;
|
u16 mgn_set;
|
u16 tar;
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
u8 l1_flag = 0;
|
|
#if (INTF_INTGRA_HOSTREF_V1 <= INTF_INTGRA_MINREF_V1)
|
return status;
|
#endif
|
/* Disable L1BD */
|
bdr_ori = dbi_r8_88xx(adapter, PCIE_L1_CTRL);
|
if (bdr_ori & PCIE_BIT_L1) {
|
status = dbi_w8_88xx(adapter, PCIE_L1_CTRL,
|
bdr_ori & ~(PCIE_BIT_L1));
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
l1_flag = 1;
|
}
|
|
/* Disable function */
|
tmp_u16 = mdio_read_88xx(adapter, RAC_CTRL_PPR_V1,
|
HAL_INTF_PHY_PCIE_GEN1);
|
if (tmp_u16 & BIT(13)) {
|
status = mdio_write_88xx(adapter, RAC_CTRL_PPR_V1,
|
tmp_u16 & ~(BIT(13)),
|
HAL_INTF_PHY_PCIE_GEN1);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
}
|
if (adapter->pcie_refautok_en == 0) {
|
if (l1_flag == 1)
|
status = dbi_w8_88xx(adapter, PCIE_L1_CTRL, bdr_ori);
|
return status;
|
}
|
|
/* Set div */
|
tmp_u16 = mdio_read_88xx(adapter, RAC_CTRL_PPR_V1
|
, HAL_INTF_PHY_PCIE_GEN1);
|
status = mdio_write_88xx(adapter, RAC_CTRL_PPR_V1,
|
tmp_u16 & ~(BIT(15) | BIT(14)),
|
HAL_INTF_PHY_PCIE_GEN1);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
|
/* Obtain div and margin */
|
tar = get_target(adapter);
|
if (tar == 0xFFFF)
|
return HALMAC_RET_FAIL;
|
mgn_tmp = tar * INTF_INTGRA_HOSTREF_V1 / INTF_INTGRA_MINREF_V1 - tar;
|
|
if (mgn_tmp >= 128) {
|
div_set = 0x0003;
|
mgn_set = 0x000F;
|
} else if (mgn_tmp >= 64) {
|
div_set = 0x0003;
|
mgn_set = mgn_tmp >> 3;
|
} else if (mgn_tmp >= 32) {
|
div_set = 0x0002;
|
mgn_set = mgn_tmp >> 2;
|
} else if (mgn_tmp >= 16) {
|
div_set = 0x0001;
|
mgn_set = mgn_tmp >> 1;
|
} else if (mgn_tmp == 0) {
|
div_set = 0x0000;
|
mgn_set = 0x0001;
|
} else {
|
div_set = 0x0000;
|
mgn_set = mgn_tmp;
|
}
|
|
/* Set div, margin, target*/
|
tmp_u16 = mdio_read_88xx(adapter, RAC_CTRL_PPR_V1,
|
HAL_INTF_PHY_PCIE_GEN1);
|
tmp_u16 = (tmp_u16 & ~(BIT(15) | BIT(14))) | (div_set << 14);
|
status = mdio_write_88xx(adapter, RAC_CTRL_PPR_V1,
|
tmp_u16, HAL_INTF_PHY_PCIE_GEN1);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
tar = get_target(adapter);
|
if (tar == 0xFFFF)
|
return HALMAC_RET_FAIL;
|
PLTFM_MSG_TRACE("[TRACE]target = 0x%X, div = 0x%X, margin = 0x%X\n",
|
tar, div_set, mgn_set);
|
status = mdio_write_88xx(adapter, RAC_SET_PPR_V1,
|
(tar & 0x0FFF) | (mgn_set << 12),
|
HAL_INTF_PHY_PCIE_GEN1);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
|
/* Enable function */
|
tmp_u16 = mdio_read_88xx(adapter, RAC_CTRL_PPR_V1,
|
HAL_INTF_PHY_PCIE_GEN1);
|
status = mdio_write_88xx(adapter, RAC_CTRL_PPR_V1, tmp_u16 | BIT(13),
|
HAL_INTF_PHY_PCIE_GEN1);
|
if (status != HALMAC_RET_SUCCESS)
|
return status;
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
/* Set L1BD to ori */
|
if (l1_flag == 1)
|
status = dbi_w8_88xx(adapter, PCIE_L1_CTRL, bdr_ori);
|
|
return status;
|
}
|
|
static u16
|
get_target(struct halmac_adapter *adapter)
|
{
|
u16 tmp_u16;
|
u16 tar;
|
u16 count;
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
/* Enable counter */
|
tmp_u16 = mdio_read_88xx(adapter, RAC_CTRL_PPR_V1,
|
HAL_INTF_PHY_PCIE_GEN1);
|
status = mdio_write_88xx(adapter, RAC_CTRL_PPR_V1,
|
tmp_u16 | BIT(12), HAL_INTF_PHY_PCIE_GEN1);
|
if (status != HALMAC_RET_SUCCESS)
|
return 0xFFFF;
|
|
/* Obtain target */
|
count = 0;
|
do {
|
PLTFM_DELAY_US(10);
|
tmp_u16 = mdio_read_88xx(adapter, RAC_CTRL_PPR_V1,
|
HAL_INTF_PHY_PCIE_GEN1);
|
count++;
|
if (count > 100)
|
break;
|
} while ((tmp_u16 & BIT(12)) == BIT(12));
|
if (count > 100) {
|
PLTFM_MSG_ERR("[ERR]Get target timeout.\n");
|
return 0xFFFF;
|
}
|
tar = mdio_read_88xx(adapter, RAC_CTRL_PPR_V1, HAL_INTF_PHY_PCIE_GEN1);
|
tar = tar & 0x0FFF;
|
if (tar == 0) {
|
PLTFM_MSG_ERR("[ERR]Get target failed.\n");
|
return 0xFFFF;
|
}
|
return tar;
|
}
|
|
#endif /* HALMAC_8822C_SUPPORT*/
|