cns3xxx: remove 2.6.31 support
[openwrt.git] / target / linux / cns3xxx / patches-2.6.31 / 204-cns3xxx_mmc_support.patch
diff --git a/target/linux/cns3xxx/patches-2.6.31/204-cns3xxx_mmc_support.patch b/target/linux/cns3xxx/patches-2.6.31/204-cns3xxx_mmc_support.patch
deleted file mode 100644 (file)
index 3f81ad8..0000000
+++ /dev/null
@@ -1,2663 +0,0 @@
---- a/drivers/mmc/card/block.c
-+++ b/drivers/mmc/card/block.c
-@@ -130,7 +130,7 @@ mmc_blk_getgeo(struct block_device *bdev
-       return 0;
- }
--static struct block_device_operations mmc_bdops = {
-+static const struct block_device_operations mmc_bdops = {
-       .open                   = mmc_blk_open,
-       .release                = mmc_blk_release,
-       .getgeo                 = mmc_blk_getgeo,
-@@ -392,13 +392,9 @@ static int mmc_blk_issue_rq(struct mmc_q
-                       } while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
-                               (R1_CURRENT_STATE(cmd.resp[0]) == 7));
--#if 0
-                       if (cmd.resp[0] & ~0x00000900)
-                               printk(KERN_ERR "%s: status = %08x\n",
-                                      req->rq_disk->disk_name, cmd.resp[0]);
--                      if (mmc_decode_status(cmd.resp))
--                              goto cmd_err;
--#endif
-               }
-               if (brq.cmd.error || brq.stop.error || brq.data.error) {
---- a/drivers/mmc/core/core.c
-+++ b/drivers/mmc/core/core.c
-@@ -37,6 +37,9 @@
- #include "sd_ops.h"
- #include "sdio_ops.h"
-+/* scott.trace */
-+//#define MMC_DEBUG
-+
- static struct workqueue_struct *workqueue;
- /*
-@@ -90,17 +93,30 @@ void mmc_request_done(struct mmc_host *h
-               cmd->error = 0;
-               host->ops->request(host, mrq);
-       } else {
-+#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
-               led_trigger_event(host->led, LED_OFF);
-+#endif
-               pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n",
-                       mmc_hostname(host), cmd->opcode, err,
-                       cmd->resp[0], cmd->resp[1],
-                       cmd->resp[2], cmd->resp[3]);
-+#ifdef MMC_DEBUG
-+              printk("[MMC_DEBUG] %s: req done (CMD%u): %d: %08x %08x %08x %08x\n",
-+                      mmc_hostname(host), cmd->opcode, err,
-+                      cmd->resp[0], cmd->resp[1],
-+                      cmd->resp[2], cmd->resp[3]);
-+#endif
-               if (mrq->data) {
-                       pr_debug("%s:     %d bytes transferred: %d\n",
-                               mmc_hostname(host),
-                               mrq->data->bytes_xfered, mrq->data->error);
-+#ifdef MMC_DEBUG
-+                      printk("[MMC_DEBUG] %s:     %d bytes transferred: %d\n",
-+                              mmc_hostname(host),
-+                              mrq->data->bytes_xfered, mrq->data->error);
-+#endif
-               }
-               if (mrq->stop) {
-@@ -109,6 +125,13 @@ void mmc_request_done(struct mmc_host *h
-                               mrq->stop->error,
-                               mrq->stop->resp[0], mrq->stop->resp[1],
-                               mrq->stop->resp[2], mrq->stop->resp[3]);
-+#ifdef MMC_DEBUG
-+                      printk("[MMC_DEBUG] %s:     (CMD%u): %d: %08x %08x %08x %08x\n",
-+                              mmc_hostname(host), mrq->stop->opcode,
-+                              mrq->stop->error,
-+                              mrq->stop->resp[0], mrq->stop->resp[1],
-+                              mrq->stop->resp[2], mrq->stop->resp[3]);
-+#endif
-               }
-               if (mrq->done)
-@@ -129,6 +152,11 @@ mmc_start_request(struct mmc_host *host,
-       pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
-                mmc_hostname(host), mrq->cmd->opcode,
-                mrq->cmd->arg, mrq->cmd->flags);
-+#ifdef MMC_DEBUG
-+      printk("[MMC_DEBUG] %s: starting CMD%u arg %08x flags %08x\n",
-+               mmc_hostname(host), mrq->cmd->opcode,
-+               mrq->cmd->arg, mrq->cmd->flags);
-+#endif
-       if (mrq->data) {
-               pr_debug("%s:     blksz %d blocks %d flags %08x "
-@@ -137,17 +165,32 @@ mmc_start_request(struct mmc_host *host,
-                       mrq->data->blocks, mrq->data->flags,
-                       mrq->data->timeout_ns / 1000000,
-                       mrq->data->timeout_clks);
-+#ifdef MMC_DEBUG
-+              printk("[MMC_DEBUG] %s:     blksz %d blocks %d flags %08x "
-+                      "tsac %d ms nsac %d\n",
-+                      mmc_hostname(host), mrq->data->blksz,
-+                      mrq->data->blocks, mrq->data->flags,
-+                      mrq->data->timeout_ns / 1000000,
-+                      mrq->data->timeout_clks);
-+#endif
-       }
-       if (mrq->stop) {
-               pr_debug("%s:     CMD%u arg %08x flags %08x\n",
-                        mmc_hostname(host), mrq->stop->opcode,
-                        mrq->stop->arg, mrq->stop->flags);
-+#ifdef MMC_DEBUG
-+              printk("[MMC_DEBUG] %s:     CMD%u arg %08x flags %08x\n",
-+                       mmc_hostname(host), mrq->stop->opcode,
-+                       mrq->stop->arg, mrq->stop->flags);
-+#endif
-       }
-       WARN_ON(!host->claimed);
-+#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
-       led_trigger_event(host->led, LED_FULL);
-+#endif
-       mrq->cmd->error = 0;
-       mrq->cmd->mrq = mrq;
-@@ -286,9 +329,9 @@ void mmc_set_data_timeout(struct mmc_dat
-                        * The limit is really 250 ms, but that is
-                        * insufficient for some crappy cards.
-                        */
--                      limit_us = 300000;
-+                      limit_us = 500000;
-               else
--                      limit_us = 100000;
-+                      limit_us = 200000;
-               /*
-                * SDHC cards always use these fixed values.
-@@ -344,6 +387,101 @@ unsigned int mmc_align_data_size(struct 
- EXPORT_SYMBOL(mmc_align_data_size);
- /**
-+ *    mmc_host_enable - enable a host.
-+ *    @host: mmc host to enable
-+ *
-+ *    Hosts that support power saving can use the 'enable' and 'disable'
-+ *    methods to exit and enter power saving states. For more information
-+ *    see comments for struct mmc_host_ops.
-+ */
-+int mmc_host_enable(struct mmc_host *host)
-+{
-+      if (!(host->caps & MMC_CAP_DISABLE))
-+              return 0;
-+
-+      if (host->en_dis_recurs)
-+              return 0;
-+
-+      if (host->nesting_cnt++)
-+              return 0;
-+
-+      cancel_delayed_work_sync(&host->disable);
-+
-+      if (host->enabled)
-+              return 0;
-+
-+      if (host->ops->enable) {
-+              int err;
-+
-+              host->en_dis_recurs = 1;
-+              err = host->ops->enable(host);
-+              host->en_dis_recurs = 0;
-+
-+              if (err) {
-+                      pr_debug("%s: enable error %d\n",
-+                               mmc_hostname(host), err);
-+                      return err;
-+              }
-+      }
-+      host->enabled = 1;
-+      return 0;
-+}
-+EXPORT_SYMBOL(mmc_host_enable);
-+
-+static int mmc_host_do_disable(struct mmc_host *host, int lazy)
-+{
-+      if (host->ops->disable) {
-+              int err;
-+
-+              host->en_dis_recurs = 1;
-+              err = host->ops->disable(host, lazy);
-+              host->en_dis_recurs = 0;
-+
-+              if (err < 0) {
-+                      pr_debug("%s: disable error %d\n",
-+                               mmc_hostname(host), err);
-+                      return err;
-+              }
-+              if (err > 0) {
-+                      unsigned long delay = msecs_to_jiffies(err);
-+
-+                      mmc_schedule_delayed_work(&host->disable, delay);
-+              }
-+      }
-+      host->enabled = 0;
-+      return 0;
-+}
-+
-+/**
-+ *    mmc_host_disable - disable a host.
-+ *    @host: mmc host to disable
-+ *
-+ *    Hosts that support power saving can use the 'enable' and 'disable'
-+ *    methods to exit and enter power saving states. For more information
-+ *    see comments for struct mmc_host_ops.
-+ */
-+int mmc_host_disable(struct mmc_host *host)
-+{
-+      int err;
-+
-+      if (!(host->caps & MMC_CAP_DISABLE))
-+              return 0;
-+
-+      if (host->en_dis_recurs)
-+              return 0;
-+
-+      if (--host->nesting_cnt)
-+              return 0;
-+
-+      if (!host->enabled)
-+              return 0;
-+
-+      err = mmc_host_do_disable(host, 0);
-+      return err;
-+}
-+EXPORT_SYMBOL(mmc_host_disable);
-+
-+/**
-  *    __mmc_claim_host - exclusively claim a host
-  *    @host: mmc host to claim
-  *    @abort: whether or not the operation should be aborted
-@@ -366,25 +504,111 @@ int __mmc_claim_host(struct mmc_host *ho
-       while (1) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               stop = abort ? atomic_read(abort) : 0;
--              if (stop || !host->claimed)
-+              if (stop || !host->claimed || host->claimer == current)
-                       break;
-               spin_unlock_irqrestore(&host->lock, flags);
-               schedule();
-               spin_lock_irqsave(&host->lock, flags);
-       }
-       set_current_state(TASK_RUNNING);
--      if (!stop)
-+      if (!stop) {
-               host->claimed = 1;
--      else
-+              host->claimer = current;
-+              host->claim_cnt += 1;
-+      } else
-               wake_up(&host->wq);
-       spin_unlock_irqrestore(&host->lock, flags);
-       remove_wait_queue(&host->wq, &wait);
-+      if (!stop)
-+              mmc_host_enable(host);
-       return stop;
- }
- EXPORT_SYMBOL(__mmc_claim_host);
- /**
-+ *    mmc_try_claim_host - try exclusively to claim a host
-+ *    @host: mmc host to claim
-+ *
-+ *    Returns %1 if the host is claimed, %0 otherwise.
-+ */
-+int mmc_try_claim_host(struct mmc_host *host)
-+{
-+      int claimed_host = 0;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&host->lock, flags);
-+      if (!host->claimed || host->claimer == current) {
-+              host->claimed = 1;
-+              host->claimer = current;
-+              host->claim_cnt += 1;
-+              claimed_host = 1;
-+      }
-+      spin_unlock_irqrestore(&host->lock, flags);
-+      return claimed_host;
-+}
-+EXPORT_SYMBOL(mmc_try_claim_host);
-+
-+static void mmc_do_release_host(struct mmc_host *host)
-+{
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&host->lock, flags);
-+      if (--host->claim_cnt) {
-+              /* Release for nested claim */
-+              spin_unlock_irqrestore(&host->lock, flags);
-+      } else {
-+              host->claimed = 0;
-+              host->claimer = NULL;
-+              spin_unlock_irqrestore(&host->lock, flags);
-+              wake_up(&host->wq);
-+      }
-+}
-+
-+void mmc_host_deeper_disable(struct work_struct *work)
-+{
-+      struct mmc_host *host =
-+              container_of(work, struct mmc_host, disable.work);
-+
-+      /* If the host is claimed then we do not want to disable it anymore */
-+      if (!mmc_try_claim_host(host))
-+              return;
-+      mmc_host_do_disable(host, 1);
-+      mmc_do_release_host(host);
-+}
-+
-+/**
-+ *    mmc_host_lazy_disable - lazily disable a host.
-+ *    @host: mmc host to disable
-+ *
-+ *    Hosts that support power saving can use the 'enable' and 'disable'
-+ *    methods to exit and enter power saving states. For more information
-+ *    see comments for struct mmc_host_ops.
-+ */
-+int mmc_host_lazy_disable(struct mmc_host *host)
-+{
-+      if (!(host->caps & MMC_CAP_DISABLE))
-+              return 0;
-+
-+      if (host->en_dis_recurs)
-+              return 0;
-+
-+      if (--host->nesting_cnt)
-+              return 0;
-+
-+      if (!host->enabled)
-+              return 0;
-+
-+      if (host->disable_delay) {
-+              mmc_schedule_delayed_work(&host->disable,
-+                              msecs_to_jiffies(host->disable_delay));
-+              return 0;
-+      } else
-+              return mmc_host_do_disable(host, 1);
-+}
-+EXPORT_SYMBOL(mmc_host_lazy_disable);
-+
-+/**
-  *    mmc_release_host - release a host
-  *    @host: mmc host to release
-  *
-@@ -393,15 +617,11 @@ EXPORT_SYMBOL(__mmc_claim_host);
-  */
- void mmc_release_host(struct mmc_host *host)
- {
--      unsigned long flags;
--
-       WARN_ON(!host->claimed);
--      spin_lock_irqsave(&host->lock, flags);
--      host->claimed = 0;
--      spin_unlock_irqrestore(&host->lock, flags);
-+      mmc_host_lazy_disable(host);
--      wake_up(&host->wq);
-+      mmc_do_release_host(host);
- }
- EXPORT_SYMBOL(mmc_release_host);
-@@ -687,7 +907,13 @@ void mmc_set_timing(struct mmc_host *hos
-  */
- static void mmc_power_up(struct mmc_host *host)
- {
--      int bit = fls(host->ocr_avail) - 1;
-+      int bit;
-+
-+      /* If ocr is set, we use it */
-+      if (host->ocr)
-+              bit = ffs(host->ocr) - 1;
-+      else
-+              bit = fls(host->ocr_avail) - 1;
-       host->ios.vdd = bit;
-       if (mmc_host_is_spi(host)) {
-@@ -947,6 +1173,8 @@ void mmc_stop_host(struct mmc_host *host
-       spin_unlock_irqrestore(&host->lock, flags);
- #endif
-+      if (host->caps & MMC_CAP_DISABLE)
-+              cancel_delayed_work(&host->disable);
-       cancel_delayed_work(&host->detect);
-       mmc_flush_scheduled_work();
-@@ -958,6 +1186,8 @@ void mmc_stop_host(struct mmc_host *host
-               mmc_claim_host(host);
-               mmc_detach_bus(host);
-               mmc_release_host(host);
-+              mmc_bus_put(host);
-+              return;
-       }
-       mmc_bus_put(host);
-@@ -966,6 +1196,80 @@ void mmc_stop_host(struct mmc_host *host
-       mmc_power_off(host);
- }
-+void mmc_power_save_host(struct mmc_host *host)
-+{
-+      mmc_bus_get(host);
-+
-+      if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
-+              mmc_bus_put(host);
-+              return;
-+      }
-+
-+      if (host->bus_ops->power_save)
-+              host->bus_ops->power_save(host);
-+
-+      mmc_bus_put(host);
-+
-+      mmc_power_off(host);
-+}
-+EXPORT_SYMBOL(mmc_power_save_host);
-+
-+void mmc_power_restore_host(struct mmc_host *host)
-+{
-+      mmc_bus_get(host);
-+
-+      if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
-+              mmc_bus_put(host);
-+              return;
-+      }
-+
-+      mmc_power_up(host);
-+      host->bus_ops->power_restore(host);
-+
-+      mmc_bus_put(host);
-+}
-+EXPORT_SYMBOL(mmc_power_restore_host);
-+
-+int mmc_card_awake(struct mmc_host *host)
-+{
-+      int err = -ENOSYS;
-+
-+      mmc_bus_get(host);
-+
-+      if (host->bus_ops && !host->bus_dead && host->bus_ops->awake)
-+              err = host->bus_ops->awake(host);
-+
-+      mmc_bus_put(host);
-+
-+      return err;
-+}
-+EXPORT_SYMBOL(mmc_card_awake);
-+
-+int mmc_card_sleep(struct mmc_host *host)
-+{
-+      int err = -ENOSYS;
-+
-+      mmc_bus_get(host);
-+
-+      if (host->bus_ops && !host->bus_dead && host->bus_ops->awake)
-+              err = host->bus_ops->sleep(host);
-+
-+      mmc_bus_put(host);
-+
-+      return err;
-+}
-+EXPORT_SYMBOL(mmc_card_sleep);
-+
-+int mmc_card_can_sleep(struct mmc_host *host)
-+{
-+      struct mmc_card *card = host->card;
-+
-+      if (card && mmc_card_mmc(card) && card->ext_csd.rev >= 3)
-+              return 1;
-+      return 0;
-+}
-+EXPORT_SYMBOL(mmc_card_can_sleep);
-+
- #ifdef CONFIG_PM
- /**
-@@ -975,27 +1279,36 @@ void mmc_stop_host(struct mmc_host *host
-  */
- int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
- {
-+      int err = 0;
-+
-+      if (host->caps & MMC_CAP_DISABLE)
-+              cancel_delayed_work(&host->disable);
-       cancel_delayed_work(&host->detect);
-       mmc_flush_scheduled_work();
-       mmc_bus_get(host);
-       if (host->bus_ops && !host->bus_dead) {
-               if (host->bus_ops->suspend)
--                      host->bus_ops->suspend(host);
--              if (!host->bus_ops->resume) {
-+                      err = host->bus_ops->suspend(host);
-+              if (err == -ENOSYS || !host->bus_ops->resume) {
-+                      /*
-+                       * We simply "remove" the card in this case.
-+                       * It will be redetected on resume.
-+                       */
-                       if (host->bus_ops->remove)
-                               host->bus_ops->remove(host);
--
-                       mmc_claim_host(host);
-                       mmc_detach_bus(host);
-                       mmc_release_host(host);
-+                      err = 0;
-               }
-       }
-       mmc_bus_put(host);
--      mmc_power_off(host);
-+      if (!err)
-+              mmc_power_off(host);
--      return 0;
-+      return err;
- }
- EXPORT_SYMBOL(mmc_suspend_host);
-@@ -1006,12 +1319,26 @@ EXPORT_SYMBOL(mmc_suspend_host);
-  */
- int mmc_resume_host(struct mmc_host *host)
- {
-+      int err = 0;
-+
-       mmc_bus_get(host);
-       if (host->bus_ops && !host->bus_dead) {
-               mmc_power_up(host);
-               mmc_select_voltage(host, host->ocr);
-               BUG_ON(!host->bus_ops->resume);
--              host->bus_ops->resume(host);
-+              err = host->bus_ops->resume(host);
-+              if (err) {
-+                      printk(KERN_WARNING "%s: error %d during resume "
-+                                          "(card was removed?)\n",
-+                                          mmc_hostname(host), err);
-+                      if (host->bus_ops->remove)
-+                              host->bus_ops->remove(host);
-+                      mmc_claim_host(host);
-+                      mmc_detach_bus(host);
-+                      mmc_release_host(host);
-+                      /* no need to bother upper layers */
-+                      err = 0;
-+              }
-       }
-       mmc_bus_put(host);
-@@ -1021,7 +1348,7 @@ int mmc_resume_host(struct mmc_host *hos
-        */
-       mmc_detect_change(host, 1);
--      return 0;
-+      return err;
- }
- EXPORT_SYMBOL(mmc_resume_host);
---- a/drivers/mmc/core/core.h
-+++ b/drivers/mmc/core/core.h
-@@ -16,10 +16,14 @@
- #define MMC_CMD_RETRIES        3
- struct mmc_bus_ops {
-+      int (*awake)(struct mmc_host *);
-+      int (*sleep)(struct mmc_host *);
-       void (*remove)(struct mmc_host *);
-       void (*detect)(struct mmc_host *);
--      void (*suspend)(struct mmc_host *);
--      void (*resume)(struct mmc_host *);
-+      int (*suspend)(struct mmc_host *);
-+      int (*resume)(struct mmc_host *);
-+      void (*power_save)(struct mmc_host *);
-+      void (*power_restore)(struct mmc_host *);
- };
- void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
---- a/drivers/mmc/core/debugfs.c
-+++ b/drivers/mmc/core/debugfs.c
-@@ -240,7 +240,7 @@ static int mmc_ext_csd_release(struct in
-       return 0;
- }
--static struct file_operations mmc_dbg_ext_csd_fops = {
-+static const struct file_operations mmc_dbg_ext_csd_fops = {
-       .open           = mmc_ext_csd_open,
-       .read           = mmc_ext_csd_read,
-       .release        = mmc_ext_csd_release,
---- a/drivers/mmc/core/host.c
-+++ b/drivers/mmc/core/host.c
-@@ -83,6 +83,7 @@ struct mmc_host *mmc_alloc_host(int extr
-       spin_lock_init(&host->lock);
-       init_waitqueue_head(&host->wq);
-       INIT_DELAYED_WORK(&host->detect, mmc_rescan);
-+      INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable);
-       /*
-        * By default, hosts do not support SGIO or large requests.
---- a/drivers/mmc/core/host.h
-+++ b/drivers/mmc/core/host.h
-@@ -14,5 +14,7 @@
- int mmc_register_host_class(void);
- void mmc_unregister_host_class(void);
-+void mmc_host_deeper_disable(struct work_struct *work);
-+
- #endif
---- a/drivers/mmc/core/mmc.c
-+++ b/drivers/mmc/core/mmc.c
-@@ -160,7 +160,6 @@ static int mmc_read_ext_csd(struct mmc_c
- {
-       int err;
-       u8 *ext_csd;
--      unsigned int ext_csd_struct;
-       BUG_ON(!card);
-@@ -207,16 +206,16 @@ static int mmc_read_ext_csd(struct mmc_c
-               goto out;
-       }
--      ext_csd_struct = ext_csd[EXT_CSD_REV];
--      if (ext_csd_struct > 3) {
-+      card->ext_csd.rev = ext_csd[EXT_CSD_REV];
-+      if (card->ext_csd.rev > 3) {
-               printk(KERN_ERR "%s: unrecognised EXT_CSD structure "
-                       "version %d\n", mmc_hostname(card->host),
--                      ext_csd_struct);
-+                      card->ext_csd.rev);
-               err = -EINVAL;
-               goto out;
-       }
--      if (ext_csd_struct >= 2) {
-+      if (card->ext_csd.rev >= 2) {
-               card->ext_csd.sectors =
-                       ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
-                       ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
-@@ -241,6 +240,15 @@ static int mmc_read_ext_csd(struct mmc_c
-               goto out;
-       }
-+      if (card->ext_csd.rev >= 3) {
-+              u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT];
-+
-+              /* Sleep / awake timeout in 100ns units */
-+              if (sa_shift > 0 && sa_shift <= 0x17)
-+                      card->ext_csd.sa_timeout =
-+                                      1 << ext_csd[EXT_CSD_S_A_TIMEOUT];
-+      }
-+
- out:
-       kfree(ext_csd);
-@@ -276,7 +284,7 @@ static struct attribute_group mmc_std_at
-       .attrs = mmc_std_attrs,
- };
--static struct attribute_group *mmc_attr_groups[] = {
-+static const struct attribute_group *mmc_attr_groups[] = {
-       &mmc_std_attr_group,
-       NULL,
- };
-@@ -408,12 +416,17 @@ static int mmc_init_card(struct mmc_host
-               (host->caps & MMC_CAP_MMC_HIGHSPEED)) {
-               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                       EXT_CSD_HS_TIMING, 1);
--              if (err)
-+              if (err && err != -EBADMSG)
-                       goto free_card;
--              mmc_card_set_highspeed(card);
--
--              mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-+              if (err) {
-+                      printk(KERN_WARNING "%s: switch to highspeed failed\n",
-+                             mmc_hostname(card->host));
-+                      err = 0;
-+              } else {
-+                      mmc_card_set_highspeed(card);
-+                      mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-+              }
-       }
-       /*
-@@ -448,10 +461,17 @@ static int mmc_init_card(struct mmc_host
-               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                                EXT_CSD_BUS_WIDTH, ext_csd_bit);
--              if (err)
-+              if (err && err != -EBADMSG)
-                       goto free_card;
--              mmc_set_bus_width(card->host, bus_width);
-+              if (err) {
-+                      printk(KERN_WARNING "%s: switch to bus width %d "
-+                             "failed\n", mmc_hostname(card->host),
-+                             1 << bus_width);
-+                      err = 0;
-+              } else {
-+                      mmc_set_bus_width(card->host, bus_width);
-+              }
-       }
-       if (!oldcard)
-@@ -507,12 +527,10 @@ static void mmc_detect(struct mmc_host *
-       }
- }
--#ifdef CONFIG_MMC_UNSAFE_RESUME
--
- /*
-  * Suspend callback from host.
-  */
--static void mmc_suspend(struct mmc_host *host)
-+static int mmc_suspend(struct mmc_host *host)
- {
-       BUG_ON(!host);
-       BUG_ON(!host->card);
-@@ -522,6 +540,8 @@ static void mmc_suspend(struct mmc_host 
-               mmc_deselect_cards(host);
-       host->card->state &= ~MMC_STATE_HIGHSPEED;
-       mmc_release_host(host);
-+
-+      return 0;
- }
- /*
-@@ -530,7 +550,7 @@ static void mmc_suspend(struct mmc_host 
-  * This function tries to determine if the same card is still present
-  * and, if so, restore all state to it.
-  */
--static void mmc_resume(struct mmc_host *host)
-+static int mmc_resume(struct mmc_host *host)
- {
-       int err;
-@@ -541,30 +561,99 @@ static void mmc_resume(struct mmc_host *
-       err = mmc_init_card(host, host->ocr, host->card);
-       mmc_release_host(host);
--      if (err) {
--              mmc_remove(host);
-+      return err;
-+}
--              mmc_claim_host(host);
--              mmc_detach_bus(host);
--              mmc_release_host(host);
-+static void mmc_power_restore(struct mmc_host *host)
-+{
-+      host->card->state &= ~MMC_STATE_HIGHSPEED;
-+      mmc_claim_host(host);
-+      mmc_init_card(host, host->ocr, host->card);
-+      mmc_release_host(host);
-+}
-+
-+static int mmc_sleep(struct mmc_host *host)
-+{
-+      struct mmc_card *card = host->card;
-+      int err = -ENOSYS;
-+
-+      if (card && card->ext_csd.rev >= 3) {
-+              err = mmc_card_sleepawake(host, 1);
-+              if (err < 0)
-+                      pr_debug("%s: Error %d while putting card into sleep",
-+                               mmc_hostname(host), err);
-       }
-+      return err;
- }
--#else
-+static int mmc_awake(struct mmc_host *host)
-+{
-+      struct mmc_card *card = host->card;
-+      int err = -ENOSYS;
--#define mmc_suspend NULL
--#define mmc_resume NULL
-+      if (card && card->ext_csd.rev >= 3) {
-+              err = mmc_card_sleepawake(host, 0);
-+              if (err < 0)
-+                      pr_debug("%s: Error %d while awaking sleeping card",
-+                               mmc_hostname(host), err);
-+      }
--#endif
-+      return err;
-+}
-+
-+#ifdef CONFIG_MMC_UNSAFE_RESUME
-+
-+static const struct mmc_bus_ops mmc_ops = {
-+      .awake = mmc_awake,
-+      .sleep = mmc_sleep,
-+      .remove = mmc_remove,
-+      .detect = mmc_detect,
-+      .suspend = mmc_suspend,
-+      .resume = mmc_resume,
-+      .power_restore = mmc_power_restore,
-+};
-+
-+static void mmc_attach_bus_ops(struct mmc_host *host)
-+{
-+      mmc_attach_bus(host, &mmc_ops);
-+}
-+
-+#else
- static const struct mmc_bus_ops mmc_ops = {
-+      .awake = mmc_awake,
-+      .sleep = mmc_sleep,
-+      .remove = mmc_remove,
-+      .detect = mmc_detect,
-+      .suspend = NULL,
-+      .resume = NULL,
-+      .power_restore = mmc_power_restore,
-+};
-+
-+static const struct mmc_bus_ops mmc_ops_unsafe = {
-+      .awake = mmc_awake,
-+      .sleep = mmc_sleep,
-       .remove = mmc_remove,
-       .detect = mmc_detect,
-       .suspend = mmc_suspend,
-       .resume = mmc_resume,
-+      .power_restore = mmc_power_restore,
- };
-+static void mmc_attach_bus_ops(struct mmc_host *host)
-+{
-+      const struct mmc_bus_ops *bus_ops;
-+
-+      if (host->caps & MMC_CAP_NONREMOVABLE)
-+              bus_ops = &mmc_ops_unsafe;
-+      else
-+              bus_ops = &mmc_ops;
-+      mmc_attach_bus(host, bus_ops);
-+}
-+
-+#endif
-+
- /*
-  * Starting point for MMC card init.
-  */
-@@ -575,7 +664,7 @@ int mmc_attach_mmc(struct mmc_host *host
-       BUG_ON(!host);
-       WARN_ON(!host->claimed);
--      mmc_attach_bus(host, &mmc_ops);
-+      mmc_attach_bus_ops(host);
-       /*
-        * We need to get OCR a different way for SPI.
---- a/drivers/mmc/core/mmc_ops.c
-+++ b/drivers/mmc/core/mmc_ops.c
-@@ -57,6 +57,42 @@ int mmc_deselect_cards(struct mmc_host *
-       return _mmc_select_card(host, NULL);
- }
-+int mmc_card_sleepawake(struct mmc_host *host, int sleep)
-+{
-+      struct mmc_command cmd;
-+      struct mmc_card *card = host->card;
-+      int err;
-+
-+      if (sleep)
-+              mmc_deselect_cards(host);
-+
-+      memset(&cmd, 0, sizeof(struct mmc_command));
-+
-+      cmd.opcode = MMC_SLEEP_AWAKE;
-+      cmd.arg = card->rca << 16;
-+      if (sleep)
-+              cmd.arg |= 1 << 15;
-+
-+      cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
-+      err = mmc_wait_for_cmd(host, &cmd, 0);
-+      if (err)
-+              return err;
-+
-+      /*
-+       * If the host does not wait while the card signals busy, then we will
-+       * will have to wait the sleep/awake timeout.  Note, we cannot use the
-+       * SEND_STATUS command to poll the status because that command (and most
-+       * others) is invalid while the card sleeps.
-+       */
-+      if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
-+              mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000));
-+
-+      if (!sleep)
-+              err = mmc_select_card(card);
-+
-+      return err;
-+}
-+
- int mmc_go_idle(struct mmc_host *host)
- {
-       int err;
-@@ -354,6 +390,7 @@ int mmc_switch(struct mmc_card *card, u8
- {
-       int err;
-       struct mmc_command cmd;
-+      u32 status;
-       BUG_ON(!card);
-       BUG_ON(!card->host);
-@@ -371,6 +408,28 @@ int mmc_switch(struct mmc_card *card, u8
-       if (err)
-               return err;
-+      /* Must check status to be sure of no errors */
-+      do {
-+              err = mmc_send_status(card, &status);
-+              if (err)
-+                      return err;
-+              if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-+                      break;
-+              if (mmc_host_is_spi(card->host))
-+                      break;
-+      } while (R1_CURRENT_STATE(status) == 7);
-+
-+      if (mmc_host_is_spi(card->host)) {
-+              if (status & R1_SPI_ILLEGAL_COMMAND)
-+                      return -EBADMSG;
-+      } else {
-+              if (status & 0xFDFFA000)
-+                      printk(KERN_WARNING "%s: unexpected status %#x after "
-+                             "switch", mmc_hostname(card->host), status);
-+              if (status & R1_SWITCH_ERROR)
-+                      return -EBADMSG;
-+      }
-+
-       return 0;
- }
---- a/drivers/mmc/core/mmc_ops.h
-+++ b/drivers/mmc/core/mmc_ops.h
-@@ -25,6 +25,7 @@ int mmc_send_status(struct mmc_card *car
- int mmc_send_cid(struct mmc_host *host, u32 *cid);
- int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
- int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
-+int mmc_card_sleepawake(struct mmc_host *host, int sleep);
- #endif
---- a/drivers/mmc/core/sd.c
-+++ b/drivers/mmc/core/sd.c
-@@ -314,7 +314,7 @@ static struct attribute_group sd_std_att
-       .attrs = sd_std_attrs,
- };
--static struct attribute_group *sd_attr_groups[] = {
-+static const struct attribute_group *sd_attr_groups[] = {
-       &sd_std_attr_group,
-       NULL,
- };
-@@ -561,12 +561,10 @@ static void mmc_sd_detect(struct mmc_hos
-       }
- }
--#ifdef CONFIG_MMC_UNSAFE_RESUME
--
- /*
-  * Suspend callback from host.
-  */
--static void mmc_sd_suspend(struct mmc_host *host)
-+static int mmc_sd_suspend(struct mmc_host *host)
- {
-       BUG_ON(!host);
-       BUG_ON(!host->card);
-@@ -576,6 +574,8 @@ static void mmc_sd_suspend(struct mmc_ho
-               mmc_deselect_cards(host);
-       host->card->state &= ~MMC_STATE_HIGHSPEED;
-       mmc_release_host(host);
-+
-+      return 0;
- }
- /*
-@@ -584,7 +584,7 @@ static void mmc_sd_suspend(struct mmc_ho
-  * This function tries to determine if the same card is still present
-  * and, if so, restore all state to it.
-  */
--static void mmc_sd_resume(struct mmc_host *host)
-+static int mmc_sd_resume(struct mmc_host *host)
- {
-       int err;
-@@ -595,30 +595,63 @@ static void mmc_sd_resume(struct mmc_hos
-       err = mmc_sd_init_card(host, host->ocr, host->card);
-       mmc_release_host(host);
--      if (err) {
--              mmc_sd_remove(host);
--
--              mmc_claim_host(host);
--              mmc_detach_bus(host);
--              mmc_release_host(host);
--      }
-+      return err;
-+}
-+static void mmc_sd_power_restore(struct mmc_host *host)
-+{
-+      host->card->state &= ~MMC_STATE_HIGHSPEED;
-+      mmc_claim_host(host);
-+      mmc_sd_init_card(host, host->ocr, host->card);
-+      mmc_release_host(host);
- }
--#else
-+#ifdef CONFIG_MMC_UNSAFE_RESUME
--#define mmc_sd_suspend NULL
--#define mmc_sd_resume NULL
-+static const struct mmc_bus_ops mmc_sd_ops = {
-+      .remove = mmc_sd_remove,
-+      .detect = mmc_sd_detect,
-+      .suspend = mmc_sd_suspend,
-+      .resume = mmc_sd_resume,
-+      .power_restore = mmc_sd_power_restore,
-+};
--#endif
-+static void mmc_sd_attach_bus_ops(struct mmc_host *host)
-+{
-+      mmc_attach_bus(host, &mmc_sd_ops);
-+}
-+
-+#else
- static const struct mmc_bus_ops mmc_sd_ops = {
-       .remove = mmc_sd_remove,
-       .detect = mmc_sd_detect,
-+      .suspend = NULL,
-+      .resume = NULL,
-+      .power_restore = mmc_sd_power_restore,
-+};
-+
-+static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
-+      .remove = mmc_sd_remove,
-+      .detect = mmc_sd_detect,
-       .suspend = mmc_sd_suspend,
-       .resume = mmc_sd_resume,
-+      .power_restore = mmc_sd_power_restore,
- };
-+static void mmc_sd_attach_bus_ops(struct mmc_host *host)
-+{
-+      const struct mmc_bus_ops *bus_ops;
-+
-+      if (host->caps & MMC_CAP_NONREMOVABLE)
-+              bus_ops = &mmc_sd_ops_unsafe;
-+      else
-+              bus_ops = &mmc_sd_ops;
-+      mmc_attach_bus(host, bus_ops);
-+}
-+
-+#endif
-+
- /*
-  * Starting point for SD card init.
-  */
-@@ -629,7 +662,7 @@ int mmc_attach_sd(struct mmc_host *host,
-       BUG_ON(!host);
-       WARN_ON(!host->claimed);
--      mmc_attach_bus(host, &mmc_sd_ops);
-+      mmc_sd_attach_bus_ops(host);
-       /*
-        * We need to get OCR a different way for SPI.
---- a/drivers/mmc/core/sdio_bus.c
-+++ b/drivers/mmc/core/sdio_bus.c
-@@ -20,9 +20,6 @@
- #include "sdio_cis.h"
- #include "sdio_bus.h"
--#define dev_to_sdio_func(d)   container_of(d, struct sdio_func, dev)
--#define to_sdio_driver(d)      container_of(d, struct sdio_driver, drv)
--
- /* show configuration fields */
- #define sdio_config_attr(field, format_string)                                \
- static ssize_t                                                                \
-@@ -251,12 +248,15 @@ int sdio_add_func(struct sdio_func *func
- /*
-  * Unregister a SDIO function with the driver model, and
-  * (eventually) free it.
-+ * This function can be called through error paths where sdio_add_func() was
-+ * never executed (because a failure occurred at an earlier point).
-  */
- void sdio_remove_func(struct sdio_func *func)
- {
--      if (sdio_func_present(func))
--              device_del(&func->dev);
-+      if (!sdio_func_present(func))
-+              return;
-+      device_del(&func->dev);
-       put_device(&func->dev);
- }
---- a/drivers/mmc/core/sdio.c
-+++ b/drivers/mmc/core/sdio.c
-@@ -165,6 +165,29 @@ static int sdio_enable_wide(struct mmc_c
- }
- /*
-+ * If desired, disconnect the pull-up resistor on CD/DAT[3] (pin 1)
-+ * of the card. This may be required on certain setups of boards,
-+ * controllers and embedded sdio device which do not need the card's
-+ * pull-up. As a result, card detection is disabled and power is saved.
-+ */
-+static int sdio_disable_cd(struct mmc_card *card)
-+{
-+      int ret;
-+      u8 ctrl;
-+
-+      if (!card->cccr.disable_cd)
-+              return 0;
-+
-+      ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl);
-+      if (ret)
-+              return ret;
-+
-+      ctrl |= SDIO_BUS_CD_DISABLE;
-+
-+      return mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
-+}
-+
-+/*
-  * Test if the card supports high-speed mode and, if so, switch to it.
-  */
- static int sdio_enable_hs(struct mmc_card *card)
-@@ -195,6 +218,135 @@ static int sdio_enable_hs(struct mmc_car
- }
- /*
-+ * Handle the detection and initialisation of a card.
-+ *
-+ * In the case of a resume, "oldcard" will contain the card
-+ * we're trying to reinitialise.
-+ */
-+static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
-+                            struct mmc_card *oldcard)
-+{
-+      struct mmc_card *card;
-+      int err;
-+
-+      BUG_ON(!host);
-+      WARN_ON(!host->claimed);
-+
-+      /*
-+       * Inform the card of the voltage
-+       */
-+      err = mmc_send_io_op_cond(host, host->ocr, &ocr);
-+      if (err)
-+              goto err;
-+
-+      /*
-+       * For SPI, enable CRC as appropriate.
-+       */
-+      if (mmc_host_is_spi(host)) {
-+              err = mmc_spi_set_crc(host, use_spi_crc);
-+              if (err)
-+                      goto err;
-+      }
-+
-+      /*
-+       * Allocate card structure.
-+       */
-+      card = mmc_alloc_card(host, NULL);
-+      if (IS_ERR(card)) {
-+              err = PTR_ERR(card);
-+              goto err;
-+      }
-+
-+      card->type = MMC_TYPE_SDIO;
-+
-+      /*
-+       * For native busses:  set card RCA and quit open drain mode.
-+       */
-+      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 registers.
-+       */
-+      err = sdio_read_cccr(card);
-+      if (err)
-+              goto remove;
-+
-+      /*
-+       * Read the common CIS tuples.
-+       */
-+      err = sdio_read_common_cis(card);
-+      if (err)
-+              goto remove;
-+
-+      if (oldcard) {
-+              int same = (card->cis.vendor == oldcard->cis.vendor &&
-+                          card->cis.device == oldcard->cis.device);
-+              mmc_remove_card(card);
-+              if (!same) {
-+                      err = -ENOENT;
-+                      goto err;
-+              }
-+              card = oldcard;
-+              return 0;
-+      }
-+
-+      /*
-+       * Switch to high-speed (if supported).
-+       */
-+      err = sdio_enable_hs(card);
-+      if (err)
-+              goto remove;
-+
-+      /*
-+       * Change to the card's maximum speed.
-+       */
-+      if (mmc_card_highspeed(card)) {
-+              /*
-+               * The SDIO specification doesn't mention how
-+               * the CIS transfer speed register relates to
-+               * high-speed, but it seems that 50 MHz is
-+               * mandatory.
-+               */
-+              mmc_set_clock(host, 50000000);
-+      } else {
-+              mmc_set_clock(host, card->cis.max_dtr);
-+      }
-+
-+      /*
-+       * Switch to wider bus (if supported).
-+       */
-+      err = sdio_enable_wide(card);
-+      if (err)
-+              goto remove;
-+
-+      if (!oldcard)
-+              host->card = card;
-+      return 0;
-+
-+remove:
-+      if (!oldcard)
-+              mmc_remove_card(card);
-+
-+err:
-+      return err;
-+}
-+
-+/*
-  * Host is being removed. Free up the current card.
-  */
- static void mmc_sdio_remove(struct mmc_host *host)
-@@ -243,10 +395,77 @@ static void mmc_sdio_detect(struct mmc_h
-       }
- }
-+/*
-+ * SDIO suspend.  We need to suspend all functions separately.
-+ * Therefore all registered functions must have drivers with suspend
-+ * and resume methods.  Failing that we simply remove the whole card.
-+ */
-+static int mmc_sdio_suspend(struct mmc_host *host)
-+{
-+      int i, err = 0;
-+
-+      for (i = 0; i < host->card->sdio_funcs; i++) {
-+              struct sdio_func *func = host->card->sdio_func[i];
-+              if (func && sdio_func_present(func) && func->dev.driver) {
-+                      const struct dev_pm_ops *pmops = func->dev.driver->pm;
-+                      if (!pmops || !pmops->suspend || !pmops->resume) {
-+                              /* force removal of entire card in that case */
-+                              err = -ENOSYS;
-+                      } else
-+                              err = pmops->suspend(&func->dev);
-+                      if (err)
-+                              break;
-+              }
-+      }
-+      while (err && --i >= 0) {
-+              struct sdio_func *func = host->card->sdio_func[i];
-+              if (func && sdio_func_present(func) && func->dev.driver) {
-+                      const struct dev_pm_ops *pmops = func->dev.driver->pm;
-+                      pmops->resume(&func->dev);
-+              }
-+      }
-+
-+      return err;
-+}
-+
-+static int mmc_sdio_resume(struct mmc_host *host)
-+{
-+      int i, err;
-+
-+      BUG_ON(!host);
-+      BUG_ON(!host->card);
-+
-+      /* Basic card reinitialization. */
-+      mmc_claim_host(host);
-+      err = mmc_sdio_init_card(host, host->ocr, host->card);
-+      mmc_release_host(host);
-+
-+      /*
-+       * If the card looked to be the same as before suspending, then
-+       * we proceed to resume all card functions.  If one of them returns
-+       * an error then we simply return that error to the core and the
-+       * card will be redetected as new.  It is the responsibility of
-+       * the function driver to perform further tests with the extra
-+       * knowledge it has of the card to confirm the card is indeed the
-+       * same as before suspending (same MAC address for network cards,
-+       * etc.) and return an error otherwise.
-+       */
-+      for (i = 0; !err && i < host->card->sdio_funcs; i++) {
-+              struct sdio_func *func = host->card->sdio_func[i];
-+              if (func && sdio_func_present(func) && func->dev.driver) {
-+                      const struct dev_pm_ops *pmops = func->dev.driver->pm;
-+                      err = pmops->resume(&func->dev);
-+              }
-+      }
-+
-+      return err;
-+}
- static const struct mmc_bus_ops mmc_sdio_ops = {
-       .remove = mmc_sdio_remove,
-       .detect = mmc_sdio_detect,
-+      .suspend = mmc_sdio_suspend,
-+      .resume = mmc_sdio_resume,
- };
-@@ -275,13 +494,6 @@ int mmc_attach_sdio(struct mmc_host *hos
-               ocr &= ~0x7F;
-       }
--      if (ocr & MMC_VDD_165_195) {
--              printk(KERN_WARNING "%s: SDIO card claims to support the "
--                     "incompletely defined 'low voltage range'. This "
--                     "will be ignored.\n", mmc_hostname(host));
--              ocr &= ~MMC_VDD_165_195;
--      }
--
-       host->ocr = mmc_select_voltage(host, ocr);
-       /*
-@@ -293,108 +505,31 @@ int mmc_attach_sdio(struct mmc_host *hos
-       }
-       /*
--       * Inform the card of the voltage
-+       * Detect and init the card.
-        */
--      err = mmc_send_io_op_cond(host, host->ocr, &ocr);
-+      err = mmc_sdio_init_card(host, host->ocr, NULL);
-       if (err)
-               goto err;
--
--      /*
--       * For SPI, enable CRC as appropriate.
--       */
--      if (mmc_host_is_spi(host)) {
--              err = mmc_spi_set_crc(host, use_spi_crc);
--              if (err)
--                      goto err;
--      }
-+      card = host->card;
-       /*
-        * The number of functions on the card is encoded inside
-        * the ocr.
-        */
-       funcs = (ocr & 0x70000000) >> 28;
-+      card->sdio_funcs = 0;
-       /*
--       * Allocate card structure.
--       */
--      card = mmc_alloc_card(host, NULL);
--      if (IS_ERR(card)) {
--              err = PTR_ERR(card);
--              goto err;
--      }
--
--      card->type = MMC_TYPE_SDIO;
--      card->sdio_funcs = funcs;
--
--      host->card = card;
--
--      /*
--       * For native busses:  set card RCA and quit open drain mode.
-+       * If needed, disconnect card detection pull-up resistor.
-        */
--      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 registers.
--       */
--      err = sdio_read_cccr(card);
--      if (err)
--              goto remove;
--
--      /*
--       * Read the common CIS tuples.
--       */
--      err = sdio_read_common_cis(card);
--      if (err)
--              goto remove;
--
--      /*
--       * Switch to high-speed (if supported).
--       */
--      err = sdio_enable_hs(card);
--      if (err)
--              goto remove;
--
--      /*
--       * Change to the card's maximum speed.
--       */
--      if (mmc_card_highspeed(card)) {
--              /*
--               * The SDIO specification doesn't mention how
--               * the CIS transfer speed register relates to
--               * high-speed, but it seems that 50 MHz is
--               * mandatory.
--               */
--              mmc_set_clock(host, 50000000);
--      } else {
--              mmc_set_clock(host, card->cis.max_dtr);
--      }
--
--      /*
--       * Switch to wider bus (if supported).
--       */
--      err = sdio_enable_wide(card);
-+      err = sdio_disable_cd(card);
-       if (err)
-               goto remove;
-       /*
-        * Initialize (but don't add) all present functions.
-        */
--      for (i = 0;i < funcs;i++) {
-+      for (i = 0; i < funcs; i++, card->sdio_funcs++) {
-               err = sdio_init_func(host->card, i + 1);
-               if (err)
-                       goto remove;
---- a/drivers/mmc/core/sdio_cis.c
-+++ b/drivers/mmc/core/sdio_cis.c
-@@ -29,6 +29,8 @@ static int cistpl_vers_1(struct mmc_card
-       unsigned i, nr_strings;
-       char **buffer, *string;
-+      /* Find all null-terminated (including zero length) strings in
-+         the TPLLV1_INFO field. Trailing garbage is ignored. */
-       buf += 2;
-       size -= 2;
-@@ -39,11 +41,8 @@ static int cistpl_vers_1(struct mmc_card
-               if (buf[i] == 0)
-                       nr_strings++;
-       }
--
--      if (buf[i-1] != '\0') {
--              printk(KERN_WARNING "SDIO: ignoring broken CISTPL_VERS_1\n");
-+      if (nr_strings == 0)
-               return 0;
--      }
-       size = i;
-@@ -98,6 +97,22 @@ static const unsigned char speed_val[16]
- static const unsigned int speed_unit[8] =
-       { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 };
-+/* FUNCE tuples with these types get passed to SDIO drivers */
-+static const unsigned char funce_type_whitelist[] = {
-+      4 /* CISTPL_FUNCE_LAN_NODE_ID used in Broadcom cards */
-+};
-+
-+static int cistpl_funce_whitelisted(unsigned char type)
-+{
-+      int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(funce_type_whitelist); i++) {
-+              if (funce_type_whitelist[i] == type)
-+                      return 1;
-+      }
-+      return 0;
-+}
-+
- static int cistpl_funce_common(struct mmc_card *card,
-                              const unsigned char *buf, unsigned size)
- {
-@@ -120,6 +135,10 @@ static int cistpl_funce_func(struct sdio
-       unsigned vsn;
-       unsigned min_size;
-+      /* let SDIO drivers take care of whitelisted FUNCE tuples */
-+      if (cistpl_funce_whitelisted(buf[0]))
-+              return -EILSEQ;
-+
-       vsn = func->card->cccr.sdio_vsn;
-       min_size = (vsn == SDIO_SDIO_REV_1_00) ? 28 : 42;
-@@ -154,13 +173,12 @@ static int cistpl_funce(struct mmc_card 
-       else
-               ret = cistpl_funce_common(card, buf, size);
--      if (ret) {
-+      if (ret && ret != -EILSEQ) {
-               printk(KERN_ERR "%s: bad CISTPL_FUNCE size %u "
-                      "type %u\n", mmc_hostname(card->host), size, buf[0]);
--              return ret;
-       }
--      return 0;
-+      return ret;
- }
- typedef int (tpl_parse_t)(struct mmc_card *, struct sdio_func *,
-@@ -253,21 +271,12 @@ static int sdio_read_cis(struct mmc_card
-               for (i = 0; i < ARRAY_SIZE(cis_tpl_list); i++)
-                       if (cis_tpl_list[i].code == tpl_code)
-                               break;
--              if (i >= ARRAY_SIZE(cis_tpl_list)) {
--                      /* this tuple is unknown to the core */
--                      this->next = NULL;
--                      this->code = tpl_code;
--                      this->size = tpl_link;
--                      *prev = this;
--                      prev = &this->next;
--                      printk(KERN_DEBUG
--                             "%s: queuing CIS tuple 0x%02x length %u\n",
--                             mmc_hostname(card->host), tpl_code, tpl_link);
--              } else {
-+              if (i < ARRAY_SIZE(cis_tpl_list)) {
-                       const struct cis_tpl *tpl = cis_tpl_list + i;
-                       if (tpl_link < tpl->min_size) {
-                               printk(KERN_ERR
--                                     "%s: bad CIS tuple 0x%02x (length = %u, expected >= %u)\n",
-+                                     "%s: bad CIS tuple 0x%02x"
-+                                     " (length = %u, expected >= %u)\n",
-                                      mmc_hostname(card->host),
-                                      tpl_code, tpl_link, tpl->min_size);
-                               ret = -EINVAL;
-@@ -275,7 +284,30 @@ static int sdio_read_cis(struct mmc_card
-                               ret = tpl->parse(card, func,
-                                                this->data, tpl_link);
-                       }
--                      kfree(this);
-+                      /*
-+                       * We don't need the tuple anymore if it was
-+                       * successfully parsed by the SDIO core or if it is
-+                       * not going to be parsed by SDIO drivers.
-+                       */
-+                      if (!ret || ret != -EILSEQ)
-+                              kfree(this);
-+              } else {
-+                      /* unknown tuple */
-+                      ret = -EILSEQ;
-+              }
-+
-+              if (ret == -EILSEQ) {
-+                      /* this tuple is unknown to the core or whitelisted */
-+                      this->next = NULL;
-+                      this->code = tpl_code;
-+                      this->size = tpl_link;
-+                      *prev = this;
-+                      prev = &this->next;
-+                      printk(KERN_DEBUG
-+                             "%s: queuing CIS tuple 0x%02x length %u\n",
-+                             mmc_hostname(card->host), tpl_code, tpl_link);
-+                      /* keep on analyzing tuples */
-+                      ret = 0;
-               }
-               ptr += tpl_link;
---- a/drivers/mmc/core/sdio_io.c
-+++ b/drivers/mmc/core/sdio_io.c
-@@ -624,7 +624,7 @@ void sdio_f0_writeb(struct sdio_func *fu
-       BUG_ON(!func);
--      if (addr < 0xF0 || addr > 0xFF) {
-+      if ((addr < 0xF0 || addr > 0xFF) && (!mmc_card_lenient_fn0(func->card))) {
-               if (err_ret)
-                       *err_ret = -EINVAL;
-               return;
---- a/drivers/mmc/host/Kconfig
-+++ b/drivers/mmc/host/Kconfig
-@@ -55,6 +55,17 @@ config MMC_SDHCI_PCI
-         If unsure, say N.
-+config MMC_SDHCI_CNS3XXX
-+      tristate "SDHCI support on CNS3XXX"
-+      depends on MMC_SDHCI && ARCH_CNS3XXX
-+      help
-+        This selects the Secure Digital Host Controller Interface (SDHCI)
-+        in Cavium Networks CNS3XXX SOCs.
-+
-+        If you have a controller with this interface, say Y or M here.
-+
-+        If unsure, say N.
-+
- config MMC_RICOH_MMC
-       tristate "Ricoh MMC Controller Disabler  (EXPERIMENTAL)"
-       depends on MMC_SDHCI_PCI
---- a/drivers/mmc/host/Makefile
-+++ b/drivers/mmc/host/Makefile
-@@ -12,6 +12,7 @@ obj-$(CONFIG_MMC_IMX)                += imxmmc.o
- obj-$(CONFIG_MMC_MXC)         += mxcmmc.o
- obj-$(CONFIG_MMC_SDHCI)               += sdhci.o
- obj-$(CONFIG_MMC_SDHCI_PCI)   += sdhci-pci.o
-+obj-$(CONFIG_MMC_SDHCI_CNS3XXX)       += sdhci-cns3xxx.o
- obj-$(CONFIG_MMC_RICOH_MMC)   += ricoh_mmc.o
- obj-$(CONFIG_MMC_SDHCI_OF)    += sdhci-of.o
- obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
---- a/drivers/mmc/host/sdhci.c
-+++ b/drivers/mmc/host/sdhci.c
-@@ -27,6 +27,15 @@
- #define DRIVER_NAME "sdhci"
-+#define SDHCI_DEBUG
-+#undef SDHCI_DEBUG
-+
-+#ifdef SDHCI_DEBUG
-+#define sd_printk(x...)       printk(x)
-+#else
-+#define sd_printk(x...)       do { } while(0)
-+#endif
-+
- #define DBG(f, x...) \
-       pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)
-@@ -43,6 +52,39 @@ static void sdhci_finish_data(struct sdh
- static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
- static void sdhci_finish_command(struct sdhci_host *);
-+static void sdhci_dumpallregs(struct sdhci_host *host)
-+{
-+#ifdef SDHCI_DEBUG
-+      printk(" _______________________________________________\n");
-+
-+      printk("       0x00: 0x%08x | 0x04: 0x%08x\n", sdhci_readl(host, 0x00), sdhci_readl(host, 0x04));
-+      printk("       0x08: 0x%08x | 0x0C: 0x%08x\n", sdhci_readl(host, 0x08), sdhci_readl(host, 0x0C));
-+      printk("       0x10: 0x%08x | 0x14: 0x%08x\n", sdhci_readl(host, 0x10), sdhci_readl(host, 0x14));
-+      printk("       0x18: 0x%08x | 0x1C: 0x%08x\n", sdhci_readl(host, 0x18), sdhci_readl(host, 0x1C));
-+      printk("       -----------------| 0x24: 0x%08x\n", sdhci_readl(host, 0x24));
-+      printk("       0x28: 0x%08x | 0x2C: 0x%08x\n", sdhci_readl(host, 0x28), sdhci_readl(host, 0x2C));
-+      printk("       0x30: 0x%08x | 0x34: 0x%08x\n", sdhci_readl(host, 0x30), sdhci_readl(host, 0x34));
-+      printk("       0x38: 0x%08x | 0x3C: 0x%08x\n", sdhci_readl(host, 0x38), sdhci_readl(host, 0x3C));
-+      printk("       0x40: 0x%08x | 0x44: 0x%08x\n", sdhci_readl(host, 0x40), sdhci_readl(host, 0x44));
-+      printk("       0x48: 0x%08x | 0x4C: 0x%08x\n", sdhci_readl(host, 0x48), sdhci_readl(host, 0x4C));
-+      printk("       0x50: 0x%08x | 0xFC: 0x%08x\n", sdhci_readl(host, 0x50), sdhci_readl(host, 0xFC));
-+//#else
-+      printk(KERN_DEBUG " _______________________________________________\n");
-+
-+      printk(KERN_DEBUG "       0x00: 0x%08x | 0x04: 0x%08x\n", sdhci_readl(host, 0x00), sdhci_readl(host, 0x04));
-+      printk(KERN_DEBUG "       0x08: 0x%08x | 0x0C: 0x%08x\n", sdhci_readl(host, 0x08), sdhci_readl(host, 0x0C));
-+      printk(KERN_DEBUG "       0x10: 0x%08x | 0x14: 0x%08x\n", sdhci_readl(host, 0x10), sdhci_readl(host, 0x14));
-+      printk(KERN_DEBUG "       0x18: 0x%08x | 0x1C: 0x%08x\n", sdhci_readl(host, 0x18), sdhci_readl(host, 0x1C));
-+      printk(KERN_DEBUG "       -----------------| 0x24: 0x%08x\n", sdhci_readl(host, 0x24));
-+      printk(KERN_DEBUG "       0x28: 0x%08x | 0x2C: 0x%08x\n", sdhci_readl(host, 0x28), sdhci_readl(host, 0x2C));
-+      printk(KERN_DEBUG "       0x30: 0x%08x | 0x34: 0x%08x\n", sdhci_readl(host, 0x30), sdhci_readl(host, 0x34));
-+      printk(KERN_DEBUG "       0x38: 0x%08x | 0x3C: 0x%08x\n", sdhci_readl(host, 0x38), sdhci_readl(host, 0x3C));
-+      printk(KERN_DEBUG "       0x40: 0x%08x | 0x44: 0x%08x\n", sdhci_readl(host, 0x40), sdhci_readl(host, 0x44));
-+      printk(KERN_DEBUG "       0x48: 0x%08x | 0x4C: 0x%08x\n", sdhci_readl(host, 0x48), sdhci_readl(host, 0x4C));
-+      printk(KERN_DEBUG "       0x50: 0x%08x | 0xFC: 0x%08x\n", sdhci_readl(host, 0x50), sdhci_readl(host, 0xFC));
-+#endif
-+}
-+
- static void sdhci_dumpregs(struct sdhci_host *host)
- {
-       printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n");
-@@ -591,6 +633,9 @@ static u8 sdhci_calc_timeout(struct sdhc
-       target_timeout = data->timeout_ns / 1000 +
-               data->timeout_clks / host->clock;
-+      if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
-+              host->timeout_clk = host->clock / 1000;
-+
-       /*
-        * Figure out needed cycles.
-        * We do this in steps in order to fit inside a 32 bit int.
-@@ -622,7 +667,7 @@ static u8 sdhci_calc_timeout(struct sdhc
- static void sdhci_set_transfer_irqs(struct sdhci_host *host)
- {
-       u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL;
--      u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR;
-+      u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ACMD12ERR | SDHCI_INT_ADMA_ERROR;
-       if (host->flags & SDHCI_REQ_USE_DMA)
-               sdhci_clear_set_irqs(host, pio_irqs, dma_irqs);
-@@ -652,7 +697,7 @@ static void sdhci_prepare_data(struct sd
-       count = sdhci_calc_timeout(host, data);
-       sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
--      if (host->flags & SDHCI_USE_DMA)
-+      if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))
-               host->flags |= SDHCI_REQ_USE_DMA;
-       /*
-@@ -736,11 +781,21 @@ static void sdhci_prepare_data(struct sd
-               } else {
-                       int sg_cnt;
-+                      sd_printk("[SDHCI_DEBUG] dma_map_sg(), mmc_dev(host->mmc) = %p \n", mmc_dev(host->mmc));
-+                      sd_printk("[SDHCI_DEBUG] dma_map_sg(), data->sg = %p \n", data->sg);
-+                      sd_printk("[SDHCI_DEBUG] dma_map_sg(), data->sg_len = %d \n", data->sg_len);
-                       sg_cnt = dma_map_sg(mmc_dev(host->mmc),
-                                       data->sg, data->sg_len,
-                                       (data->flags & MMC_DATA_READ) ?
-                                               DMA_FROM_DEVICE :
-                                               DMA_TO_DEVICE);
-+                      if (data->sg == NULL) {
-+                              sd_printk("[SDHCI_DEBUG] dma_map_sg(), data->sg = (NULL) \n");
-+                              return;
-+                      }
-+                      sd_printk("[SDHCI_DEBUG] dma_map_sg(), data->sg = %p \n", data->sg);
-+                      sd_printk("[SDHCI_DEBUG] dma_map_sg(), sg_cnt = %d \n", sg_cnt);
-+
-                       if (sg_cnt == 0) {
-                               /*
-                                * This only happens when someone fed
-@@ -750,6 +805,7 @@ static void sdhci_prepare_data(struct sd
-                               host->flags &= ~SDHCI_REQ_USE_DMA;
-                       } else {
-                               WARN_ON(sg_cnt != 1);
-+                              sd_printk("[SDHCI_DEBUG] sg_dma_address() => %08x \n", sg_dma_address(data->sg));
-                               sdhci_writel(host, sg_dma_address(data->sg),
-                                       SDHCI_DMA_ADDRESS);
-                       }
-@@ -763,14 +819,32 @@ static void sdhci_prepare_data(struct sd
-        */
-       if (host->version >= SDHCI_SPEC_200) {
-               ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
-+#ifdef SDHCI_USE_LEDS_CLASS
-+              ctrl |= SDHCI_CTRL_LED;
-+#else
-+              ctrl &= ~SDHCI_CTRL_LED;
-+#endif
-               ctrl &= ~SDHCI_CTRL_DMA_MASK;
-               if ((host->flags & SDHCI_REQ_USE_DMA) &&
-                       (host->flags & SDHCI_USE_ADMA))
-                       ctrl |= SDHCI_CTRL_ADMA32;
-               else
-                       ctrl |= SDHCI_CTRL_SDMA;
-+
-               sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
--      }
-+      } else if (host->version == SDHCI_SPEC_100) {
-+              ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
-+#ifdef SDHCI_USE_LEDS_CLASS
-+              ctrl |= SDHCI_CTRL_LED;
-+#else
-+              ctrl &= ~SDHCI_CTRL_LED;
-+#endif
-+              ctrl &= ~SDHCI_CTRL_DMA_MASK;
-+              if (host->flags & SDHCI_REQ_USE_DMA)
-+                      ctrl |= SDHCI_CTRL_SDMA;
-+
-+              sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-+      }       
-       if (!(host->flags & SDHCI_REQ_USE_DMA)) {
-               int flags;
-@@ -795,15 +869,26 @@ static void sdhci_set_transfer_mode(stru
-       struct mmc_data *data)
- {
-       u16 mode;
-+      u8 bgctrl;
-       if (data == NULL)
-               return;
-       WARN_ON(!host->data);
-+      bgctrl = sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL);
-+      if (host->quirks & SDHCI_QUIRK_READ_WAIT_CTRL)
-+              bgctrl |= SDHCI_READ_WAIT_CTRL;
-+      sdhci_writeb(host, bgctrl, SDHCI_BLOCK_GAP_CONTROL);
-+
-       mode = SDHCI_TRNS_BLK_CNT_EN;
--      if (data->blocks > 1)
-+
-+      if (data->blocks > 1) {
-               mode |= SDHCI_TRNS_MULTI;
-+
-+              if (host->quirks & SDHCI_QUIRK_AUTO_CMD12)
-+                      mode |= SDHCI_TRNS_ACMD12;
-+      }
-       if (data->flags & MMC_DATA_READ)
-               mode |= SDHCI_TRNS_READ;
-       if (host->flags & SDHCI_REQ_USE_DMA)
-@@ -812,6 +897,20 @@ static void sdhci_set_transfer_mode(stru
-       sdhci_writew(host, mode, SDHCI_TRANSFER_MODE);
- }
-+static void shdci_check_dma_overrun(struct sdhci_host *host, struct mmc_data *data)
-+{
-+      u32 dma_pos = sdhci_readl(host, SDHCI_DMA_ADDRESS);
-+      u32 dma_start = sg_dma_address(data->sg);
-+      u32 dma_end = dma_start + data->sg->length;
-+
-+      /* Test whether we ended up moving more data than was originally requested. */
-+      if (dma_pos <= dma_end)
-+              return;
-+
-+      printk(KERN_ERR "%s: dma overrun, dma %08x, req %08x..%08x\n",
-+             mmc_hostname(host->mmc), dma_pos, dma_start, dma_end);
-+}
-+
- static void sdhci_finish_data(struct sdhci_host *host)
- {
-       struct mmc_data *data;
-@@ -825,6 +924,9 @@ static void sdhci_finish_data(struct sdh
-               if (host->flags & SDHCI_USE_ADMA)
-                       sdhci_adma_table_post(host, data);
-               else {
-+                      shdci_check_dma_overrun(host, data);
-+
-+                      sd_printk("[SDHCI_DEBUG] dma_unmap_sg(), data->sg_len = %d \n", data->sg_len);
-                       dma_unmap_sg(mmc_dev(host->mmc), data->sg,
-                               data->sg_len, (data->flags & MMC_DATA_READ) ?
-                                       DMA_FROM_DEVICE : DMA_TO_DEVICE);
-@@ -866,12 +968,16 @@ static void sdhci_send_command(struct sd
-       WARN_ON(host->cmd);
-+      sd_printk("[SDHCI_DEBUG] sdhci_send_command() \n");
-+
-       /* Wait max 10 ms */
-       timeout = 10;
-       mask = SDHCI_CMD_INHIBIT;
-       if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY))
-               mask |= SDHCI_DATA_INHIBIT;
-+      if ((cmd->data != NULL))
-+              mask |= SDHCI_DATA_INHIBIT;
-       /* We shouldn't wait for data inihibit for stop commands, even
-          though they might use busy signaling */
-@@ -925,7 +1031,11 @@ static void sdhci_send_command(struct sd
-       if (cmd->data)
-               flags |= SDHCI_CMD_DATA;
-+      sd_printk("[SDHCI_DEBUG] sdhci_send_command() => %08x \n", SDHCI_MAKE_CMD(cmd->opcode, flags));
-+      sdhci_dumpallregs(host);
-       sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
-+      sd_printk("[SDHCI_DEBUG] sdhci_send_command(): After issue command \n");
-+      sdhci_dumpallregs(host);
- }
- static void sdhci_finish_command(struct sdhci_host *host)
-@@ -934,6 +1044,8 @@ static void sdhci_finish_command(struct 
-       BUG_ON(host->cmd == NULL);
-+      sd_printk("[SDHCI_DEBUG] sdhci_finish_command() \n");
-+
-       if (host->cmd->flags & MMC_RSP_PRESENT) {
-               if (host->cmd->flags & MMC_RSP_136) {
-                       /* CRC is stripped so we need to do some shifting. */
-@@ -991,8 +1103,8 @@ static void sdhci_set_clock(struct sdhci
-       clk |= SDHCI_CLOCK_INT_EN;
-       sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
--      /* Wait max 10 ms */
--      timeout = 10;
-+      /* Wait max 20 ms */
-+      timeout = 20;
-       while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
-               & SDHCI_CLOCK_INT_STABLE)) {
-               if (timeout == 0) {
-@@ -1154,6 +1266,12 @@ static void sdhci_set_ios(struct mmc_hos
-       else
-               ctrl &= ~SDHCI_CTRL_HISPD;
-+#ifdef SDHCI_USE_LEDS_CLASS
-+      ctrl |= SDHCI_CTRL_LED;
-+#else
-+      ctrl &= ~SDHCI_CTRL_LED;
-+#endif
-+
-       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-       /*
-@@ -1321,7 +1439,11 @@ static void sdhci_timeout_timer(unsigned
-       if (host->mrq) {
-               printk(KERN_ERR "%s: Timeout waiting for hardware "
-                       "interrupt.\n", mmc_hostname(host->mmc));
-+#ifdef SDHCI_DEBUG
-+              sdhci_dumpallregs(host);
-+#else
-               sdhci_dumpregs(host);
-+#endif
-               if (host->data) {
-                       host->data->error = -ETIMEDOUT;
-@@ -1508,6 +1630,10 @@ static irqreturn_t sdhci_irq(int irq, vo
-       DBG("*** %s got interrupt: 0x%08x\n",
-               mmc_hostname(host->mmc), intmask);
-+#ifdef SDHCI_DEBUG
-+      printk("*** %s got interrupt: 0x%08x\n", mmc_hostname(host->mmc), intmask);
-+#endif
-+
-       if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
-               sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
-                       SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
-@@ -1597,7 +1723,7 @@ int sdhci_resume_host(struct sdhci_host 
- {
-       int ret;
--      if (host->flags & SDHCI_USE_DMA) {
-+      if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
-               if (host->ops->enable_dma)
-                       host->ops->enable_dma(host);
-       }
-@@ -1678,23 +1804,20 @@ int sdhci_add_host(struct sdhci_host *ho
-       caps = sdhci_readl(host, SDHCI_CAPABILITIES);
-       if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
--              host->flags |= SDHCI_USE_DMA;
--      else if (!(caps & SDHCI_CAN_DO_DMA))
--              DBG("Controller doesn't have DMA capability\n");
-+              host->flags |= SDHCI_USE_SDMA;
-+      else if (!(caps & SDHCI_CAN_DO_SDMA))
-+              DBG("Controller doesn't have SDMA capability\n");
-       else
--              host->flags |= SDHCI_USE_DMA;
-+              host->flags |= SDHCI_USE_SDMA;
-       if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) &&
--              (host->flags & SDHCI_USE_DMA)) {
-+              (host->flags & SDHCI_USE_SDMA)) {
-               DBG("Disabling DMA as it is marked broken\n");
--              host->flags &= ~SDHCI_USE_DMA;
-+              host->flags &= ~SDHCI_USE_SDMA;
-       }
--      if (host->flags & SDHCI_USE_DMA) {
--              if ((host->version >= SDHCI_SPEC_200) &&
--                              (caps & SDHCI_CAN_DO_ADMA2))
--                      host->flags |= SDHCI_USE_ADMA;
--      }
-+      if ((host->version >= SDHCI_SPEC_200) && (caps & SDHCI_CAN_DO_ADMA2))
-+              host->flags |= SDHCI_USE_ADMA;
-       if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) &&
-               (host->flags & SDHCI_USE_ADMA)) {
-@@ -1702,13 +1825,14 @@ int sdhci_add_host(struct sdhci_host *ho
-               host->flags &= ~SDHCI_USE_ADMA;
-       }
--      if (host->flags & SDHCI_USE_DMA) {
-+      if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
-               if (host->ops->enable_dma) {
-                       if (host->ops->enable_dma(host)) {
-                               printk(KERN_WARNING "%s: No suitable DMA "
-                                       "available. Falling back to PIO.\n",
-                                       mmc_hostname(mmc));
--                              host->flags &= ~(SDHCI_USE_DMA | SDHCI_USE_ADMA);
-+                              host->flags &=
-+                                      ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA);
-                       }
-               }
-       }
-@@ -1736,7 +1860,7 @@ int sdhci_add_host(struct sdhci_host *ho
-        * mask, but PIO does not need the hw shim so we set a new
-        * mask here in that case.
-        */
--      if (!(host->flags & SDHCI_USE_DMA)) {
-+      if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) {
-               host->dma_mask = DMA_BIT_MASK(64);
-               mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
-       }
-@@ -1757,13 +1881,15 @@ int sdhci_add_host(struct sdhci_host *ho
-       host->timeout_clk =
-               (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
-       if (host->timeout_clk == 0) {
--              if (!host->ops->get_timeout_clock) {
-+              if (host->ops->get_timeout_clock) {
-+                      host->timeout_clk = host->ops->get_timeout_clock(host);
-+              } else if (!(host->quirks &
-+                              SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
-                       printk(KERN_ERR
-                              "%s: Hardware doesn't specify timeout clock "
-                              "frequency.\n", mmc_hostname(mmc));
-                       return -ENODEV;
-               }
--              host->timeout_clk = host->ops->get_timeout_clock(host);
-       }
-       if (caps & SDHCI_TIMEOUT_CLK_UNIT)
-               host->timeout_clk *= 1000;
-@@ -1772,7 +1898,8 @@ int sdhci_add_host(struct sdhci_host *ho
-        * Set host parameters.
-        */
-       mmc->ops = &sdhci_ops;
--      if (host->ops->get_min_clock)
-+      if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK &&
-+                      host->ops->set_clock && host->ops->get_min_clock)
-               mmc->f_min = host->ops->get_min_clock(host);
-       else
-               mmc->f_min = host->max_clk / 256;
-@@ -1810,7 +1937,7 @@ int sdhci_add_host(struct sdhci_host *ho
-        */
-       if (host->flags & SDHCI_USE_ADMA)
-               mmc->max_hw_segs = 128;
--      else if (host->flags & SDHCI_USE_DMA)
-+      else if (host->flags & SDHCI_USE_SDMA)
-               mmc->max_hw_segs = 1;
-       else /* PIO */
-               mmc->max_hw_segs = 128;
-@@ -1893,10 +2020,10 @@ int sdhci_add_host(struct sdhci_host *ho
-       mmc_add_host(mmc);
--      printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s%s\n",
-+      printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s\n",
-               mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
--              (host->flags & SDHCI_USE_ADMA)?"A":"",
--              (host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
-+              (host->flags & SDHCI_USE_ADMA) ? "ADMA" :
-+              (host->flags & SDHCI_USE_SDMA) ? "SDMA" : "PIO");
-       sdhci_enable_card_detection(host);
---- /dev/null
-+++ b/drivers/mmc/host/sdhci-cns3xxx.c
-@@ -0,0 +1,313 @@
-+/*******************************************************************************
-+ *
-+ *  drivers/mmc/host/sdhci-cns3xxx.c
-+ *
-+ *  SDHCI support for the CNS3XXX SOCs
-+ *
-+ *  Author: Scott Shu
-+ *
-+ *  Copyright (c) 2008 Cavium Networks 
-+ * 
-+ *  This file is free software; you can redistribute it and/or modify 
-+ *  it under the terms of the GNU General Public License, Version 2, as 
-+ *  published by the Free Software Foundation. 
-+ *
-+ *  This file is distributed in the hope that it will be useful, 
-+ *  but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of 
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 
-+ *  NONINFRINGEMENT.  See the GNU General Public License for more details. 
-+ *
-+ *  You should have received a copy of the GNU General Public License 
-+ *  along with this file; if not, write to the Free Software 
-+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or 
-+ *  visit http://www.gnu.org/licenses/. 
-+ *
-+ *  This file may also be available under a different license from Cavium. 
-+ *  Contact Cavium Networks for more information
-+ *
-+ ******************************************************************************/
-+
-+#include <linux/delay.h>
-+#include <linux/highmem.h>
-+#include <linux/platform_device.h>
-+#include <linux/dma-mapping.h>
-+
-+#include <linux/mmc/host.h>
-+
-+#include <asm/scatterlist.h>
-+#include <asm/io.h>
-+#include <linux/interrupt.h>
-+
-+#include <mach/sdhci.h>
-+#include <mach/pm.h>
-+
-+#include "sdhci.h"
-+
-+//#define DEBUG
-+
-+#define MAX_BUS_CLK   (4)
-+
-+static unsigned __initdata use_dma = 0;
-+
-+struct sdhci_cns3xxx {
-+      struct sdhci_host       *host;
-+      struct platform_device  *pdev;
-+      struct resource         *ioarea;
-+      struct cns3xxx_sdhci_platdata *pdata;
-+      struct clk              *clk_io;
-+      struct clk              *clk_bus[MAX_BUS_CLK];
-+};
-+
-+static unsigned int sdhci_cns3xxx_get_max_clk(struct sdhci_host *host)
-+{
-+      int clk = 50000000;
-+
-+      return clk;
-+}
-+
-+static unsigned int sdhci_cns3xxx_get_timeout_clk(struct sdhci_host *host)
-+{
-+      return sdhci_cns3xxx_get_max_clk(host) / 100000;
-+}
-+
-+/*
-+ * sdhci_cns3xxx_set_clock - callback on clock change
-+ *
-+ * When the card's clock is going to be changed, look at the new frequency
-+ * and find the best clock source to go with it.
-+ */
-+static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)
-+{
-+      u16 clk;
-+      unsigned long timeout;
-+
-+      if (clock == host->clock)
-+              return;
-+
-+      sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
-+
-+      if (clock == 0)
-+              goto out;
-+#if 1
-+      clk = 0x03 << SDHCI_DIVIDER_SHIFT;      /* base clock divided by 3 */
-+#else
-+      /* high speed mode or normal speed mode */
-+      if (0x4 & sdhci_readw(host, 0x28)) {
-+              clk = 0x03 << SDHCI_DIVIDER_SHIFT;      /* base clock divided by 3 */
-+      } else {
-+              clk = 0x02 << SDHCI_DIVIDER_SHIFT;      /* base clock divided by 4 */
-+      }
-+#endif
-+      clk |= SDHCI_CLOCK_INT_EN;
-+      sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-+
-+      timeout = 10;
-+      while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
-+              & SDHCI_CLOCK_INT_STABLE)) {
-+              if (timeout == 0) {
-+                      return;
-+              }
-+              timeout--;
-+              mdelay(1);
-+      }
-+
-+      clk |= SDHCI_CLOCK_CARD_EN;
-+      sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-+
-+      host->timeout_clk = sdhci_cns3xxx_get_timeout_clk(host);
-+out:
-+      host->clock = clock;
-+}
-+
-+static struct sdhci_ops sdhci_cns3xxx_ops = {
-+      .get_max_clock          = sdhci_cns3xxx_get_max_clk,
-+      .get_timeout_clock      = sdhci_cns3xxx_get_timeout_clk,
-+      .set_clock              = sdhci_cns3xxx_set_clock,
-+};
-+
-+static int __devinit sdhci_cns3xxx_probe(struct platform_device *pdev)
-+{
-+      struct cns3xxx_sdhci_platdata *pdata = pdev->dev.platform_data;
-+      struct device *dev = &pdev->dev;
-+      struct sdhci_host *host;
-+      struct sdhci_cns3xxx *sc;
-+      struct resource *res;
-+      int ret, irq;
-+
-+      if (!pdata) {
-+              dev_err(dev, "no device data specified\n");
-+              return -ENOENT;
-+      }
-+
-+      irq = platform_get_irq(pdev, 0);
-+      if (irq < 0) {
-+              dev_err(dev, "no irq specified\n");
-+              return irq;
-+      }
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      if (!res) {
-+              dev_err(dev, "no memory specified\n");
-+              return -ENOENT;
-+      }
-+
-+      host = sdhci_alloc_host(dev, sizeof(*sc));
-+      if (IS_ERR(host)) {
-+              dev_err(dev, "sdhci_alloc_host() failed\n");
-+              return PTR_ERR(host);
-+      }
-+
-+      sc = sdhci_priv(host);
-+
-+      sc->host = host;
-+      sc->pdev = pdev;
-+      sc->pdata = pdata;
-+
-+      platform_set_drvdata(pdev, host);
-+
-+      sc->ioarea = request_mem_region(res->start, resource_size(res), mmc_hostname(host->mmc));
-+      if (!sc->ioarea) {
-+              dev_err(dev, "failed to reserve register area\n");
-+              ret = -ENXIO;
-+              goto err_req_regs;
-+      }
-+
-+      host->ioaddr = ioremap_nocache(res->start, resource_size(res));
-+      if (!host->ioaddr) {
-+              dev_err(dev, "failed to map registers\n");
-+              ret = -ENXIO;
-+              goto err_req_regs;
-+      }
-+
-+      host->hw_name = "cns3xxx";
-+      host->ops = &sdhci_cns3xxx_ops;
-+      host->quirks = 0;
-+      host->irq = irq;
-+
-+      if (use_dma != 1) {
-+              host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
-+              host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
-+      } else {
-+              host->quirks |= SDHCI_QUIRK_FORCE_DMA;
-+              host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
-+              host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE);
-+              host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ;
-+              //host->quirks |= SDHCI_QUIRK_FORCE_BLK_SZ_2048;
-+              //host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
-+              host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
-+              host->quirks |= SDHCI_QUIRK_AUTO_CMD12;
-+              host->quirks |= SDHCI_QUIRK_READ_WAIT_CTRL;
-+      }
-+
-+      //host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
-+
-+      host->quirks |= SDHCI_QUIRK_NONSTANDARD_CLOCK;
-+
-+      host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
-+
-+      ret = sdhci_add_host(host);
-+      if (ret) {
-+              dev_err(dev, "sdhci_add_host() failed (%d)\n", ret);
-+              goto err_add_host;
-+      }
-+
-+      return 0;
-+
-+err_add_host:
-+      free_irq(host->irq, host);
-+      iounmap(host->ioaddr);
-+      release_resource(sc->ioarea);
-+      kfree(sc->ioarea);
-+
-+err_req_regs:
-+      sdhci_free_host(host);
-+
-+      return ret;
-+}
-+
-+static int __devexit sdhci_cns3xxx_remove(struct platform_device *pdev)
-+{
-+      struct device *dev = &pdev->dev;
-+      struct sdhci_host *host = dev_get_drvdata(dev);
-+      struct resource *res;
-+
-+      pr_debug("%s: remove=%p\n", __func__, pdev);
-+
-+      sdhci_remove_host(host, 0);
-+      sdhci_free_host(host);
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      release_mem_region(res->start, resource_size(res));
-+
-+      return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+
-+static int sdhci_cns3xxx_suspend(struct platform_device *dev, pm_message_t state)
-+{
-+
-+      return 0;
-+}
-+
-+static int sdhci_cns3xxx_resume(struct platform_device *dev)
-+{
-+
-+      return 0;
-+}
-+
-+#else
-+#define sdhci_cns3xxx_suspend NULL
-+#define sdhci_cns3xxx_resume  NULL
-+#endif /* CONFIG_PM */
-+
-+static struct platform_driver sdhci_cns3xxx_driver = {
-+      .probe          = sdhci_cns3xxx_probe,
-+      .remove         = __devexit_p(sdhci_cns3xxx_remove),
-+      .suspend        = sdhci_cns3xxx_suspend,
-+      .resume         = sdhci_cns3xxx_resume,
-+      .driver         = {
-+              .name   = "cns3xxx-sdhci",
-+              .owner  = THIS_MODULE,
-+      },
-+};
-+
-+static char banner[] __initdata = KERN_INFO "cns3xxx-sdhci, (c) 2009 Cavium Networks\n";
-+
-+static int __init sdhci_cns3xxx_init(void)
-+{
-+#ifdef CONFIG_SILICON
-+      unsigned long gpioapin = __raw_readl((void __iomem *)(CNS3XXX_MISC_BASE_VIRT + 0x0014));;
-+#else
-+      unsigned long status = __raw_readl((void __iomem *)(CNS3XXX_MISC_BASE_VIRT + 0x0700));
-+#endif
-+
-+      printk(banner);
-+
-+#ifdef CONFIG_SILICON
-+      /* MMC/SD pins share with GPIOA */
-+      __raw_writel(gpioapin | (0x1fff0004), (void __iomem *)(CNS3XXX_MISC_BASE_VIRT + 0x0014));
-+      cns3xxx_pwr_clk_en(CNS3XXX_PWR_CLK_EN(SDIO));
-+    cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SDIO));
-+#else
-+      /* insert a delay on SDIO output interface (only for FPGA mode & high-speed mode) */
-+      __raw_writel(status | (1 << 4), (void __iomem *)(CNS3XXX_MISC_BASE_VIRT + 0x0700));
-+#endif
-+      return platform_driver_register(&sdhci_cns3xxx_driver);
-+}
-+
-+static void __exit sdhci_cns3xxx_exit(void)
-+{
-+      platform_driver_unregister(&sdhci_cns3xxx_driver);
-+}
-+
-+module_init(sdhci_cns3xxx_init);
-+module_exit(sdhci_cns3xxx_exit);
-+
-+module_param(use_dma, uint, 0);
-+
-+MODULE_AUTHOR("Scott Shu");
-+MODULE_DESCRIPTION("Cavium Networks CNS3XXX SDHCI glue");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:cns3xxx-sdhci");
-+
-+MODULE_PARM_DESC(use_dma, "Whether to use DMA or not. Default = 0");
---- a/drivers/mmc/host/sdhci.h
-+++ b/drivers/mmc/host/sdhci.h
-@@ -8,6 +8,8 @@
-  * the Free Software Foundation; either version 2 of the License, or (at
-  * your option) any later version.
-  */
-+#ifndef __SDHCI_H
-+#define __SDHCI_H
- #include <linux/scatterlist.h>
- #include <linux/compiler.h>
-@@ -78,6 +80,7 @@
- #define  SDHCI_POWER_330      0x0E
- #define SDHCI_BLOCK_GAP_CONTROL       0x2A
-+#define  SDHCI_READ_WAIT_CTRL 0x04
- #define SDHCI_WAKE_UP_CONTROL 0x2B
-@@ -143,7 +146,7 @@
- #define  SDHCI_CAN_DO_ADMA2   0x00080000
- #define  SDHCI_CAN_DO_ADMA1   0x00100000
- #define  SDHCI_CAN_DO_HISPD   0x00200000
--#define  SDHCI_CAN_DO_DMA     0x00400000
-+#define  SDHCI_CAN_DO_SDMA    0x00400000
- #define  SDHCI_CAN_VDD_330    0x01000000
- #define  SDHCI_CAN_VDD_300    0x02000000
- #define  SDHCI_CAN_VDD_180    0x04000000
-@@ -232,6 +235,12 @@ struct sdhci_host {
- #define SDHCI_QUIRK_FORCE_1_BIT_DATA                  (1<<22)
- /* Controller needs 10ms delay between applying power and clock */
- #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 uses Auto CMD12 */
-+#define SDHCI_QUIRK_AUTO_CMD12                                (1<<25)
-+/* Controller uses read wait control protocol */
-+#define SDHCI_QUIRK_READ_WAIT_CTRL                    (1<<26)
-       int                     irq;            /* Device IRQ */
-       void __iomem *          ioaddr;         /* Mapped address */
-@@ -250,7 +259,7 @@ struct sdhci_host {
-       spinlock_t              lock;           /* Mutex */
-       int                     flags;          /* Host attributes */
--#define SDHCI_USE_DMA         (1<<0)          /* Host is DMA capable */
-+#define SDHCI_USE_SDMA                (1<<0)          /* Host is SDMA capable */
- #define SDHCI_USE_ADMA                (1<<1)          /* Host is ADMA capable */
- #define SDHCI_REQ_USE_DMA     (1<<2)          /* Use DMA for this req. */
- #define SDHCI_DEVICE_DEAD     (1<<3)          /* Device unresponsive */
-@@ -406,3 +415,5 @@ extern void sdhci_remove_host(struct sdh
- extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state);
- extern int sdhci_resume_host(struct sdhci_host *host);
- #endif
-+
-+#endif /* __SDHCI_H */
---- a/include/linux/mmc/card.h
-+++ b/include/linux/mmc/card.h
-@@ -40,6 +40,8 @@ struct mmc_csd {
- };
- struct mmc_ext_csd {
-+      u8                      rev;
-+      unsigned int            sa_timeout;             /* Units: 100ns */
-       unsigned int            hs_max_dtr;
-       unsigned int            sectors;
- };
-@@ -62,7 +64,8 @@ struct sdio_cccr {
-                               low_speed:1,
-                               wide_bus:1,
-                               high_power:1,
--                              high_speed:1;
-+                              high_speed:1,
-+                              disable_cd:1;
- };
- struct sdio_cis {
-@@ -94,6 +97,8 @@ 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 */
-+      unsigned int            quirks;         /* card quirks */
-+#define MMC_QUIRK_LENIENT_FN0 (1<<0)          /* allow SDIO FN0 writes outside of the VS CCCR range */
-       u32                     raw_cid[4];     /* raw card CID */
-       u32                     raw_csd[4];     /* raw card CSD */
-@@ -129,6 +134,11 @@ struct mmc_card {
- #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
- #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
-+static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
-+{
-+      return c->quirks & MMC_QUIRK_LENIENT_FN0;
-+}
-+
- #define mmc_card_name(c)      ((c)->cid.prod_name)
- #define mmc_card_id(c)                (dev_name(&(c)->dev))
---- a/include/linux/mmc/core.h
-+++ b/include/linux/mmc/core.h
-@@ -139,6 +139,7 @@ extern unsigned int mmc_align_data_size(
- extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort);
- extern void mmc_release_host(struct mmc_host *host);
-+extern int mmc_try_claim_host(struct mmc_host *host);
- /**
-  *    mmc_claim_host - exclusively claim a host
---- a/include/linux/mmc/host.h
-+++ b/include/linux/mmc/host.h
-@@ -11,6 +11,7 @@
- #define LINUX_MMC_HOST_H
- #include <linux/leds.h>
-+#include <linux/sched.h>
- #include <linux/mmc/core.h>
-@@ -51,6 +52,35 @@ struct mmc_ios {
- };
- struct mmc_host_ops {
-+      /*
-+       * Hosts that support power saving can use the 'enable' and 'disable'
-+       * methods to exit and enter power saving states. 'enable' is called
-+       * when the host is claimed and 'disable' is called (or scheduled with
-+       * a delay) when the host is released. The 'disable' is scheduled if
-+       * the disable delay set by 'mmc_set_disable_delay()' is non-zero,
-+       * otherwise 'disable' is called immediately. 'disable' may be
-+       * scheduled repeatedly, to permit ever greater power saving at the
-+       * expense of ever greater latency to re-enable. Rescheduling is
-+       * determined by the return value of the 'disable' method. A positive
-+       * value gives the delay in milliseconds.
-+       *
-+       * In the case where a host function (like set_ios) may be called
-+       * with or without the host claimed, enabling and disabling can be
-+       * done directly and will nest correctly. Call 'mmc_host_enable()' and
-+       * 'mmc_host_lazy_disable()' for this purpose, but note that these
-+       * functions must be paired.
-+       *
-+       * Alternatively, 'mmc_host_enable()' may be paired with
-+       * 'mmc_host_disable()' which calls 'disable' immediately.  In this
-+       * case the 'disable' method will be called with 'lazy' set to 0.
-+       * This is mainly useful for error paths.
-+       *
-+       * Because lazy disable may be called from a work queue, the 'disable'
-+       * method must claim the host when 'lazy' != 0, which will work
-+       * correctly because recursion is detected and handled.
-+       */
-+      int (*enable)(struct mmc_host *host);
-+      int (*disable)(struct mmc_host *host, int lazy);
-       void    (*request)(struct mmc_host *host, struct mmc_request *req);
-       /*
-        * Avoid calling these three functions too often or in a "fast path",
-@@ -118,6 +148,9 @@ struct mmc_host {
- #define MMC_CAP_SPI           (1 << 4)        /* Talks only SPI protocols */
- #define MMC_CAP_NEEDS_POLL    (1 << 5)        /* Needs polling for card-detection */
- #define MMC_CAP_8_BIT_DATA    (1 << 6)        /* Can the host do 8 bit transfers */
-+#define MMC_CAP_DISABLE               (1 << 7)        /* Can the host be disabled */
-+#define MMC_CAP_NONREMOVABLE  (1 << 8)        /* Nonremovable e.g. eMMC */
-+#define MMC_CAP_WAIT_WHILE_BUSY       (1 << 9)        /* Waits while card is busy */
-       /* host specific block data */
-       unsigned int            max_seg_size;   /* see blk_queue_max_segment_size */
-@@ -142,9 +175,18 @@ struct mmc_host {
-       unsigned int            removed:1;      /* host is being removed */
- #endif
-+      /* Only used with MMC_CAP_DISABLE */
-+      int                     enabled;        /* host is enabled */
-+      int                     nesting_cnt;    /* "enable" nesting count */
-+      int                     en_dis_recurs;  /* detect recursion */
-+      unsigned int            disable_delay;  /* disable delay in msecs */
-+      struct delayed_work     disable;        /* disabling work */
-+
-       struct mmc_card         *card;          /* device attached to this host */
-       wait_queue_head_t       wq;
-+      struct task_struct      *claimer;       /* task that has host claimed */
-+      int                     claim_cnt;      /* "claim" nesting count */
-       struct delayed_work     detect;
-@@ -183,6 +225,9 @@ static inline void *mmc_priv(struct mmc_
- extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
- extern int mmc_resume_host(struct mmc_host *);
-+extern void mmc_power_save_host(struct mmc_host *host);
-+extern void mmc_power_restore_host(struct mmc_host *host);
-+
- extern void mmc_detect_change(struct mmc_host *, unsigned long delay);
- extern void mmc_request_done(struct mmc_host *, struct mmc_request *);
-@@ -197,5 +242,19 @@ struct regulator;
- int mmc_regulator_get_ocrmask(struct regulator *supply);
- int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit);
-+int mmc_card_awake(struct mmc_host *host);
-+int mmc_card_sleep(struct mmc_host *host);
-+int mmc_card_can_sleep(struct mmc_host *host);
-+
-+int mmc_host_enable(struct mmc_host *host);
-+int mmc_host_disable(struct mmc_host *host);
-+int mmc_host_lazy_disable(struct mmc_host *host);
-+
-+static inline void mmc_set_disable_delay(struct mmc_host *host,
-+                                       unsigned int disable_delay)
-+{
-+      host->disable_delay = disable_delay;
-+}
-+
- #endif
---- a/include/linux/mmc/mmc.h
-+++ b/include/linux/mmc/mmc.h
-@@ -31,6 +31,7 @@
- #define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
- #define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
- #define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
-+#define MMC_SLEEP_AWAKE                 5   /* ac   [31:16] RCA 15:flg R1b */
- #define MMC_SWITCH                6   /* ac   [31:0] See below   R1b */
- #define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
- #define MMC_SEND_EXT_CSD          8   /* adtc                    R1  */
-@@ -127,6 +128,7 @@
- #define R1_STATUS(x)            (x & 0xFFFFE000)
- #define R1_CURRENT_STATE(x)   ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
- #define R1_READY_FOR_DATA     (1 << 8)        /* sx, a */
-+#define R1_SWITCH_ERROR               (1 << 7)        /* sx, c */
- #define R1_APP_CMD            (1 << 5)        /* sr, c */
- /*
-@@ -254,6 +256,7 @@ struct _mmc_csd {
- #define EXT_CSD_CARD_TYPE     196     /* RO */
- #define EXT_CSD_REV           192     /* RO */
- #define EXT_CSD_SEC_CNT               212     /* RO, 4 bytes */
-+#define EXT_CSD_S_A_TIMEOUT   217
- /*
-  * EXT_CSD field definitions
---- a/include/linux/mmc/sdio_func.h
-+++ b/include/linux/mmc/sdio_func.h
-@@ -67,6 +67,7 @@ struct sdio_func {
- #define sdio_get_drvdata(f)   dev_get_drvdata(&(f)->dev)
- #define sdio_set_drvdata(f,d) dev_set_drvdata(&(f)->dev, d)
-+#define dev_to_sdio_func(d)   container_of(d, struct sdio_func, dev)
- /*
-  * SDIO function device driver
-@@ -81,6 +82,8 @@ struct sdio_driver {
-       struct device_driver drv;
- };
-+#define to_sdio_driver(d)     container_of(d, struct sdio_driver, drv)
-+
- /**
-  * SDIO_DEVICE - macro used to describe a specific SDIO device
-  * @vend: the 16 bit manufacturer code
---- a/include/linux/mmc/sdio_ids.h
-+++ b/include/linux/mmc/sdio_ids.h
-@@ -22,6 +22,12 @@
- /*
-  * Vendors and devices.  Sort key: vendor first, device next.
-  */
-+#define SDIO_VENDOR_ID_INTEL                  0x0089
-+#define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX    0x1402
-+#define SDIO_DEVICE_ID_INTEL_IWMC3200WIFI     0x1403
-+#define SDIO_DEVICE_ID_INTEL_IWMC3200TOP      0x1404
-+#define SDIO_DEVICE_ID_INTEL_IWMC3200GPS      0x1405
-+#define SDIO_DEVICE_ID_INTEL_IWMC3200BT               0x1406
- #define SDIO_VENDOR_ID_MARVELL                        0x02df
- #define SDIO_DEVICE_ID_MARVELL_LIBERTAS               0x9103