Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

The patch adds device tree probe support for sdhci-esdhc-imx driver.

Signed-off-by: Shawn 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: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Chris Ball <cjb@laptop.org>

Shawn Guo abfafc2d a4d2177f

+103 -9
+34
Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
··· 1 + * Freescale Enhanced Secure Digital Host Controller (eSDHC) for i.MX 2 + 3 + The Enhanced Secure Digital Host Controller on Freescale i.MX family 4 + provides an interface for MMC, SD, and SDIO types of memory cards. 5 + 6 + Required properties: 7 + - compatible : Should be "fsl,<chip>-esdhc" 8 + - reg : Should contain eSDHC registers location and length 9 + - interrupts : Should contain eSDHC interrupt 10 + 11 + Optional properties: 12 + - fsl,card-wired : Indicate the card is wired to host permanently 13 + - fsl,cd-internal : Indicate to use controller internal card detection 14 + - fsl,wp-internal : Indicate to use controller internal write protection 15 + - cd-gpios : Specify GPIOs for card detection 16 + - wp-gpios : Specify GPIOs for write protection 17 + 18 + Examples: 19 + 20 + esdhc@70004000 { 21 + compatible = "fsl,imx51-esdhc"; 22 + reg = <0x70004000 0x4000>; 23 + interrupts = <1>; 24 + fsl,cd-internal; 25 + fsl,wp-internal; 26 + }; 27 + 28 + esdhc@70008000 { 29 + compatible = "fsl,imx51-esdhc"; 30 + reg = <0x70008000 0x4000>; 31 + interrupts = <2>; 32 + cd-gpios = <&gpio0 6 0>; /* GPIO1_6 */ 33 + wp-gpios = <&gpio0 5 0>; /* GPIO1_5 */ 34 + };
+69 -9
drivers/mmc/host/sdhci-esdhc-imx.c
··· 20 20 #include <linux/mmc/host.h> 21 21 #include <linux/mmc/mmc.h> 22 22 #include <linux/mmc/sdio.h> 23 + #include <linux/of.h> 24 + #include <linux/of_device.h> 25 + #include <linux/of_gpio.h> 23 26 #include <mach/esdhc.h> 24 27 #include "sdhci-pltfm.h" 25 28 #include "sdhci-esdhc.h" ··· 76 73 } 77 74 }; 78 75 MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype); 76 + 77 + static const struct of_device_id imx_esdhc_dt_ids[] = { 78 + { .compatible = "fsl,imx25-esdhc", .data = &imx_esdhc_devtype[IMX25_ESDHC], }, 79 + { .compatible = "fsl,imx35-esdhc", .data = &imx_esdhc_devtype[IMX35_ESDHC], }, 80 + { .compatible = "fsl,imx51-esdhc", .data = &imx_esdhc_devtype[IMX51_ESDHC], }, 81 + { .compatible = "fsl,imx53-esdhc", .data = &imx_esdhc_devtype[IMX53_ESDHC], }, 82 + { /* sentinel */ } 83 + }; 84 + MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids); 79 85 80 86 static inline int is_imx25_esdhc(struct pltfm_imx_data *data) 81 87 { ··· 302 290 return IRQ_HANDLED; 303 291 }; 304 292 293 + #ifdef CONFIG_OF 294 + static int __devinit 295 + sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, 296 + struct esdhc_platform_data *boarddata) 297 + { 298 + struct device_node *np = pdev->dev.of_node; 299 + 300 + if (!np) 301 + return -ENODEV; 302 + 303 + if (of_get_property(np, "fsl,card-wired", NULL)) 304 + boarddata->cd_type = ESDHC_CD_PERMANENT; 305 + 306 + if (of_get_property(np, "fsl,cd-controller", NULL)) 307 + boarddata->cd_type = ESDHC_CD_CONTROLLER; 308 + 309 + if (of_get_property(np, "fsl,wp-controller", NULL)) 310 + boarddata->wp_type = ESDHC_WP_CONTROLLER; 311 + 312 + boarddata->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); 313 + if (gpio_is_valid(boarddata->cd_gpio)) 314 + boarddata->cd_type = ESDHC_CD_GPIO; 315 + 316 + boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); 317 + if (gpio_is_valid(boarddata->wp_gpio)) 318 + boarddata->wp_type = ESDHC_WP_GPIO; 319 + 320 + return 0; 321 + } 322 + #else 323 + static inline int 324 + sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, 325 + struct esdhc_platform_data *boarddata) 326 + { 327 + return -ENODEV; 328 + } 329 + #endif 330 + 305 331 static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) 306 332 { 333 + const struct of_device_id *of_id = 334 + of_match_device(imx_esdhc_dt_ids, &pdev->dev); 307 335 struct sdhci_pltfm_host *pltfm_host; 308 336 struct sdhci_host *host; 309 337 struct esdhc_platform_data *boarddata; ··· 358 306 pltfm_host = sdhci_priv(host); 359 307 360 308 imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL); 361 - if (!imx_data) 362 - return -ENOMEM; 309 + if (!imx_data) { 310 + err = -ENOMEM; 311 + goto err_imx_data; 312 + } 363 313 314 + if (of_id) 315 + pdev->id_entry = of_id->data; 364 316 imx_data->devtype = pdev->id_entry->driver_data; 365 317 pltfm_host->priv = imx_data; 366 318 ··· 387 331 if (is_imx53_esdhc(imx_data)) 388 332 imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT; 389 333 390 - if (!host->mmc->parent->platform_data) { 391 - dev_err(mmc_dev(host->mmc), "no board data!\n"); 392 - err = -EINVAL; 393 - goto no_board_data; 394 - } 395 - imx_data->boarddata = *((struct esdhc_platform_data *) 396 - host->mmc->parent->platform_data); 397 334 boarddata = &imx_data->boarddata; 335 + if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) { 336 + if (!host->mmc->parent->platform_data) { 337 + dev_err(mmc_dev(host->mmc), "no board data!\n"); 338 + err = -EINVAL; 339 + goto no_board_data; 340 + } 341 + imx_data->boarddata = *((struct esdhc_platform_data *) 342 + host->mmc->parent->platform_data); 343 + } 398 344 399 345 /* write_protect */ 400 346 if (boarddata->wp_type == ESDHC_WP_GPIO) { ··· 465 407 clk_put(pltfm_host->clk); 466 408 err_clk_get: 467 409 kfree(imx_data); 410 + err_imx_data: 468 411 sdhci_pltfm_free(pdev); 469 412 return err; 470 413 } ··· 501 442 .driver = { 502 443 .name = "sdhci-esdhc-imx", 503 444 .owner = THIS_MODULE, 445 + .of_match_table = imx_esdhc_dt_ids, 504 446 }, 505 447 .id_table = imx_esdhc_devtype, 506 448 .probe = sdhci_esdhc_imx_probe,