diff -Naur kernel-source-2.6.16.27.old/arch/arm/mach-omap1/board-nokia770-mmc.c kernel-source-2.6.16.27/arch/arm/mach-omap1/board-nokia770-mmc.c
--- kernel-source-2.6.16.27.old/arch/arm/mach-omap1/board-nokia770-mmc.c	2006-09-19 15:07:36.000000000 +0200
+++ kernel-source-2.6.16.27/arch/arm/mach-omap1/board-nokia770-mmc.c	2006-11-11 14:05:44.000000000 +0100
@@ -138,7 +138,7 @@
 	.enabled		= 1,
 	.nr_slots		= 1,
 	.wire4			= 0,
-	.max_freq		= 12000000,
+	.max_freq		= 48000000,
 	.init			= nokia770_mmc_late_init,
 	.cleanup		= nokia770_mmc_cleanup,
 	.slots[0] = {
diff -Naur kernel-source-2.6.16.27.old/drivers/mmc/mmc.c kernel-source-2.6.16.27/drivers/mmc/mmc.c
--- kernel-source-2.6.16.27.old/drivers/mmc/mmc.c	2006-09-19 15:07:44.000000000 +0200
+++ kernel-source-2.6.16.27/drivers/mmc/mmc.c	2006-11-11 14:02:14.000000000 +0100
@@ -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
@@ -905,6 +906,109 @@
 	}
 }
 
+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[512];
+
+	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.timeout_ns = card->csd.tacc_ns * 10;
+		data.timeout_clks = card->csd.tacc_clks * 10;
+
+		data.blksz_bits = 9;
+		data.blksz = 1 << 9;
+		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);
+			/* printk a warning */
+			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);
+	}
+
+	mmc_deselect_cards(host);
+}
+
 static void mmc_read_scrs(struct mmc_host *host)
 {
 	int err;
@@ -986,8 +1090,14 @@
 	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)) {
+				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),
@@ -1115,6 +1225,8 @@
 
 	if (host->mode == MMC_MODE_SD)
 		mmc_read_scrs(host);
+	else
+		mmc_process_ext_csds(host);
 }
 
 
diff -Naur kernel-source-2.6.16.27.old/drivers/mmc/mmc_block.c kernel-source-2.6.16.27/drivers/mmc/mmc_block.c
--- kernel-source-2.6.16.27.old/drivers/mmc/mmc_block.c	2006-09-19 15:07:44.000000000 +0200
+++ kernel-source-2.6.16.27/drivers/mmc/mmc_block.c	2006-11-12 14:43:13.000000000 +0100
@@ -33,6 +33,7 @@
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -166,6 +167,7 @@
 	do {
 		struct mmc_blk_request brq;
 		struct mmc_command cmd;
+		u32 readcmd, writecmd;
 		int loop_count = 0, poll_count = 0;
 
 		memset(&brq, 0, sizeof(struct mmc_blk_request));
@@ -183,13 +185,31 @@
 		brq.stop.arg = 0;
 		brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
 
+		/*
+		 * If the host doesn't support multiple block writes, force
+		 * block writes to single block.
+		 */
+		if (rq_data_dir(req) != READ &&
+		    !(card->host->caps & MMC_CAP_MULTI_WRITE))
+			brq.data.blocks = 1;
+
+		if (brq.data.blocks > 1) {
+			brq.data.flags |= MMC_DATA_MULTI;
+			brq.mrq.stop = &brq.stop;
+			readcmd = MMC_READ_MULTIPLE_BLOCK;
+			writecmd = MMC_WRITE_MULTIPLE_BLOCK;
+		} else {
+			brq.mrq.stop = NULL;
+			readcmd = MMC_READ_SINGLE_BLOCK;
+			writecmd = MMC_WRITE_BLOCK;
+		}
+
 		if (rq_data_dir(req) == READ) {
-			brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
+			brq.cmd.opcode = readcmd;
 			brq.data.flags |= MMC_DATA_READ;
 		} else {
-			brq.cmd.opcode = MMC_WRITE_BLOCK;
+			brq.cmd.opcode = writecmd;
 			brq.data.flags |= MMC_DATA_WRITE;
-			brq.data.blocks = 1;
 
 			/*
 			 * Scale up the timeout by the r2w factor
@@ -198,13 +218,6 @@
 			brq.data.timeout_clks <<= card->csd.r2w_factor;
 		}
 
-		if (brq.data.blocks > 1) {
-			brq.data.flags |= MMC_DATA_MULTI;
-			brq.mrq.stop = &brq.stop;
-		} else {
-			brq.mrq.stop = NULL;
-		}
-
 		brq.data.sg = mq->sg;
 		brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
 
diff -Naur kernel-source-2.6.16.27.old/drivers/mmc/omap.c kernel-source-2.6.16.27/drivers/mmc/omap.c
--- kernel-source-2.6.16.27.old/drivers/mmc/omap.c	2006-09-19 15:07:44.000000000 +0200
+++ kernel-source-2.6.16.27/drivers/mmc/omap.c	2006-11-13 22:07:28.000000000 +0100
@@ -1113,12 +1113,13 @@
 	if (host->pdata->wire4)
 		mmc->caps |= MMC_CAP_4_BIT_DATA;
 
+//	mmc->caps |= MMC_CAP_MULTI_WRITE;
 	mmc->ops = &mmc_omap_ops;
 	mmc->f_min = 400000;
-	if (cpu_class_is_omap2())
+//	if (cpu_class_is_omap2())
 		mmc->f_max = 48000000;
-	else
-		mmc->f_max = 24000000;
+//	else
+//		mmc->f_max = 24000000;
 	if (host->pdata->max_freq)
 		mmc->f_max = min(host->pdata->max_freq, mmc->f_max);
 	mmc->ocr_avail = slot->pdata->ocr_mask;
diff -Naur kernel-source-2.6.16.27.old/include/linux/mmc/card.h kernel-source-2.6.16.27/include/linux/mmc/card.h
--- kernel-source-2.6.16.27.old/include/linux/mmc/card.h	2006-09-19 15:07:52.000000000 +0200
+++ kernel-source-2.6.16.27/include/linux/mmc/card.h	2006-11-11 13:45:54.000000000 +0100
@@ -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;
@@ -62,11 +66,13 @@
 #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 mmc4 highspeed 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 */
 };
 
@@ -75,12 +81,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 -Naur kernel-source-2.6.16.27.old/include/linux/mmc/host.h kernel-source-2.6.16.27/include/linux/mmc/host.h
--- kernel-source-2.6.16.27.old/include/linux/mmc/host.h	2006-09-19 15:07:52.000000000 +0200
+++ kernel-source-2.6.16.27/include/linux/mmc/host.h	2006-11-12 14:44:12.000000000 +0100
@@ -85,6 +85,7 @@
 	unsigned long		caps;		/* Host capabilities */
 
 #define MMC_CAP_4_BIT_DATA	(1 << 0)	/* Can the host do 4 bit transfers */
+#define MMC_CAP_MULTI_WRITE	(1 << 1)	/* Can do multiple block writes */
 
 	/* host specific block data */
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
diff -Naur kernel-source-2.6.16.27.old/include/linux/mmc/protocol.h kernel-source-2.6.16.27/include/linux/mmc/protocol.h
--- kernel-source-2.6.16.27.old/include/linux/mmc/protocol.h	2006-09-19 15:07:52.000000000 +0200
+++ kernel-source-2.6.16.27/include/linux/mmc/protocol.h	2006-11-11 13:45:54.000000000 +0100
@@ -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  */
@@ -87,6 +89,17 @@
 #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
+ */
+
+/*
   MMC status in R1
   Type
   	e : error bit
@@ -229,13 +242,41 @@
 
 #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_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 */
+
+/*
+ * 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 */
 
 /*
  * SD bus widths
