diff options
| -rw-r--r-- | drivers/mmc/host/at91_mci.c | 114 |
1 files changed, 80 insertions, 34 deletions
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index b1edcefdd4f9..21acecc9fe3a 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c | |||
| @@ -70,10 +70,11 @@ | |||
| 70 | 70 | ||
| 71 | #include <asm/io.h> | 71 | #include <asm/io.h> |
| 72 | #include <asm/irq.h> | 72 | #include <asm/irq.h> |
| 73 | #include <asm/gpio.h> | ||
| 74 | |||
| 73 | #include <asm/mach/mmc.h> | 75 | #include <asm/mach/mmc.h> |
| 74 | #include <asm/arch/board.h> | 76 | #include <asm/arch/board.h> |
| 75 | #include <asm/arch/cpu.h> | 77 | #include <asm/arch/cpu.h> |
| 76 | #include <asm/arch/gpio.h> | ||
| 77 | #include <asm/arch/at91_mci.h> | 78 | #include <asm/arch/at91_mci.h> |
| 78 | 79 | ||
| 79 | #define DRIVER_NAME "at91_mci" | 80 | #define DRIVER_NAME "at91_mci" |
| @@ -659,11 +660,11 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 659 | if (host->board->vcc_pin) { | 660 | if (host->board->vcc_pin) { |
| 660 | switch (ios->power_mode) { | 661 | switch (ios->power_mode) { |
| 661 | case MMC_POWER_OFF: | 662 | case MMC_POWER_OFF: |
| 662 | at91_set_gpio_value(host->board->vcc_pin, 0); | 663 | gpio_set_value(host->board->vcc_pin, 0); |
| 663 | break; | 664 | break; |
| 664 | case MMC_POWER_UP: | 665 | case MMC_POWER_UP: |
| 665 | case MMC_POWER_ON: | 666 | case MMC_POWER_ON: |
| 666 | at91_set_gpio_value(host->board->vcc_pin, 1); | 667 | gpio_set_value(host->board->vcc_pin, 1); |
| 667 | break; | 668 | break; |
| 668 | } | 669 | } |
| 669 | } | 670 | } |
| @@ -768,7 +769,7 @@ static irqreturn_t at91_mci_irq(int irq, void *devid) | |||
| 768 | static irqreturn_t at91_mmc_det_irq(int irq, void *_host) | 769 | static irqreturn_t at91_mmc_det_irq(int irq, void *_host) |
| 769 | { | 770 | { |
| 770 | struct at91mci_host *host = _host; | 771 | struct at91mci_host *host = _host; |
| 771 | int present = !at91_get_gpio_value(irq); | 772 | int present = !gpio_get_value(irq_to_gpio(irq)); |
| 772 | 773 | ||
| 773 | /* | 774 | /* |
| 774 | * we expect this irq on both insert and remove, | 775 | * we expect this irq on both insert and remove, |
| @@ -793,7 +794,7 @@ static int at91_mci_get_ro(struct mmc_host *mmc) | |||
| 793 | struct at91mci_host *host = mmc_priv(mmc); | 794 | struct at91mci_host *host = mmc_priv(mmc); |
| 794 | 795 | ||
| 795 | if (host->board->wp_pin) { | 796 | if (host->board->wp_pin) { |
| 796 | read_only = at91_get_gpio_value(host->board->wp_pin); | 797 | read_only = gpio_get_value(host->board->wp_pin); |
| 797 | printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc), | 798 | printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc), |
| 798 | (read_only ? "read-only" : "read-write") ); | 799 | (read_only ? "read-only" : "read-write") ); |
| 799 | } | 800 | } |
| @@ -820,8 +821,6 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
| 820 | struct resource *res; | 821 | struct resource *res; |
| 821 | int ret; | 822 | int ret; |
| 822 | 823 | ||
| 823 | pr_debug("Probe MCI devices\n"); | ||
| 824 | |||
| 825 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 824 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 826 | if (!res) | 825 | if (!res) |
| 827 | return -ENXIO; | 826 | return -ENXIO; |
| @@ -831,9 +830,9 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
| 831 | 830 | ||
| 832 | mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev); | 831 | mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev); |
| 833 | if (!mmc) { | 832 | if (!mmc) { |
| 834 | pr_debug("Failed to allocate mmc host\n"); | 833 | ret = -ENOMEM; |
| 835 | release_mem_region(res->start, res->end - res->start + 1); | 834 | dev_dbg(&pdev->dev, "couldn't allocate mmc host\n"); |
| 836 | return -ENOMEM; | 835 | goto fail6; |
| 837 | } | 836 | } |
| 838 | 837 | ||
| 839 | mmc->ops = &at91_mci_ops; | 838 | mmc->ops = &at91_mci_ops; |
| @@ -853,19 +852,44 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
| 853 | if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) | 852 | if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) |
| 854 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 853 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
| 855 | else | 854 | else |
| 856 | printk("AT91 MMC: 4 wire bus mode not supported" | 855 | dev_warn(&pdev->dev, "4 wire bus mode not supported" |
| 857 | " - using 1 wire\n"); | 856 | " - using 1 wire\n"); |
| 858 | } | 857 | } |
| 859 | 858 | ||
| 860 | /* | 859 | /* |
| 860 | * Reserve GPIOs ... board init code makes sure these pins are set | ||
| 861 | * up as GPIOs with the right direction (input, except for vcc) | ||
| 862 | */ | ||
| 863 | if (host->board->det_pin) { | ||
| 864 | ret = gpio_request(host->board->det_pin, "mmc_detect"); | ||
| 865 | if (ret < 0) { | ||
| 866 | dev_dbg(&pdev->dev, "couldn't claim card detect pin\n"); | ||
| 867 | goto fail5; | ||
| 868 | } | ||
| 869 | } | ||
| 870 | if (host->board->wp_pin) { | ||
| 871 | ret = gpio_request(host->board->wp_pin, "mmc_wp"); | ||
| 872 | if (ret < 0) { | ||
| 873 | dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n"); | ||
| 874 | goto fail4; | ||
| 875 | } | ||
| 876 | } | ||
| 877 | if (host->board->vcc_pin) { | ||
| 878 | ret = gpio_request(host->board->vcc_pin, "mmc_vcc"); | ||
| 879 | if (ret < 0) { | ||
| 880 | dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n"); | ||
| 881 | goto fail3; | ||
| 882 | } | ||
| 883 | } | ||
| 884 | |||
| 885 | /* | ||
| 861 | * Get Clock | 886 | * Get Clock |
| 862 | */ | 887 | */ |
| 863 | host->mci_clk = clk_get(&pdev->dev, "mci_clk"); | 888 | host->mci_clk = clk_get(&pdev->dev, "mci_clk"); |
| 864 | if (IS_ERR(host->mci_clk)) { | 889 | if (IS_ERR(host->mci_clk)) { |
| 865 | printk(KERN_ERR "AT91 MMC: no clock defined.\n"); | 890 | ret = -ENODEV; |
| 866 | mmc_free_host(mmc); | 891 | dev_dbg(&pdev->dev, "no mci_clk?\n"); |
| 867 | release_mem_region(res->start, res->end - res->start + 1); | 892 | goto fail2; |
| 868 | return -ENODEV; | ||
| 869 | } | 893 | } |
| 870 | 894 | ||
| 871 | /* | 895 | /* |
| @@ -873,10 +897,8 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
| 873 | */ | 897 | */ |
| 874 | host->baseaddr = ioremap(res->start, res->end - res->start + 1); | 898 | host->baseaddr = ioremap(res->start, res->end - res->start + 1); |
| 875 | if (!host->baseaddr) { | 899 | if (!host->baseaddr) { |
| 876 | clk_put(host->mci_clk); | 900 | ret = -ENOMEM; |
| 877 | mmc_free_host(mmc); | 901 | goto fail1; |
| 878 | release_mem_region(res->start, res->end - res->start + 1); | ||
| 879 | return -ENOMEM; | ||
| 880 | } | 902 | } |
| 881 | 903 | ||
| 882 | /* | 904 | /* |
| @@ -890,15 +912,11 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
| 890 | * Allocate the MCI interrupt | 912 | * Allocate the MCI interrupt |
| 891 | */ | 913 | */ |
| 892 | host->irq = platform_get_irq(pdev, 0); | 914 | host->irq = platform_get_irq(pdev, 0); |
| 893 | ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host); | 915 | ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, |
| 916 | mmc_hostname(mmc), host); | ||
| 894 | if (ret) { | 917 | if (ret) { |
| 895 | printk(KERN_ERR "AT91 MMC: Failed to request MCI interrupt\n"); | 918 | dev_dbg(&pdev->dev, "request MCI interrupt failed\n"); |
| 896 | clk_disable(host->mci_clk); | 919 | goto fail0; |
| 897 | clk_put(host->mci_clk); | ||
| 898 | mmc_free_host(mmc); | ||
| 899 | iounmap(host->baseaddr); | ||
| 900 | release_mem_region(res->start, res->end - res->start + 1); | ||
| 901 | return ret; | ||
| 902 | } | 920 | } |
| 903 | 921 | ||
| 904 | platform_set_drvdata(pdev, mmc); | 922 | platform_set_drvdata(pdev, mmc); |
| @@ -907,8 +925,7 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
| 907 | * Add host to MMC layer | 925 | * Add host to MMC layer |
| 908 | */ | 926 | */ |
| 909 | if (host->board->det_pin) { | 927 | if (host->board->det_pin) { |
| 910 | host->present = !at91_get_gpio_value(host->board->det_pin); | 928 | host->present = !gpio_get_value(host->board->det_pin); |
| 911 | device_init_wakeup(&pdev->dev, 1); | ||
| 912 | } | 929 | } |
| 913 | else | 930 | else |
| 914 | host->present = -1; | 931 | host->present = -1; |
| @@ -919,15 +936,38 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
| 919 | * monitor card insertion/removal if we can | 936 | * monitor card insertion/removal if we can |
| 920 | */ | 937 | */ |
| 921 | if (host->board->det_pin) { | 938 | if (host->board->det_pin) { |
| 922 | ret = request_irq(host->board->det_pin, at91_mmc_det_irq, | 939 | ret = request_irq(gpio_to_irq(host->board->det_pin), |
| 923 | 0, DRIVER_NAME, host); | 940 | at91_mmc_det_irq, 0, mmc_hostname(mmc), host); |
| 924 | if (ret) | 941 | if (ret) |
| 925 | printk(KERN_ERR "AT91 MMC: Couldn't allocate MMC detect irq\n"); | 942 | dev_warn(&pdev->dev, "request MMC detect irq failed\n"); |
| 943 | else | ||
| 944 | device_init_wakeup(&pdev->dev, 1); | ||
| 926 | } | 945 | } |
| 927 | 946 | ||
| 928 | pr_debug("Added MCI driver\n"); | 947 | pr_debug("Added MCI driver\n"); |
| 929 | 948 | ||
| 930 | return 0; | 949 | return 0; |
| 950 | |||
| 951 | fail0: | ||
| 952 | clk_disable(host->mci_clk); | ||
| 953 | iounmap(host->baseaddr); | ||
| 954 | fail1: | ||
| 955 | clk_put(host->mci_clk); | ||
| 956 | fail2: | ||
| 957 | if (host->board->vcc_pin) | ||
| 958 | gpio_free(host->board->vcc_pin); | ||
| 959 | fail3: | ||
| 960 | if (host->board->wp_pin) | ||
| 961 | gpio_free(host->board->wp_pin); | ||
| 962 | fail4: | ||
| 963 | if (host->board->det_pin) | ||
| 964 | gpio_free(host->board->det_pin); | ||
| 965 | fail5: | ||
| 966 | mmc_free_host(mmc); | ||
| 967 | fail6: | ||
| 968 | release_mem_region(res->start, res->end - res->start + 1); | ||
| 969 | dev_err(&pdev->dev, "probe failed, err %d\n", ret); | ||
| 970 | return ret; | ||
| 931 | } | 971 | } |
| 932 | 972 | ||
| 933 | /* | 973 | /* |
| @@ -945,9 +985,10 @@ static int __exit at91_mci_remove(struct platform_device *pdev) | |||
| 945 | host = mmc_priv(mmc); | 985 | host = mmc_priv(mmc); |
| 946 | 986 | ||
| 947 | if (host->board->det_pin) { | 987 | if (host->board->det_pin) { |
| 988 | if (device_can_wakeup(&pdev->dev)) | ||
| 989 | free_irq(gpio_to_irq(host->board->det_pin), host); | ||
| 948 | device_init_wakeup(&pdev->dev, 0); | 990 | device_init_wakeup(&pdev->dev, 0); |
| 949 | free_irq(host->board->det_pin, host); | 991 | gpio_free(host->board->det_pin); |
| 950 | cancel_delayed_work(&host->mmc->detect); | ||
| 951 | } | 992 | } |
| 952 | 993 | ||
| 953 | at91_mci_disable(host); | 994 | at91_mci_disable(host); |
| @@ -957,6 +998,11 @@ static int __exit at91_mci_remove(struct platform_device *pdev) | |||
| 957 | clk_disable(host->mci_clk); /* Disable the peripheral clock */ | 998 | clk_disable(host->mci_clk); /* Disable the peripheral clock */ |
| 958 | clk_put(host->mci_clk); | 999 | clk_put(host->mci_clk); |
| 959 | 1000 | ||
| 1001 | if (host->board->vcc_pin) | ||
| 1002 | gpio_free(host->board->vcc_pin); | ||
| 1003 | if (host->board->wp_pin) | ||
| 1004 | gpio_free(host->board->wp_pin); | ||
| 1005 | |||
| 960 | iounmap(host->baseaddr); | 1006 | iounmap(host->baseaddr); |
| 961 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1007 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 962 | release_mem_region(res->start, res->end - res->start + 1); | 1008 | release_mem_region(res->start, res->end - res->start + 1); |
