in host/wmt-sdmmc.c [749:879]
static int wmt_mci_probe(struct platform_device *pdev)
{
struct mmc_host *mmc;
struct wmt_mci_priv *priv;
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *of_id =
of_match_device(wmt_mci_dt_ids, &pdev->dev);
const struct wmt_mci_caps *wmt_caps;
int ret;
int regular_irq, dma_irq;
if (!of_id || !of_id->data) {
dev_err(&pdev->dev, "Controller capabilities data missing\n");
return -EFAULT;
}
wmt_caps = of_id->data;
if (!np) {
dev_err(&pdev->dev, "Missing SDMMC description in devicetree\n");
return -EFAULT;
}
regular_irq = irq_of_parse_and_map(np, 0);
dma_irq = irq_of_parse_and_map(np, 1);
if (!regular_irq || !dma_irq) {
dev_err(&pdev->dev, "Getting IRQs failed!\n");
ret = -ENXIO;
goto fail1;
}
mmc = mmc_alloc_host(sizeof(struct wmt_mci_priv), &pdev->dev);
if (!mmc) {
dev_err(&pdev->dev, "Failed to allocate mmc_host\n");
ret = -ENOMEM;
goto fail1;
}
mmc->ops = &wmt_mci_ops;
mmc->f_min = wmt_caps->f_min;
mmc->f_max = wmt_caps->f_max;
mmc->ocr_avail = wmt_caps->ocr_avail;
mmc->caps = wmt_caps->caps;
mmc->max_seg_size = wmt_caps->max_seg_size;
mmc->max_segs = wmt_caps->max_segs;
mmc->max_blk_size = wmt_caps->max_blk_size;
mmc->max_req_size = (16*512*mmc->max_segs);
mmc->max_blk_count = mmc->max_req_size / 512;
priv = mmc_priv(mmc);
priv->mmc = mmc;
priv->dev = &pdev->dev;
priv->power_inverted = 0;
priv->cd_inverted = 0;
if (of_get_property(np, "sdon-inverted", NULL))
priv->power_inverted = 1;
if (of_get_property(np, "cd-inverted", NULL))
priv->cd_inverted = 1;
priv->sdmmc_base = of_iomap(np, 0);
if (!priv->sdmmc_base) {
dev_err(&pdev->dev, "Failed to map IO space\n");
ret = -ENOMEM;
goto fail2;
}
priv->irq_regular = regular_irq;
priv->irq_dma = dma_irq;
ret = request_irq(regular_irq, wmt_mci_regular_isr, 0, "sdmmc", priv);
if (ret) {
dev_err(&pdev->dev, "Register regular IRQ fail\n");
goto fail3;
}
ret = request_irq(dma_irq, wmt_mci_dma_isr, 0, "sdmmc", priv);
if (ret) {
dev_err(&pdev->dev, "Register DMA IRQ fail\n");
goto fail4;
}
/* alloc some DMA buffers for descriptors/transfers */
priv->dma_desc_buffer = dma_alloc_coherent(&pdev->dev,
mmc->max_blk_count * 16,
&priv->dma_desc_device_addr,
GFP_KERNEL);
if (!priv->dma_desc_buffer) {
dev_err(&pdev->dev, "DMA alloc fail\n");
ret = -EPERM;
goto fail5;
}
platform_set_drvdata(pdev, mmc);
priv->clk_sdmmc = of_clk_get(np, 0);
if (IS_ERR(priv->clk_sdmmc)) {
dev_err(&pdev->dev, "Error getting clock\n");
ret = PTR_ERR(priv->clk_sdmmc);
goto fail5;
}
ret = clk_prepare_enable(priv->clk_sdmmc);
if (ret)
goto fail6;
/* configure the controller to a known 'ready' state */
wmt_reset_hardware(mmc);
mmc_add_host(mmc);
dev_info(&pdev->dev, "WMT SDHC Controller initialized\n");
return 0;
fail6:
clk_put(priv->clk_sdmmc);
fail5:
free_irq(dma_irq, priv);
fail4:
free_irq(regular_irq, priv);
fail3:
iounmap(priv->sdmmc_base);
fail2:
mmc_free_host(mmc);
fail1:
return ret;
}