diff -Naru linux-2.6.14.6-20060127.org/arch/m32r/kernel/setup_m32700ut.c linux-2.6.14.6-20060127/arch/m32r/kernel/setup_m32700ut.c
--- linux-2.6.14.6-20060127.org/arch/m32r/kernel/setup_m32700ut.c	2006-04-11 09:26:15.000000000 +0900
+++ linux-2.6.14.6-20060127/arch/m32r/kernel/setup_m32700ut.c	2006-09-22 09:43:54.000000000 +0900
@@ -411,6 +411,16 @@
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* 'H' edge sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_CFC_EJECT);
 
+#if defined(CONFIG_MMC_M32R) || defined(CONFIG_MMC_M32R_MODULE)
+	/* INT#1: MMC Card Insert/Eject on PLD */
+	irq_desc[PLD_IRQ_MMCCARD].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_MMCCARD].handler = &m32700ut_pld_irq_type;
+	irq_desc[PLD_IRQ_MMCCARD].action = 0;
+	irq_desc[PLD_IRQ_MMCCARD].depth = 1;	/* disable nested irq */
+	pld_icu_data[irq2pldirq(PLD_IRQ_MMCCARD)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
+	disable_m32700ut_pld_irq(PLD_IRQ_MMCCARD);
+#endif	/* CONFIG_MMC_M32R || CONFIG_MMC_M32R_MODULE */
+
 	/*
 	 * INT0# is used for LAN, DIO
 	 * We enable it here.
diff -Naru linux-2.6.14.6-20060127.org/drivers/mmc/Kconfig linux-2.6.14.6-20060127/drivers/mmc/Kconfig
--- linux-2.6.14.6-20060127.org/drivers/mmc/Kconfig	2006-01-08 10:15:24.000000000 +0800
+++ linux-2.6.14.6-20060127/drivers/mmc/Kconfig	2006-09-22 08:57:39.000000000 +0900
@@ -29,6 +29,16 @@
 	  mount the filesystem. Almost everyone wishing MMC support
 	  should say Y or M here.
 
+config MMC_M32R
+	tristate "Renesas M32R MMC Card Interface support"
+	depends on M32R && MMC
+	help
+	  This selects the Renesas M32R MMC card interface.
+	  If you have an M32R platform with a Multimedia Card slot,
+	  say Y or M here.
+
+	  If unsure, say N.
+
 config MMC_ARMMMCI
 	tristate "ARM AMBA Multimedia Card Interface support"
 	depends on ARM_AMBA && MMC
diff -Naru linux-2.6.14.6-20060127.org/drivers/mmc/Makefile linux-2.6.14.6-20060127/drivers/mmc/Makefile
--- linux-2.6.14.6-20060127.org/drivers/mmc/Makefile	2006-01-08 10:15:24.000000000 +0800
+++ linux-2.6.14.6-20060127/drivers/mmc/Makefile	2006-09-22 08:56:11.000000000 +0900
@@ -18,5 +18,6 @@
 obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o
 obj-$(CONFIG_MMC_PXA)		+= pxamci.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
+obj-$(CONFIG_MMC_M32R)		+= m32r_mmc.o
 
 mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
diff -Naru linux-2.6.14.6-20060127.org/drivers/mmc/m32r_mmc.c linux-2.6.14.6-20060127/drivers/mmc/m32r_mmc.c
--- linux-2.6.14.6-20060127.org/drivers/mmc/m32r_mmc.c	1970-01-01 07:00:00.000000000 +0700
+++ linux-2.6.14.6-20060127/drivers/mmc/m32r_mmc.c	2006-09-27 12:22:41.000000000 +0900
@@ -0,0 +1,780 @@
+/*
+ * linux/drivers/mmc/m32r_mmc.c - MMC driver for M32R evaluation boards
+ *
+ * Copyright (C) 2006	Renesas Technology Corp. and Renesas Solutions Corp.
+ *
+ * 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/config.h>
+
+#ifdef CONFIG_MMC_DEBUG
+#define DEBUG
+#else
+#undef	DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/highmem.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/protocol.h>
+#include <linux/jiffies.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/scatterlist.h>
+#include <asm/m32r.h>
+
+#include "m32r_mmc.h"
+
+#define DRIVER_NAME	"m32r_mmc"
+
+static void m32r_mmc_complete_request(struct m32r_mmc_host *host, int result);
+static u8 *m32r_mmc_map_buffer(struct m32r_mmc_host *host);
+static void m32r_mmc_unmap_buffer(struct m32r_mmc_host *host, u8 *buff, int xfered);
+
+static void m32r_mmc_reset(void)
+{
+	outw(M32R_MMC_CLR, (unsigned long)PLD_MMCCR);
+}
+
+static void m32r_mmc_set_clock(u32 rate)
+{
+	unsigned short val;
+
+	val = (boot_cpu_data.bus_clock / (rate * 2)) - 1;
+
+	m32r_mmc_reset();
+	outw(val, (unsigned long)PLD_MMCBAUR);
+}
+
+static void m32r_mmc_receive_dummy_data(int clock)
+{
+	int i;
+
+	/* setup */
+	outw(M32R_MMC_DMY, (unsigned long)PLD_MMCMOD);	/* set dummy clock mode */
+	outw(clock * 2, (unsigned long)PLD_MMCCDTBCUT); /* set transfer size */
+
+	/* start */
+	outw(M32R_MMC_DTEN, (unsigned long)PLD_MMCCR);
+	for (i = 0; i < 0xffffff; i++) {
+		if (inw((unsigned long)PLD_MMCCDTBCUT) == 0 &&
+		    inw((unsigned long)PLD_MMCCR) == 0) {
+			outw(0, (unsigned long)PLD_MMCMOD);	/* set receive mode */
+			return;
+		}
+	}
+
+	m32r_mmc_reset();
+}
+
+static void m32r_mmc_set_command(u16 cmd, u32 arg)
+{
+	int i;
+	u16 cmd_data[3];
+	u8 *buf;
+	u16 data;
+
+	cmd_data[0] = ((cmd << 8) & 0xff00) | 0x4000 | ((arg >> 24) & 0xff);
+	cmd_data[1] = (((arg >> 16) << 8) & 0xff00) | ((arg >> 8) & 0xff);
+	cmd_data[2] = ((arg << 8) & 0xff00);
+
+	/* set command CRC */
+	outw(0, (unsigned long)PLD_CRC7DATA);
+	buf = (u8 *)&cmd_data[0];
+	for (i = 0; i < 5; i++) {
+		outw(*buf++, (unsigned long)PLD_CRC7INDATA);
+	}
+
+	data = inw((unsigned long)PLD_CRC7DATA) << 1;
+	cmd_data[2] = cmd_data[2] | data | 1;
+
+	/* set command */
+	for (i = 0; i < 3; i++) {
+		outw(cmd_data[i], (unsigned long)(PLD_MMCCMDDATA + i));
+	}
+}
+
+static int m32r_mmc_start_receive(struct m32r_mmc_host *host)
+{
+	pr_debug(DRIVER_NAME " receive start: offset=0x%x, index=%d, pos=%d\n",
+		host->offset, host->sg_index, host->buff_pos);
+
+	/* setup */
+	outw(0, (unsigned long)PLD_MMCCR);	/* disable read */
+	outw(0, (unsigned long)PLD_MMCMOD);	/* set receive mode */
+	outw(M32R_BLOCK_LEN + 2, (unsigned long)PLD_MMCCDTBCUT);	/* set transfer size */
+
+	host->start = jiffies;
+	host->stat_recv++;
+
+	/* start transfer */
+	outw(M32R_MMC_DTEN, (unsigned long)PLD_MMCCR);
+
+	host->timeout_tick = M32R_DATA_TIMEOUT;
+
+	return MMC_ERR_NONE;
+}
+
+static int m32r_mmc_complete_receive(struct m32r_mmc_host *host, u8 *buff)
+{
+	int i;
+	u16 data;
+	u8 *p;
+
+	/* reset CRC */
+	outw(0, (unsigned long)PLD_CRC16DATA);
+
+	/* read data */
+	p = buff + (host->buff_pos * M32R_BLOCK_LEN);
+	for (i = 0; i < M32R_BLOCK_LEN / 2; i++) {
+		u8 tmp;
+
+		data = inw((unsigned long)(PLD_MMCRDATA + i));
+
+		tmp = data >> 8;
+		outw(tmp, (unsigned long)PLD_CRC16INDATA);
+		*p++ = tmp;
+
+		tmp = data & 0xff;
+		outw(tmp, (unsigned long)PLD_CRC16INDATA);
+		*p++ = tmp;
+	}
+
+	/* read CRC */
+	data = inw((unsigned long)(PLD_MMCRDATA + i));
+	m32r_mmc_receive_dummy_data(10);
+
+	/* check CRC value */
+	if (inw((unsigned long)PLD_CRC16DATA) != data) {
+		pr_debug(DRIVER_NAME " receive compete: CRC Error\n");
+		return MMC_ERR_BADCRC;
+	}
+
+	return MMC_ERR_NONE;
+}
+
+static int m32r_mmc_start_send(struct m32r_mmc_host *host, u8 *buff)
+{
+	int i;
+	u16 data;
+	u8 *p;
+
+	pr_debug(DRIVER_NAME " send start: offset=0x%x, index=%d, pos=%d\n",
+		host->offset, host->sg_index, host->buff_pos);
+
+	/* setup */
+	outw(0, (unsigned long)PLD_MMCCR);	/* disable write */
+	outw(M32R_MMC_DSEL, (unsigned long)PLD_MMCMOD); /* set send mode */
+	outw(0, (unsigned long)PLD_MMCSTS);	/* clear CRC status */
+	outw(M32R_BLOCK_LEN + 2, (unsigned long)PLD_MMCCDTBCUT);	/* set transfer size */
+
+	outw(0, (unsigned long)PLD_CRC16DATA);	/* reset CRC */
+
+	/* write data */
+	p = buff + (host->buff_pos * M32R_BLOCK_LEN);
+	for (i = 0; i < M32R_BLOCK_LEN / 2; i++) {
+		outw(*p, (unsigned long)PLD_CRC16INDATA);
+		data = *p++ << 8;
+		outw(*p, (unsigned long)PLD_CRC16INDATA);
+		data |= *p++;
+
+		outw(data, (unsigned long)(PLD_MMCWDATA + i));
+	}
+
+	/* write CRC */
+	data = inw((unsigned long)PLD_CRC16DATA);
+	outw(data, (unsigned long)(PLD_MMCWDATA + i));
+
+	host->timeout_tick = M32R_DATA_TIMEOUT;
+
+	host->start = jiffies;
+	host->stat_send++;
+
+	/* start transfer */
+	outw(M32R_MMC_DTEN, (unsigned long)PLD_MMCCR);
+
+	return MMC_ERR_NONE;
+}
+
+static int m32r_mmc_complete_send(struct m32r_mmc_host *host)
+{
+	u16 data;
+
+	/* check CRC */
+	data = inw((unsigned long)PLD_MMCSTS);
+	if (data != 0x0002) {
+		pr_debug(DRIVER_NAME " send complete: CRC ERROR status=0x%x\n",
+			data);
+		return MMC_ERR_BADCRC;
+	}
+
+	return MMC_ERR_NONE;
+}
+
+static void m32r_mmc_send_command(struct m32r_mmc_host *host)
+{
+	struct mmc_command *cmd = host->mrq->cmd;
+	struct mmc_data *data = host->mrq->data;
+	unsigned int flags;
+
+	host->cmd = cmd->opcode;
+	if (host->cmd == MMC_READ_MULTIPLE_BLOCK) {
+		host->cmd = MMC_READ_SINGLE_BLOCK;
+	}
+
+	host->arg = cmd->arg + host->offset;
+
+	/* calculate the response length */
+	flags = cmd->flags &
+		(MMC_RSP_NONE | MMC_RSP_R1 | MMC_RSP_R1B | MMC_RSP_R2 | MMC_RSP_R3 | MMC_RSP_R6);
+	if (flags == MMC_RSP_NONE) {
+		host->res_len = 0;
+	} else if (flags == MMC_RSP_R2) {
+		host->res_len = 17;
+	} else {
+		host->res_len = 6;
+	}
+
+	/* get cmd type */
+	if (data != NULL) {
+		if (data->flags & MMC_DATA_READ) {
+			host->type = CT_READ;
+		} else if (data->flags & MMC_DATA_WRITE) {
+			host->type = CT_WRITE;
+		} else {
+			pr_info("send command: MMC_DATA_STREAM is not supported\n");
+			m32r_mmc_complete_request(host, MMC_ERR_INVALID);
+			return;
+		}
+	} else {
+		host->type = ((0 < host->res_len) ? CT_RESPONSE_ONLY : CT_NO_RESPONSE);
+	}
+
+	pr_debug(DRIVER_NAME " send command: cmd=%d arg=%08x\n",
+		host->cmd, host->arg);
+
+	/* setup */
+	m32r_mmc_set_clock(host->clock);
+	m32r_mmc_set_command(host->cmd, host->arg);
+	outw(host->res_len + 6, (unsigned long)PLD_MMCCMDBCUT);
+
+	host->start = jiffies;
+	host->stat_cmd++;
+
+	/* start transfer */
+	outw(M32R_MMC_CMDEN, (unsigned long)PLD_MMCCR);
+
+	/* schedule the polling timer */
+	host->state = CS_START_CMD;
+	host->timeout_tick = M32R_CMD_TIMEOUT;
+
+#ifdef M32R_USE_TIMER
+	mod_timer(&host->poll_timer, jiffies + M32R_POLL_INTERVAL);
+#endif /* M32R_USE_TIMER */
+}
+
+static void m32r_mmc_receive_response(struct m32r_mmc_host *host)
+{
+	int i;
+	int dummy;
+	u16 *buf;
+
+	/* read response data */
+	buf = (u16 *)host->res_buff;
+	for (i = 0; i < (host->res_len + 1) / 2; i++) {
+		*buf++ = inw((unsigned long)(PLD_MMCRSPDATA + i));
+	}
+
+	switch (host->type) {
+	case CT_READ:
+		dummy = 0;
+		break;
+	case CT_WRITE:
+	default:
+		dummy = M32R_DUMMY_CLOCK;
+		break;
+	}
+	if (dummy != 0) {
+		m32r_mmc_receive_dummy_data(dummy);
+	}
+
+	/* copy response data to mrq */
+	for (i = 0; i < 4; i++) {
+		host->mrq->cmd->resp[i] = host->res_buff[i*4 + 1] << 24 |
+					  host->res_buff[i*4 + 2] << 16 |
+					  host->res_buff[i*4 + 3] << 8 |
+					  host->res_buff[i*4 + 4];
+	}
+}
+
+static int m32r_mmc_irq(int irq, void *devid, struct pt_regs *regs)
+{
+	struct m32r_mmc_host *host = devid;
+	u16 cr;
+	int ret;
+	u8 *buff;		/* mapped data buffer */
+
+	cr = inw((unsigned long)PLD_MMCCR);
+
+	switch (host->state) {
+	case CS_START_CMD:
+		/* check cmd timeout */
+		if ((cr != 0) || (0 < inw((unsigned long)PLD_MMCCMDBCUT))) {
+			if (0 < host->timeout_tick--) {
+				/* continue */
+				return IRQ_NONE;
+			} else {
+				/* timeout */
+				m32r_mmc_reset();
+				m32r_mmc_complete_request(host, MMC_ERR_TIMEOUT);
+				return IRQ_HANDLED;
+			}
+		}
+
+		/* command transfer was completed */
+		switch (host->type) {
+		case CT_READ:
+			host->state = CS_START_READ;
+
+			m32r_mmc_receive_response(host);
+			m32r_mmc_start_receive(host);
+
+			/* continue */
+			return IRQ_NONE;
+			break;
+
+		case CT_WRITE:
+			host->state = CS_START_WRITE;
+
+			m32r_mmc_receive_response(host);
+
+			buff = m32r_mmc_map_buffer(host);
+			if (buff == NULL) {
+				m32r_mmc_reset();
+				m32r_mmc_complete_request(host, MMC_ERR_FAILED);
+				return IRQ_HANDLED;
+			}
+			m32r_mmc_start_send(host, buff);
+			m32r_mmc_unmap_buffer(host, buff, M32R_BLOCK_LEN);
+
+			/* continue */
+			return IRQ_NONE;
+			break;
+
+		case CT_RESPONSE_ONLY:
+			m32r_mmc_receive_response(host);
+			m32r_mmc_complete_request(host, MMC_ERR_NONE);
+			break;
+
+		case CT_NO_RESPONSE:
+		default:
+			m32r_mmc_receive_dummy_data(1);
+			m32r_mmc_complete_request(host, MMC_ERR_NONE);
+			break;
+		}
+		break;
+
+	case CS_START_READ:
+	case CS_START_WRITE:
+		/* check data timeout */
+		if (0 < inw((unsigned long)PLD_MMCCDTBCUT)) {
+			if (0 < host->timeout_tick--) {
+				/* continue */
+				return IRQ_NONE;
+			} else {
+				/* timeout */
+				m32r_mmc_reset();
+				m32r_mmc_complete_request(host, MMC_ERR_TIMEOUT);
+				return IRQ_HANDLED;
+			}
+		}
+
+		/* data transfer was completed */
+		if (host->state == CS_START_READ) {
+			buff = m32r_mmc_map_buffer(host);
+			if (buff == NULL) {
+				m32r_mmc_reset();
+				m32r_mmc_complete_request(host, MMC_ERR_FAILED);
+				return IRQ_HANDLED;
+			}
+
+			ret = m32r_mmc_complete_receive(host, buff);
+			m32r_mmc_unmap_buffer(host, buff, M32R_BLOCK_LEN);
+
+		} else {
+			ret = m32r_mmc_complete_send(host);
+
+		}
+		if (ret != MMC_ERR_NONE) {
+			/* error */
+			m32r_mmc_reset();
+			m32r_mmc_complete_request(host, ret);
+			return IRQ_HANDLED;
+		}
+
+		host->state = CS_IDLE;
+
+		/* check next block transfer */
+		if (!host->eob) {
+			/* set arg to next block */
+			host->offset += M32R_BLOCK_LEN;
+
+			/* send next cmd */
+			m32r_mmc_send_command(host);
+#ifdef M32R_USE_TIMER
+			/* the polling timer is already started by m32r_mmc_send_command() */
+#else
+			return IRQ_NONE;
+#endif /* M32R_USE_TIMER */
+
+		} else {
+			m32r_mmc_complete_request(host, MMC_ERR_NONE);
+			return IRQ_HANDLED;
+		}
+		break;
+
+	default:
+		pr_debug(DRIVER_NAME " irq: invalid state (%d)\n", host->state);
+		break;
+	}
+
+	return IRQ_HANDLED;
+}
+
+#ifdef M32R_USE_TIMER
+static void m32r_mmc_polling(unsigned long arg)
+{
+	struct m32r_mmc_host *host = (struct m32r_mmc_host *)arg;
+	int ret;
+
+	ret = m32r_mmc_irq(0, (void *)arg, NULL);
+
+	/* reschedule the polling timer */
+	if (ret != IRQ_HANDLED) {
+		mod_timer(&host->poll_timer, jiffies + M32R_POLL_INTERVAL);
+	}
+}
+#endif /* M32R_USE_TIMER */
+
+static irqreturn_t m32r_mmc_card_irq(int irq, void *devid, struct pt_regs *regs)
+{
+	struct m32r_mmc_host *host = devid;
+	int detect;
+
+	detect = inw((unsigned long)PLD_MMCDET);
+	if (detect != host->detect) {
+		pr_debug(DRIVER_NAME " card irq: detect=%d\n", detect);
+
+		host->detect = detect;
+		mmc_detect_change(host->mmc, msecs_to_jiffies(500));
+	}
+
+	return IRQ_HANDLED;
+}
+
+static u8 *m32r_mmc_map_buffer(struct m32r_mmc_host *host)
+{
+	struct mmc_data *data = host->mrq->data;
+	struct scatterlist *sg;
+
+	if (data == NULL) {
+		return NULL;
+	}
+	if (host->eob) {
+		host->eob = 0;
+		host->sg_index = 0;
+		host->buff_pos = 0;
+	}
+
+	sg = &data->sg[host->sg_index];
+	return kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+}
+
+static void m32r_mmc_unmap_buffer(struct m32r_mmc_host *host, u8 *buff, int xfered)
+{
+	struct mmc_data *data = host->mrq->data;
+	struct scatterlist *sg = &data->sg[host->sg_index];
+
+	/* unmap buffer */
+	kunmap_atomic(buff, KM_BIO_SRC_IRQ);
+
+	/* update counter */
+	data->bytes_xfered += xfered;
+
+	host->buff_pos++;
+	if ((sg->length / M32R_BLOCK_LEN) <= host->buff_pos) {
+		host->buff_pos = 0;
+
+		host->sg_index++;
+		if (data->sg_len <= host->sg_index) {
+			/* reach the end of buffer */
+			host->eob = 1;
+		}
+	}
+}
+
+static void m32r_mmc_complete_request(struct m32r_mmc_host *host, int result)
+{
+	struct mmc_request* mrq = host->mrq;
+
+	pr_debug(DRIVER_NAME " request complete: host=0x%x, result=%d (%x)\n",
+		(int)host, result, (int)mrq);
+
+	host->state = CS_IDLE;
+	host->mrq = NULL;
+
+	/* notify to core driver */
+	mrq->cmd->error = result;
+	mmc_request_done(host->mmc, mrq);
+}
+
+static void m32r_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct m32r_mmc_host *host = mmc_priv(mmc);
+
+	/* check card status */
+	if (host->detect) {
+		mrq->cmd->error = MMC_ERR_TIMEOUT;
+		mmc_request_done(mmc, mrq);
+
+		pr_debug(DRIVER_NAME " request: abort\n");
+		return;
+	}
+
+	/* remember request */
+	host->mrq = mrq;
+
+	/* prepare buffer */
+	if (mrq->data != NULL) {
+		host->eob = 1;
+		mrq->data->bytes_xfered = 0;
+	}
+
+	/* send command */
+	host->offset = 0;
+	m32r_mmc_send_command(host);
+
+#ifndef M32R_USE_TIMER
+	do {
+		udelay(1);
+	} while (m32r_mmc_irq(0, (void *)host, NULL) != IRQ_HANDLED);
+#endif /* M32R_USE_TIMER */
+}
+
+static int m32r_mmc_get_ro(struct mmc_host *mmc)
+{
+	/* struct m32r_mmc_host *host = mmc_priv(mmc); */
+
+	return inw((unsigned long)PLD_MMCWP) & M32R_MMC_MMCWP;
+}
+
+static void m32r_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct m32r_mmc_host *host = mmc_priv(mmc);
+	u16 status;
+
+	pr_debug(DRIVER_NAME " set_ios: clock=%d, vdd=%d, bus_mode=%d, power_mode=%d\n",
+		ios->clock, ios->vdd, ios->bus_mode, ios->power_mode);
+
+	/* set power */
+	if (ios->power_mode == MMC_POWER_OFF) {
+		/* disable MMC power */
+		status = inw((unsigned int)PLD_CPCR);
+		outw(status & ~PLD_CPCR_MMC, (unsigned int)PLD_CPCR);
+		udelay(100);
+
+	} else if (ios->power_mode == MMC_POWER_UP) {
+		/* enablr MMC power */
+		status = inw((unsigned int)PLD_CPCR);
+		if ((status & PLD_CPCR_MMC) == 0) {
+			outw(status | PLD_CPCR_MMC, (unsigned int)PLD_CPCR);
+			udelay(100);
+
+			/* dummy clock 160clock */
+			m32r_mmc_set_clock(M32R_CLOCKRATE_MIN);
+			m32r_mmc_receive_dummy_data(M32R_DUMMY_CLOCK);
+		}
+	}
+
+	/* set clock */
+	if (ios->clock) {
+		host->clock = ios->clock;
+	}
+}
+
+static struct mmc_host_ops m32r_mmc_ops = {
+	.request = m32r_mmc_request,
+	.get_ro  = m32r_mmc_get_ro,
+	.set_ios = m32r_mmc_set_ios,
+};
+
+static int __devinit m32r_mmc_alloc(struct device* dev)
+{
+	struct mmc_host* mmc;
+	struct m32r_mmc_host *host;
+
+	/* allocate MMC structure */
+	mmc = mmc_alloc_host(sizeof(struct m32r_mmc_host), dev);
+	if (!mmc) {
+		printk(KERN_ERR "failed to allocate mmc host\n");
+		return -ENOMEM;
+	}
+
+	/* set host parameters */
+	mmc->ops = &m32r_mmc_ops;
+	mmc->f_min = M32R_CLOCKRATE_MIN;
+	mmc->f_max = M32R_CLOCKRATE_MAX;
+
+	mmc->max_hw_segs = 1;
+	mmc->max_phys_segs = 1;
+	mmc->max_sectors = 1;
+	mmc->max_seg_size = M32R_BLOCK_LEN;
+
+	mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->type = CT_NO_RESPONSE;
+	host->state = CS_IDLE;
+
+	host->stat_cmd = 0;
+	host->stat_recv = 0;
+	host->stat_send = 0;
+
+	dev_set_drvdata(dev, mmc);
+
+	/* register mmc host */
+	mmc_add_host(mmc);
+
+	return 0;
+}
+
+static void __devexit m32r_mmc_free(struct device* dev)
+{
+	struct mmc_host* mmc = dev_get_drvdata(dev);
+
+	if (!mmc) {
+		return;
+	}
+
+	/* remove mmc host */
+	mmc_remove_host(mmc);
+	mmc_free_host(mmc);
+
+	dev_set_drvdata(dev, NULL);
+}
+
+static int m32r_mmc_probe(struct device *dev)
+{
+	struct mmc_host *mmc;
+	struct m32r_mmc_host *host;
+	int ret;
+
+	printk(KERN_INFO DRIVER_NAME " driver\n");
+
+	/* allocate MMC structure */
+	ret = m32r_mmc_alloc(dev);
+	if (ret) {
+		return ret;
+	}
+
+	mmc = dev_get_drvdata(dev);
+	host = mmc_priv(mmc);
+
+#ifdef M32R_USE_TIMER
+	/* set up the polling timer */
+	host->poll_timer.function = m32r_mmc_polling;
+	host->poll_timer.data	  = (unsigned long)host;
+	init_timer(&host->poll_timer);
+#endif /* M32R_USE_TIMER */
+
+	/* setup card detect interrupt */
+	host->detect = inw((unsigned long)PLD_MMCDET);
+	ret = request_irq(PLD_IRQ_MMCCARD, m32r_mmc_card_irq, SA_SHIRQ, DRIVER_NAME, host);
+	if (ret) {
+		printk(KERN_ERR "failed to request M32R interrupt\n");
+		m32r_mmc_free(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int m32r_mmc_remove(struct device *dev)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct m32r_mmc_host *host;
+	u16 status;
+
+	if (mmc != NULL) {
+		host = mmc_priv(mmc);
+
+		free_irq(PLD_IRQ_MMCCARD, host);
+#ifdef M32R_USE_TIMER
+		del_timer_sync(&host->poll_timer);
+#endif /* M32R_USE_TIMER */
+
+		/* disable MMC */
+		m32r_mmc_reset();
+
+		/* power off MMC */
+		status = inw((unsigned long)PLD_CPCR);
+		outw(status & ~PLD_CPCR_MMC, (unsigned long)PLD_CPCR);
+
+		m32r_mmc_free(dev);
+
+		pr_debug(DRIVER_NAME " removed\n");
+	}
+
+	return 0;
+}
+
+static struct platform_device *m32r_mmc_device;
+
+static struct device_driver m32r_mmc_driver = {
+	.name		= DRIVER_NAME,
+	.bus		= &platform_bus_type,
+	.probe		= m32r_mmc_probe,
+	.remove 	= m32r_mmc_remove,
+};
+
+static int __init m32r_mmc_init(void)
+{
+	int result;
+
+	result = driver_register(&m32r_mmc_driver);
+	if (result < 0) {
+		return result;
+	}
+
+	m32r_mmc_device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
+	if (IS_ERR(m32r_mmc_device)) {
+		return PTR_ERR(m32r_mmc_device);
+	}
+
+	return 0;
+}
+
+static void __exit m32r_mmc_exit(void)
+{
+	platform_device_unregister(m32r_mmc_device);
+	driver_unregister(&m32r_mmc_driver);
+}
+
+module_init(m32r_mmc_init);
+module_exit(m32r_mmc_exit);
+
+MODULE_DESCRIPTION("M32R MMC Card Interface Driver");
+MODULE_LICENSE("GPL");
diff -Naru linux-2.6.14.6-20060127.org/drivers/mmc/m32r_mmc.h linux-2.6.14.6-20060127/drivers/mmc/m32r_mmc.h
--- linux-2.6.14.6-20060127.org/drivers/mmc/m32r_mmc.h	1970-01-01 07:00:00.000000000 +0700
+++ linux-2.6.14.6-20060127/drivers/mmc/m32r_mmc.h	2006-09-27 12:22:20.000000000 +0900
@@ -0,0 +1,104 @@
+/*
+ * linux/drivers/mmc/m32r_mmc.h - MMC driver for M32R evaluation boards
+ *
+ * Copyright (C) 2006	Renesas Technology Corp. and Renesas Solutions Corp.
+ *
+ * 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 M32RMMC_H
+#define M32RMMC_H
+
+/* polling mode */
+#define M32R_USE_TIMER
+
+/* PLD_MMCCR bit */
+#define M32R_MMC_CLR		0x0100		/* 1: init mmc */
+#define M32R_MMC_CMDEN		0x0002		/* write: 0: N/A
+							  1: start command transfer
+						   read:  0: idle
+							  1: command transfer busy */
+#define M32R_MMC_DTEN		0x0001		/* write: 0: N/A
+							  1: start data transfer
+						    read: 0: idle
+							  1: data transfer busy */
+
+/* PLD_MMCMOD bit */
+#define M32R_MMC_DMY		0x0100		/* 1: send dummy clock	*/
+#define M32R_MMC_DSEL		0x0001		/* 0: receive data
+						   1: send data */
+
+#define M32R_MMC_MMCWP		0x0001		/* write protect bit */
+
+/* PLD_MMCSTS */
+/* PLD_MMCBAUR */
+
+/* the constant depending on a driver */
+#define M32R_BLOCK_LEN		512		/* block size */
+
+#define M32R_CLOCKRATE_MIN	370000		/* minimum baud rate for cmd */
+#define M32R_CLOCKRATE_MAX	20000000	/* maximum baud rate for data */
+
+#define M32R_POLL_INTERVAL	((5 * HZ)/1000) /* command polling interval */
+#ifdef	M32R_USE_TIMER
+#define M32R_CMD_TIMEOUT	25		/* command timeout count */
+#define M32R_DATA_TIMEOUT	25		/* data timeout count */
+#else
+#define M32R_CMD_TIMEOUT	2500		/* command timeout count */
+#define M32R_DATA_TIMEOUT	2500		/* data timeout count */
+#endif	/* M32R_USE_TIMER */
+
+#define M32R_DUMMY_CLOCK	(160/16)	/* dummy clock = 160clock (provisional) */
+
+enum M32R_CMD_TYPE {
+	CT_NO_RESPONSE,
+	CT_RESPONSE_ONLY,
+	CT_READ,
+	CT_WRITE
+};
+
+enum M32R_CMD_STATE {
+	CS_IDLE,
+	CS_START_CMD,
+	CS_START_READ,
+	CS_START_WRITE,
+};
+
+struct m32r_mmc_host {
+	/* host information */
+	struct mmc_host 	*mmc;
+	struct timer_list	poll_timer;
+
+	/* current status */
+	u32			clock;		/* current clock frequency */
+	int			detect; 	/* current card detect status */
+
+	/* cmd status */
+	struct mmc_request*	mrq;		/* current request */
+
+	enum M32R_CMD_TYPE	type;		/* command type */
+	enum M32R_CMD_STATE	state;		/* command state */
+
+	u16			cmd;		/* command code */
+	u32			arg;		/* command argument */
+	int			offset;
+	int			timeout_tick;	/* polling timeout counter */
+
+	/* data */
+	int			sg_index;	/* currect segment index */
+	int			buff_pos;	/* currect position */
+	int			eob;		/* end of buffer */
+
+	u8			res_buff[18];	/* buffer for store response */
+	int			res_len;	/* response length */
+
+	/* statistics */
+	unsigned int		stat_cmd;
+	unsigned int		stat_recv;
+	unsigned int		stat_send;
+	unsigned long		start;
+};
+
+#endif /* M32RMMC_H */
