提交 abfafc2d 编写于 作者: S Shawn Guo

mmc: sdhci-esdhc-imx: add device tree probe support

The patch adds device tree probe support for sdhci-esdhc-imx driver.
Signed-off-by: NShawn Guo <shawn.guo@linaro.org>
Cc: Wolfram Sang <w.sang@pengutronix.de>
Cc: Chris Ball <cjb@laptop.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Acked-by: NGrant Likely <grant.likely@secretlab.ca>
Acked-by: NChris Ball <cjb@laptop.org>
上级 a4d2177f
* Freescale Enhanced Secure Digital Host Controller (eSDHC) for i.MX
The Enhanced Secure Digital Host Controller on Freescale i.MX family
provides an interface for MMC, SD, and SDIO types of memory cards.
Required properties:
- compatible : Should be "fsl,<chip>-esdhc"
- reg : Should contain eSDHC registers location and length
- interrupts : Should contain eSDHC interrupt
Optional properties:
- fsl,card-wired : Indicate the card is wired to host permanently
- fsl,cd-internal : Indicate to use controller internal card detection
- fsl,wp-internal : Indicate to use controller internal write protection
- cd-gpios : Specify GPIOs for card detection
- wp-gpios : Specify GPIOs for write protection
Examples:
esdhc@70004000 {
compatible = "fsl,imx51-esdhc";
reg = <0x70004000 0x4000>;
interrupts = <1>;
fsl,cd-internal;
fsl,wp-internal;
};
esdhc@70008000 {
compatible = "fsl,imx51-esdhc";
reg = <0x70008000 0x4000>;
interrupts = <2>;
cd-gpios = <&gpio0 6 0>; /* GPIO1_6 */
wp-gpios = <&gpio0 5 0>; /* GPIO1_5 */
};
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/mmc.h> #include <linux/mmc/mmc.h>
#include <linux/mmc/sdio.h> #include <linux/mmc/sdio.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <mach/esdhc.h> #include <mach/esdhc.h>
#include "sdhci-pltfm.h" #include "sdhci-pltfm.h"
#include "sdhci-esdhc.h" #include "sdhci-esdhc.h"
...@@ -74,6 +77,15 @@ static struct platform_device_id imx_esdhc_devtype[] = { ...@@ -74,6 +77,15 @@ static struct platform_device_id imx_esdhc_devtype[] = {
}; };
MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype); MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype);
static const struct of_device_id imx_esdhc_dt_ids[] = {
{ .compatible = "fsl,imx25-esdhc", .data = &imx_esdhc_devtype[IMX25_ESDHC], },
{ .compatible = "fsl,imx35-esdhc", .data = &imx_esdhc_devtype[IMX35_ESDHC], },
{ .compatible = "fsl,imx51-esdhc", .data = &imx_esdhc_devtype[IMX51_ESDHC], },
{ .compatible = "fsl,imx53-esdhc", .data = &imx_esdhc_devtype[IMX53_ESDHC], },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids);
static inline int is_imx25_esdhc(struct pltfm_imx_data *data) static inline int is_imx25_esdhc(struct pltfm_imx_data *data)
{ {
return data->devtype == IMX25_ESDHC; return data->devtype == IMX25_ESDHC;
...@@ -290,8 +302,48 @@ static irqreturn_t cd_irq(int irq, void *data) ...@@ -290,8 +302,48 @@ static irqreturn_t cd_irq(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
}; };
#ifdef CONFIG_OF
static int __devinit
sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
struct esdhc_platform_data *boarddata)
{
struct device_node *np = pdev->dev.of_node;
if (!np)
return -ENODEV;
if (of_get_property(np, "fsl,card-wired", NULL))
boarddata->cd_type = ESDHC_CD_PERMANENT;
if (of_get_property(np, "fsl,cd-controller", NULL))
boarddata->cd_type = ESDHC_CD_CONTROLLER;
if (of_get_property(np, "fsl,wp-controller", NULL))
boarddata->wp_type = ESDHC_WP_CONTROLLER;
boarddata->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
if (gpio_is_valid(boarddata->cd_gpio))
boarddata->cd_type = ESDHC_CD_GPIO;
boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
if (gpio_is_valid(boarddata->wp_gpio))
boarddata->wp_type = ESDHC_WP_GPIO;
return 0;
}
#else
static inline int
sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
struct esdhc_platform_data *boarddata)
{
return -ENODEV;
}
#endif
static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
{ {
const struct of_device_id *of_id =
of_match_device(imx_esdhc_dt_ids, &pdev->dev);
struct sdhci_pltfm_host *pltfm_host; struct sdhci_pltfm_host *pltfm_host;
struct sdhci_host *host; struct sdhci_host *host;
struct esdhc_platform_data *boarddata; struct esdhc_platform_data *boarddata;
...@@ -306,9 +358,13 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) ...@@ -306,9 +358,13 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
pltfm_host = sdhci_priv(host); pltfm_host = sdhci_priv(host);
imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL); imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
if (!imx_data) if (!imx_data) {
return -ENOMEM; err = -ENOMEM;
goto err_imx_data;
}
if (of_id)
pdev->id_entry = of_id->data;
imx_data->devtype = pdev->id_entry->driver_data; imx_data->devtype = pdev->id_entry->driver_data;
pltfm_host->priv = imx_data; pltfm_host->priv = imx_data;
...@@ -331,14 +387,16 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) ...@@ -331,14 +387,16 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (is_imx53_esdhc(imx_data)) if (is_imx53_esdhc(imx_data))
imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT; imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
if (!host->mmc->parent->platform_data) {
dev_err(mmc_dev(host->mmc), "no board data!\n");
err = -EINVAL;
goto no_board_data;
}
imx_data->boarddata = *((struct esdhc_platform_data *)
host->mmc->parent->platform_data);
boarddata = &imx_data->boarddata; boarddata = &imx_data->boarddata;
if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
if (!host->mmc->parent->platform_data) {
dev_err(mmc_dev(host->mmc), "no board data!\n");
err = -EINVAL;
goto no_board_data;
}
imx_data->boarddata = *((struct esdhc_platform_data *)
host->mmc->parent->platform_data);
}
/* write_protect */ /* write_protect */
if (boarddata->wp_type == ESDHC_WP_GPIO) { if (boarddata->wp_type == ESDHC_WP_GPIO) {
...@@ -407,6 +465,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) ...@@ -407,6 +465,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
clk_put(pltfm_host->clk); clk_put(pltfm_host->clk);
err_clk_get: err_clk_get:
kfree(imx_data); kfree(imx_data);
err_imx_data:
sdhci_pltfm_free(pdev); sdhci_pltfm_free(pdev);
return err; return err;
} }
...@@ -442,6 +501,7 @@ static struct platform_driver sdhci_esdhc_imx_driver = { ...@@ -442,6 +501,7 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
.driver = { .driver = {
.name = "sdhci-esdhc-imx", .name = "sdhci-esdhc-imx",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = imx_esdhc_dt_ids,
}, },
.id_table = imx_esdhc_devtype, .id_table = imx_esdhc_devtype,
.probe = sdhci_esdhc_imx_probe, .probe = sdhci_esdhc_imx_probe,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册