Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 5 Apr 2009 17:18:21 +0000 (10:18 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 5 Apr 2009 17:18:21 +0000 (10:18 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc: (42 commits)
  atmel-mci: fix sdc_reg typo
  tmio_mmc: add maintainer
  mmc: Add OpenFirmware bindings for SDHCI driver
  sdhci: Add quirk for forcing maximum block size to 2048 bytes
  sdhci: Add quirk for controllers that need IRQ re-init after reset
  sdhci: Add quirk for controllers that need small delays for PIO
  sdhci: Add set_clock callback and a quirk for nonstandard clocks
  sdhci: Add get_{max,timeout}_clock callbacks
  sdhci: Add support for hosts reporting inverted write-protect state
  sdhci: Add support for card-detection polling
  sdhci: Enable only relevant (DMA/PIO) interrupts during transfers
  sdhci: Split card-detection IRQs management from sdhci_init()
  sdhci: Add support for bus-specific IO memory accessors
  mmc_spi: adjust for delayed data token response
  omap_hsmmc: Wait for SDBP
  omap_hsmmc: Fix MMC3 dma
  omap_hsmmc: Disable SDBP at suspend
  omap_hsmmc: Do not prefix slot name
  omap_hsmmc: Allow cover switch to cause rescan
  omap_hsmmc: Add 8-bit bus width mode support
  ...

1  2 
MAINTAINERS
drivers/mmc/core/core.c
drivers/mmc/host/Kconfig
drivers/mmc/host/omap_hsmmc.c

diff --combined MAINTAINERS
@@@ -357,7 -357,6 +357,7 @@@ S: Odd Fixes for 2.4; Maintained for 2.
  P:    Ivan Kokshaysky
  M:    ink@jurassic.park.msu.ru
  S:    Maintained for 2.4; PCI support for 2.6.
 +L:    linux-alpha@vger.kernel.org
  
  AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER
  P:    Thomas Dahlmann
@@@ -503,13 -502,6 +503,13 @@@ P:       Richard Purdi
  M:    rpurdie@rpsys.net
  S:    Maintained
  
 +ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE
 +P:    Paulius Zaleckas
 +M:    paulius.zaleckas@teltonika.lt
 +L:    linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 +T:    git gitorious.org/linux-gemini/mainline.git
 +S:    Maintained
 +
  ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6)
  P:    Daniel Ribeiro
  M:    drwyrm@gmail.com
@@@ -521,12 -513,6 +521,12 @@@ L:       openezx-devel@lists.openezx.org (sub
  W:    http://www.openezx.org/
  S:    Maintained
  
 +ARM/FARADAY FA526 PORT
 +P:    Paulius Zaleckas
 +M:    paulius.zaleckas@teltonika.lt
 +L:    linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 +S:    Maintained
 +
  ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
  P:    Sascha Hauer
  M:    kernel@pengutronix.de
@@@ -636,7 -622,7 +636,7 @@@ P: Dirk Opfe
  M:    dirk@opfer-online.de
  S:    Maintained
  
 -ARM/PALMTX SUPPORT
 +ARM/PALMTX,PALMT5,PALMLD SUPPORT
  P:    Marek Vasut
  M:    marek.vasut@gmail.com
  W:    http://hackndev.com
@@@ -779,14 -765,6 +779,14 @@@ L:       linux-wireless@vger.kernel.or
  L:    ath9k-devel@lists.ath9k.org
  S:    Supported
  
 +ATHEROS AR9170 WIRELESS DRIVER
 +P:    Christian Lamparter
 +M:    chunkeey@web.de
 +L:    linux-wireless@vger.kernel.org
 +W:    http://wireless.kernel.org/en/users/Drivers/ar9170
 +S:    Maintained
 +F:    drivers/net/wireless/ar9170/
 +
  ATI_REMOTE2 DRIVER
  P:    Ville Syrjala
  M:    syrjala@sci.fi
@@@ -1033,8 -1011,6 +1033,8 @@@ L:      netdev@vger.kernel.or
  S:    Supported
  
  BROADCOM TG3 GIGABIT ETHERNET DRIVER
 +P:    Matt Carlson
 +M:    mcarlson@broadcom.com
  P:    Michael Chan
  M:    mchan@broadcom.com
  L:    netdev@vger.kernel.org
@@@ -1064,6 -1040,7 +1064,6 @@@ BTTV VIDEO4LINUX DRIVE
  P:    Mauro Carvalho Chehab
  M:    mchehab@infradead.org
  L:    linux-media@vger.kernel.org
 -L:    video4linux-list@redhat.com
  W:    http://linuxtv.org
  T:    git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
  S:    Maintained
@@@ -1292,12 -1269,6 +1292,12 @@@ L:    linux-crypto@vger.kernel.or
  T:    git kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6.git
  S:    Maintained
  
 +CRYPTOGRAPHIC RANDOM NUMBER GENERATOR
 +P:    Neil Horman
 +M:    nhorman@tuxdriver.com
 +L:    linux-crypto@vger.kernel.org
 +S:    Maintained
 +
  CS5535 Audio ALSA driver
  P:    Jaya Kumar
  M:    jayakumar.alsa@gmail.com
@@@ -1763,12 -1734,6 +1763,12 @@@ M:    viro@zeniv.linux.org.u
  L:    linux-fsdevel@vger.kernel.org
  S:    Maintained
  
 +FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
 +P:    Riku Voipio
 +M:    riku.vipio@iki.fi
 +L:    lm-sensors@lm-sensors.org
 +S:    Maintained
 +
  FIREWIRE SUBSYSTEM (drivers/firewire, <linux/firewire*.h>)
  P:    Kristian Hoegsberg, Stefan Richter
  M:    krh@redhat.com, stefanr@s5r6.in-berlin.de
@@@ -1951,12 -1916,6 +1951,12 @@@ L:    lm-sensors@lm-sensors.or
  W:    http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
  S:    Maintained
  
 +HYPERVISOR VIRTUAL CONSOLE DRIVER
 +L:    linuxppc-dev@ozlabs.org
 +L:    linux-kernel@vger.kernel.org
 +S:    Odd Fixes
 +F:    drivers/char/hvc_*
 +
  GSPCA FINEPIX SUBDRIVER
  P:    Frank Zago
  M:    frank@zago.net
@@@ -2214,12 -2173,25 +2214,12 @@@ L:   linux-ide@vger.kernel.or
  T:    quilt kernel.org/pub/linux/kernel/people/bart/pata-2.6/
  S:    Maintained
  
 -IDE/ATAPI CDROM DRIVER
 +IDE/ATAPI DRIVERS
  P:    Borislav Petkov
  M:    petkovbb@gmail.com
  L:    linux-ide@vger.kernel.org
  S:    Maintained
  
 -IDE/ATAPI FLOPPY DRIVERS
 -P:    Paul Bristow
 -M:    Paul Bristow <paul@paulbristow.net>
 -W:    http://paulbristow.net/linux/idefloppy.html
 -L:    linux-kernel@vger.kernel.org
 -S:    Maintained
 -
 -IDE/ATAPI TAPE DRIVERS
 -P:    Gadi Oxman
 -M:    Gadi Oxman <gadio@netvision.net.il>
 -L:    linux-kernel@vger.kernel.org
 -S:    Maintained
 -
  IDLE-I7300
  P:    Andy Henroid
  M:    andrew.d.henroid@intel.com
@@@ -2244,11 -2216,6 +2244,11 @@@ M:    stefanr@s5r6.in-berlin.d
  L:    linux1394-devel@lists.sourceforge.net
  S:    Maintained
  
 +INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
 +P:    Mimi Zohar
 +M:    zohar@us.ibm.com
 +S:    Supported
 +
  IMS TWINTURBO FRAMEBUFFER DRIVER
  L:    linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
  S:    Orphan
@@@ -2865,7 -2832,7 +2865,7 @@@ P:      Roman Zippe
  M:    zippel@linux-m68k.org
  L:    linux-m68k@lists.linux-m68k.org
  W:    http://www.linux-m68k.org/
 -W:    http://linux-m68k-cvs.ubb.ca/
 +T:    git git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git
  S:    Maintained
  
  M68K ON APPLE MACINTOSH
@@@ -2924,6 -2891,12 +2924,12 @@@ M:    buytenh@marvell.co
  L:    netdev@vger.kernel.org
  S:    Supported
  
+ MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
+ P:    Nicolas Pitre
+ M:    nico@cam.org
+ L:    linux-kernel@vger.kernel.org
+ S:    Maintained
  MARVELL YUKON / SYSKONNECT DRIVER
  P:    Mirko Lindner
  M:    mlindner@syskonnect.de
@@@ -3110,7 -3083,7 +3116,7 @@@ M:      shemminger@linux-foundation.or
  L:    netem@lists.linux-foundation.org
  S:    Maintained
  
 -NETERION (S2IO) Xframe 10GbE DRIVER
 +NETERION (S2IO) 10GbE DRIVER (xframe/vxge)
  P:    Ramkrishna Vepa
  M:    ram.vepa@neterion.com
  P:    Rastapur Santosh
@@@ -3119,11 -3092,8 +3125,11 @@@ P:    Sivakumar Subraman
  M:    sivakumar.subramani@neterion.com
  P:    Sreenivasa Honnur
  M:    sreenivasa.honnur@neterion.com
 +P:    Anil Murthy
 +M:    anil.murthy@neterion.com
  L:    netdev@vger.kernel.org
 -W:    http://trac.neterion.com/cgi-bin/trac.cgi/wiki/TitleIndex?anonymous
 +W:    http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous
 +W:    http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous
  S:    Supported
  
  NETFILTER/IPTABLES/IPCHAINS
@@@ -3325,16 -3295,6 +3331,16 @@@ L:    orinoco-devel@lists.sourceforge.ne
  W:    http://www.nongnu.org/orinoco/
  S:    Maintained
  
 +OSD LIBRARY
 +P:    Boaz Harrosh
 +M:    bharrosh@panasas.com
 +P:    Benny Halevy
 +M:    bhalevy@panasas.com
 +L:    osd-dev@open-osd.org
 +W:    http://open-osd.org
 +T:    git://git.open-osd.org/open-osd.git
 +S:    Maintained
 +
  P54 WIRELESS DRIVER
  P:    Michael Wu
  M:    flamingice@sourmilk.net
@@@ -3414,11 -3374,6 +3420,11 @@@ P:    Jim Cromi
  M:    jim.cromie@gmail.com
  S:    Maintained
  
 +PCA9532 LED DRIVER
 +P:    Riku Voipio
 +M:    riku.voipio@iki.fi
 +S:    Maintained
 +
  PCI ERROR RECOVERY
  P:    Linas Vepstas
  M:    linas@austin.ibm.com
@@@ -3590,22 -3545,6 +3596,22 @@@ M:    linux@arm.linux.org.u
  L:    linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
  S:    Maintained
  
 +PXA168 SUPPORT
 +P:    Eric Miao
 +M:    eric.miao@marvell.com
 +P:    Jason Chagas
 +M:    jason.chagas@marvell.com
 +L:    linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 +T:    git kernel.org:/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git
 +S:    Supported
 +
 +PXA910 SUPPORT
 +P:    Eric Miao
 +M:    eric.miao@marvell.com
 +L:    linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 +T:    git kernel.org:/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git
 +S:    Supported
 +
  PXA MMCI DRIVER
  S:    Orphan
  
@@@ -3656,7 -3595,7 +3662,7 @@@ S:      Maintaine
  RALINK RT2X00 WIRELESS LAN DRIVER
  P:    rt2x00 project
  L:    linux-wireless@vger.kernel.org
 -L:    rt2400-devel@lists.sourceforge.net
 +L:    users@rt2x00.serialmonkey.com
  W:    http://rt2x00.serialmonkey.com/
  S:    Maintained
  T:    git kernel.org:/pub/scm/linux/kernel/git/ivd/rt2x00.git
@@@ -3702,12 -3641,6 +3708,12 @@@ M:    florian.fainelli@telecomint.e
  L:    netdev@vger.kernel.org
  S:    Maintained
  
 +RDS - RELIABLE DATAGRAM SOCKETS
 +P:    Andy Grover
 +M:    andy.grover@oracle.com
 +L:    rds-devel@oss.oracle.com
 +S:    Supported
 +
  READ-COPY UPDATE (RCU)
  P:    Dipankar Sarma
  M:    dipankar@in.ibm.com
@@@ -3799,15 -3732,6 +3805,15 @@@ L:    linux-s390@vger.kernel.or
  W:    http://www.ibm.com/developerworks/linux/linux390/
  S:    Supported
  
 +S390 ZCRYPT DRIVER
 +P:    Felix Beck
 +M:    felix.beck@de.ibm.com
 +P:    Ralph Wuerthner
 +M:    ralph.wuerthner@de.ibm.com
 +M:    linux390@de.ibm.com
 +L:    linux-s390@vger.kernel.org
 +S:    Supported
 +
  S390 ZFCP DRIVER
  P:    Christof Schmitt
  M:    christof.schmitt@de.ibm.com
@@@ -3916,7 -3840,14 +3922,14 @@@ S:    Maintaine
  SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
  P:    Pierre Ossman
  M:    drzeus-sdhci@drzeus.cx
- L:    sdhci-devel@list.drzeus.cx
+ L:    sdhci-devel@lists.ossman.eu
+ S:    Maintained
+ SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
+ P:    Anton Vorontsov
+ M:    avorontsov@ru.mvista.com
+ L:    linuxppc-dev@ozlabs.org
+ L:    sdhci-devel@lists.ossman.eu
  S:    Maintained
  
  SECURITY SUBSYSTEM
@@@ -3926,7 -3857,6 +3939,7 @@@ M:      jmorris@namei.or
  L:    linux-kernel@vger.kernel.org
  L:    linux-security-module@vger.kernel.org (suggested Cc:)
  T:    git kernel.org:pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git
 +W:    http://security.wiki.kernel.org/
  S:    Supported
  
  SECURITY CONTACT
@@@ -4368,19 -4298,6 +4381,19 @@@ L:    tlan-devel@lists.sourceforge.net (su
  W:    http://sourceforge.net/projects/tlan/
  S:    Maintained
  
 +TOMOYO SECURITY MODULE
 +P:    Kentaro Takeda
 +M:    takedakn@nttdata.co.jp
 +P:    Tetsuo Handa
 +M:    penguin-kernel@I-love.SAKURA.ne.jp
 +L:    linux-kernel@vger.kernel.org (kernel issues)
 +L:    tomoyo-users-en@lists.sourceforge.jp (subscribers-only, for developers and users in English)
 +L:    tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese)
 +L:    tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese)
 +W:    http://tomoyo.sourceforge.jp/
 +T:    quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.2.x/tomoyo-lsm/patches/
 +S:    Maintained
 +
  TOSHIBA ACPI EXTRAS DRIVER
  P:    John Belmonte
  M:    toshiba_acpi@memebeam.org
@@@ -4394,6 -4311,11 +4407,11 @@@ L:    tlinux-users@tce.toshiba-dme.co.j
  W:    http://www.buzzard.org.uk/toshiba/
  S:    Maintained
  
+ TMIO MMC DRIVER
+ P:    Ian Molton
+ M:    ian@mnementh.co.uk
+ S:    Maintained
  TPM DEVICE DRIVER
  P:    Debora Velarde
  M:    debora@linux.vnet.ibm.com
@@@ -4842,6 -4764,7 +4860,6 @@@ VIDEO FOR LINUX (V4L
  P:    Mauro Carvalho Chehab
  M:    mchehab@infradead.org
  L:    linux-media@vger.kernel.org
 -L:    video4linux-list@redhat.com
  W:    http://linuxtv.org
  T:    git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
  S:    Maintained
@@@ -4858,7 -4781,7 +4876,7 @@@ M:      lrg@slimlogic.co.u
  P:    Mark Brown
  M:    broonie@opensource.wolfsonmicro.com
  W:    http://opensource.wolfsonmicro.com/node/15
 -W:    http://www.slimlogic.co.uk/?page_id=5
 +W:    http://www.slimlogic.co.uk/?p=48
  T:    git kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6.git
  S:    Supported
  
@@@ -4980,8 -4903,7 +4998,8 @@@ S:      Supporte
  
  XFS FILESYSTEM
  P:    Silicon Graphics Inc
 -P:    Bill O'Donnell
 +P:    Felix Blyakher
 +M:    felixb@sgi.com
  M:    xfs-masters@oss.sgi.com
  L:    xfs@oss.sgi.com
  W:    http://oss.sgi.com/projects/xfs
diff --combined drivers/mmc/core/core.c
@@@ -21,7 -21,6 +21,7 @@@
  #include <linux/leds.h>
  #include <linux/scatterlist.h>
  #include <linux/log2.h>
 +#include <linux/regulator/consumer.h>
  
  #include <linux/mmc/card.h>
  #include <linux/mmc/host.h>
@@@ -298,6 -297,21 +298,21 @@@ void mmc_set_data_timeout(struct mmc_da
                        data->timeout_clks = 0;
                }
        }
+       /*
+        * Some cards need very high timeouts if driven in SPI mode.
+        * The worst observed timeout was 900ms after writing a
+        * continuous stream of data until the internal logic
+        * overflowed.
+        */
+       if (mmc_host_is_spi(card->host)) {
+               if (data->flags & MMC_DATA_WRITE) {
+                       if (data->timeout_ns < 1000000000)
+                               data->timeout_ns = 1000000000;  /* 1s */
+               } else {
+                       if (data->timeout_ns < 100000000)
+                               data->timeout_ns =  100000000;  /* 100ms */
+               }
+       }
  }
  EXPORT_SYMBOL(mmc_set_data_timeout);
  
@@@ -524,105 -538,6 +539,105 @@@ u32 mmc_vddrange_to_ocrmask(int vdd_min
  }
  EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
  
 +#ifdef CONFIG_REGULATOR
 +
 +/**
 + * mmc_regulator_get_ocrmask - return mask of supported voltages
 + * @supply: regulator to use
 + *
 + * This returns either a negative errno, or a mask of voltages that
 + * can be provided to MMC/SD/SDIO devices using the specified voltage
 + * regulator.  This would normally be called before registering the
 + * MMC host adapter.
 + */
 +int mmc_regulator_get_ocrmask(struct regulator *supply)
 +{
 +      int                     result = 0;
 +      int                     count;
 +      int                     i;
 +
 +      count = regulator_count_voltages(supply);
 +      if (count < 0)
 +              return count;
 +
 +      for (i = 0; i < count; i++) {
 +              int             vdd_uV;
 +              int             vdd_mV;
 +
 +              vdd_uV = regulator_list_voltage(supply, i);
 +              if (vdd_uV <= 0)
 +                      continue;
 +
 +              vdd_mV = vdd_uV / 1000;
 +              result |= mmc_vddrange_to_ocrmask(vdd_mV, vdd_mV);
 +      }
 +
 +      return result;
 +}
 +EXPORT_SYMBOL(mmc_regulator_get_ocrmask);
 +
 +/**
 + * mmc_regulator_set_ocr - set regulator to match host->ios voltage
 + * @vdd_bit: zero for power off, else a bit number (host->ios.vdd)
 + * @supply: regulator to use
 + *
 + * Returns zero on success, else negative errno.
 + *
 + * MMC host drivers may use this to enable or disable a regulator using
 + * a particular supply voltage.  This would normally be called from the
 + * set_ios() method.
 + */
 +int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit)
 +{
 +      int                     result = 0;
 +      int                     min_uV, max_uV;
 +      int                     enabled;
 +
 +      enabled = regulator_is_enabled(supply);
 +      if (enabled < 0)
 +              return enabled;
 +
 +      if (vdd_bit) {
 +              int             tmp;
 +              int             voltage;
 +
 +              /* REVISIT mmc_vddrange_to_ocrmask() may have set some
 +               * bits this regulator doesn't quite support ... don't
 +               * be too picky, most cards and regulators are OK with
 +               * a 0.1V range goof (it's a small error percentage).
 +               */
 +              tmp = vdd_bit - ilog2(MMC_VDD_165_195);
 +              if (tmp == 0) {
 +                      min_uV = 1650 * 1000;
 +                      max_uV = 1950 * 1000;
 +              } else {
 +                      min_uV = 1900 * 1000 + tmp * 100 * 1000;
 +                      max_uV = min_uV + 100 * 1000;
 +              }
 +
 +              /* avoid needless changes to this voltage; the regulator
 +               * might not allow this operation
 +               */
 +              voltage = regulator_get_voltage(supply);
 +              if (voltage < 0)
 +                      result = voltage;
 +              else if (voltage < min_uV || voltage > max_uV)
 +                      result = regulator_set_voltage(supply, min_uV, max_uV);
 +              else
 +                      result = 0;
 +
 +              if (result == 0 && !enabled)
 +                      result = regulator_enable(supply);
 +      } else if (enabled) {
 +              result = regulator_disable(supply);
 +      }
 +
 +      return result;
 +}
 +EXPORT_SYMBOL(mmc_regulator_set_ocr);
 +
 +#endif
 +
  /*
   * Mask off any voltages we don't support and select
   * the lowest voltage
@@@ -915,6 -830,7 +930,7 @@@ void mmc_stop_host(struct mmc_host *hos
        spin_unlock_irqrestore(&host->lock, flags);
  #endif
  
+       cancel_delayed_work(&host->detect);
        mmc_flush_scheduled_work();
  
        mmc_bus_get(host);
   */
  int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
  {
+       cancel_delayed_work(&host->detect);
        mmc_flush_scheduled_work();
  
        mmc_bus_get(host);
@@@ -975,6 -892,7 +992,7 @@@ int mmc_resume_host(struct mmc_host *ho
        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);
        }
diff --combined drivers/mmc/host/Kconfig
@@@ -37,6 -37,13 +37,13 @@@ config MMC_SDHC
  
          If unsure, say N.
  
+ config MMC_SDHCI_IO_ACCESSORS
+       bool
+       depends on MMC_SDHCI
+       help
+         This is silent Kconfig symbol that is selected by the drivers that
+         need to overwrite SDHCI IO memory accessors.
  config MMC_SDHCI_PCI
        tristate "SDHCI support on PCI bus"
        depends on MMC_SDHCI && PCI
@@@ -65,6 -72,17 +72,17 @@@ config MMC_RICOH_MM
  
          If unsure, say Y.
  
+ config MMC_SDHCI_OF
+       tristate "SDHCI support on OpenFirmware platforms"
+       depends on MMC_SDHCI && PPC_OF
+       select MMC_SDHCI_IO_ACCESSORS
+       help
+         This selects the OF support for Secure Digital Host Controller
+         Interfaces. So far, only the Freescale eSDHC controller is known
+         to exist on OF platforms.
+         If unsure, say N.
  config MMC_OMAP
        tristate "TI OMAP Multimedia Card Interface support"
        depends on ARCH_OMAP
@@@ -171,13 -189,24 +189,24 @@@ config MMC_TIFM_S
            To compile this driver as a module, choose M here: the
          module will be called tifm_sd.
  
+ config MMC_MVSDIO
+       tristate "Marvell MMC/SD/SDIO host driver"
+       depends on PLAT_ORION
+       ---help---
+         This selects the Marvell SDIO host driver.
+         SDIO may currently be found on the Kirkwood 88F6281 and 88F6192
+         SoC controllers.
+         To compile this driver as a module, choose M here: the
+         module will be called mvsdio.
  config MMC_SPI
        tristate "MMC/SD/SDIO over SPI"
        depends on SPI_MASTER && !HIGHMEM && HAS_DMA
        select CRC7
        select CRC_ITU_T
        help
 -        Some systems accss MMC/SD/SDIO cards using a SPI controller
 +        Some systems access MMC/SD/SDIO cards using a SPI controller
          instead of using a "native" MMC/SD/SDIO controller.  This has a
          disadvantage of being relatively high overhead, but a compensating
          advantage of working on many systems without dedicated MMC/SD/SDIO
@@@ -56,6 -56,7 +56,7 @@@
  #define SDVS18                        (0x5 << 9)
  #define SDVS30                        (0x6 << 9)
  #define SDVS33                        (0x7 << 9)
+ #define SDVS_MASK             0x00000E00
  #define SDVSCLR                       0xFFFFF1FF
  #define SDVSDET                       0x00000400
  #define AUTOIDLE              0x1
@@@ -76,6 -77,7 +77,7 @@@
  #define MSBS                  (1 << 5)
  #define BCE                   (1 << 1)
  #define FOUR_BIT              (1 << 1)
+ #define DW8                   (1 << 5)
  #define CC                    0x1
  #define TC                    0x02
  #define OD                    0x1
   */
  #define OMAP_MMC1_DEVID               0
  #define OMAP_MMC2_DEVID               1
+ #define OMAP_MMC3_DEVID               2
  
- #define OMAP_MMC_DATADIR_NONE 0
- #define OMAP_MMC_DATADIR_READ 1
- #define OMAP_MMC_DATADIR_WRITE        2
  #define MMC_TIMEOUT_MS                20
  #define OMAP_MMC_MASTER_CLOCK 96000000
  #define DRIVER_NAME           "mmci-omap-hs"
@@@ -137,18 -137,18 +137,18 @@@ struct mmc_omap_host 
        resource_size_t         mapbase;
        unsigned int            id;
        unsigned int            dma_len;
-       unsigned int            dma_dir;
+       unsigned int            dma_sg_idx;
        unsigned char           bus_mode;
-       unsigned char           datadir;
        u32                     *buffer;
        u32                     bytesleft;
        int                     suspended;
        int                     irq;
        int                     carddetect;
        int                     use_dma, dma_ch;
-       int                     initstr;
+       int                     dma_line_tx, dma_line_rx;
        int                     slot_id;
        int                     dbclk_enabled;
+       int                     response_busy;
        struct  omap_mmc_platform_data  *pdata;
  };
  
@@@ -218,7 -218,7 +218,7 @@@ mmc_omap_show_slot_name(struct device *
        struct mmc_omap_host *host = mmc_priv(mmc);
        struct omap_mmc_slot_data slot = host->pdata->slots[host->slot_id];
  
-       return sprintf(buf, "slot:%s\n", slot.name);
+       return sprintf(buf, "%s\n", slot.name);
  }
  
  static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL);
@@@ -243,10 -243,14 +243,14 @@@ mmc_omap_start_command(struct mmc_omap_
        OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
        OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
  
+       host->response_busy = 0;
        if (cmd->flags & MMC_RSP_PRESENT) {
                if (cmd->flags & MMC_RSP_136)
                        resptype = 1;
-               else
+               else if (cmd->flags & MMC_RSP_BUSY) {
+                       resptype = 3;
+                       host->response_busy = 1;
+               } else
                        resptype = 2;
        }
  
        OMAP_HSMMC_WRITE(host->base, CMD, cmdreg);
  }
  
+ static int
+ mmc_omap_get_dma_dir(struct mmc_omap_host *host, struct mmc_data *data)
+ {
+       if (data->flags & MMC_DATA_WRITE)
+               return DMA_TO_DEVICE;
+       else
+               return DMA_FROM_DEVICE;
+ }
  /*
   * Notify the transfer complete to MMC core
   */
  static void
  mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
  {
+       if (!data) {
+               struct mmc_request *mrq = host->mrq;
+               host->mrq = NULL;
+               mmc_omap_fclk_lazy_disable(host);
+               mmc_request_done(host->mmc, mrq);
+               return;
+       }
        host->data = NULL;
  
        if (host->use_dma && host->dma_ch != -1)
                dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
-                       host->dma_dir);
-       host->datadir = OMAP_MMC_DATADIR_NONE;
+                       mmc_omap_get_dma_dir(host, data));
  
        if (!data->error)
                data->bytes_xfered += data->blocks * (data->blksz);
@@@ -322,7 -342,7 +342,7 @@@ mmc_omap_cmd_done(struct mmc_omap_host 
                        cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10);
                }
        }
-       if (host->data == NULL || cmd->error) {
+       if ((host->data == NULL && !host->response_busy) || cmd->error) {
                host->mrq = NULL;
                mmc_request_done(host->mmc, cmd->mrq);
        }
  /*
   * DMA clean up for command errors
   */
- static void mmc_dma_cleanup(struct mmc_omap_host *host)
+ static void mmc_dma_cleanup(struct mmc_omap_host *host, int errno)
  {
-       host->data->error = -ETIMEDOUT;
+       host->data->error = errno;
  
        if (host->use_dma && host->dma_ch != -1) {
                dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len,
-                       host->dma_dir);
+                       mmc_omap_get_dma_dir(host, host->data));
                omap_free_dma(host->dma_ch);
                host->dma_ch = -1;
                up(&host->sem);
        }
        host->data = NULL;
-       host->datadir = OMAP_MMC_DATADIR_NONE;
  }
  
  /*
@@@ -412,7 -431,7 +431,7 @@@ static irqreturn_t mmc_omap_irq(int irq
        struct mmc_data *data;
        int end_cmd = 0, end_trans = 0, status;
  
-       if (host->cmd == NULL && host->data == NULL) {
+       if (host->mrq == NULL) {
                OMAP_HSMMC_WRITE(host->base, STAT,
                        OMAP_HSMMC_READ(host->base, STAT));
                return IRQ_HANDLED;
                                }
                                end_cmd = 1;
                        }
-                       if (host->data) {
-                               mmc_dma_cleanup(host);
+                       if (host->data || host->response_busy) {
+                               if (host->data)
+                                       mmc_dma_cleanup(host, -ETIMEDOUT);
+                               host->response_busy = 0;
                                mmc_omap_reset_controller_fsm(host, SRD);
                        }
                }
                if ((status & DATA_TIMEOUT) ||
                        (status & DATA_CRC)) {
-                       if (host->data) {
-                               if (status & DATA_TIMEOUT)
-                                       mmc_dma_cleanup(host);
+                       if (host->data || host->response_busy) {
+                               int err = (status & DATA_TIMEOUT) ?
+                                               -ETIMEDOUT : -EILSEQ;
+                               if (host->data)
+                                       mmc_dma_cleanup(host, err);
                                else
-                                       host->data->error = -EILSEQ;
+                                       host->mrq->cmd->error = err;
+                               host->response_busy = 0;
                                mmc_omap_reset_controller_fsm(host, SRD);
                                end_trans = 1;
                        }
        return IRQ_HANDLED;
  }
  
+ static void set_sd_bus_power(struct mmc_omap_host *host)
+ {
+       unsigned long i;
+       OMAP_HSMMC_WRITE(host->base, HCTL,
+                        OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
+       for (i = 0; i < loops_per_jiffy; i++) {
+               if (OMAP_HSMMC_READ(host->base, HCTL) & SDBP)
+                       break;
+               cpu_relax();
+       }
+ }
  /*
   * Switch MMC interface voltage ... only relevant for MMC1.
   *
@@@ -485,9 -523,6 +523,6 @@@ static int omap_mmc_switch_opcond(struc
        u32 reg_val = 0;
        int ret;
  
-       if (host->id != OMAP_MMC1_DEVID)
-               return 0;
        /* Disable the clocks */
        clk_disable(host->fclk);
        clk_disable(host->iclk);
                reg_val |= SDVS30;
  
        OMAP_HSMMC_WRITE(host->base, HCTL, reg_val);
-       OMAP_HSMMC_WRITE(host->base, HCTL,
-               OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
+       set_sd_bus_power(host);
  
        return 0;
  err:
@@@ -551,7 -584,10 +584,10 @@@ static void mmc_omap_detect(struct work
                                                mmc_carddetect_work);
        struct omap_mmc_slot_data *slot = &mmc_slot(host);
  
-       host->carddetect = slot->card_detect(slot->card_detect_irq);
+       if (mmc_slot(host).card_detect)
+               host->carddetect = slot->card_detect(slot->card_detect_irq);
+       else
+               host->carddetect = -ENOSYS;
  
        sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
        if (host->carddetect) {
@@@ -574,6 -610,48 +610,48 @@@ static irqreturn_t omap_mmc_cd_handler(
        return IRQ_HANDLED;
  }
  
+ static int mmc_omap_get_dma_sync_dev(struct mmc_omap_host *host,
+                                    struct mmc_data *data)
+ {
+       int sync_dev;
+       if (data->flags & MMC_DATA_WRITE)
+               sync_dev = host->dma_line_tx;
+       else
+               sync_dev = host->dma_line_rx;
+       return sync_dev;
+ }
+ static void mmc_omap_config_dma_params(struct mmc_omap_host *host,
+                                      struct mmc_data *data,
+                                      struct scatterlist *sgl)
+ {
+       int blksz, nblk, dma_ch;
+       dma_ch = host->dma_ch;
+       if (data->flags & MMC_DATA_WRITE) {
+               omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT,
+                       (host->mapbase + OMAP_HSMMC_DATA), 0, 0);
+               omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
+                       sg_dma_address(sgl), 0, 0);
+       } else {
+               omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT,
+                                       (host->mapbase + OMAP_HSMMC_DATA), 0, 0);
+               omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
+                       sg_dma_address(sgl), 0, 0);
+       }
+       blksz = host->data->blksz;
+       nblk = sg_dma_len(sgl) / blksz;
+       omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32,
+                       blksz / 4, nblk, OMAP_DMA_SYNC_FRAME,
+                       mmc_omap_get_dma_sync_dev(host, data),
+                       !(data->flags & MMC_DATA_WRITE));
+       omap_start_dma(dma_ch);
+ }
  /*
   * DMA call back function
   */
@@@ -587,6 -665,14 +665,14 @@@ static void mmc_omap_dma_cb(int lch, u1
        if (host->dma_ch < 0)
                return;
  
+       host->dma_sg_idx++;
+       if (host->dma_sg_idx < host->dma_len) {
+               /* Fire up the next transfer. */
+               mmc_omap_config_dma_params(host, host->data,
+                                          host->data->sg + host->dma_sg_idx);
+               return;
+       }
        omap_free_dma(host->dma_ch);
        host->dma_ch = -1;
        /*
        up(&host->sem);
  }
  
- /*
-  * Configure dma src and destination parameters
-  */
- static int mmc_omap_config_dma_param(int sync_dir, struct mmc_omap_host *host,
-                               struct mmc_data *data)
- {
-       if (sync_dir == 0) {
-               omap_set_dma_dest_params(host->dma_ch, 0,
-                       OMAP_DMA_AMODE_CONSTANT,
-                       (host->mapbase + OMAP_HSMMC_DATA), 0, 0);
-               omap_set_dma_src_params(host->dma_ch, 0,
-                       OMAP_DMA_AMODE_POST_INC,
-                       sg_dma_address(&data->sg[0]), 0, 0);
-       } else {
-               omap_set_dma_src_params(host->dma_ch, 0,
-                       OMAP_DMA_AMODE_CONSTANT,
-                       (host->mapbase + OMAP_HSMMC_DATA), 0, 0);
-               omap_set_dma_dest_params(host->dma_ch, 0,
-                       OMAP_DMA_AMODE_POST_INC,
-                       sg_dma_address(&data->sg[0]), 0, 0);
-       }
-       return 0;
- }
  /*
   * Routine to configure and start DMA for the MMC card
   */
  static int
  mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req)
  {
-       int sync_dev, sync_dir = 0;
-       int dma_ch = 0, ret = 0, err = 1;
+       int dma_ch = 0, ret = 0, err = 1, i;
        struct mmc_data *data = req->data;
  
+       /* Sanity check: all the SG entries must be aligned by block size. */
+       for (i = 0; i < host->dma_len; i++) {
+               struct scatterlist *sgl;
+               sgl = data->sg + i;
+               if (sgl->length % data->blksz)
+                       return -EINVAL;
+       }
+       if ((data->blksz % 4) != 0)
+               /* REVISIT: The MMC buffer increments only when MSB is written.
+                * Return error for blksz which is non multiple of four.
+                */
+               return -EINVAL;
        /*
         * If for some reason the DMA transfer is still active,
         * we wait for timeout period and free the dma
                        return err;
        }
  
-       if (!(data->flags & MMC_DATA_WRITE)) {
-               host->dma_dir = DMA_FROM_DEVICE;
-               if (host->id == OMAP_MMC1_DEVID)
-                       sync_dev = OMAP24XX_DMA_MMC1_RX;
-               else
-                       sync_dev = OMAP24XX_DMA_MMC2_RX;
-       } else {
-               host->dma_dir = DMA_TO_DEVICE;
-               if (host->id == OMAP_MMC1_DEVID)
-                       sync_dev = OMAP24XX_DMA_MMC1_TX;
-               else
-                       sync_dev = OMAP24XX_DMA_MMC2_TX;
-       }
-       ret = omap_request_dma(sync_dev, "MMC/SD", mmc_omap_dma_cb,
-                       host, &dma_ch);
+       ret = omap_request_dma(mmc_omap_get_dma_sync_dev(host, data), "MMC/SD",
+                              mmc_omap_dma_cb,host, &dma_ch);
        if (ret != 0) {
-               dev_dbg(mmc_dev(host->mmc),
+               dev_err(mmc_dev(host->mmc),
                        "%s: omap_request_dma() failed with %d\n",
                        mmc_hostname(host->mmc), ret);
                return ret;
        }
  
        host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
-                       data->sg_len, host->dma_dir);
+                       data->sg_len, mmc_omap_get_dma_dir(host, data));
        host->dma_ch = dma_ch;
+       host->dma_sg_idx = 0;
  
-       if (!(data->flags & MMC_DATA_WRITE))
-               mmc_omap_config_dma_param(1, host, data);
-       else
-               mmc_omap_config_dma_param(0, host, data);
-       if ((data->blksz % 4) == 0)
-               omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32,
-                       (data->blksz / 4), data->blocks, OMAP_DMA_SYNC_FRAME,
-                       sync_dev, sync_dir);
-       else
-               /* REVISIT: The MMC buffer increments only when MSB is written.
-                * Return error for blksz which is non multiple of four.
-                */
-               return -EINVAL;
+       mmc_omap_config_dma_params(host, data, data->sg);
  
-       omap_start_dma(dma_ch);
        return 0;
  }
  
@@@ -739,7 -788,6 +788,6 @@@ mmc_omap_prepare_data(struct mmc_omap_h
        host->data = req->data;
  
        if (req->data == NULL) {
-               host->datadir = OMAP_MMC_DATADIR_NONE;
                OMAP_HSMMC_WRITE(host->base, BLK, 0);
                return 0;
        }
                                        | (req->data->blocks << 16));
        set_data_timeout(host, req);
  
-       host->datadir = (req->data->flags & MMC_DATA_WRITE) ?
-                       OMAP_MMC_DATADIR_WRITE : OMAP_MMC_DATADIR_READ;
        if (host->use_dma) {
                ret = mmc_omap_start_dma_transfer(host, req);
                if (ret != 0) {
@@@ -782,36 -827,29 +827,29 @@@ static void omap_mmc_set_ios(struct mmc
        u16 dsor = 0;
        unsigned long regval;
        unsigned long timeout;
+       u32 con;
  
        switch (ios->power_mode) {
        case MMC_POWER_OFF:
                mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
-               /*
-                * Reset interface voltage to 3V if it's 1.8V now;
-                * only relevant on MMC-1, the others always use 1.8V.
-                *
-                * REVISIT: If we are able to detect cards after unplugging
-                * a 1.8V card, this code should not be needed.
-                */
-               if (host->id != OMAP_MMC1_DEVID)
-                       break;
-               if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
-                       int vdd = fls(host->mmc->ocr_avail) - 1;
-                       if (omap_mmc_switch_opcond(host, vdd) != 0)
-                               host->mmc->ios.vdd = vdd;
-               }
                break;
        case MMC_POWER_UP:
                mmc_slot(host).set_power(host->dev, host->slot_id, 1, ios->vdd);
                break;
        }
  
+       con = OMAP_HSMMC_READ(host->base, CON);
        switch (mmc->ios.bus_width) {
+       case MMC_BUS_WIDTH_8:
+               OMAP_HSMMC_WRITE(host->base, CON, con | DW8);
+               break;
        case MMC_BUS_WIDTH_4:
+               OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
                OMAP_HSMMC_WRITE(host->base, HCTL,
                        OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
                break;
        case MMC_BUS_WIDTH_1:
+               OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8);
                OMAP_HSMMC_WRITE(host->base, HCTL,
                        OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
                break;
@@@ -891,6 -929,33 +929,33 @@@ static int omap_hsmmc_get_ro(struct mmc
        return pdata->slots[0].get_ro(host->dev, 0);
  }
  
+ static void omap_hsmmc_init(struct mmc_omap_host *host)
+ {
+       u32 hctl, capa, value;
+       /* Only MMC1 supports 3.0V */
+       if (host->id == OMAP_MMC1_DEVID) {
+               hctl = SDVS30;
+               capa = VS30 | VS18;
+       } else {
+               hctl = SDVS18;
+               capa = VS18;
+       }
+       value = OMAP_HSMMC_READ(host->base, HCTL) & ~SDVS_MASK;
+       OMAP_HSMMC_WRITE(host->base, HCTL, value | hctl);
+       value = OMAP_HSMMC_READ(host->base, CAPA);
+       OMAP_HSMMC_WRITE(host->base, CAPA, value | capa);
+       /* Set the controller to AUTO IDLE mode */
+       value = OMAP_HSMMC_READ(host->base, SYSCONFIG);
+       OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE);
+       /* Set SD bus power bit */
+       set_sd_bus_power(host);
+ }
  static struct mmc_host_ops mmc_omap_ops = {
        .request = omap_mmc_request,
        .set_ios = omap_mmc_set_ios,
@@@ -906,7 -971,6 +971,6 @@@ static int __init omap_mmc_probe(struc
        struct mmc_omap_host *host = NULL;
        struct resource *res;
        int ret = 0, irq;
-       u32 hctl, capa;
  
        if (pdata == NULL) {
                dev_err(&pdev->dev, "Platform Data is missing\n");
  
        sema_init(&host->sem, 1);
  
 -      host->iclk = clk_get(&pdev->dev, "mmchs_ick");
 +      host->iclk = clk_get(&pdev->dev, "ick");
        if (IS_ERR(host->iclk)) {
                ret = PTR_ERR(host->iclk);
                host->iclk = NULL;
                goto err1;
        }
 -      host->fclk = clk_get(&pdev->dev, "mmchs_fck");
 +      host->fclk = clk_get(&pdev->dev, "fck");
        if (IS_ERR(host->fclk)) {
                ret = PTR_ERR(host->fclk);
                host->fclk = NULL;
                else
                        host->dbclk_enabled = 1;
  
- #ifdef CONFIG_MMC_BLOCK_BOUNCE
-       mmc->max_phys_segs = 1;
-       mmc->max_hw_segs = 1;
- #endif
+       /* Since we do only SG emulation, we can have as many segs
+        * as we want. */
+       mmc->max_phys_segs = 1024;
+       mmc->max_hw_segs = 1024;
        mmc->max_blk_size = 512;       /* Block Length at max can be 1024 */
        mmc->max_blk_count = 0xFFFF;    /* No. of Blocks is 16 bits */
        mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
        mmc->ocr_avail = mmc_slot(host).ocr_mask;
        mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
  
-       if (pdata->slots[host->slot_id].wires >= 4)
+       if (pdata->slots[host->slot_id].wires >= 8)
+               mmc->caps |= MMC_CAP_8_BIT_DATA;
+       else if (pdata->slots[host->slot_id].wires >= 4)
                mmc->caps |= MMC_CAP_4_BIT_DATA;
  
-       /* Only MMC1 supports 3.0V */
-       if (host->id == OMAP_MMC1_DEVID) {
-               hctl = SDVS30;
-               capa = VS30 | VS18;
-       } else {
-               hctl = SDVS18;
-               capa = VS18;
-       }
-       OMAP_HSMMC_WRITE(host->base, HCTL,
-                       OMAP_HSMMC_READ(host->base, HCTL) | hctl);
-       OMAP_HSMMC_WRITE(host->base, CAPA,
-                       OMAP_HSMMC_READ(host->base, CAPA) | capa);
-       /* Set the controller to AUTO IDLE mode */
-       OMAP_HSMMC_WRITE(host->base, SYSCONFIG,
-                       OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE);
+       omap_hsmmc_init(host);
  
-       /* Set SD bus power bit */
-       OMAP_HSMMC_WRITE(host->base, HCTL,
-                       OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
+       /* Select DMA lines */
+       switch (host->id) {
+       case OMAP_MMC1_DEVID:
+               host->dma_line_tx = OMAP24XX_DMA_MMC1_TX;
+               host->dma_line_rx = OMAP24XX_DMA_MMC1_RX;
+               break;
+       case OMAP_MMC2_DEVID:
+               host->dma_line_tx = OMAP24XX_DMA_MMC2_TX;
+               host->dma_line_rx = OMAP24XX_DMA_MMC2_RX;
+               break;
+       case OMAP_MMC3_DEVID:
+               host->dma_line_tx = OMAP34XX_DMA_MMC3_TX;
+               host->dma_line_rx = OMAP34XX_DMA_MMC3_RX;
+               break;
+       default:
+               dev_err(mmc_dev(host->mmc), "Invalid MMC id\n");
+               goto err_irq;
+       }
  
        /* Request IRQ for MMC operations */
        ret = request_irq(host->irq, mmc_omap_irq, IRQF_DISABLED,
        }
  
        /* Request IRQ for card detect */
-       if ((mmc_slot(host).card_detect_irq) && (mmc_slot(host).card_detect)) {
+       if ((mmc_slot(host).card_detect_irq)) {
                ret = request_irq(mmc_slot(host).card_detect_irq,
                                  omap_mmc_cd_handler,
                                  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
                if (ret < 0)
                        goto err_slot_name;
        }
-       if (mmc_slot(host).card_detect_irq && mmc_slot(host).card_detect &&
-                       host->pdata->slots[host->slot_id].get_cover_state) {
+       if (mmc_slot(host).card_detect_irq &&
+           host->pdata->slots[host->slot_id].get_cover_state) {
                ret = device_create_file(&mmc->class_dev,
                                        &dev_attr_cover_switch);
                if (ret < 0)
@@@ -1173,20 -1238,8 +1238,8 @@@ static int omap_mmc_suspend(struct plat
                                                " level suspend\n");
                        }
  
-                       if (host->id == OMAP_MMC1_DEVID
-                                       && !(OMAP_HSMMC_READ(host->base, HCTL)
-                                                       & SDVSDET)) {
-                               OMAP_HSMMC_WRITE(host->base, HCTL,
-                                       OMAP_HSMMC_READ(host->base, HCTL)
-                                       & SDVSCLR);
-                               OMAP_HSMMC_WRITE(host->base, HCTL,
-                                       OMAP_HSMMC_READ(host->base, HCTL)
-                                       | SDVS30);
-                               OMAP_HSMMC_WRITE(host->base, HCTL,
-                                       OMAP_HSMMC_READ(host->base, HCTL)
-                                       | SDBP);
-                       }
+                       OMAP_HSMMC_WRITE(host->base, HCTL,
+                                        OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
                        clk_disable(host->fclk);
                        clk_disable(host->iclk);
                        clk_disable(host->dbclk);
@@@ -1222,6 -1275,8 +1275,8 @@@ static int omap_mmc_resume(struct platf
                        dev_dbg(mmc_dev(host->mmc),
                                        "Enabling debounce clk failed\n");
  
+               omap_hsmmc_init(host);
                if (host->pdata->resume) {
                        ret = host->pdata->resume(&pdev->dev, host->slot_id);
                        if (ret)