]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/mmc/host/omap_hsmmc.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[mv-sheeva.git] / drivers / mmc / host / omap_hsmmc.c
index 0bfea9c2a5970baa0799af79e78b2fdd023558b8..4487cc0979112ea71e412f2c722ad45282cd3328 100644 (file)
 #define OMAP_MMC1_DEVID                0
 #define OMAP_MMC2_DEVID                1
 #define OMAP_MMC3_DEVID                2
+#define OMAP_MMC4_DEVID                3
+#define OMAP_MMC5_DEVID                4
 
 #define MMC_TIMEOUT_MS         20
 #define OMAP_MMC_MASTER_CLOCK  96000000
 #define OMAP_HSMMC_WRITE(base, reg, val) \
        __raw_writel((val), (base) + OMAP_HSMMC_##reg)
 
-struct mmc_omap_host {
+struct omap_hsmmc_host {
        struct  device          *dev;
        struct  mmc_host        *mmc;
        struct  mmc_request     *mrq;
@@ -162,11 +164,13 @@ struct mmc_omap_host {
        int                     use_dma, dma_ch;
        int                     dma_line_tx, dma_line_rx;
        int                     slot_id;
-       int                     dbclk_enabled;
+       int                     got_dbclk;
        int                     response_busy;
        int                     context_loss;
        int                     dpm_state;
        int                     vdd;
+       int                     protect_card;
+       int                     reqs_blocked;
 
        struct  omap_mmc_platform_data  *pdata;
 };
@@ -174,7 +178,7 @@ struct mmc_omap_host {
 /*
  * Stop clock to the card
  */
-static void omap_mmc_stop_clock(struct mmc_omap_host *host)
+static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host)
 {
        OMAP_HSMMC_WRITE(host->base, SYSCTL,
                OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN);
@@ -188,7 +192,7 @@ static void omap_mmc_stop_clock(struct mmc_omap_host *host)
  * Restore the MMC host context, if it was lost as result of a
  * power state change.
  */
-static int omap_mmc_restore_ctx(struct mmc_omap_host *host)
+static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 {
        struct mmc_ios *ios = &host->mmc->ios;
        struct omap_mmc_platform_data *pdata = host->pdata;
@@ -316,7 +320,7 @@ out:
 /*
  * Save the MMC host context (store the number of power state changes so far).
  */
-static void omap_mmc_save_ctx(struct mmc_omap_host *host)
+static void omap_hsmmc_context_save(struct omap_hsmmc_host *host)
 {
        struct omap_mmc_platform_data *pdata = host->pdata;
        int context_loss;
@@ -331,12 +335,12 @@ static void omap_mmc_save_ctx(struct mmc_omap_host *host)
 
 #else
 
-static int omap_mmc_restore_ctx(struct mmc_omap_host *host)
+static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 {
        return 0;
 }
 
-static void omap_mmc_save_ctx(struct mmc_omap_host *host)
+static void omap_hsmmc_context_save(struct omap_hsmmc_host *host)
 {
 }
 
@@ -346,11 +350,14 @@ static void omap_mmc_save_ctx(struct mmc_omap_host *host)
  * Send init stream sequence to card
  * before sending IDLE command
  */
-static void send_init_stream(struct mmc_omap_host *host)
+static void send_init_stream(struct omap_hsmmc_host *host)
 {
        int reg = 0;
        unsigned long timeout;
 
+       if (host->protect_card)
+               return;
+
        disable_irq(host->irq);
        OMAP_HSMMC_WRITE(host->base, CON,
                OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM);
@@ -370,7 +377,7 @@ static void send_init_stream(struct mmc_omap_host *host)
 }
 
 static inline
-int mmc_omap_cover_is_closed(struct mmc_omap_host *host)
+int omap_hsmmc_cover_is_closed(struct omap_hsmmc_host *host)
 {
        int r = 1;
 
@@ -380,35 +387,35 @@ int mmc_omap_cover_is_closed(struct mmc_omap_host *host)
 }
 
 static ssize_t
-mmc_omap_show_cover_switch(struct device *dev, struct device_attribute *attr,
+omap_hsmmc_show_cover_switch(struct device *dev, struct device_attribute *attr,
                           char *buf)
 {
        struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
-       struct mmc_omap_host *host = mmc_priv(mmc);
+       struct omap_hsmmc_host *host = mmc_priv(mmc);
 
-       return sprintf(buf, "%s\n", mmc_omap_cover_is_closed(host) ? "closed" :
-                      "open");
+       return sprintf(buf, "%s\n",
+                       omap_hsmmc_cover_is_closed(host) ? "closed" : "open");
 }
 
-static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
+static DEVICE_ATTR(cover_switch, S_IRUGO, omap_hsmmc_show_cover_switch, NULL);
 
 static ssize_t
-mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr,
+omap_hsmmc_show_slot_name(struct device *dev, struct device_attribute *attr,
                        char *buf)
 {
        struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
-       struct mmc_omap_host *host = mmc_priv(mmc);
+       struct omap_hsmmc_host *host = mmc_priv(mmc);
 
        return sprintf(buf, "%s\n", mmc_slot(host).name);
 }
 
-static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL);
+static DEVICE_ATTR(slot_name, S_IRUGO, omap_hsmmc_show_slot_name, NULL);
 
 /*
  * Configure the response type and send the cmd.
  */
 static void
-mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
+omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
        struct mmc_data *data)
 {
        int cmdreg = 0, resptype = 0, cmdtype = 0;
@@ -474,7 +481,7 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
 }
 
 static int
-mmc_omap_get_dma_dir(struct mmc_omap_host *host, struct mmc_data *data)
+omap_hsmmc_get_dma_dir(struct omap_hsmmc_host *host, struct mmc_data *data)
 {
        if (data->flags & MMC_DATA_WRITE)
                return DMA_TO_DEVICE;
@@ -486,7 +493,7 @@ mmc_omap_get_dma_dir(struct mmc_omap_host *host, struct mmc_data *data)
  * Notify the transfer complete to MMC core
  */
 static void
-mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
+omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data)
 {
        if (!data) {
                struct mmc_request *mrq = host->mrq;
@@ -507,7 +514,7 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
 
        if (host->use_dma && host->dma_ch != -1)
                dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
-                       mmc_omap_get_dma_dir(host, data));
+                       omap_hsmmc_get_dma_dir(host, data));
 
        if (!data->error)
                data->bytes_xfered += data->blocks * (data->blksz);
@@ -519,14 +526,14 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
                mmc_request_done(host->mmc, data->mrq);
                return;
        }
-       mmc_omap_start_command(host, data->stop, NULL);
+       omap_hsmmc_start_command(host, data->stop, NULL);
 }
 
 /*
  * Notify the core about command completion
  */
 static void
-mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
+omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd)
 {
        host->cmd = NULL;
 
@@ -551,13 +558,13 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
 /*
  * DMA clean up for command errors
  */
-static void mmc_dma_cleanup(struct mmc_omap_host *host, int errno)
+static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
 {
        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,
-                       mmc_omap_get_dma_dir(host, host->data));
+                       omap_hsmmc_get_dma_dir(host, host->data));
                omap_free_dma(host->dma_ch);
                host->dma_ch = -1;
                up(&host->sem);
@@ -569,10 +576,10 @@ static void mmc_dma_cleanup(struct mmc_omap_host *host, int errno)
  * Readable error output
  */
 #ifdef CONFIG_MMC_DEBUG
-static void mmc_omap_report_irq(struct mmc_omap_host *host, u32 status)
+static void omap_hsmmc_report_irq(struct omap_hsmmc_host *host, u32 status)
 {
        /* --- means reserved bit without definition at documentation */
-       static const char *mmc_omap_status_bits[] = {
+       static const char *omap_hsmmc_status_bits[] = {
                "CC", "TC", "BGE", "---", "BWR", "BRR", "---", "---", "CIRQ",
                "OBI", "---", "---", "---", "---", "---", "ERRI", "CTO", "CCRC",
                "CEB", "CIE", "DTO", "DCRC", "DEB", "---", "ACE", "---",
@@ -585,9 +592,9 @@ static void mmc_omap_report_irq(struct mmc_omap_host *host, u32 status)
        len = sprintf(buf, "MMC IRQ 0x%x :", status);
        buf += len;
 
-       for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++)
+       for (i = 0; i < ARRAY_SIZE(omap_hsmmc_status_bits); i++)
                if (status & (1 << i)) {
-                       len = sprintf(buf, " %s", mmc_omap_status_bits[i]);
+                       len = sprintf(buf, " %s", omap_hsmmc_status_bits[i]);
                        buf += len;
                }
 
@@ -602,8 +609,8 @@ static void mmc_omap_report_irq(struct mmc_omap_host *host, u32 status)
  *  SRC or SRD bit of SYSCTL register
  * Can be called from interrupt context
  */
-static inline void mmc_omap_reset_controller_fsm(struct mmc_omap_host *host,
-               unsigned long bit)
+static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
+                                                  unsigned long bit)
 {
        unsigned long i = 0;
        unsigned long limit = (loops_per_jiffy *
@@ -625,9 +632,9 @@ static inline void mmc_omap_reset_controller_fsm(struct mmc_omap_host *host,
 /*
  * MMC controller IRQ handler
  */
-static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
 {
-       struct mmc_omap_host *host = dev_id;
+       struct omap_hsmmc_host *host = dev_id;
        struct mmc_data *data;
        int end_cmd = 0, end_trans = 0, status;
 
@@ -648,14 +655,14 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 
        if (status & ERR) {
 #ifdef CONFIG_MMC_DEBUG
-               mmc_omap_report_irq(host, status);
+               omap_hsmmc_report_irq(host, status);
 #endif
                if ((status & CMD_TIMEOUT) ||
                        (status & CMD_CRC)) {
                        if (host->cmd) {
                                if (status & CMD_TIMEOUT) {
-                                       mmc_omap_reset_controller_fsm(host,
-                                                                     SRC);
+                                       omap_hsmmc_reset_controller_fsm(host,
+                                                                       SRC);
                                        host->cmd->error = -ETIMEDOUT;
                                } else {
                                        host->cmd->error = -EILSEQ;
@@ -664,9 +671,10 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                        }
                        if (host->data || host->response_busy) {
                                if (host->data)
-                                       mmc_dma_cleanup(host, -ETIMEDOUT);
+                                       omap_hsmmc_dma_cleanup(host,
+                                                               -ETIMEDOUT);
                                host->response_busy = 0;
-                               mmc_omap_reset_controller_fsm(host, SRD);
+                               omap_hsmmc_reset_controller_fsm(host, SRD);
                        }
                }
                if ((status & DATA_TIMEOUT) ||
@@ -676,11 +684,11 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                                                -ETIMEDOUT : -EILSEQ;
 
                                if (host->data)
-                                       mmc_dma_cleanup(host, err);
+                                       omap_hsmmc_dma_cleanup(host, err);
                                else
                                        host->mrq->cmd->error = err;
                                host->response_busy = 0;
-                               mmc_omap_reset_controller_fsm(host, SRD);
+                               omap_hsmmc_reset_controller_fsm(host, SRD);
                                end_trans = 1;
                        }
                }
@@ -699,16 +707,16 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
        OMAP_HSMMC_READ(host->base, STAT);
 
        if (end_cmd || ((status & CC) && host->cmd))
-               mmc_omap_cmd_done(host, host->cmd);
+               omap_hsmmc_cmd_done(host, host->cmd);
        if ((end_trans || (status & TC)) && host->mrq)
-               mmc_omap_xfer_done(host, data);
+               omap_hsmmc_xfer_done(host, data);
 
        spin_unlock(&host->irq_lock);
 
        return IRQ_HANDLED;
 }
 
-static void set_sd_bus_power(struct mmc_omap_host *host)
+static void set_sd_bus_power(struct omap_hsmmc_host *host)
 {
        unsigned long i;
 
@@ -728,7 +736,7 @@ static void set_sd_bus_power(struct mmc_omap_host *host)
  * The MMC2 transceiver controls are used instead of DAT4..DAT7.
  * Some chips, like eMMC ones, use internal transceivers.
  */
-static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
+static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)
 {
        u32 reg_val = 0;
        int ret;
@@ -736,22 +744,24 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
        /* Disable the clocks */
        clk_disable(host->fclk);
        clk_disable(host->iclk);
-       clk_disable(host->dbclk);
+       if (host->got_dbclk)
+               clk_disable(host->dbclk);
 
        /* Turn the power off */
        ret = mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
-       if (ret != 0)
-               goto err;
 
        /* Turn the power ON with given VDD 1.8 or 3.0v */
-       ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1, vdd);
+       if (!ret)
+               ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1,
+                                              vdd);
+       clk_enable(host->iclk);
+       clk_enable(host->fclk);
+       if (host->got_dbclk)
+               clk_enable(host->dbclk);
+
        if (ret != 0)
                goto err;
 
-       clk_enable(host->fclk);
-       clk_enable(host->iclk);
-       clk_enable(host->dbclk);
-
        OMAP_HSMMC_WRITE(host->base, HCTL,
                OMAP_HSMMC_READ(host->base, HCTL) & SDVSCLR);
        reg_val = OMAP_HSMMC_READ(host->base, HCTL);
@@ -759,7 +769,7 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
        /*
         * If a MMC dual voltage card is detected, the set_ios fn calls
         * this fn with VDD bit set for 1.8V. Upon card removal from the
-        * slot, omap_mmc_set_ios sets the VDD back to 3V on MMC_POWER_OFF.
+        * slot, omap_hsmmc_set_ios sets the VDD back to 3V on MMC_POWER_OFF.
         *
         * Cope with a bit of slop in the range ... per data sheets:
         *  - "1.8V" for vdds_mmc1/vdds_mmc1a can be up to 2.45V max,
@@ -785,13 +795,37 @@ err:
        return ret;
 }
 
+/* Protect the card while the cover is open */
+static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host)
+{
+       if (!mmc_slot(host).get_cover_state)
+               return;
+
+       host->reqs_blocked = 0;
+       if (mmc_slot(host).get_cover_state(host->dev, host->slot_id)) {
+               if (host->protect_card) {
+                       printk(KERN_INFO "%s: cover is closed, "
+                                        "card is now accessible\n",
+                                        mmc_hostname(host->mmc));
+                       host->protect_card = 0;
+               }
+       } else {
+               if (!host->protect_card) {
+                       printk(KERN_INFO "%s: cover is open, "
+                                        "card is now inaccessible\n",
+                                        mmc_hostname(host->mmc));
+                       host->protect_card = 1;
+               }
+       }
+}
+
 /*
  * Work Item to notify the core about card insertion/removal
  */
-static void mmc_omap_detect(struct work_struct *work)
+static void omap_hsmmc_detect(struct work_struct *work)
 {
-       struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
-                                               mmc_carddetect_work);
+       struct omap_hsmmc_host *host =
+               container_of(work, struct omap_hsmmc_host, mmc_carddetect_work);
        struct omap_mmc_slot_data *slot = &mmc_slot(host);
        int carddetect;
 
@@ -802,15 +836,18 @@ static void mmc_omap_detect(struct work_struct *work)
 
        if (slot->card_detect)
                carddetect = slot->card_detect(slot->card_detect_irq);
-       else
+       else {
+               omap_hsmmc_protect_card(host);
                carddetect = -ENOSYS;
+       }
 
        if (carddetect) {
                mmc_detect_change(host->mmc, (HZ * 200) / 1000);
        } else {
                mmc_host_enable(host->mmc);
-               mmc_omap_reset_controller_fsm(host, SRD);
+               omap_hsmmc_reset_controller_fsm(host, SRD);
                mmc_host_lazy_disable(host->mmc);
+
                mmc_detect_change(host->mmc, (HZ * 50) / 1000);
        }
 }
@@ -818,9 +855,9 @@ static void mmc_omap_detect(struct work_struct *work)
 /*
  * ISR for handling card insertion and removal
  */
-static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id)
+static irqreturn_t omap_hsmmc_cd_handler(int irq, void *dev_id)
 {
-       struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id;
+       struct omap_hsmmc_host *host = (struct omap_hsmmc_host *)dev_id;
 
        if (host->suspended)
                return IRQ_HANDLED;
@@ -829,7 +866,7 @@ static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int mmc_omap_get_dma_sync_dev(struct mmc_omap_host *host,
+static int omap_hsmmc_get_dma_sync_dev(struct omap_hsmmc_host *host,
                                     struct mmc_data *data)
 {
        int sync_dev;
@@ -841,7 +878,7 @@ static int mmc_omap_get_dma_sync_dev(struct mmc_omap_host *host,
        return sync_dev;
 }
 
-static void mmc_omap_config_dma_params(struct mmc_omap_host *host,
+static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host,
                                       struct mmc_data *data,
                                       struct scatterlist *sgl)
 {
@@ -865,7 +902,7 @@ static void mmc_omap_config_dma_params(struct mmc_omap_host *host,
 
        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),
+                       omap_hsmmc_get_dma_sync_dev(host, data),
                        !(data->flags & MMC_DATA_WRITE));
 
        omap_start_dma(dma_ch);
@@ -874,9 +911,9 @@ static void mmc_omap_config_dma_params(struct mmc_omap_host *host,
 /*
  * DMA call back function
  */
-static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
+static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *data)
 {
-       struct mmc_omap_host *host = data;
+       struct omap_hsmmc_host *host = data;
 
        if (ch_status & OMAP2_DMA_MISALIGNED_ERR_IRQ)
                dev_dbg(mmc_dev(host->mmc), "MISALIGNED_ADRS_ERR\n");
@@ -887,7 +924,7 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
        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,
+               omap_hsmmc_config_dma_params(host, host->data,
                                           host->data->sg + host->dma_sg_idx);
                return;
        }
@@ -904,8 +941,8 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
 /*
  * 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)
+static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host,
+                                       struct mmc_request *req)
 {
        int dma_ch = 0, ret = 0, err = 1, i;
        struct mmc_data *data = req->data;
@@ -942,8 +979,8 @@ mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req)
                        return err;
        }
 
-       ret = omap_request_dma(mmc_omap_get_dma_sync_dev(host, data), "MMC/SD",
-                              mmc_omap_dma_cb, host, &dma_ch);
+       ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data),
+                              "MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch);
        if (ret != 0) {
                dev_err(mmc_dev(host->mmc),
                        "%s: omap_request_dma() failed with %d\n",
@@ -952,17 +989,18 @@ mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req)
        }
 
        host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
-                       data->sg_len, mmc_omap_get_dma_dir(host, data));
+                       data->sg_len, omap_hsmmc_get_dma_dir(host, data));
        host->dma_ch = dma_ch;
        host->dma_sg_idx = 0;
 
-       mmc_omap_config_dma_params(host, data, data->sg);
+       omap_hsmmc_config_dma_params(host, data, data->sg);
 
        return 0;
 }
 
-static void set_data_timeout(struct mmc_omap_host *host,
-                            struct mmc_request *req)
+static void set_data_timeout(struct omap_hsmmc_host *host,
+                            unsigned int timeout_ns,
+                            unsigned int timeout_clks)
 {
        unsigned int timeout, cycle_ns;
        uint32_t reg, clkd, dto = 0;
@@ -973,8 +1011,8 @@ static void set_data_timeout(struct mmc_omap_host *host,
                clkd = 1;
 
        cycle_ns = 1000000000 / (clk_get_rate(host->fclk) / clkd);
-       timeout = req->data->timeout_ns / cycle_ns;
-       timeout += req->data->timeout_clks;
+       timeout = timeout_ns / cycle_ns;
+       timeout += timeout_clks;
        if (timeout) {
                while ((timeout & 0x80000000) == 0) {
                        dto += 1;
@@ -1001,22 +1039,28 @@ static void set_data_timeout(struct mmc_omap_host *host,
  * Configure block length for MMC/SD cards and initiate the transfer.
  */
 static int
-mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
+omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
 {
        int ret;
        host->data = req->data;
 
        if (req->data == NULL) {
                OMAP_HSMMC_WRITE(host->base, BLK, 0);
+               /*
+                * Set an arbitrary 100ms data timeout for commands with
+                * busy signal.
+                */
+               if (req->cmd->flags & MMC_RSP_BUSY)
+                       set_data_timeout(host, 100000000U, 0);
                return 0;
        }
 
        OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz)
                                        | (req->data->blocks << 16));
-       set_data_timeout(host, req);
+       set_data_timeout(host, req->data->timeout_ns, req->data->timeout_clks);
 
        if (host->use_dma) {
-               ret = mmc_omap_start_dma_transfer(host, req);
+               ret = omap_hsmmc_start_dma_transfer(host, req);
                if (ret != 0) {
                        dev_dbg(mmc_dev(host->mmc), "MMC start dma failure\n");
                        return ret;
@@ -1028,9 +1072,9 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
 /*
  * Request function. for read/write operation
  */
-static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req)
+static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
 {
-       struct mmc_omap_host *host = mmc_priv(mmc);
+       struct omap_hsmmc_host *host = mmc_priv(mmc);
        int err;
 
        /*
@@ -1038,11 +1082,35 @@ static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req)
         * interrupts, but not if we are already in interrupt context i.e.
         * retries.
         */
-       if (!in_interrupt())
+       if (!in_interrupt()) {
                spin_lock_irqsave(&host->irq_lock, host->flags);
+               /*
+                * Protect the card from I/O if there is a possibility
+                * it can be removed.
+                */
+               if (host->protect_card) {
+                       if (host->reqs_blocked < 3) {
+                               /*
+                                * Ensure the controller is left in a consistent
+                                * state by resetting the command and data state
+                                * machines.
+                                */
+                               omap_hsmmc_reset_controller_fsm(host, SRD);
+                               omap_hsmmc_reset_controller_fsm(host, SRC);
+                               host->reqs_blocked += 1;
+                       }
+                       req->cmd->error = -EBADF;
+                       if (req->data)
+                               req->data->error = -EBADF;
+                       spin_unlock_irqrestore(&host->irq_lock, host->flags);
+                       mmc_request_done(mmc, req);
+                       return;
+               } else if (host->reqs_blocked)
+                       host->reqs_blocked = 0;
+       }
        WARN_ON(host->mrq != NULL);
        host->mrq = req;
-       err = mmc_omap_prepare_data(host, req);
+       err = omap_hsmmc_prepare_data(host, req);
        if (err) {
                req->cmd->error = err;
                if (req->data)
@@ -1054,14 +1122,13 @@ static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req)
                return;
        }
 
-       mmc_omap_start_command(host, req->cmd, req->data);
+       omap_hsmmc_start_command(host, req->cmd, req->data);
 }
 
-
 /* Routine to configure clock values. Exposed API to core */
-static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
-       struct mmc_omap_host *host = mmc_priv(mmc);
+       struct omap_hsmmc_host *host = mmc_priv(mmc);
        u16 dsor = 0;
        unsigned long regval;
        unsigned long timeout;
@@ -1120,8 +1187,8 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                                 * MMC_POWER_UP upon recalculating the voltage.
                                 * vdd 1.8v.
                                 */
-                               if (omap_mmc_switch_opcond(host, ios->vdd) != 0)
-                                       dev_dbg(mmc_dev(host->mmc),
+                       if (omap_hsmmc_switch_opcond(host, ios->vdd) != 0)
+                               dev_dbg(mmc_dev(host->mmc),
                                                "Switch operation failed\n");
                }
        }
@@ -1137,7 +1204,7 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                if (dsor > 250)
                        dsor = 250;
        }
-       omap_mmc_stop_clock(host);
+       omap_hsmmc_stop_clock(host);
        regval = OMAP_HSMMC_READ(host->base, SYSCTL);
        regval = regval & ~(CLKD_MASK);
        regval = regval | (dsor << 6) | (DTO << 16);
@@ -1171,7 +1238,7 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 static int omap_hsmmc_get_cd(struct mmc_host *mmc)
 {
-       struct mmc_omap_host *host = mmc_priv(mmc);
+       struct omap_hsmmc_host *host = mmc_priv(mmc);
 
        if (!mmc_slot(host).card_detect)
                return -ENOSYS;
@@ -1180,14 +1247,14 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc)
 
 static int omap_hsmmc_get_ro(struct mmc_host *mmc)
 {
-       struct mmc_omap_host *host = mmc_priv(mmc);
+       struct omap_hsmmc_host *host = mmc_priv(mmc);
 
        if (!mmc_slot(host).get_ro)
                return -ENOSYS;
        return mmc_slot(host).get_ro(host->dev, 0);
 }
 
-static void omap_hsmmc_init(struct mmc_omap_host *host)
+static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
 {
        u32 hctl, capa, value;
 
@@ -1233,9 +1300,9 @@ static void omap_hsmmc_init(struct mmc_omap_host *host)
 enum {ENABLED = 0, DISABLED, CARDSLEEP, REGSLEEP, OFF};
 
 /* Handler for [ENABLED -> DISABLED] transition */
-static int omap_mmc_enabled_to_disabled(struct mmc_omap_host *host)
+static int omap_hsmmc_enabled_to_disabled(struct omap_hsmmc_host *host)
 {
-       omap_mmc_save_ctx(host);
+       omap_hsmmc_context_save(host);
        clk_disable(host->fclk);
        host->dpm_state = DISABLED;
 
@@ -1248,7 +1315,7 @@ static int omap_mmc_enabled_to_disabled(struct mmc_omap_host *host)
 }
 
 /* Handler for [DISABLED -> REGSLEEP / CARDSLEEP] transition */
-static int omap_mmc_disabled_to_sleep(struct mmc_omap_host *host)
+static int omap_hsmmc_disabled_to_sleep(struct omap_hsmmc_host *host)
 {
        int err, new_state;
 
@@ -1256,7 +1323,7 @@ static int omap_mmc_disabled_to_sleep(struct mmc_omap_host *host)
                return 0;
 
        clk_enable(host->fclk);
-       omap_mmc_restore_ctx(host);
+       omap_hsmmc_context_restore(host);
        if (mmc_card_can_sleep(host->mmc)) {
                err = mmc_card_sleep(host->mmc);
                if (err < 0) {
@@ -1265,8 +1332,9 @@ static int omap_mmc_disabled_to_sleep(struct mmc_omap_host *host)
                        return err;
                }
                new_state = CARDSLEEP;
-       } else
+       } else {
                new_state = REGSLEEP;
+       }
        if (mmc_slot(host).set_sleep)
                mmc_slot(host).set_sleep(host->dev, host->slot_id, 1, 0,
                                         new_state == CARDSLEEP);
@@ -1289,7 +1357,7 @@ static int omap_mmc_disabled_to_sleep(struct mmc_omap_host *host)
 }
 
 /* Handler for [REGSLEEP / CARDSLEEP -> OFF] transition */
-static int omap_mmc_sleep_to_off(struct mmc_omap_host *host)
+static int omap_hsmmc_sleep_to_off(struct omap_hsmmc_host *host)
 {
        if (!mmc_try_claim_host(host->mmc))
                return 0;
@@ -1317,7 +1385,7 @@ static int omap_mmc_sleep_to_off(struct mmc_omap_host *host)
 }
 
 /* Handler for [DISABLED -> ENABLED] transition */
-static int omap_mmc_disabled_to_enabled(struct mmc_omap_host *host)
+static int omap_hsmmc_disabled_to_enabled(struct omap_hsmmc_host *host)
 {
        int err;
 
@@ -1325,8 +1393,7 @@ static int omap_mmc_disabled_to_enabled(struct mmc_omap_host *host)
        if (err < 0)
                return err;
 
-       omap_mmc_restore_ctx(host);
-
+       omap_hsmmc_context_restore(host);
        host->dpm_state = ENABLED;
 
        dev_dbg(mmc_dev(host->mmc), "DISABLED -> ENABLED\n");
@@ -1335,13 +1402,13 @@ static int omap_mmc_disabled_to_enabled(struct mmc_omap_host *host)
 }
 
 /* Handler for [SLEEP -> ENABLED] transition */
-static int omap_mmc_sleep_to_enabled(struct mmc_omap_host *host)
+static int omap_hsmmc_sleep_to_enabled(struct omap_hsmmc_host *host)
 {
        if (!mmc_try_claim_host(host->mmc))
                return 0;
 
        clk_enable(host->fclk);
-       omap_mmc_restore_ctx(host);
+       omap_hsmmc_context_restore(host);
        if (mmc_slot(host).set_sleep)
                mmc_slot(host).set_sleep(host->dev, host->slot_id, 0,
                         host->vdd, host->dpm_state == CARDSLEEP);
@@ -1359,12 +1426,12 @@ static int omap_mmc_sleep_to_enabled(struct mmc_omap_host *host)
 }
 
 /* Handler for [OFF -> ENABLED] transition */
-static int omap_mmc_off_to_enabled(struct mmc_omap_host *host)
+static int omap_hsmmc_off_to_enabled(struct omap_hsmmc_host *host)
 {
        clk_enable(host->fclk);
 
-       omap_mmc_restore_ctx(host);
-       omap_hsmmc_init(host);
+       omap_hsmmc_context_restore(host);
+       omap_hsmmc_conf_bus_power(host);
        mmc_power_restore_host(host->mmc);
 
        host->dpm_state = ENABLED;
@@ -1377,18 +1444,18 @@ static int omap_mmc_off_to_enabled(struct mmc_omap_host *host)
 /*
  * Bring MMC host to ENABLED from any other PM state.
  */
-static int omap_mmc_enable(struct mmc_host *mmc)
+static int omap_hsmmc_enable(struct mmc_host *mmc)
 {
-       struct mmc_omap_host *host = mmc_priv(mmc);
+       struct omap_hsmmc_host *host = mmc_priv(mmc);
 
        switch (host->dpm_state) {
        case DISABLED:
-               return omap_mmc_disabled_to_enabled(host);
+               return omap_hsmmc_disabled_to_enabled(host);
        case CARDSLEEP:
        case REGSLEEP:
-               return omap_mmc_sleep_to_enabled(host);
+               return omap_hsmmc_sleep_to_enabled(host);
        case OFF:
-               return omap_mmc_off_to_enabled(host);
+               return omap_hsmmc_off_to_enabled(host);
        default:
                dev_dbg(mmc_dev(host->mmc), "UNKNOWN state\n");
                return -EINVAL;
@@ -1398,68 +1465,68 @@ static int omap_mmc_enable(struct mmc_host *mmc)
 /*
  * Bring MMC host in PM state (one level deeper).
  */
-static int omap_mmc_disable(struct mmc_host *mmc, int lazy)
+static int omap_hsmmc_disable(struct mmc_host *mmc, int lazy)
 {
-       struct mmc_omap_host *host = mmc_priv(mmc);
+       struct omap_hsmmc_host *host = mmc_priv(mmc);
 
        switch (host->dpm_state) {
        case ENABLED: {
                int delay;
 
-               delay = omap_mmc_enabled_to_disabled(host);
+               delay = omap_hsmmc_enabled_to_disabled(host);
                if (lazy || delay < 0)
                        return delay;
                return 0;
        }
        case DISABLED:
-               return omap_mmc_disabled_to_sleep(host);
+               return omap_hsmmc_disabled_to_sleep(host);
        case CARDSLEEP:
        case REGSLEEP:
-               return omap_mmc_sleep_to_off(host);
+               return omap_hsmmc_sleep_to_off(host);
        default:
                dev_dbg(mmc_dev(host->mmc), "UNKNOWN state\n");
                return -EINVAL;
        }
 }
 
-static int omap_mmc_enable_fclk(struct mmc_host *mmc)
+static int omap_hsmmc_enable_fclk(struct mmc_host *mmc)
 {
-       struct mmc_omap_host *host = mmc_priv(mmc);
+       struct omap_hsmmc_host *host = mmc_priv(mmc);
        int err;
 
        err = clk_enable(host->fclk);
        if (err)
                return err;
        dev_dbg(mmc_dev(host->mmc), "mmc_fclk: enabled\n");
-       omap_mmc_restore_ctx(host);
+       omap_hsmmc_context_restore(host);
        return 0;
 }
 
-static int omap_mmc_disable_fclk(struct mmc_host *mmc, int lazy)
+static int omap_hsmmc_disable_fclk(struct mmc_host *mmc, int lazy)
 {
-       struct mmc_omap_host *host = mmc_priv(mmc);
+       struct omap_hsmmc_host *host = mmc_priv(mmc);
 
-       omap_mmc_save_ctx(host);
+       omap_hsmmc_context_save(host);
        clk_disable(host->fclk);
        dev_dbg(mmc_dev(host->mmc), "mmc_fclk: disabled\n");
        return 0;
 }
 
-static const struct mmc_host_ops mmc_omap_ops = {
-       .enable = omap_mmc_enable_fclk,
-       .disable = omap_mmc_disable_fclk,
-       .request = omap_mmc_request,
-       .set_ios = omap_mmc_set_ios,
+static const struct mmc_host_ops omap_hsmmc_ops = {
+       .enable = omap_hsmmc_enable_fclk,
+       .disable = omap_hsmmc_disable_fclk,
+       .request = omap_hsmmc_request,
+       .set_ios = omap_hsmmc_set_ios,
        .get_cd = omap_hsmmc_get_cd,
        .get_ro = omap_hsmmc_get_ro,
        /* NYET -- enable_sdio_irq */
 };
 
-static const struct mmc_host_ops mmc_omap_ps_ops = {
-       .enable = omap_mmc_enable,
-       .disable = omap_mmc_disable,
-       .request = omap_mmc_request,
-       .set_ios = omap_mmc_set_ios,
+static const struct mmc_host_ops omap_hsmmc_ps_ops = {
+       .enable = omap_hsmmc_enable,
+       .disable = omap_hsmmc_disable,
+       .request = omap_hsmmc_request,
+       .set_ios = omap_hsmmc_set_ios,
        .get_cd = omap_hsmmc_get_cd,
        .get_ro = omap_hsmmc_get_ro,
        /* NYET -- enable_sdio_irq */
@@ -1467,15 +1534,14 @@ static const struct mmc_host_ops mmc_omap_ps_ops = {
 
 #ifdef CONFIG_DEBUG_FS
 
-static int mmc_regs_show(struct seq_file *s, void *data)
+static int omap_hsmmc_regs_show(struct seq_file *s, void *data)
 {
        struct mmc_host *mmc = s->private;
-       struct mmc_omap_host *host = mmc_priv(mmc);
-       struct omap_mmc_platform_data *pdata = host->pdata;
+       struct omap_hsmmc_host *host = mmc_priv(mmc);
        int context_loss = 0;
 
-       if (pdata->get_context_loss_count)
-               context_loss = pdata->get_context_loss_count(host->dev);
+       if (host->pdata->get_context_loss_count)
+               context_loss = host->pdata->get_context_loss_count(host->dev);
 
        seq_printf(s, "mmc%d:\n"
                        " enabled:\t%d\n"
@@ -1517,19 +1583,19 @@ static int mmc_regs_show(struct seq_file *s, void *data)
        return 0;
 }
 
-static int mmc_regs_open(struct inode *inode, struct file *file)
+static int omap_hsmmc_regs_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, mmc_regs_show, inode->i_private);
+       return single_open(file, omap_hsmmc_regs_show, inode->i_private);
 }
 
 static const struct file_operations mmc_regs_fops = {
-       .open           = mmc_regs_open,
+       .open           = omap_hsmmc_regs_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = single_release,
 };
 
-static void omap_mmc_debugfs(struct mmc_host *mmc)
+static void omap_hsmmc_debugfs(struct mmc_host *mmc)
 {
        if (mmc->debugfs_root)
                debugfs_create_file("regs", S_IRUSR, mmc->debugfs_root,
@@ -1538,17 +1604,17 @@ static void omap_mmc_debugfs(struct mmc_host *mmc)
 
 #else
 
-static void omap_mmc_debugfs(struct mmc_host *mmc)
+static void omap_hsmmc_debugfs(struct mmc_host *mmc)
 {
 }
 
 #endif
 
-static int __init omap_mmc_probe(struct platform_device *pdev)
+static int __init omap_hsmmc_probe(struct platform_device *pdev)
 {
        struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
        struct mmc_host *mmc;
-       struct mmc_omap_host *host = NULL;
+       struct omap_hsmmc_host *host = NULL;
        struct resource *res;
        int ret = 0, irq;
 
@@ -1572,7 +1638,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
        if (res == NULL)
                return -EBUSY;
 
-       mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
+       mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), &pdev->dev);
        if (!mmc) {
                ret = -ENOMEM;
                goto err;
@@ -1593,12 +1659,12 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
        host->power_mode = -1;
 
        platform_set_drvdata(pdev, host);
-       INIT_WORK(&host->mmc_carddetect_work, mmc_omap_detect);
+       INIT_WORK(&host->mmc_carddetect_work, omap_hsmmc_detect);
 
        if (mmc_slot(host).power_saving)
-               mmc->ops        = &mmc_omap_ps_ops;
+               mmc->ops        = &omap_hsmmc_ps_ops;
        else
-               mmc->ops        = &mmc_omap_ops;
+               mmc->ops        = &omap_hsmmc_ops;
 
        mmc->f_min      = 400000;
        mmc->f_max      = 52000000;
@@ -1620,7 +1686,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
                goto err1;
        }
 
-       omap_mmc_save_ctx(host);
+       omap_hsmmc_context_save(host);
 
        mmc->caps |= MMC_CAP_DISABLE;
        mmc_set_disable_delay(mmc, OMAP_MMC_DISABLED_TIMEOUT);
@@ -1640,18 +1706,22 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
                goto err1;
        }
 
-       host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
-       /*
-        * MMC can still work without debounce clock.
-        */
-       if (IS_ERR(host->dbclk))
-               dev_warn(mmc_dev(host->mmc), "Failed to get debounce clock\n");
-       else
-               if (clk_enable(host->dbclk) != 0)
-                       dev_dbg(mmc_dev(host->mmc), "Enabling debounce"
-                                                       " clk failed\n");
+       if (cpu_is_omap2430()) {
+               host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
+               /*
+                * MMC can still work without debounce clock.
+                */
+               if (IS_ERR(host->dbclk))
+                       dev_warn(mmc_dev(host->mmc),
+                               "Failed to get debounce clock\n");
                else
-                       host->dbclk_enabled = 1;
+                       host->got_dbclk = 1;
+
+               if (host->got_dbclk)
+                       if (clk_enable(host->dbclk) != 0)
+                               dev_dbg(mmc_dev(host->mmc), "Enabling debounce"
+                                                       " clk failed\n");
+       }
 
        /* Since we do only SG emulation, we can have as many segs
         * as we want. */
@@ -1674,7 +1744,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
        if (mmc_slot(host).nonremovable)
                mmc->caps |= MMC_CAP_NONREMOVABLE;
 
-       omap_hsmmc_init(host);
+       omap_hsmmc_conf_bus_power(host);
 
        /* Select DMA lines */
        switch (host->id) {
@@ -1690,13 +1760,21 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
                host->dma_line_tx = OMAP34XX_DMA_MMC3_TX;
                host->dma_line_rx = OMAP34XX_DMA_MMC3_RX;
                break;
+       case OMAP_MMC4_DEVID:
+               host->dma_line_tx = OMAP44XX_DMA_MMC4_TX;
+               host->dma_line_rx = OMAP44XX_DMA_MMC4_RX;
+               break;
+       case OMAP_MMC5_DEVID:
+               host->dma_line_tx = OMAP44XX_DMA_MMC5_TX;
+               host->dma_line_rx = OMAP44XX_DMA_MMC5_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,
+       ret = request_irq(host->irq, omap_hsmmc_irq, IRQF_DISABLED,
                        mmc_hostname(mmc), host);
        if (ret) {
                dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
@@ -1706,7 +1784,8 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
        /* initialize power supplies, gpios, etc */
        if (pdata->init != NULL) {
                if (pdata->init(&pdev->dev) != 0) {
-                       dev_dbg(mmc_dev(host->mmc), "late init error\n");
+                       dev_dbg(mmc_dev(host->mmc),
+                               "Unable to configure MMC IRQs\n");
                        goto err_irq_cd_init;
                }
        }
@@ -1715,7 +1794,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
        /* Request IRQ for card detect */
        if ((mmc_slot(host).card_detect_irq)) {
                ret = request_irq(mmc_slot(host).card_detect_irq,
-                                 omap_mmc_cd_handler,
+                                 omap_hsmmc_cd_handler,
                                  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
                                          | IRQF_DISABLED,
                                  mmc_hostname(mmc), host);
@@ -1731,6 +1810,8 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 
        mmc_host_lazy_disable(host->mmc);
 
+       omap_hsmmc_protect_card(host);
+
        mmc_add_host(mmc);
 
        if (mmc_slot(host).name != NULL) {
@@ -1745,7 +1826,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
                        goto err_cover_switch;
        }
 
-       omap_mmc_debugfs(mmc);
+       omap_hsmmc_debugfs(mmc);
 
        return 0;
 
@@ -1762,7 +1843,7 @@ err_irq:
        clk_disable(host->iclk);
        clk_put(host->fclk);
        clk_put(host->iclk);
-       if (host->dbclk_enabled) {
+       if (host->got_dbclk) {
                clk_disable(host->dbclk);
                clk_put(host->dbclk);
        }
@@ -1777,9 +1858,9 @@ err:
        return ret;
 }
 
-static int omap_mmc_remove(struct platform_device *pdev)
+static int omap_hsmmc_remove(struct platform_device *pdev)
 {
-       struct mmc_omap_host *host = platform_get_drvdata(pdev);
+       struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
        struct resource *res;
 
        if (host) {
@@ -1796,7 +1877,7 @@ static int omap_mmc_remove(struct platform_device *pdev)
                clk_disable(host->iclk);
                clk_put(host->fclk);
                clk_put(host->iclk);
-               if (host->dbclk_enabled) {
+               if (host->got_dbclk) {
                        clk_disable(host->dbclk);
                        clk_put(host->dbclk);
                }
@@ -1814,10 +1895,10 @@ static int omap_mmc_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
+static int omap_hsmmc_suspend(struct platform_device *pdev, pm_message_t state)
 {
        int ret = 0;
-       struct mmc_omap_host *host = platform_get_drvdata(pdev);
+       struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
 
        if (host && host->suspended)
                return 0;
@@ -1847,7 +1928,8 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
                                OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
                        mmc_host_disable(host->mmc);
                        clk_disable(host->iclk);
-                       clk_disable(host->dbclk);
+                       if (host->got_dbclk)
+                               clk_disable(host->dbclk);
                } else {
                        host->suspended = 0;
                        if (host->pdata->resume) {
@@ -1865,10 +1947,10 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
 }
 
 /* Routine to resume the MMC device */
-static int omap_mmc_resume(struct platform_device *pdev)
+static int omap_hsmmc_resume(struct platform_device *pdev)
 {
        int ret = 0;
-       struct mmc_omap_host *host = platform_get_drvdata(pdev);
+       struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
 
        if (host && !host->suspended)
                return 0;
@@ -1878,16 +1960,15 @@ static int omap_mmc_resume(struct platform_device *pdev)
                if (ret)
                        goto clk_en_err;
 
-               if (clk_enable(host->dbclk) != 0)
-                       dev_dbg(mmc_dev(host->mmc),
-                                       "Enabling debounce clk failed\n");
-
                if (mmc_host_enable(host->mmc) != 0) {
                        clk_disable(host->iclk);
                        goto clk_en_err;
                }
 
-               omap_hsmmc_init(host);
+               if (host->got_dbclk)
+                       clk_enable(host->dbclk);
+
+               omap_hsmmc_conf_bus_power(host);
 
                if (host->pdata->resume) {
                        ret = host->pdata->resume(&pdev->dev, host->slot_id);
@@ -1896,10 +1977,13 @@ static int omap_mmc_resume(struct platform_device *pdev)
                                        "Unmask interrupt failed\n");
                }
 
+               omap_hsmmc_protect_card(host);
+
                /* Notify the core to resume the host */
                ret = mmc_resume_host(host->mmc);
                if (ret == 0)
                        host->suspended = 0;
+
                mmc_host_lazy_disable(host->mmc);
        }
 
@@ -1912,34 +1996,34 @@ clk_en_err:
 }
 
 #else
-#define omap_mmc_suspend       NULL
-#define omap_mmc_resume                NULL
+#define omap_hsmmc_suspend     NULL
+#define omap_hsmmc_resume              NULL
 #endif
 
-static struct platform_driver omap_mmc_driver = {
-       .remove         = omap_mmc_remove,
-       .suspend        = omap_mmc_suspend,
-       .resume         = omap_mmc_resume,
+static struct platform_driver omap_hsmmc_driver = {
+       .remove         = omap_hsmmc_remove,
+       .suspend        = omap_hsmmc_suspend,
+       .resume         = omap_hsmmc_resume,
        .driver         = {
                .name = DRIVER_NAME,
                .owner = THIS_MODULE,
        },
 };
 
-static int __init omap_mmc_init(void)
+static int __init omap_hsmmc_init(void)
 {
        /* Register the MMC driver */
-       return platform_driver_probe(&omap_mmc_driver, omap_mmc_probe);
+       return platform_driver_register(&omap_hsmmc_driver);
 }
 
-static void __exit omap_mmc_cleanup(void)
+static void __exit omap_hsmmc_cleanup(void)
 {
        /* Unregister MMC driver */
-       platform_driver_unregister(&omap_mmc_driver);
+       platform_driver_unregister(&omap_hsmmc_driver);
 }
 
-module_init(omap_mmc_init);
-module_exit(omap_mmc_cleanup);
+module_init(omap_hsmmc_init);
+module_exit(omap_hsmmc_cleanup);
 
 MODULE_DESCRIPTION("OMAP High Speed Multimedia Card driver");
 MODULE_LICENSE("GPL");