コード例 #1
0
int btif_rx_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_DMA_CTRL ctrl_id)
{
	unsigned int i_ret = -1;
	unsigned int base = p_dma_info->base;

	BTIF_TRC_FUNC();

	if (DMA_CTRL_DISABLE == ctrl_id) {
/*if write 0 to EN bit, DMA will be stoped imediately*/
/*if write 1 to STOP bit, DMA will be stoped after current transaction finished*/
		BTIF_CLR_BIT(RX_DMA_EN(base), DMA_EN_BIT);
		BTIF_DBG_FUNC("BTIF Rx DMA disabled\n");
		i_ret = 0;
	} else if (DMA_CTRL_ENABLE == ctrl_id) {
		BTIF_SET_BIT(RX_DMA_EN(base), DMA_EN_BIT);
		BTIF_DBG_FUNC("BTIF Rx DMA enabled\n");
		i_ret = 0;
	} else {
/*TODO: print error log*/
		BTIF_ERR_FUNC("invalid DMA ctrl_id (%d)\n", ctrl_id);
		i_ret = ERR_INVALID_PAR;
	}
	BTIF_TRC_FUNC();

	return i_ret;
}
コード例 #2
0
int btif_tx_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_DMA_CTRL ctrl_id)
{
	unsigned int i_ret = -1;
	unsigned long base = p_dma_info->base;
	unsigned int dat;
	BTIF_TRC_FUNC();
	if (DMA_CTRL_DISABLE == ctrl_id) {
		/*if write 0 to EN bit, DMA will be stoped imediately*/
		/*if write 1 to STOP bit, DMA will be stoped after current transaction finished*/
		/*BTIF_CLR_BIT(TX_DMA_EN(base), DMA_EN_BIT);*/
		BTIF_SET_BIT(TX_DMA_STOP(base), DMA_STOP_BIT);
		do {
			dat = BTIF_READ32(TX_DMA_STOP(base));
		} while (0x1 & dat);
		BTIF_DBG_FUNC("BTIF Tx DMA disabled,EN(0x%x),STOP(0x%x)\n",
			BTIF_READ32(TX_DMA_EN(base)), BTIF_READ32(TX_DMA_STOP(base)));
		i_ret = 0;
	} else if (DMA_CTRL_ENABLE == ctrl_id) {
		BTIF_SET_BIT(TX_DMA_EN(base), DMA_EN_BIT);
		BTIF_DBG_FUNC("BTIF Tx DMA enabled\n");
		i_ret = 0;
	} else {
/*TODO: print error log*/
		BTIF_ERR_FUNC("invalid DMA ctrl_id (%d)\n", ctrl_id);
		i_ret = ERR_INVALID_PAR;
	}
	BTIF_TRC_FUNC();
	return i_ret;
}
コード例 #3
0
int btif_tx_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en)
{
	unsigned int i_ret = -1;
	unsigned long base = p_dma_info->base;

	BTIF_TRC_FUNC();
	if (!en)
		BTIF_CLR_BIT(TX_DMA_INT_EN(base), TX_DMA_INTEN_BIT);
	else
		BTIF_SET_BIT(TX_DMA_INT_EN(base), TX_DMA_INTEN_BIT);
	i_ret = 0;
	BTIF_TRC_FUNC();

	return i_ret;
}
コード例 #4
0
/*****************************************************************************
* FUNCTION
*  hal_tx_vfifo_reset
* DESCRIPTION
*  reset tx virtaul fifo information, except memory information
* PARAMETERS
* p_dma_info   [IN]        pointer to BTIF dma channel's information
* RETURNS
*  0 means success, negative means fail
*****************************************************************************/
int hal_btif_vfifo_reset(P_MTK_DMA_INFO_STR p_dma_info)
{
	unsigned int i_ret = -1;
	P_DMA_VFIFO p_vfifo = p_dma_info->p_vfifo;
	P_MTK_BTIF_DMA_VFIFO p_mtk_dma_vfifo = container_of(p_vfifo,
							    MTK_BTIF_DMA_VFIFO,
							    vfifo);

	BTIF_TRC_FUNC();
	p_mtk_dma_vfifo->rpt = 0;
	p_mtk_dma_vfifo->last_rpt_wrap = 0;
	p_mtk_dma_vfifo->wpt = 0;
	p_mtk_dma_vfifo->last_wpt_wrap = 0;
	BTIF_TRC_FUNC();
	return i_ret;
}
コード例 #5
0
int btif_rx_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en)
{
	unsigned int i_ret = -1;
	unsigned int base = p_dma_info->base;

	BTIF_TRC_FUNC();
	if (!en) {
		BTIF_CLR_BIT(RX_DMA_INT_EN(base),
			     (RX_DMA_INT_THRE_EN | RX_DMA_INT_DONE_EN));
	} else {
		BTIF_SET_BIT(RX_DMA_INT_EN(base),
			     (RX_DMA_INT_THRE_EN | RX_DMA_INT_DONE_EN));
	}
	i_ret = 0;
	BTIF_TRC_FUNC();

	return i_ret;
}
コード例 #6
0
/*****************************************************************************
* FUNCTION
*  hal_tx_dma_info_get
* DESCRIPTION
*  get btif tx dma channel's information
* PARAMETERS
* dma_dir        [IN]         DMA's direction
* RETURNS
*  pointer to btif dma's information structure
*****************************************************************************/
P_MTK_DMA_INFO_STR hal_btif_dma_info_get(ENUM_DMA_DIR dma_dir)
{
	P_MTK_DMA_INFO_STR p_dma_info = NULL;

	BTIF_TRC_FUNC();
	if (DMA_DIR_RX == dma_dir) {
/*Rx DMA*/
		p_dma_info = &mtk_btif_rx_dma;
	} else if (DMA_DIR_TX == dma_dir) {
/*Tx DMA*/
		p_dma_info = &mtk_btif_tx_dma;
	} else {
/*print error log*/
		BTIF_ERR_FUNC("invalid DMA dir (%d)\n", dma_dir);
	}
	spin_lock_init(&g_clk_cg_spinlock);
	BTIF_TRC_FUNC();
	return p_dma_info;
}
コード例 #7
0
/*****************************************************************************
* FUNCTION
*  hal_tx_dma_info_get
* DESCRIPTION
*  get btif tx dma channel's information
* PARAMETERS
* dma_dir        [IN]         DMA's direction
* RETURNS
*  pointer to btif dma's information structure
*****************************************************************************/
P_MTK_DMA_INFO_STR hal_btif_dma_info_get(ENUM_DMA_DIR dma_dir)
{
	P_MTK_DMA_INFO_STR p_dma_info = NULL;

	BTIF_TRC_FUNC();
#ifdef CONFIG_OF
	hal_dma_set_default_setting(dma_dir);
#endif
	if (DMA_DIR_RX == dma_dir)
		/*Rx DMA*/
		p_dma_info = &mtk_btif_rx_dma;
	else if (DMA_DIR_TX == dma_dir)
		/*Tx DMA*/
		p_dma_info = &mtk_btif_tx_dma;
	else
		/*print error log*/
		BTIF_ERR_FUNC("invalid DMA dir (%d)\n", dma_dir);
	spin_lock_init(&g_clk_cg_spinlock);
	BTIF_TRC_FUNC();
	return p_dma_info;
}
コード例 #8
0
/*****************************************************************************
* FUNCTION
*  hal_tx_dma_info_get
* DESCRIPTION
*  get btif tx dma channel's information
* PARAMETERS
* dma_dir        [IN]         DMA's direction
* RETURNS
*  pointer to btif dma's information structure
*****************************************************************************/
P_MTK_DMA_INFO_STR hal_btif_dma_info_get(ENUM_DMA_DIR dma_dir)
{
	P_MTK_DMA_INFO_STR p_dma_info = NULL;

	BTIF_TRC_FUNC();
	if (DMA_DIR_RX == dma_dir) {
/*Rx DMA*/
		p_dma_info = &mtk_btif_rx_dma;
	} else if (DMA_DIR_TX == dma_dir) {
/*Tx DMA*/
		p_dma_info = &mtk_btif_tx_dma;
	} else {
/*print error log*/
		BTIF_ERR_FUNC("invalid DMA dir (%d)\n", dma_dir);
	}
	spin_lock_init(&g_clk_cg_spinlock);
/*dummy call to prevent build warning*/
    hal_dma_receive_data(NULL, NULL, 0);
	BTIF_TRC_FUNC();
	return p_dma_info;
}
コード例 #9
0
/*****************************************************************************
* FUNCTION
*  hal_dma_send_data
* DESCRIPTION
*  send data through btif in DMA mode
* PARAMETERS
* p_dma_info   [IN]        pointer to BTIF dma channel's information
* p_buf     [IN]        pointer to rx data buffer
* max_len  [IN]        tx buffer length
* RETURNS
*  0 means success, negative means fail
*****************************************************************************/
int hal_dma_send_data(P_MTK_DMA_INFO_STR p_dma_info,
		      const unsigned char *p_buf, const unsigned int buf_len)
{
	unsigned int i_ret = -1;
	unsigned int base = p_dma_info->base;
	P_DMA_VFIFO p_vfifo = p_dma_info->p_vfifo;
	unsigned int len_to_send = buf_len;
	unsigned int ava_len = 0;
	unsigned int wpt = 0;
	unsigned int last_wpt_wrap = 0;
	unsigned int vff_size = 0;
	unsigned char *p_data = (unsigned char *)p_buf;
	P_MTK_BTIF_DMA_VFIFO p_mtk_vfifo = container_of(p_vfifo,
							MTK_BTIF_DMA_VFIFO,
							vfifo);

	BTIF_TRC_FUNC();
	if ((NULL == p_buf) || (0 == buf_len)) {
		i_ret = ERR_INVALID_PAR;
		BTIF_ERR_FUNC("invalid parameters, p_buf:0x%08x, buf_len:%d\n",
			      p_buf, buf_len);
		return i_ret;
	}
/*check if tx dma in flush operation? if yes, should wait until DMA finish flush operation*/
/*currently uplayer logic will make sure this pre-condition*/
/*disable Tx IER, in case Tx irq happens, flush bit may be set in irq handler*/
	btif_tx_dma_ier_ctrl(p_dma_info, false);

	vff_size = p_mtk_vfifo->vfifo.vfifo_size;
	ava_len = BTIF_READ32(TX_DMA_VFF_LEFT_SIZE(base));
	wpt = BTIF_READ32(TX_DMA_VFF_WPT(base)) & DMA_WPT_MASK;
	last_wpt_wrap = BTIF_READ32(TX_DMA_VFF_WPT(base)) & DMA_WPT_WRAP;

/*copy data to vFIFO, Note: ava_len should always large than buf_len, otherwise common logic layer will not call hal_dma_send_data*/
	if (buf_len > ava_len) {
		BTIF_ERR_FUNC
		    ("length to send:(%d) < length available(%d), abnormal!!!---!!!\n",
		     buf_len, ava_len);
		BUG_ON(buf_len > ava_len);	/* this will cause kernel panic */
	}

	len_to_send = buf_len < ava_len ? buf_len : ava_len;
	if (len_to_send + wpt >= vff_size) {
		unsigned int tail_len = vff_size - wpt;
		memcpy((p_mtk_vfifo->vfifo.p_vir_addr + wpt), p_data, tail_len);
		p_data += tail_len;
		memcpy(p_mtk_vfifo->vfifo.p_vir_addr,
		       p_data, len_to_send - tail_len);
/*make sure all data write to memory area tx vfifo locates*/
		dsb();

/*calculate WPT*/
		wpt = wpt + len_to_send - vff_size;
		last_wpt_wrap ^= DMA_WPT_WRAP;
	} else {
		memcpy((p_mtk_vfifo->vfifo.p_vir_addr + wpt),
		       p_data, len_to_send);
/*make sure all data write to memory area tx vfifo locates*/
		dsb();

/*calculate WPT*/
		wpt += len_to_send;
	}
	p_mtk_vfifo->wpt = wpt;
	p_mtk_vfifo->last_wpt_wrap = last_wpt_wrap;

/*make sure tx dma is allowed(tx flush bit is not set) to use before update WPT*/
	if (hal_dma_is_tx_allow(p_dma_info)) {
/*make sure tx dma enabled*/
		hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_ENABLE);

/*update WTP to Tx DMA controller's control register*/
		btif_reg_sync_writel(wpt | last_wpt_wrap, TX_DMA_VFF_WPT(base));

		if ((8 > BTIF_READ32(TX_DMA_VFF_VALID_SIZE(base))) &&
		    (0 < BTIF_READ32(TX_DMA_VFF_VALID_SIZE(base)))) {
/*0 < valid size in Tx vFIFO < 8 && TX Flush is not in process<should always be done>? if yes, set flush bit to DMA*/
			_tx_dma_flush(p_dma_info);
		}
		i_ret = len_to_send;
	} else {
/*TODO: print error log*/
		BTIF_ERR_FUNC
		    ("Tx DMA flush operation is in process, this case should never happen, please check if tx operation is allowed before call this API\n");
/*if flush operation is in process , we will return 0*/
		i_ret = 0;
	}

/*Enable Tx IER*/
	btif_tx_dma_ier_ctrl(p_dma_info, true);

	BTIF_TRC_FUNC();
	return i_ret;
}