diff --git a/common/Makefile b/common/Makefile
index eb8e283a6dda2d10c3c556ed369bcde736178429..9a71302f996714d48b0e1a49fb4c84fb83f7a271 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -53,6 +53,7 @@ COBJS-$(CONFIG_ENV_IS_IN_DATAFLASH) += env_dataflash.o
 COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += env_eeprom.o
 COBJS-y += env_embedded.o
 COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
+COBJS-$(CONFIG_ENV_IS_IN_MG_DISK) += env_mgdisk.o
 COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
 COBJS-$(CONFIG_ENV_IS_IN_NVRAM) += env_nvram.o
 COBJS-$(CONFIG_ENV_IS_IN_ONENAND) += env_onenand.o
@@ -104,6 +105,7 @@ COBJS-$(CONFIG_LOGBUFFER) += cmd_log.o
 COBJS-$(CONFIG_ID_EEPROM) += cmd_mac.o
 COBJS-$(CONFIG_CMD_MEMORY) += cmd_mem.o
 COBJS-$(CONFIG_CMD_MFSL) += cmd_mfsl.o
+COBJS-$(CONFIG_CMD_MG_DISK) += cmd_mgdisk.o
 COBJS-$(CONFIG_MII) += miiphyutil.o
 COBJS-$(CONFIG_CMD_MII) += miiphyutil.o
 COBJS-$(CONFIG_CMD_MII) += cmd_mii.o
diff --git a/common/cmd_mgdisk.c b/common/cmd_mgdisk.c
new file mode 100644
index 0000000000000000000000000000000000000000..48323d45befbc69c367631141d95c1f9f582f7dd
--- /dev/null
+++ b/common/cmd_mgdisk.c
@@ -0,0 +1,76 @@
+/*
+ * (C) Copyright 2009 mGine co.
+ * unsik Kim <donari75@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+
+#if defined (CONFIG_CMD_MG_DISK)
+
+#include <mg_disk.h>
+
+int do_mg_disk_cmd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	u32 from, to, size;
+
+	switch (argc) {
+	case 2:
+		if (!strcmp(argv[1], "init"))
+			mg_disk_init();
+		else
+			return 1;
+		break;
+	case 5:
+		from = simple_strtoul(argv[2], NULL, 0);
+		to = simple_strtoul(argv[3], NULL, 0);
+		size = simple_strtoul(argv[4], NULL, 0);
+
+		if (!strcmp(argv[1], "read"))
+			mg_disk_read(from, (u8 *)to, size);
+		else if (!strcmp(argv[1], "write"))
+			mg_disk_write(to, (u8 *)from, size);
+		else if (!strcmp(argv[1], "readsec"))
+			mg_disk_read_sects((void *)to, from, size);
+		else if (!strcmp(argv[1], "writesec"))
+			mg_disk_write_sects((void *)from, to, size);
+		else
+			return 1;
+		break;
+	default:
+		printf("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+	return 0;
+}
+
+U_BOOT_CMD(
+	mgd,	5,	0,	do_mg_disk_cmd,
+	"mgd     - mgine m[g]flash command\n",
+	": mgine mflash IO mode (disk) command\n"
+	"    - initialize : mgd init\n"
+	"    - random read : mgd read [from] [to] [size]\n"
+	"    - random write : mgd write [from] [to] [size]\n"
+	"    - sector read : mgd readsec [sector] [to] [counts]\n"
+	"    - sector write : mgd writesec [from] [sector] [counts]\n"
+);
+
+#endif
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 95eebb57646735ed8f0d59491ff59003720c9bbd..163765a8a0b29cf6803f84b1d90ec758f5f77cfc 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -52,15 +52,17 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if !defined(CONFIG_ENV_IS_IN_NVRAM)	&& \
-    !defined(CONFIG_ENV_IS_IN_EEPROM)	&& \
+#if !defined(CONFIG_ENV_IS_IN_EEPROM)	&& \
     !defined(CONFIG_ENV_IS_IN_FLASH)	&& \
     !defined(CONFIG_ENV_IS_IN_DATAFLASH)	&& \
+    !defined(CONFIG_ENV_IS_IN_MG_DISK)	&& \
     !defined(CONFIG_ENV_IS_IN_NAND)	&& \
+    !defined(CONFIG_ENV_IS_IN_NVRAM)	&& \
     !defined(CONFIG_ENV_IS_IN_ONENAND)	&& \
     !defined(CONFIG_ENV_IS_IN_SPI_FLASH)	&& \
     !defined(CONFIG_ENV_IS_NOWHERE)
-# error Define one of CONFIG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|ONENAND|SPI_FLASH|NOWHERE}
+# error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|DATAFLASH|ONENAND|\
+SPI_FLASH|MG_DISK|NVRAM|NOWHERE}
 #endif
 
 #define XMK_STR(x)	#x
diff --git a/common/env_mgdisk.c b/common/env_mgdisk.c
new file mode 100644
index 0000000000000000000000000000000000000000..363ee68c27e83d3ac397f1120f69483ea8f027e4
--- /dev/null
+++ b/common/env_mgdisk.c
@@ -0,0 +1,92 @@
+/*
+ * (C) Copyright 2009 mGine co.
+ * unsik Kim <donari75@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <environment.h>
+#include <linux/stddef.h>
+#include <mg_disk.h>
+
+/* references to names in env_common.c */
+extern uchar default_environment[];
+extern int default_environment_size;
+
+char * env_name_spec = "MG_DISK";
+
+env_t *env_ptr = 0;
+
+DECLARE_GLOBAL_DATA_PTR;
+
+uchar env_get_char_spec(int index)
+{
+	return (*((uchar *) (gd->env_addr + index)));
+}
+
+void env_relocate_spec(void)
+{
+	unsigned int err;
+
+	err = mg_disk_init();
+	if (err) {
+		puts ("*** Warning - mg_disk_init error");
+		goto OUT;
+	}
+	err = mg_disk_read(CONFIG_ENV_ADDR, (u_char *)env_ptr, CONFIG_ENV_SIZE);
+	if (err) {
+		puts ("*** Warning - mg_disk_read error");
+		goto OUT;
+	}
+
+	if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) {
+		puts ("*** Warning - CRC error");
+		goto OUT;
+	}
+
+	return;
+
+OUT:
+	printf (", using default environment\n\n");
+	set_default_env();
+}
+
+int saveenv(void)
+{
+	unsigned int err;
+
+	env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE);
+	err = mg_disk_write(CONFIG_ENV_ADDR, (u_char *)env_ptr,
+			CONFIG_ENV_SIZE);
+	if (err)
+		puts ("*** Warning - mg_disk_write error\n\n");
+
+	return err;
+}
+
+int env_init(void)
+{
+	/* use default */
+	gd->env_addr = (ulong) & default_environment[0];
+	gd->env_valid = 1;
+
+	return 0;
+}
diff --git a/disk/part.c b/disk/part.c
index fdc49d339c1952d002cad1f89f591f7cd84178b4..c7774930b8499d2d1f3d83b17484cccddc25b404 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -35,6 +35,7 @@
 #endif
 
 #if (defined(CONFIG_CMD_IDE) || \
+     defined(CONFIG_CMD_MG_DISK) || \
      defined(CONFIG_CMD_SATA) || \
      defined(CONFIG_CMD_SCSI) || \
      defined(CONFIG_CMD_USB) || \
@@ -64,6 +65,9 @@ static const struct block_drvr block_drvr[] = {
 #endif
 #if defined(CONFIG_SYSTEMACE)
 	{ .name = "ace", .get_dev = systemace_get_dev, },
+#endif
+#if defined(CONFIG_CMD_MG_DISK)
+	{ .name = "mgd", .get_dev = mg_disk_get_dev, },
 #endif
 	{ },
 };
@@ -91,6 +95,7 @@ block_dev_desc_t *get_dev(char* ifname, int dev)
 #endif
 
 #if (defined(CONFIG_CMD_IDE) || \
+     defined(CONFIG_CMD_MG_DISK) || \
      defined(CONFIG_CMD_SATA) || \
      defined(CONFIG_CMD_SCSI) || \
      defined(CONFIG_CMD_USB) || \
@@ -203,11 +208,12 @@ void dev_print (block_dev_desc_t *dev_desc)
 #endif
 
 #if (defined(CONFIG_CMD_IDE) || \
+     defined(CONFIG_CMD_MG_DISK) || \
      defined(CONFIG_CMD_SATA) || \
      defined(CONFIG_CMD_SCSI) || \
      defined(CONFIG_CMD_USB) || \
      defined(CONFIG_MMC)		|| \
-     defined(CONFIG_SYSTEMACE)          )
+     defined(CONFIG_SYSTEMACE) )
 
 #if defined(CONFIG_MAC_PARTITION) || \
     defined(CONFIG_DOS_PARTITION) || \
diff --git a/disk/part_amiga.c b/disk/part_amiga.c
index c2daf6a6008910bba7eaf23296b1ee6bf96bc663..50efe39b1b28ad6a532dfbbecfc0b36c24fbcd46 100644
--- a/disk/part_amiga.c
+++ b/disk/part_amiga.c
@@ -27,6 +27,7 @@
 #include "part_amiga.h"
 
 #if defined(CONFIG_CMD_IDE) || \
+    defined(CONFIG_CMD_MG_DISK) || \
     defined(CONFIG_CMD_SCSI) || \
     defined(CONFIG_CMD_USB) || \
     defined(CONFIG_MMC) || \
@@ -154,7 +155,7 @@ struct rigid_disk_block *get_rdisk(block_dev_desc_t *dev_desc)
 
     s = getenv("amiga_scanlimit");
     if (s)
-	limit = atoi(s);
+	limit = simple_strtoul(s, NULL, 10);
     else
 	limit = AMIGA_BLOCK_LIMIT;
 
@@ -195,7 +196,7 @@ struct bootcode_block *get_bootcode(block_dev_desc_t *dev_desc)
 
     s = getenv("amiga_scanlimit");
     if (s)
-	limit = atoi(s);
+	limit = simple_strtoul(s, NULL, 10);
     else
 	limit = AMIGA_BLOCK_LIMIT;
 
diff --git a/disk/part_dos.c b/disk/part_dos.c
index 4ab0b40601ea35bc5310a70e1160122b83f18e0c..93bf3dd4ea9d98028512829ddb7eaf287863a7ad 100644
--- a/disk/part_dos.c
+++ b/disk/part_dos.c
@@ -36,6 +36,7 @@
 #include "part_dos.h"
 
 #if defined(CONFIG_CMD_IDE) || \
+    defined(CONFIG_CMD_MG_DISK) || \
     defined(CONFIG_CMD_SATA) || \
     defined(CONFIG_CMD_SCSI) || \
     defined(CONFIG_CMD_USB) || \
diff --git a/disk/part_efi.c b/disk/part_efi.c
index 70f62cc9afe03ed02b84228acf53233baa3a0632..626f022f9d588330c22532d2302fbeb790fe6310 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -37,6 +37,7 @@
 #include "part_efi.h"
 
 #if defined(CONFIG_CMD_IDE) || \
+    defined(CONFIG_CMD_MG_DISK) || \
     defined(CONFIG_CMD_SATA) || \
     defined(CONFIG_CMD_SCSI) || \
     defined(CONFIG_CMD_USB) || \
diff --git a/disk/part_iso.c b/disk/part_iso.c
index 719b9495c82bb6873a8f9fa6784e757b6cc34c5a..8fe6148c21854ef6d5a0a3ae48da3b89185bdccd 100644
--- a/disk/part_iso.c
+++ b/disk/part_iso.c
@@ -26,6 +26,7 @@
 #include "part_iso.h"
 
 #if defined(CONFIG_CMD_IDE) || \
+    defined(CONFIG_CMD_MG_DISK) || \
     defined(CONFIG_CMD_SCSI) || \
     defined(CONFIG_CMD_SATA) || \
     defined(CONFIG_CMD_USB) || \
diff --git a/disk/part_mac.c b/disk/part_mac.c
index c1afc8c20aca1e99b1771e3732cd1c97925f9d5d..bebe415d6290e8b90f4f066e5402985bc7682312 100644
--- a/disk/part_mac.c
+++ b/disk/part_mac.c
@@ -35,6 +35,7 @@
 #include "part_mac.h"
 
 #if defined(CONFIG_CMD_IDE) || \
+    defined(CONFIG_CMD_MG_DISK) || \
     defined(CONFIG_CMD_SCSI) || \
     defined(CONFIG_CMD_SATA) || \
     defined(CONFIG_CMD_USB) || \
diff --git a/doc/README.mflash b/doc/README.mflash
new file mode 100644
index 0000000000000000000000000000000000000000..50133b461f9814e871219182a70e1ab50b625d99
--- /dev/null
+++ b/doc/README.mflash
@@ -0,0 +1,94 @@
+
+This document describes m[g]flash support in u-boot.
+
+Contents
+  1. Overview
+  2. Porting mflash driver
+  3. Mflash command
+  4. Misc.
+
+1. Overview
+Mflash and gflash are embedded flash drive. The only difference is mflash is
+MCP(Multi Chip Package) device. These two device operate exactly same way.
+So the rest mflash repersents mflash and gflash altogether.
+
+2. Porting mflash driver
+
+2-1. Board configuration
+* Mflash driver support
+#define CONFIG_CMD_MG_DISK
+#define CONFIG_LIBATA
+
+* Environment variable support (optional)
+#define CONFIG_ENV_IS_IN_MG_DISK
+Also CONFIG_ENV_ADDR and CONFIG_ENV_SIZE should be defined.
+CONFIG_ENV_ADDR is byte offset starting from 0.
+
+Following example sets environment variable location to 0x80000 (1024'th
+sector) and size of 0x400 (1024 byte)
+#define CONFIG_ENV_ADDR		0x80000
+#define CONFIG_ENV_SIZE		0x400
+
+* Reserved size config (optional)
+If you want to use some reserved area for bootloader, environment variable or
+whatever, use CONFIG_MG_DISK_RES. The unit is KB. Mflash's block operation
+method use this value as start offset. So any u-boot's partition table parser
+and file system command work consistently. You can access this area by using
+mflash command.
+
+Following example sets 10MB of reserved area.
+#define CONFIG_MG_DISK_RES	10240
+
+2-2. Porting mg_get_drv_data function
+Mflash is active device and need some gpio control for proper operation.
+This board dependency resolved by using mg_get_drv_data function.
+Port this function at your board init file. See include/mg_disk.h
+
+Here is some pseudo example.
+
+static void custom_hdrst_pin (u8 level)
+{
+	if (level)
+		/* set hard reset pin to high */
+	else
+		/* set hard reset pin to low */
+}
+
+static void custom_ctrl_pin_init (void)
+{
+	/* Set hard reset, write protect, deep power down pins
+	 * to gpio.
+	 * Set these pins to output high
+	 */
+}
+
+struct mg_drv_data* mg_get_drv_data (void)
+{
+	static struct mg_drv_data prv;
+
+	prv.base = /* base address of mflash */
+	prv.mg_ctrl_pin_init = custom_ctrl_pin_init;
+	prv.mg_hdrst_pin = custom_hdrst_pin;
+
+	return &prv;
+}
+
+3. Mflash command
+
+* initialize : mgd init
+* random read : mgd read [from] [to] [size]
+  ex) read 256 bytes from 0x300000 of mflash to 0xA0100000 of host memory
+      mgd read 0x300000 0xA0100000 256
+* random write : mgd write [from] [to] [size]
+* sector read : mgd readsec [sector] [to] [count]
+  ex) read 10 sectors starts from 400 sector to 0xA0100000
+      mgd readsec 400 0xA0100000 10
+* sector write : mgd writesec [from] [sector] [count]
+
+4. Misc.
+Mflash's device interface name for block driver is "mgd".
+Here is ext2 file system access example.
+
+ mgd init
+ ext2ls mgd 0:1 /boot
+ ext2load mgd 0:1 0xa0010000 /boot/uImage 1954156
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 59388d9d452fc8e393c1f5c70c4162bed1be4b9a..eccefc1e52545617558be02a7abbb2c756be9bd9 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -25,13 +25,14 @@ include $(TOPDIR)/config.mk
 
 LIB	:= $(obj)libblock.a
 
-COBJS-$(CONFIG_SCSI_AHCI) += ahci.o
 COBJS-$(CONFIG_ATA_PIIX) += ata_piix.o
+COBJS-$(CONFIG_CMD_MG_DISK) += mg_disk.o
 COBJS-$(CONFIG_FSL_SATA) += fsl_sata.o
+COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_LIBATA) += libata.o
 COBJS-$(CONFIG_PATA_BFIN) += pata_bfin.o
 COBJS-$(CONFIG_SATA_SIL3114) += sata_sil3114.o
-COBJS-$(CONFIG_IDE_SIL680) += sil680.o
+COBJS-$(CONFIG_SCSI_AHCI) += ahci.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
 
diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c
new file mode 100644
index 0000000000000000000000000000000000000000..b74307ab6c49704c473c4ee44ca4b2d0917cda80
--- /dev/null
+++ b/drivers/block/mg_disk.c
@@ -0,0 +1,582 @@
+/*
+ * (C) Copyright 2009 mGine co.
+ * unsik Kim <donari75@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <part.h>
+#include <ata.h>
+#include <asm/io.h>
+#include "mg_disk_prv.h"
+
+#ifndef CONFIG_MG_DISK_RES
+#define CONFIG_MG_DISK_RES	0
+#endif
+
+#define MG_RES_SEC ((CONFIG_MG_DISK_RES) << 1)
+
+static struct mg_host host;
+
+static inline u32 mg_base(void)
+{
+	return host.drv_data->base;
+}
+
+static block_dev_desc_t mg_disk_dev = {
+	.if_type = IF_TYPE_ATAPI,
+	.part_type = PART_TYPE_UNKNOWN,
+	.type = DEV_TYPE_HARDDISK,
+	.blksz = MG_SECTOR_SIZE,
+	.priv = &host };
+
+static void mg_dump_status (const char *msg, unsigned int stat, unsigned err)
+{
+	char *name = MG_DEV_NAME;
+
+	printf("%s: %s: status=0x%02x { ", name, msg, stat & 0xff);
+	if (stat & MG_REG_STATUS_BIT_BUSY)
+		printf("Busy ");
+	if (stat & MG_REG_STATUS_BIT_READY)
+		printf("DriveReady ");
+	if (stat & MG_REG_STATUS_BIT_WRITE_FAULT)
+		printf("WriteFault ");
+	if (stat & MG_REG_STATUS_BIT_SEEK_DONE)
+		printf("SeekComplete ");
+	if (stat & MG_REG_STATUS_BIT_DATA_REQ)
+		printf("DataRequest ");
+	if (stat & MG_REG_STATUS_BIT_CORRECTED_ERROR)
+		printf("CorrectedError ");
+	if (stat & MG_REG_STATUS_BIT_ERROR)
+		printf("Error ");
+	printf("}\n");
+
+	if ((stat & MG_REG_STATUS_BIT_ERROR)) {
+		printf("%s: %s: error=0x%02x { ", name, msg, err & 0xff);
+		if (err & MG_REG_ERR_BBK)
+			printf("BadSector ");
+		if (err & MG_REG_ERR_UNC)
+			printf("UncorrectableError ");
+		if (err & MG_REG_ERR_IDNF)
+			printf("SectorIdNotFound ");
+		if (err & MG_REG_ERR_ABRT)
+			printf("DriveStatusError ");
+		if (err & MG_REG_ERR_AMNF)
+			printf("AddrMarkNotFound ");
+		printf("}\n");
+	}
+}
+
+static unsigned int mg_wait (u32 expect, u32 msec)
+{
+	u8 status;
+	u32 from, cur, err;
+
+	err = MG_ERR_NONE;
+	reset_timer();
+	from = get_timer(0);
+
+	status = readb(mg_base() + MG_REG_STATUS);
+	do {
+		cur = get_timer(from);
+		if (status & MG_REG_STATUS_BIT_BUSY) {
+			if (expect == MG_REG_STATUS_BIT_BUSY)
+				break;
+		} else {
+			/* Check the error condition! */
+			if (status & MG_REG_STATUS_BIT_ERROR) {
+				err = readb(mg_base() + MG_REG_ERROR);
+				mg_dump_status("mg_wait", status, err);
+				break;
+			}
+
+			if (expect == MG_STAT_READY)
+				if (MG_READY_OK(status))
+					break;
+
+			if (expect == MG_REG_STATUS_BIT_DATA_REQ)
+				if (status & MG_REG_STATUS_BIT_DATA_REQ)
+					break;
+		}
+		status = readb(mg_base() + MG_REG_STATUS);
+	} while (cur < msec);
+
+	if (cur >= msec)
+		err = MG_ERR_TIMEOUT;
+
+	return err;
+}
+
+static int mg_get_disk_id (void)
+{
+	u16 id[(MG_SECTOR_SIZE / sizeof(u16))];
+	hd_driveid_t *iop = (hd_driveid_t *)id;
+	u32 i, err, res;
+
+	writeb(MG_CMD_ID, mg_base() + MG_REG_COMMAND);
+	err = mg_wait(MG_REG_STATUS_BIT_DATA_REQ, 3000);
+	if (err)
+		return err;
+
+	for(i = 0; i < (MG_SECTOR_SIZE / sizeof(u16)); i++)
+		id[i] = readw(mg_base() + MG_BUFF_OFFSET + i * 2);
+
+	writeb(MG_CMD_RD_CONF, mg_base() + MG_REG_COMMAND);
+	err = mg_wait(MG_STAT_READY, 3000);
+	if (err)
+		return err;
+
+	ata_swap_buf_le16(id, MG_SECTOR_SIZE / sizeof(u16));
+
+	if((iop->field_valid & 1) == 0)
+		return MG_ERR_TRANSLATION;
+
+	ata_id_c_string(id, (unsigned char *)mg_disk_dev.revision,
+			ATA_ID_FW_REV, sizeof(mg_disk_dev.revision));
+	ata_id_c_string(id, (unsigned char *)mg_disk_dev.vendor,
+			ATA_ID_PROD, sizeof(mg_disk_dev.vendor));
+	ata_id_c_string(id, (unsigned char *)mg_disk_dev.product,
+			ATA_ID_SERNO, sizeof(mg_disk_dev.product));
+
+#ifdef __BIG_ENDIAN
+	iop->lba_capacity = (iop->lba_capacity << 16) |
+		(iop->lba_capacity >> 16);
+#endif /* __BIG_ENDIAN */
+
+	if (MG_RES_SEC) {
+		MG_DBG("MG_RES_SEC=%d\n", MG_RES_SEC);
+		iop->cyls = (iop->lba_capacity - MG_RES_SEC) /
+			iop->sectors / iop->heads;
+		res = iop->lba_capacity -
+			iop->cyls * iop->heads * iop->sectors;
+		iop->lba_capacity -= res;
+		printf("mg_disk: %d sectors reserved\n", res);
+	}
+
+	mg_disk_dev.lba = iop->lba_capacity;
+	return MG_ERR_NONE;
+}
+
+static int mg_disk_reset (void)
+{
+	struct mg_drv_data *prv_data = host.drv_data;
+	s32 err;
+	u8 init_status;
+
+	/* hdd rst low */
+	prv_data->mg_hdrst_pin(0);
+	err = mg_wait(MG_REG_STATUS_BIT_BUSY, 300);
+	if(err)
+		return err;
+
+	/* hdd rst high */
+	prv_data->mg_hdrst_pin(1);
+	err = mg_wait(MG_STAT_READY, 3000);
+	if(err)
+		return err;
+
+	/* soft reset on */
+	writeb(MG_REG_CTRL_RESET | MG_REG_CTRL_INTR_DISABLE,
+		mg_base() + MG_REG_DRV_CTRL);
+	err = mg_wait(MG_REG_STATUS_BIT_BUSY, 3000);
+	if(err)
+		return err;
+
+	/* soft reset off */
+	writeb(MG_REG_CTRL_INTR_DISABLE, mg_base() + MG_REG_DRV_CTRL);
+	err = mg_wait(MG_STAT_READY, 3000);
+	if(err)
+		return err;
+
+	init_status = readb(mg_base() + MG_REG_STATUS) & 0xf;
+
+	if (init_status == 0xf)
+		return MG_ERR_INIT_STAT;
+
+	return err;
+}
+
+
+static unsigned int mg_out(unsigned int sect_num,
+			unsigned int sect_cnt,
+			unsigned int cmd)
+{
+	u32 err = MG_ERR_NONE;
+
+	err = mg_wait(MG_STAT_READY, 3000);
+	if (err)
+		return err;
+
+	writeb((u8)sect_cnt, mg_base() + MG_REG_SECT_CNT);
+	writeb((u8)sect_num, mg_base() + MG_REG_SECT_NUM);
+	writeb((u8)(sect_num >> 8), mg_base() + MG_REG_CYL_LOW);
+	writeb((u8)(sect_num >> 16), mg_base() + MG_REG_CYL_HIGH);
+	writeb((u8)((sect_num >> 24) | MG_REG_HEAD_LBA_MODE),
+		mg_base() + MG_REG_DRV_HEAD);
+	writeb(cmd, mg_base() + MG_REG_COMMAND);
+
+	return err;
+}
+
+static unsigned int mg_do_read_sects(void *buff, u32 sect_num, u32 sect_cnt)
+{
+	u32 i, j, err;
+	u8 *buff_ptr = buff;
+	union mg_uniwb uniwb;
+
+	err = mg_out(sect_num, sect_cnt, MG_CMD_RD);
+	if (err)
+		return err;
+
+	for (i = 0; i < sect_cnt; i++) {
+		err = mg_wait(MG_REG_STATUS_BIT_DATA_REQ, 3000);
+		if (err)
+			return err;
+
+		if ((u32)buff_ptr & 1) {
+			for (j = 0; j < MG_SECTOR_SIZE >> 1; j++) {
+				uniwb.w = readw(mg_base() + MG_BUFF_OFFSET
+						+ (j << 1));
+				*buff_ptr++ = uniwb.b[0];
+				*buff_ptr++ = uniwb.b[1];
+			}
+		} else {
+			for(j = 0; j < MG_SECTOR_SIZE >> 1; j++) {
+				*(u16 *)buff_ptr = readw(mg_base() +
+						MG_BUFF_OFFSET + (j << 1));
+				buff_ptr += 2;
+			}
+		}
+		writeb(MG_CMD_RD_CONF, mg_base() + MG_REG_COMMAND);
+
+		MG_DBG("%u (0x%8.8x) sector read", sect_num + i,
+			(sect_num + i) * MG_SECTOR_SIZE);
+	}
+
+	return err;
+}
+
+unsigned int mg_disk_read_sects(void *buff, u32 sect_num, u32 sect_cnt)
+{
+	u32 quotient, residue, i, err;
+	u8 *buff_ptr = buff;
+
+	quotient = sect_cnt >> 8;
+	residue = sect_cnt % 256;
+
+	for (i = 0; i < quotient; i++) {
+		MG_DBG("sect num : %u buff : 0x%8.8x", sect_num, (u32)buff_ptr);
+		err = mg_do_read_sects(buff_ptr, sect_num, 256);
+		if (err)
+			return err;
+		sect_num += 256;
+		buff_ptr += 256 * MG_SECTOR_SIZE;
+	}
+
+	if (residue) {
+		MG_DBG("sect num : %u buff : %8.8x", sect_num, (u32)buff_ptr);
+		err = mg_do_read_sects(buff_ptr, sect_num, residue);
+	}
+
+	return err;
+}
+
+unsigned long mg_block_read (int dev, unsigned long start,
+		lbaint_t blkcnt, void *buffer)
+{
+	start += MG_RES_SEC;
+	if (! mg_disk_read_sects(buffer, start, blkcnt))
+		return blkcnt;
+	else
+		return 0;
+}
+
+unsigned int mg_disk_read (u32 addr, u8 *buff, u32 len)
+{
+	u8 *sect_buff, *buff_ptr = buff;
+	u32 cur_addr, next_sec_addr, end_addr, cnt, sect_num;
+	u32 err = MG_ERR_NONE;
+
+	/* TODO : sanity chk */
+	cnt = 0;
+	cur_addr = addr;
+	end_addr = addr + len;
+
+	sect_buff = malloc(MG_SECTOR_SIZE);
+
+	if (cur_addr & MG_SECTOR_SIZE_MASK) {
+		next_sec_addr = (cur_addr + MG_SECTOR_SIZE) &
+				~MG_SECTOR_SIZE_MASK;
+		sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT;
+		err = mg_disk_read_sects(sect_buff, sect_num, 1);
+		if (err)
+			goto mg_read_exit;
+
+		if (end_addr < next_sec_addr) {
+			memcpy(buff_ptr,
+				sect_buff + (cur_addr & MG_SECTOR_SIZE_MASK),
+				end_addr - cur_addr);
+			MG_DBG("copies %u byte from sector offset 0x%8.8x",
+				end_addr - cur_addr, cur_addr);
+			cur_addr = end_addr;
+		} else {
+			memcpy(buff_ptr,
+				sect_buff + (cur_addr & MG_SECTOR_SIZE_MASK),
+				next_sec_addr - cur_addr);
+			MG_DBG("copies %u byte from sector offset 0x%8.8x",
+				next_sec_addr - cur_addr, cur_addr);
+			buff_ptr += (next_sec_addr - cur_addr);
+			cur_addr = next_sec_addr;
+		}
+	}
+
+	if (cur_addr < end_addr) {
+		sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT;
+		cnt = ((end_addr & ~MG_SECTOR_SIZE_MASK) - cur_addr) >>
+			MG_SECTOR_SIZE_SHIFT;
+
+		if (cnt)
+			err = mg_disk_read_sects(buff_ptr, sect_num, cnt);
+		if (err)
+			goto mg_read_exit;
+
+		buff_ptr += cnt * MG_SECTOR_SIZE;
+		cur_addr += cnt * MG_SECTOR_SIZE;
+
+		if (cur_addr < end_addr) {
+			sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT;
+			err = mg_disk_read_sects(sect_buff, sect_num, 1);
+			if (err)
+				goto mg_read_exit;
+			memcpy(buff_ptr, sect_buff, end_addr - cur_addr);
+			MG_DBG("copies %u byte", end_addr - cur_addr);
+		}
+	}
+
+mg_read_exit:
+	free(sect_buff);
+
+	return err;
+}
+static int mg_do_write_sects(void *buff, u32 sect_num, u32 sect_cnt)
+{
+	u32 i, j, err;
+	u8 *buff_ptr = buff;
+	union mg_uniwb uniwb;
+
+	err = mg_out(sect_num, sect_cnt, MG_CMD_WR);
+	if (err)
+		return err;
+
+	for (i = 0; i < sect_cnt; i++) {
+		err = mg_wait(MG_REG_STATUS_BIT_DATA_REQ, 3000);
+		if (err)
+			return err;
+
+		if ((u32)buff_ptr & 1) {
+			uniwb.b[0] = *buff_ptr++;
+			uniwb.b[1] = *buff_ptr++;
+			writew(uniwb.w, mg_base() + MG_BUFF_OFFSET + (j << 1));
+		} else {
+			for(j = 0; j < MG_SECTOR_SIZE >> 1; j++) {
+				writew(*(u16 *)buff_ptr,
+						mg_base() + MG_BUFF_OFFSET +
+						(j << 1));
+				buff_ptr += 2;
+			}
+		}
+		writeb(MG_CMD_WR_CONF, mg_base() + MG_REG_COMMAND);
+
+		MG_DBG("%u (0x%8.8x) sector write",
+			sect_num + i, (sect_num + i) * MG_SECTOR_SIZE);
+	}
+
+	return err;
+}
+
+unsigned int mg_disk_write_sects(void *buff, u32 sect_num, u32 sect_cnt)
+{
+	u32 quotient, residue, i;
+	u32 err = MG_ERR_NONE;
+	u8 *buff_ptr = buff;
+
+	quotient = sect_cnt >> 8;
+	residue = sect_cnt % 256;
+
+	for (i = 0; i < quotient; i++) {
+		MG_DBG("sect num : %u buff : %8.8x", sect_num, (u32)buff_ptr);
+		err = mg_do_write_sects(buff_ptr, sect_num, 256);
+		if (err)
+			return err;
+		sect_num += 256;
+		buff_ptr += 256 * MG_SECTOR_SIZE;
+	}
+
+	if (residue) {
+		MG_DBG("sect num : %u buff : %8.8x", sect_num, (u32)buff_ptr);
+		err = mg_do_write_sects(buff_ptr, sect_num, residue);
+	}
+
+	return err;
+}
+
+unsigned long mg_block_write (int dev, unsigned long start,
+		lbaint_t blkcnt, const void *buffer)
+{
+	start += MG_RES_SEC;
+	if (!mg_disk_write_sects((void *)buffer, start, blkcnt))
+		return blkcnt;
+	else
+		return 0;
+}
+
+unsigned int mg_disk_write(u32 addr, u8 *buff, u32 len)
+{
+	u8 *sect_buff, *buff_ptr = buff;
+	u32 cur_addr, next_sec_addr, end_addr, cnt, sect_num;
+	u32 err = MG_ERR_NONE;
+
+	/* TODO : sanity chk */
+	cnt = 0;
+	cur_addr = addr;
+	end_addr = addr + len;
+
+	sect_buff = malloc(MG_SECTOR_SIZE);
+
+	if (cur_addr & MG_SECTOR_SIZE_MASK) {
+
+		next_sec_addr = (cur_addr + MG_SECTOR_SIZE) &
+				~MG_SECTOR_SIZE_MASK;
+		sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT;
+		err = mg_disk_read_sects(sect_buff, sect_num, 1);
+		if (err)
+			goto mg_write_exit;
+
+		if (end_addr < next_sec_addr) {
+			memcpy(sect_buff + (cur_addr & MG_SECTOR_SIZE_MASK),
+				buff_ptr, end_addr - cur_addr);
+			MG_DBG("copies %u byte to sector offset 0x%8.8x",
+				end_addr - cur_addr, cur_addr);
+			cur_addr = end_addr;
+		} else {
+			memcpy(sect_buff + (cur_addr & MG_SECTOR_SIZE_MASK),
+				buff_ptr, next_sec_addr - cur_addr);
+			MG_DBG("copies %u byte to sector offset 0x%8.8x",
+				next_sec_addr - cur_addr, cur_addr);
+			buff_ptr += (next_sec_addr - cur_addr);
+			cur_addr = next_sec_addr;
+		}
+
+		err = mg_disk_write_sects(sect_buff, sect_num, 1);
+		if (err)
+			goto mg_write_exit;
+	}
+
+	if (cur_addr < end_addr) {
+
+		sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT;
+		cnt = ((end_addr & ~MG_SECTOR_SIZE_MASK) - cur_addr) >>
+			MG_SECTOR_SIZE_SHIFT;
+
+		if (cnt)
+			err = mg_disk_write_sects(buff_ptr, sect_num, cnt);
+		if (err)
+			goto mg_write_exit;
+
+		buff_ptr += cnt * MG_SECTOR_SIZE;
+		cur_addr += cnt * MG_SECTOR_SIZE;
+
+		if (cur_addr < end_addr) {
+			sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT;
+			err = mg_disk_read_sects(sect_buff, sect_num, 1);
+			if (err)
+				goto mg_write_exit;
+			memcpy(sect_buff, buff_ptr, end_addr - cur_addr);
+			MG_DBG("copies %u byte", end_addr - cur_addr);
+			err = mg_disk_write_sects(sect_buff, sect_num, 1);
+		}
+
+	}
+
+mg_write_exit:
+	free(sect_buff);
+
+	return err;
+}
+
+block_dev_desc_t *mg_disk_get_dev(int dev)
+{
+	return ((block_dev_desc_t *) & mg_disk_dev);
+}
+
+/* must override this function */
+struct mg_drv_data * __attribute__((weak)) mg_get_drv_data (void)
+{
+	puts ("### WARNING ### port mg_get_drv_data function\n");
+	return NULL;
+}
+
+unsigned int mg_disk_init (void)
+{
+	struct mg_drv_data *prv_data;
+	u32 err = MG_ERR_NONE;
+
+	prv_data = mg_get_drv_data();
+	if (! prv_data) {
+		printf("%s:%d fail (no driver_data)\n", __func__, __LINE__);
+		err = MG_ERR_NO_DRV_DATA;
+		return err;
+	}
+
+	((struct mg_host *)mg_disk_dev.priv)->drv_data = prv_data;
+
+	/* init ctrl pin */
+	if (prv_data->mg_ctrl_pin_init)
+		prv_data->mg_ctrl_pin_init();
+
+	if (! prv_data->mg_hdrst_pin) {
+		err = MG_ERR_CTRL_RST;
+		return err;
+	}
+
+	/* disk reset */
+	err = mg_disk_reset();
+	if (err) {
+		printf("%s:%d fail (err code : %d)\n", __func__, __LINE__, err);
+		return err;
+	}
+
+	/* get disk id */
+	err = mg_get_disk_id();
+	if (err) {
+		printf("%s:%d fail (err code : %d)\n", __func__, __LINE__, err);
+		return err;
+	}
+
+	mg_disk_dev.block_read = mg_block_read;
+	mg_disk_dev.block_write = mg_block_write;
+
+	init_part(&mg_disk_dev);
+
+	dev_print(&mg_disk_dev);
+
+	return err;
+}
diff --git a/drivers/block/mg_disk_prv.h b/drivers/block/mg_disk_prv.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f22e280be3005dca02b52440c6925b0cbb63e6c
--- /dev/null
+++ b/drivers/block/mg_disk_prv.h
@@ -0,0 +1,145 @@
+/*
+ * (C) Copyright 2009 mGine co.
+ * unsik Kim <donari75@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __MG_DISK_PRV_H__
+#define __MG_DISK_PRV_H__
+
+#include <mg_disk.h>
+
+/* name for block device */
+#define MG_DISK_NAME "mgd"
+/* name for platform device */
+#define MG_DEV_NAME "mg_disk"
+
+#define MG_DISK_MAJ 240
+#define MG_DISK_MAX_PART 16
+#define MG_SECTOR_SIZE 512
+#define MG_SECTOR_SIZE_MASK (512 - 1)
+#define MG_SECTOR_SIZE_SHIFT (9)
+#define MG_MAX_SECTS 256
+
+/* Register offsets */
+#define MG_BUFF_OFFSET			0x8000
+#define MG_STORAGE_BUFFER_SIZE		0x200
+#define MG_REG_OFFSET			0xC000
+#define MG_REG_FEATURE			(MG_REG_OFFSET + 2)	/* write case */
+#define MG_REG_ERROR			(MG_REG_OFFSET + 2)	/* read case */
+#define MG_REG_SECT_CNT			(MG_REG_OFFSET + 4)
+#define MG_REG_SECT_NUM			(MG_REG_OFFSET + 6)
+#define MG_REG_CYL_LOW			(MG_REG_OFFSET + 8)
+#define MG_REG_CYL_HIGH			(MG_REG_OFFSET + 0xA)
+#define MG_REG_DRV_HEAD			(MG_REG_OFFSET + 0xC)
+#define MG_REG_COMMAND			(MG_REG_OFFSET + 0xE)	/* write case */
+#define MG_REG_STATUS			(MG_REG_OFFSET + 0xE)	/* read  case */
+#define MG_REG_DRV_CTRL			(MG_REG_OFFSET + 0x10)
+#define MG_REG_BURST_CTRL		(MG_REG_OFFSET + 0x12)
+
+/* "Drive Select/Head Register" bit values */
+#define MG_REG_HEAD_MUST_BE_ON		0xA0 /* These 2 bits are always on */
+#define MG_REG_HEAD_DRIVE_MASTER	(0x00 | MG_REG_HEAD_MUST_BE_ON)
+#define MG_REG_HEAD_DRIVE_SLAVE		(0x10 | MG_REG_HEAD_MUST_BE_ON)
+#define MG_REG_HEAD_LBA_MODE		(0x40 | MG_REG_HEAD_MUST_BE_ON)
+
+
+/* "Device Control Register" bit values */
+#define MG_REG_CTRL_INTR_ENABLE			0x0
+#define MG_REG_CTRL_INTR_DISABLE		(0x1 << 1)
+#define MG_REG_CTRL_RESET			(0x1 << 2)
+#define MG_REG_CTRL_INTR_POLA_ACTIVE_HIGH	0x0
+#define MG_REG_CTRL_INTR_POLA_ACTIVE_LOW	(0x1 << 4)
+#define MG_REG_CTRL_DPD_POLA_ACTIVE_LOW		0x0
+#define MG_REG_CTRL_DPD_POLA_ACTIVE_HIGH	(0x1 << 5)
+#define MG_REG_CTRL_DPD_DISABLE			0x0
+#define MG_REG_CTRL_DPD_ENABLE			(0x1 << 6)
+
+/* Status register bit */
+ /* error bit in status register */
+#define MG_REG_STATUS_BIT_ERROR			0x01
+ /* corrected error in status register */
+#define MG_REG_STATUS_BIT_CORRECTED_ERROR	0x04
+ /* data request bit in status register */
+#define MG_REG_STATUS_BIT_DATA_REQ		0x08
+ /* DSC - Drive Seek Complete */
+#define MG_REG_STATUS_BIT_SEEK_DONE		0x10
+ /* DWF - Drive Write Fault */
+#define MG_REG_STATUS_BIT_WRITE_FAULT		0x20
+#define MG_REG_STATUS_BIT_READY			0x40
+#define MG_REG_STATUS_BIT_BUSY			0x80
+
+/* handy status */
+#define MG_STAT_READY	(MG_REG_STATUS_BIT_READY | MG_REG_STATUS_BIT_SEEK_DONE)
+#define MG_READY_OK(s)	(((s) & (MG_STAT_READY | \
+				(MG_REG_STATUS_BIT_BUSY | \
+				 MG_REG_STATUS_BIT_WRITE_FAULT | \
+				 MG_REG_STATUS_BIT_ERROR))) == MG_STAT_READY)
+
+/* Error register */
+#define MG_REG_ERR_AMNF		0x01
+#define MG_REG_ERR_ABRT		0x04
+#define MG_REG_ERR_IDNF		0x10
+#define MG_REG_ERR_UNC		0x40
+#define MG_REG_ERR_BBK		0x80
+
+/* error code for others */
+#define MG_ERR_NONE		0
+#define MG_ERR_TIMEOUT		0x100
+#define MG_ERR_INIT_STAT	0x101
+#define MG_ERR_TRANSLATION	0x102
+#define MG_ERR_CTRL_RST		0x103
+#define MG_ERR_NO_DRV_DATA	0x104
+
+#define MG_MAX_ERRORS	16	/* Max read/write errors/sector */
+#define MG_RESET_FREQ	4	/* Reset controller every 4th retry */
+
+/* command */
+#define MG_CMD_RD	0x20
+#define MG_CMD_WR	0x30
+#define MG_CMD_SLEEP	0x99
+#define MG_CMD_WAKEUP	0xC3
+#define MG_CMD_ID	0xEC
+#define MG_CMD_WR_CONF	0x3C
+#define MG_CMD_RD_CONF	0x40
+
+union mg_uniwb{
+	u16 w;
+	u8 b[2];
+};
+
+/* main structure for mflash driver */
+struct mg_host {
+	struct mg_drv_data *drv_data;
+	/* for future use */
+};
+
+/*
+ * Debugging macro and defines
+ */
+#undef DO_MG_DEBUG
+#ifdef DO_MG_DEBUG
+# define MG_DBG(fmt, args...) printf("%s:%d "fmt"\n", __func__, __LINE__,##args)
+#else /* CONFIG_MG_DEBUG */
+# define MG_DBG(fmt, args...) do { } while(0)
+#endif /* CONFIG_MG_DEBUG */
+
+#endif
+
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 8081ee7a837a0d915692d01dc959ce24e3277dd4..602edae6b0f3fdbeb5df24833edd05f51321125e 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -84,6 +84,7 @@ fat_register_device(block_dev_desc_t *dev_desc, int part_no)
 		return -1;
 	}
 #if (defined(CONFIG_CMD_IDE) || \
+     defined(CONFIG_CMD_MG_DISK) || \
      defined(CONFIG_CMD_SATA) || \
      defined(CONFIG_CMD_SCSI) || \
      defined(CONFIG_CMD_USB) || \
@@ -987,6 +988,7 @@ file_fat_detectfs(void)
 		return 1;
 	}
 #if defined(CONFIG_CMD_IDE) || \
+    defined(CONFIG_CMD_MG_DISK) || \
     defined(CONFIG_CMD_SATA) || \
     defined(CONFIG_CMD_SCSI) || \
     defined(CONFIG_CMD_USB) || \
diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h
index c5e0d268e3ace8f521b28225749cd0c5962e893c..c747b4baa193e60c74eb7b0f4a7051378b2febb7 100644
--- a/include/config_cmd_all.h
+++ b/include/config_cmd_all.h
@@ -84,5 +84,6 @@
 #define CONFIG_CMD_VFD		/* VFD support (TRAB)		*/
 #define CONFIG_CMD_XIMG		/* Load part of Multi Image	*/
 #define CONFIG_CMD_AT91_SPIMUX	/* AT91 MMC/SPI Mux Support     */
+#define CONFIG_CMD_MG_DISK	/* mGine m(g)flash IO node support */
 
 #endif	/* _CONFIG_CMD_ALL_H */
diff --git a/include/environment.h b/include/environment.h
index ea6b4d12ec6b61439da0bb5accfe711f1093c41d..507e8326a3a64d6a2363366156351682f8d8ec28 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -84,6 +84,18 @@
 # endif
 #endif /* CONFIG_ENV_IS_IN_NAND */
 
+#if defined(CONFIG_ENV_IS_IN_MG_DISK)
+# ifndef CONFIG_ENV_ADDR
+#  error "Need to define CONFIG_ENV_ADDR when using CONFIG_ENV_IS_IN_MG_DISK"
+# endif
+# ifndef CONFIG_ENV_SIZE
+#  error "Need to define CONFIG_ENV_SIZE when using CONFIG_ENV_IS_IN_MG_DISK"
+# endif
+# ifdef CONFIG_ENV_IS_EMBEDDED
+#  error "CONFIG_ENV_IS_EMBEDDED not supported when using CONFIG_ENV_IS_IN_MG_DISK"
+# endif
+#endif /* CONFIG_ENV_IS_IN_MG_DISK */
+
 #ifdef USE_HOSTCC
 # include <stdint.h>
 #else
diff --git a/include/mg_disk.h b/include/mg_disk.h
new file mode 100644
index 0000000000000000000000000000000000000000..bd767a11570a5edb14414c7ea78d52a845a13251
--- /dev/null
+++ b/include/mg_disk.h
@@ -0,0 +1,51 @@
+/*
+ * (C) Copyright 2009 mGine co.
+ * unsik Kim <donari75@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef MG_DISK_H_
+#define MG_DISK_H_
+
+#include <asm/types.h>
+
+/* private driver data */
+struct mg_drv_data {
+	/* base address of mflash */
+	u32 base;
+	/* Initialize hard reset, write protect, deep power down pins.
+	 * Set these pins to GPIO and output high
+	 */
+	void (*mg_ctrl_pin_init) (void);
+	/* Set hard reset pin for given level
+	 * level : logical level of hard reset pin (0 or 1)
+	 */
+	void (*mg_hdrst_pin) (u8 level);
+};
+
+struct mg_drv_data* mg_get_drv_data (void);
+
+unsigned int mg_disk_init (void);
+unsigned int mg_disk_read (u32 addr, u8 *buff, u32 len);
+unsigned int mg_disk_write(u32 addr, u8 *buff, u32 len);
+unsigned int mg_disk_write_sects(void *buff, u32 sect_num, u32 sect_cnt);
+unsigned int mg_disk_read_sects(void *buff, u32 sect_num, u32 sect_cnt);
+
+#endif /*MG_DISK_H_*/
diff --git a/include/part.h b/include/part.h
index 980fd043593e2c53651ab1dbdc50d4ff5cc07a65..3cdae0214eeaae747257bc9b92c1d9abe391d9ec 100644
--- a/include/part.h
+++ b/include/part.h
@@ -100,6 +100,7 @@ block_dev_desc_t* scsi_get_dev(int dev);
 block_dev_desc_t* usb_stor_get_dev(int dev);
 block_dev_desc_t* mmc_get_dev(int dev);
 block_dev_desc_t* systemace_get_dev(int dev);
+block_dev_desc_t* mg_disk_get_dev(int dev);
 
 /* disk/part.c */
 int get_partition_info (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);