in btmtksdio.c [531:621]
static int btmtksdio_open(struct hci_dev *hdev)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
u32 status, val;
int err;
sdio_claim_host(bdev->func);
err = sdio_enable_func(bdev->func);
if (err < 0)
goto err_release_host;
set_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state);
/* Get ownership from the device */
sdio_writel(bdev->func, C_FW_OWN_REQ_CLR, MTK_REG_CHLPCR, &err);
if (err < 0)
goto err_disable_func;
err = readx_poll_timeout(btmtksdio_drv_own_query, bdev, status,
status & C_COM_DRV_OWN, 2000, 1000000);
if (err < 0) {
bt_dev_err(bdev->hdev, "Cannot get ownership from device");
goto err_disable_func;
}
/* Disable interrupt & mask out all interrupt sources */
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, &err);
if (err < 0)
goto err_disable_func;
sdio_writel(bdev->func, 0, MTK_REG_CHIER, &err);
if (err < 0)
goto err_disable_func;
err = sdio_claim_irq(bdev->func, btmtksdio_interrupt);
if (err < 0)
goto err_disable_func;
err = sdio_set_block_size(bdev->func, MTK_SDIO_BLOCK_SIZE);
if (err < 0)
goto err_release_irq;
/* SDIO CMD 5 allows the SDIO device back to idle state an
* synchronous interrupt is supported in SDIO 4-bit mode
*/
val = sdio_readl(bdev->func, MTK_REG_CSDIOCSR, &err);
if (err < 0)
goto err_release_irq;
val |= SDIO_INT_CTL;
sdio_writel(bdev->func, val, MTK_REG_CSDIOCSR, &err);
if (err < 0)
goto err_release_irq;
/* Explitly set write-1-clear method */
val = sdio_readl(bdev->func, MTK_REG_CHCR, &err);
if (err < 0)
goto err_release_irq;
val |= C_INT_CLR_CTRL;
sdio_writel(bdev->func, val, MTK_REG_CHCR, &err);
if (err < 0)
goto err_release_irq;
/* Setup interrupt sources */
sdio_writel(bdev->func, RX_DONE_INT | TX_EMPTY | TX_FIFO_OVERFLOW,
MTK_REG_CHIER, &err);
if (err < 0)
goto err_release_irq;
/* Enable interrupt */
sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, &err);
if (err < 0)
goto err_release_irq;
sdio_release_host(bdev->func);
return 0;
err_release_irq:
sdio_release_irq(bdev->func);
err_disable_func:
sdio_disable_func(bdev->func);
err_release_host:
sdio_release_host(bdev->func);
return err;
}