Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7ff747c4 authored by Markus Pargmann's avatar Markus Pargmann Committed by Chris Ball
Browse files

mmc: mxcmmc: DT support



Adding devicetree support for imx21-mmc and imx31-mmc. Based on generic
gpio helper functions by Guennadi and generic DMA devicetree bindings.

Signed-off-by: default avatarMarkus Pargmann <mpa@pengutronix.de>
Signed-off-by: default avatarAnatolij Gustschin <agust@denx.de>
Acked-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 32d781a3
Loading
Loading
Loading
Loading
+24 −0
Original line number Original line Diff line number Diff line
* Freescale Secure Digital Host Controller for i.MX2/3 series

This file documents differences to the properties defined in mmc.txt.

Required properties:
- compatible : Should be "fsl,<chip>-mmc", chip can be imx21 or imx31

Optional properties:
- dmas: One DMA phandle with arguments as defined by the devicetree bindings
	of the used DMA controller.
- dma-names: Has to be "rx-tx".

Example:

sdhci1: sdhci@10014000 {
	compatible = "fsl,imx27-mmc", "fsl,imx21-mmc";
	reg = <0x10014000 0x1000>;
	interrupts = <11>;
	dmas = <&dma 7>;
	dma-names = "rx-tx";
	bus-width = <4>;
	cd-gpios = <&gpio3 29>;
	status = "okay";
};
+61 −18
Original line number Original line Diff line number Diff line
@@ -34,6 +34,10 @@
#include <linux/regulator/consumer.h>
#include <linux/regulator/consumer.h>
#include <linux/dmaengine.h>
#include <linux/dmaengine.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_dma.h>
#include <linux/of_gpio.h>


#include <asm/dma.h>
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/irq.h>
@@ -173,6 +177,19 @@ static struct platform_device_id mxcmci_devtype[] = {
};
};
MODULE_DEVICE_TABLE(platform, mxcmci_devtype);
MODULE_DEVICE_TABLE(platform, mxcmci_devtype);


static const struct of_device_id mxcmci_of_match[] = {
	{
		.compatible = "fsl,imx21-mmc",
		.data = &mxcmci_devtype[IMX21_MMC],
	}, {
		.compatible = "fsl,imx31-mmc",
		.data = &mxcmci_devtype[IMX31_MMC],
	}, {
		/* sentinel */
	}
};
MODULE_DEVICE_TABLE(of, mxcmci_of_match);

static inline int is_imx31_mmc(struct mxcmci_host *host)
static inline int is_imx31_mmc(struct mxcmci_host *host)
{
{
	return host->devtype == IMX31_MMC;
	return host->devtype == IMX31_MMC;
@@ -935,10 +952,15 @@ static int mxcmci_probe(struct platform_device *pdev)
	struct mxcmci_host *host = NULL;
	struct mxcmci_host *host = NULL;
	struct resource *iores, *r;
	struct resource *iores, *r;
	int ret = 0, irq;
	int ret = 0, irq;
	bool dat3_card_detect = false;
	dma_cap_mask_t mask;
	dma_cap_mask_t mask;
	const struct of_device_id *of_id;
	struct imxmmc_platform_data *pdata = pdev->dev.platform_data;


	pr_info("i.MX SDHC driver\n");
	pr_info("i.MX SDHC driver\n");


	of_id = of_match_device(mxcmci_of_match, &pdev->dev);

	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	irq = platform_get_irq(pdev, 0);
	irq = platform_get_irq(pdev, 0);
	if (!iores || irq < 0)
	if (!iores || irq < 0)
@@ -954,8 +976,14 @@ static int mxcmci_probe(struct platform_device *pdev)
		goto out_release_mem;
		goto out_release_mem;
	}
	}


	mmc_of_parse(mmc);
	mmc->ops = &mxcmci_ops;
	mmc->ops = &mxcmci_ops;

	/* For devicetree parsing, the bus width is read from devicetree */
	if (pdata)
		mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
		mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
	else
		mmc->caps |= MMC_CAP_SDIO_IRQ;


	/* MMC core transfer sizes tunable parameters */
	/* MMC core transfer sizes tunable parameters */
	mmc->max_segs = 64;
	mmc->max_segs = 64;
@@ -971,14 +999,25 @@ static int mxcmci_probe(struct platform_device *pdev)
		goto out_free;
		goto out_free;
	}
	}


	host->mmc = mmc;
	if (of_id) {
	host->pdata = pdev->dev.platform_data;
		const struct platform_device_id *id_entry = of_id->data;
		host->devtype = id_entry->driver_data;
	} else {
		host->devtype = pdev->id_entry->driver_data;
		host->devtype = pdev->id_entry->driver_data;
	}
	host->mmc = mmc;
	host->pdata = pdata;
	spin_lock_init(&host->lock);
	spin_lock_init(&host->lock);


	if (pdata)
		dat3_card_detect = pdata->dat3_card_detect;
	else if (!(mmc->caps & MMC_CAP_NONREMOVABLE)
			&& !of_property_read_bool(pdev->dev.of_node, "cd-gpios"))
		dat3_card_detect = true;

	mxcmci_init_ocr(host);
	mxcmci_init_ocr(host);


	if (host->pdata && host->pdata->dat3_card_detect)
	if (dat3_card_detect)
		host->default_irq_mask =
		host->default_irq_mask =
			INT_CARD_INSERTION_EN | INT_CARD_REMOVAL_EN;
			INT_CARD_INSERTION_EN | INT_CARD_REMOVAL_EN;
	else
	else
@@ -1020,6 +1059,9 @@ static int mxcmci_probe(struct platform_device *pdev)


	writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR);
	writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR);


	if (!host->pdata) {
		host->dma = dma_request_slave_channel(&pdev->dev, "rx-tx");
	} else {
		r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
		r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
		if (r) {
		if (r) {
			host->dmareq = r->start;
			host->dmareq = r->start;
@@ -1029,12 +1071,12 @@ static int mxcmci_probe(struct platform_device *pdev)
			dma_cap_zero(mask);
			dma_cap_zero(mask);
			dma_cap_set(DMA_SLAVE, mask);
			dma_cap_set(DMA_SLAVE, mask);
			host->dma = dma_request_channel(mask, filter, host);
			host->dma = dma_request_channel(mask, filter, host);
		}
	}
	if (host->dma)
	if (host->dma)
		mmc->max_seg_size = dma_get_max_seg_size(
		mmc->max_seg_size = dma_get_max_seg_size(
				host->dma->device->dev);
				host->dma->device->dev);
	}
	else

	if (!host->dma)
		dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n");
		dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n");


	INIT_WORK(&host->datawork, mxcmci_datawork);
	INIT_WORK(&host->datawork, mxcmci_datawork);
@@ -1153,6 +1195,7 @@ static struct platform_driver mxcmci_driver = {
#ifdef CONFIG_PM
#ifdef CONFIG_PM
		.pm	= &mxcmci_pm_ops,
		.pm	= &mxcmci_pm_ops,
#endif
#endif
		.of_match_table	= mxcmci_of_match,
	}
	}
};
};