diff options
author | Daniel Mack <daniel@zonque.org> | 2018-07-03 16:10:26 -0400 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2018-07-16 05:21:45 -0400 |
commit | 38a8dda908683c30bcabe7e03a3418aaf2022f5f (patch) | |
tree | f2dab04f77d62faa801da213cba7f154b9b125e1 /drivers/mmc | |
parent | 61951fd6cb49593c57da22b780ab9114060032d4 (diff) |
mmc: pxamci: make GPIO lookups from pdata optional
A recent commit introduced a call to mmc_of_parse() and removed the
explicit assignment of GPIOs in the pdata structure. This will leave
them set to 0, which is a valid GPIO per se, so the code that looks
at these members will try to allocate them and fail.
To fix this properly, make the following changes:
a) Refrain from allocating and assiging a pdata struct from
pxamci_of_init(). It's a hack to do it this way anyway.
Instead, move the only remaining member of interest in
'struct pxamci_host' and assign the value from either
the passed in pdata pointer or with the value read from DT.
b) Let the only user of 'detect_delay_ms' look at the member of
'struct pxamci_host', not the pdata.
c) Make more code in pxamci_probe() dependent on the presence of
actual pdata.
This will also ease the removal of pdata one day.
Signed-off-by: Daniel Mack <daniel@zonque.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/pxamci.c | 92 |
1 files changed, 47 insertions, 45 deletions
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index ed576809fae8..f1297080d0e0 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
@@ -62,6 +62,7 @@ struct pxamci_host { | |||
62 | unsigned int cmdat; | 62 | unsigned int cmdat; |
63 | unsigned int imask; | 63 | unsigned int imask; |
64 | unsigned int power_mode; | 64 | unsigned int power_mode; |
65 | unsigned long detect_delay_ms; | ||
65 | struct pxamci_platform_data *pdata; | 66 | struct pxamci_platform_data *pdata; |
66 | 67 | ||
67 | struct mmc_request *mrq; | 68 | struct mmc_request *mrq; |
@@ -567,7 +568,7 @@ static irqreturn_t pxamci_detect_irq(int irq, void *devid) | |||
567 | { | 568 | { |
568 | struct pxamci_host *host = mmc_priv(devid); | 569 | struct pxamci_host *host = mmc_priv(devid); |
569 | 570 | ||
570 | mmc_detect_change(devid, msecs_to_jiffies(host->pdata->detect_delay_ms)); | 571 | mmc_detect_change(devid, msecs_to_jiffies(host->detect_delay_ms)); |
571 | return IRQ_HANDLED; | 572 | return IRQ_HANDLED; |
572 | } | 573 | } |
573 | 574 | ||
@@ -583,27 +584,21 @@ static int pxamci_of_init(struct platform_device *pdev, | |||
583 | struct mmc_host *mmc) | 584 | struct mmc_host *mmc) |
584 | { | 585 | { |
585 | struct device_node *np = pdev->dev.of_node; | 586 | struct device_node *np = pdev->dev.of_node; |
586 | struct pxamci_platform_data *pdata; | 587 | struct pxamci_host *host = mmc_priv(mmc); |
587 | u32 tmp; | 588 | u32 tmp; |
588 | int ret; | 589 | int ret; |
589 | 590 | ||
590 | if (!np) | 591 | if (!np) |
591 | return 0; | 592 | return 0; |
592 | 593 | ||
593 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
594 | if (!pdata) | ||
595 | return -ENOMEM; | ||
596 | |||
597 | /* pxa-mmc specific */ | 594 | /* pxa-mmc specific */ |
598 | if (of_property_read_u32(np, "pxa-mmc,detect-delay-ms", &tmp) == 0) | 595 | if (of_property_read_u32(np, "pxa-mmc,detect-delay-ms", &tmp) == 0) |
599 | pdata->detect_delay_ms = tmp; | 596 | host->detect_delay_ms = tmp; |
600 | 597 | ||
601 | ret = mmc_of_parse(mmc); | 598 | ret = mmc_of_parse(mmc); |
602 | if (ret < 0) | 599 | if (ret < 0) |
603 | return ret; | 600 | return ret; |
604 | 601 | ||
605 | pdev->dev.platform_data = pdata; | ||
606 | |||
607 | return 0; | 602 | return 0; |
608 | } | 603 | } |
609 | #else | 604 | #else |
@@ -619,7 +614,7 @@ static int pxamci_probe(struct platform_device *pdev) | |||
619 | struct mmc_host *mmc; | 614 | struct mmc_host *mmc; |
620 | struct pxamci_host *host = NULL; | 615 | struct pxamci_host *host = NULL; |
621 | struct resource *r; | 616 | struct resource *r; |
622 | int ret, irq, gpio_cd = -1, gpio_ro = -1, gpio_power = -1; | 617 | int ret, irq; |
623 | 618 | ||
624 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 619 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
625 | irq = platform_get_irq(pdev, 0); | 620 | irq = platform_get_irq(pdev, 0); |
@@ -734,47 +729,54 @@ static int pxamci_probe(struct platform_device *pdev) | |||
734 | } | 729 | } |
735 | 730 | ||
736 | if (host->pdata) { | 731 | if (host->pdata) { |
737 | gpio_cd = host->pdata->gpio_card_detect; | 732 | int gpio_cd = host->pdata->gpio_card_detect; |
738 | gpio_ro = host->pdata->gpio_card_ro; | 733 | int gpio_ro = host->pdata->gpio_card_ro; |
739 | gpio_power = host->pdata->gpio_power; | 734 | int gpio_power = host->pdata->gpio_power; |
740 | } | 735 | |
741 | if (gpio_is_valid(gpio_power)) { | 736 | host->detect_delay_ms = host->pdata->detect_delay_ms; |
742 | ret = devm_gpio_request(&pdev->dev, gpio_power, | 737 | |
743 | "mmc card power"); | 738 | if (gpio_is_valid(gpio_power)) { |
744 | if (ret) { | 739 | ret = devm_gpio_request(&pdev->dev, gpio_power, |
745 | dev_err(&pdev->dev, "Failed requesting gpio_power %d\n", | 740 | "mmc card power"); |
746 | gpio_power); | 741 | if (ret) { |
747 | goto out; | 742 | dev_err(&pdev->dev, |
743 | "Failed requesting gpio_power %d\n", | ||
744 | gpio_power); | ||
745 | goto out; | ||
746 | } | ||
747 | gpio_direction_output(gpio_power, | ||
748 | host->pdata->gpio_power_invert); | ||
748 | } | 749 | } |
749 | gpio_direction_output(gpio_power, | 750 | |
750 | host->pdata->gpio_power_invert); | 751 | if (gpio_is_valid(gpio_ro)) { |
751 | } | 752 | ret = mmc_gpio_request_ro(mmc, gpio_ro); |
752 | if (gpio_is_valid(gpio_ro)) { | 753 | if (ret) { |
753 | ret = mmc_gpio_request_ro(mmc, gpio_ro); | 754 | dev_err(&pdev->dev, |
755 | "Failed requesting gpio_ro %d\n", | ||
756 | gpio_ro); | ||
757 | goto out; | ||
758 | } else { | ||
759 | mmc->caps2 |= host->pdata->gpio_card_ro_invert ? | ||
760 | 0 : MMC_CAP2_RO_ACTIVE_HIGH; | ||
761 | } | ||
762 | } | ||
763 | |||
764 | if (gpio_is_valid(gpio_cd)) | ||
765 | ret = mmc_gpio_request_cd(mmc, gpio_cd, 0); | ||
754 | if (ret) { | 766 | if (ret) { |
755 | dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n", | 767 | dev_err(&pdev->dev, "Failed requesting gpio_cd %d\n", |
756 | gpio_ro); | 768 | gpio_cd); |
757 | goto out; | 769 | goto out; |
758 | } else { | ||
759 | mmc->caps2 |= host->pdata->gpio_card_ro_invert ? | ||
760 | 0 : MMC_CAP2_RO_ACTIVE_HIGH; | ||
761 | } | 770 | } |
762 | } | ||
763 | 771 | ||
764 | if (gpio_is_valid(gpio_cd)) | 772 | if (host->pdata->init) |
765 | ret = mmc_gpio_request_cd(mmc, gpio_cd, 0); | 773 | host->pdata->init(&pdev->dev, pxamci_detect_irq, mmc); |
766 | if (ret) { | ||
767 | dev_err(&pdev->dev, "Failed requesting gpio_cd %d\n", gpio_cd); | ||
768 | goto out; | ||
769 | } | ||
770 | 774 | ||
771 | if (host->pdata && host->pdata->init) | 775 | if (gpio_is_valid(gpio_power) && host->pdata->setpower) |
772 | host->pdata->init(&pdev->dev, pxamci_detect_irq, mmc); | 776 | dev_warn(&pdev->dev, "gpio_power and setpower() both defined\n"); |
773 | 777 | if (gpio_is_valid(gpio_ro) && host->pdata->get_ro) | |
774 | if (gpio_is_valid(gpio_power) && host->pdata->setpower) | 778 | dev_warn(&pdev->dev, "gpio_ro and get_ro() both defined\n"); |
775 | dev_warn(&pdev->dev, "gpio_power and setpower() both defined\n"); | 779 | } |
776 | if (gpio_is_valid(gpio_ro) && host->pdata->get_ro) | ||
777 | dev_warn(&pdev->dev, "gpio_ro and get_ro() both defined\n"); | ||
778 | 780 | ||
779 | mmc_add_host(mmc); | 781 | mmc_add_host(mmc); |
780 | 782 | ||