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

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc: (46 commits)
  mmc-omap: Clean up omap set_ios and make MMC_POWER_ON work
  mmc-omap: Fix omap to use MMC_POWER_ON
  mmc-omap: add missing '\n'
  mmc: make tifm_sd_set_dma_data() static
  mmc: remove old card states
  mmc: support unsafe resume of cards
  mmc: separate out reading EXT_CSD
  mmc: break apart switch function
  MMC: Fix handling of low-voltage cards
  MMC: Consolidate voltage definitions
  mmc: add bus handler
  wbsd: check for data opcode earlier
  mmc: Separate out protocol ops
  mmc: Move core functions to subdir
  mmc: deprecate mmc bus topology
  mmc: remove card upon suspend
  mmc: allow suspended block driver to be removed
  mmc: Flush pending detects on host removal
  mmc: Move host and card drivers to subdirs
  mmc: Move queue functions to mmc_block
  ...
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index bc60e2f..1ba6c08 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -11,10 +11,20 @@
 
 #include <linux/tifm.h>
 #include <linux/dma-mapping.h>
-#include <linux/freezer.h>
 
 #define DRIVER_NAME "tifm_7xx1"
-#define DRIVER_VERSION "0.7"
+#define DRIVER_VERSION "0.8"
+
+#define TIFM_IRQ_ENABLE           0x80000000
+#define TIFM_IRQ_SOCKMASK(x)      (x)
+#define TIFM_IRQ_CARDMASK(x)      ((x) << 8)
+#define TIFM_IRQ_FIFOMASK(x)      ((x) << 16)
+#define TIFM_IRQ_SETALL           0xffffffff
+
+static void tifm_7xx1_dummy_eject(struct tifm_adapter *fm,
+				  struct tifm_dev *sock)
+{
+}
 
 static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock)
 {
@@ -22,7 +32,7 @@
 
 	spin_lock_irqsave(&fm->lock, flags);
 	fm->socket_change_set |= 1 << sock->socket_id;
-	wake_up_all(&fm->change_set_notify);
+	tifm_queue_work(&fm->media_switcher);
 	spin_unlock_irqrestore(&fm->lock, flags);
 }
 
@@ -30,8 +40,7 @@
 {
 	struct tifm_adapter *fm = dev_id;
 	struct tifm_dev *sock;
-	unsigned int irq_status;
-	unsigned int sock_irq_status, cnt;
+	unsigned int irq_status, cnt;
 
 	spin_lock(&fm->lock);
 	irq_status = readl(fm->addr + FM_INTERRUPT_STATUS);
@@ -45,12 +54,12 @@
 
 		for (cnt = 0; cnt < fm->num_sockets; cnt++) {
 			sock = fm->sockets[cnt];
-			sock_irq_status = (irq_status >> cnt)
-					  & (TIFM_IRQ_FIFOMASK(1)
-					     | TIFM_IRQ_CARDMASK(1));
-
-			if (sock && sock_irq_status)
-				sock->signal_irq(sock, sock_irq_status);
+			if (sock) {
+				if ((irq_status >> cnt) & TIFM_IRQ_FIFOMASK(1))
+					sock->data_event(sock);
+				if ((irq_status >> cnt) & TIFM_IRQ_CARDMASK(1))
+					sock->card_event(sock);
+			}
 		}
 
 		fm->socket_change_set |= irq_status
@@ -58,57 +67,57 @@
 	}
 	writel(irq_status, fm->addr + FM_INTERRUPT_STATUS);
 
-	if (!fm->socket_change_set)
+	if (fm->finish_me)
+		complete_all(fm->finish_me);
+	else if (!fm->socket_change_set)
 		writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
 	else
-		wake_up_all(&fm->change_set_notify);
+		tifm_queue_work(&fm->media_switcher);
 
 	spin_unlock(&fm->lock);
 	return IRQ_HANDLED;
 }
 
-static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr,
-						 int is_x2)
+static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr)
 {
 	unsigned int s_state;
 	int cnt;
 
 	writel(0x0e00, sock_addr + SOCK_CONTROL);
 
-	for (cnt = 0; cnt < 100; cnt++) {
+	for (cnt = 16; cnt <= 256; cnt <<= 1) {
 		if (!(TIFM_SOCK_STATE_POWERED
 		      & readl(sock_addr + SOCK_PRESENT_STATE)))
 			break;
-		msleep(10);
+
+		msleep(cnt);
 	}
 
 	s_state = readl(sock_addr + SOCK_PRESENT_STATE);
 	if (!(TIFM_SOCK_STATE_OCCUPIED & s_state))
-		return FM_NULL;
+		return 0;
 
-	if (is_x2) {
-		writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL);
-	} else {
-		// SmartMedia cards need extra 40 msec
-		if (((readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7) == 1)
-			msleep(40);
-		writel(readl(sock_addr + SOCK_CONTROL) | TIFM_CTRL_LED,
-		       sock_addr + SOCK_CONTROL);
-		msleep(10);
-		writel((s_state & 0x7) | 0x0c00 | TIFM_CTRL_LED,
-			sock_addr + SOCK_CONTROL);
-	}
+	writel(readl(sock_addr + SOCK_CONTROL) | TIFM_CTRL_LED,
+	       sock_addr + SOCK_CONTROL);
 
-	for (cnt = 0; cnt < 100; cnt++) {
+	/* xd needs some extra time before power on */
+	if (((readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7)
+	    == TIFM_TYPE_XD)
+		msleep(40);
+
+	writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL);
+	/* wait for power to stabilize */
+	msleep(20);
+	for (cnt = 16; cnt <= 256; cnt <<= 1) {
 		if ((TIFM_SOCK_STATE_POWERED
 		     & readl(sock_addr + SOCK_PRESENT_STATE)))
 			break;
-		msleep(10);
+
+		msleep(cnt);
 	}
 
-	if (!is_x2)
-		writel(readl(sock_addr + SOCK_CONTROL) & (~TIFM_CTRL_LED),
-		       sock_addr + SOCK_CONTROL);
+	writel(readl(sock_addr + SOCK_CONTROL) & (~TIFM_CTRL_LED),
+	       sock_addr + SOCK_CONTROL);
 
 	return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7;
 }
@@ -119,127 +128,77 @@
 	return base_addr + ((sock_num + 1) << 10);
 }
 
-static int tifm_7xx1_switch_media(void *data)
+static void tifm_7xx1_switch_media(struct work_struct *work)
 {
-	struct tifm_adapter *fm = data;
-	unsigned long flags;
-	tifm_media_id media_id;
-	char *card_name = "xx";
-	int cnt, rc;
+	struct tifm_adapter *fm = container_of(work, struct tifm_adapter,
+					       media_switcher);
 	struct tifm_dev *sock;
-	unsigned int socket_change_set;
+	unsigned long flags;
+	unsigned char media_id;
+	unsigned int socket_change_set, cnt;
 
-	while (1) {
-		rc = wait_event_interruptible(fm->change_set_notify,
-					      fm->socket_change_set);
-		if (rc == -ERESTARTSYS)
-			try_to_freeze();
+	spin_lock_irqsave(&fm->lock, flags);
+	socket_change_set = fm->socket_change_set;
+	fm->socket_change_set = 0;
 
-		spin_lock_irqsave(&fm->lock, flags);
-		socket_change_set = fm->socket_change_set;
-		fm->socket_change_set = 0;
+	dev_dbg(fm->cdev.dev, "checking media set %x\n",
+		socket_change_set);
 
-		dev_dbg(fm->dev, "checking media set %x\n",
-			socket_change_set);
+	if (!socket_change_set) {
+		spin_unlock_irqrestore(&fm->lock, flags);
+		return;
+	}
 
-		if (kthread_should_stop())
-			socket_change_set = (1 << fm->num_sockets) - 1;
+	for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+		if (!(socket_change_set & (1 << cnt)))
+			continue;
+		sock = fm->sockets[cnt];
+		if (sock) {
+			printk(KERN_INFO
+			       "%s : demand removing card from socket %u:%u\n",
+			       fm->cdev.class_id, fm->id, cnt);
+			fm->sockets[cnt] = NULL;
+			spin_unlock_irqrestore(&fm->lock, flags);
+			device_unregister(&sock->dev);
+			spin_lock_irqsave(&fm->lock, flags);
+			writel(0x0e00, tifm_7xx1_sock_addr(fm->addr, cnt)
+			       + SOCK_CONTROL);
+		}
+
 		spin_unlock_irqrestore(&fm->lock, flags);
 
-		if (!socket_change_set)
-			continue;
+		media_id = tifm_7xx1_toggle_sock_power(
+				tifm_7xx1_sock_addr(fm->addr, cnt));
 
-		spin_lock_irqsave(&fm->lock, flags);
-		for (cnt = 0; cnt < fm->num_sockets; cnt++) {
-			if (!(socket_change_set & (1 << cnt)))
-				continue;
-			sock = fm->sockets[cnt];
-			if (sock) {
-				printk(KERN_INFO DRIVER_NAME
-				       ": demand removing card from socket %d\n",
-				       cnt);
-				fm->sockets[cnt] = NULL;
-				spin_unlock_irqrestore(&fm->lock, flags);
-				device_unregister(&sock->dev);
+		// tifm_alloc_device will check if media_id is valid
+		sock = tifm_alloc_device(fm, cnt, media_id);
+		if (sock) {
+			sock->addr = tifm_7xx1_sock_addr(fm->addr, cnt);
+
+			if (!device_register(&sock->dev)) {
 				spin_lock_irqsave(&fm->lock, flags);
-				writel(0x0e00,
-				       tifm_7xx1_sock_addr(fm->addr, cnt)
-				       + SOCK_CONTROL);
-			}
-			if (kthread_should_stop())
-				continue;
-
-			spin_unlock_irqrestore(&fm->lock, flags);
-			media_id = tifm_7xx1_toggle_sock_power(
-					tifm_7xx1_sock_addr(fm->addr, cnt),
-					fm->num_sockets == 2);
-			if (media_id) {
-				sock = tifm_alloc_device(fm);
-				if (sock) {
-					sock->addr = tifm_7xx1_sock_addr(fm->addr,
-									 cnt);
-					sock->media_id = media_id;
-					sock->socket_id = cnt;
-					switch (media_id) {
-					case 1:
-						card_name = "xd";
-						break;
-					case 2:
-						card_name = "ms";
-						break;
-					case 3:
-						card_name = "sd";
-						break;
-					default:
-						tifm_free_device(&sock->dev);
-						spin_lock_irqsave(&fm->lock, flags);
-						continue;
-					}
-					snprintf(sock->dev.bus_id, BUS_ID_SIZE,
-						 "tifm_%s%u:%u", card_name,
-						 fm->id, cnt);
-					printk(KERN_INFO DRIVER_NAME
-					       ": %s card detected in socket %d\n",
-					       card_name, cnt);
-					if (!device_register(&sock->dev)) {
-						spin_lock_irqsave(&fm->lock, flags);
-						if (!fm->sockets[cnt]) {
-							fm->sockets[cnt] = sock;
-							sock = NULL;
-						}
-						spin_unlock_irqrestore(&fm->lock, flags);
-					}
-					if (sock)
-						tifm_free_device(&sock->dev);
+				if (!fm->sockets[cnt]) {
+					fm->sockets[cnt] = sock;
+					sock = NULL;
 				}
-				spin_lock_irqsave(&fm->lock, flags);
-			}
-		}
-
-		if (!kthread_should_stop()) {
-			writel(TIFM_IRQ_FIFOMASK(socket_change_set)
-			       | TIFM_IRQ_CARDMASK(socket_change_set),
-			       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-			writel(TIFM_IRQ_FIFOMASK(socket_change_set)
-			       | TIFM_IRQ_CARDMASK(socket_change_set),
-			       fm->addr + FM_SET_INTERRUPT_ENABLE);
-			writel(TIFM_IRQ_ENABLE,
-			       fm->addr + FM_SET_INTERRUPT_ENABLE);
-			spin_unlock_irqrestore(&fm->lock, flags);
-		} else {
-			for (cnt = 0; cnt < fm->num_sockets; cnt++) {
-				if (fm->sockets[cnt])
-					fm->socket_change_set |= 1 << cnt;
-			}
-			if (!fm->socket_change_set) {
-				spin_unlock_irqrestore(&fm->lock, flags);
-				return 0;
-			} else {
 				spin_unlock_irqrestore(&fm->lock, flags);
 			}
+			if (sock)
+				tifm_free_device(&sock->dev);
 		}
+		spin_lock_irqsave(&fm->lock, flags);
 	}
-	return 0;
+
+	writel(TIFM_IRQ_FIFOMASK(socket_change_set)
+	       | TIFM_IRQ_CARDMASK(socket_change_set),
+	       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+
+	writel(TIFM_IRQ_FIFOMASK(socket_change_set)
+	       | TIFM_IRQ_CARDMASK(socket_change_set),
+	       fm->addr + FM_SET_INTERRUPT_ENABLE);
+
+	writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
+	spin_unlock_irqrestore(&fm->lock, flags);
 }
 
 #ifdef CONFIG_PM
@@ -258,9 +217,11 @@
 static int tifm_7xx1_resume(struct pci_dev *dev)
 {
 	struct tifm_adapter *fm = pci_get_drvdata(dev);
-	int cnt, rc;
+	int rc;
+	unsigned int good_sockets = 0, bad_sockets = 0;
 	unsigned long flags;
-	tifm_media_id new_ids[fm->num_sockets];
+	unsigned char new_ids[fm->num_sockets];
+	DECLARE_COMPLETION_ONSTACK(finish_resume);
 
 	pci_set_power_state(dev, PCI_D0);
 	pci_restore_state(dev);
@@ -271,45 +232,49 @@
 
 	dev_dbg(&dev->dev, "resuming host\n");
 
-	for (cnt = 0; cnt < fm->num_sockets; cnt++)
-		new_ids[cnt] = tifm_7xx1_toggle_sock_power(
-					tifm_7xx1_sock_addr(fm->addr, cnt),
-					fm->num_sockets == 2);
+	for (rc = 0; rc < fm->num_sockets; rc++)
+		new_ids[rc] = tifm_7xx1_toggle_sock_power(
+					tifm_7xx1_sock_addr(fm->addr, rc));
 	spin_lock_irqsave(&fm->lock, flags);
-	fm->socket_change_set = 0;
-	for (cnt = 0; cnt < fm->num_sockets; cnt++) {
-		if (fm->sockets[cnt]) {
-			if (fm->sockets[cnt]->media_id == new_ids[cnt])
-				fm->socket_change_set |= 1 << cnt;
-
-			fm->sockets[cnt]->media_id = new_ids[cnt];
+	for (rc = 0; rc < fm->num_sockets; rc++) {
+		if (fm->sockets[rc]) {
+			if (fm->sockets[rc]->type == new_ids[rc])
+				good_sockets |= 1 << rc;
+			else
+				bad_sockets |= 1 << rc;
 		}
 	}
 
 	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
 	       fm->addr + FM_SET_INTERRUPT_ENABLE);
-	if (!fm->socket_change_set) {
+	dev_dbg(&dev->dev, "change sets on resume: good %x, bad %x\n",
+		good_sockets, bad_sockets);
+
+	fm->socket_change_set = 0;
+	if (good_sockets) {
+		fm->finish_me = &finish_resume;
 		spin_unlock_irqrestore(&fm->lock, flags);
-		return 0;
-	} else {
-		fm->socket_change_set = 0;
-		spin_unlock_irqrestore(&fm->lock, flags);
+		rc = wait_for_completion_timeout(&finish_resume, HZ);
+		dev_dbg(&dev->dev, "wait returned %d\n", rc);
+		writel(TIFM_IRQ_FIFOMASK(good_sockets)
+		       | TIFM_IRQ_CARDMASK(good_sockets),
+		       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+		writel(TIFM_IRQ_FIFOMASK(good_sockets)
+		       | TIFM_IRQ_CARDMASK(good_sockets),
+		       fm->addr + FM_SET_INTERRUPT_ENABLE);
+		spin_lock_irqsave(&fm->lock, flags);
+		fm->finish_me = NULL;
+		fm->socket_change_set ^= good_sockets & fm->socket_change_set;
 	}
 
-	wait_event_timeout(fm->change_set_notify, fm->socket_change_set, HZ);
-
-	spin_lock_irqsave(&fm->lock, flags);
-	writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
-	       | TIFM_IRQ_CARDMASK(fm->socket_change_set),
-	       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-	writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
-	       | TIFM_IRQ_CARDMASK(fm->socket_change_set),
-	       fm->addr + FM_SET_INTERRUPT_ENABLE);
-	writel(TIFM_IRQ_ENABLE,
-	       fm->addr + FM_SET_INTERRUPT_ENABLE);
-	fm->socket_change_set = 0;
+	fm->socket_change_set |= bad_sockets;
+	if (fm->socket_change_set)
+		tifm_queue_work(&fm->media_switcher);
 
 	spin_unlock_irqrestore(&fm->lock, flags);
+	writel(TIFM_IRQ_ENABLE,
+	       fm->addr + FM_SET_INTERRUPT_ENABLE);
+
 	return 0;
 }
 
@@ -345,20 +310,14 @@
 
 	pci_intx(dev, 1);
 
-	fm = tifm_alloc_adapter();
+	fm = tifm_alloc_adapter(dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM
+				? 4 : 2, &dev->dev);
 	if (!fm) {
 		rc = -ENOMEM;
 		goto err_out_int;
 	}
 
-	fm->dev = &dev->dev;
-	fm->num_sockets = (dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM)
-			  ? 4 : 2;
-	fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->num_sockets,
-			      GFP_KERNEL);
-	if (!fm->sockets)
-		goto err_out_free;
-
+	INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media);
 	fm->eject = tifm_7xx1_eject;
 	pci_set_drvdata(dev, fm);
 
@@ -367,19 +326,16 @@
 	if (!fm->addr)
 		goto err_out_free;
 
-	rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm);
+	rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm);
 	if (rc)
 		goto err_out_unmap;
 
-	init_waitqueue_head(&fm->change_set_notify);
-	rc = tifm_add_adapter(fm, tifm_7xx1_switch_media);
+	rc = tifm_add_adapter(fm);
 	if (rc)
 		goto err_out_irq;
 
-	writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
 	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
 	       fm->addr + FM_SET_INTERRUPT_ENABLE);
-	wake_up_process(fm->media_switcher);
 	return 0;
 
 err_out_irq:
@@ -401,18 +357,12 @@
 static void tifm_7xx1_remove(struct pci_dev *dev)
 {
 	struct tifm_adapter *fm = pci_get_drvdata(dev);
-	unsigned long flags;
 
+	fm->eject = tifm_7xx1_dummy_eject;
 	writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
 	mmiowb();
 	free_irq(dev->irq, fm);
 
-	spin_lock_irqsave(&fm->lock, flags);
-	fm->socket_change_set = (1 << fm->num_sockets) - 1;
-	spin_unlock_irqrestore(&fm->lock, flags);
-
-	kthread_stop(fm->media_switcher);
-
 	tifm_remove_adapter(fm);
 
 	pci_set_drvdata(dev, NULL);
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c
index 6b10ebe..d195fb0 100644
--- a/drivers/misc/tifm_core.c
+++ b/drivers/misc/tifm_core.c
@@ -14,71 +14,124 @@
 #include <linux/idr.h>
 
 #define DRIVER_NAME "tifm_core"
-#define DRIVER_VERSION "0.7"
+#define DRIVER_VERSION "0.8"
 
+static struct workqueue_struct *workqueue;
 static DEFINE_IDR(tifm_adapter_idr);
 static DEFINE_SPINLOCK(tifm_adapter_lock);
 
-static tifm_media_id *tifm_device_match(tifm_media_id *ids,
-			struct tifm_dev *dev)
+static const char *tifm_media_type_name(unsigned char type, unsigned char nt)
 {
-	while (*ids) {
-		if (dev->media_id == *ids)
-			return ids;
-		ids++;
-	}
-	return NULL;
+	const char *card_type_name[3][3] = {
+		{ "SmartMedia/xD", "MemoryStick", "MMC/SD" },
+		{ "XD", "MS", "SD"},
+		{ "xd", "ms", "sd"}
+	};
+
+	if (nt > 2 || type < 1 || type > 3)
+		return NULL;
+	return card_type_name[nt][type - 1];
 }
 
-static int tifm_match(struct device *dev, struct device_driver *drv)
+static int tifm_dev_match(struct tifm_dev *sock, struct tifm_device_id *id)
 {
-	struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-	struct tifm_driver *fm_drv;
-
-	fm_drv = container_of(drv, struct tifm_driver, driver);
-	if (!fm_drv->id_table)
-		return -EINVAL;
-	if (tifm_device_match(fm_drv->id_table, fm_dev))
+	if (sock->type == id->type)
 		return 1;
-	return -ENODEV;
+	return 0;
+}
+
+static int tifm_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	struct tifm_driver *fm_drv = container_of(drv, struct tifm_driver,
+						  driver);
+	struct tifm_device_id *ids = fm_drv->id_table;
+
+	if (ids) {
+		while (ids->type) {
+			if (tifm_dev_match(sock, ids))
+				return 1;
+			++ids;
+		}
+	}
+	return 0;
 }
 
 static int tifm_uevent(struct device *dev, char **envp, int num_envp,
 		       char *buffer, int buffer_size)
 {
-	struct tifm_dev *fm_dev;
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 	int i = 0;
 	int length = 0;
-	const char *card_type_name[] = {"INV", "SM", "MS", "SD"};
 
-	if (!dev || !(fm_dev = container_of(dev, struct tifm_dev, dev)))
-		return -ENODEV;
 	if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
-			"TIFM_CARD_TYPE=%s", card_type_name[fm_dev->media_id]))
+			   "TIFM_CARD_TYPE=%s",
+			   tifm_media_type_name(sock->type, 1)))
 		return -ENOMEM;
 
 	return 0;
 }
 
+static int tifm_device_probe(struct device *dev)
+{
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
+					       driver);
+	int rc = -ENODEV;
+
+	get_device(dev);
+	if (dev->driver && drv->probe) {
+		rc = drv->probe(sock);
+		if (!rc)
+			return 0;
+	}
+	put_device(dev);
+	return rc;
+}
+
+static void tifm_dummy_event(struct tifm_dev *sock)
+{
+	return;
+}
+
+static int tifm_device_remove(struct device *dev)
+{
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
+					       driver);
+
+	if (dev->driver && drv->remove) {
+		sock->card_event = tifm_dummy_event;
+		sock->data_event = tifm_dummy_event;
+		drv->remove(sock);
+		sock->dev.driver = NULL;
+	}
+
+	put_device(dev);
+	return 0;
+}
+
 #ifdef CONFIG_PM
 
 static int tifm_device_suspend(struct device *dev, pm_message_t state)
 {
-	struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-	struct tifm_driver *drv = fm_dev->drv;
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
+					       driver);
 
-	if (drv && drv->suspend)
-		return drv->suspend(fm_dev, state);
+	if (dev->driver && drv->suspend)
+		return drv->suspend(sock, state);
 	return 0;
 }
 
 static int tifm_device_resume(struct device *dev)
 {
-	struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-	struct tifm_driver *drv = fm_dev->drv;
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver,
+					       driver);
 
-	if (drv && drv->resume)
-		return drv->resume(fm_dev);
+	if (dev->driver && drv->resume)
+		return drv->resume(sock);
 	return 0;
 }
 
@@ -89,19 +142,33 @@
 
 #endif /* CONFIG_PM */
 
+static ssize_t type_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	return sprintf(buf, "%x", sock->type);
+}
+
+static struct device_attribute tifm_dev_attrs[] = {
+	__ATTR(type, S_IRUGO, type_show, NULL),
+	__ATTR_NULL
+};
+
 static struct bus_type tifm_bus_type = {
-	.name    = "tifm",
-	.match   = tifm_match,
-	.uevent  = tifm_uevent,
-	.suspend = tifm_device_suspend,
-	.resume  = tifm_device_resume
+	.name      = "tifm",
+	.dev_attrs = tifm_dev_attrs,
+	.match     = tifm_bus_match,
+	.uevent    = tifm_uevent,
+	.probe     = tifm_device_probe,
+	.remove    = tifm_device_remove,
+	.suspend   = tifm_device_suspend,
+	.resume    = tifm_device_resume
 };
 
 static void tifm_free(struct class_device *cdev)
 {
 	struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev);
 
-	kfree(fm->sockets);
 	kfree(fm);
 }
 
@@ -110,28 +177,25 @@
 	.release = tifm_free
 };
 
-struct tifm_adapter *tifm_alloc_adapter(void)
+struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
+					struct device *dev)
 {
 	struct tifm_adapter *fm;
 
-	fm = kzalloc(sizeof(struct tifm_adapter), GFP_KERNEL);
+	fm = kzalloc(sizeof(struct tifm_adapter)
+		     + sizeof(struct tifm_dev*) * num_sockets, GFP_KERNEL);
 	if (fm) {
 		fm->cdev.class = &tifm_adapter_class;
-		spin_lock_init(&fm->lock);
+		fm->cdev.dev = dev;
 		class_device_initialize(&fm->cdev);
+		spin_lock_init(&fm->lock);
+		fm->num_sockets = num_sockets;
 	}
 	return fm;
 }
 EXPORT_SYMBOL(tifm_alloc_adapter);
 
-void tifm_free_adapter(struct tifm_adapter *fm)
-{
-	class_device_put(&fm->cdev);
-}
-EXPORT_SYMBOL(tifm_free_adapter);
-
-int tifm_add_adapter(struct tifm_adapter *fm,
-		     int (*mediathreadfn)(void *data))
+int tifm_add_adapter(struct tifm_adapter *fm)
 {
 	int rc;
 
@@ -141,59 +205,80 @@
 	spin_lock(&tifm_adapter_lock);
 	rc = idr_get_new(&tifm_adapter_idr, fm, &fm->id);
 	spin_unlock(&tifm_adapter_lock);
-	if (!rc) {
-		snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id);
-		fm->media_switcher = kthread_create(mediathreadfn,
-						    fm, "tifm/%u", fm->id);
+	if (rc)
+		return rc;
 
-		if (!IS_ERR(fm->media_switcher))
-			return class_device_add(&fm->cdev);
-
+	snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id);
+	rc = class_device_add(&fm->cdev);
+	if (rc) {
 		spin_lock(&tifm_adapter_lock);
 		idr_remove(&tifm_adapter_idr, fm->id);
 		spin_unlock(&tifm_adapter_lock);
-		rc = -ENOMEM;
 	}
+
 	return rc;
 }
 EXPORT_SYMBOL(tifm_add_adapter);
 
 void tifm_remove_adapter(struct tifm_adapter *fm)
 {
-	class_device_del(&fm->cdev);
+	unsigned int cnt;
+
+	flush_workqueue(workqueue);
+	for (cnt = 0; cnt < fm->num_sockets; ++cnt) {
+		if (fm->sockets[cnt])
+			device_unregister(&fm->sockets[cnt]->dev);
+	}
 
 	spin_lock(&tifm_adapter_lock);
 	idr_remove(&tifm_adapter_idr, fm->id);
 	spin_unlock(&tifm_adapter_lock);
+	class_device_del(&fm->cdev);
 }
 EXPORT_SYMBOL(tifm_remove_adapter);
 
+void tifm_free_adapter(struct tifm_adapter *fm)
+{
+	class_device_put(&fm->cdev);
+}
+EXPORT_SYMBOL(tifm_free_adapter);
+
 void tifm_free_device(struct device *dev)
 {
-	struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-	kfree(fm_dev);
+	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
+	kfree(sock);
 }
 EXPORT_SYMBOL(tifm_free_device);
 
-static void tifm_dummy_signal_irq(struct tifm_dev *sock,
-				  unsigned int sock_irq_status)
+struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id,
+				   unsigned char type)
 {
-	return;
-}
+	struct tifm_dev *sock = NULL;
 
-struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm)
-{
-	struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL);
+	if (!tifm_media_type_name(type, 0))
+		return sock;
 
-	if (dev) {
-		spin_lock_init(&dev->lock);
+	sock = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL);
+	if (sock) {
+		spin_lock_init(&sock->lock);
+		sock->type = type;
+		sock->socket_id = id;
+		sock->card_event = tifm_dummy_event;
+		sock->data_event = tifm_dummy_event;
 
-		dev->dev.parent = fm->dev;
-		dev->dev.bus = &tifm_bus_type;
-		dev->dev.release = tifm_free_device;
-		dev->signal_irq = tifm_dummy_signal_irq;
+		sock->dev.parent = fm->cdev.dev;
+		sock->dev.bus = &tifm_bus_type;
+		sock->dev.dma_mask = fm->cdev.dev->dma_mask;
+		sock->dev.release = tifm_free_device;
+
+		snprintf(sock->dev.bus_id, BUS_ID_SIZE,
+			 "tifm_%s%u:%u", tifm_media_type_name(type, 2),
+			 fm->id, id);
+		printk(KERN_INFO DRIVER_NAME
+		       ": %s card detected in socket %u:%u\n",
+		       tifm_media_type_name(type, 0), fm->id, id);
 	}
-	return dev;
+	return sock;
 }
 EXPORT_SYMBOL(tifm_alloc_device);
 
@@ -218,54 +303,15 @@
 }
 EXPORT_SYMBOL(tifm_unmap_sg);
 
-static int tifm_device_probe(struct device *dev)
+void tifm_queue_work(struct work_struct *work)
 {
-	struct tifm_driver *drv;
-	struct tifm_dev *fm_dev;
-	int rc = 0;
-	const tifm_media_id *id;
-
-	drv = container_of(dev->driver, struct tifm_driver, driver);
-	fm_dev = container_of(dev, struct tifm_dev, dev);
-	get_device(dev);
-	if (!fm_dev->drv && drv->probe && drv->id_table) {
-		rc = -ENODEV;
-		id = tifm_device_match(drv->id_table, fm_dev);
-		if (id)
-			rc = drv->probe(fm_dev);
-		if (rc >= 0) {
-			rc = 0;
-			fm_dev->drv = drv;
-		}
-	}
-	if (rc)
-		put_device(dev);
-	return rc;
+	queue_work(workqueue, work);
 }
-
-static int tifm_device_remove(struct device *dev)
-{
-	struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-	struct tifm_driver *drv = fm_dev->drv;
-
-	if (drv) {
-		fm_dev->signal_irq = tifm_dummy_signal_irq;
-		if (drv->remove)
-			drv->remove(fm_dev);
-		fm_dev->drv = NULL;
-	}
-
-	put_device(dev);
-	return 0;
-}
+EXPORT_SYMBOL(tifm_queue_work);
 
 int tifm_register_driver(struct tifm_driver *drv)
 {
 	drv->driver.bus = &tifm_bus_type;
-	drv->driver.probe = tifm_device_probe;
-	drv->driver.remove = tifm_device_remove;
-	drv->driver.suspend = tifm_device_suspend;
-	drv->driver.resume = tifm_device_resume;
 
 	return driver_register(&drv->driver);
 }
@@ -279,13 +325,25 @@
 
 static int __init tifm_init(void)
 {
-	int rc = bus_register(&tifm_bus_type);
+	int rc;
 
-	if (!rc) {
-		rc = class_register(&tifm_adapter_class);
-		if (rc)
-			bus_unregister(&tifm_bus_type);
-	}
+	workqueue = create_freezeable_workqueue("tifm");
+	if (!workqueue)
+		return -ENOMEM;
+
+	rc = bus_register(&tifm_bus_type);
+
+	if (rc)
+		goto err_out_wq;
+
+	rc = class_register(&tifm_adapter_class);
+	if (!rc)
+		return 0;
+
+	bus_unregister(&tifm_bus_type);
+
+err_out_wq:
+	destroy_workqueue(workqueue);
 
 	return rc;
 }
@@ -294,6 +352,7 @@
 {
 	class_unregister(&tifm_adapter_class);
 	bus_unregister(&tifm_bus_type);
+	destroy_workqueue(workqueue);
 }
 
 subsys_initcall(tifm_init);
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 12af9c7..6c97491 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -19,110 +19,10 @@
 	  This is an option for use by developers; most people should
 	  say N here.  This enables MMC core and driver debugging.
 
-config MMC_BLOCK
-	tristate "MMC block device driver"
-	depends on MMC && BLOCK
-	default y
-	help
-	  Say Y here to enable the MMC block device driver support.
-	  This provides a block device driver, which you can use to
-	  mount the filesystem. Almost everyone wishing MMC support
-	  should say Y or M here.
+source "drivers/mmc/core/Kconfig"
 
-config MMC_ARMMMCI
-	tristate "ARM AMBA Multimedia Card Interface support"
-	depends on ARM_AMBA && MMC
-	help
-	  This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card
-	  Interface (PL180 and PL181) support.  If you have an ARM(R)
-	  platform with a Multimedia Card slot, say Y or M here.
+source "drivers/mmc/card/Kconfig"
 
-	  If unsure, say N.
-
-config MMC_PXA
-	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.
-	  If you have a PXA(R) platform with a Multimedia Card slot,
-	  say Y or M here.
-
-	  If unsure, say N.
-
-config MMC_SDHCI
-	tristate "Secure Digital Host Controller Interface support  (EXPERIMENTAL)"
-	depends on PCI && MMC && EXPERIMENTAL
-	help
-	  This select the generic Secure Digital Host Controller Interface.
-	  It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
-	  and Toshiba(R). Most controllers found in laptops are of this type.
-	  If you have a controller with this interface, say Y or M here.
-
-	  If unsure, say N.
-
-config MMC_OMAP
-	tristate "TI OMAP Multimedia Card Interface support"
-	depends on ARCH_OMAP && MMC
-	select TPS65010 if MACH_OMAP_H2
-	help
-	  This selects the TI OMAP Multimedia card Interface.
-	  If you have an OMAP board with a Multimedia Card slot,
-	  say Y or M here.
-
-	  If unsure, say N.
-
-config MMC_WBSD
-	tristate "Winbond W83L51xD SD/MMC Card Interface support"
-	depends on MMC && ISA_DMA_API
-	help
-	  This selects the Winbond(R) W83L51xD Secure digital and
-          Multimedia card Interface.
-	  If you have a machine with a integrated W83L518D or W83L519D
-	  SD/MMC card reader, say Y or M here.
-
-	  If unsure, say N.
-
-config MMC_AU1X
-	tristate "Alchemy AU1XX0 MMC Card Interface support"
-	depends on MMC && SOC_AU1200
-	help
-	  This selects the AMD Alchemy(R) Multimedia card interface.
-	  If you have a Alchemy platform with a MMC slot, say Y or M here.
-
-	  If unsure, say N.
-
-config MMC_AT91
-	tristate "AT91 SD/MMC Card Interface support"
-	depends on ARCH_AT91 && MMC
-	help
-	  This selects the AT91 MCI controller.
-
-	  If unsure, say N.
-
-config MMC_IMX
-	tristate "Motorola i.MX Multimedia Card Interface support"
-	depends on ARCH_IMX && MMC
-	help
-	  This selects the Motorola i.MX Multimedia card Interface.
-	  If you have a i.MX platform with a Multimedia Card slot,
-	  say Y or M here.
-
-	  If unsure, say N.
-
-config MMC_TIFM_SD
-	tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
-	depends on MMC && EXPERIMENTAL && PCI
-	select TIFM_CORE
-	help
-	  Say Y here if you want to be able to access MMC/SD cards with
-	  the Texas Instruments(R) Flash Media card reader, found in many
-	  laptops.
-	  This option 'selects' (turns on, enables) 'TIFM_CORE', but you
-	  probably also need appropriate card reader host adapter, such as
-	  'Misc devices: TI Flash Media PCI74xx/PCI76xx host adapter support
-	  (TIFM_7XX1)'.
-
-          To compile this driver as a module, choose M here: the
-	  module will be called tifm_sd.
+source "drivers/mmc/host/Kconfig"
 
 endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 83ffb93..9979f5e 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -2,32 +2,11 @@
 # Makefile for the kernel mmc device drivers.
 #
 
-#
-# Core
-#
-obj-$(CONFIG_MMC)		+= mmc_core.o
-
-#
-# Media drivers
-#
-obj-$(CONFIG_MMC_BLOCK)		+= mmc_block.o
-
-#
-# Host drivers
-#
-obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o
-obj-$(CONFIG_MMC_PXA)		+= pxamci.o
-obj-$(CONFIG_MMC_IMX)		+= imxmmc.o
-obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
-obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
-obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
-obj-$(CONFIG_MMC_OMAP)		+= omap.o
-obj-$(CONFIG_MMC_AT91)		+= at91_mci.o
-obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o
-
-mmc_core-y := mmc.o mmc_sysfs.o
-mmc_core-$(CONFIG_BLOCK) += mmc_queue.o
-
 ifeq ($(CONFIG_MMC_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
+	EXTRA_CFLAGS		+= -DDEBUG
 endif
+
+obj-$(CONFIG_MMC)		+= core/
+obj-$(CONFIG_MMC)		+= card/
+obj-$(CONFIG_MMC)		+= host/
+
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
new file mode 100644
index 0000000..01a9fd3
--- /dev/null
+++ b/drivers/mmc/card/Kconfig
@@ -0,0 +1,17 @@
+#
+# MMC/SD card drivers
+#
+
+comment "MMC/SD Card Drivers"
+	depends MMC
+
+config MMC_BLOCK
+	tristate "MMC block device driver"
+	depends on MMC && BLOCK
+	default y
+	help
+	  Say Y here to enable the MMC block device driver support.
+	  This provides a block device driver, which you can use to
+	  mount the filesystem. Almost everyone wishing MMC support
+	  should say Y or M here.
+
diff --git a/drivers/mmc/card/Makefile b/drivers/mmc/card/Makefile
new file mode 100644
index 0000000..cf8c939
--- /dev/null
+++ b/drivers/mmc/card/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for MMC/SD card drivers
+#
+
+ifeq ($(CONFIG_MMC_DEBUG),y)
+	EXTRA_CFLAGS		+= -DDEBUG
+endif
+
+obj-$(CONFIG_MMC_BLOCK)		+= mmc_block.o
+mmc_block-objs			:= block.o queue.o
+
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/card/block.c
similarity index 92%
rename from drivers/mmc/mmc_block.c
rename to drivers/mmc/card/block.c
index 86439a0..d24ab23 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/card/block.c
@@ -2,6 +2,7 @@
  * Block driver for media (i.e., flash cards)
  *
  * Copyright 2002 Hewlett-Packard Company
+ * Copyright 2005-2007 Pierre Ossman
  *
  * Use consistent with the GNU GPL is permitted,
  * provided that this copyright notice is
@@ -31,13 +32,13 @@
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
-#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-#include "mmc_queue.h"
+#include "queue.h"
 
 /*
  * max 8 partitions per card
@@ -223,10 +224,9 @@
 	struct mmc_blk_data *md = mq->data;
 	struct mmc_card *card = md->queue.card;
 	struct mmc_blk_request brq;
-	int ret = 1;
+	int ret = 1, sg_pos, data_size;
 
-	if (mmc_card_claim_host(card))
-		goto flush_queue;
+	mmc_claim_host(card->host);
 
 	do {
 		struct mmc_command cmd;
@@ -283,6 +283,20 @@
 		brq.data.sg = mq->sg;
 		brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
 
+		if (brq.data.blocks !=
+		    (req->nr_sectors >> (md->block_bits - 9))) {
+			data_size = brq.data.blocks * brq.data.blksz;
+			for (sg_pos = 0; sg_pos < brq.data.sg_len; sg_pos++) {
+				data_size -= mq->sg[sg_pos].length;
+				if (data_size <= 0) {
+					mq->sg[sg_pos].length += data_size;
+					sg_pos++;
+					break;
+				}
+			}
+			brq.data.sg_len = sg_pos;
+		}
+
 		mmc_wait_for_req(card->host, &brq.mrq);
 		if (brq.cmd.error) {
 			printk(KERN_ERR "%s: error %d sending read/write command\n",
@@ -342,7 +356,7 @@
 		spin_unlock_irq(&md->lock);
 	} while (ret);
 
-	mmc_card_release_host(card);
+	mmc_release_host(card->host);
 
 	return 1;
 
@@ -378,9 +392,7 @@
 		spin_unlock_irq(&md->lock);
 	}
 
-flush_queue:
-
-	mmc_card_release_host(card);
+	mmc_release_host(card->host);
 
 	spin_lock_irq(&md->lock);
 	while (ret) {
@@ -477,11 +489,20 @@
 
 	blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
 
-	/*
-	 * The CSD capacity field is in units of read_blkbits.
-	 * set_capacity takes units of 512 bytes.
-	 */
-	set_capacity(md->disk, card->csd.capacity << (card->csd.read_blkbits - 9));
+	if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
+		/*
+		 * The EXT_CSD sector count is in number or 512 byte
+		 * sectors.
+		 */
+		set_capacity(md->disk, card->ext_csd.sectors);
+	} else {
+		/*
+		 * The CSD capacity field is in units of read_blkbits.
+		 * set_capacity takes units of 512 bytes.
+		 */
+		set_capacity(md->disk,
+			card->csd.capacity << (card->csd.read_blkbits - 9));
+	}
 	return md;
 
  err_putdisk:
@@ -502,12 +523,12 @@
 	if (mmc_card_blockaddr(card))
 		return 0;
 
-	mmc_card_claim_host(card);
+	mmc_claim_host(card->host);
 	cmd.opcode = MMC_SET_BLOCKLEN;
 	cmd.arg = 1 << md->block_bits;
 	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 	err = mmc_wait_for_cmd(card->host, &cmd, 5);
-	mmc_card_release_host(card);
+	mmc_release_host(card->host);
 
 	if (err) {
 		printk(KERN_ERR "%s: unable to set block size to %d: %d\n",
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/card/queue.c
similarity index 96%
rename from drivers/mmc/mmc_queue.c
rename to drivers/mmc/card/queue.c
index c27e426..2e77963 100644
--- a/drivers/mmc/mmc_queue.c
+++ b/drivers/mmc/card/queue.c
@@ -1,7 +1,8 @@
 /*
- *  linux/drivers/mmc/mmc_queue.c
+ *  linux/drivers/mmc/queue.c
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2006-2007 Pierre Ossman
  *
  * 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
@@ -14,7 +15,7 @@
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
-#include "mmc_queue.h"
+#include "queue.h"
 
 #define MMC_QUEUE_SUSPENDED	(1 << 0)
 
@@ -179,7 +180,6 @@
 	blk_cleanup_queue(mq->queue);
 	return ret;
 }
-EXPORT_SYMBOL(mmc_init_queue);
 
 void mmc_cleanup_queue(struct mmc_queue *mq)
 {
@@ -191,6 +191,9 @@
 	q->queuedata = NULL;
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
+	/* Make sure the queue isn't suspended, as that will deadlock */
+	mmc_queue_resume(mq);
+
 	/* Then terminate our worker thread */
 	kthread_stop(mq->thread);
 
@@ -226,7 +229,6 @@
 		down(&mq->thread_sem);
 	}
 }
-EXPORT_SYMBOL(mmc_queue_suspend);
 
 /**
  * mmc_queue_resume - resume a previously suspended MMC request queue
@@ -247,4 +249,4 @@
 		spin_unlock_irqrestore(q->queue_lock, flags);
 	}
 }
-EXPORT_SYMBOL(mmc_queue_resume);
+
diff --git a/drivers/mmc/mmc_queue.h b/drivers/mmc/card/queue.h
similarity index 100%
rename from drivers/mmc/mmc_queue.h
rename to drivers/mmc/card/queue.h
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
new file mode 100644
index 0000000..94222b9
--- /dev/null
+++ b/drivers/mmc/core/Kconfig
@@ -0,0 +1,17 @@
+#
+# MMC core configuration
+#
+
+config MMC_UNSAFE_RESUME
+	bool "Allow unsafe resume (DANGEROUS)"
+	depends on MMC != n
+	help
+	  If you say Y here, the MMC layer will assume that all cards
+	  stayed in their respective slots during the suspend. The
+	  normal behaviour is to remove them at suspend and
+	  redetecting them at resume. Breaking this assumption will
+	  in most cases result in data corruption.
+
+	  This option is usually just for embedded systems which use
+	  a MMC/SD card for rootfs. Most people should say N here.
+
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
new file mode 100644
index 0000000..1075b02
--- /dev/null
+++ b/drivers/mmc/core/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the kernel mmc core.
+#
+
+ifeq ($(CONFIG_MMC_DEBUG),y)
+	EXTRA_CFLAGS		+= -DDEBUG
+endif
+
+obj-$(CONFIG_MMC)		+= mmc_core.o
+mmc_core-y			:= core.o sysfs.o mmc.o mmc_ops.o sd.o sd_ops.o
+
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
new file mode 100644
index 0000000..72c7cf4
--- /dev/null
+++ b/drivers/mmc/core/core.c
@@ -0,0 +1,727 @@
+/*
+ *  linux/drivers/mmc/core/core.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
+ *  Copyright (C) 2005-2007 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
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/pagemap.h>
+#include <linux/err.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+
+#include "core.h"
+#include "sysfs.h"
+
+#include "mmc_ops.h"
+#include "sd_ops.h"
+
+extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
+extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
+
+/**
+ *	mmc_request_done - finish processing an MMC request
+ *	@host: MMC host which completed request
+ *	@mrq: MMC request which request
+ *
+ *	MMC drivers should call this function when they have completed
+ *	their processing of a request.
+ */
+void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
+{
+	struct mmc_command *cmd = mrq->cmd;
+	int err = cmd->error;
+
+	pr_debug("%s: req done (CMD%u): %d/%d/%d: %08x %08x %08x %08x\n",
+		 mmc_hostname(host), cmd->opcode, err,
+		 mrq->data ? mrq->data->error : 0,
+		 mrq->stop ? mrq->stop->error : 0,
+		 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+
+	if (err && cmd->retries) {
+		cmd->retries--;
+		cmd->error = 0;
+		host->ops->request(host, mrq);
+	} else if (mrq->done) {
+		mrq->done(mrq);
+	}
+}
+
+EXPORT_SYMBOL(mmc_request_done);
+
+/**
+ *	mmc_start_request - start a command on a host
+ *	@host: MMC host to start command on
+ *	@mrq: MMC request to start
+ *
+ *	Queue a command on the specified host.  We expect the
+ *	caller to be holding the host lock with interrupts disabled.
+ */
+void
+mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
+{
+#ifdef CONFIG_MMC_DEBUG
+	unsigned int i, sz;
+#endif
+
+	pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
+		 mmc_hostname(host), mrq->cmd->opcode,
+		 mrq->cmd->arg, mrq->cmd->flags);
+
+	WARN_ON(!host->claimed);
+
+	mrq->cmd->error = 0;
+	mrq->cmd->mrq = mrq;
+	if (mrq->data) {
+		BUG_ON(mrq->data->blksz > host->max_blk_size);
+		BUG_ON(mrq->data->blocks > host->max_blk_count);
+		BUG_ON(mrq->data->blocks * mrq->data->blksz >
+			host->max_req_size);
+
+#ifdef CONFIG_MMC_DEBUG
+		sz = 0;
+		for (i = 0;i < mrq->data->sg_len;i++)
+			sz += mrq->data->sg[i].length;
+		BUG_ON(sz != mrq->data->blocks * mrq->data->blksz);
+#endif
+
+		mrq->cmd->data = mrq->data;
+		mrq->data->error = 0;
+		mrq->data->mrq = mrq;
+		if (mrq->stop) {
+			mrq->data->stop = mrq->stop;
+			mrq->stop->error = 0;
+			mrq->stop->mrq = mrq;
+		}
+	}
+	host->ops->request(host, mrq);
+}
+
+EXPORT_SYMBOL(mmc_start_request);
+
+static void mmc_wait_done(struct mmc_request *mrq)
+{
+	complete(mrq->done_data);
+}
+
+int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
+{
+	DECLARE_COMPLETION_ONSTACK(complete);
+
+	mrq->done_data = &complete;
+	mrq->done = mmc_wait_done;
+
+	mmc_start_request(host, mrq);
+
+	wait_for_completion(&complete);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_req);
+
+/**
+ *	mmc_wait_for_cmd - start a command and wait for completion
+ *	@host: MMC host to start command
+ *	@cmd: MMC command to start
+ *	@retries: maximum number of retries
+ *
+ *	Start a new MMC command for a host, and wait for the command
+ *	to complete.  Return any error that occurred while the command
+ *	was executing.  Do not attempt to parse the response.
+ */
+int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
+{
+	struct mmc_request mrq;
+
+	BUG_ON(!host->claimed);
+
+	memset(&mrq, 0, sizeof(struct mmc_request));
+
+	memset(cmd->resp, 0, sizeof(cmd->resp));
+	cmd->retries = retries;
+
+	mrq.cmd = cmd;
+	cmd->data = NULL;
+
+	mmc_wait_for_req(host, &mrq);
+
+	return cmd->error;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_cmd);
+
+/**
+ *	mmc_set_data_timeout - set the timeout for a data command
+ *	@data: data phase for command
+ *	@card: the MMC card associated with the data transfer
+ *	@write: flag to differentiate reads from writes
+ */
+void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
+			  int write)
+{
+	unsigned int mult;
+
+	/*
+	 * SD cards use a 100 multiplier rather than 10
+	 */
+	mult = mmc_card_sd(card) ? 100 : 10;
+
+	/*
+	 * Scale up the multiplier (and therefore the timeout) by
+	 * the r2w factor for writes.
+	 */
+	if (write)
+		mult <<= card->csd.r2w_factor;
+
+	data->timeout_ns = card->csd.tacc_ns * mult;
+	data->timeout_clks = card->csd.tacc_clks * mult;
+
+	/*
+	 * SD cards also have an upper limit on the timeout.
+	 */
+	if (mmc_card_sd(card)) {
+		unsigned int timeout_us, limit_us;
+
+		timeout_us = data->timeout_ns / 1000;
+		timeout_us += data->timeout_clks * 1000 /
+			(card->host->ios.clock / 1000);
+
+		if (write)
+			limit_us = 250000;
+		else
+			limit_us = 100000;
+
+		/*
+		 * SDHC cards always use these fixed values.
+		 */
+		if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
+			data->timeout_ns = limit_us * 1000;
+			data->timeout_clks = 0;
+		}
+	}
+}
+EXPORT_SYMBOL(mmc_set_data_timeout);
+
+/**
+ *	__mmc_claim_host - exclusively claim a host
+ *	@host: mmc host to claim
+ *	@card: mmc card to claim host for
+ *
+ *	Claim a host for a set of operations.  If a valid card
+ *	is passed and this wasn't the last card selected, select
+ *	the card before returning.
+ *
+ *	Note: you should use mmc_card_claim_host or mmc_claim_host.
+ */
+void mmc_claim_host(struct mmc_host *host)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+
+	add_wait_queue(&host->wq, &wait);
+	spin_lock_irqsave(&host->lock, flags);
+	while (1) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		if (!host->claimed)
+			break;
+		spin_unlock_irqrestore(&host->lock, flags);
+		schedule();
+		spin_lock_irqsave(&host->lock, flags);
+	}
+	set_current_state(TASK_RUNNING);
+	host->claimed = 1;
+	spin_unlock_irqrestore(&host->lock, flags);
+	remove_wait_queue(&host->wq, &wait);
+}
+
+EXPORT_SYMBOL(mmc_claim_host);
+
+/**
+ *	mmc_release_host - release a host
+ *	@host: mmc host to release
+ *
+ *	Release a MMC host, allowing others to claim the host
+ *	for their operations.
+ */
+void mmc_release_host(struct mmc_host *host)
+{
+	unsigned long flags;
+
+	BUG_ON(!host->claimed);
+
+	spin_lock_irqsave(&host->lock, flags);
+	host->claimed = 0;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	wake_up(&host->wq);
+}
+
+EXPORT_SYMBOL(mmc_release_host);
+
+/*
+ * Internal function that does the actual ios call to the host driver,
+ * optionally printing some debug output.
+ */
+static inline void mmc_set_ios(struct mmc_host *host)
+{
+	struct mmc_ios *ios = &host->ios;
+
+	pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
+		"width %u timing %u\n",
+		 mmc_hostname(host), ios->clock, ios->bus_mode,
+		 ios->power_mode, ios->chip_select, ios->vdd,
+		 ios->bus_width, ios->timing);
+
+	host->ops->set_ios(host, ios);
+}
+
+/*
+ * Control chip select pin on a host.
+ */
+void mmc_set_chip_select(struct mmc_host *host, int mode)
+{
+	host->ios.chip_select = mode;
+	mmc_set_ios(host);
+}
+
+/*
+ * Sets the host clock to the highest possible frequency that
+ * is below "hz".
+ */
+void mmc_set_clock(struct mmc_host *host, unsigned int hz)
+{
+	WARN_ON(hz < host->f_min);
+
+	if (hz > host->f_max)
+		hz = host->f_max;
+
+	host->ios.clock = hz;
+	mmc_set_ios(host);
+}
+
+/*
+ * Change the bus mode (open drain/push-pull) of a host.
+ */
+void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
+{
+	host->ios.bus_mode = mode;
+	mmc_set_ios(host);
+}
+
+/*
+ * Change data bus width of a host.
+ */
+void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
+{
+	host->ios.bus_width = width;
+	mmc_set_ios(host);
+}
+
+/*
+ * Mask off any voltages we don't support and select
+ * the lowest voltage
+ */
+u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
+{
+	int bit;
+
+	ocr &= host->ocr_avail;
+
+	bit = ffs(ocr);
+	if (bit) {
+		bit -= 1;
+
+		ocr &= 3 << bit;
+
+		host->ios.vdd = bit;
+		mmc_set_ios(host);
+	} else {
+		ocr = 0;
+	}
+
+	return ocr;
+}
+
+/*
+ * Select timing parameters for host.
+ */
+void mmc_set_timing(struct mmc_host *host, unsigned int timing)
+{
+	host->ios.timing = timing;
+	mmc_set_ios(host);
+}
+
+/*
+ * Allocate a new MMC card
+ */
+struct mmc_card *mmc_alloc_card(struct mmc_host *host)
+{
+	struct mmc_card *card;
+
+	card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
+	if (!card)
+		return ERR_PTR(-ENOMEM);
+
+	mmc_init_card(card, host);
+
+	return card;
+}
+
+/*
+ * Apply power to the MMC stack.  This is a two-stage process.
+ * First, we enable power to the card without the clock running.
+ * We then wait a bit for the power to stabilise.  Finally,
+ * enable the bus drivers and clock to the card.
+ *
+ * We must _NOT_ enable the clock prior to power stablising.
+ *
+ * If a host does all the power sequencing itself, ignore the
+ * initial MMC_POWER_UP stage.
+ */
+static void mmc_power_up(struct mmc_host *host)
+{
+	int bit = fls(host->ocr_avail) - 1;
+
+	host->ios.vdd = bit;
+	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+	host->ios.chip_select = MMC_CS_DONTCARE;
+	host->ios.power_mode = MMC_POWER_UP;
+	host->ios.bus_width = MMC_BUS_WIDTH_1;
+	host->ios.timing = MMC_TIMING_LEGACY;
+	mmc_set_ios(host);
+
+	mmc_delay(1);
+
+	host->ios.clock = host->f_min;
+	host->ios.power_mode = MMC_POWER_ON;
+	mmc_set_ios(host);
+
+	mmc_delay(2);
+}
+
+static void mmc_power_off(struct mmc_host *host)
+{
+	host->ios.clock = 0;
+	host->ios.vdd = 0;
+	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+	host->ios.chip_select = MMC_CS_DONTCARE;
+	host->ios.power_mode = MMC_POWER_OFF;
+	host->ios.bus_width = MMC_BUS_WIDTH_1;
+	host->ios.timing = MMC_TIMING_LEGACY;
+	mmc_set_ios(host);
+}
+
+/*
+ * Assign a mmc bus handler to a host. Only one bus handler may control a
+ * host at any given time.
+ */
+void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
+{
+	unsigned long flags;
+
+	BUG_ON(!host);
+	BUG_ON(!ops);
+
+	BUG_ON(!host->claimed);
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	BUG_ON(host->bus_ops);
+	BUG_ON(host->bus_refs);
+
+	host->bus_ops = ops;
+	host->bus_refs = 1;
+	host->bus_dead = 0;
+
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+/*
+ * Remove the current bus handler from a host. Assumes that there are
+ * no interesting cards left, so the bus is powered down.
+ */
+void mmc_detach_bus(struct mmc_host *host)
+{
+	unsigned long flags;
+
+	BUG_ON(!host);
+
+	BUG_ON(!host->claimed);
+	BUG_ON(!host->bus_ops);
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	host->bus_dead = 1;
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	mmc_power_off(host);
+
+	mmc_bus_put(host);
+}
+
+/*
+ * Cleanup when the last reference to the bus operator is dropped.
+ */
+void __mmc_release_bus(struct mmc_host *host)
+{
+	BUG_ON(!host);
+	BUG_ON(host->bus_refs);
+	BUG_ON(!host->bus_dead);
+
+	host->bus_ops = NULL;
+}
+
+/**
+ *	mmc_detect_change - process change of state on a MMC socket
+ *	@host: host which changed state.
+ *	@delay: optional delay to wait before detection (jiffies)
+ *
+ *	All we know is that card(s) have been inserted or removed
+ *	from the socket(s).  We don't know which socket or cards.
+ */
+void mmc_detect_change(struct mmc_host *host, unsigned long delay)
+{
+#ifdef CONFIG_MMC_DEBUG
+	mmc_claim_host(host);
+	BUG_ON(host->removed);
+	mmc_release_host(host);
+#endif
+
+	mmc_schedule_delayed_work(&host->detect, delay);
+}
+
+EXPORT_SYMBOL(mmc_detect_change);
+
+
+static void mmc_rescan(struct work_struct *work)
+{
+	struct mmc_host *host =
+		container_of(work, struct mmc_host, detect.work);
+	u32 ocr;
+	int err;
+
+	mmc_bus_get(host);
+
+	if (host->bus_ops == NULL) {
+		/*
+		 * Only we can add a new handler, so it's safe to
+		 * release the lock here.
+		 */
+		mmc_bus_put(host);
+
+		mmc_claim_host(host);
+
+		mmc_power_up(host);
+		mmc_go_idle(host);
+
+		mmc_send_if_cond(host, host->ocr_avail);
+
+		err = mmc_send_app_op_cond(host, 0, &ocr);
+		if (err == MMC_ERR_NONE) {
+			if (mmc_attach_sd(host, ocr))
+				mmc_power_off(host);
+		} else {
+			/*
+			 * If we fail to detect any SD cards then try
+			 * searching for MMC cards.
+			 */
+			err = mmc_send_op_cond(host, 0, &ocr);
+			if (err == MMC_ERR_NONE) {
+				if (mmc_attach_mmc(host, ocr))
+					mmc_power_off(host);
+			} else {
+				mmc_power_off(host);
+				mmc_release_host(host);
+			}
+		}
+	} else {
+		if (host->bus_ops->detect && !host->bus_dead)
+			host->bus_ops->detect(host);
+
+		mmc_bus_put(host);
+	}
+}
+
+
+/**
+ *	mmc_alloc_host - initialise the per-host structure.
+ *	@extra: sizeof private data structure
+ *	@dev: pointer to host device model structure
+ *
+ *	Initialise the per-host structure.
+ */
+struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+{
+	struct mmc_host *host;
+
+	host = mmc_alloc_host_sysfs(extra, dev);
+	if (host) {
+		spin_lock_init(&host->lock);
+		init_waitqueue_head(&host->wq);
+		INIT_DELAYED_WORK(&host->detect, mmc_rescan);
+
+		/*
+		 * By default, hosts do not support SGIO or large requests.
+		 * They have to set these according to their abilities.
+		 */
+		host->max_hw_segs = 1;
+		host->max_phys_segs = 1;
+		host->max_seg_size = PAGE_CACHE_SIZE;
+
+		host->max_req_size = PAGE_CACHE_SIZE;
+		host->max_blk_size = 512;
+		host->max_blk_count = PAGE_CACHE_SIZE / 512;
+	}
+
+	return host;
+}
+
+EXPORT_SYMBOL(mmc_alloc_host);
+
+/**
+ *	mmc_add_host - initialise host hardware
+ *	@host: mmc host
+ */
+int mmc_add_host(struct mmc_host *host)
+{
+	int ret;
+
+	ret = mmc_add_host_sysfs(host);
+	if (ret == 0) {
+		mmc_power_off(host);
+		mmc_detect_change(host, 0);
+	}
+
+	return ret;
+}
+
+EXPORT_SYMBOL(mmc_add_host);
+
+/**
+ *	mmc_remove_host - remove host hardware
+ *	@host: mmc host
+ *
+ *	Unregister and remove all cards associated with this host,
+ *	and power down the MMC bus.
+ */
+void mmc_remove_host(struct mmc_host *host)
+{
+#ifdef CONFIG_MMC_DEBUG
+	mmc_claim_host(host);
+	host->removed = 1;
+	mmc_release_host(host);
+#endif
+
+	mmc_flush_scheduled_work();
+
+	mmc_bus_get(host);
+	if (host->bus_ops && !host->bus_dead) {
+		if (host->bus_ops->remove)
+			host->bus_ops->remove(host);
+
+		mmc_claim_host(host);
+		mmc_detach_bus(host);
+		mmc_release_host(host);
+	}
+	mmc_bus_put(host);
+
+	BUG_ON(host->card);
+
+	mmc_power_off(host);
+	mmc_remove_host_sysfs(host);
+}
+
+EXPORT_SYMBOL(mmc_remove_host);
+
+/**
+ *	mmc_free_host - free the host structure
+ *	@host: mmc host
+ *
+ *	Free the host once all references to it have been dropped.
+ */
+void mmc_free_host(struct mmc_host *host)
+{
+	mmc_free_host_sysfs(host);
+}
+
+EXPORT_SYMBOL(mmc_free_host);
+
+#ifdef CONFIG_PM
+
+/**
+ *	mmc_suspend_host - suspend a host
+ *	@host: mmc host
+ *	@state: suspend mode (PM_SUSPEND_xxx)
+ */
+int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
+{
+	mmc_flush_scheduled_work();
+
+	mmc_bus_get(host);
+	if (host->bus_ops && !host->bus_dead) {
+		if (host->bus_ops->suspend)
+			host->bus_ops->suspend(host);
+		if (!host->bus_ops->resume) {
+			if (host->bus_ops->remove)
+				host->bus_ops->remove(host);
+
+			mmc_claim_host(host);
+			mmc_detach_bus(host);
+			mmc_release_host(host);
+		}
+	}
+	mmc_bus_put(host);
+
+	mmc_power_off(host);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(mmc_suspend_host);
+
+/**
+ *	mmc_resume_host - resume a previously suspended host
+ *	@host: mmc host
+ */
+int mmc_resume_host(struct mmc_host *host)
+{
+	mmc_bus_get(host);
+	if (host->bus_ops && !host->bus_dead) {
+		mmc_power_up(host);
+		BUG_ON(!host->bus_ops->resume);
+		host->bus_ops->resume(host);
+	}
+	mmc_bus_put(host);
+
+	/*
+	 * We add a slight delay here so that resume can progress
+	 * in parallel.
+	 */
+	mmc_detect_change(host, 1);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(mmc_resume_host);
+
+#endif
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
new file mode 100644
index 0000000..177264d
--- /dev/null
+++ b/drivers/mmc/core/core.h
@@ -0,0 +1,70 @@
+/*
+ *  linux/drivers/mmc/core/core.h
+ *
+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
+ *
+ * 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
+ * published by the Free Software Foundation.
+ */
+#ifndef _MMC_CORE_CORE_H
+#define _MMC_CORE_CORE_H
+
+#include <linux/delay.h>
+
+#define MMC_CMD_RETRIES        3
+
+struct mmc_bus_ops {
+	void (*remove)(struct mmc_host *);
+	void (*detect)(struct mmc_host *);
+	void (*suspend)(struct mmc_host *);
+	void (*resume)(struct mmc_host *);
+};
+
+void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
+void mmc_detach_bus(struct mmc_host *host);
+
+void __mmc_release_bus(struct mmc_host *host);
+
+static inline void mmc_bus_get(struct mmc_host *host)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	host->bus_refs++;
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static inline void mmc_bus_put(struct mmc_host *host)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	host->bus_refs--;
+	if ((host->bus_refs == 0) && host->bus_ops)
+		__mmc_release_bus(host);
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+void mmc_set_chip_select(struct mmc_host *host, int mode);
+void mmc_set_clock(struct mmc_host *host, unsigned int hz);
+void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode);
+void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
+u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
+void mmc_set_timing(struct mmc_host *host, unsigned int timing);
+
+struct mmc_card *mmc_alloc_card(struct mmc_host *host);
+
+static inline void mmc_delay(unsigned int ms)
+{
+	if (ms < 1000 / HZ) {
+		cond_resched();
+		mdelay(ms);
+	} else {
+		msleep(ms);
+	}
+}
+
+#endif
+
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
new file mode 100644
index 0000000..42cc286
--- /dev/null
+++ b/drivers/mmc/core/mmc.c
@@ -0,0 +1,537 @@
+/*
+ *  linux/drivers/mmc/mmc.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ *  Copyright (C) 2005-2007 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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+
+#include "core.h"
+#include "sysfs.h"
+#include "mmc_ops.h"
+
+static const unsigned int tran_exp[] = {
+	10000,		100000,		1000000,	10000000,
+	0,		0,		0,		0
+};
+
+static const unsigned char tran_mant[] = {
+	0,	10,	12,	13,	15,	20,	25,	30,
+	35,	40,	45,	50,	55,	60,	70,	80,
+};
+
+static const unsigned int tacc_exp[] = {
+	1,	10,	100,	1000,	10000,	100000,	1000000, 10000000,
+};
+
+static const unsigned int tacc_mant[] = {
+	0,	10,	12,	13,	15,	20,	25,	30,
+	35,	40,	45,	50,	55,	60,	70,	80,
+};
+
+#define UNSTUFF_BITS(resp,start,size)					\
+	({								\
+		const int __size = size;				\
+		const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1;	\
+		const int __off = 3 - ((start) / 32);			\
+		const int __shft = (start) & 31;			\
+		u32 __res;						\
+									\
+		__res = resp[__off] >> __shft;				\
+		if (__size + __shft > 32)				\
+			__res |= resp[__off-1] << ((32 - __shft) % 32);	\
+		__res & __mask;						\
+	})
+
+/*
+ * Given the decoded CSD structure, decode the raw CID to our CID structure.
+ */
+static int mmc_decode_cid(struct mmc_card *card)
+{
+	u32 *resp = card->raw_cid;
+
+	/*
+	 * The selection of the format here is based upon published
+	 * specs from sandisk and from what people have reported.
+	 */
+	switch (card->csd.mmca_vsn) {
+	case 0: /* MMC v1.0 - v1.2 */
+	case 1: /* MMC v1.4 */
+		card->cid.manfid	= UNSTUFF_BITS(resp, 104, 24);
+		card->cid.prod_name[0]	= UNSTUFF_BITS(resp, 96, 8);
+		card->cid.prod_name[1]	= UNSTUFF_BITS(resp, 88, 8);
+		card->cid.prod_name[2]	= UNSTUFF_BITS(resp, 80, 8);
+		card->cid.prod_name[3]	= UNSTUFF_BITS(resp, 72, 8);
+		card->cid.prod_name[4]	= UNSTUFF_BITS(resp, 64, 8);
+		card->cid.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);
+		card->cid.prod_name[6]	= UNSTUFF_BITS(resp, 48, 8);
+		card->cid.hwrev		= UNSTUFF_BITS(resp, 44, 4);
+		card->cid.fwrev		= UNSTUFF_BITS(resp, 40, 4);
+		card->cid.serial	= UNSTUFF_BITS(resp, 16, 24);
+		card->cid.month		= UNSTUFF_BITS(resp, 12, 4);
+		card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;
+		break;
+
+	case 2: /* MMC v2.0 - v2.2 */
+	case 3: /* MMC v3.1 - v3.3 */
+	case 4: /* MMC v4 */
+		card->cid.manfid	= UNSTUFF_BITS(resp, 120, 8);
+		card->cid.oemid		= UNSTUFF_BITS(resp, 104, 16);
+		card->cid.prod_name[0]	= UNSTUFF_BITS(resp, 96, 8);
+		card->cid.prod_name[1]	= UNSTUFF_BITS(resp, 88, 8);
+		card->cid.prod_name[2]	= UNSTUFF_BITS(resp, 80, 8);
+		card->cid.prod_name[3]	= UNSTUFF_BITS(resp, 72, 8);
+		card->cid.prod_name[4]	= UNSTUFF_BITS(resp, 64, 8);
+		card->cid.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);
+		card->cid.serial	= UNSTUFF_BITS(resp, 16, 32);
+		card->cid.month		= UNSTUFF_BITS(resp, 12, 4);
+		card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;
+		break;
+
+	default:
+		printk("%s: card has unknown MMCA version %d\n",
+			mmc_hostname(card->host), card->csd.mmca_vsn);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Given a 128-bit response, decode to our card CSD structure.
+ */
+static int mmc_decode_csd(struct mmc_card *card)
+{
+	struct mmc_csd *csd = &card->csd;
+	unsigned int e, m, csd_struct;
+	u32 *resp = card->raw_csd;
+
+	/*
+	 * We only understand CSD structure v1.1 and v1.2.
+	 * v1.2 has extra information in bits 15, 11 and 10.
+	 */
+	csd_struct = UNSTUFF_BITS(resp, 126, 2);
+	if (csd_struct != 1 && csd_struct != 2) {
+		printk("%s: unrecognised CSD structure version %d\n",
+			mmc_hostname(card->host), csd_struct);
+		return -EINVAL;
+	}
+
+	csd->mmca_vsn	 = UNSTUFF_BITS(resp, 122, 4);
+	m = UNSTUFF_BITS(resp, 115, 4);
+	e = UNSTUFF_BITS(resp, 112, 3);
+	csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+	csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+	m = UNSTUFF_BITS(resp, 99, 4);
+	e = UNSTUFF_BITS(resp, 96, 3);
+	csd->max_dtr	  = tran_exp[e] * tran_mant[m];
+	csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
+
+	e = UNSTUFF_BITS(resp, 47, 3);
+	m = UNSTUFF_BITS(resp, 62, 12);
+	csd->capacity	  = (1 + m) << (e + 2);
+
+	csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+	csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+	csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+	csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+	csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+	csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+	csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+
+	return 0;
+}
+
+/*
+ * Read and decode extended CSD.
+ */
+static int mmc_read_ext_csd(struct mmc_card *card)
+{
+	int err;
+	u8 *ext_csd;
+
+	BUG_ON(!card);
+
+	err = MMC_ERR_FAILED;
+
+	if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+		return MMC_ERR_NONE;
+
+	/*
+	 * As the ext_csd is so large and mostly unused, we don't store the
+	 * raw block in mmc_card.
+	 */
+	ext_csd = kmalloc(512, GFP_KERNEL);
+	if (!ext_csd) {
+		printk(KERN_ERR "%s: could not allocate a buffer to "
+			"receive the ext_csd. mmc v4 cards will be "
+			"treated as v3.\n", mmc_hostname(card->host));
+		return MMC_ERR_FAILED;
+	}
+
+	err = mmc_send_ext_csd(card, ext_csd);
+	if (err != MMC_ERR_NONE) {
+		/*
+		 * High capacity cards should have this "magic" size
+		 * stored in their CSD.
+		 */
+		if (card->csd.capacity == (4096 * 512)) {
+			printk(KERN_ERR "%s: unable to read EXT_CSD "
+				"on a possible high capacity card. "
+				"Card will be ignored.\n",
+				mmc_hostname(card->host));
+		} else {
+			printk(KERN_WARNING "%s: unable to read "
+				"EXT_CSD, performance might "
+				"suffer.\n",
+				mmc_hostname(card->host));
+			err = MMC_ERR_NONE;
+		}
+		goto out;
+	}
+
+	card->ext_csd.sectors =
+		ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
+		ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
+		ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
+		ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
+	if (card->ext_csd.sectors)
+		mmc_card_set_blockaddr(card);
+
+	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(KERN_WARNING "%s: card is mmc v4 but doesn't "
+			"support any high-speed modes.\n",
+			mmc_hostname(card->host));
+		goto out;
+	}
+
+out:
+	kfree(ext_csd);
+
+	return err;
+}
+
+/*
+ * Handle the detection and initialisation of a card.
+ *
+ * In the case of a resume, "curcard" will contain the card
+ * we're trying to reinitialise.
+ */
+static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
+	struct mmc_card *oldcard)
+{
+	struct mmc_card *card;
+	int err;
+	u32 cid[4];
+	unsigned int max_dtr;
+
+	BUG_ON(!host);
+	BUG_ON(!host->claimed);
+
+	/*
+	 * Since we're changing the OCR value, we seem to
+	 * need to tell some cards to go back to the idle
+	 * state.  We wait 1ms to give cards time to
+	 * respond.
+	 */
+	mmc_go_idle(host);
+
+	/* The extra bit indicates that we support high capacity */
+	err = mmc_send_op_cond(host, ocr | (1 << 30), NULL);
+	if (err != MMC_ERR_NONE)
+		goto err;
+
+	/*
+	 * Fetch CID from card.
+	 */
+	err = mmc_all_send_cid(host, cid);
+	if (err != MMC_ERR_NONE)
+		goto err;
+
+	if (oldcard) {
+		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
+			goto err;
+
+		card = oldcard;
+	} else {
+		/*
+		 * Allocate card structure.
+		 */
+		card = mmc_alloc_card(host);
+		if (IS_ERR(card))
+			goto err;
+
+		card->type = MMC_TYPE_MMC;
+		card->rca = 1;
+		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
+	}
+
+	/*
+	 * Set card RCA.
+	 */
+	err = mmc_set_relative_addr(card);
+	if (err != MMC_ERR_NONE)
+		goto free_card;
+
+	mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+
+	if (!oldcard) {
+		/*
+		 * Fetch CSD from card.
+		 */
+		err = mmc_send_csd(card, card->raw_csd);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+
+		err = mmc_decode_csd(card);
+		if (err < 0)
+			goto free_card;
+		err = mmc_decode_cid(card);
+		if (err < 0)
+			goto free_card;
+	}
+
+	/*
+	 * Select card, as all following commands rely on that.
+	 */
+	err = mmc_select_card(card);
+	if (err != MMC_ERR_NONE)
+		goto free_card;
+
+	if (!oldcard) {
+		/*
+		 * Fetch and process extened CSD.
+		 */
+		err = mmc_read_ext_csd(card);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+	}
+
+	/*
+	 * Activate high speed (if supported)
+	 */
+	if ((card->ext_csd.hs_max_dtr != 0) &&
+		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			EXT_CSD_HS_TIMING, 1);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+
+		mmc_card_set_highspeed(card);
+
+		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+	}
+
+	/*
+	 * Compute bus speed.
+	 */
+	max_dtr = (unsigned int)-1;
+
+	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;
+	}
+
+	mmc_set_clock(host, max_dtr);
+
+	/*
+	 * Activate wide bus (if supported).
+	 */
+	if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
+		(host->caps & MMC_CAP_4_BIT_DATA)) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+
+		mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
+	}
+
+	if (!oldcard)
+		host->card = card;
+
+	return MMC_ERR_NONE;
+
+free_card:
+	if (!oldcard)
+		mmc_remove_card(card);
+err:
+
+	return MMC_ERR_FAILED;
+}
+
+/*
+ * Host is being removed. Free up the current card.
+ */
+static void mmc_remove(struct mmc_host *host)
+{
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_remove_card(host->card);
+	host->card = NULL;
+}
+
+/*
+ * Card detection callback from host.
+ */
+static void mmc_detect(struct mmc_host *host)
+{
+	int err;
+
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_claim_host(host);
+
+	/*
+	 * Just check if our card has been removed.
+	 */
+	err = mmc_send_status(host->card, NULL);
+
+	mmc_release_host(host);
+
+	if (err != MMC_ERR_NONE) {
+		mmc_remove_card(host->card);
+		host->card = NULL;
+
+		mmc_claim_host(host);
+		mmc_detach_bus(host);
+		mmc_release_host(host);
+	}
+}
+
+#ifdef CONFIG_MMC_UNSAFE_RESUME
+
+/*
+ * Suspend callback from host.
+ */
+static void mmc_suspend(struct mmc_host *host)
+{
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_claim_host(host);
+	mmc_deselect_cards(host);
+	host->card->state &= ~MMC_STATE_HIGHSPEED;
+	mmc_release_host(host);
+}
+
+/*
+ * Resume callback from host.
+ *
+ * This function tries to determine if the same card is still present
+ * and, if so, restore all state to it.
+ */
+static void mmc_resume(struct mmc_host *host)
+{
+	int err;
+
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_claim_host(host);
+
+	err = mmc_sd_init_card(host, host->ocr, host->card);
+	if (err != MMC_ERR_NONE) {
+		mmc_remove_card(host->card);
+		host->card = NULL;
+
+		mmc_detach_bus(host);
+	}
+
+	mmc_release_host(host);
+}
+
+#else
+
+#define mmc_suspend NULL
+#define mmc_resume NULL
+
+#endif
+
+static const struct mmc_bus_ops mmc_ops = {
+	.remove = mmc_remove,
+	.detect = mmc_detect,
+	.suspend = mmc_suspend,
+	.resume = mmc_resume,
+};
+
+/*
+ * Starting point for MMC card init.
+ */
+int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
+{
+	int err;
+
+	BUG_ON(!host);
+	BUG_ON(!host->claimed);
+
+	mmc_attach_bus(host, &mmc_ops);
+
+	/*
+	 * Sanity check the voltages that the card claims to
+	 * support.
+	 */
+	if (ocr & 0x7F) {
+		printk(KERN_WARNING "%s: card claims to support voltages "
+		       "below the defined range. These will be ignored.\n",
+		       mmc_hostname(host));
+		ocr &= ~0x7F;
+	}
+
+	host->ocr = mmc_select_voltage(host, ocr);
+
+	/*
+	 * Can we support the voltage of the card?
+	 */
+	if (!host->ocr)
+		goto err;
+
+	/*
+	 * Detect and init the card.
+	 */
+	err = mmc_sd_init_card(host, host->ocr, NULL);
+	if (err != MMC_ERR_NONE)
+		goto err;
+
+	mmc_release_host(host);
+
+	err = mmc_register_card(host->card);
+	if (err)
+		goto reclaim_host;
+
+	return 0;
+
+reclaim_host:
+	mmc_claim_host(host);
+	mmc_remove_card(host->card);
+	host->card = NULL;
+err:
+	mmc_detach_bus(host);
+	mmc_release_host(host);
+
+	return 0;
+}
+
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
new file mode 100644
index 0000000..7dd720f
--- /dev/null
+++ b/drivers/mmc/core/mmc_ops.c
@@ -0,0 +1,276 @@
+/*
+ *  linux/drivers/mmc/mmc_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+
+#include "core.h"
+#include "mmc_ops.h"
+
+static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SELECT_CARD;
+
+	if (card) {
+		cmd.arg = card->rca << 16;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+	} else {
+		cmd.arg = 0;
+		cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
+	}
+
+	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_select_card(struct mmc_card *card)
+{
+	BUG_ON(!card);
+
+	return _mmc_select_card(card->host, card);
+}
+
+int mmc_deselect_cards(struct mmc_host *host)
+{
+	return _mmc_select_card(host, NULL);
+}
+
+int mmc_go_idle(struct mmc_host *host)
+{
+	int err;
+	struct mmc_command cmd;
+
+	mmc_set_chip_select(host, MMC_CS_HIGH);
+
+	mmc_delay(1);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_GO_IDLE_STATE;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
+
+	err = mmc_wait_for_cmd(host, &cmd, 0);
+
+	mmc_delay(1);
+
+	mmc_set_chip_select(host, MMC_CS_DONTCARE);
+
+	mmc_delay(1);
+
+	return err;
+}
+
+int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+{
+	struct mmc_command cmd;
+	int i, err = 0;
+
+	BUG_ON(!host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SEND_OP_COND;
+	cmd.arg = ocr;
+	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
+
+	for (i = 100; i; i--) {
+		err = mmc_wait_for_cmd(host, &cmd, 0);
+		if (err != MMC_ERR_NONE)
+			break;
+
+		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+			break;
+
+		err = MMC_ERR_TIMEOUT;
+
+		mmc_delay(10);
+	}
+
+	if (rocr)
+		*rocr = cmd.resp[0];
+
+	return err;
+}
+
+int mmc_all_send_cid(struct mmc_host *host, u32 *cid)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!host);
+	BUG_ON(!cid);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_ALL_SEND_CID;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
+
+	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	memcpy(cid, cmd.resp, sizeof(u32) * 4);
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_set_relative_addr(struct mmc_card *card)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SET_RELATIVE_ADDR;
+	cmd.arg = card->rca << 16;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_send_csd(struct mmc_card *card, u32 *csd)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+	BUG_ON(!csd);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SEND_CSD;
+	cmd.arg = card->rca << 16;
+	cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	memcpy(csd, cmd.resp, sizeof(u32) * 4);
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
+{
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+	struct scatterlist sg;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+	BUG_ON(!ext_csd);
+
+	memset(&mrq, 0, sizeof(struct mmc_request));
+	memset(&cmd, 0, sizeof(struct mmc_command));
+	memset(&data, 0, sizeof(struct mmc_data));
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+
+	cmd.opcode = MMC_SEND_EXT_CSD;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	data.blksz = 512;
+	data.blocks = 1;
+	data.flags = MMC_DATA_READ;
+	data.sg = &sg;
+	data.sg_len = 1;
+
+	sg_init_one(&sg, ext_csd, 512);
+
+	mmc_set_data_timeout(&data, card, 0);
+
+	mmc_wait_for_req(card->host, &mrq);
+
+	if (cmd.error != MMC_ERR_NONE)
+		return cmd.error;
+	if (data.error != MMC_ERR_NONE)
+		return data.error;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SWITCH;
+	cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+		  (index << 16) |
+		  (value << 8) |
+		  set;
+	cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_send_status(struct mmc_card *card, u32 *status)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = MMC_SEND_STATUS;
+	cmd.arg = card->rca << 16;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	if (status)
+		*status = cmd.resp[0];
+
+	return MMC_ERR_NONE;
+}
+
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
new file mode 100644
index 0000000..7a481e8
--- /dev/null
+++ b/drivers/mmc/core/mmc_ops.h
@@ -0,0 +1,27 @@
+/*
+ *  linux/drivers/mmc/mmc_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef _MMC_MMC_OPS_H
+#define _MMC_MMC_OPS_H
+
+int mmc_select_card(struct mmc_card *card);
+int mmc_deselect_cards(struct mmc_host *host);
+int mmc_go_idle(struct mmc_host *host);
+int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
+int mmc_all_send_cid(struct mmc_host *host, u32 *cid);
+int mmc_set_relative_addr(struct mmc_card *card);
+int mmc_send_csd(struct mmc_card *card, u32 *csd);
+int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
+int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value);
+int mmc_send_status(struct mmc_card *card, u32 *status);
+
+#endif
+
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
new file mode 100644
index 0000000..c1dfd03
--- /dev/null
+++ b/drivers/mmc/core/sd.c
@@ -0,0 +1,587 @@
+/*
+ *  linux/drivers/mmc/sd.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
+ *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, 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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+
+#include "core.h"
+#include "sysfs.h"
+#include "mmc_ops.h"
+#include "sd_ops.h"
+
+#include "core.h"
+
+static const unsigned int tran_exp[] = {
+	10000,		100000,		1000000,	10000000,
+	0,		0,		0,		0
+};
+
+static const unsigned char tran_mant[] = {
+	0,	10,	12,	13,	15,	20,	25,	30,
+	35,	40,	45,	50,	55,	60,	70,	80,
+};
+
+static const unsigned int tacc_exp[] = {
+	1,	10,	100,	1000,	10000,	100000,	1000000, 10000000,
+};
+
+static const unsigned int tacc_mant[] = {
+	0,	10,	12,	13,	15,	20,	25,	30,
+	35,	40,	45,	50,	55,	60,	70,	80,
+};
+
+#define UNSTUFF_BITS(resp,start,size)					\
+	({								\
+		const int __size = size;				\
+		const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1;	\
+		const int __off = 3 - ((start) / 32);			\
+		const int __shft = (start) & 31;			\
+		u32 __res;						\
+									\
+		__res = resp[__off] >> __shft;				\
+		if (__size + __shft > 32)				\
+			__res |= resp[__off-1] << ((32 - __shft) % 32);	\
+		__res & __mask;						\
+	})
+
+/*
+ * Given the decoded CSD structure, decode the raw CID to our CID structure.
+ */
+static void mmc_decode_cid(struct mmc_card *card)
+{
+	u32 *resp = card->raw_cid;
+
+	memset(&card->cid, 0, sizeof(struct mmc_cid));
+
+	/*
+	 * SD doesn't currently have a version field so we will
+	 * have to assume we can parse this.
+	 */
+	card->cid.manfid		= UNSTUFF_BITS(resp, 120, 8);
+	card->cid.oemid			= UNSTUFF_BITS(resp, 104, 16);
+	card->cid.prod_name[0]		= UNSTUFF_BITS(resp, 96, 8);
+	card->cid.prod_name[1]		= UNSTUFF_BITS(resp, 88, 8);
+	card->cid.prod_name[2]		= UNSTUFF_BITS(resp, 80, 8);
+	card->cid.prod_name[3]		= UNSTUFF_BITS(resp, 72, 8);
+	card->cid.prod_name[4]		= UNSTUFF_BITS(resp, 64, 8);
+	card->cid.hwrev			= UNSTUFF_BITS(resp, 60, 4);
+	card->cid.fwrev			= UNSTUFF_BITS(resp, 56, 4);
+	card->cid.serial		= UNSTUFF_BITS(resp, 24, 32);
+	card->cid.year			= UNSTUFF_BITS(resp, 12, 8);
+	card->cid.month			= UNSTUFF_BITS(resp, 8, 4);
+
+	card->cid.year += 2000; /* SD cards year offset */
+}
+
+/*
+ * Given a 128-bit response, decode to our card CSD structure.
+ */
+static int mmc_decode_csd(struct mmc_card *card)
+{
+	struct mmc_csd *csd = &card->csd;
+	unsigned int e, m, csd_struct;
+	u32 *resp = card->raw_csd;
+
+	csd_struct = UNSTUFF_BITS(resp, 126, 2);
+
+	switch (csd_struct) {
+	case 0:
+		m = UNSTUFF_BITS(resp, 115, 4);
+		e = UNSTUFF_BITS(resp, 112, 3);
+		csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+		csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+		m = UNSTUFF_BITS(resp, 99, 4);
+		e = UNSTUFF_BITS(resp, 96, 3);
+		csd->max_dtr	  = tran_exp[e] * tran_mant[m];
+		csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
+
+		e = UNSTUFF_BITS(resp, 47, 3);
+		m = UNSTUFF_BITS(resp, 62, 12);
+		csd->capacity	  = (1 + m) << (e + 2);
+
+		csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+		csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+		csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+		csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+		csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+		csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+		csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+		break;
+	case 1:
+		/*
+		 * This is a block-addressed SDHC card. Most
+		 * interesting fields are unused and have fixed
+		 * values. To avoid getting tripped by buggy cards,
+		 * we assume those fixed values ourselves.
+		 */
+		mmc_card_set_blockaddr(card);
+
+		csd->tacc_ns	 = 0; /* Unused */
+		csd->tacc_clks	 = 0; /* Unused */
+
+		m = UNSTUFF_BITS(resp, 99, 4);
+		e = UNSTUFF_BITS(resp, 96, 3);
+		csd->max_dtr	  = tran_exp[e] * tran_mant[m];
+		csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
+
+		m = UNSTUFF_BITS(resp, 48, 22);
+		csd->capacity     = (1 + m) << 10;
+
+		csd->read_blkbits = 9;
+		csd->read_partial = 0;
+		csd->write_misalign = 0;
+		csd->read_misalign = 0;
+		csd->r2w_factor = 4; /* Unused */
+		csd->write_blkbits = 9;
+		csd->write_partial = 0;
+		break;
+	default:
+		printk("%s: unrecognised CSD structure version %d\n",
+			mmc_hostname(card->host), csd_struct);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Given a 64-bit response, decode to our card SCR structure.
+ */
+static int mmc_decode_scr(struct mmc_card *card)
+{
+	struct sd_scr *scr = &card->scr;
+	unsigned int scr_struct;
+	u32 resp[4];
+
+	BUG_ON(!mmc_card_sd(card));
+
+	resp[3] = card->raw_scr[1];
+	resp[2] = card->raw_scr[0];
+
+	scr_struct = UNSTUFF_BITS(resp, 60, 4);
+	if (scr_struct != 0) {
+		printk("%s: unrecognised SCR structure version %d\n",
+			mmc_hostname(card->host), scr_struct);
+		return -EINVAL;
+	}
+
+	scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
+	scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
+
+	return 0;
+}
+
+/*
+ * Fetches and decodes switch information
+ */
+static int mmc_read_switch(struct mmc_card *card)
+{
+	int err;
+	u8 *status;
+
+	err = MMC_ERR_FAILED;
+
+	status = kmalloc(64, GFP_KERNEL);
+	if (!status) {
+		printk("%s: could not allocate a buffer for switch "
+		       "capabilities.\n",
+			mmc_hostname(card->host));
+		return err;
+	}
+
+	err = mmc_sd_switch(card, 0, 0, 1, status);
+	if (err != MMC_ERR_NONE) {
+		/*
+		 * Card not supporting high-speed will ignore the
+		 * command.
+		 */
+		err = MMC_ERR_NONE;
+		goto out;
+	}
+
+	if (status[13] & 0x02)
+		card->sw_caps.hs_max_dtr = 50000000;
+
+out:
+	kfree(status);
+
+	return err;
+}
+
+/*
+ * Test if the card supports high-speed mode and, if so, switch to it.
+ */
+static int mmc_switch_hs(struct mmc_card *card)
+{
+	int err;
+	u8 *status;
+
+	if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
+		return MMC_ERR_NONE;
+
+	if (card->sw_caps.hs_max_dtr == 0)
+		return MMC_ERR_NONE;
+
+	err = MMC_ERR_FAILED;
+
+	status = kmalloc(64, GFP_KERNEL);
+	if (!status) {
+		printk("%s: could not allocate a buffer for switch "
+		       "capabilities.\n",
+			mmc_hostname(card->host));
+		return err;
+	}
+
+	err = mmc_sd_switch(card, 1, 0, 1, status);
+	if (err != MMC_ERR_NONE)
+		goto out;
+
+	if ((status[16] & 0xF) != 1) {
+		printk(KERN_WARNING "%s: Problem switching card "
+			"into high-speed mode!\n",
+			mmc_hostname(card->host));
+	} else {
+		mmc_card_set_highspeed(card);
+		mmc_set_timing(card->host, MMC_TIMING_SD_HS);
+	}
+
+out:
+	kfree(status);
+
+	return err;
+}
+
+/*
+ * Handle the detection and initialisation of a card.
+ *
+ * In the case of a resume, "curcard" will contain the card
+ * we're trying to reinitialise.
+ */
+static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
+	struct mmc_card *oldcard)
+{
+	struct mmc_card *card;
+	int err;
+	u32 cid[4];
+	unsigned int max_dtr;
+
+	BUG_ON(!host);
+	BUG_ON(!host->claimed);
+
+	/*
+	 * Since we're changing the OCR value, we seem to
+	 * need to tell some cards to go back to the idle
+	 * state.  We wait 1ms to give cards time to
+	 * respond.
+	 */
+	mmc_go_idle(host);
+
+	/*
+	 * If SD_SEND_IF_COND indicates an SD 2.0
+	 * compliant card and we should set bit 30
+	 * of the ocr to indicate that we can handle
+	 * block-addressed SDHC cards.
+	 */
+	err = mmc_send_if_cond(host, ocr);
+	if (err == MMC_ERR_NONE)
+		ocr |= 1 << 30;
+
+	err = mmc_send_app_op_cond(host, ocr, NULL);
+	if (err != MMC_ERR_NONE)
+		goto err;
+
+	/*
+	 * Fetch CID from card.
+	 */
+	err = mmc_all_send_cid(host, cid);
+	if (err != MMC_ERR_NONE)
+		goto err;
+
+	if (oldcard) {
+		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0)
+			goto err;
+
+		card = oldcard;
+	} else {
+		/*
+		 * Allocate card structure.
+		 */
+		card = mmc_alloc_card(host);
+		if (IS_ERR(card))
+			goto err;
+
+		card->type = MMC_TYPE_SD;
+		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
+	}
+
+	/*
+	 * Set card RCA.
+	 */
+	err = mmc_send_relative_addr(host, &card->rca);
+	if (err != MMC_ERR_NONE)
+		goto free_card;
+
+	mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
+
+	if (!oldcard) {
+		/*
+		 * Fetch CSD from card.
+		 */
+		err = mmc_send_csd(card, card->raw_csd);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+
+		err = mmc_decode_csd(card);
+		if (err < 0)
+			goto free_card;
+
+		mmc_decode_cid(card);
+	}
+
+	/*
+	 * Select card, as all following commands rely on that.
+	 */
+	err = mmc_select_card(card);
+	if (err != MMC_ERR_NONE)
+		goto free_card;
+
+	if (!oldcard) {
+		/*
+		 * Fetch SCR from card.
+		 */
+		err = mmc_app_send_scr(card, card->raw_scr);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+
+		err = mmc_decode_scr(card);
+		if (err < 0)
+			goto free_card;
+
+		/*
+		 * Fetch switch information from card.
+		 */
+		err = mmc_read_switch(card);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+	}
+
+	/*
+	 * Attempt to change to high-speed (if supported)
+	 */
+	err = mmc_switch_hs(card);
+	if (err != MMC_ERR_NONE)
+		goto free_card;
+
+	/*
+	 * Compute bus speed.
+	 */
+	max_dtr = (unsigned int)-1;
+
+	if (mmc_card_highspeed(card)) {
+		if (max_dtr > card->sw_caps.hs_max_dtr)
+			max_dtr = card->sw_caps.hs_max_dtr;
+	} else if (max_dtr > card->csd.max_dtr) {
+		max_dtr = card->csd.max_dtr;
+	}
+
+	mmc_set_clock(host, max_dtr);
+
+	/*
+	 * Switch to wider bus (if supported).
+	 */
+	if ((host->caps && MMC_CAP_4_BIT_DATA) &&
+		(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+		err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
+		if (err != MMC_ERR_NONE)
+			goto free_card;
+
+		mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
+	}
+
+	if (!oldcard)
+		host->card = card;
+
+	return MMC_ERR_NONE;
+
+free_card:
+	if (!oldcard)
+		mmc_remove_card(card);
+err:
+
+	return MMC_ERR_FAILED;
+}
+
+/*
+ * Host is being removed. Free up the current card.
+ */
+static void mmc_sd_remove(struct mmc_host *host)
+{
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_remove_card(host->card);
+	host->card = NULL;
+}
+
+/*
+ * Card detection callback from host.
+ */
+static void mmc_sd_detect(struct mmc_host *host)
+{
+	int err;
+
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_claim_host(host);
+
+	/*
+	 * Just check if our card has been removed.
+	 */
+	err = mmc_send_status(host->card, NULL);
+
+	mmc_release_host(host);
+
+	if (err != MMC_ERR_NONE) {
+		mmc_remove_card(host->card);
+		host->card = NULL;
+
+		mmc_claim_host(host);
+		mmc_detach_bus(host);
+		mmc_release_host(host);
+	}
+}
+
+#ifdef CONFIG_MMC_UNSAFE_RESUME
+
+/*
+ * Suspend callback from host.
+ */
+static void mmc_sd_suspend(struct mmc_host *host)
+{
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_claim_host(host);
+	mmc_deselect_cards(host);
+	host->card->state &= ~MMC_STATE_HIGHSPEED;
+	mmc_release_host(host);
+}
+
+/*
+ * Resume callback from host.
+ *
+ * This function tries to determine if the same card is still present
+ * and, if so, restore all state to it.
+ */
+static void mmc_sd_resume(struct mmc_host *host)
+{
+	int err;
+
+	BUG_ON(!host);
+	BUG_ON(!host->card);
+
+	mmc_claim_host(host);
+
+	err = mmc_sd_init_card(host, host->ocr, host->card);
+	if (err != MMC_ERR_NONE) {
+		mmc_remove_card(host->card);
+		host->card = NULL;
+
+		mmc_detach_bus(host);
+	}
+
+	mmc_release_host(host);
+}
+
+#else
+
+#define mmc_sd_suspend NULL
+#define mmc_sd_resume NULL
+
+#endif
+
+static const struct mmc_bus_ops mmc_sd_ops = {
+	.remove = mmc_sd_remove,
+	.detect = mmc_sd_detect,
+	.suspend = mmc_sd_suspend,
+	.resume = mmc_sd_resume,
+};
+
+/*
+ * Starting point for SD card init.
+ */
+int mmc_attach_sd(struct mmc_host *host, u32 ocr)
+{
+	int err;
+
+	BUG_ON(!host);
+	BUG_ON(!host->claimed);
+
+	mmc_attach_bus(host, &mmc_sd_ops);
+
+	/*
+	 * Sanity check the voltages that the card claims to
+	 * support.
+	 */
+	if (ocr & 0x7F) {
+		printk(KERN_WARNING "%s: card claims to support voltages "
+		       "below the defined range. These will be ignored.\n",
+		       mmc_hostname(host));
+		ocr &= ~0x7F;
+	}
+
+	if (ocr & MMC_VDD_165_195) {
+		printk(KERN_WARNING "%s: SD card claims to support the "
+		       "incompletely defined 'low voltage range'. This "
+		       "will be ignored.\n", mmc_hostname(host));
+		ocr &= ~MMC_VDD_165_195;
+	}
+
+	host->ocr = mmc_select_voltage(host, ocr);
+
+	/*
+	 * Can we support the voltage(s) of the card(s)?
+	 */
+	if (!host->ocr)
+		goto err;
+
+	/*
+	 * Detect and init the card.
+	 */
+	err = mmc_sd_init_card(host, host->ocr, NULL);
+	if (err != MMC_ERR_NONE)
+		goto err;
+
+	mmc_release_host(host);
+
+	err = mmc_register_card(host->card);
+	if (err)
+		goto reclaim_host;
+
+	return 0;
+
+reclaim_host:
+	mmc_claim_host(host);
+	mmc_remove_card(host->card);
+	host->card = NULL;
+err:
+	mmc_detach_bus(host);
+	mmc_release_host(host);
+
+	return 0;
+}
+
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
new file mode 100644
index 0000000..9697ce5
--- /dev/null
+++ b/drivers/mmc/core/sd_ops.c
@@ -0,0 +1,316 @@
+/*
+ *  linux/drivers/mmc/sd_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+
+#include "core.h"
+#include "sd_ops.h"
+
+/**
+ *	mmc_wait_for_app_cmd - start an application command and wait for
+ 			       completion
+ *	@host: MMC host to start command
+ *	@rca: RCA to send MMC_APP_CMD to
+ *	@cmd: MMC command to start
+ *	@retries: maximum number of retries
+ *
+ *	Sends a MMC_APP_CMD, checks the card response, sends the command
+ *	in the parameter and waits for it to complete. Return any error
+ *	that occurred while the command was executing.  Do not attempt to
+ *	parse the response.
+ */
+int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card,
+	struct mmc_command *cmd, int retries)
+{
+	struct mmc_request mrq;
+
+	int i, err;
+
+	BUG_ON(!cmd);
+	BUG_ON(retries < 0);
+
+	err = MMC_ERR_INVALID;
+
+	/*
+	 * We have to resend MMC_APP_CMD for each attempt so
+	 * we cannot use the retries field in mmc_command.
+	 */
+	for (i = 0;i <= retries;i++) {
+		memset(&mrq, 0, sizeof(struct mmc_request));
+
+		err = mmc_app_cmd(host, card);
+		if (err != MMC_ERR_NONE)
+			continue;
+
+		memset(&mrq, 0, sizeof(struct mmc_request));
+
+		memset(cmd->resp, 0, sizeof(cmd->resp));
+		cmd->retries = 0;
+
+		mrq.cmd = cmd;
+		cmd->data = NULL;
+
+		mmc_wait_for_req(host, &mrq);
+
+		err = cmd->error;
+		if (cmd->error == MMC_ERR_NONE)
+			break;
+	}
+
+	return err;
+}
+
+EXPORT_SYMBOL(mmc_wait_for_app_cmd);
+
+int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!host);
+	BUG_ON(card && (card->host != host));
+
+	cmd.opcode = MMC_APP_CMD;
+
+	if (card) {
+		cmd.arg = card->rca << 16;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+	} else {
+		cmd.arg = 0;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_BCR;
+	}
+
+	err = mmc_wait_for_cmd(host, &cmd, 0);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	/* Check that card supported application commands */
+	if (!(cmd.resp[0] & R1_APP_CMD))
+		return MMC_ERR_FAILED;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_app_set_bus_width(struct mmc_card *card, int width)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = SD_APP_SET_BUS_WIDTH;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+	switch (width) {
+	case MMC_BUS_WIDTH_1:
+		cmd.arg = SD_BUS_WIDTH_1;
+		break;
+	case MMC_BUS_WIDTH_4:
+		cmd.arg = SD_BUS_WIDTH_4;
+		break;
+	default:
+		return MMC_ERR_INVALID;
+	}
+
+	err = mmc_wait_for_app_cmd(card->host, card, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
+{
+	struct mmc_command cmd;
+	int i, err = 0;
+
+	BUG_ON(!host);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = SD_APP_OP_COND;
+	cmd.arg = ocr;
+	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
+
+	for (i = 100; i; i--) {
+		err = mmc_wait_for_app_cmd(host, NULL, &cmd, MMC_CMD_RETRIES);
+		if (err != MMC_ERR_NONE)
+			break;
+
+		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
+			break;
+
+		err = MMC_ERR_TIMEOUT;
+
+		mmc_delay(10);
+	}
+
+	if (rocr)
+		*rocr = cmd.resp[0];
+
+	return err;
+}
+
+int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
+{
+	struct mmc_command cmd;
+	int err;
+	static const u8 test_pattern = 0xAA;
+
+	/*
+	 * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
+	 * before SD_APP_OP_COND. This command will harmlessly fail for
+	 * SD 1.0 cards.
+	 */
+	cmd.opcode = SD_SEND_IF_COND;
+	cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
+	cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
+
+	err = mmc_wait_for_cmd(host, &cmd, 0);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	if ((cmd.resp[0] & 0xFF) != test_pattern)
+		return MMC_ERR_FAILED;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca)
+{
+	int err;
+	struct mmc_command cmd;
+
+	BUG_ON(!host);
+	BUG_ON(!rca);
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = SD_SEND_RELATIVE_ADDR;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
+
+	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	*rca = cmd.resp[0] >> 16;
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_app_send_scr(struct mmc_card *card, u32 *scr)
+{
+	int err;
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+	struct scatterlist sg;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+	BUG_ON(!scr);
+
+	err = mmc_app_cmd(card->host, card);
+	if (err != MMC_ERR_NONE)
+		return err;
+
+	memset(&mrq, 0, sizeof(struct mmc_request));
+	memset(&cmd, 0, sizeof(struct mmc_command));
+	memset(&data, 0, sizeof(struct mmc_data));
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+
+	cmd.opcode = SD_APP_SEND_SCR;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	data.blksz = 8;
+	data.blocks = 1;
+	data.flags = MMC_DATA_READ;
+	data.sg = &sg;
+	data.sg_len = 1;
+
+	sg_init_one(&sg, scr, 8);
+
+	mmc_set_data_timeout(&data, card, 0);
+
+	mmc_wait_for_req(card->host, &mrq);
+
+	if (cmd.error != MMC_ERR_NONE)
+		return cmd.error;
+	if (data.error != MMC_ERR_NONE)
+		return data.error;
+
+	scr[0] = ntohl(scr[0]);
+	scr[1] = ntohl(scr[1]);
+
+	return MMC_ERR_NONE;
+}
+
+int mmc_sd_switch(struct mmc_card *card, int mode, int group,
+	u8 value, u8 *resp)
+{
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+	struct scatterlist sg;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+
+	mode = !!mode;
+	value &= 0xF;
+
+	memset(&mrq, 0, sizeof(struct mmc_request));
+	memset(&cmd, 0, sizeof(struct mmc_command));
+	memset(&data, 0, sizeof(struct mmc_data));
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+
+	cmd.opcode = SD_SWITCH;
+	cmd.arg = mode << 31 | 0x00FFFFFF;
+	cmd.arg &= ~(0xF << (group * 4));
+	cmd.arg |= value << (group * 4);
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	data.blksz = 64;
+	data.blocks = 1;
+	data.flags = MMC_DATA_READ;
+	data.sg = &sg;
+	data.sg_len = 1;
+
+	sg_init_one(&sg, resp, 64);
+
+	mmc_set_data_timeout(&data, card, 0);
+
+	mmc_wait_for_req(card->host, &mrq);
+
+	if (cmd.error != MMC_ERR_NONE)
+		return cmd.error;
+	if (data.error != MMC_ERR_NONE)
+		return data.error;
+
+	return MMC_ERR_NONE;
+}
+
diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h
new file mode 100644
index 0000000..1240fdd
--- /dev/null
+++ b/drivers/mmc/core/sd_ops.h
@@ -0,0 +1,25 @@
+/*
+ *  linux/drivers/mmc/sd_ops.h
+ *
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef _MMC_SD_OPS_H
+#define _MMC_SD_OPS_H
+
+int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card);
+int mmc_app_set_bus_width(struct mmc_card *card, int width);
+int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
+int mmc_send_if_cond(struct mmc_host *host, u32 ocr);
+int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca);
+int mmc_app_send_scr(struct mmc_card *card, u32 *scr);
+int mmc_sd_switch(struct mmc_card *card, int mode, int group,
+	u8 value, u8 *resp);
+
+#endif
+
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/core/sysfs.c
similarity index 97%
rename from drivers/mmc/mmc_sysfs.c
rename to drivers/mmc/core/sysfs.c
index e0e82d8..843b1fb 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/core/sysfs.c
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/mmc/mmc_sysfs.c
+ *  linux/drivers/mmc/core/sysfs.c
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
  *
@@ -18,7 +18,7 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 
-#include "mmc.h"
+#include "sysfs.h"
 
 #define dev_to_mmc_card(d)	container_of(d, struct mmc_card, dev)
 #define to_mmc_driver(d)	container_of(d, struct mmc_driver, drv)
@@ -72,12 +72,11 @@
 /*
  * This currently matches any MMC driver to any MMC card - drivers
  * themselves make the decision whether to drive this card in their
- * probe method.  However, we force "bad" cards to fail.
+ * probe method.
  */
 static int mmc_bus_match(struct device *dev, struct device_driver *drv)
 {
-	struct mmc_card *card = dev_to_mmc_card(dev);
-	return !mmc_card_bad(card);
+	return 1;
 }
 
 static int
@@ -217,6 +216,8 @@
 				device_del(&card->dev);
 		}
 	}
+	if (ret == 0)
+		mmc_card_set_present(card);
 	return ret;
 }
 
diff --git a/drivers/mmc/mmc.h b/drivers/mmc/core/sysfs.h
similarity index 86%
rename from drivers/mmc/mmc.h
rename to drivers/mmc/core/sysfs.h
index 149affe..80e29b3 100644
--- a/drivers/mmc/mmc.h
+++ b/drivers/mmc/core/sysfs.h
@@ -1,15 +1,16 @@
 /*
- *  linux/drivers/mmc/mmc.h
+ *  linux/drivers/mmc/core/sysfs.h
  *
  *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2007 Pierre Ossman
  *
  * 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
  * published by the Free Software Foundation.
  */
-#ifndef _MMC_H
-#define _MMC_H
-/* core-internal functions */
+#ifndef _MMC_CORE_SYSFS_H
+#define _MMC_CORE_SYSFS_H
+
 void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
 int mmc_register_card(struct mmc_card *card);
 void mmc_remove_card(struct mmc_card *card);
@@ -22,4 +23,5 @@
 int mmc_schedule_work(struct work_struct *work);
 int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay);
 void mmc_flush_scheduled_work(void);
+
 #endif
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
new file mode 100644
index 0000000..ed4deab
--- /dev/null
+++ b/drivers/mmc/host/Kconfig
@@ -0,0 +1,103 @@
+#
+# MMC/SD host controller drivers
+#
+
+comment "MMC/SD Host Controller Drivers"
+	depends on MMC
+
+config MMC_ARMMMCI
+	tristate "ARM AMBA Multimedia Card Interface support"
+	depends on ARM_AMBA && MMC
+	help
+	  This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card
+	  Interface (PL180 and PL181) support.  If you have an ARM(R)
+	  platform with a Multimedia Card slot, say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_PXA
+	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.
+	  If you have a PXA(R) platform with a Multimedia Card slot,
+	  say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_SDHCI
+	tristate "Secure Digital Host Controller Interface support  (EXPERIMENTAL)"
+	depends on PCI && MMC && EXPERIMENTAL
+	help
+	  This select the generic Secure Digital Host Controller Interface.
+	  It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
+	  and Toshiba(R). Most controllers found in laptops are of this type.
+	  If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_OMAP
+	tristate "TI OMAP Multimedia Card Interface support"
+	depends on ARCH_OMAP && MMC
+	select TPS65010 if MACH_OMAP_H2
+	help
+	  This selects the TI OMAP Multimedia card Interface.
+	  If you have an OMAP board with a Multimedia Card slot,
+	  say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_WBSD
+	tristate "Winbond W83L51xD SD/MMC Card Interface support"
+	depends on MMC && ISA_DMA_API
+	help
+	  This selects the Winbond(R) W83L51xD Secure digital and
+          Multimedia card Interface.
+	  If you have a machine with a integrated W83L518D or W83L519D
+	  SD/MMC card reader, say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_AU1X
+	tristate "Alchemy AU1XX0 MMC Card Interface support"
+	depends on MMC && SOC_AU1200
+	help
+	  This selects the AMD Alchemy(R) Multimedia card interface.
+	  If you have a Alchemy platform with a MMC slot, say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_AT91
+	tristate "AT91 SD/MMC Card Interface support"
+	depends on ARCH_AT91 && MMC
+	help
+	  This selects the AT91 MCI controller.
+
+	  If unsure, say N.
+
+config MMC_IMX
+	tristate "Motorola i.MX Multimedia Card Interface support"
+	depends on ARCH_IMX && MMC
+	help
+	  This selects the Motorola i.MX Multimedia card Interface.
+	  If you have a i.MX platform with a Multimedia Card slot,
+	  say Y or M here.
+
+	  If unsure, say N.
+
+config MMC_TIFM_SD
+	tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
+	depends on MMC && EXPERIMENTAL && PCI
+	select TIFM_CORE
+	help
+	  Say Y here if you want to be able to access MMC/SD cards with
+	  the Texas Instruments(R) Flash Media card reader, found in many
+	  laptops.
+	  This option 'selects' (turns on, enables) 'TIFM_CORE', but you
+	  probably also need appropriate card reader host adapter, such as
+	  'Misc devices: TI Flash Media PCI74xx/PCI76xx host adapter support
+	  (TIFM_7XX1)'.
+
+          To compile this driver as a module, choose M here: the
+	  module will be called tifm_sd.
+
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
new file mode 100644
index 0000000..6685f64
--- /dev/null
+++ b/drivers/mmc/host/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for MMC/SD host controller drivers
+#
+
+ifeq ($(CONFIG_MMC_DEBUG),y)
+	EXTRA_CFLAGS		+= -DDEBUG
+endif
+
+obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o
+obj-$(CONFIG_MMC_PXA)		+= pxamci.o
+obj-$(CONFIG_MMC_IMX)		+= imxmmc.o
+obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
+obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
+obj-$(CONFIG_MMC_AU1X)		+= au1xmmc.o
+obj-$(CONFIG_MMC_OMAP)		+= omap.o
+obj-$(CONFIG_MMC_AT91)		+= at91_mci.o
+obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o
+
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/host/at91_mci.c
similarity index 99%
rename from drivers/mmc/at91_mci.c
rename to drivers/mmc/host/at91_mci.c
index 459f4b4fe..e37943c 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -67,7 +67,6 @@
 #include <linux/atmel_pdc.h>
 
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
similarity index 99%
rename from drivers/mmc/au1xmmc.c
rename to drivers/mmc/host/au1xmmc.c
index b834be2..b7156a4 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -42,7 +42,6 @@
 #include <linux/dma-mapping.h>
 
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 #include <asm/io.h>
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
diff --git a/drivers/mmc/au1xmmc.h b/drivers/mmc/host/au1xmmc.h
similarity index 100%
rename from drivers/mmc/au1xmmc.h
rename to drivers/mmc/host/au1xmmc.h
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/host/imxmmc.c
similarity index 99%
rename from drivers/mmc/imxmmc.c
rename to drivers/mmc/host/imxmmc.c
index 0de5c9e..7ee2045 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/host/imxmmc.c
@@ -41,7 +41,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
-#include <linux/mmc/protocol.h>
 #include <linux/delay.h>
 
 #include <asm/dma.h>
diff --git a/drivers/mmc/imxmmc.h b/drivers/mmc/host/imxmmc.h
similarity index 100%
rename from drivers/mmc/imxmmc.h
rename to drivers/mmc/host/imxmmc.h
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/host/mmci.c
similarity index 99%
rename from drivers/mmc/mmci.c
rename to drivers/mmc/host/mmci.c
index 5941dd9..d11c2d2 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -17,7 +17,6 @@
 #include <linux/err.h>
 #include <linux/highmem.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 #include <linux/amba/bus.h>
 #include <linux/clk.h>
 
diff --git a/drivers/mmc/mmci.h b/drivers/mmc/host/mmci.h
similarity index 100%
rename from drivers/mmc/mmci.h
rename to drivers/mmc/host/mmci.h
diff --git a/drivers/mmc/omap.c b/drivers/mmc/host/omap.c
similarity index 97%
rename from drivers/mmc/omap.c
rename to drivers/mmc/host/omap.c
index 1e96a2f..1914e65 100644
--- a/drivers/mmc/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -22,7 +22,6 @@
 #include <linux/spinlock.h>
 #include <linux/timer.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 #include <linux/mmc/card.h>
 #include <linux/clk.h>
 
@@ -605,7 +604,7 @@
 	}
 	if (mmc_omap_cover_is_open(host)) {
 		if (!complained) {
-			dev_info(mmc_dev(host->mmc), "cover is open");
+			dev_info(mmc_dev(host->mmc), "cover is open\n");
 			complained = 1;
 		}
 		if (mmc_omap_enable_poll)
@@ -937,48 +936,55 @@
 	}
 }
 
+static int mmc_omap_calc_divisor(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct mmc_omap_host *host = mmc_priv(mmc);
+	int func_clk_rate = clk_get_rate(host->fclk);
+	int dsor;
+
+	if (ios->clock == 0)
+		return 0;
+
+	dsor = func_clk_rate / ios->clock;
+	if (dsor < 1)
+		dsor = 1;
+
+	if (func_clk_rate / dsor > ios->clock)
+		dsor++;
+
+	if (dsor > 250)
+		dsor = 250;
+	dsor++;
+
+	if (ios->bus_width == MMC_BUS_WIDTH_4)
+		dsor |= 1 << 15;
+
+	return dsor;
+}
+
 static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct mmc_omap_host *host = mmc_priv(mmc);
 	int dsor;
-	int realclock, i;
+	int i;
 
-	realclock = ios->clock;
-
-	if (ios->clock == 0)
-		dsor = 0;
-	else {
-		int func_clk_rate = clk_get_rate(host->fclk);
-
-		dsor = func_clk_rate / realclock;
-		if (dsor < 1)
-			dsor = 1;
-
-		if (func_clk_rate / dsor > realclock)
-			dsor++;
-
-		if (dsor > 250)
-			dsor = 250;
-		dsor++;
-
-		if (ios->bus_width == MMC_BUS_WIDTH_4)
-			dsor |= 1 << 15;
-	}
+	dsor = mmc_omap_calc_divisor(mmc, ios);
+	host->bus_mode = ios->bus_mode;
+	host->hw_bus_mode = host->bus_mode;
 
 	switch (ios->power_mode) {
 	case MMC_POWER_OFF:
 		mmc_omap_power(host, 0);
 		break;
 	case MMC_POWER_UP:
-	case MMC_POWER_ON:
+		/* Cannot touch dsor yet, just power up MMC */
 		mmc_omap_power(host, 1);
+		return;
+	case MMC_POWER_ON:
 		dsor |= 1 << 11;
 		break;
 	}
 
-	host->bus_mode = ios->bus_mode;
-	host->hw_bus_mode = host->bus_mode;
-
 	clk_enable(host->fclk);
 
 	/* On insanely high arm_per frequencies something sometimes
@@ -987,7 +993,7 @@
 	 * Writing to the CON register twice seems to do the trick. */
 	for (i = 0; i < 2; i++)
 		OMAP_MMC_WRITE(host, CON, dsor);
-	if (ios->power_mode == MMC_POWER_UP) {
+	if (ios->power_mode == MMC_POWER_ON) {
 		/* Send clock cycles, poll completion */
 		OMAP_MMC_WRITE(host, IE, 0);
 		OMAP_MMC_WRITE(host, STAT, 0xffff);
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/host/pxamci.c
similarity index 99%
rename from drivers/mmc/pxamci.c
rename to drivers/mmc/host/pxamci.c
index 9774fc6..a98ff98 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -24,7 +24,6 @@
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 
 #include <asm/dma.h>
 #include <asm/io.h>
diff --git a/drivers/mmc/pxamci.h b/drivers/mmc/host/pxamci.h
similarity index 100%
rename from drivers/mmc/pxamci.h
rename to drivers/mmc/host/pxamci.h
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/host/sdhci.c
similarity index 97%
rename from drivers/mmc/sdhci.c
rename to drivers/mmc/host/sdhci.c
index d749f08..ff5bf73 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/sdhci.c - Secure Digital Host Controller Interface driver
  *
- *  Copyright (C) 2005-2006 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, 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 as published by
@@ -15,7 +15,6 @@
 #include <linux/dma-mapping.h>
 
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 
 #include <asm/scatterlist.h>
 
@@ -247,14 +246,13 @@
 			chunk_remain = min(blksize, 4);
 		}
 
-		size = min(host->size, host->remain);
-		size = min(size, chunk_remain);
+		size = min(host->remain, chunk_remain);
 
 		chunk_remain -= size;
 		blksize -= size;
 		host->offset += size;
 		host->remain -= size;
-		host->size -= size;
+
 		while (size) {
 			*buffer = data & 0xFF;
 			buffer++;
@@ -289,14 +287,13 @@
 	buffer = sdhci_sg_to_buffer(host) + host->offset;
 
 	while (blksize) {
-		size = min(host->size, host->remain);
-		size = min(size, chunk_remain);
+		size = min(host->remain, chunk_remain);
 
 		chunk_remain -= size;
 		blksize -= size;
 		host->offset += size;
 		host->remain -= size;
-		host->size -= size;
+
 		while (size) {
 			data >>= 8;
 			data |= (u32)*buffer << 24;
@@ -325,7 +322,7 @@
 
 	BUG_ON(!host->data);
 
-	if (host->size == 0)
+	if (host->num_sg == 0)
 		return;
 
 	if (host->data->flags & MMC_DATA_READ)
@@ -339,10 +336,8 @@
 		else
 			sdhci_write_block_pio(host);
 
-		if (host->size == 0)
+		if (host->num_sg == 0)
 			break;
-
-		BUG_ON(host->num_sg == 0);
 	}
 
 	DBG("PIO transfer complete.\n");
@@ -408,8 +403,6 @@
 
 		writel(sg_dma_address(data->sg), host->ioaddr + SDHCI_DMA_ADDRESS);
 	} else {
-		host->size = data->blksz * data->blocks;
-
 		host->cur_sg = data->sg;
 		host->num_sg = data->sg_len;
 
@@ -473,10 +466,6 @@
 			"though there were blocks left.\n",
 			mmc_hostname(host->mmc));
 		data->error = MMC_ERR_FAILED;
-	} else if (host->size != 0) {
-		printk(KERN_ERR "%s: %d bytes were left untransferred.\n",
-			mmc_hostname(host->mmc), host->size);
-		data->error = MMC_ERR_FAILED;
 	}
 
 	DBG("Ending data transfer (%d bytes)\n", data->bytes_xfered);
@@ -669,20 +658,16 @@
 
 	pwr = SDHCI_POWER_ON;
 
-	switch (power) {
-	case MMC_VDD_170:
-	case MMC_VDD_180:
-	case MMC_VDD_190:
+	switch (1 << power) {
+	case MMC_VDD_165_195:
 		pwr |= SDHCI_POWER_180;
 		break;
-	case MMC_VDD_290:
-	case MMC_VDD_300:
-	case MMC_VDD_310:
+	case MMC_VDD_29_30:
+	case MMC_VDD_30_31:
 		pwr |= SDHCI_POWER_300;
 		break;
-	case MMC_VDD_320:
-	case MMC_VDD_330:
-	case MMC_VDD_340:
+	case MMC_VDD_32_33:
+	case MMC_VDD_33_34:
 		pwr |= SDHCI_POWER_330;
 		break;
 	default:
@@ -1294,7 +1279,7 @@
 	if (caps & SDHCI_CAN_VDD_300)
 		mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31;
 	if (caps & SDHCI_CAN_VDD_180)
-		mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
+		mmc->ocr_avail |= MMC_VDD_165_195;
 
 	if (mmc->ocr_avail == 0) {
 		printk(KERN_ERR "%s: Hardware doesn't report any "
diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/host/sdhci.h
similarity index 97%
rename from drivers/mmc/sdhci.h
rename to drivers/mmc/host/sdhci.h
index e324f0a..7400f4b 100644
--- a/drivers/mmc/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/sdhci.h - Secure Digital Host Controller Interface driver
  *
- *  Copyright (C) 2005 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2005-2007 Pierre Ossman, 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 as published by
@@ -187,8 +187,6 @@
 	int			offset;		/* Offset into current sg */
 	int			remain;		/* Bytes left in current */
 
-	int			size;		/* Remaining bytes in transfer */
-
 	char			slot_descr[20];	/* Name for reservations */
 
 	int			irq;		/* Device IRQ */
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c
new file mode 100644
index 0000000..7511f96
--- /dev/null
+++ b/drivers/mmc/host/tifm_sd.c
@@ -0,0 +1,1102 @@
+/*
+ *  tifm_sd.c - TI FlashMedia driver
+ *
+ *  Copyright (C) 2006 Alex Dubov <oakad@yahoo.com>
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ * Special thanks to Brad Campbell for extensive testing of this driver.
+ *
+ */
+
+
+#include <linux/tifm.h>
+#include <linux/mmc/host.h>
+#include <linux/highmem.h>
+#include <linux/scatterlist.h>
+#include <asm/io.h>
+
+#define DRIVER_NAME "tifm_sd"
+#define DRIVER_VERSION "0.8"
+
+static int no_dma = 0;
+static int fixed_timeout = 0;
+module_param(no_dma, bool, 0644);
+module_param(fixed_timeout, bool, 0644);
+
+/* Constants here are mostly from OMAP5912 datasheet */
+#define TIFM_MMCSD_RESET      0x0002
+#define TIFM_MMCSD_CLKMASK    0x03ff
+#define TIFM_MMCSD_POWER      0x0800
+#define TIFM_MMCSD_4BBUS      0x8000
+#define TIFM_MMCSD_RXDE       0x8000   /* rx dma enable */
+#define TIFM_MMCSD_TXDE       0x0080   /* tx dma enable */
+#define TIFM_MMCSD_BUFINT     0x0c00   /* set bits: AE, AF */
+#define TIFM_MMCSD_DPE        0x0020   /* data timeout counted in kilocycles */
+#define TIFM_MMCSD_INAB       0x0080   /* abort / initialize command */
+#define TIFM_MMCSD_READ       0x8000
+
+#define TIFM_MMCSD_ERRMASK    0x01e0   /* set bits: CCRC, CTO, DCRC, DTO */
+#define TIFM_MMCSD_EOC        0x0001   /* end of command phase  */
+#define TIFM_MMCSD_CD         0x0002   /* card detect           */
+#define TIFM_MMCSD_CB         0x0004   /* card enter busy state */
+#define TIFM_MMCSD_BRS        0x0008   /* block received/sent   */
+#define TIFM_MMCSD_EOFB       0x0010   /* card exit busy state  */
+#define TIFM_MMCSD_DTO        0x0020   /* data time-out         */
+#define TIFM_MMCSD_DCRC       0x0040   /* data crc error        */
+#define TIFM_MMCSD_CTO        0x0080   /* command time-out      */
+#define TIFM_MMCSD_CCRC       0x0100   /* command crc error     */
+#define TIFM_MMCSD_AF         0x0400   /* fifo almost full      */
+#define TIFM_MMCSD_AE         0x0800   /* fifo almost empty     */
+#define TIFM_MMCSD_OCRB       0x1000   /* OCR busy              */
+#define TIFM_MMCSD_CIRQ       0x2000   /* card irq (cmd40/sdio) */
+#define TIFM_MMCSD_CERR       0x4000   /* card status error     */
+
+#define TIFM_MMCSD_ODTO       0x0040   /* open drain / extended timeout */
+#define TIFM_MMCSD_CARD_RO    0x0200   /* card is read-only     */
+
+#define TIFM_MMCSD_FIFO_SIZE  0x0020
+
+#define TIFM_MMCSD_RSP_R0     0x0000
+#define TIFM_MMCSD_RSP_R1     0x0100
+#define TIFM_MMCSD_RSP_R2     0x0200
+#define TIFM_MMCSD_RSP_R3     0x0300
+#define TIFM_MMCSD_RSP_R4     0x0400
+#define TIFM_MMCSD_RSP_R5     0x0500
+#define TIFM_MMCSD_RSP_R6     0x0600
+
+#define TIFM_MMCSD_RSP_BUSY   0x0800
+
+#define TIFM_MMCSD_CMD_BC     0x0000
+#define TIFM_MMCSD_CMD_BCR    0x1000
+#define TIFM_MMCSD_CMD_AC     0x2000
+#define TIFM_MMCSD_CMD_ADTC   0x3000
+
+#define TIFM_MMCSD_MAX_BLOCK_SIZE  0x0800UL
+
+enum {
+	CMD_READY    = 0x0001,
+	FIFO_READY   = 0x0002,
+	BRS_READY    = 0x0004,
+	SCMD_ACTIVE  = 0x0008,
+	SCMD_READY   = 0x0010,
+	CARD_BUSY    = 0x0020,
+	DATA_CARRY   = 0x0040
+};
+
+struct tifm_sd {
+	struct tifm_dev       *dev;
+
+	unsigned short        eject:1,
+			      open_drain:1,
+			      no_dma:1;
+	unsigned short        cmd_flags;
+
+	unsigned int          clk_freq;
+	unsigned int          clk_div;
+	unsigned long         timeout_jiffies;
+
+	struct tasklet_struct finish_tasklet;
+	struct timer_list     timer;
+	struct mmc_request    *req;
+
+	int                   sg_len;
+	int                   sg_pos;
+	unsigned int          block_pos;
+	struct scatterlist    bounce_buf;
+	unsigned char         bounce_buf_data[TIFM_MMCSD_MAX_BLOCK_SIZE];
+};
+
+/* for some reason, host won't respond correctly to readw/writew */
+static void tifm_sd_read_fifo(struct tifm_sd *host, struct page *pg,
+			      unsigned int off, unsigned int cnt)
+{
+	struct tifm_dev *sock = host->dev;
+	unsigned char *buf;
+	unsigned int pos = 0, val;
+
+	buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + off;
+	if (host->cmd_flags & DATA_CARRY) {
+		buf[pos++] = host->bounce_buf_data[0];
+		host->cmd_flags &= ~DATA_CARRY;
+	}
+
+	while (pos < cnt) {
+		val = readl(sock->addr + SOCK_MMCSD_DATA);
+		buf[pos++] = val & 0xff;
+		if (pos == cnt) {
+			host->bounce_buf_data[0] = (val >> 8) & 0xff;
+			host->cmd_flags |= DATA_CARRY;
+			break;
+		}
+		buf[pos++] = (val >> 8) & 0xff;
+	}
+	kunmap_atomic(buf - off, KM_BIO_DST_IRQ);
+}
+
+static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg,
+			       unsigned int off, unsigned int cnt)
+{
+	struct tifm_dev *sock = host->dev;
+	unsigned char *buf;
+	unsigned int pos = 0, val;
+
+	buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + off;
+	if (host->cmd_flags & DATA_CARRY) {
+		val = host->bounce_buf_data[0] | ((buf[pos++] << 8) & 0xff00);
+		writel(val, sock->addr + SOCK_MMCSD_DATA);
+		host->cmd_flags &= ~DATA_CARRY;
+	}
+
+	while (pos < cnt) {
+		val = buf[pos++];
+		if (pos == cnt) {
+			host->bounce_buf_data[0] = val & 0xff;
+			host->cmd_flags |= DATA_CARRY;
+			break;
+		}
+		val |= (buf[pos++] << 8) & 0xff00;
+		writel(val, sock->addr + SOCK_MMCSD_DATA);
+	}
+	kunmap_atomic(buf - off, KM_BIO_SRC_IRQ);
+}
+
+static void tifm_sd_transfer_data(struct tifm_sd *host)
+{
+	struct mmc_data *r_data = host->req->cmd->data;
+	struct scatterlist *sg = r_data->sg;
+	unsigned int off, cnt, t_size = TIFM_MMCSD_FIFO_SIZE * 2;
+	unsigned int p_off, p_cnt;
+	struct page *pg;
+
+	if (host->sg_pos == host->sg_len)
+		return;
+	while (t_size) {
+		cnt = sg[host->sg_pos].length - host->block_pos;
+		if (!cnt) {
+			host->block_pos = 0;
+			host->sg_pos++;
+			if (host->sg_pos == host->sg_len) {
+				if ((r_data->flags & MMC_DATA_WRITE)
+				    && DATA_CARRY)
+					writel(host->bounce_buf_data[0],
+					       host->dev->addr
+					       + SOCK_MMCSD_DATA);
+
+				return;
+			}
+			cnt = sg[host->sg_pos].length;
+		}
+		off = sg[host->sg_pos].offset + host->block_pos;
+
+		pg = nth_page(sg[host->sg_pos].page, off >> PAGE_SHIFT);
+		p_off = offset_in_page(off);
+		p_cnt = PAGE_SIZE - p_off;
+		p_cnt = min(p_cnt, cnt);
+		p_cnt = min(p_cnt, t_size);
+
+		if (r_data->flags & MMC_DATA_READ)
+			tifm_sd_read_fifo(host, pg, p_off, p_cnt);
+		else if (r_data->flags & MMC_DATA_WRITE)
+			tifm_sd_write_fifo(host, pg, p_off, p_cnt);
+
+		t_size -= p_cnt;
+		host->block_pos += p_cnt;
+	}
+}
+
+static void tifm_sd_copy_page(struct page *dst, unsigned int dst_off,
+			      struct page *src, unsigned int src_off,
+			      unsigned int count)
+{
+	unsigned char *src_buf = kmap_atomic(src, KM_BIO_SRC_IRQ) + src_off;
+	unsigned char *dst_buf = kmap_atomic(dst, KM_BIO_DST_IRQ) + dst_off;
+
+	memcpy(dst_buf, src_buf, count);
+
+	kunmap_atomic(dst_buf - dst_off, KM_BIO_DST_IRQ);
+	kunmap_atomic(src_buf - src_off, KM_BIO_SRC_IRQ);
+}
+
+static void tifm_sd_bounce_block(struct tifm_sd *host, struct mmc_data *r_data)
+{
+	struct scatterlist *sg = r_data->sg;
+	unsigned int t_size = r_data->blksz;
+	unsigned int off, cnt;
+	unsigned int p_off, p_cnt;
+	struct page *pg;
+
+	dev_dbg(&host->dev->dev, "bouncing block\n");
+	while (t_size) {
+		cnt = sg[host->sg_pos].length - host->block_pos;
+		if (!cnt) {
+			host->block_pos = 0;
+			host->sg_pos++;
+			if (host->sg_pos == host->sg_len)
+				return;
+			cnt = sg[host->sg_pos].length;
+		}
+		off = sg[host->sg_pos].offset + host->block_pos;
+
+		pg = nth_page(sg[host->sg_pos].page, off >> PAGE_SHIFT);
+		p_off = offset_in_page(off);
+		p_cnt = PAGE_SIZE - p_off;
+		p_cnt = min(p_cnt, cnt);
+		p_cnt = min(p_cnt, t_size);
+
+		if (r_data->flags & MMC_DATA_WRITE)
+			tifm_sd_copy_page(host->bounce_buf.page,
+					  r_data->blksz - t_size,
+					  pg, p_off, p_cnt);
+		else if (r_data->flags & MMC_DATA_READ)
+			tifm_sd_copy_page(pg, p_off, host->bounce_buf.page,
+					  r_data->blksz - t_size, p_cnt);
+
+		t_size -= p_cnt;
+		host->block_pos += p_cnt;
+	}
+}
+
+static int tifm_sd_set_dma_data(struct tifm_sd *host, struct mmc_data *r_data)
+{
+	struct tifm_dev *sock = host->dev;
+	unsigned int t_size = TIFM_DMA_TSIZE * r_data->blksz;
+	unsigned int dma_len, dma_blk_cnt, dma_off;
+	struct scatterlist *sg = NULL;
+	unsigned long flags;
+
+	if (host->sg_pos == host->sg_len)
+		return 1;
+
+	if (host->cmd_flags & DATA_CARRY) {
+		host->cmd_flags &= ~DATA_CARRY;
+		local_irq_save(flags);
+		tifm_sd_bounce_block(host, r_data);
+		local_irq_restore(flags);
+		if (host->sg_pos == host->sg_len)
+			return 1;
+	}
+
+	dma_len = sg_dma_len(&r_data->sg[host->sg_pos]) - host->block_pos;
+	if (!dma_len) {
+		host->block_pos = 0;
+		host->sg_pos++;
+		if (host->sg_pos == host->sg_len)
+			return 1;
+		dma_len = sg_dma_len(&r_data->sg[host->sg_pos]);
+	}
+
+	if (dma_len < t_size) {
+		dma_blk_cnt = dma_len / r_data->blksz;
+		dma_off = host->block_pos;
+		host->block_pos += dma_blk_cnt * r_data->blksz;
+	} else {
+		dma_blk_cnt = TIFM_DMA_TSIZE;
+		dma_off = host->block_pos;
+		host->block_pos += t_size;
+	}
+
+	if (dma_blk_cnt)
+		sg = &r_data->sg[host->sg_pos];
+	else if (dma_len) {
+		if (r_data->flags & MMC_DATA_WRITE) {
+			local_irq_save(flags);
+			tifm_sd_bounce_block(host, r_data);
+			local_irq_restore(flags);
+		} else
+			host->cmd_flags |= DATA_CARRY;
+
+		sg = &host->bounce_buf;
+		dma_off = 0;
+		dma_blk_cnt = 1;
+	} else
+		return 1;
+
+	dev_dbg(&sock->dev, "setting dma for %d blocks\n", dma_blk_cnt);
+	writel(sg_dma_address(sg) + dma_off, sock->addr + SOCK_DMA_ADDRESS);
+	if (r_data->flags & MMC_DATA_WRITE)
+		writel((dma_blk_cnt << 8) | TIFM_DMA_TX | TIFM_DMA_EN,
+		       sock->addr + SOCK_DMA_CONTROL);
+	else
+		writel((dma_blk_cnt << 8) | TIFM_DMA_EN,
+		       sock->addr + SOCK_DMA_CONTROL);
+
+	return 0;
+}
+
+static unsigned int tifm_sd_op_flags(struct mmc_command *cmd)
+{
+	unsigned int rc = 0;
+
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_NONE:
+		rc |= TIFM_MMCSD_RSP_R0;
+		break;
+	case MMC_RSP_R1B:
+		rc |= TIFM_MMCSD_RSP_BUSY; // deliberate fall-through
+	case MMC_RSP_R1:
+		rc |= TIFM_MMCSD_RSP_R1;
+		break;
+	case MMC_RSP_R2:
+		rc |= TIFM_MMCSD_RSP_R2;
+		break;
+	case MMC_RSP_R3:
+		rc |= TIFM_MMCSD_RSP_R3;
+		break;
+	default:
+		BUG();
+	}
+
+	switch (mmc_cmd_type(cmd)) {
+	case MMC_CMD_BC:
+		rc |= TIFM_MMCSD_CMD_BC;
+		break;
+	case MMC_CMD_BCR:
+		rc |= TIFM_MMCSD_CMD_BCR;
+		break;
+	case MMC_CMD_AC:
+		rc |= TIFM_MMCSD_CMD_AC;
+		break;
+	case MMC_CMD_ADTC:
+		rc |= TIFM_MMCSD_CMD_ADTC;
+		break;
+	default:
+		BUG();
+	}
+	return rc;
+}
+
+static void tifm_sd_exec(struct tifm_sd *host, struct mmc_command *cmd)
+{
+	struct tifm_dev *sock = host->dev;
+	unsigned int cmd_mask = tifm_sd_op_flags(cmd);
+
+	if (host->open_drain)
+		cmd_mask |= TIFM_MMCSD_ODTO;
+
+	if (cmd->data && (cmd->data->flags & MMC_DATA_READ))
+		cmd_mask |= TIFM_MMCSD_READ;
+
+	dev_dbg(&sock->dev, "executing opcode 0x%x, arg: 0x%x, mask: 0x%x\n",
+		cmd->opcode, cmd->arg, cmd_mask);
+
+	writel((cmd->arg >> 16) & 0xffff, sock->addr + SOCK_MMCSD_ARG_HIGH);
+	writel(cmd->arg & 0xffff, sock->addr + SOCK_MMCSD_ARG_LOW);
+	writel(cmd->opcode | cmd_mask, sock->addr + SOCK_MMCSD_COMMAND);
+}
+
+static void tifm_sd_fetch_resp(struct mmc_command *cmd, struct tifm_dev *sock)
+{
+	cmd->resp[0] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x1c) << 16)
+		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x18);
+	cmd->resp[1] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x14) << 16)
+		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x10);
+	cmd->resp[2] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x0c) << 16)
+		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x08);
+	cmd->resp[3] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x04) << 16)
+		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x00);
+}
+
+static void tifm_sd_check_status(struct tifm_sd *host)
+{
+	struct tifm_dev *sock = host->dev;
+	struct mmc_command *cmd = host->req->cmd;
+
+	if (cmd->error != MMC_ERR_NONE)
+		goto finish_request;
+
+	if (!(host->cmd_flags & CMD_READY))
+		return;
+
+	if (cmd->data) {
+		if (cmd->data->error != MMC_ERR_NONE) {
+			if ((host->cmd_flags & SCMD_ACTIVE)
+			    && !(host->cmd_flags & SCMD_READY))
+				return;
+
+			goto finish_request;
+		}
+
+		if (!(host->cmd_flags & BRS_READY))
+			return;
+
+		if (!(host->no_dma || (host->cmd_flags & FIFO_READY)))
+			return;
+
+		if (cmd->data->flags & MMC_DATA_WRITE) {
+			if (host->req->stop) {
+				if (!(host->cmd_flags & SCMD_ACTIVE)) {
+					host->cmd_flags |= SCMD_ACTIVE;
+					writel(TIFM_MMCSD_EOFB
+					       | readl(sock->addr
+						       + SOCK_MMCSD_INT_ENABLE),
+					       sock->addr
+					       + SOCK_MMCSD_INT_ENABLE);
+					tifm_sd_exec(host, host->req->stop);
+					return;
+				} else {
+					if (!(host->cmd_flags & SCMD_READY)
+					    || (host->cmd_flags & CARD_BUSY))
+						return;
+					writel((~TIFM_MMCSD_EOFB)
+					       & readl(sock->addr
+						       + SOCK_MMCSD_INT_ENABLE),
+					       sock->addr
+					       + SOCK_MMCSD_INT_ENABLE);
+				}
+			} else {
+				if (host->cmd_flags & CARD_BUSY)
+					return;
+				writel((~TIFM_MMCSD_EOFB)
+				       & readl(sock->addr
+					       + SOCK_MMCSD_INT_ENABLE),
+				       sock->addr + SOCK_MMCSD_INT_ENABLE);
+			}
+		} else {
+			if (host->req->stop) {
+				if (!(host->cmd_flags & SCMD_ACTIVE)) {
+					host->cmd_flags |= SCMD_ACTIVE;
+					tifm_sd_exec(host, host->req->stop);
+					return;
+				} else {
+					if (!(host->cmd_flags & SCMD_READY))
+						return;
+				}
+			}
+		}
+	}
+finish_request:
+	tasklet_schedule(&host->finish_tasklet);
+}
+
+/* Called from interrupt handler */
+static void tifm_sd_data_event(struct tifm_dev *sock)
+{
+	struct tifm_sd *host;
+	unsigned int fifo_status = 0;
+	struct mmc_data *r_data = NULL;
+
+	spin_lock(&sock->lock);
+	host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock));
+	fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
+	dev_dbg(&sock->dev, "data event: fifo_status %x, flags %x\n",
+		fifo_status, host->cmd_flags);
+
+	if (host->req) {
+		r_data = host->req->cmd->data;
+
+		if (r_data && (fifo_status & TIFM_FIFO_READY)) {
+			if (tifm_sd_set_dma_data(host, r_data)) {
+				host->cmd_flags |= FIFO_READY;
+				tifm_sd_check_status(host);
+			}
+		}
+	}
+
+	writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS);
+	spin_unlock(&sock->lock);
+}
+
+/* Called from interrupt handler */
+static void tifm_sd_card_event(struct tifm_dev *sock)
+{
+	struct tifm_sd *host;
+	unsigned int host_status = 0;
+	int cmd_error = MMC_ERR_NONE;
+	struct mmc_command *cmd = NULL;
+	unsigned long flags;
+
+	spin_lock(&sock->lock);
+	host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock));
+	host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
+	dev_dbg(&sock->dev, "host event: host_status %x, flags %x\n",
+		host_status, host->cmd_flags);
+
+	if (host->req) {
+		cmd = host->req->cmd;
+
+		if (host_status & TIFM_MMCSD_ERRMASK) {
+			writel(host_status & TIFM_MMCSD_ERRMASK,
+			       sock->addr + SOCK_MMCSD_STATUS);
+			if (host_status & TIFM_MMCSD_CTO)
+				cmd_error = MMC_ERR_TIMEOUT;
+			else if (host_status & TIFM_MMCSD_CCRC)
+				cmd_error = MMC_ERR_BADCRC;
+
+			if (cmd->data) {
+				if (host_status & TIFM_MMCSD_DTO)
+					cmd->data->error = MMC_ERR_TIMEOUT;
+				else if (host_status & TIFM_MMCSD_DCRC)
+					cmd->data->error = MMC_ERR_BADCRC;
+			}
+
+			writel(TIFM_FIFO_INT_SETALL,
+			       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+			writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
+
+			if (host->req->stop) {
+				if (host->cmd_flags & SCMD_ACTIVE) {
+					host->req->stop->error = cmd_error;
+					host->cmd_flags |= SCMD_READY;
+				} else {
+					cmd->error = cmd_error;
+					host->cmd_flags |= SCMD_ACTIVE;
+					tifm_sd_exec(host, host->req->stop);
+					goto done;
+				}
+			} else
+				cmd->error = cmd_error;
+		} else {
+			if (host_status & (TIFM_MMCSD_EOC | TIFM_MMCSD_CERR)) {
+				if (!(host->cmd_flags & CMD_READY)) {
+					host->cmd_flags |= CMD_READY;
+					tifm_sd_fetch_resp(cmd, sock);
+				} else if (host->cmd_flags & SCMD_ACTIVE) {
+					host->cmd_flags |= SCMD_READY;
+					tifm_sd_fetch_resp(host->req->stop,
+							   sock);
+				}
+			}
+			if (host_status & TIFM_MMCSD_BRS)
+				host->cmd_flags |= BRS_READY;
+		}
+
+		if (host->no_dma && cmd->data) {
+			if (host_status & TIFM_MMCSD_AE)
+				writel(host_status & TIFM_MMCSD_AE,
+				       sock->addr + SOCK_MMCSD_STATUS);
+
+			if (host_status & (TIFM_MMCSD_AE | TIFM_MMCSD_AF
+					   | TIFM_MMCSD_BRS)) {
+				local_irq_save(flags);
+				tifm_sd_transfer_data(host);
+				local_irq_restore(flags);
+				host_status &= ~TIFM_MMCSD_AE;
+			}
+		}
+
+		if (host_status & TIFM_MMCSD_EOFB)
+			host->cmd_flags &= ~CARD_BUSY;
+		else if (host_status & TIFM_MMCSD_CB)
+			host->cmd_flags |= CARD_BUSY;
+
+		tifm_sd_check_status(host);
+	}
+done:
+	writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
+	spin_unlock(&sock->lock);
+}
+
+static void tifm_sd_set_data_timeout(struct tifm_sd *host,
+				     struct mmc_data *data)
+{
+	struct tifm_dev *sock = host->dev;
+	unsigned int data_timeout = data->timeout_clks;
+
+	if (fixed_timeout)
+		return;
+
+	data_timeout += data->timeout_ns /
+			((1000000000UL / host->clk_freq) * host->clk_div);
+
+	if (data_timeout < 0xffff) {
+		writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
+		writel((~TIFM_MMCSD_DPE)
+		       & readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
+		       sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
+	} else {
+		data_timeout = (data_timeout >> 10) + 1;
+		if (data_timeout > 0xffff)
+			data_timeout = 0;	/* set to unlimited */
+		writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
+		writel(TIFM_MMCSD_DPE
+		       | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
+		       sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
+	}
+}
+
+static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct tifm_sd *host = mmc_priv(mmc);
+	struct tifm_dev *sock = host->dev;
+	unsigned long flags;
+	struct mmc_data *r_data = mrq->cmd->data;
+
+	spin_lock_irqsave(&sock->lock, flags);
+	if (host->eject) {
+		spin_unlock_irqrestore(&sock->lock, flags);
+		goto err_out;
+	}
+
+	if (host->req) {
+		printk(KERN_ERR "%s : unfinished request detected\n",
+		       sock->dev.bus_id);
+		spin_unlock_irqrestore(&sock->lock, flags);
+		goto err_out;
+	}
+
+	host->cmd_flags = 0;
+	host->block_pos = 0;
+	host->sg_pos = 0;
+
+	if (r_data) {
+		tifm_sd_set_data_timeout(host, r_data);
+
+		if ((r_data->flags & MMC_DATA_WRITE) && !mrq->stop)
+			 writel(TIFM_MMCSD_EOFB
+				| readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
+				sock->addr + SOCK_MMCSD_INT_ENABLE);
+
+		if (host->no_dma) {
+			writel(TIFM_MMCSD_BUFINT
+			       | readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
+			       sock->addr + SOCK_MMCSD_INT_ENABLE);
+			writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8)
+			       | (TIFM_MMCSD_FIFO_SIZE - 1),
+			       sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+
+			host->sg_len = r_data->sg_len;
+		} else {
+			sg_init_one(&host->bounce_buf, host->bounce_buf_data,
+				    r_data->blksz);
+
+			if(1 != tifm_map_sg(sock, &host->bounce_buf, 1,
+					    r_data->flags & MMC_DATA_WRITE
+					    ? PCI_DMA_TODEVICE
+					    : PCI_DMA_FROMDEVICE)) {
+				printk(KERN_ERR "%s : scatterlist map failed\n",
+				       sock->dev.bus_id);
+				spin_unlock_irqrestore(&sock->lock, flags);
+				goto err_out;
+			}
+			host->sg_len = tifm_map_sg(sock, r_data->sg,
+						   r_data->sg_len,
+						   r_data->flags
+						   & MMC_DATA_WRITE
+						   ? PCI_DMA_TODEVICE
+						   : PCI_DMA_FROMDEVICE);
+			if (host->sg_len < 1) {
+				printk(KERN_ERR "%s : scatterlist map failed\n",
+				       sock->dev.bus_id);
+				tifm_unmap_sg(sock, &host->bounce_buf, 1,
+					      r_data->flags & MMC_DATA_WRITE
+					      ? PCI_DMA_TODEVICE
+					      : PCI_DMA_FROMDEVICE);
+				spin_unlock_irqrestore(&sock->lock, flags);
+				goto err_out;
+			}
+
+			writel(TIFM_FIFO_INT_SETALL,
+			       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+			writel(ilog2(r_data->blksz) - 2,
+			       sock->addr + SOCK_FIFO_PAGE_SIZE);
+			writel(TIFM_FIFO_ENABLE,
+			       sock->addr + SOCK_FIFO_CONTROL);
+			writel(TIFM_FIFO_INTMASK,
+			       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+
+			if (r_data->flags & MMC_DATA_WRITE)
+				writel(TIFM_MMCSD_TXDE,
+				       sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+			else
+				writel(TIFM_MMCSD_RXDE,
+				       sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+
+			tifm_sd_set_dma_data(host, r_data);
+		}
+
+		writel(r_data->blocks - 1,
+		       sock->addr + SOCK_MMCSD_NUM_BLOCKS);
+		writel(r_data->blksz - 1,
+		       sock->addr + SOCK_MMCSD_BLOCK_LEN);
+	}
+
+	host->req = mrq;
+	mod_timer(&host->timer, jiffies + host->timeout_jiffies);
+	writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
+	       sock->addr + SOCK_CONTROL);
+	tifm_sd_exec(host, mrq->cmd);
+	spin_unlock_irqrestore(&sock->lock, flags);
+	return;
+
+err_out:
+	mrq->cmd->error = MMC_ERR_TIMEOUT;
+	mmc_request_done(mmc, mrq);
+}
+
+static void tifm_sd_end_cmd(unsigned long data)
+{
+	struct tifm_sd *host = (struct tifm_sd*)data;
+	struct tifm_dev *sock = host->dev;
+	struct mmc_host *mmc = tifm_get_drvdata(sock);
+	struct mmc_request *mrq;
+	struct mmc_data *r_data = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sock->lock, flags);
+
+	del_timer(&host->timer);
+	mrq = host->req;
+	host->req = NULL;
+
+	if (!mrq) {
+		printk(KERN_ERR " %s : no request to complete?\n",
+		       sock->dev.bus_id);
+		spin_unlock_irqrestore(&sock->lock, flags);
+		return;
+	}
+
+	r_data = mrq->cmd->data;
+	if (r_data) {
+		if (host->no_dma) {
+			writel((~TIFM_MMCSD_BUFINT)
+			       & readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
+			       sock->addr + SOCK_MMCSD_INT_ENABLE);
+		} else {
+			tifm_unmap_sg(sock, &host->bounce_buf, 1,
+				      (r_data->flags & MMC_DATA_WRITE)
+				      ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+			tifm_unmap_sg(sock, r_data->sg, r_data->sg_len,
+				      (r_data->flags & MMC_DATA_WRITE)
+				      ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+		}
+
+		r_data->bytes_xfered = r_data->blocks
+			- readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1;
+		r_data->bytes_xfered *= r_data->blksz;
+		r_data->bytes_xfered += r_data->blksz
+			- readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
+	}
+
+	writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
+	       sock->addr + SOCK_CONTROL);
+
+	spin_unlock_irqrestore(&sock->lock, flags);
+	mmc_request_done(mmc, mrq);
+}
+
+static void tifm_sd_abort(unsigned long data)
+{
+	struct tifm_sd *host = (struct tifm_sd*)data;
+
+	printk(KERN_ERR
+	       "%s : card failed to respond for a long period of time "
+	       "(%x, %x)\n",
+	       host->dev->dev.bus_id, host->req->cmd->opcode, host->cmd_flags);
+
+	tifm_eject(host->dev);
+}
+
+static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct tifm_sd *host = mmc_priv(mmc);
+	struct tifm_dev *sock = host->dev;
+	unsigned int clk_div1, clk_div2;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sock->lock, flags);
+
+	dev_dbg(&sock->dev, "ios: clock = %u, vdd = %x, bus_mode = %x, "
+		"chip_select = %x, power_mode = %x, bus_width = %x\n",
+		ios->clock, ios->vdd, ios->bus_mode, ios->chip_select,
+		ios->power_mode, ios->bus_width);
+
+	if (ios->bus_width == MMC_BUS_WIDTH_4) {
+		writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG),
+		       sock->addr + SOCK_MMCSD_CONFIG);
+	} else {
+		writel((~TIFM_MMCSD_4BBUS)
+		       & readl(sock->addr + SOCK_MMCSD_CONFIG),
+		       sock->addr + SOCK_MMCSD_CONFIG);
+	}
+
+	if (ios->clock) {
+		clk_div1 = 20000000 / ios->clock;
+		if (!clk_div1)
+			clk_div1 = 1;
+
+		clk_div2 = 24000000 / ios->clock;
+		if (!clk_div2)
+			clk_div2 = 1;
+
+		if ((20000000 / clk_div1) > ios->clock)
+			clk_div1++;
+		if ((24000000 / clk_div2) > ios->clock)
+			clk_div2++;
+		if ((20000000 / clk_div1) > (24000000 / clk_div2)) {
+			host->clk_freq = 20000000;
+			host->clk_div = clk_div1;
+			writel((~TIFM_CTRL_FAST_CLK)
+			       & readl(sock->addr + SOCK_CONTROL),
+			       sock->addr + SOCK_CONTROL);
+		} else {
+			host->clk_freq = 24000000;
+			host->clk_div = clk_div2;
+			writel(TIFM_CTRL_FAST_CLK
+			       | readl(sock->addr + SOCK_CONTROL),
+			       sock->addr + SOCK_CONTROL);
+		}
+	} else {
+		host->clk_div = 0;
+	}
+	host->clk_div &= TIFM_MMCSD_CLKMASK;
+	writel(host->clk_div
+	       | ((~TIFM_MMCSD_CLKMASK)
+		  & readl(sock->addr + SOCK_MMCSD_CONFIG)),
+	       sock->addr + SOCK_MMCSD_CONFIG);
+
+	host->open_drain = (ios->bus_mode == MMC_BUSMODE_OPENDRAIN);
+
+	/* chip_select : maybe later */
+	//vdd
+	//power is set before probe / after remove
+
+	spin_unlock_irqrestore(&sock->lock, flags);
+}
+
+static int tifm_sd_ro(struct mmc_host *mmc)
+{
+	int rc = 0;
+	struct tifm_sd *host = mmc_priv(mmc);
+	struct tifm_dev *sock = host->dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sock->lock, flags);
+	if (TIFM_MMCSD_CARD_RO & readl(sock->addr + SOCK_PRESENT_STATE))
+		rc = 1;
+	spin_unlock_irqrestore(&sock->lock, flags);
+	return rc;
+}
+
+static const struct mmc_host_ops tifm_sd_ops = {
+	.request = tifm_sd_request,
+	.set_ios = tifm_sd_ios,
+	.get_ro  = tifm_sd_ro
+};
+
+static int tifm_sd_initialize_host(struct tifm_sd *host)
+{
+	int rc;
+	unsigned int host_status = 0;
+	struct tifm_dev *sock = host->dev;
+
+	writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
+	mmiowb();
+	host->clk_div = 61;
+	host->clk_freq = 20000000;
+	writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL);
+	writel(host->clk_div | TIFM_MMCSD_POWER,
+	       sock->addr + SOCK_MMCSD_CONFIG);
+
+	/* wait up to 0.51 sec for reset */
+	for (rc = 32; rc <= 256; rc <<= 1) {
+		if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) {
+			rc = 0;
+			break;
+		}
+		msleep(rc);
+	}
+
+	if (rc) {
+		printk(KERN_ERR "%s : controller failed to reset\n",
+		       sock->dev.bus_id);
+		return -ENODEV;
+	}
+
+	writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
+	writel(host->clk_div | TIFM_MMCSD_POWER,
+	       sock->addr + SOCK_MMCSD_CONFIG);
+	writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+
+	// command timeout fixed to 64 clocks for now
+	writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO);
+	writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND);
+
+	for (rc = 16; rc <= 64; rc <<= 1) {
+		host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
+		writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
+		if (!(host_status & TIFM_MMCSD_ERRMASK)
+		    && (host_status & TIFM_MMCSD_EOC)) {
+			rc = 0;
+			break;
+		}
+		msleep(rc);
+	}
+
+	if (rc) {
+		printk(KERN_ERR
+		       "%s : card not ready - probe failed on initialization\n",
+		       sock->dev.bus_id);
+		return -ENODEV;
+	}
+
+	writel(TIFM_MMCSD_CERR | TIFM_MMCSD_BRS | TIFM_MMCSD_EOC
+	       | TIFM_MMCSD_ERRMASK,
+	       sock->addr + SOCK_MMCSD_INT_ENABLE);
+	mmiowb();
+
+	return 0;
+}
+
+static int tifm_sd_probe(struct tifm_dev *sock)
+{
+	struct mmc_host *mmc;
+	struct tifm_sd *host;
+	int rc = -EIO;
+
+	if (!(TIFM_SOCK_STATE_OCCUPIED
+	      & readl(sock->addr + SOCK_PRESENT_STATE))) {
+		printk(KERN_WARNING "%s : card gone, unexpectedly\n",
+		       sock->dev.bus_id);
+		return rc;
+	}
+
+	mmc = mmc_alloc_host(sizeof(struct tifm_sd), &sock->dev);
+	if (!mmc)
+		return -ENOMEM;
+
+	host = mmc_priv(mmc);
+	host->no_dma = no_dma;
+	tifm_set_drvdata(sock, mmc);
+	host->dev = sock;
+	host->timeout_jiffies = msecs_to_jiffies(1000);
+
+	tasklet_init(&host->finish_tasklet, tifm_sd_end_cmd,
+		     (unsigned long)host);
+	setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host);
+
+	mmc->ops = &tifm_sd_ops;
+	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
+	mmc->f_min = 20000000 / 60;
+	mmc->f_max = 24000000;
+
+	mmc->max_blk_count = 2048;
+	mmc->max_hw_segs = mmc->max_blk_count;
+	mmc->max_blk_size = min(TIFM_MMCSD_MAX_BLOCK_SIZE, PAGE_SIZE);
+	mmc->max_seg_size = mmc->max_blk_count * mmc->max_blk_size;
+	mmc->max_req_size = mmc->max_seg_size;
+	mmc->max_phys_segs = mmc->max_hw_segs;
+
+	sock->card_event = tifm_sd_card_event;
+	sock->data_event = tifm_sd_data_event;
+	rc = tifm_sd_initialize_host(host);
+
+	if (!rc)
+		rc = mmc_add_host(mmc);
+	if (!rc)
+		return 0;
+
+	mmc_free_host(mmc);
+	return rc;
+}
+
+static void tifm_sd_remove(struct tifm_dev *sock)
+{
+	struct mmc_host *mmc = tifm_get_drvdata(sock);
+	struct tifm_sd *host = mmc_priv(mmc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&sock->lock, flags);
+	host->eject = 1;
+	writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
+	mmiowb();
+	spin_unlock_irqrestore(&sock->lock, flags);
+
+	tasklet_kill(&host->finish_tasklet);
+
+	spin_lock_irqsave(&sock->lock, flags);
+	if (host->req) {
+		writel(TIFM_FIFO_INT_SETALL,
+		       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+		writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+		host->req->cmd->error = MMC_ERR_TIMEOUT;
+		if (host->req->stop)
+			host->req->stop->error = MMC_ERR_TIMEOUT;
+		tasklet_schedule(&host->finish_tasklet);
+	}
+	spin_unlock_irqrestore(&sock->lock, flags);
+	mmc_remove_host(mmc);
+	dev_dbg(&sock->dev, "after remove\n");
+
+	/* The meaning of the bit majority in this constant is unknown. */
+	writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
+	       sock->addr + SOCK_CONTROL);
+
+	mmc_free_host(mmc);
+}
+
+#ifdef CONFIG_PM
+
+static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state)
+{
+	struct mmc_host *mmc = tifm_get_drvdata(sock);
+	int rc;
+
+	rc = mmc_suspend_host(mmc, state);
+	/* The meaning of the bit majority in this constant is unknown. */
+	writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
+	       sock->addr + SOCK_CONTROL);
+	return rc;
+}
+
+static int tifm_sd_resume(struct tifm_dev *sock)
+{
+	struct mmc_host *mmc = tifm_get_drvdata(sock);
+	struct tifm_sd *host = mmc_priv(mmc);
+	int rc;
+
+	rc = tifm_sd_initialize_host(host);
+	dev_dbg(&sock->dev, "resume initialize %d\n", rc);
+
+	if (rc)
+		host->eject = 1;
+	else
+		rc = mmc_resume_host(mmc);
+
+	return rc;
+}
+
+#else
+
+#define tifm_sd_suspend NULL
+#define tifm_sd_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct tifm_device_id tifm_sd_id_tbl[] = {
+	{ TIFM_TYPE_SD }, { }
+};
+
+static struct tifm_driver tifm_sd_driver = {
+	.driver = {
+		.name  = DRIVER_NAME,
+		.owner = THIS_MODULE
+	},
+	.id_table = tifm_sd_id_tbl,
+	.probe    = tifm_sd_probe,
+	.remove   = tifm_sd_remove,
+	.suspend  = tifm_sd_suspend,
+	.resume   = tifm_sd_resume
+};
+
+static int __init tifm_sd_init(void)
+{
+	return tifm_register_driver(&tifm_sd_driver);
+}
+
+static void __exit tifm_sd_exit(void)
+{
+	tifm_unregister_driver(&tifm_sd_driver);
+}
+
+MODULE_AUTHOR("Alex Dubov");
+MODULE_DESCRIPTION("TI FlashMedia SD driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(tifm, tifm_sd_id_tbl);
+MODULE_VERSION(DRIVER_VERSION);
+
+module_init(tifm_sd_init);
+module_exit(tifm_sd_exit);
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/host/wbsd.c
similarity index 92%
rename from drivers/mmc/wbsd.c
rename to drivers/mmc/host/wbsd.c
index 05ccfc4..867ca6a 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver
  *
- *  Copyright (C) 2004-2006 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2004-2007 Pierre Ossman, 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 as published by
@@ -33,7 +33,6 @@
 #include <linux/pnp.h>
 #include <linux/highmem.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -178,9 +177,8 @@
 	ier = 0;
 	ier |= WBSD_EINT_CARD;
 	ier |= WBSD_EINT_FIFO_THRE;
-	ier |= WBSD_EINT_CCRC;
-	ier |= WBSD_EINT_TIMEOUT;
 	ier |= WBSD_EINT_CRC;
+	ier |= WBSD_EINT_TIMEOUT;
 	ier |= WBSD_EINT_TC;
 
 	outb(ier, host->base + WBSD_EIR);
@@ -278,90 +276,36 @@
 
 static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
 {
-	unsigned int len, i, size;
+	unsigned int len, i;
 	struct scatterlist *sg;
 	char *dmabuf = host->dma_buffer;
 	char *sgbuf;
 
-	size = host->size;
-
 	sg = data->sg;
 	len = data->sg_len;
 
-	/*
-	 * Just loop through all entries. Size might not
-	 * be the entire list though so make sure that
-	 * we do not transfer too much.
-	 */
 	for (i = 0; i < len; i++) {
 		sgbuf = page_address(sg[i].page) + sg[i].offset;
-		if (size < sg[i].length)
-			memcpy(dmabuf, sgbuf, size);
-		else
-			memcpy(dmabuf, sgbuf, sg[i].length);
+		memcpy(dmabuf, sgbuf, sg[i].length);
 		dmabuf += sg[i].length;
-
-		if (size < sg[i].length)
-			size = 0;
-		else
-			size -= sg[i].length;
-
-		if (size == 0)
-			break;
 	}
-
-	/*
-	 * Check that we didn't get a request to transfer
-	 * more data than can fit into the SG list.
-	 */
-
-	BUG_ON(size != 0);
-
-	host->size -= size;
 }
 
 static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data)
 {
-	unsigned int len, i, size;
+	unsigned int len, i;
 	struct scatterlist *sg;
 	char *dmabuf = host->dma_buffer;
 	char *sgbuf;
 
-	size = host->size;
-
 	sg = data->sg;
 	len = data->sg_len;
 
-	/*
-	 * Just loop through all entries. Size might not
-	 * be the entire list though so make sure that
-	 * we do not transfer too much.
-	 */
 	for (i = 0; i < len; i++) {
 		sgbuf = page_address(sg[i].page) + sg[i].offset;
-		if (size < sg[i].length)
-			memcpy(sgbuf, dmabuf, size);
-		else
-			memcpy(sgbuf, dmabuf, sg[i].length);
+		memcpy(sgbuf, dmabuf, sg[i].length);
 		dmabuf += sg[i].length;
-
-		if (size < sg[i].length)
-			size = 0;
-		else
-			size -= sg[i].length;
-
-		if (size == 0)
-			break;
 	}
-
-	/*
-	 * Check that we didn't get a request to transfer
-	 * more data than can fit into the SG list.
-	 */
-
-	BUG_ON(size != 0);
-
-	host->size -= size;
 }
 
 /*
@@ -484,7 +428,7 @@
 	/*
 	 * Handle excessive data.
 	 */
-	if (data->bytes_xfered == host->size)
+	if (host->num_sg == 0)
 		return;
 
 	buffer = wbsd_sg_to_buffer(host) + host->offset;
@@ -514,31 +458,14 @@
 			data->bytes_xfered++;
 
 			/*
-			 * Transfer done?
-			 */
-			if (data->bytes_xfered == host->size)
-				return;
-
-			/*
 			 * End of scatter list entry?
 			 */
 			if (host->remain == 0) {
 				/*
 				 * Get next entry. Check if last.
 				 */
-				if (!wbsd_next_sg(host)) {
-					/*
-					 * We should never reach this point.
-					 * It means that we're trying to
-					 * transfer more blocks than can fit
-					 * into the scatter list.
-					 */
-					BUG_ON(1);
-
-					host->size = data->bytes_xfered;
-
+				if (!wbsd_next_sg(host))
 					return;
-				}
 
 				buffer = wbsd_sg_to_buffer(host);
 			}
@@ -550,7 +477,7 @@
 	 * hardware problem. The chip doesn't trigger
 	 * FIFO threshold interrupts properly.
 	 */
-	if ((host->size - data->bytes_xfered) < 16)
+	if ((data->blocks * data->blksz - data->bytes_xfered) < 16)
 		tasklet_schedule(&host->fifo_tasklet);
 }
 
@@ -564,7 +491,7 @@
 	 * Check that we aren't being called after the
 	 * entire buffer has been transfered.
 	 */
-	if (data->bytes_xfered == host->size)
+	if (host->num_sg == 0)
 		return;
 
 	buffer = wbsd_sg_to_buffer(host) + host->offset;
@@ -594,31 +521,14 @@
 			data->bytes_xfered++;
 
 			/*
-			 * Transfer done?
-			 */
-			if (data->bytes_xfered == host->size)
-				return;
-
-			/*
 			 * End of scatter list entry?
 			 */
 			if (host->remain == 0) {
 				/*
 				 * Get next entry. Check if last.
 				 */
-				if (!wbsd_next_sg(host)) {
-					/*
-					 * We should never reach this point.
-					 * It means that we're trying to
-					 * transfer more blocks than can fit
-					 * into the scatter list.
-					 */
-					BUG_ON(1);
-
-					host->size = data->bytes_xfered;
-
+				if (!wbsd_next_sg(host))
 					return;
-				}
 
 				buffer = wbsd_sg_to_buffer(host);
 			}
@@ -638,6 +548,7 @@
 	u16 blksize;
 	u8 setup;
 	unsigned long dmaflags;
+	unsigned int size;
 
 	DBGF("blksz %04x blks %04x flags %08x\n",
 		data->blksz, data->blocks, data->flags);
@@ -647,7 +558,7 @@
 	/*
 	 * Calculate size.
 	 */
-	host->size = data->blocks * data->blksz;
+	size = data->blocks * data->blksz;
 
 	/*
 	 * Check timeout values for overflow.
@@ -705,8 +616,8 @@
 		/*
 		 * The buffer for DMA is only 64 kB.
 		 */
-		BUG_ON(host->size > 0x10000);
-		if (host->size > 0x10000) {
+		BUG_ON(size > 0x10000);
+		if (size > 0x10000) {
 			data->error = MMC_ERR_INVALID;
 			return;
 		}
@@ -729,7 +640,7 @@
 		else
 			set_dma_mode(host->dma, DMA_MODE_WRITE & ~0x40);
 		set_dma_addr(host->dma, host->dma_addr);
-		set_dma_count(host->dma, host->size);
+		set_dma_count(host->dma, size);
 
 		enable_dma(host->dma);
 		release_dma_lock(dmaflags);
@@ -812,6 +723,10 @@
 		count = get_dma_residue(host->dma);
 		release_dma_lock(dmaflags);
 
+		data->bytes_xfered = host->mrq->data->blocks *
+			host->mrq->data->blksz - count;
+		data->bytes_xfered -= data->bytes_xfered % data->blksz;
+
 		/*
 		 * Any leftover data?
 		 */
@@ -820,7 +735,8 @@
 				"%d bytes left.\n",
 				mmc_hostname(host->mmc), count);
 
-			data->error = MMC_ERR_FAILED;
+			if (data->error == MMC_ERR_NONE)
+				data->error = MMC_ERR_FAILED;
 		} else {
 			/*
 			 * Transfer data from DMA buffer to
@@ -828,8 +744,11 @@
 			 */
 			if (data->flags & MMC_DATA_READ)
 				wbsd_dma_to_sg(host, data);
+		}
 
-			data->bytes_xfered = host->size;
+		if (data->error != MMC_ERR_NONE) {
+			if (data->bytes_xfered)
+				data->bytes_xfered -= data->blksz;
 		}
 	}
 
@@ -869,24 +788,7 @@
 		goto done;
 	}
 
-	/*
-	 * Does the request include data?
-	 */
 	if (cmd->data) {
-		wbsd_prepare_data(host, cmd->data);
-
-		if (cmd->data->error != MMC_ERR_NONE)
-			goto done;
-	}
-
-	wbsd_send_command(host, cmd);
-
-	/*
-	 * If this is a data transfer the request
-	 * will be finished after the data has
-	 * transfered.
-	 */
-	if (cmd->data && (cmd->error == MMC_ERR_NONE)) {
 		/*
 		 * The hardware is so delightfully stupid that it has a list
 		 * of "data" commands. If a command isn't on this list, it'll
@@ -918,14 +820,30 @@
 				"supported by this controller.\n",
 				mmc_hostname(host->mmc), cmd->opcode);
 #endif
-			cmd->data->error = MMC_ERR_INVALID;
-
-			if (cmd->data->stop)
-				wbsd_send_command(host, cmd->data->stop);
+			cmd->error = MMC_ERR_INVALID;
 
 			goto done;
 		};
+	}
 
+	/*
+	 * Does the request include data?
+	 */
+	if (cmd->data) {
+		wbsd_prepare_data(host, cmd->data);
+
+		if (cmd->data->error != MMC_ERR_NONE)
+			goto done;
+	}
+
+	wbsd_send_command(host, cmd);
+
+	/*
+	 * If this is a data transfer the request
+	 * will be finished after the data has
+	 * transfered.
+	 */
+	if (cmd->data && (cmd->error == MMC_ERR_NONE)) {
 		/*
 		 * Dirty fix for hardware bug.
 		 */
@@ -1167,7 +1085,7 @@
 	/*
 	 * Done?
 	 */
-	if (host->size == data->bytes_xfered) {
+	if (host->num_sg == 0) {
 		wbsd_write_index(host, WBSD_IDX_FIFOEN, 0);
 		tasklet_schedule(&host->finish_tasklet);
 	}
@@ -1245,30 +1163,6 @@
 	spin_unlock(&host->lock);
 }
 
-static void wbsd_tasklet_block(unsigned long param)
-{
-	struct wbsd_host *host = (struct wbsd_host *)param;
-	struct mmc_data *data;
-
-	spin_lock(&host->lock);
-
-	if ((wbsd_read_index(host, WBSD_IDX_CRCSTATUS) & WBSD_CRC_MASK) !=
-		WBSD_CRC_OK) {
-		data = wbsd_get_data(host);
-		if (!data)
-			goto end;
-
-		DBGF("CRC error\n");
-
-		data->error = MMC_ERR_BADCRC;
-
-		tasklet_schedule(&host->finish_tasklet);
-	}
-
-end:
-	spin_unlock(&host->lock);
-}
-
 /*
  * Interrupt handling
  */
@@ -1299,8 +1193,6 @@
 		tasklet_hi_schedule(&host->crc_tasklet);
 	if (isr & WBSD_INT_TIMEOUT)
 		tasklet_hi_schedule(&host->timeout_tasklet);
-	if (isr & WBSD_INT_BUSYEND)
-		tasklet_hi_schedule(&host->block_tasklet);
 	if (isr & WBSD_INT_TC)
 		tasklet_schedule(&host->finish_tasklet);
 
@@ -1601,8 +1493,6 @@
 			(unsigned long)host);
 	tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish,
 			(unsigned long)host);
-	tasklet_init(&host->block_tasklet, wbsd_tasklet_block,
-			(unsigned long)host);
 
 	return 0;
 }
@@ -1621,7 +1511,6 @@
 	tasklet_kill(&host->crc_tasklet);
 	tasklet_kill(&host->timeout_tasklet);
 	tasklet_kill(&host->finish_tasklet);
-	tasklet_kill(&host->block_tasklet);
 }
 
 /*
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/host/wbsd.h
similarity index 95%
rename from drivers/mmc/wbsd.h
rename to drivers/mmc/host/wbsd.h
index d06718b..873bda1 100644
--- a/drivers/mmc/wbsd.h
+++ b/drivers/mmc/host/wbsd.h
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/wbsd.h - Winbond W83L51xD SD/MMC driver
  *
- *  Copyright (C) 2004-2005 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2004-2007 Pierre Ossman, 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 as published by
@@ -46,10 +46,10 @@
 
 #define WBSD_EINT_CARD		0x40
 #define WBSD_EINT_FIFO_THRE	0x20
-#define WBSD_EINT_CCRC		0x10
+#define WBSD_EINT_CRC		0x10
 #define WBSD_EINT_TIMEOUT	0x08
 #define WBSD_EINT_PROGEND	0x04
-#define WBSD_EINT_CRC		0x02
+#define WBSD_EINT_BUSYEND	0x02
 #define WBSD_EINT_TC		0x01
 
 #define WBSD_INT_PENDING	0x80
@@ -158,8 +158,6 @@
 	unsigned int		offset;		/* Offset into current entry */
 	unsigned int		remain;		/* Data left in curren entry */
 
-	int			size;		/* Total size of transfer */
-
 	char*			dma_buffer;	/* ISA DMA buffer */
 	dma_addr_t		dma_addr;	/* Physical address for same */
 
@@ -182,7 +180,6 @@
 	struct tasklet_struct	crc_tasklet;
 	struct tasklet_struct	timeout_tasklet;
 	struct tasklet_struct	finish_tasklet;
-	struct tasklet_struct	block_tasklet;
 
 	struct timer_list	ignore_timer;	/* Ignore detection timer */
 };
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
deleted file mode 100644
index 4a73e8b..0000000
--- a/drivers/mmc/mmc.c
+++ /dev/null
@@ -1,1724 +0,0 @@
-/*
- *  linux/drivers/mmc/mmc.c
- *
- *  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
- * published by the Free Software Foundation.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/completion.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/pagemap.h>
-#include <linux/err.h>
-#include <asm/scatterlist.h>
-#include <linux/scatterlist.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/protocol.h>
-
-#include "mmc.h"
-
-#define CMD_RETRIES	3
-
-/*
- * OCR Bit positions to 10s of Vdd mV.
- */
-static const unsigned short mmc_ocr_bit_to_vdd[] = {
-	150,	155,	160,	165,	170,	180,	190,	200,
-	210,	220,	230,	240,	250,	260,	270,	280,
-	290,	300,	310,	320,	330,	340,	350,	360
-};
-
-static const unsigned int tran_exp[] = {
-	10000,		100000,		1000000,	10000000,
-	0,		0,		0,		0
-};
-
-static const unsigned char tran_mant[] = {
-	0,	10,	12,	13,	15,	20,	25,	30,
-	35,	40,	45,	50,	55,	60,	70,	80,
-};
-
-static const unsigned int tacc_exp[] = {
-	1,	10,	100,	1000,	10000,	100000,	1000000, 10000000,
-};
-
-static const unsigned int tacc_mant[] = {
-	0,	10,	12,	13,	15,	20,	25,	30,
-	35,	40,	45,	50,	55,	60,	70,	80,
-};
-
-
-/**
- *	mmc_request_done - finish processing an MMC request
- *	@host: MMC host which completed request
- *	@mrq: MMC request which request
- *
- *	MMC drivers should call this function when they have completed
- *	their processing of a request.
- */
-void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
-{
-	struct mmc_command *cmd = mrq->cmd;
-	int err = cmd->error;
-
-	pr_debug("%s: req done (CMD%u): %d/%d/%d: %08x %08x %08x %08x\n",
-		 mmc_hostname(host), cmd->opcode, err,
-		 mrq->data ? mrq->data->error : 0,
-		 mrq->stop ? mrq->stop->error : 0,
-		 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
-
-	if (err && cmd->retries) {
-		cmd->retries--;
-		cmd->error = 0;
-		host->ops->request(host, mrq);
-	} else if (mrq->done) {
-		mrq->done(mrq);
-	}
-}
-
-EXPORT_SYMBOL(mmc_request_done);
-
-/**
- *	mmc_start_request - start a command on a host
- *	@host: MMC host to start command on
- *	@mrq: MMC request to start
- *
- *	Queue a command on the specified host.  We expect the
- *	caller to be holding the host lock with interrupts disabled.
- */
-void
-mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
-{
-	pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
-		 mmc_hostname(host), mrq->cmd->opcode,
-		 mrq->cmd->arg, mrq->cmd->flags);
-
-	WARN_ON(!host->claimed);
-
-	mrq->cmd->error = 0;
-	mrq->cmd->mrq = mrq;
-	if (mrq->data) {
-		BUG_ON(mrq->data->blksz > host->max_blk_size);
-		BUG_ON(mrq->data->blocks > host->max_blk_count);
-		BUG_ON(mrq->data->blocks * mrq->data->blksz >
-			host->max_req_size);
-
-		mrq->cmd->data = mrq->data;
-		mrq->data->error = 0;
-		mrq->data->mrq = mrq;
-		if (mrq->stop) {
-			mrq->data->stop = mrq->stop;
-			mrq->stop->error = 0;
-			mrq->stop->mrq = mrq;
-		}
-	}
-	host->ops->request(host, mrq);
-}
-
-EXPORT_SYMBOL(mmc_start_request);
-
-static void mmc_wait_done(struct mmc_request *mrq)
-{
-	complete(mrq->done_data);
-}
-
-int mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
-{
-	DECLARE_COMPLETION_ONSTACK(complete);
-
-	mrq->done_data = &complete;
-	mrq->done = mmc_wait_done;
-
-	mmc_start_request(host, mrq);
-
-	wait_for_completion(&complete);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(mmc_wait_for_req);
-
-/**
- *	mmc_wait_for_cmd - start a command and wait for completion
- *	@host: MMC host to start command
- *	@cmd: MMC command to start
- *	@retries: maximum number of retries
- *
- *	Start a new MMC command for a host, and wait for the command
- *	to complete.  Return any error that occurred while the command
- *	was executing.  Do not attempt to parse the response.
- */
-int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
-{
-	struct mmc_request mrq;
-
-	BUG_ON(!host->claimed);
-
-	memset(&mrq, 0, sizeof(struct mmc_request));
-
-	memset(cmd->resp, 0, sizeof(cmd->resp));
-	cmd->retries = retries;
-
-	mrq.cmd = cmd;
-	cmd->data = NULL;
-
-	mmc_wait_for_req(host, &mrq);
-
-	return cmd->error;
-}
-
-EXPORT_SYMBOL(mmc_wait_for_cmd);
-
-/**
- *	mmc_wait_for_app_cmd - start an application command and wait for
- 			       completion
- *	@host: MMC host to start command
- *	@rca: RCA to send MMC_APP_CMD to
- *	@cmd: MMC command to start
- *	@retries: maximum number of retries
- *
- *	Sends a MMC_APP_CMD, checks the card response, sends the command
- *	in the parameter and waits for it to complete. Return any error
- *	that occurred while the command was executing.  Do not attempt to
- *	parse the response.
- */
-int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
-	struct mmc_command *cmd, int retries)
-{
-	struct mmc_request mrq;
-	struct mmc_command appcmd;
-
-	int i, err;
-
-	BUG_ON(!host->claimed);
-	BUG_ON(retries < 0);
-
-	err = MMC_ERR_INVALID;
-
-	/*
-	 * We have to resend MMC_APP_CMD for each attempt so
-	 * we cannot use the retries field in mmc_command.
-	 */
-	for (i = 0;i <= retries;i++) {
-		memset(&mrq, 0, sizeof(struct mmc_request));
-
-		appcmd.opcode = MMC_APP_CMD;
-		appcmd.arg = rca << 16;
-		appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-		appcmd.retries = 0;
-		memset(appcmd.resp, 0, sizeof(appcmd.resp));
-		appcmd.data = NULL;
-
-		mrq.cmd = &appcmd;
-		appcmd.data = NULL;
-
-		mmc_wait_for_req(host, &mrq);
-
-		if (appcmd.error) {
-			err = appcmd.error;
-			continue;
-		}
-
-		/* Check that card supported application commands */
-		if (!(appcmd.resp[0] & R1_APP_CMD))
-			return MMC_ERR_FAILED;
-
-		memset(&mrq, 0, sizeof(struct mmc_request));
-
-		memset(cmd->resp, 0, sizeof(cmd->resp));
-		cmd->retries = 0;
-
-		mrq.cmd = cmd;
-		cmd->data = NULL;
-
-		mmc_wait_for_req(host, &mrq);
-
-		err = cmd->error;
-		if (cmd->error == MMC_ERR_NONE)
-			break;
-	}
-
-	return err;
-}
-
-EXPORT_SYMBOL(mmc_wait_for_app_cmd);
-
-/**
- *	mmc_set_data_timeout - set the timeout for a data command
- *	@data: data phase for command
- *	@card: the MMC card associated with the data transfer
- *	@write: flag to differentiate reads from writes
- */
-void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
-			  int write)
-{
-	unsigned int mult;
-
-	/*
-	 * SD cards use a 100 multiplier rather than 10
-	 */
-	mult = mmc_card_sd(card) ? 100 : 10;
-
-	/*
-	 * Scale up the multiplier (and therefore the timeout) by
-	 * the r2w factor for writes.
-	 */
-	if (write)
-		mult <<= card->csd.r2w_factor;
-
-	data->timeout_ns = card->csd.tacc_ns * mult;
-	data->timeout_clks = card->csd.tacc_clks * mult;
-
-	/*
-	 * SD cards also have an upper limit on the timeout.
-	 */
-	if (mmc_card_sd(card)) {
-		unsigned int timeout_us, limit_us;
-
-		timeout_us = data->timeout_ns / 1000;
-		timeout_us += data->timeout_clks * 1000 /
-			(card->host->ios.clock / 1000);
-
-		if (write)
-			limit_us = 250000;
-		else
-			limit_us = 100000;
-
-		/*
-		 * SDHC cards always use these fixed values.
-		 */
-		if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
-			data->timeout_ns = limit_us * 1000;
-			data->timeout_clks = 0;
-		}
-	}
-}
-EXPORT_SYMBOL(mmc_set_data_timeout);
-
-static int mmc_select_card(struct mmc_host *host, struct mmc_card *card);
-
-/**
- *	__mmc_claim_host - exclusively claim a host
- *	@host: mmc host to claim
- *	@card: mmc card to claim host for
- *
- *	Claim a host for a set of operations.  If a valid card
- *	is passed and this wasn't the last card selected, select
- *	the card before returning.
- *
- *	Note: you should use mmc_card_claim_host or mmc_claim_host.
- */
-int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long flags;
-	int err = 0;
-
-	add_wait_queue(&host->wq, &wait);
-	spin_lock_irqsave(&host->lock, flags);
-	while (1) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		if (!host->claimed)
-			break;
-		spin_unlock_irqrestore(&host->lock, flags);
-		schedule();
-		spin_lock_irqsave(&host->lock, flags);
-	}
-	set_current_state(TASK_RUNNING);
-	host->claimed = 1;
-	spin_unlock_irqrestore(&host->lock, flags);
-	remove_wait_queue(&host->wq, &wait);
-
-	if (card != (void *)-1) {
-		err = mmc_select_card(host, card);
-		if (err != MMC_ERR_NONE)
-			return err;
-	}
-
-	return err;
-}
-
-EXPORT_SYMBOL(__mmc_claim_host);
-
-/**
- *	mmc_release_host - release a host
- *	@host: mmc host to release
- *
- *	Release a MMC host, allowing others to claim the host
- *	for their operations.
- */
-void mmc_release_host(struct mmc_host *host)
-{
-	unsigned long flags;
-
-	BUG_ON(!host->claimed);
-
-	spin_lock_irqsave(&host->lock, flags);
-	host->claimed = 0;
-	spin_unlock_irqrestore(&host->lock, flags);
-
-	wake_up(&host->wq);
-}
-
-EXPORT_SYMBOL(mmc_release_host);
-
-static inline void mmc_set_ios(struct mmc_host *host)
-{
-	struct mmc_ios *ios = &host->ios;
-
-	pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
-		"width %u timing %u\n",
-		 mmc_hostname(host), ios->clock, ios->bus_mode,
-		 ios->power_mode, ios->chip_select, ios->vdd,
-		 ios->bus_width, ios->timing);
-
-	host->ops->set_ios(host, ios);
-}
-
-static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
-{
-	int err;
-	struct mmc_command cmd;
-
-	BUG_ON(!host->claimed);
-
-	if (host->card_selected == card)
-		return MMC_ERR_NONE;
-
-	host->card_selected = card;
-
-	cmd.opcode = MMC_SELECT_CARD;
-	cmd.arg = card->rca << 16;
-	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-	err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-	if (err != MMC_ERR_NONE)
-		return err;
-
-	/*
-	 * 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 (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;
-			cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-			err = mmc_wait_for_app_cmd(host, card->rca, &cmd,
-				CMD_RETRIES);
-			if (err != MMC_ERR_NONE)
-				return err;
-
-			host->ios.bus_width = MMC_BUS_WIDTH_4;
-		}
-	}
-
-	mmc_set_ios(host);
-
-	return MMC_ERR_NONE;
-}
-
-/*
- * Ensure that no card is selected.
- */
-static void mmc_deselect_cards(struct mmc_host *host)
-{
-	struct mmc_command cmd;
-
-	if (host->card_selected) {
-		host->card_selected = NULL;
-
-		cmd.opcode = MMC_SELECT_CARD;
-		cmd.arg = 0;
-		cmd.flags = MMC_RSP_NONE | MMC_CMD_AC;
-
-		mmc_wait_for_cmd(host, &cmd, 0);
-	}
-}
-
-
-static inline void mmc_delay(unsigned int ms)
-{
-	if (ms < 1000 / HZ) {
-		cond_resched();
-		mdelay(ms);
-	} else {
-		msleep(ms);
-	}
-}
-
-/*
- * Mask off any voltages we don't support and select
- * the lowest voltage
- */
-static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
-{
-	int bit;
-
-	ocr &= host->ocr_avail;
-
-	bit = ffs(ocr);
-	if (bit) {
-		bit -= 1;
-
-		ocr &= 3 << bit;
-
-		host->ios.vdd = bit;
-		mmc_set_ios(host);
-	} else {
-		ocr = 0;
-	}
-
-	return ocr;
-}
-
-#define UNSTUFF_BITS(resp,start,size)					\
-	({								\
-		const int __size = size;				\
-		const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1;	\
-		const int __off = 3 - ((start) / 32);			\
-		const int __shft = (start) & 31;			\
-		u32 __res;						\
-									\
-		__res = resp[__off] >> __shft;				\
-		if (__size + __shft > 32)				\
-			__res |= resp[__off-1] << ((32 - __shft) % 32);	\
-		__res & __mask;						\
-	})
-
-/*
- * Given the decoded CSD structure, decode the raw CID to our CID structure.
- */
-static void mmc_decode_cid(struct mmc_card *card)
-{
-	u32 *resp = card->raw_cid;
-
-	memset(&card->cid, 0, sizeof(struct mmc_cid));
-
-	if (mmc_card_sd(card)) {
-		/*
-		 * SD doesn't currently have a version field so we will
-		 * have to assume we can parse this.
-		 */
-		card->cid.manfid		= UNSTUFF_BITS(resp, 120, 8);
-		card->cid.oemid			= UNSTUFF_BITS(resp, 104, 16);
-		card->cid.prod_name[0]		= UNSTUFF_BITS(resp, 96, 8);
-		card->cid.prod_name[1]		= UNSTUFF_BITS(resp, 88, 8);
-		card->cid.prod_name[2]		= UNSTUFF_BITS(resp, 80, 8);
-		card->cid.prod_name[3]		= UNSTUFF_BITS(resp, 72, 8);
-		card->cid.prod_name[4]		= UNSTUFF_BITS(resp, 64, 8);
-		card->cid.hwrev			= UNSTUFF_BITS(resp, 60, 4);
-		card->cid.fwrev			= UNSTUFF_BITS(resp, 56, 4);
-		card->cid.serial		= UNSTUFF_BITS(resp, 24, 32);
-		card->cid.year			= UNSTUFF_BITS(resp, 12, 8);
-		card->cid.month			= UNSTUFF_BITS(resp, 8, 4);
-
-		card->cid.year += 2000; /* SD cards year offset */
-	} else {
-		/*
-		 * The selection of the format here is based upon published
-		 * specs from sandisk and from what people have reported.
-		 */
-		switch (card->csd.mmca_vsn) {
-		case 0: /* MMC v1.0 - v1.2 */
-		case 1: /* MMC v1.4 */
-			card->cid.manfid	= UNSTUFF_BITS(resp, 104, 24);
-			card->cid.prod_name[0]	= UNSTUFF_BITS(resp, 96, 8);
-			card->cid.prod_name[1]	= UNSTUFF_BITS(resp, 88, 8);
-			card->cid.prod_name[2]	= UNSTUFF_BITS(resp, 80, 8);
-			card->cid.prod_name[3]	= UNSTUFF_BITS(resp, 72, 8);
-			card->cid.prod_name[4]	= UNSTUFF_BITS(resp, 64, 8);
-			card->cid.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);
-			card->cid.prod_name[6]	= UNSTUFF_BITS(resp, 48, 8);
-			card->cid.hwrev		= UNSTUFF_BITS(resp, 44, 4);
-			card->cid.fwrev		= UNSTUFF_BITS(resp, 40, 4);
-			card->cid.serial	= UNSTUFF_BITS(resp, 16, 24);
-			card->cid.month		= UNSTUFF_BITS(resp, 12, 4);
-			card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;
-			break;
-
-		case 2: /* MMC v2.0 - v2.2 */
-		case 3: /* MMC v3.1 - v3.3 */
-		case 4: /* MMC v4 */
-			card->cid.manfid	= UNSTUFF_BITS(resp, 120, 8);
-			card->cid.oemid		= UNSTUFF_BITS(resp, 104, 16);
-			card->cid.prod_name[0]	= UNSTUFF_BITS(resp, 96, 8);
-			card->cid.prod_name[1]	= UNSTUFF_BITS(resp, 88, 8);
-			card->cid.prod_name[2]	= UNSTUFF_BITS(resp, 80, 8);
-			card->cid.prod_name[3]	= UNSTUFF_BITS(resp, 72, 8);
-			card->cid.prod_name[4]	= UNSTUFF_BITS(resp, 64, 8);
-			card->cid.prod_name[5]	= UNSTUFF_BITS(resp, 56, 8);
-			card->cid.serial	= UNSTUFF_BITS(resp, 16, 32);
-			card->cid.month		= UNSTUFF_BITS(resp, 12, 4);
-			card->cid.year		= UNSTUFF_BITS(resp, 8, 4) + 1997;
-			break;
-
-		default:
-			printk("%s: card has unknown MMCA version %d\n",
-				mmc_hostname(card->host), card->csd.mmca_vsn);
-			mmc_card_set_bad(card);
-			break;
-		}
-	}
-}
-
-/*
- * Given a 128-bit response, decode to our card CSD structure.
- */
-static void mmc_decode_csd(struct mmc_card *card)
-{
-	struct mmc_csd *csd = &card->csd;
-	unsigned int e, m, csd_struct;
-	u32 *resp = card->raw_csd;
-
-	if (mmc_card_sd(card)) {
-		csd_struct = UNSTUFF_BITS(resp, 126, 2);
-
-		switch (csd_struct) {
-		case 0:
-			m = UNSTUFF_BITS(resp, 115, 4);
-			e = UNSTUFF_BITS(resp, 112, 3);
-			csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
-			csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
-
-			m = UNSTUFF_BITS(resp, 99, 4);
-			e = UNSTUFF_BITS(resp, 96, 3);
-			csd->max_dtr	  = tran_exp[e] * tran_mant[m];
-			csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
-
-			e = UNSTUFF_BITS(resp, 47, 3);
-			m = UNSTUFF_BITS(resp, 62, 12);
-			csd->capacity	  = (1 + m) << (e + 2);
-
-			csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-			csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
-			csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
-			csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
-			csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
-			csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
-			csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
-			break;
-		case 1:
-			/*
-			 * This is a block-addressed SDHC card. Most
-			 * interesting fields are unused and have fixed
-			 * values. To avoid getting tripped by buggy cards,
-			 * we assume those fixed values ourselves.
-			 */
-			mmc_card_set_blockaddr(card);
-
-			csd->tacc_ns	 = 0; /* Unused */
-			csd->tacc_clks	 = 0; /* Unused */
-
-			m = UNSTUFF_BITS(resp, 99, 4);
-			e = UNSTUFF_BITS(resp, 96, 3);
-			csd->max_dtr	  = tran_exp[e] * tran_mant[m];
-			csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
-
-			m = UNSTUFF_BITS(resp, 48, 22);
-			csd->capacity     = (1 + m) << 10;
-
-			csd->read_blkbits = 9;
-			csd->read_partial = 0;
-			csd->write_misalign = 0;
-			csd->read_misalign = 0;
-			csd->r2w_factor = 4; /* Unused */
-			csd->write_blkbits = 9;
-			csd->write_partial = 0;
-			break;
-		default:
-			printk("%s: unrecognised CSD structure version %d\n",
-				mmc_hostname(card->host), csd_struct);
-			mmc_card_set_bad(card);
-			return;
-		}
-	} else {
-		/*
-		 * We only understand CSD structure v1.1 and v1.2.
-		 * v1.2 has extra information in bits 15, 11 and 10.
-		 */
-		csd_struct = UNSTUFF_BITS(resp, 126, 2);
-		if (csd_struct != 1 && csd_struct != 2) {
-			printk("%s: unrecognised CSD structure version %d\n",
-				mmc_hostname(card->host), csd_struct);
-			mmc_card_set_bad(card);
-			return;
-		}
-
-		csd->mmca_vsn	 = UNSTUFF_BITS(resp, 122, 4);
-		m = UNSTUFF_BITS(resp, 115, 4);
-		e = UNSTUFF_BITS(resp, 112, 3);
-		csd->tacc_ns	 = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
-		csd->tacc_clks	 = UNSTUFF_BITS(resp, 104, 8) * 100;
-
-		m = UNSTUFF_BITS(resp, 99, 4);
-		e = UNSTUFF_BITS(resp, 96, 3);
-		csd->max_dtr	  = tran_exp[e] * tran_mant[m];
-		csd->cmdclass	  = UNSTUFF_BITS(resp, 84, 12);
-
-		e = UNSTUFF_BITS(resp, 47, 3);
-		m = UNSTUFF_BITS(resp, 62, 12);
-		csd->capacity	  = (1 + m) << (e + 2);
-
-		csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-		csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
-		csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
-		csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
-		csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
-		csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
-		csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
-	}
-}
-
-/*
- * Given a 64-bit response, decode to our card SCR structure.
- */
-static void mmc_decode_scr(struct mmc_card *card)
-{
-	struct sd_scr *scr = &card->scr;
-	unsigned int scr_struct;
-	u32 resp[4];
-
-	BUG_ON(!mmc_card_sd(card));
-
-	resp[3] = card->raw_scr[1];
-	resp[2] = card->raw_scr[0];
-
-	scr_struct = UNSTUFF_BITS(resp, 60, 4);
-	if (scr_struct != 0) {
-		printk("%s: unrecognised SCR structure version %d\n",
-			mmc_hostname(card->host), scr_struct);
-		mmc_card_set_bad(card);
-		return;
-	}
-
-	scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
-	scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
-}
-
-/*
- * Locate a MMC card on this MMC host given a raw CID.
- */
-static struct mmc_card *mmc_find_card(struct mmc_host *host, u32 *raw_cid)
-{
-	struct mmc_card *card;
-
-	list_for_each_entry(card, &host->cards, node) {
-		if (memcmp(card->raw_cid, raw_cid, sizeof(card->raw_cid)) == 0)
-			return card;
-	}
-	return NULL;
-}
-
-/*
- * Allocate a new MMC card, and assign a unique RCA.
- */
-static struct mmc_card *
-mmc_alloc_card(struct mmc_host *host, u32 *raw_cid, unsigned int *frca)
-{
-	struct mmc_card *card, *c;
-	unsigned int rca = *frca;
-
-	card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
-	if (!card)
-		return ERR_PTR(-ENOMEM);
-
-	mmc_init_card(card, host);
-	memcpy(card->raw_cid, raw_cid, sizeof(card->raw_cid));
-
- again:
-	list_for_each_entry(c, &host->cards, node)
-		if (c->rca == rca) {
-			rca++;
-			goto again;
-		}
-
-	card->rca = rca;
-
-	*frca = rca;
-
-	return card;
-}
-
-/*
- * Tell attached cards to go to IDLE state
- */
-static void mmc_idle_cards(struct mmc_host *host)
-{
-	struct mmc_command cmd;
-
-	host->ios.chip_select = MMC_CS_HIGH;
-	mmc_set_ios(host);
-
-	mmc_delay(1);
-
-	cmd.opcode = MMC_GO_IDLE_STATE;
-	cmd.arg = 0;
-	cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
-
-	mmc_wait_for_cmd(host, &cmd, 0);
-
-	mmc_delay(1);
-
-	host->ios.chip_select = MMC_CS_DONTCARE;
-	mmc_set_ios(host);
-
-	mmc_delay(1);
-}
-
-/*
- * Apply power to the MMC stack.  This is a two-stage process.
- * First, we enable power to the card without the clock running.
- * We then wait a bit for the power to stabilise.  Finally,
- * enable the bus drivers and clock to the card.
- *
- * We must _NOT_ enable the clock prior to power stablising.
- *
- * If a host does all the power sequencing itself, ignore the
- * initial MMC_POWER_UP stage.
- */
-static void mmc_power_up(struct mmc_host *host)
-{
-	int bit = fls(host->ocr_avail) - 1;
-
-	host->ios.vdd = bit;
-	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-	host->ios.chip_select = MMC_CS_DONTCARE;
-	host->ios.power_mode = MMC_POWER_UP;
-	host->ios.bus_width = MMC_BUS_WIDTH_1;
-	host->ios.timing = MMC_TIMING_LEGACY;
-	mmc_set_ios(host);
-
-	mmc_delay(1);
-
-	host->ios.clock = host->f_min;
-	host->ios.power_mode = MMC_POWER_ON;
-	mmc_set_ios(host);
-
-	mmc_delay(2);
-}
-
-static void mmc_power_off(struct mmc_host *host)
-{
-	host->ios.clock = 0;
-	host->ios.vdd = 0;
-	host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-	host->ios.chip_select = MMC_CS_DONTCARE;
-	host->ios.power_mode = MMC_POWER_OFF;
-	host->ios.bus_width = MMC_BUS_WIDTH_1;
-	host->ios.timing = MMC_TIMING_LEGACY;
-	mmc_set_ios(host);
-}
-
-static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
-{
-	struct mmc_command cmd;
-	int i, err = 0;
-
-	cmd.opcode = MMC_SEND_OP_COND;
-	cmd.arg = ocr;
-	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
-
-	for (i = 100; i; i--) {
-		err = mmc_wait_for_cmd(host, &cmd, 0);
-		if (err != MMC_ERR_NONE)
-			break;
-
-		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
-			break;
-
-		err = MMC_ERR_TIMEOUT;
-
-		mmc_delay(10);
-	}
-
-	if (rocr)
-		*rocr = cmd.resp[0];
-
-	return err;
-}
-
-static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
-{
-	struct mmc_command cmd;
-	int i, err = 0;
-
-	cmd.opcode = SD_APP_OP_COND;
-	cmd.arg = ocr;
-	cmd.flags = MMC_RSP_R3 | MMC_CMD_BCR;
-
-	for (i = 100; i; i--) {
-		err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);
-		if (err != MMC_ERR_NONE)
-			break;
-
-		if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0)
-			break;
-
-		err = MMC_ERR_TIMEOUT;
-
-		mmc_delay(10);
-	}
-
-	if (rocr)
-		*rocr = cmd.resp[0];
-
-	return err;
-}
-
-static int mmc_send_if_cond(struct mmc_host *host, u32 ocr, int *rsd2)
-{
-	struct mmc_command cmd;
-	int err, sd2;
-	static const u8 test_pattern = 0xAA;
-
-	/*
-	* To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
-	* before SD_APP_OP_COND. This command will harmlessly fail for
-	* SD 1.0 cards.
-	*/
-	cmd.opcode = SD_SEND_IF_COND;
-	cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
-	cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
-
-	err = mmc_wait_for_cmd(host, &cmd, 0);
-	if (err == MMC_ERR_NONE) {
-		if ((cmd.resp[0] & 0xFF) == test_pattern) {
-			sd2 = 1;
-		} else {
-			sd2 = 0;
-			err = MMC_ERR_FAILED;
-		}
-	} else {
-		/*
-		 * Treat errors as SD 1.0 card.
-		 */
-		sd2 = 0;
-		err = MMC_ERR_NONE;
-	}
-	if (rsd2)
-		*rsd2 = sd2;
-	return err;
-}
-
-/*
- * Discover cards by requesting their CID.  If this command
- * times out, it is not an error; there are no further cards
- * to be discovered.  Add new cards to the list.
- *
- * Create a mmc_card entry for each discovered card, assigning
- * it an RCA, and save the raw CID for decoding later.
- */
-static void mmc_discover_cards(struct mmc_host *host)
-{
-	struct mmc_card *card;
-	unsigned int first_rca = 1, err;
-
-	while (1) {
-		struct mmc_command cmd;
-
-		cmd.opcode = MMC_ALL_SEND_CID;
-		cmd.arg = 0;
-		cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
-
-		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-		if (err == MMC_ERR_TIMEOUT) {
-			err = MMC_ERR_NONE;
-			break;
-		}
-		if (err != MMC_ERR_NONE) {
-			printk(KERN_ERR "%s: error requesting CID: %d\n",
-				mmc_hostname(host), err);
-			break;
-		}
-
-		card = mmc_find_card(host, cmd.resp);
-		if (!card) {
-			card = mmc_alloc_card(host, cmd.resp, &first_rca);
-			if (IS_ERR(card)) {
-				err = PTR_ERR(card);
-				break;
-			}
-			list_add(&card->node, &host->cards);
-		}
-
-		card->state &= ~MMC_STATE_DEAD;
-
-		if (host->mode == MMC_MODE_SD) {
-			mmc_card_set_sd(card);
-
-			cmd.opcode = SD_SEND_RELATIVE_ADDR;
-			cmd.arg = 0;
-			cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
-
-			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-			if (err != MMC_ERR_NONE)
-				mmc_card_set_dead(card);
-			else {
-				card->rca = cmd.resp[0] >> 16;
-
-				if (!host->ops->get_ro) {
-					printk(KERN_WARNING "%s: host does not "
-						"support reading read-only "
-						"switch. assuming write-enable.\n",
-						mmc_hostname(host));
-				} else {
-					if (host->ops->get_ro(host))
-						mmc_card_set_readonly(card);
-				}
-			}
-		} else {
-			cmd.opcode = MMC_SET_RELATIVE_ADDR;
-			cmd.arg = card->rca << 16;
-			cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-			err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-			if (err != MMC_ERR_NONE)
-				mmc_card_set_dead(card);
-		}
-	}
-}
-
-static void mmc_read_csds(struct mmc_host *host)
-{
-	struct mmc_card *card;
-
-	list_for_each_entry(card, &host->cards, node) {
-		struct mmc_command cmd;
-		int err;
-
-		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
-			continue;
-
-		cmd.opcode = MMC_SEND_CSD;
-		cmd.arg = card->rca << 16;
-		cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
-
-		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-		if (err != MMC_ERR_NONE) {
-			mmc_card_set_dead(card);
-			continue;
-		}
-
-		memcpy(card->raw_csd, cmd.resp, sizeof(card->raw_csd));
-
-		mmc_decode_csd(card);
-		mmc_decode_cid(card);
-	}
-}
-
-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) {
-			printk("%s: unable to read EXT_CSD, performance "
-				"might suffer.\n", mmc_hostname(card->host));
-			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));
-			continue;
-		}
-
-		if (host->caps & MMC_CAP_MMC_HIGHSPEED) {
-			/* 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);
-
-			host->ios.timing = MMC_TIMING_SD_HS;
-			mmc_set_ios(host);
-		}
-
-		/* Check for host support for wide-bus modes. */
-		if (host->caps & MMC_CAP_4_BIT_DATA) {
-			/* 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;
-			mmc_set_ios(host);
-		}
-	}
-
-	kfree(ext_csd);
-
-	mmc_deselect_cards(host);
-}
-
-static void mmc_read_scrs(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;
-
-	list_for_each_entry(card, &host->cards, node) {
-		if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT))
-			continue;
-		if (!mmc_card_sd(card))
-			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_APP_CMD;
-		cmd.arg = card->rca << 16;
-		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-		err = mmc_wait_for_cmd(host, &cmd, 0);
-		if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) {
-			mmc_card_set_dead(card);
-			continue;
-		}
-
-		memset(&cmd, 0, sizeof(struct mmc_command));
-
-		cmd.opcode = SD_APP_SEND_SCR;
-		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 = 1 << 3;
-		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, (u8*)card->raw_scr, 8);
-
-		mmc_wait_for_req(host, &mrq);
-
-		if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-			mmc_card_set_dead(card);
-			continue;
-		}
-
-		card->raw_scr[0] = ntohl(card->raw_scr[0]);
-		card->raw_scr[1] = ntohl(card->raw_scr[1]);
-
-		mmc_decode_scr(card);
-	}
-
-	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;
-
-	if (!(host->caps & MMC_CAP_SD_HIGHSPEED))
-		return;
-
-	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) {
-			printk("%s: unable to read switch capabilities, "
-				"performance might suffer.\n",
-				mmc_hostname(card->host));
-			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 ||
-			(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);
-
-		host->ios.timing = MMC_TIMING_SD_HS;
-		mmc_set_ios(host);
-	}
-
-	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)) {
-			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),
-		 max_dtr / 1000000, (max_dtr / 1000) % 1000);
-
-	return max_dtr;
-}
-
-/*
- * Check whether cards we already know about are still present.
- * We do this by requesting status, and checking whether a card
- * responds.
- *
- * A request for status does not cause a state change in data
- * transfer mode.
- */
-static void mmc_check_cards(struct mmc_host *host)
-{
-	struct list_head *l, *n;
-
-	mmc_deselect_cards(host);
-
-	list_for_each_safe(l, n, &host->cards) {
-		struct mmc_card *card = mmc_list_to_card(l);
-		struct mmc_command cmd;
-		int err;
-
-		cmd.opcode = MMC_SEND_STATUS;
-		cmd.arg = card->rca << 16;
-		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-		err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-		if (err == MMC_ERR_NONE)
-			continue;
-
-		mmc_card_set_dead(card);
-	}
-}
-
-static void mmc_setup(struct mmc_host *host)
-{
-	if (host->ios.power_mode != MMC_POWER_ON) {
-		int err;
-		u32 ocr;
-
-		host->mode = MMC_MODE_SD;
-
-		mmc_power_up(host);
-		mmc_idle_cards(host);
-
-		err = mmc_send_if_cond(host, host->ocr_avail, NULL);
-		if (err != MMC_ERR_NONE) {
-			return;
-		}
-		err = mmc_send_app_op_cond(host, 0, &ocr);
-
-		/*
-		 * If we fail to detect any SD cards then try
-		 * searching for MMC cards.
-		 */
-		if (err != MMC_ERR_NONE) {
-			host->mode = MMC_MODE_MMC;
-
-			err = mmc_send_op_cond(host, 0, &ocr);
-			if (err != MMC_ERR_NONE)
-				return;
-		}
-
-		host->ocr = mmc_select_voltage(host, ocr);
-
-		/*
-		 * Since we're changing the OCR value, we seem to
-		 * need to tell some cards to go back to the idle
-		 * state.  We wait 1ms to give cards time to
-		 * respond.
-		 */
-		if (host->ocr)
-			mmc_idle_cards(host);
-	} else {
-		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-		host->ios.clock = host->f_min;
-		mmc_set_ios(host);
-
-		/*
-		 * We should remember the OCR mask from the existing
-		 * cards, and detect the new cards OCR mask, combine
-		 * the two and re-select the VDD.  However, if we do
-		 * change VDD, we should do an idle, and then do a
-		 * full re-initialisation.  We would need to notify
-		 * drivers so that they can re-setup the cards as
-		 * well, while keeping their queues at bay.
-		 *
-		 * For the moment, we take the easy way out - if the
-		 * new cards don't like our currently selected VDD,
-		 * they drop off the bus.
-		 */
-	}
-
-	if (host->ocr == 0)
-		return;
-
-	/*
-	 * Send the selected OCR multiple times... until the cards
-	 * all get the idea that they should be ready for CMD2.
-	 * (My SanDisk card seems to need this.)
-	 */
-	if (host->mode == MMC_MODE_SD) {
-		int err, sd2;
-		err = mmc_send_if_cond(host, host->ocr, &sd2);
-		if (err == MMC_ERR_NONE) {
-			/*
-			* If SD_SEND_IF_COND indicates an SD 2.0
-			* compliant card and we should set bit 30
-			* of the ocr to indicate that we can handle
-			* block-addressed SDHC cards.
-			*/
-			mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL);
-		}
-	} else {
-		mmc_send_op_cond(host, host->ocr, NULL);
-	}
-
-	mmc_discover_cards(host);
-
-	/*
-	 * Ok, now switch to push-pull mode.
-	 */
-	host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
-	mmc_set_ios(host);
-
-	mmc_read_csds(host);
-
-	if (host->mode == MMC_MODE_SD) {
-		mmc_read_scrs(host);
-		mmc_read_switch_caps(host);
-	} else
-		mmc_process_ext_csds(host);
-}
-
-
-/**
- *	mmc_detect_change - process change of state on a MMC socket
- *	@host: host which changed state.
- *	@delay: optional delay to wait before detection (jiffies)
- *
- *	All we know is that card(s) have been inserted or removed
- *	from the socket(s).  We don't know which socket or cards.
- */
-void mmc_detect_change(struct mmc_host *host, unsigned long delay)
-{
-	mmc_schedule_delayed_work(&host->detect, delay);
-}
-
-EXPORT_SYMBOL(mmc_detect_change);
-
-
-static void mmc_rescan(struct work_struct *work)
-{
-	struct mmc_host *host =
-		container_of(work, struct mmc_host, detect.work);
-	struct list_head *l, *n;
-	unsigned char power_mode;
-
-	mmc_claim_host(host);
-
-	/*
-	 * Check for removed cards and newly inserted ones. We check for
-	 * removed cards first so we can intelligently re-select the VDD.
-	 */
-	power_mode = host->ios.power_mode;
-	if (power_mode == MMC_POWER_ON)
-		mmc_check_cards(host);
-
-	mmc_setup(host);
-
-	/*
-	 * Some broken cards process CMD1 even in stand-by state. There is
-	 * no reply, but an ILLEGAL_COMMAND error is cached and returned
-	 * after next command. We poll for card status here to clear any
-	 * possibly pending error.
-	 */
-	if (power_mode == MMC_POWER_ON)
-		mmc_check_cards(host);
-
-	if (!list_empty(&host->cards)) {
-		/*
-		 * (Re-)calculate the fastest clock rate which the
-		 * attached cards and the host support.
-		 */
-		host->ios.clock = mmc_calculate_clock(host);
-		mmc_set_ios(host);
-	}
-
-	mmc_release_host(host);
-
-	list_for_each_safe(l, n, &host->cards) {
-		struct mmc_card *card = mmc_list_to_card(l);
-
-		/*
-		 * If this is a new and good card, register it.
-		 */
-		if (!mmc_card_present(card) && !mmc_card_dead(card)) {
-			if (mmc_register_card(card))
-				mmc_card_set_dead(card);
-			else
-				mmc_card_set_present(card);
-		}
-
-		/*
-		 * If this card is dead, destroy it.
-		 */
-		if (mmc_card_dead(card)) {
-			list_del(&card->node);
-			mmc_remove_card(card);
-		}
-	}
-
-	/*
-	 * If we discover that there are no cards on the
-	 * bus, turn off the clock and power down.
-	 */
-	if (list_empty(&host->cards))
-		mmc_power_off(host);
-}
-
-
-/**
- *	mmc_alloc_host - initialise the per-host structure.
- *	@extra: sizeof private data structure
- *	@dev: pointer to host device model structure
- *
- *	Initialise the per-host structure.
- */
-struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
-{
-	struct mmc_host *host;
-
-	host = mmc_alloc_host_sysfs(extra, dev);
-	if (host) {
-		spin_lock_init(&host->lock);
-		init_waitqueue_head(&host->wq);
-		INIT_LIST_HEAD(&host->cards);
-		INIT_DELAYED_WORK(&host->detect, mmc_rescan);
-
-		/*
-		 * By default, hosts do not support SGIO or large requests.
-		 * They have to set these according to their abilities.
-		 */
-		host->max_hw_segs = 1;
-		host->max_phys_segs = 1;
-		host->max_seg_size = PAGE_CACHE_SIZE;
-
-		host->max_req_size = PAGE_CACHE_SIZE;
-		host->max_blk_size = 512;
-		host->max_blk_count = PAGE_CACHE_SIZE / 512;
-	}
-
-	return host;
-}
-
-EXPORT_SYMBOL(mmc_alloc_host);
-
-/**
- *	mmc_add_host - initialise host hardware
- *	@host: mmc host
- */
-int mmc_add_host(struct mmc_host *host)
-{
-	int ret;
-
-	ret = mmc_add_host_sysfs(host);
-	if (ret == 0) {
-		mmc_power_off(host);
-		mmc_detect_change(host, 0);
-	}
-
-	return ret;
-}
-
-EXPORT_SYMBOL(mmc_add_host);
-
-/**
- *	mmc_remove_host - remove host hardware
- *	@host: mmc host
- *
- *	Unregister and remove all cards associated with this host,
- *	and power down the MMC bus.
- */
-void mmc_remove_host(struct mmc_host *host)
-{
-	struct list_head *l, *n;
-
-	list_for_each_safe(l, n, &host->cards) {
-		struct mmc_card *card = mmc_list_to_card(l);
-
-		mmc_remove_card(card);
-	}
-
-	mmc_power_off(host);
-	mmc_remove_host_sysfs(host);
-}
-
-EXPORT_SYMBOL(mmc_remove_host);
-
-/**
- *	mmc_free_host - free the host structure
- *	@host: mmc host
- *
- *	Free the host once all references to it have been dropped.
- */
-void mmc_free_host(struct mmc_host *host)
-{
-	mmc_flush_scheduled_work();
-	mmc_free_host_sysfs(host);
-}
-
-EXPORT_SYMBOL(mmc_free_host);
-
-#ifdef CONFIG_PM
-
-/**
- *	mmc_suspend_host - suspend a host
- *	@host: mmc host
- *	@state: suspend mode (PM_SUSPEND_xxx)
- */
-int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
-{
-	mmc_claim_host(host);
-	mmc_deselect_cards(host);
-	mmc_power_off(host);
-	mmc_release_host(host);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(mmc_suspend_host);
-
-/**
- *	mmc_resume_host - resume a previously suspended host
- *	@host: mmc host
- */
-int mmc_resume_host(struct mmc_host *host)
-{
-	mmc_rescan(&host->detect.work);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(mmc_resume_host);
-
-#endif
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c
deleted file mode 100644
index 0581d09..0000000
--- a/drivers/mmc/tifm_sd.c
+++ /dev/null
@@ -1,987 +0,0 @@
-/*
- *  tifm_sd.c - TI FlashMedia driver
- *
- *  Copyright (C) 2006 Alex Dubov <oakad@yahoo.com>
- *
- * 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
- * published by the Free Software Foundation.
- *
- */
-
-
-#include <linux/tifm.h>
-#include <linux/mmc/protocol.h>
-#include <linux/mmc/host.h>
-#include <linux/highmem.h>
-#include <asm/io.h>
-
-#define DRIVER_NAME "tifm_sd"
-#define DRIVER_VERSION "0.7"
-
-static int no_dma = 0;
-static int fixed_timeout = 0;
-module_param(no_dma, bool, 0644);
-module_param(fixed_timeout, bool, 0644);
-
-/* Constants here are mostly from OMAP5912 datasheet */
-#define TIFM_MMCSD_RESET      0x0002
-#define TIFM_MMCSD_CLKMASK    0x03ff
-#define TIFM_MMCSD_POWER      0x0800
-#define TIFM_MMCSD_4BBUS      0x8000
-#define TIFM_MMCSD_RXDE       0x8000   /* rx dma enable */
-#define TIFM_MMCSD_TXDE       0x0080   /* tx dma enable */
-#define TIFM_MMCSD_BUFINT     0x0c00   /* set bits: AE, AF */
-#define TIFM_MMCSD_DPE        0x0020   /* data timeout counted in kilocycles */
-#define TIFM_MMCSD_INAB       0x0080   /* abort / initialize command */
-#define TIFM_MMCSD_READ       0x8000
-
-#define TIFM_MMCSD_DATAMASK   0x401d   /* set bits: CERR, EOFB, BRS, CB, EOC */
-#define TIFM_MMCSD_ERRMASK    0x01e0   /* set bits: CCRC, CTO, DCRC, DTO */
-#define TIFM_MMCSD_EOC        0x0001   /* end of command phase  */
-#define TIFM_MMCSD_CB         0x0004   /* card enter busy state */
-#define TIFM_MMCSD_BRS        0x0008   /* block received/sent   */
-#define TIFM_MMCSD_EOFB       0x0010   /* card exit busy state  */
-#define TIFM_MMCSD_DTO        0x0020   /* data time-out         */
-#define TIFM_MMCSD_DCRC       0x0040   /* data crc error        */
-#define TIFM_MMCSD_CTO        0x0080   /* command time-out      */
-#define TIFM_MMCSD_CCRC       0x0100   /* command crc error     */
-#define TIFM_MMCSD_AF         0x0400   /* fifo almost full      */
-#define TIFM_MMCSD_AE         0x0800   /* fifo almost empty     */
-#define TIFM_MMCSD_CERR       0x4000   /* card status error     */
-
-#define TIFM_MMCSD_FIFO_SIZE  0x0020
-
-#define TIFM_MMCSD_RSP_R0     0x0000
-#define TIFM_MMCSD_RSP_R1     0x0100
-#define TIFM_MMCSD_RSP_R2     0x0200
-#define TIFM_MMCSD_RSP_R3     0x0300
-#define TIFM_MMCSD_RSP_R4     0x0400
-#define TIFM_MMCSD_RSP_R5     0x0500
-#define TIFM_MMCSD_RSP_R6     0x0600
-
-#define TIFM_MMCSD_RSP_BUSY   0x0800
-
-#define TIFM_MMCSD_CMD_BC     0x0000
-#define TIFM_MMCSD_CMD_BCR    0x1000
-#define TIFM_MMCSD_CMD_AC     0x2000
-#define TIFM_MMCSD_CMD_ADTC   0x3000
-
-typedef enum {
-	IDLE = 0,
-	CMD,    /* main command ended                   */
-	BRS,    /* block transfer finished              */
-	SCMD,   /* stop command ended                   */
-	CARD,   /* card left busy state                 */
-	FIFO,   /* FIFO operation completed (uncertain) */
-	READY
-} card_state_t;
-
-enum {
-	FIFO_RDY   = 0x0001,     /* hardware dependent value */
-	EJECT      = 0x0004,
-	EJECT_DONE = 0x0008,
-	CARD_BUSY  = 0x0010,
-	OPENDRAIN  = 0x0040,     /* hardware dependent value */
-	CARD_EVENT = 0x0100,     /* hardware dependent value */
-	CARD_RO    = 0x0200,     /* hardware dependent value */
-	FIFO_EVENT = 0x10000 };  /* hardware dependent value */
-
-struct tifm_sd {
-	struct tifm_dev     *dev;
-
-	unsigned int        flags;
-	card_state_t        state;
-	unsigned int        clk_freq;
-	unsigned int        clk_div;
-	unsigned long       timeout_jiffies;
-
-	struct tasklet_struct finish_tasklet;
-	struct timer_list     timer;
-	struct mmc_request    *req;
-	wait_queue_head_t     notify;
-
-	size_t                written_blocks;
-	size_t                buffer_size;
-	size_t                buffer_pos;
-
-};
-
-static char* tifm_sd_data_buffer(struct mmc_data *data)
-{
-	return page_address(data->sg->page) + data->sg->offset;
-}
-
-static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host,
-				 unsigned int host_status)
-{
-	struct mmc_command *cmd = host->req->cmd;
-	unsigned int t_val = 0, cnt = 0;
-	char *buffer;
-
-	if (host_status & TIFM_MMCSD_BRS) {
-		/* in non-dma rx mode BRS fires when fifo is still not empty */
-		if (no_dma && (cmd->data->flags & MMC_DATA_READ)) {
-			buffer = tifm_sd_data_buffer(host->req->data);
-			while (host->buffer_size > host->buffer_pos) {
-				t_val = readl(sock->addr + SOCK_MMCSD_DATA);
-				buffer[host->buffer_pos++] = t_val & 0xff;
-				buffer[host->buffer_pos++] =
-							(t_val >> 8) & 0xff;
-			}
-		}
-		return 1;
-	} else if (no_dma) {
-		buffer = tifm_sd_data_buffer(host->req->data);
-		if ((cmd->data->flags & MMC_DATA_READ) &&
-				(host_status & TIFM_MMCSD_AF)) {
-			for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
-				t_val = readl(sock->addr + SOCK_MMCSD_DATA);
-				if (host->buffer_size > host->buffer_pos) {
-					buffer[host->buffer_pos++] =
-							t_val & 0xff;
-					buffer[host->buffer_pos++] =
-							(t_val >> 8) & 0xff;
-				}
-			}
-		} else if ((cmd->data->flags & MMC_DATA_WRITE)
-			   && (host_status & TIFM_MMCSD_AE)) {
-			for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
-				if (host->buffer_size > host->buffer_pos) {
-					t_val = buffer[host->buffer_pos++]
-						& 0x00ff;
-					t_val |= ((buffer[host->buffer_pos++])
-						  << 8) & 0xff00;
-					writel(t_val,
-					       sock->addr + SOCK_MMCSD_DATA);
-				}
-			}
-		}
-	}
-	return 0;
-}
-
-static unsigned int tifm_sd_op_flags(struct mmc_command *cmd)
-{
-	unsigned int rc = 0;
-
-	switch (mmc_resp_type(cmd)) {
-	case MMC_RSP_NONE:
-		rc |= TIFM_MMCSD_RSP_R0;
-		break;
-	case MMC_RSP_R1B:
-		rc |= TIFM_MMCSD_RSP_BUSY; // deliberate fall-through
-	case MMC_RSP_R1:
-		rc |= TIFM_MMCSD_RSP_R1;
-		break;
-	case MMC_RSP_R2:
-		rc |= TIFM_MMCSD_RSP_R2;
-		break;
-	case MMC_RSP_R3:
-		rc |= TIFM_MMCSD_RSP_R3;
-		break;
-	default:
-		BUG();
-	}
-
-	switch (mmc_cmd_type(cmd)) {
-	case MMC_CMD_BC:
-		rc |= TIFM_MMCSD_CMD_BC;
-		break;
-	case MMC_CMD_BCR:
-		rc |= TIFM_MMCSD_CMD_BCR;
-		break;
-	case MMC_CMD_AC:
-		rc |= TIFM_MMCSD_CMD_AC;
-		break;
-	case MMC_CMD_ADTC:
-		rc |= TIFM_MMCSD_CMD_ADTC;
-		break;
-	default:
-		BUG();
-	}
-	return rc;
-}
-
-static void tifm_sd_exec(struct tifm_sd *host, struct mmc_command *cmd)
-{
-	struct tifm_dev *sock = host->dev;
-	unsigned int cmd_mask = tifm_sd_op_flags(cmd) |
-				(host->flags & OPENDRAIN);
-
-	if (cmd->data && (cmd->data->flags & MMC_DATA_READ))
-		cmd_mask |= TIFM_MMCSD_READ;
-
-	dev_dbg(&sock->dev, "executing opcode 0x%x, arg: 0x%x, mask: 0x%x\n",
-		cmd->opcode, cmd->arg, cmd_mask);
-
-	writel((cmd->arg >> 16) & 0xffff, sock->addr + SOCK_MMCSD_ARG_HIGH);
-	writel(cmd->arg & 0xffff, sock->addr + SOCK_MMCSD_ARG_LOW);
-	writel(cmd->opcode | cmd_mask, sock->addr + SOCK_MMCSD_COMMAND);
-}
-
-static void tifm_sd_fetch_resp(struct mmc_command *cmd, struct tifm_dev *sock)
-{
-	cmd->resp[0] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x1c) << 16)
-		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x18);
-	cmd->resp[1] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x14) << 16)
-		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x10);
-	cmd->resp[2] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x0c) << 16)
-		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x08);
-	cmd->resp[3] = (readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x04) << 16)
-		       | readl(sock->addr + SOCK_MMCSD_RESPONSE + 0x00);
-}
-
-static void tifm_sd_process_cmd(struct tifm_dev *sock, struct tifm_sd *host,
-				       unsigned int host_status)
-{
-	struct mmc_command *cmd = host->req->cmd;
-
-change_state:
-	switch (host->state) {
-	case IDLE:
-		return;
-	case CMD:
-		if (host_status & (TIFM_MMCSD_EOC | TIFM_MMCSD_CERR)) {
-			tifm_sd_fetch_resp(cmd, sock);
-			if (cmd->data) {
-				host->state = BRS;
-			} else {
-				host->state = READY;
-			}
-			goto change_state;
-		}
-		break;
-	case BRS:
-		if (tifm_sd_transfer_data(sock, host, host_status)) {
-			if (cmd->data->flags & MMC_DATA_WRITE) {
-				host->state = CARD;
-			} else {
-				if (no_dma) {
-					if (host->req->stop) {
-						tifm_sd_exec(host, host->req->stop);
-						host->state = SCMD;
-					} else {
-						host->state = READY;
-					}
-				} else {
-					host->state = FIFO;
-				}
-			}
-			goto change_state;
-		}
-		break;
-	case SCMD:
-		if (host_status & TIFM_MMCSD_EOC) {
-			tifm_sd_fetch_resp(host->req->stop, sock);
-			host->state = READY;
-			goto change_state;
-		}
-		break;
-	case CARD:
-		dev_dbg(&sock->dev, "waiting for CARD, have %zd blocks\n",
-			host->written_blocks);
-		if (!(host->flags & CARD_BUSY)
-		    && (host->written_blocks == cmd->data->blocks)) {
-			if (no_dma) {
-				if (host->req->stop) {
-					tifm_sd_exec(host, host->req->stop);
-					host->state = SCMD;
-				} else {
-					host->state = READY;
-				}
-			} else {
-				host->state = FIFO;
-			}
-			goto change_state;
-		}
-		break;
-	case FIFO:
-		if (host->flags & FIFO_RDY) {
-			host->flags &= ~FIFO_RDY;
-			if (host->req->stop) {
-				tifm_sd_exec(host, host->req->stop);
-				host->state = SCMD;
-			} else {
-				host->state = READY;
-			}
-			goto change_state;
-		}
-		break;
-	case READY:
-		tasklet_schedule(&host->finish_tasklet);
-		return;
-	}
-
-}
-
-/* Called from interrupt handler */
-static void tifm_sd_signal_irq(struct tifm_dev *sock,
-			       unsigned int sock_irq_status)
-{
-	struct tifm_sd *host;
-	unsigned int host_status = 0, fifo_status = 0;
-	int error_code = 0;
-
-	spin_lock(&sock->lock);
-	host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock));
-
-	if (sock_irq_status & FIFO_EVENT) {
-		fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
-		writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS);
-
-		host->flags |= fifo_status & FIFO_RDY;
-	}
-
-	if (sock_irq_status & CARD_EVENT) {
-		host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
-		writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
-
-		if (!host->req)
-			goto done;
-
-		if (host_status & TIFM_MMCSD_ERRMASK) {
-			if (host_status & (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO))
-				error_code = MMC_ERR_TIMEOUT;
-			else if (host_status
-				 & (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC))
-				error_code = MMC_ERR_BADCRC;
-
-			writel(TIFM_FIFO_INT_SETALL,
-			       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
-			writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
-
-			if (host->req->stop) {
-				if (host->state == SCMD) {
-					host->req->stop->error = error_code;
-				} else if (host->state == BRS
-					   || host->state == CARD
-					   || host->state == FIFO) {
-					host->req->cmd->error = error_code;
-					tifm_sd_exec(host, host->req->stop);
-					host->state = SCMD;
-					goto done;
-				} else {
-					host->req->cmd->error = error_code;
-				}
-			} else {
-				host->req->cmd->error = error_code;
-			}
-			host->state = READY;
-		}
-
-		if (host_status & TIFM_MMCSD_CB)
-			host->flags |= CARD_BUSY;
-		if ((host_status & TIFM_MMCSD_EOFB)
-		    && (host->flags & CARD_BUSY)) {
-			host->written_blocks++;
-			host->flags &= ~CARD_BUSY;
-		}
-        }
-
-	if (host->req)
-		tifm_sd_process_cmd(sock, host, host_status);
-done:
-	dev_dbg(&sock->dev, "host_status %x, fifo_status %x\n",
-		host_status, fifo_status);
-	spin_unlock(&sock->lock);
-}
-
-static void tifm_sd_prepare_data(struct tifm_sd *host, struct mmc_command *cmd)
-{
-	struct tifm_dev *sock = host->dev;
-	unsigned int dest_cnt;
-
-	/* DMA style IO */
-	dev_dbg(&sock->dev, "setting dma for %d blocks\n",
-		cmd->data->blocks);
-	writel(TIFM_FIFO_INT_SETALL,
-	       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
-	writel(ilog2(cmd->data->blksz) - 2,
-	       sock->addr + SOCK_FIFO_PAGE_SIZE);
-	writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL);
-	writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
-
-	dest_cnt = (cmd->data->blocks) << 8;
-
-	writel(sg_dma_address(cmd->data->sg), sock->addr + SOCK_DMA_ADDRESS);
-
-	writel(cmd->data->blocks - 1, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
-	writel(cmd->data->blksz - 1, sock->addr + SOCK_MMCSD_BLOCK_LEN);
-
-	if (cmd->data->flags & MMC_DATA_WRITE) {
-		writel(TIFM_MMCSD_TXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-		writel(dest_cnt | TIFM_DMA_TX | TIFM_DMA_EN,
-		       sock->addr + SOCK_DMA_CONTROL);
-	} else {
-		writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-		writel(dest_cnt | TIFM_DMA_EN, sock->addr + SOCK_DMA_CONTROL);
-	}
-}
-
-static void tifm_sd_set_data_timeout(struct tifm_sd *host,
-				     struct mmc_data *data)
-{
-	struct tifm_dev *sock = host->dev;
-	unsigned int data_timeout = data->timeout_clks;
-
-	if (fixed_timeout)
-		return;
-
-	data_timeout += data->timeout_ns /
-			((1000000000UL / host->clk_freq) * host->clk_div);
-
-	if (data_timeout < 0xffff) {
-		writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
-		writel((~TIFM_MMCSD_DPE)
-		       & readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
-		       sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
-	} else {
-		data_timeout = (data_timeout >> 10) + 1;
-		if (data_timeout > 0xffff)
-			data_timeout = 0;	/* set to unlimited */
-		writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
-		writel(TIFM_MMCSD_DPE
-		       | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
-		       sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
-	}
-}
-
-static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-	struct tifm_sd *host = mmc_priv(mmc);
-	struct tifm_dev *sock = host->dev;
-	unsigned long flags;
-	int sg_count = 0;
-	struct mmc_data *r_data = mrq->cmd->data;
-
-	spin_lock_irqsave(&sock->lock, flags);
-	if (host->flags & EJECT) {
-		spin_unlock_irqrestore(&sock->lock, flags);
-		goto err_out;
-	}
-
-	if (host->req) {
-		printk(KERN_ERR DRIVER_NAME ": unfinished request detected\n");
-		spin_unlock_irqrestore(&sock->lock, flags);
-		goto err_out;
-	}
-
-	if (r_data) {
-		tifm_sd_set_data_timeout(host, r_data);
-
-		sg_count = tifm_map_sg(sock, r_data->sg, r_data->sg_len,
-				       mrq->cmd->flags & MMC_DATA_WRITE
-				       ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-		if (sg_count != 1) {
-			printk(KERN_ERR DRIVER_NAME
-				": scatterlist map failed\n");
-			spin_unlock_irqrestore(&sock->lock, flags);
-			goto err_out;
-		}
-
-		host->written_blocks = 0;
-		host->flags &= ~CARD_BUSY;
-		tifm_sd_prepare_data(host, mrq->cmd);
-	}
-
-	host->req = mrq;
-	mod_timer(&host->timer, jiffies + host->timeout_jiffies);
-	host->state = CMD;
-	writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
-	       sock->addr + SOCK_CONTROL);
-	tifm_sd_exec(host, mrq->cmd);
-	spin_unlock_irqrestore(&sock->lock, flags);
-	return;
-
-err_out:
-	if (sg_count > 0)
-		tifm_unmap_sg(sock, r_data->sg, r_data->sg_len,
-			      (r_data->flags & MMC_DATA_WRITE)
-			      ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-
-	mrq->cmd->error = MMC_ERR_TIMEOUT;
-	mmc_request_done(mmc, mrq);
-}
-
-static void tifm_sd_end_cmd(unsigned long data)
-{
-	struct tifm_sd *host = (struct tifm_sd*)data;
-	struct tifm_dev *sock = host->dev;
-	struct mmc_host *mmc = tifm_get_drvdata(sock);
-	struct mmc_request *mrq;
-	struct mmc_data *r_data = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sock->lock, flags);
-
-	del_timer(&host->timer);
-	mrq = host->req;
-	host->req = NULL;
-	host->state = IDLE;
-
-	if (!mrq) {
-		printk(KERN_ERR DRIVER_NAME ": no request to complete?\n");
-		spin_unlock_irqrestore(&sock->lock, flags);
-		return;
-	}
-
-	r_data = mrq->cmd->data;
-	if (r_data) {
-		if (r_data->flags & MMC_DATA_WRITE) {
-			r_data->bytes_xfered = host->written_blocks
-					       * r_data->blksz;
-		} else {
-			r_data->bytes_xfered = r_data->blocks -
-				readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1;
-			r_data->bytes_xfered *= r_data->blksz;
-			r_data->bytes_xfered += r_data->blksz -
-				readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
-		}
-		tifm_unmap_sg(sock, r_data->sg, r_data->sg_len,
-			      (r_data->flags & MMC_DATA_WRITE)
-			      ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
-	}
-
-	writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
-	       sock->addr + SOCK_CONTROL);
-
-	spin_unlock_irqrestore(&sock->lock, flags);
-	mmc_request_done(mmc, mrq);
-}
-
-static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-	struct tifm_sd *host = mmc_priv(mmc);
-	struct tifm_dev *sock = host->dev;
-	unsigned long flags;
-	struct mmc_data *r_data = mrq->cmd->data;
-
-	spin_lock_irqsave(&sock->lock, flags);
-	if (host->flags & EJECT) {
-		spin_unlock_irqrestore(&sock->lock, flags);
-		goto err_out;
-	}
-
-	if (host->req) {
-		printk(KERN_ERR DRIVER_NAME ": unfinished request detected\n");
-		spin_unlock_irqrestore(&sock->lock, flags);
-		goto err_out;
-	}
-
-	if (r_data) {
-		tifm_sd_set_data_timeout(host, r_data);
-
-		host->buffer_size = mrq->cmd->data->blocks
-				    * mrq->cmd->data->blksz;
-
-		writel(TIFM_MMCSD_BUFINT
-		       | readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
-		       sock->addr + SOCK_MMCSD_INT_ENABLE);
-		writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8)
-		       | (TIFM_MMCSD_FIFO_SIZE - 1),
-		       sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-
-		host->written_blocks = 0;
-		host->flags &= ~CARD_BUSY;
-		host->buffer_pos = 0;
-		writel(r_data->blocks - 1, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
-		writel(r_data->blksz - 1, sock->addr + SOCK_MMCSD_BLOCK_LEN);
-	}
-
-	host->req = mrq;
-	mod_timer(&host->timer, jiffies + host->timeout_jiffies);
-	host->state = CMD;
-	writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
-	       sock->addr + SOCK_CONTROL);
-	tifm_sd_exec(host, mrq->cmd);
-	spin_unlock_irqrestore(&sock->lock, flags);
-	return;
-
-err_out:
-	mrq->cmd->error = MMC_ERR_TIMEOUT;
-	mmc_request_done(mmc, mrq);
-}
-
-static void tifm_sd_end_cmd_nodma(unsigned long data)
-{
-	struct tifm_sd *host = (struct tifm_sd*)data;
-	struct tifm_dev *sock = host->dev;
-	struct mmc_host *mmc = tifm_get_drvdata(sock);
-	struct mmc_request *mrq;
-	struct mmc_data *r_data = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sock->lock, flags);
-
-	del_timer(&host->timer);
-	mrq = host->req;
-	host->req = NULL;
-	host->state = IDLE;
-
-	if (!mrq) {
-		printk(KERN_ERR DRIVER_NAME ": no request to complete?\n");
-		spin_unlock_irqrestore(&sock->lock, flags);
-		return;
-	}
-
-	r_data = mrq->cmd->data;
-	if (r_data) {
-		writel((~TIFM_MMCSD_BUFINT) &
-			readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
-			sock->addr + SOCK_MMCSD_INT_ENABLE);
-
-		if (r_data->flags & MMC_DATA_WRITE) {
-			r_data->bytes_xfered = host->written_blocks
-					       * r_data->blksz;
-		} else {
-			r_data->bytes_xfered = r_data->blocks -
-				readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1;
-			r_data->bytes_xfered *= r_data->blksz;
-			r_data->bytes_xfered += r_data->blksz -
-				readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
-		}
-		host->buffer_pos = 0;
-		host->buffer_size = 0;
-	}
-
-	writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
-	       sock->addr + SOCK_CONTROL);
-
-	spin_unlock_irqrestore(&sock->lock, flags);
-
-	mmc_request_done(mmc, mrq);
-}
-
-static void tifm_sd_terminate(struct tifm_sd *host)
-{
-	struct tifm_dev *sock = host->dev;
-	unsigned long flags;
-
-	writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
-	mmiowb();
-	spin_lock_irqsave(&sock->lock, flags);
-	host->flags |= EJECT;
-	if (host->req) {
-		writel(TIFM_FIFO_INT_SETALL,
-		       sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
-		writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
-		tasklet_schedule(&host->finish_tasklet);
-	}
-	spin_unlock_irqrestore(&sock->lock, flags);
-}
-
-static void tifm_sd_abort(unsigned long data)
-{
-	struct tifm_sd *host = (struct tifm_sd*)data;
-
-	printk(KERN_ERR DRIVER_NAME
-	       ": card failed to respond for a long period of time");
-
-	tifm_sd_terminate(host);
-	tifm_eject(host->dev);
-}
-
-static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-	struct tifm_sd *host = mmc_priv(mmc);
-	struct tifm_dev *sock = host->dev;
-	unsigned int clk_div1, clk_div2;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sock->lock, flags);
-
-	dev_dbg(&sock->dev, "Setting bus width %d, power %d\n", ios->bus_width,
-		ios->power_mode);
-	if (ios->bus_width == MMC_BUS_WIDTH_4) {
-		writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG),
-		       sock->addr + SOCK_MMCSD_CONFIG);
-	} else {
-		writel((~TIFM_MMCSD_4BBUS)
-		       & readl(sock->addr + SOCK_MMCSD_CONFIG),
-		       sock->addr + SOCK_MMCSD_CONFIG);
-	}
-
-	if (ios->clock) {
-		clk_div1 = 20000000 / ios->clock;
-		if (!clk_div1)
-			clk_div1 = 1;
-
-		clk_div2 = 24000000 / ios->clock;
-		if (!clk_div2)
-			clk_div2 = 1;
-
-		if ((20000000 / clk_div1) > ios->clock)
-			clk_div1++;
-		if ((24000000 / clk_div2) > ios->clock)
-			clk_div2++;
-		if ((20000000 / clk_div1) > (24000000 / clk_div2)) {
-			host->clk_freq = 20000000;
-			host->clk_div = clk_div1;
-			writel((~TIFM_CTRL_FAST_CLK)
-			       & readl(sock->addr + SOCK_CONTROL),
-			       sock->addr + SOCK_CONTROL);
-		} else {
-			host->clk_freq = 24000000;
-			host->clk_div = clk_div2;
-			writel(TIFM_CTRL_FAST_CLK
-			       | readl(sock->addr + SOCK_CONTROL),
-			       sock->addr + SOCK_CONTROL);
-		}
-	} else {
-		host->clk_div = 0;
-	}
-	host->clk_div &= TIFM_MMCSD_CLKMASK;
-	writel(host->clk_div
-	       | ((~TIFM_MMCSD_CLKMASK)
-		  & readl(sock->addr + SOCK_MMCSD_CONFIG)),
-	       sock->addr + SOCK_MMCSD_CONFIG);
-
-	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
-		host->flags |= OPENDRAIN;
-	else
-		host->flags &= ~OPENDRAIN;
-
-	/* chip_select : maybe later */
-	//vdd
-	//power is set before probe / after remove
-	//I believe, power_off when already marked for eject is sufficient to
-	// allow removal.
-	if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) {
-		host->flags |= EJECT_DONE;
-		wake_up_all(&host->notify);
-	}
-
-	spin_unlock_irqrestore(&sock->lock, flags);
-}
-
-static int tifm_sd_ro(struct mmc_host *mmc)
-{
-	int rc;
-	struct tifm_sd *host = mmc_priv(mmc);
-	struct tifm_dev *sock = host->dev;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sock->lock, flags);
-
-	host->flags |= (CARD_RO & readl(sock->addr + SOCK_PRESENT_STATE));
-	rc = (host->flags & CARD_RO) ? 1 : 0;
-
-	spin_unlock_irqrestore(&sock->lock, flags);
-	return rc;
-}
-
-static struct mmc_host_ops tifm_sd_ops = {
-	.request = tifm_sd_request,
-	.set_ios = tifm_sd_ios,
-	.get_ro  = tifm_sd_ro
-};
-
-static int tifm_sd_initialize_host(struct tifm_sd *host)
-{
-	int rc;
-	unsigned int host_status = 0;
-	struct tifm_dev *sock = host->dev;
-
-	writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
-	mmiowb();
-	host->clk_div = 61;
-	host->clk_freq = 20000000;
-	writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL);
-	writel(host->clk_div | TIFM_MMCSD_POWER,
-	       sock->addr + SOCK_MMCSD_CONFIG);
-
-	/* wait up to 0.51 sec for reset */
-	for (rc = 2; rc <= 256; rc <<= 1) {
-		if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) {
-			rc = 0;
-			break;
-		}
-		msleep(rc);
-	}
-
-	if (rc) {
-		printk(KERN_ERR DRIVER_NAME
-		       ": controller failed to reset\n");
-		return -ENODEV;
-	}
-
-	writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
-	writel(host->clk_div | TIFM_MMCSD_POWER,
-	       sock->addr + SOCK_MMCSD_CONFIG);
-	writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-
-	// command timeout fixed to 64 clocks for now
-	writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO);
-	writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND);
-
-	/* INAB should take much less than reset */
-	for (rc = 1; rc <= 16; rc <<= 1) {
-		host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
-		writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
-		if (!(host_status & TIFM_MMCSD_ERRMASK)
-		    && (host_status & TIFM_MMCSD_EOC)) {
-			rc = 0;
-			break;
-		}
-		msleep(rc);
-	}
-
-	if (rc) {
-		printk(KERN_ERR DRIVER_NAME
-		       ": card not ready - probe failed on initialization\n");
-		return -ENODEV;
-	}
-
-	writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK,
-	       sock->addr + SOCK_MMCSD_INT_ENABLE);
-	mmiowb();
-
-	return 0;
-}
-
-static int tifm_sd_probe(struct tifm_dev *sock)
-{
-	struct mmc_host *mmc;
-	struct tifm_sd *host;
-	int rc = -EIO;
-
-	if (!(TIFM_SOCK_STATE_OCCUPIED
-	      & readl(sock->addr + SOCK_PRESENT_STATE))) {
-		printk(KERN_WARNING DRIVER_NAME ": card gone, unexpectedly\n");
-		return rc;
-	}
-
-	mmc = mmc_alloc_host(sizeof(struct tifm_sd), &sock->dev);
-	if (!mmc)
-		return -ENOMEM;
-
-	host = mmc_priv(mmc);
-	tifm_set_drvdata(sock, mmc);
-	host->dev = sock;
-	host->timeout_jiffies = msecs_to_jiffies(1000);
-
-	init_waitqueue_head(&host->notify);
-	tasklet_init(&host->finish_tasklet,
-		     no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd,
-		     (unsigned long)host);
-	setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host);
-
-	tifm_sd_ops.request = no_dma ? tifm_sd_request_nodma : tifm_sd_request;
-	mmc->ops = &tifm_sd_ops;
-	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-	mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
-	mmc->f_min = 20000000 / 60;
-	mmc->f_max = 24000000;
-	mmc->max_hw_segs = 1;
-	mmc->max_phys_segs = 1;
-	// limited by DMA counter - it's safer to stick with
-	// block counter has 11 bits though
-	mmc->max_blk_count = 256;
-	// 2k maximum hw block length
-	mmc->max_blk_size = 2048;
-	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-	mmc->max_seg_size = mmc->max_req_size;
-	sock->signal_irq = tifm_sd_signal_irq;
-	rc = tifm_sd_initialize_host(host);
-
-	if (!rc)
-		rc = mmc_add_host(mmc);
-	if (rc)
-		goto out_free_mmc;
-
-	return 0;
-out_free_mmc:
-	mmc_free_host(mmc);
-	return rc;
-}
-
-static void tifm_sd_remove(struct tifm_dev *sock)
-{
-	struct mmc_host *mmc = tifm_get_drvdata(sock);
-	struct tifm_sd *host = mmc_priv(mmc);
-
-	del_timer_sync(&host->timer);
-	tifm_sd_terminate(host);
-	wait_event_timeout(host->notify, host->flags & EJECT_DONE,
-			   host->timeout_jiffies);
-	tasklet_kill(&host->finish_tasklet);
-	mmc_remove_host(mmc);
-
-	/* The meaning of the bit majority in this constant is unknown. */
-	writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
-	       sock->addr + SOCK_CONTROL);
-
-	tifm_set_drvdata(sock, NULL);
-	mmc_free_host(mmc);
-}
-
-#ifdef CONFIG_PM
-
-static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state)
-{
-	struct mmc_host *mmc = tifm_get_drvdata(sock);
-	int rc;
-
-	rc = mmc_suspend_host(mmc, state);
-	/* The meaning of the bit majority in this constant is unknown. */
-	writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
-	       sock->addr + SOCK_CONTROL);
-	return rc;
-}
-
-static int tifm_sd_resume(struct tifm_dev *sock)
-{
-	struct mmc_host *mmc = tifm_get_drvdata(sock);
-	struct tifm_sd *host = mmc_priv(mmc);
-
-	if (sock->media_id != FM_SD
-	    || tifm_sd_initialize_host(host)) {
-		tifm_eject(sock);
-		return 0;
-	} else {
-		return mmc_resume_host(mmc);
-	}
-}
-
-#else
-
-#define tifm_sd_suspend NULL
-#define tifm_sd_resume NULL
-
-#endif /* CONFIG_PM */
-
-static tifm_media_id tifm_sd_id_tbl[] = {
-	FM_SD, 0
-};
-
-static struct tifm_driver tifm_sd_driver = {
-	.driver = {
-		.name  = DRIVER_NAME,
-		.owner = THIS_MODULE
-	},
-	.id_table = tifm_sd_id_tbl,
-	.probe    = tifm_sd_probe,
-	.remove   = tifm_sd_remove,
-	.suspend  = tifm_sd_suspend,
-	.resume   = tifm_sd_resume
-};
-
-static int __init tifm_sd_init(void)
-{
-	return tifm_register_driver(&tifm_sd_driver);
-}
-
-static void __exit tifm_sd_exit(void)
-{
-	tifm_unregister_driver(&tifm_sd_driver);
-}
-
-MODULE_AUTHOR("Alex Dubov");
-MODULE_DESCRIPTION("TI FlashMedia SD driver");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(tifm, tifm_sd_id_tbl);
-MODULE_VERSION(DRIVER_VERSION);
-
-module_init(tifm_sd_init);
-module_exit(tifm_sd_exit);
diff --git a/include/asm-arm/arch-imx/mmc.h b/include/asm-arm/arch-imx/mmc.h
index 1937151..84c7269 100644
--- a/include/asm-arm/arch-imx/mmc.h
+++ b/include/asm-arm/arch-imx/mmc.h
@@ -1,7 +1,7 @@
 #ifndef ASMARM_ARCH_MMC_H
 #define ASMARM_ARCH_MMC_H
 
-#include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 
 struct imxmmc_platform_data {
 	int (*card_present)(void);
diff --git a/include/asm-arm/arch-pxa/mmc.h b/include/asm-arm/arch-pxa/mmc.h
index a38a28c..ef4f570 100644
--- a/include/asm-arm/arch-pxa/mmc.h
+++ b/include/asm-arm/arch-pxa/mmc.h
@@ -1,7 +1,7 @@
 #ifndef ASMARM_ARCH_MMC_H
 #define ASMARM_ARCH_MMC_H
 
-#include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 #include <linux/interrupt.h>
 
 struct device;
diff --git a/include/asm-arm/mach/mmc.h b/include/asm-arm/mach/mmc.h
index 1b3555d..eb91145 100644
--- a/include/asm-arm/mach/mmc.h
+++ b/include/asm-arm/mach/mmc.h
@@ -4,7 +4,7 @@
 #ifndef ASMARM_MACH_MMC_H
 #define ASMARM_MACH_MMC_H
 
-#include <linux/mmc/protocol.h>
+#include <linux/mmc/host.h>
 
 struct mmc_platform_data {
 	unsigned int ocr_mask;			/* available voltages */
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index e45712ac..badf702 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -10,7 +10,7 @@
 #ifndef LINUX_MMC_CARD_H
 #define LINUX_MMC_CARD_H
 
-#include <linux/mmc/mmc.h>
+#include <linux/mmc/core.h>
 
 struct mmc_cid {
 	unsigned int		manfid;
@@ -41,6 +41,7 @@
 
 struct mmc_ext_csd {
 	unsigned int		hs_max_dtr;
+	unsigned int		sectors;
 };
 
 struct sd_scr {
@@ -60,18 +61,17 @@
  * MMC device
  */
 struct mmc_card {
-	struct list_head	node;		/* node in hosts devices list */
 	struct mmc_host		*host;		/* the host this device belongs to */
 	struct device		dev;		/* the device */
 	unsigned int		rca;		/* relative card address of device */
+	unsigned int		type;		/* card type */
+#define MMC_TYPE_MMC		0		/* MMC card */
+#define MMC_TYPE_SD		1		/* SD card */
 	unsigned int		state;		/* (our) card state */
 #define MMC_STATE_PRESENT	(1<<0)		/* present in sysfs */
-#define MMC_STATE_DEAD		(1<<1)		/* device no longer in stack */
-#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 */
-#define MMC_STATE_BLOCKADDR	(1<<6)		/* card uses block-addressing */
+#define MMC_STATE_READONLY	(1<<1)		/* card is read-only */
+#define MMC_STATE_HIGHSPEED	(1<<2)		/* card is in high speed mode */
+#define MMC_STATE_BLOCKADDR	(1<<3)		/* card uses block-addressing */
 	u32			raw_cid[4];	/* raw card CID */
 	u32			raw_csd[4];	/* raw card CSD */
 	u32			raw_scr[2];	/* raw card SCR */
@@ -82,18 +82,15 @@
 	struct sd_switch_caps	sw_caps;	/* switch (CMD6) caps */
 };
 
+#define mmc_card_mmc(c)		((c)->type == MMC_TYPE_MMC)
+#define mmc_card_sd(c)		((c)->type == MMC_TYPE_SD)
+
 #define mmc_card_present(c)	((c)->state & MMC_STATE_PRESENT)
-#define mmc_card_dead(c)	((c)->state & MMC_STATE_DEAD)
-#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_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
 
 #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_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
@@ -119,11 +116,4 @@
 extern int mmc_register_driver(struct mmc_driver *);
 extern void mmc_unregister_driver(struct mmc_driver *);
 
-static inline int mmc_card_claim_host(struct mmc_card *card)
-{
-	return __mmc_claim_host(card->host, card);
-}
-
-#define mmc_card_release_host(c)	mmc_release_host((c)->host)
-
 #endif
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
new file mode 100644
index 0000000..04bbe12f
--- /dev/null
+++ b/include/linux/mmc/core.h
@@ -0,0 +1,112 @@
+/*
+ *  linux/include/linux/mmc/core.h
+ *
+ * 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
+ * published by the Free Software Foundation.
+ */
+#ifndef LINUX_MMC_CORE_H
+#define LINUX_MMC_CORE_H
+
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+struct request;
+struct mmc_data;
+struct mmc_request;
+
+struct mmc_command {
+	u32			opcode;
+	u32			arg;
+	u32			resp[4];
+	unsigned int		flags;		/* expected response type */
+#define MMC_RSP_PRESENT	(1 << 0)
+#define MMC_RSP_136	(1 << 1)		/* 136 bit response */
+#define MMC_RSP_CRC	(1 << 2)		/* expect valid crc */
+#define MMC_RSP_BUSY	(1 << 3)		/* card may send busy */
+#define MMC_RSP_OPCODE	(1 << 4)		/* response contains opcode */
+#define MMC_CMD_MASK	(3 << 5)		/* command type */
+#define MMC_CMD_AC	(0 << 5)
+#define MMC_CMD_ADTC	(1 << 5)
+#define MMC_CMD_BC	(2 << 5)
+#define MMC_CMD_BCR	(3 << 5)
+
+/*
+ * These are the response types, and correspond to valid bit
+ * patterns of the above flags.  One additional valid pattern
+ * is all zeros, which means we don't expect a response.
+ */
+#define MMC_RSP_NONE	(0)
+#define MMC_RSP_R1	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R1B	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
+#define MMC_RSP_R2	(MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
+#define MMC_RSP_R3	(MMC_RSP_PRESENT)
+#define MMC_RSP_R6	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R7	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+
+#define mmc_resp_type(cmd)	((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
+
+/*
+ * These are the command types.
+ */
+#define mmc_cmd_type(cmd)	((cmd)->flags & MMC_CMD_MASK)
+
+	unsigned int		retries;	/* max number of retries */
+	unsigned int		error;		/* command error */
+
+#define MMC_ERR_NONE	0
+#define MMC_ERR_TIMEOUT	1
+#define MMC_ERR_BADCRC	2
+#define MMC_ERR_FIFO	3
+#define MMC_ERR_FAILED	4
+#define MMC_ERR_INVALID	5
+
+	struct mmc_data		*data;		/* data segment associated with cmd */
+	struct mmc_request	*mrq;		/* associated request */
+};
+
+struct mmc_data {
+	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
+	unsigned int		timeout_clks;	/* data timeout (in clocks) */
+	unsigned int		blksz;		/* data block size */
+	unsigned int		blocks;		/* number of blocks */
+	unsigned int		error;		/* data error */
+	unsigned int		flags;
+
+#define MMC_DATA_WRITE	(1 << 8)
+#define MMC_DATA_READ	(1 << 9)
+#define MMC_DATA_STREAM	(1 << 10)
+#define MMC_DATA_MULTI	(1 << 11)
+
+	unsigned int		bytes_xfered;
+
+	struct mmc_command	*stop;		/* stop command */
+	struct mmc_request	*mrq;		/* associated request */
+
+	unsigned int		sg_len;		/* size of scatter list */
+	struct scatterlist	*sg;		/* I/O scatter list */
+};
+
+struct mmc_request {
+	struct mmc_command	*cmd;
+	struct mmc_data		*data;
+	struct mmc_command	*stop;
+
+	void			*done_data;	/* completion data */
+	void			(*done)(struct mmc_request *);/* completion function */
+};
+
+struct mmc_host;
+struct mmc_card;
+
+extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
+extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
+extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
+	struct mmc_command *, int);
+
+extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *, int);
+
+extern void mmc_claim_host(struct mmc_host *host);
+extern void mmc_release_host(struct mmc_host *host);
+
+#endif
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index bfcef8a..b1350df 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -10,36 +10,13 @@
 #ifndef LINUX_MMC_HOST_H
 #define LINUX_MMC_HOST_H
 
-#include <linux/mmc/mmc.h>
+#include <linux/mmc/core.h>
 
 struct mmc_ios {
 	unsigned int	clock;			/* clock rate */
 	unsigned short	vdd;
 
-#define	MMC_VDD_150	0
-#define	MMC_VDD_155	1
-#define	MMC_VDD_160	2
-#define	MMC_VDD_165	3
-#define	MMC_VDD_170	4
-#define	MMC_VDD_180	5
-#define	MMC_VDD_190	6
-#define	MMC_VDD_200	7
-#define	MMC_VDD_210	8
-#define	MMC_VDD_220	9
-#define	MMC_VDD_230	10
-#define	MMC_VDD_240	11
-#define	MMC_VDD_250	12
-#define	MMC_VDD_260	13
-#define	MMC_VDD_270	14
-#define	MMC_VDD_280	15
-#define	MMC_VDD_290	16
-#define	MMC_VDD_300	17
-#define	MMC_VDD_310	18
-#define	MMC_VDD_320	19
-#define	MMC_VDD_330	20
-#define	MMC_VDD_340	21
-#define	MMC_VDD_350	22
-#define	MMC_VDD_360	23
+/* vdd stores the bit number of the selected voltage range from below. */
 
 	unsigned char	bus_mode;		/* command output mode */
 
@@ -88,6 +65,24 @@
 	unsigned int		f_max;
 	u32			ocr_avail;
 
+#define MMC_VDD_165_195		0x00000080	/* VDD voltage 1.65 - 1.95 */
+#define MMC_VDD_20_21		0x00000100	/* VDD voltage 2.0 ~ 2.1 */
+#define MMC_VDD_21_22		0x00000200	/* VDD voltage 2.1 ~ 2.2 */
+#define MMC_VDD_22_23		0x00000400	/* VDD voltage 2.2 ~ 2.3 */
+#define MMC_VDD_23_24		0x00000800	/* VDD voltage 2.3 ~ 2.4 */
+#define MMC_VDD_24_25		0x00001000	/* VDD voltage 2.4 ~ 2.5 */
+#define MMC_VDD_25_26		0x00002000	/* VDD voltage 2.5 ~ 2.6 */
+#define MMC_VDD_26_27		0x00004000	/* VDD voltage 2.6 ~ 2.7 */
+#define MMC_VDD_27_28		0x00008000	/* VDD voltage 2.7 ~ 2.8 */
+#define MMC_VDD_28_29		0x00010000	/* VDD voltage 2.8 ~ 2.9 */
+#define MMC_VDD_29_30		0x00020000	/* VDD voltage 2.9 ~ 3.0 */
+#define MMC_VDD_30_31		0x00040000	/* VDD voltage 3.0 ~ 3.1 */
+#define MMC_VDD_31_32		0x00080000	/* VDD voltage 3.1 ~ 3.2 */
+#define MMC_VDD_32_33		0x00100000	/* VDD voltage 3.2 ~ 3.3 */
+#define MMC_VDD_33_34		0x00200000	/* VDD voltage 3.3 ~ 3.4 */
+#define MMC_VDD_34_35		0x00400000	/* VDD voltage 3.4 ~ 3.5 */
+#define MMC_VDD_35_36		0x00800000	/* VDD voltage 3.5 ~ 3.6 */
+
 	unsigned long		caps;		/* Host capabilities */
 
 #define MMC_CAP_4_BIT_DATA	(1 << 0)	/* Can the host do 4 bit transfers */
@@ -106,6 +101,8 @@
 	unsigned int		max_blk_count;	/* maximum number of blocks in one req */
 
 	/* private data */
+	spinlock_t		lock;		/* lock for claim and bus ops */
+
 	struct mmc_ios		ios;		/* current io bus settings */
 	u32			ocr;		/* the current OCR setting */
 
@@ -113,15 +110,19 @@
 #define MMC_MODE_MMC		0
 #define MMC_MODE_SD		1
 
-	struct list_head	cards;		/* devices attached to this host */
+	struct mmc_card		*card;		/* device attached to this host */
 
 	wait_queue_head_t	wq;
-	spinlock_t		lock;		/* claimed lock */
 	unsigned int		claimed:1;	/* host exclusively claimed */
 
-	struct mmc_card		*card_selected;	/* the selected MMC card */
-
 	struct delayed_work	detect;
+#ifdef CONFIG_MMC_DEBUG
+	unsigned int		removed:1;	/* host is being removed */
+#endif
+
+	const struct mmc_bus_ops *bus_ops;	/* current bus driver */
+	unsigned int		bus_refs;	/* reference counter */
+	unsigned int		bus_dead:1;	/* bus has been released */
 
 	unsigned long		private[0] ____cacheline_aligned;
 };
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index cdc54be..e3ed9b9 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -1,119 +1,257 @@
 /*
- *  linux/include/linux/mmc/mmc.h
+ * Header for MultiMediaCard (MMC)
  *
- * 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
- * published by the Free Software Foundation.
+ * Copyright 2002 Hewlett-Packard Company
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * Many thanks to Alessandro Rubini and Jonathan Corbet!
+ *
+ * Based strongly on code by:
+ *
+ * Author: Yong-iL Joh <tolkien@mizi.com>
+ * Date  : $Date: 2002/06/18 12:37:30 $
+ *
+ * Author:  Andrew Christian
+ *          15 May 2002
  */
-#ifndef MMC_H
-#define MMC_H
 
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
+#ifndef MMC_MMC_H
+#define MMC_MMC_H
 
-struct request;
-struct mmc_data;
-struct mmc_request;
+/* 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  */
+#define MMC_STOP_TRANSMISSION    12   /* ac                      R1b */
+#define MMC_SEND_STATUS	         13   /* ac   [31:16] RCA        R1  */
+#define MMC_GO_INACTIVE_STATE    15   /* ac   [31:16] RCA            */
 
-struct mmc_command {
-	u32			opcode;
-	u32			arg;
-	u32			resp[4];
-	unsigned int		flags;		/* expected response type */
-#define MMC_RSP_PRESENT	(1 << 0)
-#define MMC_RSP_136	(1 << 1)		/* 136 bit response */
-#define MMC_RSP_CRC	(1 << 2)		/* expect valid crc */
-#define MMC_RSP_BUSY	(1 << 3)		/* card may send busy */
-#define MMC_RSP_OPCODE	(1 << 4)		/* response contains opcode */
-#define MMC_CMD_MASK	(3 << 5)		/* command type */
-#define MMC_CMD_AC	(0 << 5)
-#define MMC_CMD_ADTC	(1 << 5)
-#define MMC_CMD_BC	(2 << 5)
-#define MMC_CMD_BCR	(3 << 5)
+  /* class 2 */
+#define MMC_SET_BLOCKLEN         16   /* ac   [31:0] block len   R1  */
+#define MMC_READ_SINGLE_BLOCK    17   /* adtc [31:0] data addr   R1  */
+#define MMC_READ_MULTIPLE_BLOCK  18   /* adtc [31:0] data addr   R1  */
+
+  /* class 3 */
+#define MMC_WRITE_DAT_UNTIL_STOP 20   /* adtc [31:0] data addr   R1  */
+
+  /* class 4 */
+#define MMC_SET_BLOCK_COUNT      23   /* adtc [31:0] data addr   R1  */
+#define MMC_WRITE_BLOCK          24   /* adtc [31:0] data addr   R1  */
+#define MMC_WRITE_MULTIPLE_BLOCK 25   /* adtc                    R1  */
+#define MMC_PROGRAM_CID          26   /* adtc                    R1  */
+#define MMC_PROGRAM_CSD          27   /* adtc                    R1  */
+
+  /* class 6 */
+#define MMC_SET_WRITE_PROT       28   /* ac   [31:0] data addr   R1b */
+#define MMC_CLR_WRITE_PROT       29   /* ac   [31:0] data addr   R1b */
+#define MMC_SEND_WRITE_PROT      30   /* adtc [31:0] wpdata addr R1  */
+
+  /* class 5 */
+#define MMC_ERASE_GROUP_START    35   /* ac   [31:0] data addr   R1  */
+#define MMC_ERASE_GROUP_END      36   /* ac   [31:0] data addr   R1  */
+#define MMC_ERASE                38   /* ac                      R1b */
+
+  /* class 9 */
+#define MMC_FAST_IO              39   /* ac   <Complex>          R4  */
+#define MMC_GO_IRQ_STATE         40   /* bcr                     R5  */
+
+  /* class 7 */
+#define MMC_LOCK_UNLOCK          42   /* adtc                    R1b */
+
+  /* class 8 */
+#define MMC_APP_CMD              55   /* ac   [31:16] RCA        R1  */
+#define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
 
 /*
- * These are the response types, and correspond to valid bit
- * patterns of the above flags.  One additional valid pattern
- * is all zeros, which means we don't expect a response.
+ * 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
  */
-#define MMC_RSP_NONE	(0)
-#define MMC_RSP_R1	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-#define MMC_RSP_R1B	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
-#define MMC_RSP_R2	(MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
-#define MMC_RSP_R3	(MMC_RSP_PRESENT)
-#define MMC_RSP_R6	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-#define MMC_RSP_R7	(MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-
-#define mmc_resp_type(cmd)	((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
 
 /*
- * These are the command types.
+  MMC status in R1
+  Type
+  	e : error bit
+	s : status bit
+	r : detected and set for the actual command response
+	x : detected and set during command execution. the host must poll
+            the card by sending status command in order to read these bits.
+  Clear condition
+  	a : according to the card state
+	b : always related to the previous command. Reception of
+            a valid command will clear it (with a delay of one command)
+	c : clear by read
  */
-#define mmc_cmd_type(cmd)	((cmd)->flags & MMC_CMD_MASK)
 
-	unsigned int		retries;	/* max number of retries */
-	unsigned int		error;		/* command error */
+#define R1_OUT_OF_RANGE		(1 << 31)	/* er, c */
+#define R1_ADDRESS_ERROR	(1 << 30)	/* erx, c */
+#define R1_BLOCK_LEN_ERROR	(1 << 29)	/* er, c */
+#define R1_ERASE_SEQ_ERROR      (1 << 28)	/* er, c */
+#define R1_ERASE_PARAM		(1 << 27)	/* ex, c */
+#define R1_WP_VIOLATION		(1 << 26)	/* erx, c */
+#define R1_CARD_IS_LOCKED	(1 << 25)	/* sx, a */
+#define R1_LOCK_UNLOCK_FAILED	(1 << 24)	/* erx, c */
+#define R1_COM_CRC_ERROR	(1 << 23)	/* er, b */
+#define R1_ILLEGAL_COMMAND	(1 << 22)	/* er, b */
+#define R1_CARD_ECC_FAILED	(1 << 21)	/* ex, c */
+#define R1_CC_ERROR		(1 << 20)	/* erx, c */
+#define R1_ERROR		(1 << 19)	/* erx, c */
+#define R1_UNDERRUN		(1 << 18)	/* ex, c */
+#define R1_OVERRUN		(1 << 17)	/* ex, c */
+#define R1_CID_CSD_OVERWRITE	(1 << 16)	/* erx, c, CID/CSD overwrite */
+#define R1_WP_ERASE_SKIP	(1 << 15)	/* sx, c */
+#define R1_CARD_ECC_DISABLED	(1 << 14)	/* sx, a */
+#define R1_ERASE_RESET		(1 << 13)	/* sr, c */
+#define R1_STATUS(x)            (x & 0xFFFFE000)
+#define R1_CURRENT_STATE(x)    	((x & 0x00001E00) >> 9)	/* sx, b (4 bits) */
+#define R1_READY_FOR_DATA	(1 << 8)	/* sx, a */
+#define R1_APP_CMD		(1 << 5)	/* sr, c */
 
-#define MMC_ERR_NONE	0
-#define MMC_ERR_TIMEOUT	1
-#define MMC_ERR_BADCRC	2
-#define MMC_ERR_FIFO	3
-#define MMC_ERR_FAILED	4
-#define MMC_ERR_INVALID	5
+/* These are unpacked versions of the actual responses */
 
-	struct mmc_data		*data;		/* data segment associated with cmd */
-	struct mmc_request	*mrq;		/* associated request */
+struct _mmc_csd {
+	u8  csd_structure;
+	u8  spec_vers;
+	u8  taac;
+	u8  nsac;
+	u8  tran_speed;
+	u16 ccc;
+	u8  read_bl_len;
+	u8  read_bl_partial;
+	u8  write_blk_misalign;
+	u8  read_blk_misalign;
+	u8  dsr_imp;
+	u16 c_size;
+	u8  vdd_r_curr_min;
+	u8  vdd_r_curr_max;
+	u8  vdd_w_curr_min;
+	u8  vdd_w_curr_max;
+	u8  c_size_mult;
+	union {
+		struct { /* MMC system specification version 3.1 */
+			u8  erase_grp_size;
+			u8  erase_grp_mult;
+		} v31;
+		struct { /* MMC system specification version 2.2 */
+			u8  sector_size;
+			u8  erase_grp_size;
+		} v22;
+	} erase;
+	u8  wp_grp_size;
+	u8  wp_grp_enable;
+	u8  default_ecc;
+	u8  r2w_factor;
+	u8  write_bl_len;
+	u8  write_bl_partial;
+	u8  file_format_grp;
+	u8  copy;
+	u8  perm_write_protect;
+	u8  tmp_write_protect;
+	u8  file_format;
+	u8  ecc;
 };
 
-struct mmc_data {
-	unsigned int		timeout_ns;	/* data timeout (in ns, max 80ms) */
-	unsigned int		timeout_clks;	/* data timeout (in clocks) */
-	unsigned int		blksz;		/* data block size */
-	unsigned int		blocks;		/* number of blocks */
-	unsigned int		error;		/* data error */
-	unsigned int		flags;
+/*
+ * OCR bits are mostly in host.h
+ */
+#define MMC_CARD_BUSY	0x80000000	/* Card Power up status bit */
 
-#define MMC_DATA_WRITE	(1 << 8)
-#define MMC_DATA_READ	(1 << 9)
-#define MMC_DATA_STREAM	(1 << 10)
-#define MMC_DATA_MULTI	(1 << 11)
+/*
+ * Card Command Classes (CCC)
+ */
+#define CCC_BASIC		(1<<0)	/* (0) Basic protocol functions */
+					/* (CMD0,1,2,3,4,7,9,10,12,13,15) */
+#define CCC_STREAM_READ		(1<<1)	/* (1) Stream read commands */
+					/* (CMD11) */
+#define CCC_BLOCK_READ		(1<<2)	/* (2) Block read commands */
+					/* (CMD16,17,18) */
+#define CCC_STREAM_WRITE	(1<<3)	/* (3) Stream write commands */
+					/* (CMD20) */
+#define CCC_BLOCK_WRITE		(1<<4)	/* (4) Block write commands */
+					/* (CMD16,24,25,26,27) */
+#define CCC_ERASE		(1<<5)	/* (5) Ability to erase blocks */
+					/* (CMD32,33,34,35,36,37,38,39) */
+#define CCC_WRITE_PROT		(1<<6)	/* (6) Able to write protect blocks */
+					/* (CMD28,29,30) */
+#define CCC_LOCK_CARD		(1<<7)	/* (7) Able to lock down card */
+					/* (CMD16,CMD42) */
+#define CCC_APP_SPEC		(1<<8)	/* (8) Application specific */
+					/* (CMD55,56,57,ACMD*) */
+#define CCC_IO_MODE		(1<<9)	/* (9) I/O mode */
+					/* (CMD5,39,40,52,53) */
+#define CCC_SWITCH		(1<<10)	/* (10) High speed switch */
+					/* (CMD6,34,35,36,37,50) */
+					/* (11) Reserved */
+					/* (CMD?) */
 
-	unsigned int		bytes_xfered;
+/*
+ * CSD field definitions
+ */
 
-	struct mmc_command	*stop;		/* stop command */
-	struct mmc_request	*mrq;		/* associated request */
+#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 - 3.2 - 3.31 - 4.0 - 4.1 */
+#define CSD_STRUCT_EXT_CSD  3           /* Version is coded in CSD_STRUCTURE in EXT_CSD */
 
-	unsigned int		sg_len;		/* size of scatter list */
-	struct scatterlist	*sg;		/* I/O scatter list */
-};
+#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 - 3.2 - 3.31 */
+#define CSD_SPEC_VER_4      4           /* Implements system specification 4.0 - 4.1 */
 
-struct mmc_request {
-	struct mmc_command	*cmd;
-	struct mmc_data		*data;
-	struct mmc_command	*stop;
+/*
+ * EXT_CSD fields
+ */
 
-	void			*done_data;	/* completion data */
-	void			(*done)(struct mmc_request *);/* completion function */
-};
+#define EXT_CSD_BUS_WIDTH	183	/* R/W */
+#define EXT_CSD_HS_TIMING	185	/* R/W */
+#define EXT_CSD_CARD_TYPE	196	/* RO */
+#define EXT_CSD_SEC_CNT		212	/* RO, 4 bytes */
 
-struct mmc_host;
-struct mmc_card;
+/*
+ * EXT_CSD field definitions
+ */
 
-extern int mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
-extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
-extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int,
-	struct mmc_command *, int);
+#define EXT_CSD_CMD_SET_NORMAL		(1<<0)
+#define EXT_CSD_CMD_SET_SECURE		(1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *, int);
+#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 */
 
-extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card);
+#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 */
 
-static inline void mmc_claim_host(struct mmc_host *host)
-{
-	__mmc_claim_host(host, (struct mmc_card *)-1);
-}
+/*
+ * MMC_SWITCH access modes
+ */
 
-extern void mmc_release_host(struct mmc_host *host);
+#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 */
 
-#endif
+#endif  /* MMC_MMC_PROTOCOL_H */
+
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
deleted file mode 100644
index c90b676..0000000
--- a/include/linux/mmc/protocol.h
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Header for MultiMediaCard (MMC)
- *
- * Copyright 2002 Hewlett-Packard Company
- *
- * Use consistent with the GNU GPL is permitted,
- * provided that this copyright notice is
- * preserved in its entirety in all copies and derived works.
- *
- * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
- * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
- * FITNESS FOR ANY PARTICULAR PURPOSE.
- *
- * Many thanks to Alessandro Rubini and Jonathan Corbet!
- *
- * Based strongly on code by:
- *
- * Author: Yong-iL Joh <tolkien@mizi.com>
- * Date  : $Date: 2002/06/18 12:37:30 $
- *
- * Author:  Andrew Christian
- *          15 May 2002
- */
-
-#ifndef MMC_MMC_PROTOCOL_H
-#define MMC_MMC_PROTOCOL_H
-
-/* 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  */
-#define MMC_STOP_TRANSMISSION    12   /* ac                      R1b */
-#define MMC_SEND_STATUS	         13   /* ac   [31:16] RCA        R1  */
-#define MMC_GO_INACTIVE_STATE    15   /* ac   [31:16] RCA            */
-
-  /* class 2 */
-#define MMC_SET_BLOCKLEN         16   /* ac   [31:0] block len   R1  */
-#define MMC_READ_SINGLE_BLOCK    17   /* adtc [31:0] data addr   R1  */
-#define MMC_READ_MULTIPLE_BLOCK  18   /* adtc [31:0] data addr   R1  */
-
-  /* class 3 */
-#define MMC_WRITE_DAT_UNTIL_STOP 20   /* adtc [31:0] data addr   R1  */
-
-  /* class 4 */
-#define MMC_SET_BLOCK_COUNT      23   /* adtc [31:0] data addr   R1  */
-#define MMC_WRITE_BLOCK          24   /* adtc [31:0] data addr   R1  */
-#define MMC_WRITE_MULTIPLE_BLOCK 25   /* adtc                    R1  */
-#define MMC_PROGRAM_CID          26   /* adtc                    R1  */
-#define MMC_PROGRAM_CSD          27   /* adtc                    R1  */
-
-  /* class 6 */
-#define MMC_SET_WRITE_PROT       28   /* ac   [31:0] data addr   R1b */
-#define MMC_CLR_WRITE_PROT       29   /* ac   [31:0] data addr   R1b */
-#define MMC_SEND_WRITE_PROT      30   /* adtc [31:0] wpdata addr R1  */
-
-  /* class 5 */
-#define MMC_ERASE_GROUP_START    35   /* ac   [31:0] data addr   R1  */
-#define MMC_ERASE_GROUP_END      36   /* ac   [31:0] data addr   R1  */
-#define MMC_ERASE                38   /* ac                      R1b */
-
-  /* class 9 */
-#define MMC_FAST_IO              39   /* ac   <Complex>          R4  */
-#define MMC_GO_IRQ_STATE         40   /* bcr                     R5  */
-
-  /* class 7 */
-#define MMC_LOCK_UNLOCK          42   /* adtc                    R1b */
-
-  /* class 8 */
-#define MMC_APP_CMD              55   /* ac   [31:16] RCA        R1  */
-#define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
-
-/* SD commands                           type  argument     response */
-  /* class 0 */
-/* This is basically the same command as for MMC with some quirks. */
-#define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
-#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
-
-  /* class 10 */
-#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  */
-#define SD_APP_SEND_NUM_WR_BLKS  22   /* adtc                    R1  */
-#define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
-#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
- */
-
-/*
- * SD_SEND_IF_COND argument format:
- *
- *	[31:12] Reserved (0)
- *	[11:8] Host Voltage Supply Flags
- *	[7:0] Check Pattern (0xAA)
- */
-
-/*
-  MMC status in R1
-  Type
-  	e : error bit
-	s : status bit
-	r : detected and set for the actual command response
-	x : detected and set during command execution. the host must poll
-            the card by sending status command in order to read these bits.
-  Clear condition
-  	a : according to the card state
-	b : always related to the previous command. Reception of
-            a valid command will clear it (with a delay of one command)
-	c : clear by read
- */
-
-#define R1_OUT_OF_RANGE		(1 << 31)	/* er, c */
-#define R1_ADDRESS_ERROR	(1 << 30)	/* erx, c */
-#define R1_BLOCK_LEN_ERROR	(1 << 29)	/* er, c */
-#define R1_ERASE_SEQ_ERROR      (1 << 28)	/* er, c */
-#define R1_ERASE_PARAM		(1 << 27)	/* ex, c */
-#define R1_WP_VIOLATION		(1 << 26)	/* erx, c */
-#define R1_CARD_IS_LOCKED	(1 << 25)	/* sx, a */
-#define R1_LOCK_UNLOCK_FAILED	(1 << 24)	/* erx, c */
-#define R1_COM_CRC_ERROR	(1 << 23)	/* er, b */
-#define R1_ILLEGAL_COMMAND	(1 << 22)	/* er, b */
-#define R1_CARD_ECC_FAILED	(1 << 21)	/* ex, c */
-#define R1_CC_ERROR		(1 << 20)	/* erx, c */
-#define R1_ERROR		(1 << 19)	/* erx, c */
-#define R1_UNDERRUN		(1 << 18)	/* ex, c */
-#define R1_OVERRUN		(1 << 17)	/* ex, c */
-#define R1_CID_CSD_OVERWRITE	(1 << 16)	/* erx, c, CID/CSD overwrite */
-#define R1_WP_ERASE_SKIP	(1 << 15)	/* sx, c */
-#define R1_CARD_ECC_DISABLED	(1 << 14)	/* sx, a */
-#define R1_ERASE_RESET		(1 << 13)	/* sr, c */
-#define R1_STATUS(x)            (x & 0xFFFFE000)
-#define R1_CURRENT_STATE(x)    	((x & 0x00001E00) >> 9)	/* sx, b (4 bits) */
-#define R1_READY_FOR_DATA	(1 << 8)	/* sx, a */
-#define R1_APP_CMD		(1 << 5)	/* sr, c */
-
-/* These are unpacked versions of the actual responses */
-
-struct _mmc_csd {
-	u8  csd_structure;
-	u8  spec_vers;
-	u8  taac;
-	u8  nsac;
-	u8  tran_speed;
-	u16 ccc;
-	u8  read_bl_len;
-	u8  read_bl_partial;
-	u8  write_blk_misalign;
-	u8  read_blk_misalign;
-	u8  dsr_imp;
-	u16 c_size;
-	u8  vdd_r_curr_min;
-	u8  vdd_r_curr_max;
-	u8  vdd_w_curr_min;
-	u8  vdd_w_curr_max;
-	u8  c_size_mult;
-	union {
-		struct { /* MMC system specification version 3.1 */
-			u8  erase_grp_size;
-			u8  erase_grp_mult;
-		} v31;
-		struct { /* MMC system specification version 2.2 */
-			u8  sector_size;
-			u8  erase_grp_size;
-		} v22;
-	} erase;
-	u8  wp_grp_size;
-	u8  wp_grp_enable;
-	u8  default_ecc;
-	u8  r2w_factor;
-	u8  write_bl_len;
-	u8  write_bl_partial;
-	u8  file_format_grp;
-	u8  copy;
-	u8  perm_write_protect;
-	u8  tmp_write_protect;
-	u8  file_format;
-	u8  ecc;
-};
-
-#define MMC_VDD_145_150	0x00000001	/* VDD voltage 1.45 - 1.50 */
-#define MMC_VDD_150_155	0x00000002	/* VDD voltage 1.50 - 1.55 */
-#define MMC_VDD_155_160	0x00000004	/* VDD voltage 1.55 - 1.60 */
-#define MMC_VDD_160_165	0x00000008	/* VDD voltage 1.60 - 1.65 */
-#define MMC_VDD_165_170	0x00000010	/* VDD voltage 1.65 - 1.70 */
-#define MMC_VDD_17_18	0x00000020	/* VDD voltage 1.7 - 1.8 */
-#define MMC_VDD_18_19	0x00000040	/* VDD voltage 1.8 - 1.9 */
-#define MMC_VDD_19_20	0x00000080	/* VDD voltage 1.9 - 2.0 */
-#define MMC_VDD_20_21	0x00000100	/* VDD voltage 2.0 ~ 2.1 */
-#define MMC_VDD_21_22	0x00000200	/* VDD voltage 2.1 ~ 2.2 */
-#define MMC_VDD_22_23	0x00000400	/* VDD voltage 2.2 ~ 2.3 */
-#define MMC_VDD_23_24	0x00000800	/* VDD voltage 2.3 ~ 2.4 */
-#define MMC_VDD_24_25	0x00001000	/* VDD voltage 2.4 ~ 2.5 */
-#define MMC_VDD_25_26	0x00002000	/* VDD voltage 2.5 ~ 2.6 */
-#define MMC_VDD_26_27	0x00004000	/* VDD voltage 2.6 ~ 2.7 */
-#define MMC_VDD_27_28	0x00008000	/* VDD voltage 2.7 ~ 2.8 */
-#define MMC_VDD_28_29	0x00010000	/* VDD voltage 2.8 ~ 2.9 */
-#define MMC_VDD_29_30	0x00020000	/* VDD voltage 2.9 ~ 3.0 */
-#define MMC_VDD_30_31	0x00040000	/* VDD voltage 3.0 ~ 3.1 */
-#define MMC_VDD_31_32	0x00080000	/* VDD voltage 3.1 ~ 3.2 */
-#define MMC_VDD_32_33	0x00100000	/* VDD voltage 3.2 ~ 3.3 */
-#define MMC_VDD_33_34	0x00200000	/* VDD voltage 3.3 ~ 3.4 */
-#define MMC_VDD_34_35	0x00400000	/* VDD voltage 3.4 ~ 3.5 */
-#define MMC_VDD_35_36	0x00800000	/* VDD voltage 3.5 ~ 3.6 */
-#define MMC_CARD_BUSY	0x80000000	/* Card Power up status bit */
-
-/*
- * Card Command Classes (CCC)
- */
-#define CCC_BASIC		(1<<0)	/* (0) Basic protocol functions */
-					/* (CMD0,1,2,3,4,7,9,10,12,13,15) */
-#define CCC_STREAM_READ		(1<<1)	/* (1) Stream read commands */
-					/* (CMD11) */
-#define CCC_BLOCK_READ		(1<<2)	/* (2) Block read commands */
-					/* (CMD16,17,18) */
-#define CCC_STREAM_WRITE	(1<<3)	/* (3) Stream write commands */
-					/* (CMD20) */
-#define CCC_BLOCK_WRITE		(1<<4)	/* (4) Block write commands */
-					/* (CMD16,24,25,26,27) */
-#define CCC_ERASE		(1<<5)	/* (5) Ability to erase blocks */
-					/* (CMD32,33,34,35,36,37,38,39) */
-#define CCC_WRITE_PROT		(1<<6)	/* (6) Able to write protect blocks */
-					/* (CMD28,29,30) */
-#define CCC_LOCK_CARD		(1<<7)	/* (7) Able to lock down card */
-					/* (CMD16,CMD42) */
-#define CCC_APP_SPEC		(1<<8)	/* (8) Application specific */
-					/* (CMD55,56,57,ACMD*) */
-#define CCC_IO_MODE		(1<<9)	/* (9) I/O mode */
-					/* (CMD5,39,40,52,53) */
-#define CCC_SWITCH		(1<<10)	/* (10) High speed switch */
-					/* (CMD6,34,35,36,37,50) */
-					/* (11) Reserved */
-					/* (CMD?) */
-
-/*
- * CSD field definitions
- */
-
-#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 - 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 - 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
- */
-#define SD_BUS_WIDTH_1      0
-#define SD_BUS_WIDTH_4      2
-
-#endif  /* MMC_MMC_PROTOCOL_H */
-
diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h
new file mode 100644
index 0000000..f310062
--- /dev/null
+++ b/include/linux/mmc/sd.h
@@ -0,0 +1,83 @@
+/*
+ *  include/linux/mmc/sd.h
+ *
+ *  Copyright (C) 2005-2007 Pierre Ossman, 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef MMC_SD_H
+#define MMC_SD_H
+
+/* SD commands                           type  argument     response */
+  /* class 0 */
+/* This is basically the same command as for MMC with some quirks. */
+#define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
+#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
+
+  /* class 10 */
+#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  */
+#define SD_APP_SEND_NUM_WR_BLKS  22   /* adtc                    R1  */
+#define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
+#define SD_APP_SEND_SCR          51   /* adtc                    R1  */
+
+/*
+ * 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
+ */
+
+/*
+ * SD_SEND_IF_COND argument format:
+ *
+ *	[31:12] Reserved (0)
+ *	[11:8] Host Voltage Supply Flags
+ *	[7:0] Check Pattern (0xAA)
+ */
+
+/*
+ * 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
+ */
+#define SD_BUS_WIDTH_1		0
+#define SD_BUS_WIDTH_4		2
+
+/*
+ * SD_SWITCH mode
+ */
+#define SD_SWITCH_CHECK		0
+#define SD_SWITCH_SET		1
+
+/*
+ * SD_SWITCH function groups
+ */
+#define SD_SWITCH_GRP_ACCESS	0
+
+/*
+ * SD_SWITCH access modes
+ */
+#define SD_SWITCH_ACCESS_DEF	0
+#define SD_SWITCH_ACCESS_HS	1
+
+#endif
+
diff --git a/include/linux/tifm.h b/include/linux/tifm.h
index 3deb0a6..2a19698 100644
--- a/include/linux/tifm.h
+++ b/include/linux/tifm.h
@@ -14,16 +14,16 @@
 
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
-#include <linux/wait.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/kthread.h>
+#include <linux/workqueue.h>
 
 /* Host registers (relative to pci base address): */
 enum {
 	FM_SET_INTERRUPT_ENABLE   = 0x008,
 	FM_CLEAR_INTERRUPT_ENABLE = 0x00c,
-	FM_INTERRUPT_STATUS       = 0x014 };
+	FM_INTERRUPT_STATUS       = 0x014
+};
 
 /* Socket registers (relative to socket base address): */
 enum {
@@ -58,14 +58,8 @@
 	SOCK_MS_DATA                   = 0x188,
 	SOCK_MS_STATUS                 = 0x18c,
 	SOCK_MS_SYSTEM                 = 0x190,
-	SOCK_FIFO_ACCESS               = 0x200 };
-
-
-#define TIFM_IRQ_ENABLE           0x80000000
-#define TIFM_IRQ_SOCKMASK(x)      (x)
-#define TIFM_IRQ_CARDMASK(x)      ((x) << 8)
-#define TIFM_IRQ_FIFOMASK(x)      ((x) << 16)
-#define TIFM_IRQ_SETALL           0xffffffff
+	SOCK_FIFO_ACCESS               = 0x200
+};
 
 #define TIFM_CTRL_LED             0x00000040
 #define TIFM_CTRL_FAST_CLK        0x00000100
@@ -73,63 +67,76 @@
 #define TIFM_SOCK_STATE_OCCUPIED  0x00000008
 #define TIFM_SOCK_STATE_POWERED   0x00000080
 
-#define TIFM_FIFO_ENABLE          0x00000001 /* Meaning of this constant is unverified */
+#define TIFM_FIFO_ENABLE          0x00000001
+#define TIFM_FIFO_READY           0x00000001
 #define TIFM_FIFO_INT_SETALL      0x0000ffff
-#define TIFM_FIFO_INTMASK         0x00000005 /* Meaning of this constant is unverified */
+#define TIFM_FIFO_INTMASK         0x00000005
 
-#define TIFM_DMA_RESET            0x00000002 /* Meaning of this constant is unverified */
-#define TIFM_DMA_TX               0x00008000 /* Meaning of this constant is unverified */
-#define TIFM_DMA_EN               0x00000001 /* Meaning of this constant is unverified */
+#define TIFM_DMA_RESET            0x00000002
+#define TIFM_DMA_TX               0x00008000
+#define TIFM_DMA_EN               0x00000001
+#define TIFM_DMA_TSIZE            0x0000007f
 
-typedef enum {FM_NULL = 0, FM_XD = 0x01, FM_MS = 0x02, FM_SD = 0x03} tifm_media_id;
+#define TIFM_TYPE_XD 1
+#define TIFM_TYPE_MS 2
+#define TIFM_TYPE_SD 3
+
+struct tifm_device_id {
+	unsigned char type;
+};
 
 struct tifm_driver;
 struct tifm_dev {
-	char __iomem            *addr;
-	spinlock_t              lock;
-	tifm_media_id           media_id;
-	unsigned int            socket_id;
+	char __iomem  *addr;
+	spinlock_t    lock;
+	unsigned char type;
+	unsigned int  socket_id;
 
-	void                    (*signal_irq)(struct tifm_dev *sock,
-					      unsigned int sock_irq_status);
+	void          (*card_event)(struct tifm_dev *sock);
+	void          (*data_event)(struct tifm_dev *sock);
 
-	struct tifm_driver      *drv;
-	struct device           dev;
+	struct device dev;
 };
 
 struct tifm_driver {
-	tifm_media_id        *id_table;
-	int                  (*probe)(struct tifm_dev *dev);
-	void                 (*remove)(struct tifm_dev *dev);
-	int                  (*suspend)(struct tifm_dev *dev,
-                                        pm_message_t state);
-	int                  (*resume)(struct tifm_dev *dev);
+	struct tifm_device_id *id_table;
+	int                   (*probe)(struct tifm_dev *dev);
+	void                  (*remove)(struct tifm_dev *dev);
+	int                   (*suspend)(struct tifm_dev *dev,
+					 pm_message_t state);
+	int                   (*resume)(struct tifm_dev *dev);
 
-	struct device_driver driver;
+	struct device_driver  driver;
 };
 
 struct tifm_adapter {
-	char __iomem            *addr;
-	spinlock_t              lock;
-	unsigned int            irq_status;
-	unsigned int            socket_change_set;
-	wait_queue_head_t       change_set_notify;
-	unsigned int            id;
-	unsigned int            num_sockets;
-	struct tifm_dev         **sockets;
-	struct task_struct      *media_switcher;
-	struct class_device     cdev;
-	struct device           *dev;
+	char __iomem        *addr;
+	spinlock_t          lock;
+	unsigned int        irq_status;
+	unsigned int        socket_change_set;
+	unsigned int        id;
+	unsigned int        num_sockets;
+	struct completion   *finish_me;
 
-	void                    (*eject)(struct tifm_adapter *fm, struct tifm_dev *sock);
+	struct work_struct  media_switcher;
+	struct class_device cdev;
+
+	void                (*eject)(struct tifm_adapter *fm,
+				     struct tifm_dev *sock);
+
+	struct tifm_dev     *sockets[0];
 };
 
-struct tifm_adapter *tifm_alloc_adapter(void);
-void tifm_free_device(struct device *dev);
-void tifm_free_adapter(struct tifm_adapter *fm);
-int tifm_add_adapter(struct tifm_adapter *fm, int (*mediathreadfn)(void *data));
+struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
+					struct device *dev);
+int tifm_add_adapter(struct tifm_adapter *fm);
 void tifm_remove_adapter(struct tifm_adapter *fm);
-struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm);
+void tifm_free_adapter(struct tifm_adapter *fm);
+
+void tifm_free_device(struct device *dev);
+struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id,
+				   unsigned char type);
+
 int tifm_register_driver(struct tifm_driver *drv);
 void tifm_unregister_driver(struct tifm_driver *drv);
 void tifm_eject(struct tifm_dev *sock);
@@ -137,11 +144,11 @@
 		int direction);
 void tifm_unmap_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
 		   int direction);
-
+void tifm_queue_work(struct work_struct *work);
 
 static inline void *tifm_get_drvdata(struct tifm_dev *dev)
 {
-        return dev_get_drvdata(&dev->dev);
+	return dev_get_drvdata(&dev->dev);
 }
 
 static inline void tifm_set_drvdata(struct tifm_dev *dev, void *data)
@@ -149,8 +156,4 @@
 	dev_set_drvdata(&dev->dev, data);
 }
 
-struct tifm_device_id {
-	tifm_media_id media_id;
-};
-
 #endif