Пример #1
0
int wcn36xx_dxe_init(struct wcn36xx *wcn)
{
    int reg_data = 0, ret;

    reg_data = WCN36XX_DXE_REG_RESET;
    wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data);

    /* Setting interrupt path */
    reg_data = WCN36XX_DXE_CCU_INT;
    wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);

    /***************************************/
    /* Init descriptors for TX LOW channel */
    /***************************************/
    wcn36xx_dxe_init_descs(&wcn->dxe_tx_l_ch);
    wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool);

    /* Write channel head to a NEXT register */
    wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L,
                               wcn->dxe_tx_l_ch.head_blk_ctl->desc_phy_addr);

    /* Program DMA destination addr for TX LOW */
    wcn36xx_dxe_write_register(wcn,
                               WCN36XX_DXE_CH_DEST_ADDR_TX_L,
                               WCN36XX_DXE_WQ_TX_L);

    wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);
    wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L);

    /***************************************/
    /* Init descriptors for TX HIGH channel */
    /***************************************/
    wcn36xx_dxe_init_descs(&wcn->dxe_tx_h_ch);
    wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool);

    /* Write channel head to a NEXT register */
    wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H,
                               wcn->dxe_tx_h_ch.head_blk_ctl->desc_phy_addr);

    /* Program DMA destination addr for TX HIGH */
    wcn36xx_dxe_write_register(wcn,
                               WCN36XX_DXE_CH_DEST_ADDR_TX_H,
                               WCN36XX_DXE_WQ_TX_H);

    wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);

    /* Enable channel interrupts */
    wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H);

    /***************************************/
    /* Init descriptors for RX LOW channel */
    /***************************************/
    wcn36xx_dxe_init_descs(&wcn->dxe_rx_l_ch);

    /* For RX we need to preallocated buffers */
    wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch);

    /* Write channel head to a NEXT register */
    wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L,
                               wcn->dxe_rx_l_ch.head_blk_ctl->desc_phy_addr);

    /* Write DMA source address */
    wcn36xx_dxe_write_register(wcn,
                               WCN36XX_DXE_CH_SRC_ADDR_RX_L,
                               WCN36XX_DXE_WQ_RX_L);

    /* Program preallocated destination address */
    wcn36xx_dxe_write_register(wcn,
                               WCN36XX_DXE_CH_DEST_ADDR_RX_L,
                               wcn->dxe_rx_l_ch.head_blk_ctl->desc->phy_next_l);

    /* Enable default control registers */
    wcn36xx_dxe_write_register(wcn,
                               WCN36XX_DXE_REG_CTL_RX_L,
                               WCN36XX_DXE_CH_DEFAULT_CTL_RX_L);

    /* Enable channel interrupts */
    wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L);

    /***************************************/
    /* Init descriptors for RX HIGH channel */
    /***************************************/
    wcn36xx_dxe_init_descs(&wcn->dxe_rx_h_ch);

    /* For RX we need to prealocat buffers */
    wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch);

    /* Write chanel head to a NEXT register */
    wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H,
                               wcn->dxe_rx_h_ch.head_blk_ctl->desc_phy_addr);

    /* Write DMA source address */
    wcn36xx_dxe_write_register(wcn,
                               WCN36XX_DXE_CH_SRC_ADDR_RX_H,
                               WCN36XX_DXE_WQ_RX_H);

    /* Program preallocated destination address */
    wcn36xx_dxe_write_register(wcn,
                               WCN36XX_DXE_CH_DEST_ADDR_RX_H,
                               wcn->dxe_rx_h_ch.head_blk_ctl->desc->phy_next_l);

    /* Enable default control registers */
    wcn36xx_dxe_write_register(wcn,
                               WCN36XX_DXE_REG_CTL_RX_H,
                               WCN36XX_DXE_CH_DEFAULT_CTL_RX_H);

    /* Enable channel interrupts */
    wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H);

    ret = wcn36xx_dxe_request_irqs(wcn);
    if (ret < 0)
        goto out_err;

    return 0;

out_err:
    return ret;
}
Пример #2
0
Файл: dxe.c Проект: Lyude/linux
int wcn36xx_dxe_init(struct wcn36xx *wcn)
{
	int reg_data = 0, ret;

	reg_data = WCN36XX_DXE_REG_RESET;
	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data);

	/* Select channels for rx avail and xfer done interrupts... */
	reg_data = (WCN36XX_DXE_INT_CH3_MASK | WCN36XX_DXE_INT_CH1_MASK) << 16 |
		    WCN36XX_DXE_INT_CH0_MASK | WCN36XX_DXE_INT_CH4_MASK;
	if (wcn->is_pronto)
		wcn36xx_ccu_write_register(wcn, WCN36XX_CCU_DXE_INT_SELECT_PRONTO, reg_data);
	else
		wcn36xx_ccu_write_register(wcn, WCN36XX_CCU_DXE_INT_SELECT_RIVA, reg_data);

	/***************************************/
	/* Init descriptors for TX LOW channel */
	/***************************************/
	ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch);
	if (ret) {
		dev_err(wcn->dev, "Error allocating descriptor\n");
		return ret;
	}
	wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool);

	/* Write channel head to a NEXT register */
	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L,
		wcn->dxe_tx_l_ch.head_blk_ctl->desc_phy_addr);

	/* Program DMA destination addr for TX LOW */
	wcn36xx_dxe_write_register(wcn,
		WCN36XX_DXE_CH_DEST_ADDR_TX_L,
		WCN36XX_DXE_WQ_TX_L);

	wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);
	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L);

	/***************************************/
	/* Init descriptors for TX HIGH channel */
	/***************************************/
	ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch);
	if (ret) {
		dev_err(wcn->dev, "Error allocating descriptor\n");
		goto out_err_txh_ch;
	}

	wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool);

	/* Write channel head to a NEXT register */
	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H,
		wcn->dxe_tx_h_ch.head_blk_ctl->desc_phy_addr);

	/* Program DMA destination addr for TX HIGH */
	wcn36xx_dxe_write_register(wcn,
		WCN36XX_DXE_CH_DEST_ADDR_TX_H,
		WCN36XX_DXE_WQ_TX_H);

	wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);

	/* Enable channel interrupts */
	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H);

	/***************************************/
	/* Init descriptors for RX LOW channel */
	/***************************************/
	ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch);
	if (ret) {
		dev_err(wcn->dev, "Error allocating descriptor\n");
		goto out_err_rxl_ch;
	}


	/* For RX we need to preallocated buffers */
	wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch);

	/* Write channel head to a NEXT register */
	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L,
		wcn->dxe_rx_l_ch.head_blk_ctl->desc_phy_addr);

	/* Write DMA source address */
	wcn36xx_dxe_write_register(wcn,
		WCN36XX_DXE_CH_SRC_ADDR_RX_L,
		WCN36XX_DXE_WQ_RX_L);

	/* Program preallocated destination address */
	wcn36xx_dxe_write_register(wcn,
		WCN36XX_DXE_CH_DEST_ADDR_RX_L,
		wcn->dxe_rx_l_ch.head_blk_ctl->desc->phy_next_l);

	/* Enable default control registers */
	wcn36xx_dxe_write_register(wcn,
		WCN36XX_DXE_REG_CTL_RX_L,
		WCN36XX_DXE_CH_DEFAULT_CTL_RX_L);

	/* Enable channel interrupts */
	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L);

	/***************************************/
	/* Init descriptors for RX HIGH channel */
	/***************************************/
	ret = wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch);
	if (ret) {
		dev_err(wcn->dev, "Error allocating descriptor\n");
		goto out_err_rxh_ch;
	}

	/* For RX we need to prealocat buffers */
	wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch);

	/* Write chanel head to a NEXT register */
	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H,
		wcn->dxe_rx_h_ch.head_blk_ctl->desc_phy_addr);

	/* Write DMA source address */
	wcn36xx_dxe_write_register(wcn,
		WCN36XX_DXE_CH_SRC_ADDR_RX_H,
		WCN36XX_DXE_WQ_RX_H);

	/* Program preallocated destination address */
	wcn36xx_dxe_write_register(wcn,
		WCN36XX_DXE_CH_DEST_ADDR_RX_H,
		 wcn->dxe_rx_h_ch.head_blk_ctl->desc->phy_next_l);

	/* Enable default control registers */
	wcn36xx_dxe_write_register(wcn,
		WCN36XX_DXE_REG_CTL_RX_H,
		WCN36XX_DXE_CH_DEFAULT_CTL_RX_H);

	/* Enable channel interrupts */
	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H);

	ret = wcn36xx_dxe_request_irqs(wcn);
	if (ret < 0)
		goto out_err_irq;

	return 0;

out_err_irq:
	wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_rx_h_ch);
out_err_rxh_ch:
	wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_rx_l_ch);
out_err_rxl_ch:
	wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_tx_h_ch);
out_err_txh_ch:
	wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_tx_l_ch);

	return ret;
}