/*****************************************************************************
* 函 数 名  : bsp_acc_get_status
*
* 功能描述  : 获取当前通道状态
*
* 输入参数  : 无
* 输出参数  : 无
* 返 回 值  : 通道忙/空闲
*****************************************************************************/
s32 bsp_acc_get_status()
{
    u32 chx_stat = 0;

	if(cipher_open_clk())
	{
		bsp_trace(BSP_LOG_LEVEL_ERROR, BSP_MODU_CIPHER,"CIPHER:fail to open clk\n");
		return CIPHER_UNKNOWN_ERROR;
	}
	chx_stat = readl(CIPHER_REGBASE_ADDR + CIPHER_CHN_ENABLE(ACC_CHN_NUM));
    chx_stat = chx_stat & CHN_STATBIT;
	chx_stat = chx_stat >> 30;
	return (s32)chx_stat;
}
BSP_S32 BSP_CIPHER_Enable(void)
{
	return (BSP_S32)cipher_open_clk();
}
/*****************************************************************************
* 函 数 名  : bsp_acc_enable
*
* 功能描述  : 使能组包加速
*
* 输入参数  : bd_fifo_addr : BDFIFO首地址
*
* 输出参数  : 无
* 返 回 值  : 成功/失败
*****************************************************************************/
s32 bsp_acc_enable(u32 bd_fifo_addr)
{
    u32 chx_stat = 0;
    u32 ptr = 0;
    u32 fifo_num = 0;
    u32 ret;
    u32 last_bd;

	if(cipher_open_clk())
	{
		bsp_trace(BSP_LOG_LEVEL_ERROR, BSP_MODU_CIPHER,"CIPHER:fail to open clk\n");
		return CIPHER_UNKNOWN_ERROR;
	}
    /*禁止组包,将CHX_EN寄存器的第30位写0*/
	ret = readl(CIPHER_REGBASE_ADDR + CIPHER_CHN_ENABLE(ACC_CHN_NUM));
	writel(ret & CHN_PACK_ENBITS, CIPHER_REGBASE_ADDR + CIPHER_CHN_ENABLE(ACC_CHN_NUM));

    /*去使能当前通道*/
	chx_stat = readl(CIPHER_REGBASE_ADDR + CIPHER_CHN_ENABLE(ACC_CHN_NUM));
	writel(chx_stat & CHN_DENBITS, CIPHER_REGBASE_ADDR + CIPHER_CHN_ENABLE(ACC_CHN_NUM));

    /*配置通道0配置寄存器*/
	chx_stat = readl(CIPHER_REGBASE_ADDR + CIPHER_CHN_CONFIG(ACC_CHN_NUM));
	writel(chx_stat | CHN_CFGUSR, CIPHER_REGBASE_ADDR + CIPHER_CHN_CONFIG(ACC_CHN_NUM));

    /*申请清空BD队列,复位读指针*/
	ptr = readl(CIPHER_REGBASE_ADDR + CIPHER_CHN_RESET(ACC_CHN_NUM));
	writel(ptr | CHN_BDRESET, CIPHER_REGBASE_ADDR + CIPHER_CHN_RESET(ACC_CHN_NUM));

    /*将BDFIFO首地址写入寄存器*/
	writel(bd_fifo_addr, CIPHER_REGBASE_ADDR + CIPHER_CHNBDQ_BASE(ACC_CHN_NUM));

    /*获取当前可用FIFO序号*/
	fifo_num = readl(bd_fifo_addr - sizeof(u32));
	if(fifo_num >= ACC_FIFO_NUM)
	{
		ACC_ERROR_PRINT(CIPHER_INVALID_NUM);
        return CIPHER_INVALID_NUM;
	}

    /*更新全局结构体*/
    st_acc_chx_mgr.acc_fifo_mgr[fifo_num].fifo_stat = ACC_STAT_WORK;
	st_acc_chx_mgr.cur_used_fifo_num = fifo_num;

    /*设置最后一个bd为gen_Int_en ,这样硬件就可以通过中断将CHX_EN寄存器的第30自动置反*/
    last_bd = bd_fifo_addr + (st_acc_chx_mgr.acc_fifo_mgr[fifo_num].bd_fifo_cfg_num - 1) * sizeof(struct cipher_bd_s);
	ptr = readl(last_bd + 0);
	writel(ptr | (1U << 13), last_bd + 0);
	//cacheFlush(DATA_CACHE,(void*)bd_fifo_addr,st_acc_chx_mgr.acc_fifo_mgr[fifo_num].bd_fifo_cfg_num * sizeof(struct cipher_bd_s));

    /*更新写指针*/
	ptr = readl(CIPHER_REGBASE_ADDR + CIPHER_CHNBDQ_RWPTR(ACC_CHN_NUM));
    ptr = ptr & CHN_WPT;
    ptr = ptr | st_acc_chx_mgr.acc_fifo_mgr[fifo_num].bd_fifo_cfg_num;
	writel(ptr, CIPHER_REGBASE_ADDR + CIPHER_CHNBDQ_RWPTR(ACC_CHN_NUM));

    /*将通道标志位置为0,表示通道忙,使能组包加速*/
	chx_stat = readl(CIPHER_REGBASE_ADDR + CIPHER_CHN_ENABLE(ACC_CHN_NUM));
	writel(chx_stat | CHN_ENBITS, CIPHER_REGBASE_ADDR + CIPHER_CHN_ENABLE(ACC_CHN_NUM));

    st_acc_chx_mgr.acc_debug.enable_times++;
    return CIPHER_SUCCESS;
}
/*****************************************************************************
* 函 数 名  : bsp_acc_get_bdfifo_addr
*
* 功能描述  : 用于获取当前可用的BDFIFO首地址
*
* 输入参数  : 无
*
* 输出参数  : 无
* 返 回 值  : BDFIFO首地址
*****************************************************************************/
u32 bsp_acc_get_bdfifo_addr()
{
    u32 fifo_base_addr = ACC_FIFO_ERROR;
    u32 i = 0;
	u32 reg_val = 0;
	u32 reg_fifo_addr = 0;

	if(cipher_open_clk())
	{
		bsp_trace(BSP_LOG_LEVEL_ERROR, BSP_MODU_CIPHER,"CIPHER:fail to open clk\n");
		return CIPHER_UNKNOWN_ERROR;
	}
	/* 更新fifo状态 */
	reg_val = readl(CIPHER_REGBASE_ADDR + CIPHER_CHN_ENABLE(ACC_CHN_NUM));
	reg_val &= CHN_STATBIT;
	//reg_fifo_addr = readl(CIPHER_REGBASE_ADDR + CIPHER_CHNBDQ_BASE(ACC_CHN_NUM));
	reg_fifo_addr = st_acc_chx_mgr.acc_fifo_mgr[st_acc_chx_mgr.cur_used_fifo_num].bd_fifo_addr;
	for(i = 0; i < ACC_FIFO_NUM; i++)
	{
		if(st_acc_chx_mgr.acc_fifo_mgr[i].fifo_stat == ACC_STAT_WORK)
		{
			if((i == readl(reg_fifo_addr - sizeof(u32))) && ((!reg_val)))
			{
				continue;
			}
			else
			{
				st_acc_chx_mgr.acc_fifo_mgr[i].fifo_stat = ACC_STAT_IDLE;
			}
		}
	}

	/*第一遍循环,寻找ACC_STAT_IDLE状态FIFO*/
	for(i = 0; i < ACC_FIFO_NUM; i++)
	{
		if(st_acc_chx_mgr.acc_fifo_mgr[i].fifo_stat == ACC_STAT_IDLE)
		{
			fifo_base_addr = st_acc_chx_mgr.acc_fifo_mgr[i].bd_fifo_addr;
			goto GET_FIFO_ADDR_EXIT;
		}
	}
	/*第二遍循环,寻找ACC_STAT_CFG或者ACC_STAT_IDLE状态FIFO*/
	for(i = 0; i < ACC_FIFO_NUM; i++)
	{
		if((st_acc_chx_mgr.acc_fifo_mgr[i].fifo_stat == ACC_STAT_CFG) ||
			(st_acc_chx_mgr.acc_fifo_mgr[i].fifo_stat == ACC_STAT_IDLE))
		{
			fifo_base_addr = st_acc_chx_mgr.acc_fifo_mgr[i].bd_fifo_addr;
			goto GET_FIFO_ADDR_EXIT;
		}
	}

    if (ACC_FIFO_ERROR == fifo_base_addr)
    {
		ACC_ERROR_PRINT(ACC_ALL_FIFO_WORK);
        return ACC_ALL_FIFO_WORK;
    }

GET_FIFO_ADDR_EXIT:
	st_acc_chx_mgr.acc_fifo_mgr[i].bd_fifo_cfg_num = 0; 
	st_acc_chx_mgr.acc_debug.get_fifo_times++;

    return fifo_base_addr;
}