static int omap_hsmmc_probe()

in host/omap_hsmmc.c [1763:1979]


static int omap_hsmmc_probe(struct platform_device *pdev)
{
	struct omap_hsmmc_platform_data *pdata = pdev->dev.platform_data;
	struct mmc_host *mmc;
	struct omap_hsmmc_host *host = NULL;
	struct resource *res;
	int ret, irq;
	const struct of_device_id *match;
	const struct omap_mmc_of_data *data;
	void __iomem *base;

	match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
	if (match) {
		pdata = of_get_hsmmc_pdata(&pdev->dev);

		if (IS_ERR(pdata))
			return PTR_ERR(pdata);

		if (match->data) {
			data = match->data;
			pdata->reg_offset = data->reg_offset;
			pdata->controller_flags |= data->controller_flags;
		}
	}

	if (pdata == NULL) {
		dev_err(&pdev->dev, "Platform Data is missing\n");
		return -ENXIO;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	irq = platform_get_irq(pdev, 0);
	if (res == NULL || irq < 0)
		return -ENXIO;

	base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(base))
		return PTR_ERR(base);

	mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), &pdev->dev);
	if (!mmc) {
		ret = -ENOMEM;
		goto err;
	}

	ret = mmc_of_parse(mmc);
	if (ret)
		goto err1;

	host		= mmc_priv(mmc);
	host->mmc	= mmc;
	host->pdata	= pdata;
	host->dev	= &pdev->dev;
	host->use_dma	= 1;
	host->dma_ch	= -1;
	host->irq	= irq;
	host->mapbase	= res->start + pdata->reg_offset;
	host->base	= base + pdata->reg_offset;
	host->power_mode = MMC_POWER_OFF;
	host->next_data.cookie = 1;
	host->pbias_enabled = false;
	host->vqmmc_enabled = false;

	platform_set_drvdata(pdev, host);

	if (pdev->dev.of_node)
		host->wake_irq = irq_of_parse_and_map(pdev->dev.of_node, 1);

	mmc->ops	= &omap_hsmmc_ops;

	mmc->f_min = OMAP_MMC_MIN_CLOCK;

	if (pdata->max_freq > 0)
		mmc->f_max = pdata->max_freq;
	else if (mmc->f_max == 0)
		mmc->f_max = OMAP_MMC_MAX_CLOCK;

	spin_lock_init(&host->irq_lock);

	host->fclk = devm_clk_get(&pdev->dev, "fck");
	if (IS_ERR(host->fclk)) {
		ret = PTR_ERR(host->fclk);
		host->fclk = NULL;
		goto err1;
	}

	if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) {
		dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n");
		omap_hsmmc_ops.multi_io_quirk = omap_hsmmc_multi_io_quirk;
	}

	device_init_wakeup(&pdev->dev, true);
	pm_runtime_enable(host->dev);
	pm_runtime_get_sync(host->dev);
	pm_runtime_set_autosuspend_delay(host->dev, MMC_AUTOSUSPEND_DELAY);
	pm_runtime_use_autosuspend(host->dev);

	omap_hsmmc_context_save(host);

	host->dbclk = devm_clk_get(&pdev->dev, "mmchsdb_fck");
	/*
	 * MMC can still work without debounce clock.
	 */
	if (IS_ERR(host->dbclk)) {
		host->dbclk = NULL;
	} else if (clk_prepare_enable(host->dbclk) != 0) {
		dev_warn(mmc_dev(host->mmc), "Failed to enable debounce clk\n");
		host->dbclk = NULL;
	}

	/* Set this to a value that allows allocating an entire descriptor
	 * list within a page (zero order allocation). */
	mmc->max_segs = 64;

	mmc->max_blk_size = 512;       /* Block Length at max can be 1024 */
	mmc->max_blk_count = 0xFFFF;    /* No. of Blocks is 16 bits */
	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;

	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
		     MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_CMD23;

	mmc->caps |= mmc_pdata(host)->caps;
	if (mmc->caps & MMC_CAP_8_BIT_DATA)
		mmc->caps |= MMC_CAP_4_BIT_DATA;

	if (mmc_pdata(host)->nonremovable)
		mmc->caps |= MMC_CAP_NONREMOVABLE;

	mmc->pm_caps |= mmc_pdata(host)->pm_caps;

	omap_hsmmc_conf_bus_power(host);

	host->rx_chan = dma_request_chan(&pdev->dev, "rx");
	if (IS_ERR(host->rx_chan)) {
		dev_err(mmc_dev(host->mmc), "RX DMA channel request failed\n");
		ret = PTR_ERR(host->rx_chan);
		goto err_irq;
	}

	host->tx_chan = dma_request_chan(&pdev->dev, "tx");
	if (IS_ERR(host->tx_chan)) {
		dev_err(mmc_dev(host->mmc), "TX DMA channel request failed\n");
		ret = PTR_ERR(host->tx_chan);
		goto err_irq;
	}

	/*
	 * Limit the maximum segment size to the lower of the request size
	 * and the DMA engine device segment size limits.  In reality, with
	 * 32-bit transfers, the DMA engine can do longer segments than this
	 * but there is no way to represent that in the DMA model - if we
	 * increase this figure here, we get warnings from the DMA API debug.
	 */
	mmc->max_seg_size = min3(mmc->max_req_size,
			dma_get_max_seg_size(host->rx_chan->device->dev),
			dma_get_max_seg_size(host->tx_chan->device->dev));

	/* Request IRQ for MMC operations */
	ret = devm_request_irq(&pdev->dev, host->irq, omap_hsmmc_irq, 0,
			mmc_hostname(mmc), host);
	if (ret) {
		dev_err(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
		goto err_irq;
	}

	ret = omap_hsmmc_reg_get(host);
	if (ret)
		goto err_irq;

	if (!mmc->ocr_avail)
		mmc->ocr_avail = mmc_pdata(host)->ocr_mask;

	omap_hsmmc_disable_irq(host);

	/*
	 * For now, only support SDIO interrupt if we have a separate
	 * wake-up interrupt configured from device tree. This is because
	 * the wake-up interrupt is needed for idle state and some
	 * platforms need special quirks. And we don't want to add new
	 * legacy mux platform init code callbacks any longer as we
	 * are moving to DT based booting anyways.
	 */
	ret = omap_hsmmc_configure_wake_irq(host);
	if (!ret)
		mmc->caps |= MMC_CAP_SDIO_IRQ;

	mmc_add_host(mmc);

	if (mmc_pdata(host)->name != NULL) {
		ret = device_create_file(&mmc->class_dev, &dev_attr_slot_name);
		if (ret < 0)
			goto err_slot_name;
	}

	omap_hsmmc_debugfs(mmc);
	pm_runtime_mark_last_busy(host->dev);
	pm_runtime_put_autosuspend(host->dev);

	return 0;

err_slot_name:
	mmc_remove_host(mmc);
err_irq:
	device_init_wakeup(&pdev->dev, false);
	if (!IS_ERR_OR_NULL(host->tx_chan))
		dma_release_channel(host->tx_chan);
	if (!IS_ERR_OR_NULL(host->rx_chan))
		dma_release_channel(host->rx_chan);
	pm_runtime_dont_use_autosuspend(host->dev);
	pm_runtime_put_sync(host->dev);
	pm_runtime_disable(host->dev);
	clk_disable_unprepare(host->dbclk);
err1:
	mmc_free_host(mmc);
err:
	return ret;
}