diff options
author | Markus Pargmann <mpa@pengutronix.de> | 2013-03-31 14:07:38 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2013-04-12 15:12:34 -0400 |
commit | 7ff747c45908abb4fb894b21a8752a3e48acf02b (patch) | |
tree | 5e21cf1c52a539056309591728700dc8b67a0324 /drivers/mmc/host | |
parent | 32d781a310785dcc86c41b6793b2bd4f41015d73 (diff) |
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: Markus Pargmann <mpa@pengutronix.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r-- | drivers/mmc/host/mxcmmc.c | 79 |
1 files changed, 61 insertions, 18 deletions
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 28e527ebde75..848ab2c2ff05 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
@@ -34,6 +34,10 @@ | |||
34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
35 | #include <linux/dmaengine.h> | 35 | #include <linux/dmaengine.h> |
36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
37 | #include <linux/of.h> | ||
38 | #include <linux/of_device.h> | ||
39 | #include <linux/of_dma.h> | ||
40 | #include <linux/of_gpio.h> | ||
37 | 41 | ||
38 | #include <asm/dma.h> | 42 | #include <asm/dma.h> |
39 | #include <asm/irq.h> | 43 | #include <asm/irq.h> |
@@ -173,6 +177,19 @@ static struct platform_device_id mxcmci_devtype[] = { | |||
173 | }; | 177 | }; |
174 | MODULE_DEVICE_TABLE(platform, mxcmci_devtype); | 178 | MODULE_DEVICE_TABLE(platform, mxcmci_devtype); |
175 | 179 | ||
180 | static const struct of_device_id mxcmci_of_match[] = { | ||
181 | { | ||
182 | .compatible = "fsl,imx21-mmc", | ||
183 | .data = &mxcmci_devtype[IMX21_MMC], | ||
184 | }, { | ||
185 | .compatible = "fsl,imx31-mmc", | ||
186 | .data = &mxcmci_devtype[IMX31_MMC], | ||
187 | }, { | ||
188 | /* sentinel */ | ||
189 | } | ||
190 | }; | ||
191 | MODULE_DEVICE_TABLE(of, mxcmci_of_match); | ||
192 | |||
176 | static inline int is_imx31_mmc(struct mxcmci_host *host) | 193 | static inline int is_imx31_mmc(struct mxcmci_host *host) |
177 | { | 194 | { |
178 | return host->devtype == IMX31_MMC; | 195 | return host->devtype == IMX31_MMC; |
@@ -935,10 +952,15 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
935 | struct mxcmci_host *host = NULL; | 952 | struct mxcmci_host *host = NULL; |
936 | struct resource *iores, *r; | 953 | struct resource *iores, *r; |
937 | int ret = 0, irq; | 954 | int ret = 0, irq; |
955 | bool dat3_card_detect = false; | ||
938 | dma_cap_mask_t mask; | 956 | dma_cap_mask_t mask; |
957 | const struct of_device_id *of_id; | ||
958 | struct imxmmc_platform_data *pdata = pdev->dev.platform_data; | ||
939 | 959 | ||
940 | pr_info("i.MX SDHC driver\n"); | 960 | pr_info("i.MX SDHC driver\n"); |
941 | 961 | ||
962 | of_id = of_match_device(mxcmci_of_match, &pdev->dev); | ||
963 | |||
942 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 964 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
943 | irq = platform_get_irq(pdev, 0); | 965 | irq = platform_get_irq(pdev, 0); |
944 | if (!iores || irq < 0) | 966 | if (!iores || irq < 0) |
@@ -954,8 +976,14 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
954 | goto out_release_mem; | 976 | goto out_release_mem; |
955 | } | 977 | } |
956 | 978 | ||
979 | mmc_of_parse(mmc); | ||
957 | mmc->ops = &mxcmci_ops; | 980 | mmc->ops = &mxcmci_ops; |
958 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; | 981 | |
982 | /* For devicetree parsing, the bus width is read from devicetree */ | ||
983 | if (pdata) | ||
984 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; | ||
985 | else | ||
986 | mmc->caps |= MMC_CAP_SDIO_IRQ; | ||
959 | 987 | ||
960 | /* MMC core transfer sizes tunable parameters */ | 988 | /* MMC core transfer sizes tunable parameters */ |
961 | mmc->max_segs = 64; | 989 | mmc->max_segs = 64; |
@@ -971,14 +999,25 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
971 | goto out_free; | 999 | goto out_free; |
972 | } | 1000 | } |
973 | 1001 | ||
1002 | if (of_id) { | ||
1003 | const struct platform_device_id *id_entry = of_id->data; | ||
1004 | host->devtype = id_entry->driver_data; | ||
1005 | } else { | ||
1006 | host->devtype = pdev->id_entry->driver_data; | ||
1007 | } | ||
974 | host->mmc = mmc; | 1008 | host->mmc = mmc; |
975 | host->pdata = pdev->dev.platform_data; | 1009 | host->pdata = pdata; |
976 | host->devtype = pdev->id_entry->driver_data; | ||
977 | spin_lock_init(&host->lock); | 1010 | spin_lock_init(&host->lock); |
978 | 1011 | ||
1012 | if (pdata) | ||
1013 | dat3_card_detect = pdata->dat3_card_detect; | ||
1014 | else if (!(mmc->caps & MMC_CAP_NONREMOVABLE) | ||
1015 | && !of_property_read_bool(pdev->dev.of_node, "cd-gpios")) | ||
1016 | dat3_card_detect = true; | ||
1017 | |||
979 | mxcmci_init_ocr(host); | 1018 | mxcmci_init_ocr(host); |
980 | 1019 | ||
981 | if (host->pdata && host->pdata->dat3_card_detect) | 1020 | if (dat3_card_detect) |
982 | host->default_irq_mask = | 1021 | host->default_irq_mask = |
983 | INT_CARD_INSERTION_EN | INT_CARD_REMOVAL_EN; | 1022 | INT_CARD_INSERTION_EN | INT_CARD_REMOVAL_EN; |
984 | else | 1023 | else |
@@ -1020,21 +1059,24 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
1020 | 1059 | ||
1021 | writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR); | 1060 | writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR); |
1022 | 1061 | ||
1023 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 1062 | if (!host->pdata) { |
1024 | if (r) { | 1063 | host->dma = dma_request_slave_channel(&pdev->dev, "rx-tx"); |
1025 | host->dmareq = r->start; | 1064 | } else { |
1026 | host->dma_data.peripheral_type = IMX_DMATYPE_SDHC; | 1065 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
1027 | host->dma_data.priority = DMA_PRIO_LOW; | 1066 | if (r) { |
1028 | host->dma_data.dma_request = host->dmareq; | 1067 | host->dmareq = r->start; |
1029 | dma_cap_zero(mask); | 1068 | host->dma_data.peripheral_type = IMX_DMATYPE_SDHC; |
1030 | dma_cap_set(DMA_SLAVE, mask); | 1069 | host->dma_data.priority = DMA_PRIO_LOW; |
1031 | host->dma = dma_request_channel(mask, filter, host); | 1070 | host->dma_data.dma_request = host->dmareq; |
1032 | if (host->dma) | 1071 | dma_cap_zero(mask); |
1033 | mmc->max_seg_size = dma_get_max_seg_size( | 1072 | dma_cap_set(DMA_SLAVE, mask); |
1034 | host->dma->device->dev); | 1073 | host->dma = dma_request_channel(mask, filter, host); |
1074 | } | ||
1035 | } | 1075 | } |
1036 | 1076 | if (host->dma) | |
1037 | if (!host->dma) | 1077 | mmc->max_seg_size = dma_get_max_seg_size( |
1078 | host->dma->device->dev); | ||
1079 | else | ||
1038 | dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n"); | 1080 | dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n"); |
1039 | 1081 | ||
1040 | INIT_WORK(&host->datawork, mxcmci_datawork); | 1082 | INIT_WORK(&host->datawork, mxcmci_datawork); |
@@ -1153,6 +1195,7 @@ static struct platform_driver mxcmci_driver = { | |||
1153 | #ifdef CONFIG_PM | 1195 | #ifdef CONFIG_PM |
1154 | .pm = &mxcmci_pm_ops, | 1196 | .pm = &mxcmci_pm_ops, |
1155 | #endif | 1197 | #endif |
1198 | .of_match_table = mxcmci_of_match, | ||
1156 | } | 1199 | } |
1157 | }; | 1200 | }; |
1158 | 1201 | ||