summaryrefslogtreecommitdiff
path: root/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-mmc-driver-1.0.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-mmc-driver-1.0.patch')
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-mmc-driver-1.0.patch1367
1 files changed, 0 insertions, 1367 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-mmc-driver-1.0.patch b/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-mmc-driver-1.0.patch
deleted file mode 100644
index b93f76a8e..000000000
--- a/meta-moblin/packages/linux/linux-moblin-2.6.33.2/linux-2.6.34-moorestown-mmc-driver-1.0.patch
+++ /dev/null
@@ -1,1367 +0,0 @@
-From bac1959b76f55a7845b0bb20eafd32e40c49dd74 Mon Sep 17 00:00:00 2001
-From: JiebingLi <jiebing.li@intel.com>
-Date: Wed, 25 Nov 2009 19:43:03 +0800
-Subject: [PATCH 077/104] MMC driver Beta 1.0 It is a consolidated patch against upstream Linux 2.6.31.6
-
-Beta features:
-1. removed CEATA function from MMC bus driver
-2. Added 25MHz support at High-Speed mode for SDIO Comms devices
-3. Added eMMC support for Moorestown platform
-4. Fixed sighting 3469229 and 3452438
-
-Kernel configuration:
-CONFIG_MMC=y
-CONFIG_MRST_LNW_A2_WR=y
-CONFIG_SDIO_SUSPEND=y
-CONFIG_MMC_BLOCK=y
-CONFIG_MMC_BLOCK_BOUNCE=y
-CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_PCI=y
-
-Note: Please DO NOT enable CONFIG_MMC_SDHCI_MRST_EMMC unless you
- are sure that you want to enable eMMC device for Moorestown.
-
-Signed-off-by: JiebingLi <jiebing.li@intel.com>
----
- drivers/mmc/Kconfig | 14 ++
- drivers/mmc/card/block.c | 3 +-
- drivers/mmc/core/Kconfig | 11 +
- drivers/mmc/core/core.c | 6 +
- drivers/mmc/core/mmc.c | 41 ++++-
- drivers/mmc/core/sd.c | 8 +
- drivers/mmc/core/sdio.c | 464 +++++++++++++++++++++++++++++++++++++++++
- drivers/mmc/core/sdio_bus.c | 38 ++++
- drivers/mmc/core/sdio_bus.h | 4 +
- drivers/mmc/host/Kconfig | 10 +
- drivers/mmc/host/sdhci-pci.c | 81 ++++++--
- drivers/mmc/host/sdhci.c | 125 ++++++++++-
- drivers/mmc/host/sdhci.h | 3 +
- include/linux/mmc/card.h | 12 +
- include/linux/mmc/host.h | 2 +
- include/linux/mmc/sdio_func.h | 14 ++
- include/linux/pci_ids.h | 2 +
- 17 files changed, 810 insertions(+), 28 deletions(-)
-
-diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
-index f2eeb38..2c19682 100644
---- a/drivers/mmc/Kconfig
-+++ b/drivers/mmc/Kconfig
-@@ -19,6 +19,20 @@ config MMC_DEBUG
- This is an option for use by developers; most people should
- say N here. This enables MMC core and driver debugging.
-
-+config MRST_LNW_A1_WR
-+ bool "software workaround for Moorestown LNW A-1"
-+ depends on MMC
-+ help
-+ This is an option for Moorestown developers to add workaround
-+ in the code due to LNW A-1 Silicon restrictions.
-+
-+config MRST_LNW_A2_WR
-+ bool "software workaround for Moorestown LNW A-2"
-+ depends on MMC
-+ help
-+ This is an option for Moorestown developers to add workaround
-+ in the code due to LNW A-2 Silicon restrictions.
-+
- if MMC
-
- source "drivers/mmc/core/Kconfig"
-diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
-index 1f552c6..f4ebc68 100644
---- a/drivers/mmc/card/block.c
-+++ b/drivers/mmc/card/block.c
-@@ -534,7 +534,8 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
- * messages to tell when the card is present.
- */
-
-- sprintf(md->disk->disk_name, "mmcblk%d", devidx);
-+ snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
-+ "mmcblk%d", devidx);
-
- blk_queue_logical_block_size(md->queue.queue, 512);
-
-diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
-index bb22ffd..205186c 100644
---- a/drivers/mmc/core/Kconfig
-+++ b/drivers/mmc/core/Kconfig
-@@ -16,3 +16,14 @@ config MMC_UNSAFE_RESUME
-
- This option sets a default which can be overridden by the
- module parameter "removable=0" or "removable=1".
-+
-+config SDIO_SUSPEND
-+ bool "SDIO selective suspend/resume"
-+ depends on MMC && PM
-+ help
-+ If you say Y here, you can use driver calls or the sysfs
-+ "power/level" file to suspend or resume the SDIO
-+ peripherals.
-+
-+ If you are unsure about this, say N here.
-+
-diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
-index 30acd52..951561d 100644
---- a/drivers/mmc/core/core.c
-+++ b/drivers/mmc/core/core.c
-@@ -213,9 +213,15 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
- mrq->done_data = &complete;
- mrq->done = mmc_wait_done;
-
-+ if (host->port_mutex)
-+ mutex_lock(host->port_mutex);
-+
- mmc_start_request(host, mrq);
-
- wait_for_completion(&complete);
-+
-+ if (host->port_mutex)
-+ mutex_unlock(host->port_mutex);
- }
-
- EXPORT_SYMBOL(mmc_wait_for_req);
-diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
-index 0eac6c8..15aaa66 100644
---- a/drivers/mmc/core/mmc.c
-+++ b/drivers/mmc/core/mmc.c
-@@ -179,8 +179,10 @@ static int mmc_read_ext_csd(struct mmc_card *card)
-
- err = mmc_send_ext_csd(card, ext_csd);
- if (err) {
-- /* If the host or the card can't do the switch,
-- * fail more gracefully. */
-+ /*
-+ * If the host or the card can't do the switch,
-+ * fail more gracefully.
-+ */
- if ((err != -EINVAL)
- && (err != -ENOSYS)
- && (err != -EFAULT))
-@@ -294,6 +296,28 @@ static struct device_type mmc_type = {
- };
-
- /*
-+ * Distinguish the fake MMCA4 MMC card.
-+ *
-+ * Transcend 2GB MMC card is a kind of MMCA3.31 MMC card.
-+ * However, it makes up itself as a MMCA4 one via SPEC_VERS
-+ * field of its CSD register. Once it's treated as MMCA4 by
-+ * driver, 4 bit bus is activated which leads to data error.
-+ */
-+static bool fake_mmca4_card(struct mmc_card *card)
-+{
-+ if (card->cid.manfid == 0x1e &&
-+ card->cid.oemid == 0xffff &&
-+ card->cid.prod_name[0] == 'M' &&
-+ card->cid.prod_name[1] == 'M' &&
-+ card->cid.prod_name[2] == 'C' &&
-+ card->cid.month == 9 &&
-+ card->cid.year == 2008)
-+ return true;
-+ else
-+ return false;
-+}
-+
-+/*
- * Handle the detection and initialisation of a card.
- *
- * In the case of a resume, "oldcard" will contain the card
-@@ -389,6 +413,12 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
- err = mmc_decode_cid(card);
- if (err)
- goto free_card;
-+
-+ /*
-+ * Get card's true specification version
-+ */
-+ if (fake_mmca4_card(card))
-+ card->csd.mmca_vsn = CSD_SPEC_VER_3;
- }
-
- /*
-@@ -409,6 +439,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
- goto free_card;
- }
-
-+/*
-+ * avoid MMC cards to switch to HS timing
-+ * which doesn't work yet due to LNW A-1 Silicon bug
-+ */
-+#if !defined CONFIG_MRST_LNW_A1_WR && !defined CONFIG_MRST_LNW_A2_WR
- /*
- * Activate high speed (if supported)
- */
-@@ -428,7 +463,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
- mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
- }
- }
--
-+#endif
- /*
- * Compute bus speed.
- */
-diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
-index fdd414e..5aae661 100644
---- a/drivers/mmc/core/sd.c
-+++ b/drivers/mmc/core/sd.c
-@@ -234,6 +234,7 @@ out:
- return err;
- }
-
-+#if !defined CONFIG_MRST_LNW_A1_WR && !defined CONFIG_MRST_LNW_A2_WR
- /*
- * Test if the card supports high-speed mode and, if so, switch to it.
- */
-@@ -281,6 +282,7 @@ out:
-
- return err;
- }
-+#endif
-
- MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
- card->raw_cid[2], card->raw_cid[3]);
-@@ -460,12 +462,18 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
- goto free_card;
- }
-
-+/*
-+ * avoid SD cards to switch to HS timing
-+ * which doesn't work yet due to LNW A-1 Silicon bug
-+ */
-+#if !defined CONFIG_MRST_LNW_A1_WR && !defined CONFIG_MRST_LNW_A2_WR
- /*
- * Attempt to change to high-speed (if supported)
- */
- err = mmc_switch_hs(card);
- if (err)
- goto free_card;
-+#endif
-
- /*
- * Compute bus speed.
-diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
-index 06b6408..42977e1 100644
---- a/drivers/mmc/core/sdio.c
-+++ b/drivers/mmc/core/sdio.c
-@@ -24,6 +24,262 @@
- #include "sdio_ops.h"
- #include "sdio_cis.h"
-
-+#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv)
-+
-+#ifdef CONFIG_SDIO_SUSPEND
-+
-+static int sdio_suspend_func(struct mmc_card *card,
-+ struct sdio_func *func, pm_message_t msg)
-+{
-+ struct device *dev;
-+ int error = 0;
-+
-+ dev = &func->dev;
-+ BUG_ON(!dev);
-+
-+ if (dev->bus)
-+ if (dev->bus->suspend)
-+ error = dev->bus->suspend(dev, msg);
-+
-+ return error;
-+}
-+
-+static int sdio_resume_func(struct mmc_card *card, struct sdio_func *func)
-+{
-+ struct device *dev;
-+ int error = 0;
-+
-+ dev = &func->dev;
-+ BUG_ON(!dev);
-+
-+ if (dev->bus)
-+ if (dev->bus->resume)
-+ error = dev->bus->resume(dev);
-+
-+ return error;
-+}
-+
-+int sdio_suspend_host(struct mmc_card *card, pm_message_t msg)
-+{
-+ int ret = 0;
-+ int i = 0;
-+ struct device *dev;
-+ struct sdio_driver *drv;
-+
-+ mutex_lock(&card->pm_mutex);
-+
-+ if (!mmc_card_present(card) ||
-+ mmc_card_suspended(card))
-+ goto done;
-+
-+ for (i = 0; i < card->sdio_funcs; i++)
-+ if (!sdio_func_suspended(card->sdio_func[i])) {
-+ dev = &(card->sdio_func[i])->dev;
-+ BUG_ON(!dev);
-+
-+ drv = to_sdio_driver(dev->driver);
-+
-+ if (dev->driver && drv->suspend)
-+ goto done;
-+ }
-+
-+ ret = mmc_suspend_host(card->host, msg);
-+
-+ if (ret == 0)
-+ mmc_card_set_suspended(card);
-+
-+done:
-+ mutex_unlock(&card->pm_mutex);
-+
-+ return ret;
-+}
-+
-+int sdio_resume_host(struct mmc_card *card)
-+{
-+ int ret = 0;
-+
-+ mutex_lock(&card->pm_mutex);
-+
-+ if (!mmc_card_present(card)) {
-+ ret = -ENODEV;
-+ goto done;
-+ }
-+
-+ if (mmc_card_suspended(card)) {
-+ ret = mmc_resume_host(card->host);
-+
-+ if (ret == 0)
-+ mmc_card_clear_suspended(card);
-+ else
-+ goto done;
-+ }
-+
-+done:
-+ mutex_unlock(&card->pm_mutex);
-+
-+ return ret;
-+}
-+
-+/*
-+ * This routine handles external suspend request coming from sysfs
-+ */
-+int sdio_external_suspend_device(struct sdio_func *func, pm_message_t msg)
-+{
-+ int ret = 0;
-+ struct mmc_card *card = func->card;
-+
-+ BUG_ON(!card);
-+ BUG_ON(!card->host);
-+
-+ mutex_lock(&card->pm_mutex);
-+
-+ if (!sdio_func_present(func) ||
-+ sdio_func_suspended(func)) {
-+ mutex_unlock(&card->pm_mutex);
-+ goto done;
-+ }
-+
-+ /* suspend the function of the SDIO device */
-+ ret = sdio_suspend_func(card, func, msg);
-+
-+ if (ret != 0) {
-+ mutex_unlock(&card->pm_mutex);
-+ goto done;
-+ }
-+
-+ sdio_func_set_suspended(func);
-+
-+ mutex_unlock(&card->pm_mutex);
-+
-+ ret = sdio_suspend_host(card, msg);
-+
-+done:
-+ return ret;
-+}
-+
-+/*
-+ * This routine handles external resume request coming from sysfs
-+ */
-+int sdio_external_resume_device(struct sdio_func *func)
-+{
-+ int ret = 0;
-+ struct mmc_card *card = func->card;
-+
-+ BUG_ON(!card);
-+ BUG_ON(!card->host);
-+
-+ ret = sdio_resume_host(card);
-+ if (ret)
-+ goto done;
-+
-+ mutex_lock(&card->pm_mutex);
-+
-+ if (sdio_func_suspended(func)) {
-+ ret = sdio_resume_func(card, func);
-+
-+ if (ret != 0) {
-+ mutex_unlock(&card->pm_mutex);
-+ goto done;
-+ } else
-+ sdio_func_clear_suspended(func);
-+ }
-+
-+ mutex_unlock(&card->pm_mutex);
-+done:
-+
-+ return ret;
-+}
-+
-+static const char power_group[] = "power";
-+
-+static const char resume_string[] = "resume";
-+static const char suspend_string[] = "suspend";
-+
-+static ssize_t
-+show_level(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+ struct sdio_func *func = container_of(dev, struct sdio_func, dev);
-+ const char *p = suspend_string;
-+
-+ BUG_ON(!func);
-+
-+ if (sdio_func_suspended(func))
-+ p = suspend_string;
-+ else
-+ p = resume_string;
-+
-+ return sprintf(buf, "%s\n", p);
-+}
-+
-+static ssize_t
-+set_level(struct device *dev, struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ struct sdio_func *func = container_of(dev, struct sdio_func, dev);
-+ int len = count;
-+ char *cp;
-+ int ret = 0;
-+
-+ BUG_ON(!func);
-+
-+ cp = memchr(buf, '\n', count);
-+ if (cp)
-+ len = cp - buf;
-+
-+ down(&dev->sem);
-+
-+ if (len == sizeof resume_string - 1 &&
-+ strncmp(buf, resume_string, len) == 0) {
-+ ret = sdio_external_resume_device(func);
-+ } else if (len == sizeof suspend_string - 1 &&
-+ strncmp(buf, suspend_string, len) == 0) {
-+ ret = sdio_external_suspend_device(func, PMSG_SUSPEND);
-+ } else {
-+ ret = -EINVAL;
-+ }
-+
-+ up(&dev->sem);
-+
-+ return (ret < 0 ? ret : count);
-+}
-+
-+static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
-+
-+void sdio_remove_sysfs_file(struct sdio_func *func)
-+{
-+ struct device *dev = &func->dev;
-+ struct sdio_driver *drv = to_sdio_driver(dev->driver);
-+
-+ if (dev->driver && drv->suspend)
-+ sysfs_remove_file_from_group(&dev->kobj,
-+ &dev_attr_level.attr,
-+ power_group);
-+}
-+
-+int sdio_create_sysfs_file(struct sdio_func *func)
-+{
-+ int ret;
-+ struct device *dev = &func->dev;
-+ struct sdio_driver *drv = to_sdio_driver(dev->driver);
-+
-+ if (dev->driver && drv->suspend) {
-+ ret = sysfs_add_file_to_group(&dev->kobj,
-+ &dev_attr_level.attr,
-+ power_group);
-+
-+ if (ret)
-+ goto error;
-+ }
-+
-+ return 0;
-+
-+error:
-+ sdio_remove_sysfs_file(func);
-+ return ret;
-+}
-+
-+#endif /* CONFIG_SDIO_SUSPEND */
-+
- static int sdio_read_fbr(struct sdio_func *func)
- {
- int ret;
-@@ -187,6 +443,7 @@ static int sdio_disable_cd(struct mmc_card *card)
- return mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
- }
-
-+#if !defined(CONFIG_MRST_LNW_A1_WR) && !defined(CONFIG_MRST_LNW_A2_WR)
- /*
- * Test if the card supports high-speed mode and, if so, switch to it.
- */
-@@ -216,6 +473,128 @@ static int sdio_enable_hs(struct mmc_card *card)
-
- return 0;
- }
-+#else
-+static int sdio_enable_hs(struct mmc_card *card)
-+{
-+ return 0;
-+}
-+#endif
-+
-+/*
-+ * Handle the re-initialization of a SDIO card.
-+ */
-+static int mmc_sdio_reinit_card(struct mmc_host *host,
-+ struct mmc_card *oldcard)
-+{
-+ int err = 0;
-+ u16 funcs;
-+ u32 ocr;
-+ struct mmc_card *card;
-+
-+#if !defined(CONFIG_MRST_LNW_A1_WR) && !defined(CONFIG_MRST_LNW_A2_WR)
-+ unsigned int max_dtr;
-+#endif
-+
-+ BUG_ON(!host);
-+ WARN_ON(!host->claimed);
-+
-+ if (!oldcard)
-+ goto err;
-+
-+ card = oldcard;
-+
-+ err = mmc_send_io_op_cond(host, 0, &ocr);
-+ if (err)
-+ goto remove;
-+
-+ /*
-+ * Inform the card of the voltage
-+ */
-+ err = mmc_send_io_op_cond(host, host->ocr, &ocr);
-+ if (err)
-+ goto remove;
-+
-+ /*
-+ * For SPI, enable CRC as appropriate.
-+ */
-+ if (mmc_host_is_spi(host)) {
-+ err = mmc_spi_set_crc(host, use_spi_crc);
-+ if (err)
-+ goto remove;
-+ }
-+
-+ funcs = (ocr & 0x70000000) >> 28;
-+
-+ if (funcs != card->sdio_funcs)
-+ printk(KERN_INFO "funcs number is changed from OCR register after suspend!\n");
-+
-+ if (!mmc_host_is_spi(host)) {
-+ err = mmc_send_relative_addr(host, &card->rca);
-+ if (err)
-+ goto remove;
-+
-+ mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
-+ }
-+
-+ /*
-+ * Select card, as all following commands rely on that.
-+ */
-+ if (!mmc_host_is_spi(host)) {
-+ err = mmc_select_card(card);
-+ if (err)
-+ goto remove;
-+ }
-+
-+ /*
-+ * Read the common CIS tuples.
-+ */
-+ err = sdio_read_cccr(card);
-+ if (err)
-+ goto remove;
-+
-+#if defined(CONFIG_MRST_LNW_A1_WR) || defined(CONFIG_MRST_LNW_A2_WR)
-+ /* restricting to 24MHz for Langwell A0 */
-+ if (card->cis.max_dtr > 24000000)
-+ card->cis.max_dtr = 24000000;
-+
-+ mmc_set_clock(host, card->cis.max_dtr);
-+#else
-+ /*
-+ * Switch to high-speed (if supported).
-+ */
-+ err = sdio_enable_hs(card);
-+ if (err)
-+ goto remove;
-+
-+ max_dtr = card->cis.max_dtr;
-+
-+ /*
-+ * Change to the card's maximum speed.
-+ */
-+ if (mmc_card_highspeed(card)) {
-+ if (max_dtr > 50000000)
-+ max_dtr = 50000000;
-+ } else if (max_dtr > 25000000)
-+ max_dtr = 25000000;
-+
-+ mmc_set_clock(host, max_dtr);
-+#endif
-+
-+ /*
-+ * Switch to wider bus (if supported).
-+ */
-+ err = sdio_enable_wide(card);
-+ if (err)
-+ goto remove;
-+
-+ host->card = card;
-+
-+ return 0;
-+
-+remove:
-+err:
-+ return err;
-+}
-
- /*
- * Handle the detection and initialisation of a card.
-@@ -478,6 +857,10 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
- int i, funcs;
- struct mmc_card *card;
-
-+#if !defined(CONFIG_MRST_LNW_A1_WR) && !defined(CONFIG_MRST_LNW_A2_WR)
-+ unsigned int max_dtr;
-+#endif
-+
- BUG_ON(!host);
- WARN_ON(!host->claimed);
-
-@@ -574,3 +957,84 @@ err:
- return err;
- }
-
-+/*
-+ * warn device driver and perform a SDIO device reset.
-+ * Assume that device driver knows hot to handle resets.
-+ */
-+int sdio_reset_device(struct mmc_card *card)
-+{
-+ int ret = 0;
-+ int i = 0;
-+ u8 reg = 0;
-+
-+ BUG_ON(!card);
-+ BUG_ON(!card->host);
-+ BUG_ON(!card->sdio_func);
-+
-+ if (!mmc_card_present(card) ||
-+ mmc_card_suspended(card)) {
-+ dev_dbg(&card->dev, "device reset not allowed\n");
-+ return -EINVAL;
-+ }
-+
-+ for (; i < card->sdio_funcs; i++) {
-+ struct sdio_func *func = card->sdio_func[i];
-+ struct sdio_driver *drv;
-+
-+ if (func && func->dev.driver) {
-+ drv = to_sdio_driver(func->dev.driver);
-+ if (drv->pre_reset) {
-+ ret = (drv->pre_reset)(func);
-+ if (ret)
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (ret)
-+ goto err;
-+
-+ /* reset SDIO card via CMD52 */
-+ mmc_claim_host(card->host);
-+
-+ ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_ABORT, 0, &reg);
-+
-+ if (ret)
-+ reg = 0x08;
-+ else
-+ reg |= 0x08;
-+
-+ mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_ABORT, reg, NULL);
-+
-+ /* re-enumerate the device */
-+ ret = mmc_sdio_reinit_card(card->host, card);
-+
-+ mmc_release_host(card->host);
-+
-+ if (ret)
-+ goto err;
-+
-+ for (i = card->sdio_funcs - 1; i >= 0; i--) {
-+ struct sdio_func *func = card->sdio_func[i];
-+ struct sdio_driver *drv;
-+
-+ if (func && func->dev.driver) {
-+ drv = to_sdio_driver(func->dev.driver);
-+ if (drv->post_reset) {
-+ ret = (drv->post_reset)(func);
-+ if (ret)
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (ret)
-+ goto err;
-+
-+ return 0;
-+
-+err:
-+ return -EINVAL;
-+
-+}
-+EXPORT_SYMBOL_GPL(sdio_reset_device);
-diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
-index 9e060c8..84414e8 100644
---- a/drivers/mmc/core/sdio_bus.c
-+++ b/drivers/mmc/core/sdio_bus.c
-@@ -124,6 +124,14 @@ static int sdio_bus_probe(struct device *dev)
- if (!id)
- return -ENODEV;
-
-+ /*
-+ * create the user interface to call suspend/resume
-+ * from susfs
-+ */
-+#ifdef CONFIG_SDIO_SUSPEND
-+ sdio_create_sysfs_file(func);
-+#endif
-+
- /* Set the default block size so the driver is sure it's something
- * sensible. */
- sdio_claim_host(func);
-@@ -140,6 +148,10 @@ static int sdio_bus_remove(struct device *dev)
- struct sdio_driver *drv = to_sdio_driver(dev->driver);
- struct sdio_func *func = dev_to_sdio_func(dev);
-
-+#ifdef CONFIG_SDIO_SUSPEND
-+ sdio_remove_sysfs_file(func);
-+#endif
-+
- drv->remove(func);
-
- if (func->irq_handler) {
-@@ -153,6 +165,30 @@ static int sdio_bus_remove(struct device *dev)
- return 0;
- }
-
-+static int sdio_bus_suspend(struct device *dev, pm_message_t state)
-+{
-+ struct sdio_driver *drv = to_sdio_driver(dev->driver);
-+ struct sdio_func *func = dev_to_sdio_func(dev);
-+ int ret = 0;
-+
-+ if (dev->driver && drv->suspend)
-+ ret = drv->suspend(func, state);
-+
-+ return ret;
-+}
-+
-+static int sdio_bus_resume(struct device *dev)
-+{
-+ struct sdio_driver *drv = to_sdio_driver(dev->driver);
-+ struct sdio_func *func = dev_to_sdio_func(dev);
-+ int ret = 0;
-+
-+ if (dev->driver && drv->resume)
-+ ret = drv->resume(func);
-+
-+ return ret;
-+}
-+
- static struct bus_type sdio_bus_type = {
- .name = "sdio",
- .dev_attrs = sdio_dev_attrs,
-@@ -160,6 +196,8 @@ static struct bus_type sdio_bus_type = {
- .uevent = sdio_bus_uevent,
- .probe = sdio_bus_probe,
- .remove = sdio_bus_remove,
-+ .suspend = sdio_bus_suspend,
-+ .resume = sdio_bus_resume,
- };
-
- int sdio_register_bus(void)
-diff --git a/drivers/mmc/core/sdio_bus.h b/drivers/mmc/core/sdio_bus.h
-index 567a768..18616b2 100644
---- a/drivers/mmc/core/sdio_bus.h
-+++ b/drivers/mmc/core/sdio_bus.h
-@@ -18,5 +18,9 @@ void sdio_remove_func(struct sdio_func *func);
- int sdio_register_bus(void);
- void sdio_unregister_bus(void);
-
-+#ifdef CONFIG_SDIO_SUSPEND
-+int sdio_create_sysfs_file(struct sdio_func *func);
-+void sdio_remove_sysfs_file(struct sdio_func *func);
-+#endif
- #endif
-
-diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
-index ce1d288..521cf2e 100644
---- a/drivers/mmc/host/Kconfig
-+++ b/drivers/mmc/host/Kconfig
-@@ -68,6 +68,16 @@ config MMC_SDHCI_PCI
-
- If unsure, say N.
-
-+config MMC_SDHCI_MRST_EMMC
-+ tristate "Enable eMMC device on MRST"
-+ depends on MMC_SDHCI && PCI
-+ help
-+ This enables eMMC device for MRST platform.
-+
-+ If you're using eMMC device on Moorestown, say Y or M here.
-+
-+ If unsure, say N.
-+
- config MMC_RICOH_MMC
- tristate "Ricoh MMC Controller Disabler (EXPERIMENTAL)"
- depends on MMC_SDHCI_PCI
-diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
-index 5c3a176..53f3719 100644
---- a/drivers/mmc/host/sdhci-pci.c
-+++ b/drivers/mmc/host/sdhci-pci.c
-@@ -38,6 +38,8 @@
-
- #define MAX_SLOTS 8
-
-+static struct mutex port_mutex;
-+
- struct sdhci_pci_chip;
- struct sdhci_pci_slot;
-
-@@ -364,6 +366,17 @@ static const struct sdhci_pci_fixes sdhci_via = {
- .probe = via_probe,
- };
-
-+/*
-+ * ADMA operation is disabled for Moorestown platform.
-+ */
-+static const struct sdhci_pci_fixes sdhci_intel_mrst = {
-+ .quirks = SDHCI_QUIRK_BROKEN_ADMA |
-+#ifdef CONFIG_MMC_SDHCI_MRST_EMMC
-+ SDHCI_QUIRK_BROKEN_CARD_DETECTION |
-+#endif
-+ SDHCI_QUIRK_MRST_RESTRICTION,
-+};
-+
- static const struct pci_device_id pci_ids[] __devinitdata = {
- {
- .vendor = PCI_VENDOR_ID_RICOH,
-@@ -445,6 +458,22 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
- .driver_data = (kernel_ulong_t)&sdhci_via,
- },
-
-+ {
-+ .vendor = PCI_VENDOR_ID_INTEL,
-+ .device = PCI_DEVICE_ID_INTEL_MRST_SD0,
-+ .subvendor = PCI_ANY_ID,
-+ .subdevice = PCI_ANY_ID,
-+ .driver_data = (kernel_ulong_t)&sdhci_intel_mrst,
-+ },
-+
-+ {
-+ .vendor = PCI_VENDOR_ID_INTEL,
-+ .device = PCI_DEVICE_ID_INTEL_MRST_SD1,
-+ .subvendor = PCI_ANY_ID,
-+ .subdevice = PCI_ANY_ID,
-+ .driver_data = (kernel_ulong_t)&sdhci_intel_mrst,
-+ },
-+
- { /* Generic SD host controller */
- PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
- },
-@@ -469,11 +498,14 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)
- slot = sdhci_priv(host);
- pdev = slot->chip->pdev;
-
-- if (((pdev->class & 0xFFFF00) == (PCI_CLASS_SYSTEM_SDHCI << 8)) &&
-- ((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA) &&
-- (host->flags & SDHCI_USE_SDMA)) {
-- dev_warn(&pdev->dev, "Will use DMA mode even though HW "
-- "doesn't fully claim to support it.\n");
-+ if (!(host->quirks & SDHCI_QUIRK_MRST_RESTRICTION)) {
-+ if (((pdev->class & 0xFFFF00) ==
-+ (PCI_CLASS_SYSTEM_SDHCI << 8)) &&
-+ ((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA) &&
-+ (host->flags & SDHCI_USE_SDMA)) {
-+ dev_warn(&pdev->dev, "Will use DMA mode even though HW "
-+ "doesn't fully claim to support it.\n");
-+ }
- }
-
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-@@ -622,6 +654,9 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
- return ERR_PTR(PTR_ERR(host));
- }
-
-+ if (pdev->device == PCI_DEVICE_ID_INTEL_MRST_SD0)
-+ host->mmc->port_mutex = &port_mutex;
-+
- slot = sdhci_priv(host);
-
- slot->chip = chip;
-@@ -712,22 +747,42 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
- dev_info(&pdev->dev, "SDHCI controller found [%04x:%04x] (rev %x)\n",
- (int)pdev->vendor, (int)pdev->device, (int)rev);
-
-- ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots);
-- if (ret)
-- return ret;
-+ /*
-+ * slots number is fixed to 2 by Moorestown architecture
-+ */
-+ if (pdev->device == PCI_DEVICE_ID_INTEL_MRST_SD0) {
-+ slots = 2;
-+ mutex_init(&port_mutex);
-+ } else if (pdev->device == PCI_DEVICE_ID_INTEL_MRST_SD1)
-+ slots = 1;
-+ else {
-+ ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots);
-+
-+ if (ret)
-+ return ret;
-+
-+ slots = PCI_SLOT_INFO_SLOTS(slots) + 1;
-+ }
-
-- slots = PCI_SLOT_INFO_SLOTS(slots) + 1;
- dev_dbg(&pdev->dev, "found %d slot(s)\n", slots);
- if (slots == 0)
- return -ENODEV;
-
- BUG_ON(slots > MAX_SLOTS);
-
-- ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar);
-- if (ret)
-- return ret;
-+ /*
-+ * first BAR is fixed to 0 by Moorestown architecture
-+ */
-+ if (pdev->device == PCI_DEVICE_ID_INTEL_MRST_SD0 ||
-+ pdev->device == PCI_DEVICE_ID_INTEL_MRST_SD1) {
-+ first_bar = 0;
-+ } else {
-+ ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar);
-+ if (ret)
-+ return ret;
-
-- first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK;
-+ first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK;
-+ }
-
- if (first_bar > 5) {
- dev_err(&pdev->dev, "Invalid first BAR. Aborting.\n");
-diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
-index c279fbc..ff26db0 100644
---- a/drivers/mmc/host/sdhci.c
-+++ b/drivers/mmc/host/sdhci.c
-@@ -161,9 +161,11 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
- /* hw clears the bit when it's done */
- while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
- if (timeout == 0) {
-+#ifndef CONFIG_MRST_LNW_A2_WR
- printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
- mmc_hostname(host->mmc), (int)mask);
- sdhci_dumpregs(host);
-+#endif
- return;
- }
- timeout--;
-@@ -176,13 +178,25 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
-
- static void sdhci_init(struct sdhci_host *host)
- {
-+ u32 intmask;
-+
-+ intmask = sdhci_readl(host, SDHCI_INT_STATUS);
-+ sdhci_writel(host,
-+ intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
-+ SDHCI_INT_STATUS);
-+
-+#ifndef CONFIG_MRST_LNW_A2_WR
- sdhci_reset(host, SDHCI_RESET_ALL);
-+#endif
-
- sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
- SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
- SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
- SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
- SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);
-+
-+ /* disable wakeup signal during initialization */
-+ sdhci_writeb(host, 0x0, SDHCI_WAKE_UP_CONTROL);
- }
-
- static void sdhci_reinit(struct sdhci_host *host)
-@@ -465,6 +479,54 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
- len -= offset;
- }
-
-+#if defined(CONFIG_MRST_LNW_A1_WR) || defined(CONFIG_MRST_LNW_A2_WR)
-+ if (len != 65536) {
-+ desc[7] = (addr >> 24) & 0xff;
-+ desc[6] = (addr >> 16) & 0xff;
-+ desc[5] = (addr >> 8) & 0xff;
-+ desc[4] = (addr >> 0) & 0xff;
-+
-+ BUG_ON(len > 65536);
-+
-+ desc[3] = (len >> 8) & 0xff;
-+ desc[2] = (len >> 0) & 0xff;
-+
-+ desc[1] = 0x00;
-+ desc[0] = 0x21; /* tran, valid */
-+
-+ desc += 8;
-+ } else {
-+ desc[7] = (addr >> 24) & 0xff;
-+ desc[6] = (addr >> 16) & 0xff;
-+ desc[5] = (addr >> 8) & 0xff;
-+ desc[4] = (addr >> 0) & 0xff;
-+
-+ desc[3] = (32768 >> 8) & 0xff;
-+ desc[2] = (32768 >> 0) & 0xff;
-+
-+ desc[1] = 0x00;
-+ desc[0] = 0x21; /* tran, valid */
-+
-+ desc += 8;
-+
-+ /* 2nd */
-+ addr += 32768;
-+
-+ desc[7] = (addr >> 24) & 0xff;
-+ desc[6] = (addr >> 16) & 0xff;
-+ desc[5] = (addr >> 8) & 0xff;
-+ desc[4] = (addr >> 0) & 0xff;
-+
-+ desc[3] = (32768 >> 8) & 0xff;
-+ desc[2] = (32768 >> 0) & 0xff;
-+
-+ desc[1] = 0x00;
-+ desc[0] = 0x21; /* tran, valid */
-+
-+ desc += 8;
-+ }
-+#else
-+
- desc[7] = (addr >> 24) & 0xff;
- desc[6] = (addr >> 16) & 0xff;
- desc[5] = (addr >> 8) & 0xff;
-@@ -479,7 +541,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
- desc[0] = 0x21; /* tran, valid */
-
- desc += 8;
--
-+#endif
- /*
- * If this triggers then we have a calculation bug
- * somewhere. :/
-@@ -487,6 +549,11 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
- WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4);
- }
-
-+
-+#if defined(CONFIG_MRST_LNW_A1_WR) || defined(CONFIG_MRST_LNW_A2_WR)
-+ desc -= 8;
-+ desc[0] = 0x23;
-+#else
- /*
- * Add a terminating entry.
- */
-@@ -500,7 +567,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
-
- desc[1] = 0x00;
- desc[0] = 0x03; /* nop, end, valid */
--
-+#endif
- /*
- * Resync align buffer as we might have changed it.
- */
-@@ -613,11 +680,8 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data)
- break;
- }
-
-- if (count >= 0xF) {
-- printk(KERN_WARNING "%s: Too large timeout requested!\n",
-- mmc_hostname(host->mmc));
-+ if (count >= 0xF)
- count = 0xE;
-- }
-
- return count;
- }
-@@ -928,6 +992,30 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
- if (cmd->data)
- flags |= SDHCI_CMD_DATA;
-
-+ if (host->quirks & SDHCI_QUIRK_MRST_RESTRICTION) {
-+ u16 clk;
-+
-+ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-+
-+ clk |= SDHCI_CLOCK_CARD_EN;
-+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-+
-+ /* Wait max 10 ms */
-+ timeout = 10;
-+ while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
-+ & SDHCI_CLOCK_INT_STABLE)) {
-+ if (timeout == 0) {
-+ printk(KERN_ERR "%s: Internal clock never "
-+ "stabilised.\n",
-+ mmc_hostname(host->mmc));
-+ sdhci_dumpregs(host);
-+ return;
-+ }
-+ timeout--;
-+ mdelay(1);
-+ }
-+ }
-+
- sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
- }
-
-@@ -1147,14 +1235,22 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-
- ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
-
-- if (ios->bus_width == MMC_BUS_WIDTH_4)
-+ if (ios->bus_width == MMC_BUS_WIDTH_8) {
-+ ctrl |= SDHCI_CTRL_8BITBUS;
- ctrl |= SDHCI_CTRL_4BITBUS;
-- else
-+ } else if (ios->bus_width == MMC_BUS_WIDTH_4) {
-+ ctrl &= ~SDHCI_CTRL_8BITBUS;
-+ ctrl |= SDHCI_CTRL_4BITBUS;
-+ } else {
-+ ctrl &= ~SDHCI_CTRL_8BITBUS;
- ctrl &= ~SDHCI_CTRL_4BITBUS;
-+ }
-
-- if (ios->timing == MMC_TIMING_SD_HS)
-+#ifndef CONFIG_MRST_LNW_A2_WR
-+ if (ios->timing == MMC_TIMING_SD_HS || ios->timing == MMC_TIMING_MMC_HS)
- ctrl |= SDHCI_CTRL_HISPD;
- else
-+#endif
- ctrl &= ~SDHCI_CTRL_HISPD;
-
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-@@ -1354,6 +1450,10 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
- BUG_ON(intmask == 0);
-
- if (!host->cmd) {
-+ if (host->quirks & SDHCI_QUIRK_MRST_RESTRICTION &&
-+ !(strncmp(mmc_hostname(host->mmc), "mmc1", 4)))
-+ return;
-+
- printk(KERN_ERR "%s: Got command interrupt 0x%08x even "
- "though no command operation was in progress.\n",
- mmc_hostname(host->mmc), (unsigned)intmask);
-@@ -1667,7 +1767,9 @@ int sdhci_add_host(struct sdhci_host *host)
- if (debug_quirks)
- host->quirks = debug_quirks;
-
-+#ifndef CONFIG_MRST_LNW_A2_WR
- sdhci_reset(host, SDHCI_RESET_ALL);
-+#endif
-
- host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
- host->version = (host->version & SDHCI_SPEC_VER_MASK)
-@@ -1787,7 +1889,7 @@ int sdhci_add_host(struct sdhci_host *host)
- mmc->caps |= MMC_CAP_4_BIT_DATA;
-
- if (caps & SDHCI_CAN_DO_HISPD)
-- mmc->caps |= MMC_CAP_SD_HIGHSPEED;
-+ mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
-
- if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
- mmc->caps |= MMC_CAP_NEEDS_POLL;
-@@ -1845,7 +1947,8 @@ int sdhci_add_host(struct sdhci_host *host)
- } else {
- mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >>
- SDHCI_MAX_BLOCK_SHIFT;
-- if (mmc->max_blk_size >= 3) {
-+ if ((mmc->max_blk_size >= 3) &&
-+ !(host->quirks & SDHCI_QUIRK_MRST_RESTRICTION)) {
- printk(KERN_WARNING "%s: Invalid maximum block size, "
- "assuming 512 bytes\n", mmc_hostname(mmc));
- mmc->max_blk_size = 0;
-diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
-index 842f46f..f7ba4a2 100644
---- a/drivers/mmc/host/sdhci.h
-+++ b/drivers/mmc/host/sdhci.h
-@@ -67,6 +67,7 @@
- #define SDHCI_CTRL_LED 0x01
- #define SDHCI_CTRL_4BITBUS 0x02
- #define SDHCI_CTRL_HISPD 0x04
-+#define SDHCI_CTRL_8BITBUS 0x20
- #define SDHCI_CTRL_DMA_MASK 0x18
- #define SDHCI_CTRL_SDMA 0x00
- #define SDHCI_CTRL_ADMA1 0x08
-@@ -236,6 +237,8 @@ struct sdhci_host {
- #define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23)
- /* Controller uses SDCLK instead of TMCLK for data timeouts */
- #define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1<<24)
-+/* Controller of Moorestown specific restriction */
-+#define SDHCI_QUIRK_MRST_RESTRICTION (1<<25)
-
- int irq; /* Device IRQ */
- void __iomem * ioaddr; /* Mapped address */
-diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
-index 2ee22e8..731f984 100644
---- a/include/linux/mmc/card.h
-+++ b/include/linux/mmc/card.h
-@@ -97,6 +97,7 @@ struct mmc_card {
- #define MMC_STATE_READONLY (1<<1) /* card is read-only */
- #define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */
- #define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */
-+#define MMC_STATE_SUSPENDED (1<<4) /* card uses block-addressing */
- unsigned int quirks; /* card quirks */
- #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */
-
-@@ -109,6 +110,7 @@ struct mmc_card {
- struct sd_scr scr; /* extra SD information */
- struct sd_switch_caps sw_caps; /* switch (CMD6) caps */
-
-+ /* sdio related info */
- unsigned int sdio_funcs; /* number of SDIO functions */
- struct sdio_cccr cccr; /* common card info */
- struct sdio_cis cis; /* common tuple info */
-@@ -118,6 +120,10 @@ struct mmc_card {
- struct sdio_func_tuple *tuples; /* unknown common tuples */
-
- struct dentry *debugfs_root;
-+
-+#ifdef CONFIG_SDIO_SUSPEND
-+ struct mutex pm_mutex;
-+#endif
- };
-
- #define mmc_card_mmc(c) ((c)->type == MMC_TYPE_MMC)
-@@ -128,6 +134,7 @@ struct mmc_card {
- #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
- #define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
- #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
-+#define mmc_card_suspended(c) ((c)->state & MMC_STATE_SUSPENDED)
-
- #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
- #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
-@@ -139,6 +146,11 @@ static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
- return c->quirks & MMC_QUIRK_LENIENT_FN0;
- }
-
-+#ifdef CONFIG_SDIO_SUSPEND
-+#define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED)
-+#define mmc_card_clear_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED)
-+#endif
-+
- #define mmc_card_name(c) ((c)->cid.prod_name)
- #define mmc_card_id(c) (dev_name(&(c)->dev))
-
-diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
-index eaf3636..814450a 100644
---- a/include/linux/mmc/host.h
-+++ b/include/linux/mmc/host.h
-@@ -203,6 +203,8 @@ struct mmc_host {
-
- struct dentry *debugfs_root;
-
-+ struct mutex *port_mutex;
-+
- unsigned long private[0] ____cacheline_aligned;
- };
-
-diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
-index ac3ab68..a863a9a 100644
---- a/include/linux/mmc/sdio_func.h
-+++ b/include/linux/mmc/sdio_func.h
-@@ -50,6 +50,7 @@ struct sdio_func {
-
- unsigned int state; /* function state */
- #define SDIO_STATE_PRESENT (1<<0) /* present in sysfs */
-+#define SDIO_STATE_SUSPENDED (1<<1) /* present in sysfs */
-
- u8 tmpbuf[4]; /* DMA:able scratch buffer */
-
-@@ -60,9 +61,13 @@ struct sdio_func {
- };
-
- #define sdio_func_present(f) ((f)->state & SDIO_STATE_PRESENT)
-+#define sdio_func_suspended(f) ((f)->state & SDIO_STATE_SUSPENDED)
-
- #define sdio_func_set_present(f) ((f)->state |= SDIO_STATE_PRESENT)
-
-+#define sdio_func_set_suspended(f) ((f)->state |= SDIO_STATE_SUSPENDED)
-+#define sdio_func_clear_suspended(f) ((f)->state &= ~SDIO_STATE_SUSPENDED)
-+
- #define sdio_func_id(f) (dev_name(&(f)->dev))
-
- #define sdio_get_drvdata(f) dev_get_drvdata(&(f)->dev)
-@@ -78,6 +83,11 @@ struct sdio_driver {
-
- int (*probe)(struct sdio_func *, const struct sdio_device_id *);
- void (*remove)(struct sdio_func *);
-+ int (*suspend)(struct sdio_func *, pm_message_t);
-+ int (*resume)(struct sdio_func *);
-+
-+ int (*pre_reset)(struct sdio_func *);
-+ int (*post_reset)(struct sdio_func *);
-
- struct device_driver drv;
- };
-@@ -153,5 +163,9 @@ extern unsigned char sdio_f0_readb(struct sdio_func *func,
- extern void sdio_f0_writeb(struct sdio_func *func, unsigned char b,
- unsigned int addr, int *err_ret);
-
-+extern int sdio_reset_device(struct mmc_card *card);
-+
-+extern int sdio_suspend_host(struct mmc_card *card, pm_message_t msg);
-+extern int sdio_resume_host(struct mmc_card *card);
- #endif
-
-diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
-index cca8a04..2ec7f6c 100644
---- a/include/linux/pci_ids.h
-+++ b/include/linux/pci_ids.h
-@@ -2396,6 +2396,8 @@
- #define PCI_DEVICE_ID_INTEL_82375 0x0482
- #define PCI_DEVICE_ID_INTEL_82424 0x0483
- #define PCI_DEVICE_ID_INTEL_82378 0x0484
-+#define PCI_DEVICE_ID_INTEL_MRST_SD0 0x0807
-+#define PCI_DEVICE_ID_INTEL_MRST_SD1 0x0808
- #define PCI_DEVICE_ID_INTEL_I960 0x0960
- #define PCI_DEVICE_ID_INTEL_I960RM 0x0962
- #define PCI_DEVICE_ID_INTEL_8257X_SOL 0x1062
---
-1.6.2.5
-