You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

720 lines
19 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2014-2021. All rights reserved.
* Description: ci hal func impl.
* Author: Hisilicon
* Create: 2014-08-02
*/
#include "soc_log.h"
#include "drv_gpio_ext.h"
#include "hal_ci.h"
#include "hal_ci_reg.h"
#include "osal_ext.h"
#include "soc_errno.h"
#include "drv_ci.h"
#include "linux/huanglong/securec.h"
#undef LOG_MODULE_ID
#define LOG_MODULE_ID SOC_ID_CI
#define CI_TIME_10MS 10 /* 10ms */
#define CI_PCCD_READY_COUNT 5
#define CI_PCCD_DETECT_MAX 5
#define CI_PCCD_DETECT_MIN 3
#define CI_PCCD_RESUME_ABSENT_COUNT 10
#define DAIE 0x80
#define FRIE 0x40
#define COM_STAT_REG 1
typedef enum {
CMD_TYPE_IOW = 0,
CMD_TYPE_IOR,
CMD_TYPE_MW,
CMD_TYPE_MR,
} cmd_type_list;
typedef enum {
EXT_CI_PCCD_RUN_STEP_RESUME,
EXT_CI_PCCD_RUN_STEP_STANDBY,
EXT_CI_PCCD_RUN_STEP_RUNNING,
EXT_CI_PCCD_RUN_STEP_CRAD_BUSY,
EXT_CI_PCCD_RUN_STEP_BUIT,
} ext_ci_pccd_run_step;
#define write_reg(addr, value) osal_writel((value), (addr))
#define read_reg(addr) osal_readl(addr)
#define ci_write_reg(offset, value) write_reg(g_ci_reg_base + (offset), value)
#define ci_read_reg(offset) read_reg(g_ci_reg_base + (offset))
#define crg_write_reg(offset, value) write_reg(g_crg_reg_base + (offset), value)
#define crg_read_reg(offset) read_reg(g_crg_reg_base + (offset))
#define peri_write_reg(offset, value) write_reg(g_peri_reg_base + (offset), value)
#define peri_read_reg(offset) read_reg(g_peri_reg_base + (offset))
#define EXT_CI_CHECK_PCCD_VALID(card) do { \
if ((card) >= EXT_CI_PCCD_MAX) { \
soc_log_err("invalid card id:%d.\n", card); \
return SOC_ERR_CI_INVALID_PARA; \
} \
} while (0)
typedef struct {
td_bool is_power_ctrl_gpio_used;
td_u32 power_ctrl_gpio_no[EXT_CI_PCCD_MAX];
td_bool ts_by_pass[EXT_CI_PCCD_MAX];
ext_ci_pccd_run_step run_step[EXT_CI_PCCD_MAX];
ext_ci_pccd_status status[EXT_CI_PCCD_MAX];
td_u32 resume_absent_cnt[EXT_CI_PCCD_MAX];
} ci_param;
static td_void *g_ci_reg_base = TD_NULL;
static td_void *g_crg_reg_base = TD_NULL;
static td_void *g_peri_reg_base = TD_NULL;
static gpio_ext_func* g_gpio_func = TD_NULL;
static ci_param g_ci_param[EXT_CI_PORT_MAX] = {{0}};
td_s32 ci_wait_done(td_u8 *data)
{
td_u32 time_out = 20000;
cmd0_rdata rdata;
if (data == TD_NULL) {
soc_err_print_err_code(SOC_ERR_CI_INVALID_PARA);
return SOC_ERR_CI_INVALID_PARA;
}
*data = 0x00;
rdata.u32 = ci_read_reg(CMD0_RDATA);
while (time_out > 0) {
rdata.u32 = ci_read_reg(CMD0_RDATA);
if (rdata.bits.done == 1) {
break;
}
time_out--;
}
if (time_out == 0) {
soc_log_err("wait data read timeout.\n");
return SOC_ERR_CI_TIMEOUT;
}
*data = rdata.bits.rdata;
return TD_SUCCESS;
}
td_s32 ci_base_addr_remap(td_void)
{
td_u32 ci_phy_base_addr = 0;
td_s32 ret;
ret = osal_dts_get_u32_byname("huanglong,ci", "ci_phy_base_addr", &ci_phy_base_addr);
if (ret < 0) {
soc_log_err("CI get ci_phy_base_addr failed, ret[0x%x]\n", ret);
return TD_FAILURE;
}
g_ci_reg_base = (td_void *)osal_ioremap_nocache(ci_phy_base_addr, 0x1000);
if (g_ci_reg_base == TD_NULL) {
soc_log_err("CI reg base ioremap_nocache failed.\n");
return TD_FAILURE;
}
g_crg_reg_base = (td_void *)osal_ioremap_nocache(PERI_CRG_BASE, 0x1000);
if (g_crg_reg_base == TD_NULL) {
soc_log_err("CRG base ioremap_nocache failed.\n");
osal_iounmap(g_ci_reg_base, OSAL_IOUNMAP_SIZE);
return TD_FAILURE;
}
g_peri_reg_base = (td_void *)osal_ioremap_nocache(PERI_CTRL_BASE, 0x1000);
if (g_peri_reg_base == TD_NULL) {
soc_log_err("CRG base ioremap_nocache failed.\n");
osal_iounmap(g_ci_reg_base, OSAL_IOUNMAP_SIZE);
osal_iounmap(g_crg_reg_base, OSAL_IOUNMAP_SIZE);
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_void ci_base_addr_unmap(td_void)
{
if (g_ci_reg_base != TD_NULL) {
osal_iounmap(g_ci_reg_base, OSAL_IOUNMAP_SIZE);
g_ci_reg_base = TD_NULL;
}
if (g_crg_reg_base != TD_NULL) {
osal_iounmap(g_crg_reg_base, OSAL_IOUNMAP_SIZE);
g_crg_reg_base = TD_NULL;
}
if (g_peri_reg_base != TD_NULL) {
osal_iounmap(g_peri_reg_base, OSAL_IOUNMAP_SIZE);
g_peri_reg_base = TD_NULL;
}
}
td_s32 ci_init(td_void)
{
td_s32 ret;
peri_crg98 crg98;
ci_inf_set inf_set;
cmd_cfg cfg;
slave_mode mode;
crg98.u32 = crg_read_reg(PERI_CRG98);
/* open clcok */
crg98.bits.ci_cken = 1;
crg_write_reg(PERI_CRG98, crg98.u32);
osal_msleep(1);
/* assert reset */
crg98.bits.ci_srst_req = 1;
crg_write_reg(PERI_CRG98, crg98.u32);
osal_msleep(1);
/* remove reset */
crg98.bits.ci_srst_req = 0;
crg_write_reg(PERI_CRG98, crg98.u32);
osal_msleep(1);
/* enable pin output */
inf_set.u32 = ci_read_reg(CI_INF_SET);
inf_set.bits.sw_com_oen = 0;
inf_set.bits.sw_card2_com_oen = 0;
inf_set.bits.sw_rst_oen = 0;
inf_set.bits.sw_card2_rst_oen = 0;
ci_write_reg(CI_INF_SET, inf_set.u32);
/* check ready single but don't check inpackn single */
cfg.u32 = ci_read_reg(CMD_CFG);
cfg.bits.inpackn_check = 0;
cfg.bits.rdy_check = 1;
ci_write_reg(CMD_CFG, cfg.u32);
/* indirect mode */
mode.u32 = ci_read_reg(SLAVE_MODE);
mode.bits.slave_mode = 0;
ci_write_reg(SLAVE_MODE, mode.u32);
ret = hal_ci_pccd_ts_by_pass(EXT_CI_PORT_0, EXT_CI_PCCD_A, TD_TRUE);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(hal_ci_pccd_ts_by_pass, ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 hal_ci_init(td_void)
{
td_s32 ret;
td_u32 i;
ret = ci_base_addr_remap();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ci_base_addr_remap, ret);
return ret;
}
ret = ci_init();
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(ci_init, ret);
return ret;
}
g_gpio_func = TD_NULL;
ret = osal_exportfunc_get(SOC_ID_GPIO, (td_void **)&g_gpio_func);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(osal_exportfunc_get, ret);
return ret;
}
ret = memset_s(&g_ci_param, sizeof(g_ci_param), 0x00, sizeof(g_ci_param));
if (ret != EOK) {
return ret;
}
for (i = 0; i < EXT_CI_PCCD_MAX; i++) {
g_ci_param[EXT_CI_PORT_0].run_step[i] = EXT_CI_PCCD_RUN_STEP_RUNNING;
g_ci_param[EXT_CI_PORT_0].ts_by_pass[i] = TD_TRUE;
g_ci_param[EXT_CI_PORT_0].status[i] = EXT_CI_PCCD_STATUS_MAX;
g_ci_param[EXT_CI_PORT_0].is_power_ctrl_gpio_used = TD_FALSE;
}
return TD_SUCCESS;
}
td_void hal_ci_deinit(td_void)
{
peri_crg98 crg98;
crg98.u32 = crg_read_reg(PERI_CRG98);
/* assert reset */
crg98.bits.ci_srst_req = 1;
crg_write_reg(PERI_CRG98, crg98.u32);
osal_msleep(1);
/* close clcok */
crg98.bits.ci_cken = 0;
crg_write_reg(PERI_CRG98, crg98.u32);
osal_msleep(1);
ci_base_addr_unmap();
return;
}
td_s32 hal_ci_device_open(ext_ci_port port)
{
if (port != EXT_CI_PORT_0) {
soc_log_err("only support EXT_CI_PORT_0 now.\n");
return SOC_ERR_CI_UNSUPPORT;
}
return TD_SUCCESS;
}
td_s32 hal_ci_device_close(ext_ci_port port)
{
if (port != EXT_CI_PORT_0) {
soc_log_err("only support EXT_CI_PORT_0 now.\n");
return SOC_ERR_CI_UNSUPPORT;
}
return TD_SUCCESS;
}
td_s32 hal_ci_set_attr(ext_ci_port port, ext_ci_attr attr)
{
if (port != EXT_CI_PORT_0) {
soc_log_err("only support EXT_CI_PORT_0 now.\n");
return SOC_ERR_CI_UNSUPPORT;
}
g_ci_param[port].is_power_ctrl_gpio_used = attr.dev_attr.extci.is_power_ctrl_gpio_used;
g_ci_param[port].power_ctrl_gpio_no[EXT_CI_PCCD_A] = attr.dev_attr.extci.power_ctrl_gpio_no[EXT_CI_PCCD_A];
g_ci_param[port].power_ctrl_gpio_no[EXT_CI_PCCD_B] = attr.dev_attr.extci.power_ctrl_gpio_no[EXT_CI_PCCD_B];
return TD_SUCCESS;
}
td_s32 hal_ci_pccd_open(ext_ci_port port, ext_ci_pccd card)
{
if (port != EXT_CI_PORT_0) {
soc_log_err("only support EXT_CI_PORT_0 now.\n");
return SOC_ERR_CI_UNSUPPORT;
}
return TD_SUCCESS;
}
td_void hal_ci_pccd_close(ext_ci_port port, ext_ci_pccd card)
{
}
static td_void hal_pccd_select(ext_ci_pccd card)
{
ci_inf_set inf_set;
inf_set.u32 = ci_read_reg(CI_INF_SET);
inf_set.bits.card2_sel = card;
ci_write_reg(CI_INF_SET, inf_set.u32);
}
static td_s32 ci_pccd_byte_rw(ext_ci_port port, ext_ci_pccd card, cmd_type_list type, td_u32 address, td_u8 *value)
{
td_s32 ret;
cmd0_set cmd;
td_u8 out = 0;
if (port != EXT_CI_PORT_0) {
soc_log_err("only support EXT_CI_PORT_0 now.\n");
return SOC_ERR_CI_UNSUPPORT;
}
EXT_CI_CHECK_PCCD_VALID(card);
if (g_ci_param[port].run_step[card] == EXT_CI_PCCD_RUN_STEP_RESUME) {
soc_log_err("Resume from standby, will re-insert CAM soon.\n");
return TD_FAILURE;
}
if (g_ci_param[port].run_step[card] == EXT_CI_PCCD_RUN_STEP_CRAD_BUSY) {
/* card is busy means that card may be dead,
* to avoid keep printing error messages,
* here just return 0 with TD_SUCCESS.
*/
*value = 0x00;
return TD_SUCCESS;
}
hal_pccd_select(card);
cmd.u32 = ci_read_reg(CMD0_SET);
cmd.bits.cmd_type = type;
cmd.bits.addr = address;
cmd.bits.wdata = *value;
ci_write_reg(CMD0_SET, cmd.u32);
/* wait done */
ret = ci_wait_done(&out);
if (ret != TD_SUCCESS) {
g_ci_param[port].run_step[card] = EXT_CI_PCCD_RUN_STEP_CRAD_BUSY;
soc_err_print_call_fun_err(ci_wait_done, ret);
return ret;
}
*value = out;
return TD_SUCCESS;
}
td_s32 hal_ci_pccd_io_read_byte(ext_ci_port port, ext_ci_pccd card, td_u32 address, td_u8 *value)
{
return ci_pccd_byte_rw(port, card, CMD_TYPE_IOR, address, value);
}
td_s32 hal_ci_pccd_io_write_byte(ext_ci_port port, ext_ci_pccd card, td_u32 address, td_u8 value)
{
if (address == COM_STAT_REG) {
value |= (DAIE | FRIE);
}
return ci_pccd_byte_rw(port, card, CMD_TYPE_IOW, address, &value);
}
td_s32 hal_ci_pccd_mem_read_byte(ext_ci_port port, ext_ci_pccd card, td_u32 address, td_u8 *value)
{
return ci_pccd_byte_rw(port, card, CMD_TYPE_MR, address, value);
}
td_s32 hal_ci_pccd_mem_write_byte(ext_ci_port port, ext_ci_pccd card, td_u32 address, td_u8 value)
{
return ci_pccd_byte_rw(port, card, CMD_TYPE_MW, address, &value);
}
td_u32 ci_pccd0_detect_once(td_u32 cd2_dis)
{
dbg_in_sig in_sig;
in_sig.u32 = ci_read_reg(DBG_IN_SIG);
/* check cd1, 0: card present */
if (in_sig.bits.cd1 == 0x01) {
/* card0 absent */
return 0;
}
if (cd2_dis == 1) {
/* disregard cd2, direct return present when cd1 = 0 */
return 1;
}
if (in_sig.bits.cd2 == 0x00) {
/* card0 present */
return 1;
}
/* card0 absent */
return 0;
}
td_u32 ci_pccd1_detect_once(td_u32 cd2_dis)
{
ci_inf_set inf_set;
/* check cd1, 0: card present */
inf_set.u32 = ci_read_reg(CI_INF_SET);
if (inf_set.bits.card2_cd1_n == 0x01) {
/* card1 absent */
return 0;
}
if (cd2_dis == 1) {
/* disregard cd2, direct return present when cd1 = 0 */
return 1;
}
if (inf_set.bits.card2_cd2_n == 0x00) {
/* card1 present */
return 1;
}
/* card1 absent */
return 0;
}
td_s32 hal_ci_pccd_detect(ext_ci_port port, ext_ci_pccd card, ext_ci_pccd_status* status)
{
td_u32 try_count;
td_u32 present_count = 0;
ci_inf_cmd_mode cmd_mode;
if (port != EXT_CI_PORT_0) {
soc_log_err("only support EXT_CI_PORT_0 now.\n");
return SOC_ERR_CI_UNSUPPORT;
}
EXT_CI_CHECK_PCCD_VALID(card);
if (status == TD_NULL) {
soc_err_print_err_code(SOC_ERR_CI_INVALID_PARA);
return SOC_ERR_CI_INVALID_PARA;
}
if (g_ci_param[port].run_step[card] == EXT_CI_PCCD_RUN_STEP_RESUME) {
/* assert card absent after resume to force a higher level CAM initialization */
*status = EXT_CI_PCCD_STATUS_ABSENT;
if (g_ci_param[port].resume_absent_cnt[card] == 0) {
g_ci_param[port].run_step[card] = EXT_CI_PCCD_RUN_STEP_RUNNING;
} else {
g_ci_param[port].resume_absent_cnt[card] -= 1;
}
return TD_SUCCESS;
}
cmd_mode.u32 = ci_read_reg(CI_INF_CMD_MODE);
for (try_count = 0; try_count < CI_PCCD_DETECT_MAX; try_count++) {
if (card == EXT_CI_PCCD_A) {
present_count += ci_pccd0_detect_once(cmd_mode.bits.cd2_dis);
} else {
present_count += ci_pccd1_detect_once(cmd_mode.bits.cd2_dis);
}
osal_msleep(CI_TIME_10MS);
}
if (present_count >= CI_PCCD_DETECT_MIN) {
*status = EXT_CI_PCCD_STATUS_PRESENT;
} else {
*status = EXT_CI_PCCD_STATUS_ABSENT;
}
return TD_SUCCESS;
}
td_s32 hal_ci_pccd_ready_or_busy(ext_ci_port port, ext_ci_pccd card, ext_ci_pccd_ready* ready)
{
td_u32 elapsed_time;
dbg_in_sig in_sig;
if (port != EXT_CI_PORT_0) {
soc_log_err("only support EXT_CI_PORT_0 now.\n");
return SOC_ERR_CI_UNSUPPORT;
}
EXT_CI_CHECK_PCCD_VALID(card);
if (ready == TD_NULL) {
soc_err_print_err_code(SOC_ERR_CI_INVALID_PARA);
return SOC_ERR_CI_INVALID_PARA;
}
*ready = EXT_CI_PCCD_BUSY;
/* the host shall explicitly check for the READY signal until it is set by the
* module or until a timeout of 5s has expired.
*/
for (elapsed_time = 0; elapsed_time < CI_PCCD_READY_COUNT; elapsed_time++) {
in_sig.u32 = ci_read_reg(DBG_IN_SIG);
if (card == EXT_CI_PCCD_A) {
if (in_sig.bits.rdy == 1) {
*ready = EXT_CI_PCCD_READY;
break;
}
} else {
if (in_sig.bits.card2_ready == 1) {
*ready = EXT_CI_PCCD_READY;
break;
}
}
osal_msleep(CI_TIME_10MS);
}
return TD_SUCCESS;
}
td_s32 hal_ci_pccd_reset(ext_ci_port port, ext_ci_pccd card)
{
ci_inf_set inf_set;
if (port != EXT_CI_PORT_0) {
soc_log_err("only support EXT_CI_PORT_0 now.\n");
return SOC_ERR_CI_UNSUPPORT;
}
EXT_CI_CHECK_PCCD_VALID(card);
inf_set.u32 = ci_read_reg(CI_INF_SET);
if (card == EXT_CI_PCCD_A) {
inf_set.bits.set_ci_reset = 1;
ci_write_reg(CI_INF_SET, inf_set.u32);
osal_msleep(CI_TIME_10MS);
inf_set.bits.set_ci_reset = 0;
ci_write_reg(CI_INF_SET, inf_set.u32);
osal_msleep(CI_TIME_10MS);
} else {
inf_set.bits.set_card2_reset = 1;
ci_write_reg(CI_INF_SET, inf_set.u32);
osal_msleep(CI_TIME_10MS);
inf_set.bits.set_card2_reset = 0;
ci_write_reg(CI_INF_SET, inf_set.u32);
osal_msleep(CI_TIME_10MS);
}
/* enter running state after reset */
g_ci_param[EXT_CI_PORT_0].run_step[card] = EXT_CI_PCCD_RUN_STEP_RUNNING;
soc_log_info("reset CAM OK!\n");
return TD_SUCCESS;
}
/*
* power ON/OFF
* notice: Current solution only support power control on CI port, but not for each PCCD.
* so, if you call power off but some cards are present, will return SOC_ERR_CI_CANNOT_POWEROFF.
*/
td_s32 hal_ci_pccd_ctrl_power(ext_ci_port port, ext_ci_pccd card, ext_ci_pccd_ctrl_power ctrl_power)
{
td_s32 ret, ret_bak;
td_u32 gpio_no;
td_u32 gpio_val;
if (port != EXT_CI_PORT_0) {
soc_log_err("only support EXT_CI_PORT_0 now.\n");
return SOC_ERR_CI_UNSUPPORT;
}
EXT_CI_CHECK_PCCD_VALID(card);
if (g_ci_param[port].is_power_ctrl_gpio_used == TD_FALSE) {
return TD_SUCCESS;
}
if ((g_gpio_func == TD_NULL) || (g_gpio_func->pfn_gpio_direction_set_bit == TD_NULL)
|| (g_gpio_func->pfn_gpio_write_bit == TD_NULL)) {
soc_log_err("gpio func invalid.\n");
return TD_FAILURE;
}
gpio_no = g_ci_param[port].power_ctrl_gpio_no[card];
gpio_val = (ctrl_power == EXT_CI_PCCD_CTRLPOWER_ON ? 1 : 0);
ret = g_gpio_func->pfn_gpio_direction_set_bit(gpio_no, 0);
osal_msleep(1);
ret_bak = g_gpio_func->pfn_gpio_write_bit(gpio_no, gpio_val);
ret = (td_s32)((td_u32)ret | (td_u32)ret_bak);
if (ret != TD_SUCCESS) {
soc_log_err("power off device fail, GPIO.\n");
soc_err_print_h32(gpio_no);
return ret;
}
osal_msleep(CI_TIME_10MS);
soc_log_info("power card %d, gpio_no 0x%02x, gpio_val %d\n", card, gpio_no, gpio_val);
return TD_SUCCESS;
}
td_s32 hal_ci_pccd_ts_by_pass(ext_ci_port port, ext_ci_pccd card, td_bool by_pass)
{
peri_io_oen io_oen;
if (port != EXT_CI_PORT_0) {
soc_log_err("only support EXT_CI_PORT_0 now.\n");
return SOC_ERR_CI_UNSUPPORT;
}
EXT_CI_CHECK_PCCD_VALID(card);
io_oen.u32 = peri_read_reg(PERI_IO_OEN);
if (card == EXT_CI_PCCD_A) {
io_oen.bits.peri_tso_loop_sel = (by_pass == TD_TRUE) ? 1 : 0;
peri_write_reg(PERI_IO_OEN, io_oen.u32);
} else if (card == EXT_CI_PCCD_B) {
/*
* tuner->demod->card_b->TSI1->demux->decode
* card B direct link to demod chip, so can't bypass the TS.
*/
soc_log_err("card_id == EXT_CI_PCCD_B\n");
} else {
soc_log_err("only support card A and card B.\n");
return SOC_ERR_CI_UNSUPPORT;
}
g_ci_param[port].ts_by_pass[card] = by_pass;
return TD_SUCCESS;
}
td_s32 hal_ci_pccd_get_bypass_mode(ext_ci_port port, ext_ci_pccd card, td_bool *bypass)
{
peri_io_oen io_oen;
if (bypass == TD_NULL) {
soc_err_print_err_code(SOC_ERR_CI_INVALID_PARA);
return SOC_ERR_CI_INVALID_PARA;
}
if (card == EXT_CI_PCCD_A) {
io_oen.u32 = peri_read_reg(PERI_IO_OEN);
*bypass = (io_oen.bits.peri_tso_loop_sel == 1) ? TD_TRUE : TD_FALSE;
} else {
*bypass = TD_FALSE;
}
return TD_SUCCESS;
}
/* low power */
td_s32 hal_ci_standby(ext_ci_port port)
{
td_s32 ret;
ext_ci_pccd card = 0;
if (port != EXT_CI_PORT_0) {
return TD_SUCCESS;
}
for (card = EXT_CI_PCCD_A; card < EXT_CI_PCCD_MAX; card++) {
g_ci_param[port].run_step[card] = EXT_CI_PCCD_RUN_STEP_STANDBY;
ret = hal_ci_pccd_ctrl_power(port, card, EXT_CI_PCCD_CTRLPOWER_OFF);
if (ret != TD_SUCCESS) {
return ret;
}
}
return TD_SUCCESS;
}
/* resume CI */
td_s32 hal_ci_resume(ext_ci_port port)
{
td_s32 ret;
ext_ci_pccd card = 0;
if (port != EXT_CI_PORT_0) {
return TD_SUCCESS;
}
ret = ci_init();
if (ret != TD_SUCCESS) {
return ret;
}
for (card = EXT_CI_PCCD_A; card < EXT_CI_PCCD_MAX; card++) {
/* during standby CAM may be always power on,
* but host CI is power down,
* so the CAM maybe died as not receive any respond from host
* we need to reset CAM after resume.
*/
ret = hal_ci_pccd_reset(port, card);
if (ret != TD_SUCCESS) {
return ret;
}
g_ci_param[port].run_step[card] = EXT_CI_PCCD_RUN_STEP_RESUME;
g_ci_param[port].resume_absent_cnt[card] = CI_PCCD_RESUME_ABSENT_COUNT;
}
return TD_SUCCESS;
}