aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/atmel-mci.c
diff options
context:
space:
mode:
authorLudovic Desroches <ludovic.desroches@atmel.com>2012-07-24 09:30:03 -0400
committerChris Ball <cjb@laptop.org>2012-09-04 13:58:14 -0400
commite919fd200033e80b26f152d22c00a8fae7f8d548 (patch)
tree09cf3583765d3acefe8a09b948c4827da928e9c6 /drivers/mmc/host/atmel-mci.c
parent77dcb3f4c344d4c9619803848f1aba4d271dac7b (diff)
mmc: atmel-mci: add device tree support
Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com> Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host/atmel-mci.c')
-rw-r--r--drivers/mmc/host/atmel-mci.c85
1 files changed, 83 insertions, 2 deletions
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index a53c7c478e05..8c72828239b2 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -19,6 +19,9 @@
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/ioport.h> 20#include <linux/ioport.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/of.h>
23#include <linux/of_device.h>
24#include <linux/of_gpio.h>
22#include <linux/platform_device.h> 25#include <linux/platform_device.h>
23#include <linux/scatterlist.h> 26#include <linux/scatterlist.h>
24#include <linux/seq_file.h> 27#include <linux/seq_file.h>
@@ -500,6 +503,70 @@ err:
500 dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); 503 dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n");
501} 504}
502 505
506#if defined(CONFIG_OF)
507static const struct of_device_id atmci_dt_ids[] = {
508 { .compatible = "atmel,hsmci" },
509 { /* sentinel */ }
510};
511
512MODULE_DEVICE_TABLE(of, atmci_dt_ids);
513
514static struct mci_platform_data __devinit*
515atmci_of_init(struct platform_device *pdev)
516{
517 struct device_node *np = pdev->dev.of_node;
518 struct device_node *cnp;
519 struct mci_platform_data *pdata;
520 u32 slot_id;
521
522 if (!np) {
523 dev_err(&pdev->dev, "device node not found\n");
524 return ERR_PTR(-EINVAL);
525 }
526
527 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
528 if (!pdata) {
529 dev_err(&pdev->dev, "could not allocate memory for pdata\n");
530 return ERR_PTR(-ENOMEM);
531 }
532
533 for_each_child_of_node(np, cnp) {
534 if (of_property_read_u32(cnp, "reg", &slot_id)) {
535 dev_warn(&pdev->dev, "reg property is missing for %s\n",
536 cnp->full_name);
537 continue;
538 }
539
540 if (slot_id >= ATMCI_MAX_NR_SLOTS) {
541 dev_warn(&pdev->dev, "can't have more than %d slots\n",
542 ATMCI_MAX_NR_SLOTS);
543 break;
544 }
545
546 if (of_property_read_u32(cnp, "bus-width",
547 &pdata->slot[slot_id].bus_width))
548 pdata->slot[slot_id].bus_width = 1;
549
550 pdata->slot[slot_id].detect_pin =
551 of_get_named_gpio(cnp, "cd-gpios", 0);
552
553 pdata->slot[slot_id].detect_is_active_high =
554 of_property_read_bool(cnp, "cd-inverted");
555
556 pdata->slot[slot_id].wp_pin =
557 of_get_named_gpio(cnp, "wp-gpios", 0);
558 }
559
560 return pdata;
561}
562#else /* CONFIG_OF */
563static inline struct mci_platform_data*
564atmci_of_init(struct platform_device *dev)
565{
566 return ERR_PTR(-EINVAL);
567}
568#endif
569
503static inline unsigned int atmci_get_version(struct atmel_mci *host) 570static inline unsigned int atmci_get_version(struct atmel_mci *host)
504{ 571{
505 return atmci_readl(host, ATMCI_VERSION) & 0x00000fff; 572 return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
@@ -2046,6 +2113,13 @@ static int __init atmci_init_slot(struct atmel_mci *host,
2046 slot->sdc_reg = sdc_reg; 2113 slot->sdc_reg = sdc_reg;
2047 slot->sdio_irq = sdio_irq; 2114 slot->sdio_irq = sdio_irq;
2048 2115
2116 dev_dbg(&mmc->class_dev,
2117 "slot[%u]: bus_width=%u, detect_pin=%d, "
2118 "detect_is_active_high=%s, wp_pin=%d\n",
2119 id, slot_data->bus_width, slot_data->detect_pin,
2120 slot_data->detect_is_active_high ? "true" : "false",
2121 slot_data->wp_pin);
2122
2049 mmc->ops = &atmci_ops; 2123 mmc->ops = &atmci_ops;
2050 mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); 2124 mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512);
2051 mmc->f_max = host->bus_hz / 2; 2125 mmc->f_max = host->bus_hz / 2;
@@ -2268,8 +2342,14 @@ static int __init atmci_probe(struct platform_device *pdev)
2268 if (!regs) 2342 if (!regs)
2269 return -ENXIO; 2343 return -ENXIO;
2270 pdata = pdev->dev.platform_data; 2344 pdata = pdev->dev.platform_data;
2271 if (!pdata) 2345 if (!pdata) {
2272 return -ENXIO; 2346 pdata = atmci_of_init(pdev);
2347 if (IS_ERR(pdata)) {
2348 dev_err(&pdev->dev, "platform data not available\n");
2349 return PTR_ERR(pdata);
2350 }
2351 }
2352
2273 irq = platform_get_irq(pdev, 0); 2353 irq = platform_get_irq(pdev, 0);
2274 if (irq < 0) 2354 if (irq < 0)
2275 return irq; 2355 return irq;
@@ -2487,6 +2567,7 @@ static struct platform_driver atmci_driver = {
2487 .driver = { 2567 .driver = {
2488 .name = "atmel_mci", 2568 .name = "atmel_mci",
2489 .pm = ATMCI_PM_OPS, 2569 .pm = ATMCI_PM_OPS,
2570 .of_match_table = of_match_ptr(atmci_dt_ids),
2490 }, 2571 },
2491}; 2572};
2492 2573