diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-09 14:12:15 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-09 14:12:15 -0500 |
| commit | 5b39dba5029108800b94a5f4f96e3a05417103ac (patch) | |
| tree | 7d5c59fd124a776508b3e2a58efb093cd97b29ea /drivers/mmc/host | |
| parent | 11eb3b0da3f8e4b9a6da6aba510471918239153d (diff) | |
| parent | 882c49164d72c45f37d7fa1bb3de7c31cf1a5fab (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc:
mmc: extend ricoh_mmc to support Ricoh RL5c476
at91_mci: use generic GPIO calls
sdhci: add num index for multi controllers case
MAINTAINERS: remove non-existant URLs
mmc: remove sdhci and mmc_spi experimental markers
mmc: Handle suspend/resume in Ricoh MMC disabler
Diffstat (limited to 'drivers/mmc/host')
| -rw-r--r-- | drivers/mmc/host/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/mmc/host/at91_mci.c | 114 | ||||
| -rw-r--r-- | drivers/mmc/host/ricoh_mmc.c | 162 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 13 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.h | 1 |
5 files changed, 231 insertions, 67 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 5fef6783c716..3b3cd0e74715 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
| @@ -25,8 +25,8 @@ config MMC_PXA | |||
| 25 | If unsure, say N. | 25 | If unsure, say N. |
| 26 | 26 | ||
| 27 | config MMC_SDHCI | 27 | config MMC_SDHCI |
| 28 | tristate "Secure Digital Host Controller Interface support (EXPERIMENTAL)" | 28 | tristate "Secure Digital Host Controller Interface support" |
| 29 | depends on PCI && EXPERIMENTAL | 29 | depends on PCI |
| 30 | help | 30 | help |
| 31 | This select the generic Secure Digital Host Controller Interface. | 31 | This select the generic Secure Digital Host Controller Interface. |
| 32 | It is used by manufacturers such as Texas Instruments(R), Ricoh(R) | 32 | It is used by manufacturers such as Texas Instruments(R), Ricoh(R) |
| @@ -118,8 +118,8 @@ config MMC_TIFM_SD | |||
| 118 | module will be called tifm_sd. | 118 | module will be called tifm_sd. |
| 119 | 119 | ||
| 120 | config MMC_SPI | 120 | config MMC_SPI |
| 121 | tristate "MMC/SD over SPI (EXPERIMENTAL)" | 121 | tristate "MMC/SD over SPI" |
| 122 | depends on MMC && SPI_MASTER && !HIGHMEM && EXPERIMENTAL | 122 | depends on MMC && SPI_MASTER && !HIGHMEM |
| 123 | select CRC7 | 123 | select CRC7 |
| 124 | select CRC_ITU_T | 124 | select CRC_ITU_T |
| 125 | help | 125 | help |
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); |
diff --git a/drivers/mmc/host/ricoh_mmc.c b/drivers/mmc/host/ricoh_mmc.c index 1e8704533bc5..a16d7609e4ee 100644 --- a/drivers/mmc/host/ricoh_mmc.c +++ b/drivers/mmc/host/ricoh_mmc.c | |||
| @@ -41,10 +41,91 @@ static const struct pci_device_id pci_ids[] __devinitdata = { | |||
| 41 | 41 | ||
| 42 | MODULE_DEVICE_TABLE(pci, pci_ids); | 42 | MODULE_DEVICE_TABLE(pci, pci_ids); |
| 43 | 43 | ||
| 44 | static int ricoh_mmc_disable(struct pci_dev *fw_dev) | ||
| 45 | { | ||
| 46 | u8 write_enable; | ||
| 47 | u8 write_target; | ||
| 48 | u8 disable; | ||
| 49 | |||
| 50 | if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) { | ||
| 51 | /* via RL5C476 */ | ||
| 52 | |||
| 53 | pci_read_config_byte(fw_dev, 0xB7, &disable); | ||
| 54 | if (disable & 0x02) { | ||
| 55 | printk(KERN_INFO DRIVER_NAME | ||
| 56 | ": Controller already disabled. " \ | ||
| 57 | "Nothing to do.\n"); | ||
| 58 | return -ENODEV; | ||
| 59 | } | ||
| 60 | |||
| 61 | pci_read_config_byte(fw_dev, 0x8E, &write_enable); | ||
| 62 | pci_write_config_byte(fw_dev, 0x8E, 0xAA); | ||
| 63 | pci_read_config_byte(fw_dev, 0x8D, &write_target); | ||
| 64 | pci_write_config_byte(fw_dev, 0x8D, 0xB7); | ||
| 65 | pci_write_config_byte(fw_dev, 0xB7, disable | 0x02); | ||
| 66 | pci_write_config_byte(fw_dev, 0x8E, write_enable); | ||
| 67 | pci_write_config_byte(fw_dev, 0x8D, write_target); | ||
| 68 | } else { | ||
| 69 | /* via R5C832 */ | ||
| 70 | |||
| 71 | pci_read_config_byte(fw_dev, 0xCB, &disable); | ||
| 72 | if (disable & 0x02) { | ||
| 73 | printk(KERN_INFO DRIVER_NAME | ||
| 74 | ": Controller already disabled. " \ | ||
| 75 | "Nothing to do.\n"); | ||
| 76 | return -ENODEV; | ||
| 77 | } | ||
| 78 | |||
| 79 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | ||
| 80 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | ||
| 81 | pci_write_config_byte(fw_dev, 0xCB, disable | 0x02); | ||
| 82 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | ||
| 83 | } | ||
| 84 | |||
| 85 | printk(KERN_INFO DRIVER_NAME | ||
| 86 | ": Controller is now disabled.\n"); | ||
| 87 | |||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | |||
| 91 | static int ricoh_mmc_enable(struct pci_dev *fw_dev) | ||
| 92 | { | ||
| 93 | u8 write_enable; | ||
| 94 | u8 write_target; | ||
| 95 | u8 disable; | ||
| 96 | |||
| 97 | if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) { | ||
| 98 | /* via RL5C476 */ | ||
| 99 | |||
| 100 | pci_read_config_byte(fw_dev, 0x8E, &write_enable); | ||
| 101 | pci_write_config_byte(fw_dev, 0x8E, 0xAA); | ||
| 102 | pci_read_config_byte(fw_dev, 0x8D, &write_target); | ||
| 103 | pci_write_config_byte(fw_dev, 0x8D, 0xB7); | ||
| 104 | pci_read_config_byte(fw_dev, 0xB7, &disable); | ||
| 105 | pci_write_config_byte(fw_dev, 0xB7, disable & ~0x02); | ||
| 106 | pci_write_config_byte(fw_dev, 0x8E, write_enable); | ||
| 107 | pci_write_config_byte(fw_dev, 0x8D, write_target); | ||
| 108 | } else { | ||
| 109 | /* via R5C832 */ | ||
| 110 | |||
| 111 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | ||
| 112 | pci_read_config_byte(fw_dev, 0xCB, &disable); | ||
| 113 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | ||
| 114 | pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02); | ||
| 115 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | ||
| 116 | } | ||
| 117 | |||
| 118 | printk(KERN_INFO DRIVER_NAME | ||
| 119 | ": Controller is now re-enabled.\n"); | ||
| 120 | |||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | |||
| 44 | static int __devinit ricoh_mmc_probe(struct pci_dev *pdev, | 124 | static int __devinit ricoh_mmc_probe(struct pci_dev *pdev, |
| 45 | const struct pci_device_id *ent) | 125 | const struct pci_device_id *ent) |
| 46 | { | 126 | { |
| 47 | u8 rev; | 127 | u8 rev; |
| 128 | u8 ctrlfound = 0; | ||
| 48 | 129 | ||
| 49 | struct pci_dev *fw_dev = NULL; | 130 | struct pci_dev *fw_dev = NULL; |
| 50 | 131 | ||
| @@ -58,34 +139,38 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev, | |||
| 58 | pci_name(pdev), (int)pdev->vendor, (int)pdev->device, | 139 | pci_name(pdev), (int)pdev->vendor, (int)pdev->device, |
| 59 | (int)rev); | 140 | (int)rev); |
| 60 | 141 | ||
| 61 | while ((fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) { | 142 | while ((fw_dev = |
| 143 | pci_get_device(PCI_VENDOR_ID_RICOH, | ||
| 144 | PCI_DEVICE_ID_RICOH_RL5C476, fw_dev))) { | ||
| 62 | if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) && | 145 | if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) && |
| 63 | pdev->bus == fw_dev->bus) { | 146 | pdev->bus == fw_dev->bus) { |
| 64 | u8 write_enable; | 147 | if (ricoh_mmc_disable(fw_dev) != 0) |
| 65 | u8 disable; | ||
| 66 | |||
| 67 | pci_read_config_byte(fw_dev, 0xCB, &disable); | ||
| 68 | if (disable & 0x02) { | ||
| 69 | printk(KERN_INFO DRIVER_NAME | ||
| 70 | ": Controller already disabled. Nothing to do.\n"); | ||
| 71 | return -ENODEV; | 148 | return -ENODEV; |
| 72 | } | ||
| 73 | |||
| 74 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | ||
| 75 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | ||
| 76 | pci_write_config_byte(fw_dev, 0xCB, disable | 0x02); | ||
| 77 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | ||
| 78 | 149 | ||
| 79 | pci_set_drvdata(pdev, fw_dev); | 150 | pci_set_drvdata(pdev, fw_dev); |
| 80 | 151 | ||
| 81 | printk(KERN_INFO DRIVER_NAME | 152 | ++ctrlfound; |
| 82 | ": Controller is now disabled.\n"); | ||
| 83 | |||
| 84 | break; | 153 | break; |
| 85 | } | 154 | } |
| 86 | } | 155 | } |
| 87 | 156 | ||
| 88 | if (pci_get_drvdata(pdev) == NULL) { | 157 | fw_dev = NULL; |
| 158 | |||
| 159 | while (!ctrlfound && | ||
| 160 | (fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH, | ||
| 161 | PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) { | ||
| 162 | if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) && | ||
| 163 | pdev->bus == fw_dev->bus) { | ||
| 164 | if (ricoh_mmc_disable(fw_dev) != 0) | ||
| 165 | return -ENODEV; | ||
| 166 | |||
| 167 | pci_set_drvdata(pdev, fw_dev); | ||
| 168 | |||
| 169 | ++ctrlfound; | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | if (!ctrlfound) { | ||
| 89 | printk(KERN_WARNING DRIVER_NAME | 174 | printk(KERN_WARNING DRIVER_NAME |
| 90 | ": Main firewire function not found. Cannot disable controller.\n"); | 175 | ": Main firewire function not found. Cannot disable controller.\n"); |
| 91 | return -ENODEV; | 176 | return -ENODEV; |
| @@ -96,30 +181,51 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev, | |||
| 96 | 181 | ||
| 97 | static void __devexit ricoh_mmc_remove(struct pci_dev *pdev) | 182 | static void __devexit ricoh_mmc_remove(struct pci_dev *pdev) |
| 98 | { | 183 | { |
| 99 | u8 write_enable; | ||
| 100 | u8 disable; | ||
| 101 | struct pci_dev *fw_dev = NULL; | 184 | struct pci_dev *fw_dev = NULL; |
| 102 | 185 | ||
| 103 | fw_dev = pci_get_drvdata(pdev); | 186 | fw_dev = pci_get_drvdata(pdev); |
| 104 | BUG_ON(fw_dev == NULL); | 187 | BUG_ON(fw_dev == NULL); |
| 105 | 188 | ||
| 106 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | 189 | ricoh_mmc_enable(fw_dev); |
| 107 | pci_read_config_byte(fw_dev, 0xCB, &disable); | ||
| 108 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | ||
| 109 | pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02); | ||
| 110 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | ||
| 111 | |||
| 112 | printk(KERN_INFO DRIVER_NAME | ||
| 113 | ": Controller is now re-enabled.\n"); | ||
| 114 | 190 | ||
| 115 | pci_set_drvdata(pdev, NULL); | 191 | pci_set_drvdata(pdev, NULL); |
| 116 | } | 192 | } |
| 117 | 193 | ||
| 194 | static int ricoh_mmc_suspend(struct pci_dev *pdev, pm_message_t state) | ||
| 195 | { | ||
| 196 | struct pci_dev *fw_dev = NULL; | ||
| 197 | |||
| 198 | fw_dev = pci_get_drvdata(pdev); | ||
| 199 | BUG_ON(fw_dev == NULL); | ||
| 200 | |||
| 201 | printk(KERN_INFO DRIVER_NAME ": Suspending.\n"); | ||
| 202 | |||
| 203 | ricoh_mmc_enable(fw_dev); | ||
| 204 | |||
| 205 | return 0; | ||
| 206 | } | ||
| 207 | |||
| 208 | static int ricoh_mmc_resume(struct pci_dev *pdev) | ||
| 209 | { | ||
| 210 | struct pci_dev *fw_dev = NULL; | ||
| 211 | |||
| 212 | fw_dev = pci_get_drvdata(pdev); | ||
| 213 | BUG_ON(fw_dev == NULL); | ||
| 214 | |||
| 215 | printk(KERN_INFO DRIVER_NAME ": Resuming.\n"); | ||
| 216 | |||
| 217 | ricoh_mmc_disable(fw_dev); | ||
| 218 | |||
| 219 | return 0; | ||
| 220 | } | ||
| 221 | |||
| 118 | static struct pci_driver ricoh_mmc_driver = { | 222 | static struct pci_driver ricoh_mmc_driver = { |
| 119 | .name = DRIVER_NAME, | 223 | .name = DRIVER_NAME, |
| 120 | .id_table = pci_ids, | 224 | .id_table = pci_ids, |
| 121 | .probe = ricoh_mmc_probe, | 225 | .probe = ricoh_mmc_probe, |
| 122 | .remove = __devexit_p(ricoh_mmc_remove), | 226 | .remove = __devexit_p(ricoh_mmc_remove), |
| 227 | .suspend = ricoh_mmc_suspend, | ||
| 228 | .resume = ricoh_mmc_resume, | ||
| 123 | }; | 229 | }; |
| 124 | 230 | ||
| 125 | /*****************************************************************************\ | 231 | /*****************************************************************************\ |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 785bbdcf4a58..4b673aa2dc3c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -30,6 +30,10 @@ | |||
| 30 | 30 | ||
| 31 | static unsigned int debug_quirks = 0; | 31 | static unsigned int debug_quirks = 0; |
| 32 | 32 | ||
| 33 | /* For multi controllers in one platform case */ | ||
| 34 | static u16 chip_index = 0; | ||
| 35 | static spinlock_t index_lock; | ||
| 36 | |||
| 33 | /* | 37 | /* |
| 34 | * Different quirks to handle when the hardware deviates from a strict | 38 | * Different quirks to handle when the hardware deviates from a strict |
| 35 | * interpretation of the SDHCI specification. | 39 | * interpretation of the SDHCI specification. |
| @@ -1320,7 +1324,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
| 1320 | 1324 | ||
| 1321 | DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq); | 1325 | DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq); |
| 1322 | 1326 | ||
| 1323 | snprintf(host->slot_descr, 20, "sdhci:slot%d", slot); | 1327 | snprintf(host->slot_descr, 20, "sdhc%d:slot%d", chip->index, slot); |
| 1324 | 1328 | ||
| 1325 | ret = pci_request_region(pdev, host->bar, host->slot_descr); | 1329 | ret = pci_request_region(pdev, host->bar, host->slot_descr); |
| 1326 | if (ret) | 1330 | if (ret) |
| @@ -1585,6 +1589,11 @@ static int __devinit sdhci_probe(struct pci_dev *pdev, | |||
| 1585 | chip->num_slots = slots; | 1589 | chip->num_slots = slots; |
| 1586 | pci_set_drvdata(pdev, chip); | 1590 | pci_set_drvdata(pdev, chip); |
| 1587 | 1591 | ||
| 1592 | /* Add for multi controller case */ | ||
| 1593 | spin_lock(&index_lock); | ||
| 1594 | chip->index = chip_index++; | ||
| 1595 | spin_unlock(&index_lock); | ||
| 1596 | |||
| 1588 | for (i = 0;i < slots;i++) { | 1597 | for (i = 0;i < slots;i++) { |
| 1589 | ret = sdhci_probe_slot(pdev, i); | 1598 | ret = sdhci_probe_slot(pdev, i); |
| 1590 | if (ret) { | 1599 | if (ret) { |
| @@ -1645,6 +1654,8 @@ static int __init sdhci_drv_init(void) | |||
| 1645 | ": Secure Digital Host Controller Interface driver\n"); | 1654 | ": Secure Digital Host Controller Interface driver\n"); |
| 1646 | printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); | 1655 | printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); |
| 1647 | 1656 | ||
| 1657 | spin_lock_init(&index_lock); | ||
| 1658 | |||
| 1648 | return pci_register_driver(&sdhci_driver); | 1659 | return pci_register_driver(&sdhci_driver); |
| 1649 | } | 1660 | } |
| 1650 | 1661 | ||
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index e4d77b038bfa..d5a38f1b755a 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
| @@ -208,6 +208,7 @@ struct sdhci_chip { | |||
| 208 | 208 | ||
| 209 | unsigned long quirks; | 209 | unsigned long quirks; |
| 210 | 210 | ||
| 211 | int index; /* Index for chip0, chip1 ...*/ | ||
| 211 | int num_slots; /* Slots on controller */ | 212 | int num_slots; /* Slots on controller */ |
| 212 | struct sdhci_host *hosts[0]; /* Pointers to hosts */ | 213 | struct sdhci_host *hosts[0]; /* Pointers to hosts */ |
| 213 | }; | 214 | }; |
