[U-Boot] [PATCH] mflash u-boot support

unsik Kim donari75 at gmail.com
Tue Jan 6 08:41:30 CET 2009


Hello, all?

I wrote mflash IO mode block device driver for U-Boot.

Brief desciption of mflash is following.

mflash is fusion memory device mainly targeted consumer eletronic and
mobile phone.
Internally, it have nand flash and other hardware logics and supports
some different operation (ATA, IO, XIP) modes.

IO mode is custom mode for the host that doesn't have IDE interface.
(many mobile targeted SoC doesn't have IDE bus)

This driver support mflash IO mode.

Followings are brief descriptions about IO mode.

1. IO mode based on ATA protocol and uses some custom command. (read
confirm, write confirm)
2. IO mode uses SRAM bus interface.

This driver tested some ARM platform. (pxa270, s3c2440, ...)

Any comments, help would be very appreciated. ^^

unsik Kim

Signed-off-by: unsik Kim <donari75 at gmail.com>
---
2	0	common/Makefile
83	0	common/cmd_mgdisk.c
2	1	common/cmd_nvedit.c
78	0	common/env_mgdisk.c
9	3	disk/part.c
4	1	disk/part_amiga.c
2	1	disk/part_dos.c
2	1	disk/part_efi.c
2	1	disk/part_iso.c
2	1	disk/part_mac.c
1	0	drivers/block/Makefile
595	0	drivers/block/mg_disk.c
135	0	drivers/block/mg_disk_prv.h
1	0	include/config_cmd_all.h
48	0	include/mg_disk.h
1	0	include/part.h
5	0	lib_arm/board.c
 common/Makefile             |    2 +
 common/cmd_mgdisk.c         |   83 ++++++
 common/cmd_nvedit.c         |    3 +-
 common/env_mgdisk.c         |   78 ++++++
 disk/part.c                 |   12 +-
 disk/part_amiga.c           |    5 +-
 disk/part_dos.c             |    3 +-
 disk/part_efi.c             |    3 +-
 disk/part_iso.c             |    3 +-
 disk/part_mac.c             |    3 +-
 drivers/block/Makefile      |    1 +
 drivers/block/mg_disk.c     |  595 +++++++++++++++++++++++++++++++++++++++++++
 drivers/block/mg_disk_prv.h |  135 ++++++++++
 include/config_cmd_all.h    |    1 +
 include/mg_disk.h           |   48 ++++
 include/part.h              |    1 +
 lib_arm/board.c             |    5 +
 17 files changed, 972 insertions(+), 9 deletions(-)

diff --git a/common/Makefile b/common/Makefile
index 93e3963..f93e575 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -57,6 +57,7 @@ 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
 COBJS-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
+COBJS-$(CONFIG_ENV_IS_IN_MG_DISK) += env_mgdisk.o
 COBJS-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o

 # command
@@ -138,6 +139,7 @@ endif
 COBJS-$(CONFIG_CMD_XIMG) += cmd_ximg.o
 COBJS-$(CONFIG_YAFFS2) += cmd_yaffs2.o
 COBJS-$(CONFIG_VFD) += cmd_vfd.o
+COBJS-$(CONFIG_CMD_MG_DISK) += cmd_mgdisk.o

 # others
 COBJS-$(CONFIG_DDR_SPD) += ddr_spd.o
diff --git a/common/cmd_mgdisk.c b/common/cmd_mgdisk.c
new file mode 100644
index 0000000..77bf074
--- /dev/null
+++ b/common/cmd_mgdisk.c
@@ -0,0 +1,83 @@
+/*
+ * (C) Copyright 2009 mGine co.
+ * unsik Kim <donari75 at 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 4:
+		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"
+	"\t- initialize : mgd init\n"
+	"\t- random read : mgd read [from] [to] [size]\n"
+	"\t\tbelow example read 256 bytes from 0x300000 of mflash\n"
+	"\t\tto 0xA0100000 of host memory\n"
+	"\t\tex) mgd read 0x300000 0xA0100000 256\n"
+	"\t- random write : mgd write [from] [to] [size]\n"
+	"\t\tex) mgd write 0xA0100000 0x300000 256\n"
+	"\t- sector read : mgd readsec [sector] [to] [counts]\n"
+	"\t\tbelow example read 10 sectors starts from 400 sector\n"
+	"\t\tto 0xA0100000\n"
+	"\t\tex) mgd readsec 400 0xA0100000 10\n"
+	"\t- sector write : mgd writesec [from] [sector] [counts]\n"
+);
+
+#endif
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 85025da..4945aeb 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -59,8 +59,9 @@ DECLARE_GLOBAL_DATA_PTR;
     !defined(CONFIG_ENV_IS_IN_NAND)	&& \
     !defined(CONFIG_ENV_IS_IN_ONENAND)	&& \
     !defined(CONFIG_ENV_IS_IN_SPI_FLASH)	&& \
+    !defined(CONFIG_ENV_IS_IN_MG_DISK)	&& \
     !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_{NVRAM|EEPROM|FLASH|DATAFLASH|ONENAND|SPI_FLASH|MG_DISK|NOWHERE}
 #endif

 #define XMK_STR(x)	#x
diff --git a/common/env_mgdisk.c b/common/env_mgdisk.c
new file mode 100644
index 0000000..dd6dee5
--- /dev/null
+++ b/common/env_mgdisk.c
@@ -0,0 +1,78 @@
+/*
+ * (C) Copyright 2009 mGine co.
+ * unsik Kim <donari75 at 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> /* TODO */
+#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_read(CONFIG_ENV_ADDR, (u_char *) env_ptr, CONFIG_ENV_SIZE);
+	if (err) {
+		puts ("*** Warning - mg_disk_read error, using default environment\n\n");
+		set_default_env();
+		return;
+	}
+
+	if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) {
+		puts ("*** Warning - CRC error, 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 (int)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 e353cee..c007060 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -39,7 +39,8 @@
      defined(CONFIG_CMD_SCSI) || \
      defined(CONFIG_CMD_USB) || \
      defined(CONFIG_MMC) || \
-     defined(CONFIG_SYSTEMACE) )
+     defined(CONFIG_SYSTEMACE) || \
+     defined(CONFIG_CMD_MG_DISK))

 struct block_drvr {
 	char *name;
@@ -65,6 +66,9 @@ static const struct block_drvr block_drvr[] = {
 #if defined(CONFIG_SYSTEMACE)
 	{ .name = "ace", .get_dev = systemace_get_dev, },
 #endif
+#if defined(CONFIG_CMD_MG_DISK)
+	{ .name = "mgdisk", .get_dev = mg_disk_get_dev, },
+#endif
 	{ },
 };

@@ -95,7 +99,8 @@ block_dev_desc_t *get_dev(char* ifname, int dev)
      defined(CONFIG_CMD_SCSI) || \
      defined(CONFIG_CMD_USB) || \
      defined(CONFIG_MMC) || \
-     defined(CONFIG_SYSTEMACE) )
+     defined(CONFIG_SYSTEMACE) || \
+     defined(CONFIG_CMD_MG_DISK))

 /* ------------------------------------------------------------------------- */
 /*
@@ -207,7 +212,8 @@ void dev_print (block_dev_desc_t *dev_desc)
      defined(CONFIG_CMD_SCSI) || \
      defined(CONFIG_CMD_USB) || \
      defined(CONFIG_MMC)		|| \
-     defined(CONFIG_SYSTEMACE)          )
+     defined(CONFIG_SYSTEMACE) || \
+     defined(CONFIG_CMD_MG_DISK))

 #if defined(CONFIG_MAC_PARTITION) || \
     defined(CONFIG_DOS_PARTITION) || \
diff --git a/disk/part_amiga.c b/disk/part_amiga.c
index 6c3d748..b4c2820 100644
--- a/disk/part_amiga.c
+++ b/disk/part_amiga.c
@@ -30,7 +30,8 @@
      defined(CONFIG_CMD_SCSI) || \
      defined(CONFIG_CMD_USB) || \
      defined(CONFIG_MMC) || \
-     defined(CONFIG_SYSTEMACE) ) && defined(CONFIG_AMIGA_PARTITION)
+     defined(CONFIG_SYSTEMACE) || \
+     defined(CONFIG_CMD_MG_DISK)) && defined(CONFIG_AMIGA_PARTITION)

 #undef AMIGA_DEBUG

@@ -40,6 +41,8 @@
 #define PRINTF(fmt, args...)
 #endif

+#define atoi(x)		simple_strtoul(x,NULL,10)
+
 struct block_header
 {
     u32 id;
diff --git a/disk/part_dos.c b/disk/part_dos.c
index 4d778ec..30dc39f 100644
--- a/disk/part_dos.c
+++ b/disk/part_dos.c
@@ -40,7 +40,8 @@
      defined(CONFIG_CMD_SCSI) || \
      defined(CONFIG_CMD_USB) || \
      defined(CONFIG_MMC) || \
-     defined(CONFIG_SYSTEMACE) ) && defined(CONFIG_DOS_PARTITION)
+     defined(CONFIG_SYSTEMACE) || \
+     defined(CONFIG_CMD_MG_DISK)) && defined(CONFIG_DOS_PARTITION)

 /* Convert char[4] in little endian format to the host format integer
  */
diff --git a/disk/part_efi.c b/disk/part_efi.c
index cc188ee..e7ff4af 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -41,7 +41,8 @@
      defined(CONFIG_CMD_SCSI) || \
      defined(CONFIG_CMD_USB) || \
      defined(CONFIG_MMC) || \
-     defined(CONFIG_SYSTEMACE) ) && defined(CONFIG_EFI_PARTITION)
+     defined(CONFIG_SYSTEMACE) || \
+     defined(CONFIG_CMD_MG_DISK)) && defined(CONFIG_EFI_PARTITION)

 /* Convert char[2] in little endian format to the host format integer
  */
diff --git a/disk/part_iso.c b/disk/part_iso.c
index 72ff868..95468c9 100644
--- a/disk/part_iso.c
+++ b/disk/part_iso.c
@@ -30,7 +30,8 @@
      defined(CONFIG_CMD_SATA) || \
      defined(CONFIG_CMD_USB) || \
      defined(CONFIG_MMC) || \
-     defined(CONFIG_SYSTEMACE) ) && defined(CONFIG_ISO_PARTITION)
+     defined(CONFIG_SYSTEMACE) || \
+     defined(CONFIG_CMD_MG_DISK)) && defined(CONFIG_ISO_PARTITION)

 /* #define	ISO_PART_DEBUG */

diff --git a/disk/part_mac.c b/disk/part_mac.c
index 1922fe5..fefcfdd 100644
--- a/disk/part_mac.c
+++ b/disk/part_mac.c
@@ -39,7 +39,8 @@
      defined(CONFIG_CMD_SATA) || \
      defined(CONFIG_CMD_USB) || \
      defined(CONFIG_MMC) || \
-     defined(CONFIG_SYSTEMACE) ) && defined(CONFIG_MAC_PARTITION)
+     defined(CONFIG_SYSTEMACE) || \
+     defined(CONFIG_CMD_MG_DISK)) && defined(CONFIG_MAC_PARTITION)

 /* stdlib.h causes some compatibility problems; should fixe these! -- wd */
 #ifndef __ldiv_t_defined
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 642582b..87c6e53 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -33,6 +33,7 @@ COBJS-$(CONFIG_SATA_SIL3114) += sata_sil3114.o
 COBJS-$(CONFIG_IDE_SIL680) += sil680.o
 COBJS-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o
 COBJS-$(CONFIG_SYSTEMACE) += systemace.o
+COBJS-$(CONFIG_CMD_MG_DISK) += mg_disk.o

 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c
new file mode 100644
index 0000000..06c9bd8
--- /dev/null
+++ b/drivers/block/mg_disk.c
@@ -0,0 +1,595 @@
+/*
+ * (C) Copyright 2009 mGine co.
+ * unsik Kim <donari75 at 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 "mg_disk_prv.h"
+
+#ifdef CONFIG_CMD_MG_DISK
+
+#undef printk
+#define printk printf
+
+#undef KERN_ERR
+#define KERN_ERR
+#undef KERN_DEBUG
+#define KERN_DEBUG
+#undef KERN_INFO
+#define KERN_INFO
+
+#undef inb
+#undef inw
+#undef outb
+#undef outw
+
+#define inb(a)	(*(volatile unsigned char *)(a))
+#define inw(a)	(*(volatile unsigned short *)(a))
+#define outb(v, a)	(*(volatile unsigned char *)(a) = (v))
+#define outw(v, a)	(*(volatile unsigned short *)(a) = (v))
+
+#define MG_BASE	(host.drv_data->base)
+
+static struct mg_host host;
+
+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 };
+
+#define MG_HOST ((struct mg_host *)mg_disk_dev.priv)
+
+static void mg_dump_status (const char *msg, unsigned int stat, unsigned err)
+{
+	char *name = MG_DEV_NAME;
+
+	printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff);
+	if (stat & MG_REG_STATUS_BIT_BUSY)			printk("Busy ");
+	if (stat & MG_REG_STATUS_BIT_READY)			printk("DriveReady ");
+	if (stat & MG_REG_STATUS_BIT_WRITE_FAULT)		printk("WriteFault ");
+	if (stat & MG_REG_STATUS_BIT_SEEK_DONE)		printk("SeekComplete ");
+	if (stat & MG_REG_STATUS_BIT_DATA_REQ)		printk("DataRequest ");
+	if (stat & MG_REG_STATUS_BIT_CORRECTED_ERROR)	printk("CorrectedError ");
+	if (stat & MG_REG_STATUS_BIT_ERROR)			printk("Error ");
+	printk("}\n");
+	if ((stat & MG_REG_STATUS_BIT_ERROR)) {
+		printk("%s: %s: error=0x%02x { ", name, msg, err & 0xff);
+		if (err & MG_REG_ERR_BBK)	printk("BadSector ");
+		if (err & MG_REG_ERR_UNC)	printk("UncorrectableError ");
+		if (err & MG_REG_ERR_IDNF)	printk("SectorIdNotFound ");
+		if (err & MG_REG_ERR_ABRT)	printk("DriveStatusError ");
+		if (err & MG_REG_ERR_AMNF)	printk("AddrMarkNotFound ");
+		printk("}\n");
+	}
+}
+
+static unsigned int msecs_to_hz (u32 msec)
+{
+	u32 hz = CONFIG_SYS_HZ / 1000 * msec;
+
+	if (!hz)
+		hz = 1;
+
+	return hz;
+}
+
+/*
+ * copy src to dest, skipping leading and trailing blanks and null
+ * terminate the string
+ * "len" is the size of available memory including the terminating '\0'
+ */
+static void mg_ident_cpy (unsigned char *dst, unsigned char *src,
unsigned int len)
+{
+	unsigned char *end, *last;
+
+	last = dst;
+	end  = src + len - 1;
+
+	/* reserve space for '\0' */
+	if (len < 2)
+		goto OUT;
+
+	/* skip leading white space */
+	while ((*src) && (src<end) && (*src==' '))
+		++src;
+
+	/* copy string, omitting trailing white space */
+	while ((*src) && (src<end)) {
+		*dst++ = *src;
+		if (*src++ != ' ')
+			last = dst;
+	}
+OUT:
+	*last = '\0';
+}
+
+/* port done */
+static unsigned int mg_wait (u32 expect, u32 msec)
+{
+	u8 status;
+	u32 from, cur, expire, err;
+
+	err = MG_ERR_NONE;
+	from = get_timer(0);
+	expire = from + msecs_to_hz(msec);
+
+	status = inb(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 = inb(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 = inb(MG_BASE + MG_REG_STATUS);
+	} while (cur < expire);
+
+	if (cur >= expire)
+		err = MG_ERR_TIMEOUT;
+
+	return err;
+}
+
+static int mg_get_disk_id (void)
+{
+	u32 iobuf[(MG_SECTOR_SIZE / sizeof(u32))];
+	hd_driveid_t *iop = (hd_driveid_t *)iobuf;
+	u32 i, err;
+	u16 *buff = (u16 *)iobuf;
+
+	outb(MG_CMD_ID, MG_BASE + MG_REG_COMMAND);
+	err = mg_wait(MG_REG_STATUS_BIT_DATA_REQ, 3000);
+	if (! err) {
+		for(i = 0; i < ((MG_SECTOR_SIZE / sizeof(unsigned long)) >> 1); i++) {
+			buff[i] = inw(MG_BASE + MG_BUFF_OFFSET + i * 2);
+		}
+
+		outb(MG_CMD_RD_CONF, MG_BASE + MG_REG_COMMAND);
+		err = mg_wait(MG_STAT_READY, 3000);
+		if (!err) {
+			if((iop->field_valid & 1) == 0) {
+				err = MG_ERR_TRANSLATION;
+			} else {
+				mg_ident_cpy((unsigned char*)mg_disk_dev.revision, iop->fw_rev,
sizeof(mg_disk_dev.revision));
+				mg_ident_cpy((unsigned char*)mg_disk_dev.vendor, iop->model,
sizeof(mg_disk_dev.vendor));
+				mg_ident_cpy((unsigned char*)mg_disk_dev.product, iop->serial_no,
sizeof(mg_disk_dev.product));
+#ifdef __LITTLE_ENDIAN
+				/*
+				 * firmware revision, model, and serial number have Big Endian Byte
+				 * order in Word. Convert all three to little endian.
+				 *
+				 * See CF+ and CompactFlash Specification Revision 2.0:
+				 * 6.2.1.6: Identify Drive, Table 39 for more details
+				 */
+
+				strswab(mg_disk_dev.revision);
+				strswab(mg_disk_dev.vendor);
+				strswab(mg_disk_dev.product);
+#endif /* __LITTLE_ENDIAN */
+
+#ifdef __BIG_ENDIAN
+				mg_disk_dev.lba = (iop->lba_capacity << 16) | (iop->lba_capacity >> 16);
+#else	/* ! __BIG_ENDIAN */
+				mg_disk_dev.lba = iop->lba_capacity;
+#endif /* __BIG_ENDIAN */
+			}
+		}
+	}
+
+	return err;
+}
+
+static int mg_disk_reset (void)
+{
+	struct mg_drv_data *prv_data = MG_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 */
+	outb(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 */
+	outb(MG_REG_CTRL_INTR_DISABLE, MG_BASE + MG_REG_DRV_CTRL);
+	err = mg_wait(MG_STAT_READY, 3000);
+	if(err) return err;
+
+	init_status = inb(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;
+
+	if ((err = mg_wait(MG_STAT_READY, 3000))) {
+		return err;
+	}
+
+	outb((u8)sect_cnt, MG_BASE + MG_REG_SECT_CNT);
+	outb((u8)sect_num, MG_BASE + MG_REG_SECT_NUM);
+	outb((u8)(sect_num >> 8), MG_BASE + MG_REG_CYL_LOW);
+	outb((u8)(sect_num >> 16), MG_BASE + MG_REG_CYL_HIGH);
+	outb((u8)((sect_num >> 24) | MG_REG_HEAD_LBA_MODE), MG_BASE +
MG_REG_DRV_HEAD);
+	outb(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;
+
+	if ((err = mg_out(sect_num, sect_cnt, MG_CMD_RD))) {
+		return err;
+	}
+
+	for (i = 0; i < sect_cnt; i++) {
+		if ((err = mg_wait(MG_REG_STATUS_BIT_DATA_REQ, 3000))) {
+			return err;
+		}
+
+		/* TODO : u16 unaligned case */
+		for(j = 0; j < MG_SECTOR_SIZE >> 1; j++) {
+			*(u16 *)buff_ptr = inw(MG_BASE + MG_BUFF_OFFSET + (j << 1));
+			buff_ptr += 2;
+		}
+
+		outb(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)
+{
+	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;
+		next_sec_addr = cur_addr + MG_SECTOR_SIZE;
+
+		while (next_sec_addr <= end_addr) {
+			cnt++;
+			next_sec_addr += MG_SECTOR_SIZE;
+		}
+
+		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;
+
+	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;
+
+		/* TODO : u16 unaligned case */
+		for(j = 0; j < MG_SECTOR_SIZE >> 1; j++) {
+			outw(*(u16 *)buff_ptr, MG_BASE + MG_BUFF_OFFSET + (j << 1));
+			buff_ptr += 2;
+		}
+
+		outb(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)
+{
+	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;
+		next_sec_addr = cur_addr + MG_SECTOR_SIZE;
+
+		while (next_sec_addr <= end_addr) {
+			cnt++;
+			next_sec_addr += MG_SECTOR_SIZE;
+		}
+
+		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) {
+		printk(KERN_ERR "%s:%d fail (no driver_data)\n", __func__, __LINE__);
+		err = MG_ERR_NO_DRV_DATA;
+		return err;
+	}
+
+	MG_HOST->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) {
+		printk(KERN_ERR "%s:%d fail (err code : %d)\n", __func__, __LINE__, err);
+		return err;
+	}
+
+	/* get disk id */
+	err = mg_get_disk_id();
+	if (err) {
+		printk(KERN_ERR "%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);
+
+	((struct mg_host *)mg_disk_dev.priv)->inited = 1;
+
+	return err;
+}
+
+#endif /* CONFIG_CMD_MG_DISK */
diff --git a/drivers/block/mg_disk_prv.h b/drivers/block/mg_disk_prv.h
new file mode 100644
index 0000000..678d652
--- /dev/null
+++ b/drivers/block/mg_disk_prv.h
@@ -0,0 +1,135 @@
+/*
+ * (C) Copyright 2009 mGine co.
+ * unsik Kim <donari75 at 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 */
+#define MG_REG_STATUS_BIT_ERROR			0x01 /* error bit in status register */
+#define MG_REG_STATUS_BIT_CORRECTED_ERROR		0x04 /* corrected error in
status register */
+#define MG_REG_STATUS_BIT_DATA_REQ			0x08 /* data request bit in
status register */
+#define MG_REG_STATUS_BIT_SEEK_DONE			0x10 /* DSC - Drive Seek Complete */
+#define MG_REG_STATUS_BIT_WRITE_FAULT		0x20 /* DWF - Drive Write Fault */
+#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
+
+/* main structure for mflash driver */
+struct mg_host {
+	struct mg_drv_data *drv_data;
+	u32 inited;
+	/* for future use */
+};
+
+/*
+ * Debugging macro and defines
+ */
+#undef DO_MG_DEBUG
+#ifdef DO_MG_DEBUG
+#  define MG_DBG(fmt, args...) printk(KERN_DEBUG "%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/include/config_cmd_all.h b/include/config_cmd_all.h
index d771696..0ee2b58 100644
--- a/include/config_cmd_all.h
+++ b/include/config_cmd_all.h
@@ -83,5 +83,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/mg_disk.h b/include/mg_disk.h
new file mode 100644
index 0000000..3705729
--- /dev/null
+++ b/include/mg_disk.h
@@ -0,0 +1,48 @@
+/*
+ * (C) Copyright 2009 mGine co.
+ * unsik Kim <donari75 at 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 {
+	u32 base;
+
+	/* control pin resource */
+	void (*mg_ctrl_pin_init) (void); /* initialize hdrst, wd, dpd pin to
GPIO and output high */
+	void (*mg_hdrst_pin) (u8 level);
+	void (*mg_wp_pin) (u8 level);
+	void (*mg_dpd_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 980fd04..3cdae02 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);
diff --git a/lib_arm/board.c b/lib_arm/board.c
index 2358beb..6a26bd2 100644
--- a/lib_arm/board.c
+++ b/lib_arm/board.c
@@ -48,6 +48,7 @@
 #include <serial.h>
 #include <nand.h>
 #include <onenand_uboot.h>
+#include <mg_disk.h>

 #ifdef CONFIG_DRIVER_SMC91111
 #include "../drivers/net/smc91111.h"
@@ -348,6 +349,10 @@ void start_armboot (void)
 	onenand_init();
 #endif

+#if defined(CONFIG_CMD_MG_DISK)
+	mg_disk_init();
+#endif
+
 #ifdef CONFIG_HAS_DATAFLASH
 	AT91F_DataflashInit();
 	dataflash_print_info();


More information about the U-Boot mailing list