Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Sat, 9 Feb 2008 19:12:15 +0000 (11:12 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Sat, 9 Feb 2008 19:12:15 +0000 (11:12 -0800)
* '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

MAINTAINERS
drivers/mmc/host/Kconfig
drivers/mmc/host/at91_mci.c
drivers/mmc/host/ricoh_mmc.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h

index 5740aa216e1170398c7ead134ee0902da11c760d..c40f0ae965523a04ef327be9c13c97923e67fb6c 100644 (file)
@@ -2682,7 +2682,6 @@ MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER
 P:     Pavel Pisa
 M:     ppisa@pikron.com
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
-W:     http://mmc.drzeus.cx/wiki/Controllers/Freescale/SDHC
 S:     Maintained
 
 MOUSE AND MISC DEVICES [GENERAL]
@@ -3716,7 +3715,6 @@ SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER
 P:     Pierre Ossman
 M:     drzeus-sdhci@drzeus.cx
 L:     sdhci-devel@list.drzeus.cx
-W:     http://mmc.drzeus.cx/wiki/Linux/Drivers/sdhci
 S:     Maintained
 
 SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
@@ -4286,7 +4284,6 @@ W83L51xD SD/MMC CARD INTERFACE DRIVER
 P:     Pierre Ossman
 M:     drzeus-wbsd@drzeus.cx
 L:     linux-kernel@vger.kernel.org
-W:     http://projects.drzeus.cx/wbsd
 S:     Maintained
 
 WATCHDOG DEVICE DRIVERS
index 5fef6783c7161fc8cf95b836e49dcc13259ff655..3b3cd0e74715c63161a5a3746ce0155cec420f6a 100644 (file)
@@ -25,8 +25,8 @@ config MMC_PXA
          If unsure, say N.
 
 config MMC_SDHCI
-       tristate "Secure Digital Host Controller Interface support  (EXPERIMENTAL)"
-       depends on PCI && EXPERIMENTAL
+       tristate "Secure Digital Host Controller Interface support"
+       depends on PCI
        help
          This select the generic Secure Digital Host Controller Interface.
          It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
@@ -118,8 +118,8 @@ config MMC_TIFM_SD
          module will be called tifm_sd.
 
 config MMC_SPI
-       tristate "MMC/SD over SPI (EXPERIMENTAL)"
-       depends on MMC && SPI_MASTER && !HIGHMEM && EXPERIMENTAL
+       tristate "MMC/SD over SPI"
+       depends on MMC && SPI_MASTER && !HIGHMEM
        select CRC7
        select CRC_ITU_T
        help
index b1edcefdd4f9e7a615e2e38238f4d43e8456a9b4..21acecc9fe3a929063f626a4d06990cf0216dbc6 100644 (file)
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/gpio.h>
+
 #include <asm/mach/mmc.h>
 #include <asm/arch/board.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/at91_mci.h>
 
 #define DRIVER_NAME "at91_mci"
@@ -659,11 +660,11 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        if (host->board->vcc_pin) {
                switch (ios->power_mode) {
                        case MMC_POWER_OFF:
-                               at91_set_gpio_value(host->board->vcc_pin, 0);
+                               gpio_set_value(host->board->vcc_pin, 0);
                                break;
                        case MMC_POWER_UP:
                        case MMC_POWER_ON:
-                               at91_set_gpio_value(host->board->vcc_pin, 1);
+                               gpio_set_value(host->board->vcc_pin, 1);
                                break;
                }
        }
@@ -768,7 +769,7 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
 static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
 {
        struct at91mci_host *host = _host;
-       int present = !at91_get_gpio_value(irq);
+       int present = !gpio_get_value(irq_to_gpio(irq));
 
        /*
         * we expect this irq on both insert and remove,
@@ -793,7 +794,7 @@ static int at91_mci_get_ro(struct mmc_host *mmc)
        struct at91mci_host *host = mmc_priv(mmc);
 
        if (host->board->wp_pin) {
-               read_only = at91_get_gpio_value(host->board->wp_pin);
+               read_only = gpio_get_value(host->board->wp_pin);
                printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc),
                                (read_only ? "read-only" : "read-write") );
        }
@@ -820,8 +821,6 @@ static int __init at91_mci_probe(struct platform_device *pdev)
        struct resource *res;
        int ret;
 
-       pr_debug("Probe MCI devices\n");
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
                return -ENXIO;
@@ -831,9 +830,9 @@ static int __init at91_mci_probe(struct platform_device *pdev)
 
        mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
        if (!mmc) {
-               pr_debug("Failed to allocate mmc host\n");
-               release_mem_region(res->start, res->end - res->start + 1);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
+               goto fail6;
        }
 
        mmc->ops = &at91_mci_ops;
@@ -853,19 +852,44 @@ static int __init at91_mci_probe(struct platform_device *pdev)
                if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
                        mmc->caps |= MMC_CAP_4_BIT_DATA;
                else
-                       printk("AT91 MMC: 4 wire bus mode not supported"
+                       dev_warn(&pdev->dev, "4 wire bus mode not supported"
                                " - using 1 wire\n");
        }
 
+       /*
+        * Reserve GPIOs ... board init code makes sure these pins are set
+        * up as GPIOs with the right direction (input, except for vcc)
+        */
+       if (host->board->det_pin) {
+               ret = gpio_request(host->board->det_pin, "mmc_detect");
+               if (ret < 0) {
+                       dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
+                       goto fail5;
+               }
+       }
+       if (host->board->wp_pin) {
+               ret = gpio_request(host->board->wp_pin, "mmc_wp");
+               if (ret < 0) {
+                       dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
+                       goto fail4;
+               }
+       }
+       if (host->board->vcc_pin) {
+               ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
+               if (ret < 0) {
+                       dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
+                       goto fail3;
+               }
+       }
+
        /*
         * Get Clock
         */
        host->mci_clk = clk_get(&pdev->dev, "mci_clk");
        if (IS_ERR(host->mci_clk)) {
-               printk(KERN_ERR "AT91 MMC: no clock defined.\n");
-               mmc_free_host(mmc);
-               release_mem_region(res->start, res->end - res->start + 1);
-               return -ENODEV;
+               ret = -ENODEV;
+               dev_dbg(&pdev->dev, "no mci_clk?\n");
+               goto fail2;
        }
 
        /*
@@ -873,10 +897,8 @@ static int __init at91_mci_probe(struct platform_device *pdev)
         */
        host->baseaddr = ioremap(res->start, res->end - res->start + 1);
        if (!host->baseaddr) {
-               clk_put(host->mci_clk);
-               mmc_free_host(mmc);
-               release_mem_region(res->start, res->end - res->start + 1);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto fail1;
        }
 
        /*
@@ -890,15 +912,11 @@ static int __init at91_mci_probe(struct platform_device *pdev)
         * Allocate the MCI interrupt
         */
        host->irq = platform_get_irq(pdev, 0);
-       ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
+       ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
+                       mmc_hostname(mmc), host);
        if (ret) {
-               printk(KERN_ERR "AT91 MMC: Failed to request MCI interrupt\n");
-               clk_disable(host->mci_clk);
-               clk_put(host->mci_clk);
-               mmc_free_host(mmc);
-               iounmap(host->baseaddr);
-               release_mem_region(res->start, res->end - res->start + 1);
-               return ret;
+               dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
+               goto fail0;
        }
 
        platform_set_drvdata(pdev, mmc);
@@ -907,8 +925,7 @@ static int __init at91_mci_probe(struct platform_device *pdev)
         * Add host to MMC layer
         */
        if (host->board->det_pin) {
-               host->present = !at91_get_gpio_value(host->board->det_pin);
-               device_init_wakeup(&pdev->dev, 1);
+               host->present = !gpio_get_value(host->board->det_pin);
        }
        else
                host->present = -1;
@@ -919,15 +936,38 @@ static int __init at91_mci_probe(struct platform_device *pdev)
         * monitor card insertion/removal if we can
         */
        if (host->board->det_pin) {
-               ret = request_irq(host->board->det_pin, at91_mmc_det_irq,
-                               0, DRIVER_NAME, host);
+               ret = request_irq(gpio_to_irq(host->board->det_pin),
+                               at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
                if (ret)
-                       printk(KERN_ERR "AT91 MMC: Couldn't allocate MMC detect irq\n");
+                       dev_warn(&pdev->dev, "request MMC detect irq failed\n");
+               else
+                       device_init_wakeup(&pdev->dev, 1);
        }
 
        pr_debug("Added MCI driver\n");
 
        return 0;
+
+fail0:
+       clk_disable(host->mci_clk);
+       iounmap(host->baseaddr);
+fail1:
+       clk_put(host->mci_clk);
+fail2:
+       if (host->board->vcc_pin)
+               gpio_free(host->board->vcc_pin);
+fail3:
+       if (host->board->wp_pin)
+               gpio_free(host->board->wp_pin);
+fail4:
+       if (host->board->det_pin)
+               gpio_free(host->board->det_pin);
+fail5:
+       mmc_free_host(mmc);
+fail6:
+       release_mem_region(res->start, res->end - res->start + 1);
+       dev_err(&pdev->dev, "probe failed, err %d\n", ret);
+       return ret;
 }
 
 /*
@@ -945,9 +985,10 @@ static int __exit at91_mci_remove(struct platform_device *pdev)
        host = mmc_priv(mmc);
 
        if (host->board->det_pin) {
+               if (device_can_wakeup(&pdev->dev))
+                       free_irq(gpio_to_irq(host->board->det_pin), host);
                device_init_wakeup(&pdev->dev, 0);
-               free_irq(host->board->det_pin, host);
-               cancel_delayed_work(&host->mmc->detect);
+               gpio_free(host->board->det_pin);
        }
 
        at91_mci_disable(host);
@@ -957,6 +998,11 @@ static int __exit at91_mci_remove(struct platform_device *pdev)
        clk_disable(host->mci_clk);                     /* Disable the peripheral clock */
        clk_put(host->mci_clk);
 
+       if (host->board->vcc_pin)
+               gpio_free(host->board->vcc_pin);
+       if (host->board->wp_pin)
+               gpio_free(host->board->wp_pin);
+
        iounmap(host->baseaddr);
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(res->start, res->end - res->start + 1);
index 1e8704533bc5280ecf15ccdae202feb289f2d4fe..a16d7609e4eede4fa88f4ecc6b3ac9dce699038a 100644 (file)
@@ -41,10 +41,91 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
 
 MODULE_DEVICE_TABLE(pci, pci_ids);
 
+static int ricoh_mmc_disable(struct pci_dev *fw_dev)
+{
+       u8 write_enable;
+       u8 write_target;
+       u8 disable;
+
+       if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) {
+               /* via RL5C476 */
+
+               pci_read_config_byte(fw_dev, 0xB7, &disable);
+               if (disable & 0x02) {
+                       printk(KERN_INFO DRIVER_NAME
+                               ": Controller already disabled. " \
+                               "Nothing to do.\n");
+                       return -ENODEV;
+               }
+
+               pci_read_config_byte(fw_dev, 0x8E, &write_enable);
+               pci_write_config_byte(fw_dev, 0x8E, 0xAA);
+               pci_read_config_byte(fw_dev, 0x8D, &write_target);
+               pci_write_config_byte(fw_dev, 0x8D, 0xB7);
+               pci_write_config_byte(fw_dev, 0xB7, disable | 0x02);
+               pci_write_config_byte(fw_dev, 0x8E, write_enable);
+               pci_write_config_byte(fw_dev, 0x8D, write_target);
+       } else {
+               /* via R5C832 */
+
+               pci_read_config_byte(fw_dev, 0xCB, &disable);
+               if (disable & 0x02) {
+                       printk(KERN_INFO DRIVER_NAME
+                              ": Controller already disabled. " \
+                               "Nothing to do.\n");
+                       return -ENODEV;
+               }
+
+               pci_read_config_byte(fw_dev, 0xCA, &write_enable);
+               pci_write_config_byte(fw_dev, 0xCA, 0x57);
+               pci_write_config_byte(fw_dev, 0xCB, disable | 0x02);
+               pci_write_config_byte(fw_dev, 0xCA, write_enable);
+       }
+
+       printk(KERN_INFO DRIVER_NAME
+              ": Controller is now disabled.\n");
+
+       return 0;
+}
+
+static int ricoh_mmc_enable(struct pci_dev *fw_dev)
+{
+       u8 write_enable;
+       u8 write_target;
+       u8 disable;
+
+       if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) {
+               /* via RL5C476 */
+
+               pci_read_config_byte(fw_dev, 0x8E, &write_enable);
+               pci_write_config_byte(fw_dev, 0x8E, 0xAA);
+               pci_read_config_byte(fw_dev, 0x8D, &write_target);
+               pci_write_config_byte(fw_dev, 0x8D, 0xB7);
+               pci_read_config_byte(fw_dev, 0xB7, &disable);
+               pci_write_config_byte(fw_dev, 0xB7, disable & ~0x02);
+               pci_write_config_byte(fw_dev, 0x8E, write_enable);
+               pci_write_config_byte(fw_dev, 0x8D, write_target);
+       } else {
+               /* via R5C832 */
+
+               pci_read_config_byte(fw_dev, 0xCA, &write_enable);
+               pci_read_config_byte(fw_dev, 0xCB, &disable);
+               pci_write_config_byte(fw_dev, 0xCA, 0x57);
+               pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02);
+               pci_write_config_byte(fw_dev, 0xCA, write_enable);
+       }
+
+       printk(KERN_INFO DRIVER_NAME
+              ": Controller is now re-enabled.\n");
+
+       return 0;
+}
+
 static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
                                     const struct pci_device_id *ent)
 {
        u8 rev;
+       u8 ctrlfound = 0;
 
        struct pci_dev *fw_dev = NULL;
 
@@ -58,34 +139,38 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
                pci_name(pdev), (int)pdev->vendor, (int)pdev->device,
                (int)rev);
 
-       while ((fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) {
+       while ((fw_dev =
+               pci_get_device(PCI_VENDOR_ID_RICOH,
+                       PCI_DEVICE_ID_RICOH_RL5C476, fw_dev))) {
                if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
                    pdev->bus == fw_dev->bus) {
-                       u8 write_enable;
-                       u8 disable;
-
-                       pci_read_config_byte(fw_dev, 0xCB, &disable);
-                       if (disable & 0x02) {
-                               printk(KERN_INFO DRIVER_NAME
-                                      ": Controller already disabled. Nothing to do.\n");
+                       if (ricoh_mmc_disable(fw_dev) != 0)
                                return -ENODEV;
-                       }
-
-                       pci_read_config_byte(fw_dev, 0xCA, &write_enable);
-                       pci_write_config_byte(fw_dev, 0xCA, 0x57);
-                       pci_write_config_byte(fw_dev, 0xCB, disable | 0x02);
-                       pci_write_config_byte(fw_dev, 0xCA, write_enable);
 
                        pci_set_drvdata(pdev, fw_dev);
 
-                       printk(KERN_INFO DRIVER_NAME
-                              ": Controller is now disabled.\n");
-
+                       ++ctrlfound;
                        break;
                }
        }
 
-       if (pci_get_drvdata(pdev) == NULL) {
+       fw_dev = NULL;
+
+       while (!ctrlfound &&
+           (fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH,
+                                       PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) {
+               if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
+                   pdev->bus == fw_dev->bus) {
+                       if (ricoh_mmc_disable(fw_dev) != 0)
+                               return -ENODEV;
+
+                       pci_set_drvdata(pdev, fw_dev);
+
+                       ++ctrlfound;
+               }
+       }
+
+       if (!ctrlfound) {
                printk(KERN_WARNING DRIVER_NAME
                       ": Main firewire function not found. Cannot disable controller.\n");
                return -ENODEV;
@@ -96,30 +181,51 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
 
 static void __devexit ricoh_mmc_remove(struct pci_dev *pdev)
 {
-       u8 write_enable;
-       u8 disable;
        struct pci_dev *fw_dev = NULL;
 
        fw_dev = pci_get_drvdata(pdev);
        BUG_ON(fw_dev == NULL);
 
-       pci_read_config_byte(fw_dev, 0xCA, &write_enable);
-       pci_read_config_byte(fw_dev, 0xCB, &disable);
-       pci_write_config_byte(fw_dev, 0xCA, 0x57);
-       pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02);
-       pci_write_config_byte(fw_dev, 0xCA, write_enable);
-
-       printk(KERN_INFO DRIVER_NAME
-              ": Controller is now re-enabled.\n");
+       ricoh_mmc_enable(fw_dev);
 
        pci_set_drvdata(pdev, NULL);
 }
 
+static int ricoh_mmc_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct pci_dev *fw_dev = NULL;
+
+       fw_dev = pci_get_drvdata(pdev);
+       BUG_ON(fw_dev == NULL);
+
+       printk(KERN_INFO DRIVER_NAME ": Suspending.\n");
+
+       ricoh_mmc_enable(fw_dev);
+
+       return 0;
+}
+
+static int ricoh_mmc_resume(struct pci_dev *pdev)
+{
+       struct pci_dev *fw_dev = NULL;
+
+       fw_dev = pci_get_drvdata(pdev);
+       BUG_ON(fw_dev == NULL);
+
+       printk(KERN_INFO DRIVER_NAME ": Resuming.\n");
+
+       ricoh_mmc_disable(fw_dev);
+
+       return 0;
+}
+
 static struct pci_driver ricoh_mmc_driver = {
        .name =         DRIVER_NAME,
        .id_table =     pci_ids,
        .probe =        ricoh_mmc_probe,
        .remove =       __devexit_p(ricoh_mmc_remove),
+       .suspend =      ricoh_mmc_suspend,
+       .resume =       ricoh_mmc_resume,
 };
 
 /*****************************************************************************\
index 785bbdcf4a58212e4371fbdc024a1ef1919ffc88..4b673aa2dc3cae7a7e588e1d306e59437848f54f 100644 (file)
 
 static unsigned int debug_quirks = 0;
 
+/* For multi controllers in one platform case */
+static u16 chip_index = 0;
+static spinlock_t index_lock;
+
 /*
  * Different quirks to handle when the hardware deviates from a strict
  * interpretation of the SDHCI specification.
@@ -1320,7 +1324,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 
        DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq);
 
-       snprintf(host->slot_descr, 20, "sdhci:slot%d", slot);
+       snprintf(host->slot_descr, 20, "sdhc%d:slot%d", chip->index, slot);
 
        ret = pci_request_region(pdev, host->bar, host->slot_descr);
        if (ret)
@@ -1585,6 +1589,11 @@ static int __devinit sdhci_probe(struct pci_dev *pdev,
        chip->num_slots = slots;
        pci_set_drvdata(pdev, chip);
 
+       /* Add for multi controller case */
+       spin_lock(&index_lock);
+       chip->index = chip_index++;
+       spin_unlock(&index_lock);
+
        for (i = 0;i < slots;i++) {
                ret = sdhci_probe_slot(pdev, i);
                if (ret) {
@@ -1645,6 +1654,8 @@ static int __init sdhci_drv_init(void)
                ": Secure Digital Host Controller Interface driver\n");
        printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
 
+       spin_lock_init(&index_lock);
+
        return pci_register_driver(&sdhci_driver);
 }
 
index e4d77b038bfa5e9e12c976294c3dfecb5b86d156..d5a38f1b755ae1855cca9a0d40713fe3a7c77d65 100644 (file)
@@ -208,6 +208,7 @@ struct sdhci_chip {
 
        unsigned long           quirks;
 
+       int                     index;          /* Index for chip0, chip1 ...*/
        int                     num_slots;      /* Slots on controller */
        struct sdhci_host       *hosts[0];      /* Pointers to hosts */
 };