Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/drzeus/mmc

* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/drzeus/mmc:
  mmc: correct request error handling
  mmc: Flush block queue when removing card
  mmc: sdhci high speed support
  mmc: Support for high speed SD cards
  mmc: Fix mmc_delay() function
  mmc: Add support for mmc v4 wide-bus modes
  [PATCH] mmc: Add support for mmc v4 high speed mode
  trivial change for mmc/Kconfig: MMC_PXA does not mean only PXA255
  Make general code cleanups
  Add MMC_CAP_{MULTIWRITE,BYTEBLOCK} flags
  Platform device error handling cleanup
  Move register definitions away from the header file
  Change OMAP_MMC_{READ,WRITE} macros to use the host pointer
  Replace base with virt_base and phys_base
  mmc: constify mmc_host_ops vectors
  mmc: remove kernel_thread()
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index ea41852..f4f8cca 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -40,7 +40,7 @@
 	  If unsure, say N.
 
 config MMC_PXA
-	tristate "Intel PXA255 Multimedia Card Interface support"
+	tristate "Intel PXA25x/26x/27x Multimedia Card Interface support"
 	depends on ARCH_PXA && MMC
 	help
 	  This selects the Intel(R) PXA(R) Multimedia card Interface.
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
index 494b23f..6495cd8 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/at91_mci.c
@@ -793,7 +793,7 @@
 	return read_only;
 }
 
-static struct mmc_host_ops at91_mci_ops = {
+static const struct mmc_host_ops at91_mci_ops = {
 	.request	= at91_mci_request,
 	.set_ios	= at91_mci_set_ios,
 	.get_ro		= at91_mci_get_ro,
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
index 53ffcbb..447fba5 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/au1xmmc.c
@@ -875,7 +875,7 @@
 	host->rx_chan = rxchan;
 }
 
-struct mmc_host_ops au1xmmc_ops = {
+struct const mmc_host_ops au1xmmc_ops = {
 	.request	= au1xmmc_request,
 	.set_ios	= au1xmmc_set_ios,
 };
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
index 659d4a8..06e7fcd 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/imxmmc.c
@@ -877,7 +877,7 @@
 	}
 }
 
-static struct mmc_host_ops imxmci_ops = {
+static const struct mmc_host_ops imxmci_ops = {
 	.request	= imxmci_request,
 	.set_ios	= imxmci_set_ios,
 };
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 766bc544..9d19002 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -4,6 +4,7 @@
  *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
  *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
  *  SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
+ *  MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -396,23 +397,23 @@
 		return err;
 
 	/*
-	 * Default bus width is 1 bit.
-	 */
-	host->ios.bus_width = MMC_BUS_WIDTH_1;
-
-	/*
-	 * We can only change the bus width of the selected
-	 * card so therefore we have to put the handling
+	 * We can only change the bus width of SD cards when
+	 * they are selected so we have to put the handling
 	 * here.
+	 *
+	 * The card is in 1 bit mode by default so
+	 * we only need to change if it supports the
+	 * wider version.
 	 */
-	if (host->caps & MMC_CAP_4_BIT_DATA) {
+	if (mmc_card_sd(card) &&
+		(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+
 		/*
-		 * The card is in 1 bit mode by default so
-		 * we only need to change if it supports the
-		 * wider version.
-		 */
-		if (mmc_card_sd(card) &&
-			(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+		* Default bus width is 1 bit.
+		*/
+		host->ios.bus_width = MMC_BUS_WIDTH_1;
+
+		if (host->caps & MMC_CAP_4_BIT_DATA) {
 			struct mmc_command cmd;
 			cmd.opcode = SD_APP_SET_BUS_WIDTH;
 			cmd.arg = SD_BUS_WIDTH_4;
@@ -453,11 +454,11 @@
 
 static inline void mmc_delay(unsigned int ms)
 {
-	if (ms < HZ / 1000) {
-		yield();
+	if (ms < 1000 / HZ) {
+		cond_resched();
 		mdelay(ms);
 	} else {
-		msleep_interruptible (ms);
+		msleep(ms);
 	}
 }
 
@@ -953,6 +954,137 @@
 	}
 }
 
+static void mmc_process_ext_csds(struct mmc_host *host)
+{
+	int err;
+	struct mmc_card *card;
+
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+
+	struct scatterlist sg;
+
+	/*
+	 * As the ext_csd is so large and mostly unused, we don't store the
+	 * raw block in mmc_card.
+	 */
+	u8 *ext_csd;
+	ext_csd = kmalloc(512, GFP_KERNEL);
+	if (!ext_csd) {
+		printk("%s: could not allocate a buffer to receive the ext_csd."
+		       "mmc v4 cards will be treated as v3.\n",
+			mmc_hostname(host));
+		return;
+	}
+
+	list_for_each_entry(card, &host->cards, node) {
+		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
+			continue;
+		if (mmc_card_sd(card))
+			continue;
+		if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+			continue;
+
+		err = mmc_select_card(host, card);
+		if (err != MMC_ERR_NONE) {
+			mmc_card_set_dead(card);
+			continue;
+		}
+
+		memset(&cmd, 0, sizeof(struct mmc_command));
+
+		cmd.opcode = MMC_SEND_EXT_CSD;
+		cmd.arg = 0;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+		memset(&data, 0, sizeof(struct mmc_data));
+
+		mmc_set_data_timeout(&data, card, 0);
+
+		data.blksz = 512;
+		data.blocks = 1;
+		data.flags = MMC_DATA_READ;
+		data.sg = &sg;
+		data.sg_len = 1;
+
+		memset(&mrq, 0, sizeof(struct mmc_request));
+
+		mrq.cmd = &cmd;
+		mrq.data = &data;
+
+		sg_init_one(&sg, ext_csd, 512);
+
+		mmc_wait_for_req(host, &mrq);
+
+		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+			mmc_card_set_dead(card);
+			continue;
+		}
+
+		switch (ext_csd[EXT_CSD_CARD_TYPE]) {
+		case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
+			card->ext_csd.hs_max_dtr = 52000000;
+			break;
+		case EXT_CSD_CARD_TYPE_26:
+			card->ext_csd.hs_max_dtr = 26000000;
+			break;
+		default:
+			/* MMC v4 spec says this cannot happen */
+			printk("%s: card is mmc v4 but doesn't support "
+			       "any high-speed modes.\n",
+				mmc_hostname(card->host));
+			mmc_card_set_bad(card);
+			continue;
+		}
+
+		/* Activate highspeed support. */
+		cmd.opcode = MMC_SWITCH;
+		cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+			  (EXT_CSD_HS_TIMING << 16) |
+			  (1 << 8) |
+			  EXT_CSD_CMD_SET_NORMAL;
+		cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+		if (err != MMC_ERR_NONE) {
+			printk("%s: failed to switch card to mmc v4 "
+			       "high-speed mode.\n",
+			       mmc_hostname(card->host));
+			continue;
+		}
+
+		mmc_card_set_highspeed(card);
+
+		/* Check for host support for wide-bus modes. */
+		if (!(host->caps & MMC_CAP_4_BIT_DATA)) {
+			continue;
+		}
+
+		/* Activate 4-bit support. */
+		cmd.opcode = MMC_SWITCH;
+		cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+			  (EXT_CSD_BUS_WIDTH << 16) |
+			  (EXT_CSD_BUS_WIDTH_4 << 8) |
+			  EXT_CSD_CMD_SET_NORMAL;
+		cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+		if (err != MMC_ERR_NONE) {
+			printk("%s: failed to switch card to "
+			       "mmc v4 4-bit bus mode.\n",
+			       mmc_hostname(card->host));
+			continue;
+		}
+
+		host->ios.bus_width = MMC_BUS_WIDTH_4;
+	}
+
+	kfree(ext_csd);
+
+	mmc_deselect_cards(host);
+}
+
 static void mmc_read_scrs(struct mmc_host *host)
 {
 	int err;
@@ -1025,14 +1157,133 @@
 	mmc_deselect_cards(host);
 }
 
+static void mmc_read_switch_caps(struct mmc_host *host)
+{
+	int err;
+	struct mmc_card *card;
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+	unsigned char *status;
+	struct scatterlist sg;
+
+	status = kmalloc(64, GFP_KERNEL);
+	if (!status) {
+		printk(KERN_WARNING "%s: Unable to allocate buffer for "
+			"reading switch capabilities.\n",
+			mmc_hostname(host));
+		return;
+	}
+
+	list_for_each_entry(card, &host->cards, node) {
+		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
+			continue;
+		if (!mmc_card_sd(card))
+			continue;
+		if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+			continue;
+
+		err = mmc_select_card(host, card);
+		if (err != MMC_ERR_NONE) {
+			mmc_card_set_dead(card);
+			continue;
+		}
+
+		memset(&cmd, 0, sizeof(struct mmc_command));
+
+		cmd.opcode = SD_SWITCH;
+		cmd.arg = 0x00FFFFF1;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+		memset(&data, 0, sizeof(struct mmc_data));
+
+		mmc_set_data_timeout(&data, card, 0);
+
+		data.blksz = 64;
+		data.blocks = 1;
+		data.flags = MMC_DATA_READ;
+		data.sg = &sg;
+		data.sg_len = 1;
+
+		memset(&mrq, 0, sizeof(struct mmc_request));
+
+		mrq.cmd = &cmd;
+		mrq.data = &data;
+
+		sg_init_one(&sg, status, 64);
+
+		mmc_wait_for_req(host, &mrq);
+
+		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+			mmc_card_set_dead(card);
+			continue;
+		}
+
+		if (status[13] & 0x02)
+			card->sw_caps.hs_max_dtr = 50000000;
+
+		memset(&cmd, 0, sizeof(struct mmc_command));
+
+		cmd.opcode = SD_SWITCH;
+		cmd.arg = 0x80FFFFF1;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+		memset(&data, 0, sizeof(struct mmc_data));
+
+		mmc_set_data_timeout(&data, card, 0);
+
+		data.blksz = 64;
+		data.blocks = 1;
+		data.flags = MMC_DATA_READ;
+		data.sg = &sg;
+		data.sg_len = 1;
+
+		memset(&mrq, 0, sizeof(struct mmc_request));
+
+		mrq.cmd = &cmd;
+		mrq.data = &data;
+
+		sg_init_one(&sg, status, 64);
+
+		mmc_wait_for_req(host, &mrq);
+
+		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
+			mmc_card_set_dead(card);
+			continue;
+		}
+
+		if ((status[16] & 0xF) != 1) {
+			printk(KERN_WARNING "%s: Problem switching card "
+				"into high-speed mode!\n",
+				mmc_hostname(host));
+			continue;
+		}
+
+		mmc_card_set_highspeed(card);
+	}
+
+	kfree(status);
+
+	mmc_deselect_cards(host);
+}
+
 static unsigned int mmc_calculate_clock(struct mmc_host *host)
 {
 	struct mmc_card *card;
 	unsigned int max_dtr = host->f_max;
 
 	list_for_each_entry(card, &host->cards, node)
-		if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr)
-			max_dtr = card->csd.max_dtr;
+		if (!mmc_card_dead(card)) {
+			if (mmc_card_highspeed(card) && mmc_card_sd(card)) {
+				if (max_dtr > card->sw_caps.hs_max_dtr)
+					max_dtr = card->sw_caps.hs_max_dtr;
+			} else if (mmc_card_highspeed(card) && !mmc_card_sd(card)) {
+				if (max_dtr > card->ext_csd.hs_max_dtr)
+					max_dtr = card->ext_csd.hs_max_dtr;
+			} else if (max_dtr > card->csd.max_dtr) {
+				max_dtr = card->csd.max_dtr;
+			}
+		}
 
 	pr_debug("%s: selected %d.%03dMHz transfer rate\n",
 		 mmc_hostname(host),
@@ -1150,8 +1401,11 @@
 
 	mmc_read_csds(host);
 
-	if (host->mode == MMC_MODE_SD)
+	if (host->mode == MMC_MODE_SD) {
 		mmc_read_scrs(host);
+		mmc_read_switch_caps(host);
+	} else
+		mmc_process_ext_csds(host);
 }
 
 
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index f9027c8..8771357 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -83,7 +83,6 @@
 	md->usage--;
 	if (md->usage == 0) {
 		put_disk(md->disk);
-		mmc_cleanup_queue(&md->queue);
 		kfree(md);
 	}
 	mutex_unlock(&open_lock);
@@ -225,10 +224,10 @@
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
 	struct mmc_blk_request brq;
-	int ret;
+	int ret = 1;
 
 	if (mmc_card_claim_host(card))
-		goto cmd_err;
+		goto flush_queue;
 
 	do {
 		struct mmc_command cmd;
@@ -345,8 +344,6 @@
 	return 1;
 
  cmd_err:
-	ret = 1;
-
  	/*
  	 * If this is an SD card and we're writing, we can first
  	 * mark the known good sectors as ok.
@@ -380,6 +377,7 @@
 
 	mmc_card_release_host(card);
 
+flush_queue:
 	spin_lock_irq(&md->lock);
 	while (ret) {
 		ret = end_that_request_chunk(req, 0,
@@ -553,12 +551,11 @@
 	if (md) {
 		int devidx;
 
+		/* Stop new requests from getting into the queue */
 		del_gendisk(md->disk);
 
-		/*
-		 * I think this is needed.
-		 */
-		md->disk->queue = NULL;
+		/* Then flush out any already in there */
+		mmc_cleanup_queue(&md->queue);
 
 		devidx = md->disk->first_minor >> MMC_SHIFT;
 		__clear_bit(devidx, dev_use);
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c
index 61a1de8..a17423a 100644
--- a/drivers/mmc/mmc_queue.c
+++ b/drivers/mmc/mmc_queue.c
@@ -10,13 +10,13 @@
  */
 #include <linux/module.h>
 #include <linux/blkdev.h>
+#include <linux/kthread.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include "mmc_queue.h"
 
-#define MMC_QUEUE_EXIT		(1 << 0)
-#define MMC_QUEUE_SUSPENDED	(1 << 1)
+#define MMC_QUEUE_SUSPENDED	(1 << 0)
 
 /*
  * Prepare a MMC request.  Essentially, this means passing the
@@ -59,7 +59,6 @@
 {
 	struct mmc_queue *mq = d;
 	struct request_queue *q = mq->queue;
-	DECLARE_WAITQUEUE(wait, current);
 
 	/*
 	 * Set iothread to ensure that we aren't put to sleep by
@@ -67,12 +66,7 @@
 	 */
 	current->flags |= PF_MEMALLOC|PF_NOFREEZE;
 
-	daemonize("mmcqd");
-
-	complete(&mq->thread_complete);
-
 	down(&mq->thread_sem);
-	add_wait_queue(&mq->thread_wq, &wait);
 	do {
 		struct request *req = NULL;
 
@@ -84,7 +78,7 @@
 		spin_unlock_irq(q->queue_lock);
 
 		if (!req) {
-			if (mq->flags & MMC_QUEUE_EXIT)
+			if (kthread_should_stop())
 				break;
 			up(&mq->thread_sem);
 			schedule();
@@ -95,10 +89,8 @@
 
 		mq->issue_fn(mq, req);
 	} while (1);
-	remove_wait_queue(&mq->thread_wq, &wait);
 	up(&mq->thread_sem);
 
-	complete_and_exit(&mq->thread_complete, 0);
 	return 0;
 }
 
@@ -111,9 +103,22 @@
 static void mmc_request(request_queue_t *q)
 {
 	struct mmc_queue *mq = q->queuedata;
+	struct request *req;
+	int ret;
+
+	if (!mq) {
+		printk(KERN_ERR "MMC: killing requests for dead queue\n");
+		while ((req = elv_next_request(q)) != NULL) {
+			do {
+				ret = end_that_request_chunk(req, 0,
+					req->current_nr_sectors << 9);
+			} while (ret);
+		}
+		return;
+	}
 
 	if (!mq->req)
-		wake_up(&mq->thread_wq);
+		wake_up_process(mq->thread);
 }
 
 /**
@@ -152,36 +157,40 @@
 			 GFP_KERNEL);
 	if (!mq->sg) {
 		ret = -ENOMEM;
-		goto cleanup;
+		goto cleanup_queue;
 	}
 
-	init_completion(&mq->thread_complete);
-	init_waitqueue_head(&mq->thread_wq);
 	init_MUTEX(&mq->thread_sem);
 
-	ret = kernel_thread(mmc_queue_thread, mq, CLONE_KERNEL);
-	if (ret >= 0) {
-		wait_for_completion(&mq->thread_complete);
-		init_completion(&mq->thread_complete);
-		ret = 0;
-		goto out;
+	mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");
+	if (IS_ERR(mq->thread)) {
+		ret = PTR_ERR(mq->thread);
+		goto free_sg;
 	}
 
- cleanup:
+	return 0;
+
+ free_sg:
 	kfree(mq->sg);
 	mq->sg = NULL;
-
+ cleanup_queue:
 	blk_cleanup_queue(mq->queue);
- out:
 	return ret;
 }
 EXPORT_SYMBOL(mmc_init_queue);
 
 void mmc_cleanup_queue(struct mmc_queue *mq)
 {
-	mq->flags |= MMC_QUEUE_EXIT;
-	wake_up(&mq->thread_wq);
-	wait_for_completion(&mq->thread_complete);
+	request_queue_t *q = mq->queue;
+	unsigned long flags;
+
+	/* Mark that we should start throwing out stragglers */
+	spin_lock_irqsave(q->queue_lock, flags);
+	q->queuedata = NULL;
+	spin_unlock_irqrestore(q->queue_lock, flags);
+
+	/* Then terminate our worker thread */
+	kthread_stop(mq->thread);
 
 	kfree(mq->sg);
 	mq->sg = NULL;
diff --git a/drivers/mmc/mmc_queue.h b/drivers/mmc/mmc_queue.h
index 7182d2f..c9f139e 100644
--- a/drivers/mmc/mmc_queue.h
+++ b/drivers/mmc/mmc_queue.h
@@ -6,8 +6,7 @@
 
 struct mmc_queue {
 	struct mmc_card		*card;
-	struct completion	thread_complete;
-	wait_queue_head_t	thread_wq;
+	struct task_struct	*thread;
 	struct semaphore	thread_sem;
 	unsigned int		flags;
 	struct request		*req;
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 828503c..e9b80e9 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -443,7 +443,7 @@
 	}
 }
 
-static struct mmc_host_ops mmci_ops = {
+static const struct mmc_host_ops mmci_ops = {
 	.request	= mmci_request,
 	.set_ios	= mmci_set_ios,
 };
diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c
index d593ef3..435d331 100644
--- a/drivers/mmc/omap.c
+++ b/drivers/mmc/omap.c
@@ -38,7 +38,57 @@
 #include <asm/arch/fpga.h>
 #include <asm/arch/tps65010.h>
 
-#include "omap.h"
+#define	OMAP_MMC_REG_CMD	0x00
+#define	OMAP_MMC_REG_ARGL	0x04
+#define	OMAP_MMC_REG_ARGH	0x08
+#define	OMAP_MMC_REG_CON	0x0c
+#define	OMAP_MMC_REG_STAT	0x10
+#define	OMAP_MMC_REG_IE		0x14
+#define	OMAP_MMC_REG_CTO	0x18
+#define	OMAP_MMC_REG_DTO	0x1c
+#define	OMAP_MMC_REG_DATA	0x20
+#define	OMAP_MMC_REG_BLEN	0x24
+#define	OMAP_MMC_REG_NBLK	0x28
+#define	OMAP_MMC_REG_BUF	0x2c
+#define OMAP_MMC_REG_SDIO	0x34
+#define	OMAP_MMC_REG_REV	0x3c
+#define	OMAP_MMC_REG_RSP0	0x40
+#define	OMAP_MMC_REG_RSP1	0x44
+#define	OMAP_MMC_REG_RSP2	0x48
+#define	OMAP_MMC_REG_RSP3	0x4c
+#define	OMAP_MMC_REG_RSP4	0x50
+#define	OMAP_MMC_REG_RSP5	0x54
+#define	OMAP_MMC_REG_RSP6	0x58
+#define	OMAP_MMC_REG_RSP7	0x5c
+#define	OMAP_MMC_REG_IOSR	0x60
+#define	OMAP_MMC_REG_SYSC	0x64
+#define	OMAP_MMC_REG_SYSS	0x68
+
+#define	OMAP_MMC_STAT_CARD_ERR		(1 << 14)
+#define	OMAP_MMC_STAT_CARD_IRQ		(1 << 13)
+#define	OMAP_MMC_STAT_OCR_BUSY		(1 << 12)
+#define	OMAP_MMC_STAT_A_EMPTY		(1 << 11)
+#define	OMAP_MMC_STAT_A_FULL		(1 << 10)
+#define	OMAP_MMC_STAT_CMD_CRC		(1 <<  8)
+#define	OMAP_MMC_STAT_CMD_TOUT		(1 <<  7)
+#define	OMAP_MMC_STAT_DATA_CRC		(1 <<  6)
+#define	OMAP_MMC_STAT_DATA_TOUT		(1 <<  5)
+#define	OMAP_MMC_STAT_END_BUSY		(1 <<  4)
+#define	OMAP_MMC_STAT_END_OF_DATA	(1 <<  3)
+#define	OMAP_MMC_STAT_CARD_BUSY		(1 <<  2)
+#define	OMAP_MMC_STAT_END_OF_CMD	(1 <<  0)
+
+#define OMAP_MMC_READ(host, reg)	__raw_readw((host)->virt_base + OMAP_MMC_REG_##reg)
+#define OMAP_MMC_WRITE(host, reg, val)	__raw_writew((val), (host)->virt_base + OMAP_MMC_REG_##reg)
+
+/*
+ * Command types
+ */
+#define OMAP_MMC_CMDTYPE_BC	0
+#define OMAP_MMC_CMDTYPE_BCR	1
+#define OMAP_MMC_CMDTYPE_AC	2
+#define OMAP_MMC_CMDTYPE_ADTC	3
+
 
 #define DRIVER_NAME "mmci-omap"
 #define RSP_TYPE(x)	((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
@@ -60,8 +110,9 @@
 	unsigned char		id; /* 16xx chips have 2 MMC blocks */
 	struct clk *		iclk;
 	struct clk *		fclk;
-	struct resource		*res;
-	void __iomem		*base;
+	struct resource		*mem_res;
+	void __iomem		*virt_base;
+	unsigned int		phys_base;
 	int			irq;
 	unsigned char		bus_mode;
 	unsigned char		hw_bus_mode;
@@ -191,16 +242,16 @@
 
 	clk_enable(host->fclk);
 
-	OMAP_MMC_WRITE(host->base, CTO, 200);
-	OMAP_MMC_WRITE(host->base, ARGL, cmd->arg & 0xffff);
-	OMAP_MMC_WRITE(host->base, ARGH, cmd->arg >> 16);
-	OMAP_MMC_WRITE(host->base, IE,
+	OMAP_MMC_WRITE(host, CTO, 200);
+	OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff);
+	OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16);
+	OMAP_MMC_WRITE(host, IE,
 		       OMAP_MMC_STAT_A_EMPTY    | OMAP_MMC_STAT_A_FULL    |
 		       OMAP_MMC_STAT_CMD_CRC    | OMAP_MMC_STAT_CMD_TOUT  |
 		       OMAP_MMC_STAT_DATA_CRC   | OMAP_MMC_STAT_DATA_TOUT |
 		       OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR  |
 		       OMAP_MMC_STAT_END_OF_DATA);
-	OMAP_MMC_WRITE(host->base, CMD, cmdreg);
+	OMAP_MMC_WRITE(host, CMD, cmdreg);
 }
 
 static void
@@ -296,22 +347,22 @@
 		if (cmd->flags & MMC_RSP_136) {
 			/* response type 2 */
 			cmd->resp[3] =
-				OMAP_MMC_READ(host->base, RSP0) |
-				(OMAP_MMC_READ(host->base, RSP1) << 16);
+				OMAP_MMC_READ(host, RSP0) |
+				(OMAP_MMC_READ(host, RSP1) << 16);
 			cmd->resp[2] =
-				OMAP_MMC_READ(host->base, RSP2) |
-				(OMAP_MMC_READ(host->base, RSP3) << 16);
+				OMAP_MMC_READ(host, RSP2) |
+				(OMAP_MMC_READ(host, RSP3) << 16);
 			cmd->resp[1] =
-				OMAP_MMC_READ(host->base, RSP4) |
-				(OMAP_MMC_READ(host->base, RSP5) << 16);
+				OMAP_MMC_READ(host, RSP4) |
+				(OMAP_MMC_READ(host, RSP5) << 16);
 			cmd->resp[0] =
-				OMAP_MMC_READ(host->base, RSP6) |
-				(OMAP_MMC_READ(host->base, RSP7) << 16);
+				OMAP_MMC_READ(host, RSP6) |
+				(OMAP_MMC_READ(host, RSP7) << 16);
 		} else {
 			/* response types 1, 1b, 3, 4, 5, 6 */
 			cmd->resp[0] =
-				OMAP_MMC_READ(host->base, RSP6) |
-				(OMAP_MMC_READ(host->base, RSP7) << 16);
+				OMAP_MMC_READ(host, RSP6) |
+				(OMAP_MMC_READ(host, RSP7) << 16);
 		}
 	}
 
@@ -354,9 +405,9 @@
 	host->data->bytes_xfered += n;
 
 	if (write) {
-		__raw_writesw(host->base + OMAP_MMC_REG_DATA, host->buffer, n);
+		__raw_writesw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n);
 	} else {
-		__raw_readsw(host->base + OMAP_MMC_REG_DATA, host->buffer, n);
+		__raw_readsw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n);
 	}
 }
 
@@ -386,11 +437,11 @@
 	int transfer_error;
 
 	if (host->cmd == NULL && host->data == NULL) {
-		status = OMAP_MMC_READ(host->base, STAT);
+		status = OMAP_MMC_READ(host, STAT);
 		dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status);
 		if (status != 0) {
-			OMAP_MMC_WRITE(host->base, STAT, status);
-			OMAP_MMC_WRITE(host->base, IE, 0);
+			OMAP_MMC_WRITE(host, STAT, status);
+			OMAP_MMC_WRITE(host, IE, 0);
 		}
 		return IRQ_HANDLED;
 	}
@@ -399,8 +450,8 @@
 	end_transfer = 0;
 	transfer_error = 0;
 
-	while ((status = OMAP_MMC_READ(host->base, STAT)) != 0) {
-		OMAP_MMC_WRITE(host->base, STAT, status);
+	while ((status = OMAP_MMC_READ(host, STAT)) != 0) {
+		OMAP_MMC_WRITE(host, STAT, status);
 #ifdef CONFIG_MMC_DEBUG
 		dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ",
 			status, host->cmd != NULL ? host->cmd->opcode : -1);
@@ -470,8 +521,8 @@
 
 		if (status & OMAP_MMC_STAT_CARD_ERR) {
 			if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) {
-				u32 response = OMAP_MMC_READ(host->base, RSP6)
-					| (OMAP_MMC_READ(host->base, RSP7) << 16);
+				u32 response = OMAP_MMC_READ(host, RSP6)
+					| (OMAP_MMC_READ(host, RSP7) << 16);
 				/* STOP sometimes sets must-ignore bits */
 				if (!(response & (R1_CC_ERROR
 								| R1_ILLEGAL_COMMAND
@@ -530,12 +581,6 @@
 	schedule_work(&host->switch_work);
 }
 
-/* FIXME: Handle card insertion and removal properly. Maybe use a mask
- * for MMC state? */
-static void mmc_omap_switch_callback(unsigned long data, u8 mmc_mask)
-{
-}
-
 static void mmc_omap_switch_handler(void *data)
 {
 	struct mmc_omap_host *host = (struct mmc_omap_host *) data;
@@ -581,7 +626,7 @@
 	int dst_port = 0;
 	int sync_dev = 0;
 
-	data_addr = io_v2p((u32) host->base) + OMAP_MMC_REG_DATA;
+	data_addr = host->phys_base + OMAP_MMC_REG_DATA;
 	frame = data->blksz;
 	count = sg_dma_len(sg);
 
@@ -642,7 +687,7 @@
 	/* Max limit for DMA frame count is 0xffff */
 	BUG_ON(count > 0xffff);
 
-	OMAP_MMC_WRITE(host->base, BUF, buf);
+	OMAP_MMC_WRITE(host, BUF, buf);
 	omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16,
 				     frame, count, OMAP_DMA_SYNC_FRAME,
 				     sync_dev, 0);
@@ -727,11 +772,11 @@
 {
 	u16 reg;
 
-	reg = OMAP_MMC_READ(host->base, SDIO);
+	reg = OMAP_MMC_READ(host, SDIO);
 	reg &= ~(1 << 5);
-	OMAP_MMC_WRITE(host->base, SDIO, reg);
+	OMAP_MMC_WRITE(host, SDIO, reg);
 	/* Set maximum timeout */
-	OMAP_MMC_WRITE(host->base, CTO, 0xff);
+	OMAP_MMC_WRITE(host, CTO, 0xff);
 }
 
 static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req)
@@ -745,14 +790,14 @@
 	timeout = req->data->timeout_clks + req->data->timeout_ns / 500;
 
 	/* Check if we need to use timeout multiplier register */
-	reg = OMAP_MMC_READ(host->base, SDIO);
+	reg = OMAP_MMC_READ(host, SDIO);
 	if (timeout > 0xffff) {
 		reg |= (1 << 5);
 		timeout /= 1024;
 	} else
 		reg &= ~(1 << 5);
-	OMAP_MMC_WRITE(host->base, SDIO, reg);
-	OMAP_MMC_WRITE(host->base, DTO, timeout);
+	OMAP_MMC_WRITE(host, SDIO, reg);
+	OMAP_MMC_WRITE(host, DTO, timeout);
 }
 
 static void
@@ -764,19 +809,18 @@
 
 	host->data = data;
 	if (data == NULL) {
-		OMAP_MMC_WRITE(host->base, BLEN, 0);
-		OMAP_MMC_WRITE(host->base, NBLK, 0);
-		OMAP_MMC_WRITE(host->base, BUF, 0);
+		OMAP_MMC_WRITE(host, BLEN, 0);
+		OMAP_MMC_WRITE(host, NBLK, 0);
+		OMAP_MMC_WRITE(host, BUF, 0);
 		host->dma_in_use = 0;
 		set_cmd_timeout(host, req);
 		return;
 	}
 
-
 	block_size = data->blksz;
 
-	OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1);
-	OMAP_MMC_WRITE(host->base, BLEN, block_size - 1);
+	OMAP_MMC_WRITE(host, NBLK, data->blocks - 1);
+	OMAP_MMC_WRITE(host, BLEN, block_size - 1);
 	set_data_timeout(host, req);
 
 	/* cope with calling layer confusion; it issues "single
@@ -818,7 +862,7 @@
 
 	/* Revert to PIO? */
 	if (!use_dma) {
-		OMAP_MMC_WRITE(host->base, BUF, 0x1f1f);
+		OMAP_MMC_WRITE(host, BUF, 0x1f1f);
 		host->total_bytes_left = data->blocks * block_size;
 		host->sg_len = sg_len;
 		mmc_omap_sg_to_buf(host);
@@ -844,7 +888,6 @@
 static void innovator_fpga_socket_power(int on)
 {
 #if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX)
-
 	if (on) {
 		fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3),
 		     OMAP1510_FPGA_POWER);
@@ -870,8 +913,8 @@
 			/* GPIO 4 of TPS65010 sends SD_EN signal */
 			tps65010_set_gpio_out_value(GPIO4, HIGH);
 		else if (cpu_is_omap24xx()) {
-			u16 reg = OMAP_MMC_READ(host->base, CON);
-			OMAP_MMC_WRITE(host->base, CON, reg | (1 << 11));
+			u16 reg = OMAP_MMC_READ(host, CON);
+			OMAP_MMC_WRITE(host, CON, reg | (1 << 11));
 		} else
 			if (host->power_pin >= 0)
 				omap_set_gpio_dataout(host->power_pin, 1);
@@ -883,8 +926,8 @@
 		else if (machine_is_omap_h3())
 			tps65010_set_gpio_out_value(GPIO4, LOW);
 		else if (cpu_is_omap24xx()) {
-			u16 reg = OMAP_MMC_READ(host->base, CON);
-			OMAP_MMC_WRITE(host->base, CON, reg & ~(1 << 11));
+			u16 reg = OMAP_MMC_READ(host, CON);
+			OMAP_MMC_WRITE(host, CON, reg & ~(1 << 11));
 		} else
 			if (host->power_pin >= 0)
 				omap_set_gpio_dataout(host->power_pin, 0);
@@ -926,7 +969,7 @@
 	case MMC_POWER_UP:
 	case MMC_POWER_ON:
 		mmc_omap_power(host, 1);
-		dsor |= 1<<11;
+		dsor |= 1 << 11;
 		break;
 	}
 
@@ -940,14 +983,14 @@
 	 * which results in the while loop below getting stuck.
 	 * Writing to the CON register twice seems to do the trick. */
 	for (i = 0; i < 2; i++)
-		OMAP_MMC_WRITE(host->base, CON, dsor);
+		OMAP_MMC_WRITE(host, CON, dsor);
 	if (ios->power_mode == MMC_POWER_UP) {
 		/* Send clock cycles, poll completion */
-		OMAP_MMC_WRITE(host->base, IE, 0);
-		OMAP_MMC_WRITE(host->base, STAT, 0xffff);
-		OMAP_MMC_WRITE(host->base, CMD, 1<<7);
-		while (0 == (OMAP_MMC_READ(host->base, STAT) & 1));
-		OMAP_MMC_WRITE(host->base, STAT, 1);
+		OMAP_MMC_WRITE(host, IE, 0);
+		OMAP_MMC_WRITE(host, STAT, 0xffff);
+		OMAP_MMC_WRITE(host, CMD, 1 << 7);
+		while ((OMAP_MMC_READ(host, STAT) & 1) == 0);
+		OMAP_MMC_WRITE(host, STAT, 1);
 	}
 	clk_disable(host->fclk);
 }
@@ -959,7 +1002,7 @@
 	return host->wp_pin && omap_get_gpio_datain(host->wp_pin);
 }
 
-static struct mmc_host_ops mmc_omap_ops = {
+static const struct mmc_host_ops mmc_omap_ops = {
 	.request	= mmc_omap_request,
 	.set_ios	= mmc_omap_set_ios,
 	.get_ro		= mmc_omap_get_ro,
@@ -970,25 +1013,29 @@
 	struct omap_mmc_conf *minfo = pdev->dev.platform_data;
 	struct mmc_host *mmc;
 	struct mmc_omap_host *host = NULL;
-	struct resource *r;
+	struct resource *res;
 	int ret = 0;
 	int irq;
-	
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (minfo == NULL) {
+		dev_err(&pdev->dev, "platform data missing\n");
+		return -ENXIO;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_irq(pdev, 0);
-	if (!r || irq < 0)
+	if (res == NULL || irq < 0)
 		return -ENXIO;
 
-	r = request_mem_region(pdev->resource[0].start,
-				pdev->resource[0].end - pdev->resource[0].start + 1,
-			       pdev->name);
-	if (!r)
+	res = request_mem_region(res->start, res->end - res->start + 1,
+			         pdev->name);
+	if (res == NULL)
 		return -EBUSY;
 
 	mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
-	if (!mmc) {
+	if (mmc == NULL) {
 		ret = -ENOMEM;
-		goto out;
+		goto err_free_mem_region;
 	}
 
 	host = mmc_priv(mmc);
@@ -1000,13 +1047,13 @@
 	host->dma_timer.data = (unsigned long) host;
 
 	host->id = pdev->id;
-	host->res = r;
+	host->mem_res = res;
 	host->irq = irq;
 
 	if (cpu_is_omap24xx()) {
 		host->iclk = clk_get(&pdev->dev, "mmc_ick");
 		if (IS_ERR(host->iclk))
-			goto out;
+			goto err_free_mmc_host;
 		clk_enable(host->iclk);
 	}
 
@@ -1017,7 +1064,7 @@
 
 	if (IS_ERR(host->fclk)) {
 		ret = PTR_ERR(host->fclk);
-		goto out;
+		goto err_free_iclk;
 	}
 
 	/* REVISIT:
@@ -1030,14 +1077,15 @@
 	host->use_dma = 1;
 	host->dma_ch = -1;
 
-	host->irq = pdev->resource[1].start;
-	host->base = (void __iomem*)IO_ADDRESS(r->start);
+	host->irq = irq;
+	host->phys_base = host->mem_res->start;
+	host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base);
 
 	mmc->ops = &mmc_omap_ops;
 	mmc->f_min = 400000;
 	mmc->f_max = 24000000;
-	mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
-	mmc->caps = MMC_CAP_BYTEBLOCK;
+	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+	mmc->caps = MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK;
 
 	if (minfo->wire4)
 		 mmc->caps |= MMC_CAP_4_BIT_DATA;
@@ -1055,20 +1103,18 @@
 		if ((ret = omap_request_gpio(host->power_pin)) != 0) {
 			dev_err(mmc_dev(host->mmc),
 				"Unable to get GPIO pin for MMC power\n");
-			goto out;
+			goto err_free_fclk;
 		}
 		omap_set_gpio_direction(host->power_pin, 0);
 	}
 
 	ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host);
 	if (ret)
-		goto out;
+		goto err_free_power_gpio;
 
 	host->dev = &pdev->dev;
 	platform_set_drvdata(pdev, host);
 
-	mmc_add_host(mmc);
-
 	if (host->switch_pin >= 0) {
 		INIT_WORK(&host->switch_work, mmc_omap_switch_handler, host);
 		init_timer(&host->switch_timer);
@@ -1106,10 +1152,11 @@
 			schedule_work(&host->switch_work);
 	}
 
-no_switch:
+	mmc_add_host(mmc);
+
 	return 0;
 
-out:
+no_switch:
 	/* FIXME: Free other resources too. */
 	if (host) {
 		if (host->iclk && !IS_ERR(host->iclk))
@@ -1118,6 +1165,20 @@
 			clk_put(host->fclk);
 		mmc_free_host(host->mmc);
 	}
+err_free_power_gpio:
+	if (host->power_pin >= 0)
+		omap_free_gpio(host->power_pin);
+err_free_fclk:
+	clk_put(host->fclk);
+err_free_iclk:
+	if (host->iclk != NULL) {
+		clk_disable(host->iclk);
+		clk_put(host->iclk);
+	}
+err_free_mmc_host:
+	mmc_free_host(host->mmc);
+err_free_mem_region:
+	release_mem_region(res->start, res->end - res->start + 1);
 	return ret;
 }
 
@@ -1127,30 +1188,31 @@
 
 	platform_set_drvdata(pdev, NULL);
 
-	if (host) {
-		mmc_remove_host(host->mmc);
-		free_irq(host->irq, host);
+	BUG_ON(host == NULL);
 
-		if (host->power_pin >= 0)
-			omap_free_gpio(host->power_pin);
-		if (host->switch_pin >= 0) {
-			device_remove_file(&pdev->dev, &dev_attr_enable_poll);
-			device_remove_file(&pdev->dev, &dev_attr_cover_switch);
-			free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
-			omap_free_gpio(host->switch_pin);
-			host->switch_pin = -1;
-			del_timer_sync(&host->switch_timer);
-			flush_scheduled_work();
-		}
-		if (host->iclk && !IS_ERR(host->iclk))
-			clk_put(host->iclk);
-		if (host->fclk && !IS_ERR(host->fclk))
-			clk_put(host->fclk);
-		mmc_free_host(host->mmc);
+	mmc_remove_host(host->mmc);
+	free_irq(host->irq, host);
+
+	if (host->power_pin >= 0)
+		omap_free_gpio(host->power_pin);
+	if (host->switch_pin >= 0) {
+		device_remove_file(&pdev->dev, &dev_attr_enable_poll);
+		device_remove_file(&pdev->dev, &dev_attr_cover_switch);
+		free_irq(OMAP_GPIO_IRQ(host->switch_pin), host);
+		omap_free_gpio(host->switch_pin);
+		host->switch_pin = -1;
+		del_timer_sync(&host->switch_timer);
+		flush_scheduled_work();
 	}
+	if (host->iclk && !IS_ERR(host->iclk))
+		clk_put(host->iclk);
+	if (host->fclk && !IS_ERR(host->fclk))
+		clk_put(host->fclk);
 
 	release_mem_region(pdev->resource[0].start,
-			pdev->resource[0].end - pdev->resource[0].start + 1);
+			   pdev->resource[0].end - pdev->resource[0].start + 1);
+
+	mmc_free_host(host->mmc);
 
 	return 0;
 }
diff --git a/drivers/mmc/omap.h b/drivers/mmc/omap.h
deleted file mode 100644
index c954d35..0000000
--- a/drivers/mmc/omap.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef	DRIVERS_MEDIA_MMC_OMAP_H
-#define	DRIVERS_MEDIA_MMC_OMAP_H
-
-#define	OMAP_MMC_REG_CMD	0x00
-#define	OMAP_MMC_REG_ARGL	0x04
-#define	OMAP_MMC_REG_ARGH	0x08
-#define	OMAP_MMC_REG_CON	0x0c
-#define	OMAP_MMC_REG_STAT	0x10
-#define	OMAP_MMC_REG_IE		0x14
-#define	OMAP_MMC_REG_CTO	0x18
-#define	OMAP_MMC_REG_DTO	0x1c
-#define	OMAP_MMC_REG_DATA	0x20
-#define	OMAP_MMC_REG_BLEN	0x24
-#define	OMAP_MMC_REG_NBLK	0x28
-#define	OMAP_MMC_REG_BUF	0x2c
-#define OMAP_MMC_REG_SDIO	0x34
-#define	OMAP_MMC_REG_REV	0x3c
-#define	OMAP_MMC_REG_RSP0	0x40
-#define	OMAP_MMC_REG_RSP1	0x44
-#define	OMAP_MMC_REG_RSP2	0x48
-#define	OMAP_MMC_REG_RSP3	0x4c
-#define	OMAP_MMC_REG_RSP4	0x50
-#define	OMAP_MMC_REG_RSP5	0x54
-#define	OMAP_MMC_REG_RSP6	0x58
-#define	OMAP_MMC_REG_RSP7	0x5c
-#define	OMAP_MMC_REG_IOSR	0x60
-#define	OMAP_MMC_REG_SYSC	0x64
-#define	OMAP_MMC_REG_SYSS	0x68
-
-#define	OMAP_MMC_STAT_CARD_ERR		(1 << 14)
-#define	OMAP_MMC_STAT_CARD_IRQ		(1 << 13)
-#define	OMAP_MMC_STAT_OCR_BUSY		(1 << 12)
-#define	OMAP_MMC_STAT_A_EMPTY		(1 << 11)
-#define	OMAP_MMC_STAT_A_FULL		(1 << 10)
-#define	OMAP_MMC_STAT_CMD_CRC		(1 <<  8)
-#define	OMAP_MMC_STAT_CMD_TOUT		(1 <<  7)
-#define	OMAP_MMC_STAT_DATA_CRC		(1 <<  6)
-#define	OMAP_MMC_STAT_DATA_TOUT		(1 <<  5)
-#define	OMAP_MMC_STAT_END_BUSY		(1 <<  4)
-#define	OMAP_MMC_STAT_END_OF_DATA	(1 <<  3)
-#define	OMAP_MMC_STAT_CARD_BUSY		(1 <<  2)
-#define	OMAP_MMC_STAT_END_OF_CMD	(1 <<  0)
-
-#define OMAP_MMC_READ(base, reg)	__raw_readw((base) + OMAP_MMC_REG_##reg)
-#define OMAP_MMC_WRITE(base, reg, val)	__raw_writew((val), (base) + OMAP_MMC_REG_##reg)
-
-/*
- * Command types
- */
-#define OMAP_MMC_CMDTYPE_BC	0
-#define OMAP_MMC_CMDTYPE_BCR	1
-#define OMAP_MMC_CMDTYPE_AC	2
-#define OMAP_MMC_CMDTYPE_ADTC	3
-
-#endif
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index a526698..471e9f4 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -393,7 +393,7 @@
 		 host->clkrt, host->cmdat);
 }
 
-static struct mmc_host_ops pxamci_ops = {
+static const struct mmc_host_ops pxamci_ops = {
 	.request	= pxamci_request,
 	.get_ro		= pxamci_get_ro,
 	.set_ios	= pxamci_set_ios,
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 9a7d39b..cd98117 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -616,6 +616,7 @@
 static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 {
 	int div;
+	u8 ctrl;
 	u16 clk;
 	unsigned long timeout;
 
@@ -624,6 +625,13 @@
 
 	writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
 
+	ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL);
+	if (clock > 25000000)
+		ctrl |= SDHCI_CTRL_HISPD;
+	else
+		ctrl &= ~SDHCI_CTRL_HISPD;
+	writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+
 	if (clock == 0)
 		goto out;
 
@@ -784,7 +792,7 @@
 	return !(present & SDHCI_WRITE_PROTECT);
 }
 
-static struct mmc_host_ops sdhci_ops = {
+static const struct mmc_host_ops sdhci_ops = {
 	.request	= sdhci_request,
 	.set_ios	= sdhci_set_ios,
 	.get_ro		= sdhci_get_ro,
@@ -1291,6 +1299,13 @@
 	else if (caps & SDHCI_CAN_VDD_180)
 		mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
 
+	if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) {
+		printk(KERN_ERR "%s: Controller reports > 25 MHz base clock,"
+			" but no high speed support.\n",
+			host->slot_descr);
+		mmc->f_max = 25000000;
+	}
+
 	if (mmc->ocr_avail == 0) {
 		printk(KERN_ERR "%s: Hardware doesn't report any "
 			"support voltages.\n", host->slot_descr);
diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/sdhci.h
index 72a6793..f9d1a0a 100644
--- a/drivers/mmc/sdhci.h
+++ b/drivers/mmc/sdhci.h
@@ -71,6 +71,7 @@
 #define SDHCI_HOST_CONTROL 	0x28
 #define  SDHCI_CTRL_LED		0x01
 #define  SDHCI_CTRL_4BITBUS	0x02
+#define  SDHCI_CTRL_HISPD	0x04
 
 #define SDHCI_POWER_CONTROL	0x29
 #define  SDHCI_POWER_ON		0x01
@@ -138,6 +139,7 @@
 #define  SDHCI_CLOCK_BASE_SHIFT	8
 #define  SDHCI_MAX_BLOCK_MASK	0x00030000
 #define  SDHCI_MAX_BLOCK_SHIFT  16
+#define  SDHCI_CAN_DO_HISPD	0x00200000
 #define  SDHCI_CAN_DO_DMA	0x00400000
 #define  SDHCI_CAN_VDD_330	0x01000000
 #define  SDHCI_CAN_VDD_300	0x02000000
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 682e62b..7a28267 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -1021,7 +1021,7 @@
 	return csr & WBSD_WRPT;
 }
 
-static struct mmc_host_ops wbsd_ops = {
+static const struct mmc_host_ops wbsd_ops = {
 	.request	= wbsd_request,
 	.set_ios	= wbsd_set_ios,
 	.get_ro		= wbsd_get_ro,
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 991a373..d0e6a54 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -39,6 +39,10 @@
 				write_misalign:1;
 };
 
+struct mmc_ext_csd {
+	unsigned int		hs_max_dtr;
+};
+
 struct sd_scr {
 	unsigned char		sda_vsn;
 	unsigned char		bus_widths;
@@ -46,6 +50,10 @@
 #define SD_SCR_BUS_WIDTH_4	(1<<2)
 };
 
+struct sd_switch_caps {
+	unsigned int		hs_max_dtr;
+};
+
 struct mmc_host;
 
 /*
@@ -62,12 +70,15 @@
 #define MMC_STATE_BAD		(1<<2)		/* unrecognised device */
 #define MMC_STATE_SDCARD	(1<<3)		/* is an SD card */
 #define MMC_STATE_READONLY	(1<<4)		/* card is read-only */
+#define MMC_STATE_HIGHSPEED	(1<<5)		/* card is in high speed mode */
 	u32			raw_cid[4];	/* raw card CID */
 	u32			raw_csd[4];	/* raw card CSD */
 	u32			raw_scr[2];	/* raw card SCR */
 	struct mmc_cid		cid;		/* card identification */
 	struct mmc_csd		csd;		/* card specific */
+	struct mmc_ext_csd	ext_csd;	/* mmc v4 extended card specific */
 	struct sd_scr		scr;		/* extra SD information */
+	struct sd_switch_caps	sw_caps;	/* switch (CMD6) caps */
 };
 
 #define mmc_card_present(c)	((c)->state & MMC_STATE_PRESENT)
@@ -75,12 +86,14 @@
 #define mmc_card_bad(c)		((c)->state & MMC_STATE_BAD)
 #define mmc_card_sd(c)		((c)->state & MMC_STATE_SDCARD)
 #define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
+#define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_dead(c)	((c)->state |= MMC_STATE_DEAD)
 #define mmc_card_set_bad(c)	((c)->state |= MMC_STATE_BAD)
 #define mmc_card_set_sd(c)	((c)->state |= MMC_STATE_SDCARD)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
+#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
 
 #define mmc_card_name(c)	((c)->cid.prod_name)
 #define mmc_card_id(c)		((c)->dev.bus_id)
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
index 08dec8d..2dce60c 100644
--- a/include/linux/mmc/protocol.h
+++ b/include/linux/mmc/protocol.h
@@ -25,14 +25,16 @@
 #ifndef MMC_MMC_PROTOCOL_H
 #define MMC_MMC_PROTOCOL_H
 
-/* Standard MMC commands (3.1)           type  argument     response */
+/* Standard MMC commands (4.1)           type  argument     response */
    /* class 1 */
 #define	MMC_GO_IDLE_STATE         0   /* bc                          */
 #define MMC_SEND_OP_COND          1   /* bcr  [31:0] OCR         R3  */
 #define MMC_ALL_SEND_CID          2   /* bcr                     R2  */
 #define MMC_SET_RELATIVE_ADDR     3   /* ac   [31:16] RCA        R1  */
 #define MMC_SET_DSR               4   /* bc   [31:16] RCA            */
+#define MMC_SWITCH                6   /* ac   [31:0] See below   R1b */
 #define MMC_SELECT_CARD           7   /* ac   [31:16] RCA        R1  */
+#define MMC_SEND_EXT_CSD          8   /* adtc                    R1  */
 #define MMC_SEND_CSD              9   /* ac   [31:16] RCA        R2  */
 #define MMC_SEND_CID             10   /* ac   [31:16] RCA        R2  */
 #define MMC_READ_DAT_UNTIL_STOP  11   /* adtc [31:0] dadr        R1  */
@@ -80,6 +82,7 @@
   /* class 8 */
 /* This is basically the same command as for MMC with some quirks. */
 #define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
+#define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */
 
   /* Application commands */
 #define SD_APP_SET_BUS_WIDTH      6   /* ac   [1:0] bus width    R1  */
@@ -88,6 +91,30 @@
 #define SD_APP_SEND_SCR          51   /* adtc                    R1  */
 
 /*
+ * MMC_SWITCH argument format:
+ *
+ *	[31:26] Always 0
+ *	[25:24] Access Mode
+ *	[23:16] Location of target Byte in EXT_CSD
+ *	[15:08] Value Byte
+ *	[07:03] Always 0
+ *	[02:00] Command Set
+ */
+
+/*
+ * SD_SWITCH argument format:
+ *
+ *      [31] Check (0) or switch (1)
+ *      [30:24] Reserved (0)
+ *      [23:20] Function group 6
+ *      [19:16] Function group 5
+ *      [15:12] Function group 4
+ *      [11:8] Function group 3
+ *      [7:4] Function group 2
+ *      [3:0] Function group 1
+ */
+
+/*
   MMC status in R1
   Type
   	e : error bit
@@ -230,13 +257,54 @@
 
 #define CSD_STRUCT_VER_1_0  0           /* Valid for system specification 1.0 - 1.2 */
 #define CSD_STRUCT_VER_1_1  1           /* Valid for system specification 1.4 - 2.2 */
-#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1       */
+#define CSD_STRUCT_VER_1_2  2           /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
+#define CSD_STRUCT_EXT_CSD  3           /* Version is coded in CSD_STRUCTURE in EXT_CSD */
 
 #define CSD_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.2 */
 #define CSD_SPEC_VER_1      1           /* Implements system specification 1.4 */
 #define CSD_SPEC_VER_2      2           /* Implements system specification 2.0 - 2.2 */
-#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 */
+#define CSD_SPEC_VER_3      3           /* Implements system specification 3.1 - 3.2 - 3.31 */
+#define CSD_SPEC_VER_4      4           /* Implements system specification 4.0 - 4.1 */
 
+/*
+ * EXT_CSD fields
+ */
+
+#define EXT_CSD_BUS_WIDTH	183	/* R/W */
+#define EXT_CSD_HS_TIMING	185	/* R/W */
+#define EXT_CSD_CARD_TYPE	196	/* RO */
+
+/*
+ * EXT_CSD field definitions
+ */
+
+#define EXT_CSD_CMD_SET_NORMAL		(1<<0)
+#define EXT_CSD_CMD_SET_SECURE		(1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
+
+#define EXT_CSD_CARD_TYPE_26	(1<<0)	/* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52	(1<<1)	/* Card can run at 52MHz */
+
+#define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8	2	/* Card is in 8 bit mode */
+
+/*
+ * MMC_SWITCH access modes
+ */
+
+#define MMC_SWITCH_MODE_CMD_SET		0x00	/* Change the command set */
+#define MMC_SWITCH_MODE_SET_BITS	0x01	/* Set bits which are 1 in value */
+#define MMC_SWITCH_MODE_CLEAR_BITS	0x02	/* Clear bits which are 1 in value */
+#define MMC_SWITCH_MODE_WRITE_BYTE	0x03	/* Set target to value */
+
+/*
+ * SCR field definitions
+ */
+
+#define SCR_SPEC_VER_0      0           /* Implements system specification 1.0 - 1.01 */
+#define SCR_SPEC_VER_1      1           /* Implements system specification 1.10 */
+#define SCR_SPEC_VER_2      2           /* Implements system specification 2.00 */
 
 /*
  * SD bus widths