Commit 7b43da4c authored by Manjunathappa, Prakash's avatar Manjunathappa, Prakash Committed by Sekhar Nori

mmc: davinci_mmc: add DT support

Adds device tree support for davinci_mmc. Also add binding documentation.
As of now tested for non-dma PIO mode and without GPIO card_detect/
write_protect option because of dependencies on EDMA and GPIO module DT
support.
Signed-off-by: default avatarManjunathappa, Prakash <prakash.pm@ti.com>
Reviewed-by: default avatarMark Rutland <mark.rutland@arm.com>
Tested-by: default avatarSekhar Nori <nsekhar@ti.com>
Cc: linux-mmc@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: davinci-linux-open-source@linux.davincidsp.com
Cc: devicetree-discuss@lists.ozlabs.org
Cc: cjb@laptop.org
Cc: Sekhar Nori <nsekhar@ti.com>
Cc: mporter@ti.com
Cc: Arnd Bergmann <arnd@arndb.de>
Acked-by: default avatarArnd Bergmann <arnd@arndb.de>
Acked-by: default avatarChris Ball <cjb@laptop.org>
Signed-off-by: default avatarSekhar Nori <nsekhar@ti.com>
parent c3847a39
* TI Highspeed MMC host controller for DaVinci
The Highspeed MMC Host Controller on TI DaVinci family
provides an interface for MMC, SD and SDIO types of memory cards.
This file documents the properties used by the davinci_mmc driver.
Required properties:
- compatible:
Should be "ti,da830-mmc": for da830, da850, dm365
Should be "ti,dm355-mmc": for dm355, dm644x
Optional properties:
- bus-width: Number of data lines, can be <1>, <4>, or <8>, default <1>
- max-frequency: Maximum operating clock frequency, default 25MHz.
- dmas: List of DMA specifiers with the controller specific format
as described in the generic DMA client binding. A tx and rx
specifier is required.
- dma-names: RX and TX DMA request names. These strings correspond
1:1 with the DMA specifiers listed in dmas.
Example:
mmc0: mmc@1c40000 {
compatible = "ti,da830-mmc",
reg = <0x40000 0x1000>;
interrupts = <16>;
status = "okay";
bus-width = <4>;
max-frequency = <50000000>;
dmas = <&edma 16
&edma 17>;
dma-names = "rx", "tx";
};
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/edma.h> #include <linux/edma.h>
#include <linux/mmc/mmc.h> #include <linux/mmc/mmc.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_data/mmc-davinci.h> #include <linux/platform_data/mmc-davinci.h>
...@@ -522,14 +524,16 @@ static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host) ...@@ -522,14 +524,16 @@ static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host)
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
host->dma_tx = host->dma_tx =
dma_request_channel(mask, edma_filter_fn, &host->txdma); dma_request_slave_channel_compat(mask, edma_filter_fn,
&host->txdma, mmc_dev(host->mmc), "tx");
if (!host->dma_tx) { if (!host->dma_tx) {
dev_err(mmc_dev(host->mmc), "Can't get dma_tx channel\n"); dev_err(mmc_dev(host->mmc), "Can't get dma_tx channel\n");
return -ENODEV; return -ENODEV;
} }
host->dma_rx = host->dma_rx =
dma_request_channel(mask, edma_filter_fn, &host->rxdma); dma_request_slave_channel_compat(mask, edma_filter_fn,
&host->rxdma, mmc_dev(host->mmc), "rx");
if (!host->dma_rx) { if (!host->dma_rx) {
dev_err(mmc_dev(host->mmc), "Can't get dma_rx channel\n"); dev_err(mmc_dev(host->mmc), "Can't get dma_rx channel\n");
r = -ENODEV; r = -ENODEV;
...@@ -1169,9 +1173,62 @@ static struct platform_device_id davinci_mmc_devtype[] = { ...@@ -1169,9 +1173,62 @@ static struct platform_device_id davinci_mmc_devtype[] = {
}; };
MODULE_DEVICE_TABLE(platform, davinci_mmc_devtype); MODULE_DEVICE_TABLE(platform, davinci_mmc_devtype);
static int __init davinci_mmcsd_probe(struct platform_device *pdev) static const struct of_device_id davinci_mmc_dt_ids[] = {
{
.compatible = "ti,dm6441-mmc",
.data = &davinci_mmc_devtype[MMC_CTLR_VERSION_1],
},
{
.compatible = "ti,da830-mmc",
.data = &davinci_mmc_devtype[MMC_CTLR_VERSION_2],
},
{},
};
MODULE_DEVICE_TABLE(of, davinci_mmc_dt_ids);
static struct davinci_mmc_config
*mmc_parse_pdata(struct platform_device *pdev)
{ {
struct device_node *np;
struct davinci_mmc_config *pdata = pdev->dev.platform_data; struct davinci_mmc_config *pdata = pdev->dev.platform_data;
const struct of_device_id *match =
of_match_device(of_match_ptr(davinci_mmc_dt_ids), &pdev->dev);
u32 data;
np = pdev->dev.of_node;
if (!np)
return pdata;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev, "Failed to allocate memory for struct davinci_mmc_config\n");
goto nodata;
}
if (match)
pdev->id_entry = match->data;
if (of_property_read_u32(np, "max-frequency", &pdata->max_freq))
dev_info(&pdev->dev, "'max-frequency' property not specified, defaulting to 25MHz\n");
of_property_read_u32(np, "bus-width", &data);
switch (data) {
case 1:
case 4:
case 8:
pdata->wires = data;
break;
default:
pdata->wires = 1;
dev_info(&pdev->dev, "Unsupported buswidth, defaulting to 1 bit\n");
}
nodata:
return pdata;
}
static int __init davinci_mmcsd_probe(struct platform_device *pdev)
{
struct davinci_mmc_config *pdata = NULL;
struct mmc_davinci_host *host = NULL; struct mmc_davinci_host *host = NULL;
struct mmc_host *mmc = NULL; struct mmc_host *mmc = NULL;
struct resource *r, *mem = NULL; struct resource *r, *mem = NULL;
...@@ -1179,7 +1236,11 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) ...@@ -1179,7 +1236,11 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
size_t mem_size; size_t mem_size;
const struct platform_device_id *id_entry; const struct platform_device_id *id_entry;
/* REVISIT: when we're fully converted, fail if pdata is NULL */ pdata = mmc_parse_pdata(pdev);
if (pdata == NULL) {
dev_err(&pdev->dev, "Couldn't get platform data\n");
return -ENOENT;
}
ret = -ENODEV; ret = -ENODEV;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -1421,6 +1482,7 @@ static struct platform_driver davinci_mmcsd_driver = { ...@@ -1421,6 +1482,7 @@ static struct platform_driver davinci_mmcsd_driver = {
.name = "davinci_mmc", .name = "davinci_mmc",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = davinci_mmcsd_pm_ops, .pm = davinci_mmcsd_pm_ops,
.of_match_table = of_match_ptr(davinci_mmc_dt_ids),
}, },
.remove = __exit_p(davinci_mmcsd_remove), .remove = __exit_p(davinci_mmcsd_remove),
.id_table = davinci_mmc_devtype, .id_table = davinci_mmc_devtype,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment