diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/at91_mci.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c index cc0546998367..9a6251a7815d 100644 --- a/drivers/mmc/at91_mci.c +++ b/drivers/mmc/at91_mci.c | |||
@@ -101,6 +101,7 @@ struct at91mci_host | |||
101 | struct mmc_request *request; | 101 | struct mmc_request *request; |
102 | 102 | ||
103 | void __iomem *baseaddr; | 103 | void __iomem *baseaddr; |
104 | int irq; | ||
104 | 105 | ||
105 | struct at91_mmc_data *board; | 106 | struct at91_mmc_data *board; |
106 | int present; | 107 | int present; |
@@ -792,13 +793,22 @@ static int at91_mci_probe(struct platform_device *pdev) | |||
792 | { | 793 | { |
793 | struct mmc_host *mmc; | 794 | struct mmc_host *mmc; |
794 | struct at91mci_host *host; | 795 | struct at91mci_host *host; |
796 | struct resource *res; | ||
795 | int ret; | 797 | int ret; |
796 | 798 | ||
797 | pr_debug("Probe MCI devices\n"); | 799 | pr_debug("Probe MCI devices\n"); |
798 | 800 | ||
801 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
802 | if (!res) | ||
803 | return -ENXIO; | ||
804 | |||
805 | if (!request_mem_region(res->start, res->end - res->start + 1, DRIVER_NAME)) | ||
806 | return -EBUSY; | ||
807 | |||
799 | mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev); | 808 | mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev); |
800 | if (!mmc) { | 809 | if (!mmc) { |
801 | pr_debug("Failed to allocate mmc host\n"); | 810 | pr_debug("Failed to allocate mmc host\n"); |
811 | release_mem_region(res->start, res->end - res->start + 1); | ||
802 | return -ENOMEM; | 812 | return -ENOMEM; |
803 | } | 813 | } |
804 | 814 | ||
@@ -828,27 +838,40 @@ static int at91_mci_probe(struct platform_device *pdev) | |||
828 | if (IS_ERR(mci_clk)) { | 838 | if (IS_ERR(mci_clk)) { |
829 | printk(KERN_ERR "AT91 MMC: no clock defined.\n"); | 839 | printk(KERN_ERR "AT91 MMC: no clock defined.\n"); |
830 | mmc_free_host(mmc); | 840 | mmc_free_host(mmc); |
841 | release_mem_region(res->start, res->end - res->start + 1); | ||
831 | return -ENODEV; | 842 | return -ENODEV; |
832 | } | 843 | } |
833 | clk_enable(mci_clk); /* Enable the peripheral clock */ | ||
834 | 844 | ||
835 | host->baseaddr = (void __iomem *)AT91_VA_BASE_MCI; | 845 | /* |
846 | * Map I/O region | ||
847 | */ | ||
848 | host->baseaddr = ioremap(res->start, res->end - res->start + 1); | ||
849 | if (!host->baseaddr) { | ||
850 | clk_put(mci_clk); | ||
851 | mmc_free_host(mmc); | ||
852 | release_mem_region(res->start, res->end - res->start + 1); | ||
853 | return -ENOMEM; | ||
854 | } | ||
836 | 855 | ||
837 | /* | 856 | /* |
838 | * Reset hardware | 857 | * Reset hardware |
839 | */ | 858 | */ |
859 | clk_enable(mci_clk); /* Enable the peripheral clock */ | ||
840 | at91_mci_disable(host); | 860 | at91_mci_disable(host); |
841 | at91_mci_enable(host); | 861 | at91_mci_enable(host); |
842 | 862 | ||
843 | /* | 863 | /* |
844 | * Allocate the MCI interrupt | 864 | * Allocate the MCI interrupt |
845 | */ | 865 | */ |
846 | ret = request_irq(AT91RM9200_ID_MCI, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host); | 866 | host->irq = platform_get_irq(pdev, 0); |
867 | ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host); | ||
847 | if (ret) { | 868 | if (ret) { |
848 | printk(KERN_ERR "Failed to request MCI interrupt\n"); | 869 | printk(KERN_ERR "Failed to request MCI interrupt\n"); |
849 | clk_disable(mci_clk); | 870 | clk_disable(mci_clk); |
850 | clk_put(mci_clk); | 871 | clk_put(mci_clk); |
851 | mmc_free_host(mmc); | 872 | mmc_free_host(mmc); |
873 | iounmap(host->baseaddr); | ||
874 | release_mem_region(res->start, res->end - res->start + 1); | ||
852 | return ret; | 875 | return ret; |
853 | } | 876 | } |
854 | 877 | ||
@@ -886,6 +909,7 @@ static int at91_mci_remove(struct platform_device *pdev) | |||
886 | { | 909 | { |
887 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 910 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
888 | struct at91mci_host *host; | 911 | struct at91mci_host *host; |
912 | struct resource *res; | ||
889 | 913 | ||
890 | if (!mmc) | 914 | if (!mmc) |
891 | return -1; | 915 | return -1; |
@@ -897,16 +921,19 @@ static int at91_mci_remove(struct platform_device *pdev) | |||
897 | cancel_delayed_work(&host->mmc->detect); | 921 | cancel_delayed_work(&host->mmc->detect); |
898 | } | 922 | } |
899 | 923 | ||
900 | mmc_remove_host(mmc); | ||
901 | at91_mci_disable(host); | 924 | at91_mci_disable(host); |
902 | free_irq(AT91RM9200_ID_MCI, host); | 925 | mmc_remove_host(mmc); |
903 | mmc_free_host(mmc); | 926 | free_irq(host->irq, host); |
904 | 927 | ||
905 | clk_disable(mci_clk); /* Disable the peripheral clock */ | 928 | clk_disable(mci_clk); /* Disable the peripheral clock */ |
906 | clk_put(mci_clk); | 929 | clk_put(mci_clk); |
907 | 930 | ||
908 | platform_set_drvdata(pdev, NULL); | 931 | iounmap(host->baseaddr); |
932 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
933 | release_mem_region(res->start, res->end - res->start + 1); | ||
909 | 934 | ||
935 | mmc_free_host(mmc); | ||
936 | platform_set_drvdata(pdev, NULL); | ||
910 | pr_debug("MCI Removed\n"); | 937 | pr_debug("MCI Removed\n"); |
911 | 938 | ||
912 | return 0; | 939 | return 0; |