浏览代码

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
Linus Torvalds 18 年之前
父节点
当前提交
5b39dba502
共有 6 个文件被更改,包括 231 次插入70 次删除
  1. 0 3
      MAINTAINERS
  2. 4 4
      drivers/mmc/host/Kconfig
  3. 80 34
      drivers/mmc/host/at91_mci.c
  4. 134 28
      drivers/mmc/host/ricoh_mmc.c
  5. 12 1
      drivers/mmc/host/sdhci.c
  6. 1 0
      drivers/mmc/host/sdhci.h

+ 0 - 3
MAINTAINERS

@@ -2682,7 +2682,6 @@ MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER
 P:	Pavel Pisa
 P:	Pavel Pisa
 M:	ppisa@pikron.com
 M:	ppisa@pikron.com
 L:	linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 L:	linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
-W:	http://mmc.drzeus.cx/wiki/Controllers/Freescale/SDHC
 S:	Maintained
 S:	Maintained
 
 
 MOUSE AND MISC DEVICES [GENERAL]
 MOUSE AND MISC DEVICES [GENERAL]
@@ -3716,7 +3715,6 @@ SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER
 P:	Pierre Ossman
 P:	Pierre Ossman
 M:	drzeus-sdhci@drzeus.cx
 M:	drzeus-sdhci@drzeus.cx
 L:	sdhci-devel@list.drzeus.cx
 L:	sdhci-devel@list.drzeus.cx
-W:	http://mmc.drzeus.cx/wiki/Linux/Drivers/sdhci
 S:	Maintained
 S:	Maintained
 
 
 SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
 SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
@@ -4286,7 +4284,6 @@ W83L51xD SD/MMC CARD INTERFACE DRIVER
 P:	Pierre Ossman
 P:	Pierre Ossman
 M:	drzeus-wbsd@drzeus.cx
 M:	drzeus-wbsd@drzeus.cx
 L:	linux-kernel@vger.kernel.org
 L:	linux-kernel@vger.kernel.org
-W:	http://projects.drzeus.cx/wbsd
 S:	Maintained
 S:	Maintained
 
 
 WATCHDOG DEVICE DRIVERS
 WATCHDOG DEVICE DRIVERS

+ 4 - 4
drivers/mmc/host/Kconfig

@@ -25,8 +25,8 @@ config MMC_PXA
 	  If unsure, say N.
 	  If unsure, say N.
 
 
 config MMC_SDHCI
 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
 	help
 	  This select the generic Secure Digital Host Controller Interface.
 	  This select the generic Secure Digital Host Controller Interface.
 	  It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
 	  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.
 	  module will be called tifm_sd.
 
 
 config MMC_SPI
 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 CRC7
 	select CRC_ITU_T
 	select CRC_ITU_T
 	help
 	help

+ 80 - 34
drivers/mmc/host/at91_mci.c

@@ -70,10 +70,11 @@
 
 
 #include <asm/io.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/irq.h>
+#include <asm/gpio.h>
+
 #include <asm/mach/mmc.h>
 #include <asm/mach/mmc.h>
 #include <asm/arch/board.h>
 #include <asm/arch/board.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/at91_mci.h>
 #include <asm/arch/at91_mci.h>
 
 
 #define DRIVER_NAME "at91_mci"
 #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) {
 	if (host->board->vcc_pin) {
 		switch (ios->power_mode) {
 		switch (ios->power_mode) {
 			case MMC_POWER_OFF:
 			case MMC_POWER_OFF:
-				at91_set_gpio_value(host->board->vcc_pin, 0);
+				gpio_set_value(host->board->vcc_pin, 0);
 				break;
 				break;
 			case MMC_POWER_UP:
 			case MMC_POWER_UP:
 			case MMC_POWER_ON:
 			case MMC_POWER_ON:
-				at91_set_gpio_value(host->board->vcc_pin, 1);
+				gpio_set_value(host->board->vcc_pin, 1);
 				break;
 				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)
 static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
 {
 {
 	struct at91mci_host *host = _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,
 	 * 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);
 	struct at91mci_host *host = mmc_priv(mmc);
 
 
 	if (host->board->wp_pin) {
 	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),
 		printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc),
 				(read_only ? "read-only" : "read-write") );
 				(read_only ? "read-only" : "read-write") );
 	}
 	}
@@ -820,8 +821,6 @@ static int __init at91_mci_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct resource *res;
 	int ret;
 	int ret;
 
 
-	pr_debug("Probe MCI devices\n");
-
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 	if (!res)
 		return -ENXIO;
 		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);
 	mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
 	if (!mmc) {
 	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;
 	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())
 		if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
 			mmc->caps |= MMC_CAP_4_BIT_DATA;
 			mmc->caps |= MMC_CAP_4_BIT_DATA;
 		else
 		else
-			printk("AT91 MMC: 4 wire bus mode not supported"
+			dev_warn(&pdev->dev, "4 wire bus mode not supported"
 				" - using 1 wire\n");
 				" - 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
 	 * Get Clock
 	 */
 	 */
 	host->mci_clk = clk_get(&pdev->dev, "mci_clk");
 	host->mci_clk = clk_get(&pdev->dev, "mci_clk");
 	if (IS_ERR(host->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);
 	host->baseaddr = ioremap(res->start, res->end - res->start + 1);
 	if (!host->baseaddr) {
 	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
 	 * Allocate the MCI interrupt
 	 */
 	 */
 	host->irq = platform_get_irq(pdev, 0);
 	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) {
 	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);
 	platform_set_drvdata(pdev, mmc);
@@ -907,8 +925,7 @@ static int __init at91_mci_probe(struct platform_device *pdev)
 	 * Add host to MMC layer
 	 * Add host to MMC layer
 	 */
 	 */
 	if (host->board->det_pin) {
 	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
 	else
 		host->present = -1;
 		host->present = -1;
@@ -919,15 +936,38 @@ static int __init at91_mci_probe(struct platform_device *pdev)
 	 * monitor card insertion/removal if we can
 	 * monitor card insertion/removal if we can
 	 */
 	 */
 	if (host->board->det_pin) {
 	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)
 		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");
 	pr_debug("Added MCI driver\n");
 
 
 	return 0;
 	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);
 	host = mmc_priv(mmc);
 
 
 	if (host->board->det_pin) {
 	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);
 		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);
 	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_disable(host->mci_clk);			/* Disable the peripheral clock */
 	clk_put(host->mci_clk);
 	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);
 	iounmap(host->baseaddr);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(res->start, res->end - res->start + 1);
 	release_mem_region(res->start, res->end - res->start + 1);

+ 134 - 28
drivers/mmc/host/ricoh_mmc.c

@@ -41,10 +41,91 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
 
 
 MODULE_DEVICE_TABLE(pci, pci_ids);
 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,
 static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
 				     const struct pci_device_id *ent)
 {
 {
 	u8 rev;
 	u8 rev;
+	u8 ctrlfound = 0;
 
 
 	struct pci_dev *fw_dev = NULL;
 	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,
 		pci_name(pdev), (int)pdev->vendor, (int)pdev->device,
 		(int)rev);
 		(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) &&
 		if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
 		    pdev->bus == fw_dev->bus) {
 		    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;
 				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);
 			pci_set_drvdata(pdev, fw_dev);
 
 
-			printk(KERN_INFO DRIVER_NAME
-			       ": Controller is now disabled.\n");
-
+			++ctrlfound;
 			break;
 			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
 		printk(KERN_WARNING DRIVER_NAME
 		       ": Main firewire function not found. Cannot disable controller.\n");
 		       ": Main firewire function not found. Cannot disable controller.\n");
 		return -ENODEV;
 		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)
 static void __devexit ricoh_mmc_remove(struct pci_dev *pdev)
 {
 {
-	u8 write_enable;
-	u8 disable;
 	struct pci_dev *fw_dev = NULL;
 	struct pci_dev *fw_dev = NULL;
 
 
 	fw_dev = pci_get_drvdata(pdev);
 	fw_dev = pci_get_drvdata(pdev);
 	BUG_ON(fw_dev == NULL);
 	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);
 	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 = {
 static struct pci_driver ricoh_mmc_driver = {
 	.name = 	DRIVER_NAME,
 	.name = 	DRIVER_NAME,
 	.id_table =	pci_ids,
 	.id_table =	pci_ids,
 	.probe = 	ricoh_mmc_probe,
 	.probe = 	ricoh_mmc_probe,
 	.remove =	__devexit_p(ricoh_mmc_remove),
 	.remove =	__devexit_p(ricoh_mmc_remove),
+	.suspend =	ricoh_mmc_suspend,
+	.resume =	ricoh_mmc_resume,
 };
 };
 
 
 /*****************************************************************************\
 /*****************************************************************************\

+ 12 - 1
drivers/mmc/host/sdhci.c

@@ -30,6 +30,10 @@
 
 
 static unsigned int debug_quirks = 0;
 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
  * Different quirks to handle when the hardware deviates from a strict
  * interpretation of the SDHCI specification.
  * 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);
 	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);
 	ret = pci_request_region(pdev, host->bar, host->slot_descr);
 	if (ret)
 	if (ret)
@@ -1585,6 +1589,11 @@ static int __devinit sdhci_probe(struct pci_dev *pdev,
 	chip->num_slots = slots;
 	chip->num_slots = slots;
 	pci_set_drvdata(pdev, chip);
 	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++) {
 	for (i = 0;i < slots;i++) {
 		ret = sdhci_probe_slot(pdev, i);
 		ret = sdhci_probe_slot(pdev, i);
 		if (ret) {
 		if (ret) {
@@ -1645,6 +1654,8 @@ static int __init sdhci_drv_init(void)
 		": Secure Digital Host Controller Interface driver\n");
 		": Secure Digital Host Controller Interface driver\n");
 	printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
 	printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
 
 
+	spin_lock_init(&index_lock);
+
 	return pci_register_driver(&sdhci_driver);
 	return pci_register_driver(&sdhci_driver);
 }
 }
 
 

+ 1 - 0
drivers/mmc/host/sdhci.h

@@ -208,6 +208,7 @@ struct sdhci_chip {
 
 
 	unsigned long		quirks;
 	unsigned long		quirks;
 
 
+	int			index;		/* Index for chip0, chip1 ...*/
 	int			num_slots;	/* Slots on controller */
 	int			num_slots;	/* Slots on controller */
 	struct sdhci_host	*hosts[0];	/* Pointers to hosts */
 	struct sdhci_host	*hosts[0];	/* Pointers to hosts */
 };
 };