in host/mtk-sd.c [2557:2754]
static int msdc_drv_probe(struct platform_device *pdev)
{
struct mmc_host *mmc;
struct msdc_host *host;
struct resource *res;
int ret;
if (!pdev->dev.of_node) {
dev_err(&pdev->dev, "No DT found\n");
return -EINVAL;
}
/* Allocate MMC host for this device */
mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev);
if (!mmc)
return -ENOMEM;
host = mmc_priv(mmc);
ret = mmc_of_parse(mmc);
if (ret)
goto host_free;
host->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(host->base)) {
ret = PTR_ERR(host->base);
goto host_free;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res) {
host->top_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(host->top_base))
host->top_base = NULL;
}
ret = mmc_regulator_get_supply(mmc);
if (ret)
goto host_free;
ret = msdc_of_clock_parse(pdev, host);
if (ret)
goto host_free;
host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev,
"hrst");
if (IS_ERR(host->reset)) {
ret = PTR_ERR(host->reset);
goto host_free;
}
host->irq = platform_get_irq(pdev, 0);
if (host->irq < 0) {
ret = -EINVAL;
goto host_free;
}
host->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(host->pinctrl)) {
ret = PTR_ERR(host->pinctrl);
dev_err(&pdev->dev, "Cannot find pinctrl!\n");
goto host_free;
}
host->pins_default = pinctrl_lookup_state(host->pinctrl, "default");
if (IS_ERR(host->pins_default)) {
ret = PTR_ERR(host->pins_default);
dev_err(&pdev->dev, "Cannot find pinctrl default!\n");
goto host_free;
}
host->pins_uhs = pinctrl_lookup_state(host->pinctrl, "state_uhs");
if (IS_ERR(host->pins_uhs)) {
ret = PTR_ERR(host->pins_uhs);
dev_err(&pdev->dev, "Cannot find pinctrl uhs!\n");
goto host_free;
}
msdc_of_property_parse(pdev, host);
host->dev = &pdev->dev;
host->dev_comp = of_device_get_match_data(&pdev->dev);
host->src_clk_freq = clk_get_rate(host->src_clk);
/* Set host parameters to mmc */
mmc->ops = &mt_msdc_ops;
if (host->dev_comp->clk_div_bits == 8)
mmc->f_min = DIV_ROUND_UP(host->src_clk_freq, 4 * 255);
else
mmc->f_min = DIV_ROUND_UP(host->src_clk_freq, 4 * 4095);
if (!(mmc->caps & MMC_CAP_NONREMOVABLE) &&
!mmc_can_gpio_cd(mmc) &&
host->dev_comp->use_internal_cd) {
/*
* Is removable but no GPIO declared, so
* use internal functionality.
*/
host->internal_cd = true;
}
if (mmc->caps & MMC_CAP_SDIO_IRQ)
mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
mmc->caps |= MMC_CAP_CMD23;
if (host->cqhci)
mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
/* MMC core transfer sizes tunable parameters */
mmc->max_segs = MAX_BD_NUM;
if (host->dev_comp->support_64g)
mmc->max_seg_size = BDMA_DESC_BUFLEN_EXT;
else
mmc->max_seg_size = BDMA_DESC_BUFLEN;
mmc->max_blk_size = 2048;
mmc->max_req_size = 512 * 1024;
mmc->max_blk_count = mmc->max_req_size / 512;
if (host->dev_comp->support_64g)
host->dma_mask = DMA_BIT_MASK(36);
else
host->dma_mask = DMA_BIT_MASK(32);
mmc_dev(mmc)->dma_mask = &host->dma_mask;
host->timeout_clks = 3 * 1048576;
host->dma.gpd = dma_alloc_coherent(&pdev->dev,
2 * sizeof(struct mt_gpdma_desc),
&host->dma.gpd_addr, GFP_KERNEL);
host->dma.bd = dma_alloc_coherent(&pdev->dev,
MAX_BD_NUM * sizeof(struct mt_bdma_desc),
&host->dma.bd_addr, GFP_KERNEL);
if (!host->dma.gpd || !host->dma.bd) {
ret = -ENOMEM;
goto release_mem;
}
msdc_init_gpd_bd(host, &host->dma);
INIT_DELAYED_WORK(&host->req_timeout, msdc_request_timeout);
spin_lock_init(&host->lock);
platform_set_drvdata(pdev, mmc);
ret = msdc_ungate_clock(host);
if (ret) {
dev_err(&pdev->dev, "Cannot ungate clocks!\n");
goto release_mem;
}
msdc_init_hw(host);
if (mmc->caps2 & MMC_CAP2_CQE) {
host->cq_host = devm_kzalloc(mmc->parent,
sizeof(*host->cq_host),
GFP_KERNEL);
if (!host->cq_host) {
ret = -ENOMEM;
goto host_free;
}
host->cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
host->cq_host->mmio = host->base + 0x800;
host->cq_host->ops = &msdc_cmdq_ops;
ret = cqhci_init(host->cq_host, mmc, true);
if (ret)
goto host_free;
mmc->max_segs = 128;
/* cqhci 16bit length */
/* 0 size, means 65536 so we don't have to -1 here */
mmc->max_seg_size = 64 * 1024;
}
ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq,
IRQF_TRIGGER_NONE, pdev->name, host);
if (ret)
goto release;
pm_runtime_set_active(host->dev);
pm_runtime_set_autosuspend_delay(host->dev, MTK_MMC_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(host->dev);
pm_runtime_enable(host->dev);
ret = mmc_add_host(mmc);
if (ret)
goto end;
return 0;
end:
pm_runtime_disable(host->dev);
release:
platform_set_drvdata(pdev, NULL);
msdc_deinit_hw(host);
msdc_gate_clock(host);
release_mem:
if (host->dma.gpd)
dma_free_coherent(&pdev->dev,
2 * sizeof(struct mt_gpdma_desc),
host->dma.gpd, host->dma.gpd_addr);
if (host->dma.bd)
dma_free_coherent(&pdev->dev,
MAX_BD_NUM * sizeof(struct mt_bdma_desc),
host->dma.bd, host->dma.bd_addr);
host_free:
mmc_free_host(mmc);
return ret;
}