From 46856a68dcb5f67c779d211fd6bcb5d7a2a7f19b Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Mon, 12 Mar 2012 20:32:37 +0530 Subject: [PATCH] mmc: omap_hsmmc: Convert hsmmc driver to use device tree Define dt bindings for the ti-omap-hsmmc, and adapt the driver to extract data (which was earlier passed as platform_data) from device tree. Signed-off-by: Rajendra Nayak Acked-by: Rob Herring Signed-off-by: Chris Ball --- .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 33 +++++++++ drivers/mmc/host/omap_hsmmc.c | 73 +++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt new file mode 100644 index 000000000000..dbd4368ab8cc --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt @@ -0,0 +1,33 @@ +* TI Highspeed MMC host controller for OMAP + +The Highspeed MMC Host Controller on TI OMAP family +provides an interface for MMC, SD, and SDIO types of memory cards. + +Required properties: +- compatible: + Should be "ti,omap2-hsmmc", for OMAP2 controllers + Should be "ti,omap3-hsmmc", for OMAP3 controllers + Should be "ti,omap4-hsmmc", for OMAP4 controllers +- ti,hwmods: Must be "mmc", n is controller instance starting 1 +- reg : should contain hsmmc registers location and length + +Optional properties: +ti,dual-volt: boolean, supports dual voltage cards +-supply: phandle to the regulator device tree node +"supply-name" examples are "vmmc", "vmmc_aux" etc +ti,bus-width: Number of data lines, default assumed is 1 if the property is missing. +cd-gpios: GPIOs for card detection +wp-gpios: GPIOs for write protection +ti,non-removable: non-removable slot (like eMMC) +ti,needs-special-reset: Requires a special softreset sequence + +Example: + mmc1: mmc@0x4809c000 { + compatible = "ti,omap4-hsmmc"; + reg = <0x4809c000 0x400>; + ti,hwmods = "mmc1"; + ti,dual-volt; + ti,bus-width = <4>; + vmmc-supply = <&vmmc>; /* phandle to regulator node */ + ti,non-removable; + }; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 0306aea329d4..e0808d4a7681 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -1710,6 +1713,65 @@ static void omap_hsmmc_debugfs(struct mmc_host *mmc) #endif +#ifdef CONFIG_OF +static u16 omap4_reg_offset = 0x100; + +static const struct of_device_id omap_mmc_of_match[] = { + { + .compatible = "ti,omap2-hsmmc", + }, + { + .compatible = "ti,omap3-hsmmc", + }, + { + .compatible = "ti,omap4-hsmmc", + .data = &omap4_reg_offset, + }, + {}, +} +MODULE_DEVICE_TABLE(of, omap_mmc_of_match); + +static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev) +{ + struct omap_mmc_platform_data *pdata; + struct device_node *np = dev->of_node; + u32 bus_width; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; /* out of memory */ + + if (of_find_property(np, "ti,dual-volt", NULL)) + pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT; + + /* This driver only supports 1 slot */ + pdata->nr_slots = 1; + pdata->slots[0].switch_pin = of_get_named_gpio(np, "cd-gpios", 0); + pdata->slots[0].gpio_wp = of_get_named_gpio(np, "wp-gpios", 0); + + if (of_find_property(np, "ti,non-removable", NULL)) { + pdata->slots[0].nonremovable = true; + pdata->slots[0].no_regulator_off_init = true; + } + of_property_read_u32(np, "ti,bus-width", &bus_width); + if (bus_width == 4) + pdata->slots[0].caps |= MMC_CAP_4_BIT_DATA; + else if (bus_width == 8) + pdata->slots[0].caps |= MMC_CAP_8_BIT_DATA; + + if (of_find_property(np, "ti,needs-special-reset", NULL)) + pdata->slots[0].features |= HSMMC_HAS_UPDATED_RESET; + + return pdata; +} +#else +static inline struct omap_mmc_platform_data + *of_get_hsmmc_pdata(struct device *dev) +{ + return NULL; +} +#endif + static int __init omap_hsmmc_probe(struct platform_device *pdev) { struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; @@ -1717,6 +1779,16 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) struct omap_hsmmc_host *host = NULL; struct resource *res; int ret, irq; + const struct of_device_id *match; + + match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev); + if (match) { + pdata = of_get_hsmmc_pdata(&pdev->dev); + if (match->data) { + u16 *offsetp = match->data; + pdata->reg_offset = *offsetp; + } + } if (pdata == NULL) { dev_err(&pdev->dev, "Platform Data is missing\n"); @@ -2122,6 +2194,7 @@ static struct platform_driver omap_hsmmc_driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, .pm = &omap_hsmmc_dev_pm_ops, + .of_match_table = of_match_ptr(omap_mmc_of_match), }, }; -- 2.20.1