diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 91c8013..160538d 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -22,6 +22,12 @@
 
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_MTD_PARTITIONS
+#include <linux/mtd/partitions.h>
+#define MTD_PART_DEV_NUM	0x0000FFFF
+#define MTD_PART_FLAGS		0xFFFF0000
+#endif
+
 #define MTD_INODE_FS_MAGIC 0x11307854
 static struct vfsmount *mtd_inode_mnt __read_mostly;
 
@@ -471,7 +477,15 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
 	int ret = 0;
 	u_long size;
 	struct mtd_info_user info;
-
+#ifdef CONFIG_MTD_PARTITIONS
+	struct mtd_partition	*pmtd;
+	struct mtd_partition	*pmtd1;
+	struct mtd_partition	free;
+	struct mtd_info *pinfo1;
+	struct mtd_info *pinfo2;
+	struct user_mtd	*ppart = NULL;
+	struct user_mtd_info	upart;
+#endif
 	DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
 
 	size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
@@ -825,6 +839,117 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
 		}
 		file->f_pos = 0;
 		break;
+#ifdef CONFIG_MTD_PARTITIONS
+
+	case MTDPARTITIONCREATE:
+	{
+		u_int64_t	uoffset = 0;
+		u_int64_t	usize = 0;
+		u_int32_t	i;
+
+			if (copy_from_user(&upart, argp,
+				sizeof(struct user_mtd_info))) {
+				ret = -EFAULT;
+				break;
+			}
+			ppart = kzalloc(sizeof(struct user_mtd)*
+						upart.num_partitions
+						, GFP_KERNEL);
+			pmtd = kzalloc(sizeof(struct mtd_partition)*
+					upart.num_partitions,
+					GFP_KERNEL);
+			pmtd1 = pmtd;
+			if (ppart == NULL) {
+				ret = -EFAULT;
+				break;
+			}
+			if (copy_from_user(ppart,
+					upart.pst_user_partitions,
+					sizeof(struct user_mtd)*
+					upart.num_partitions)) {
+				ret = -EFAULT;
+				break;
+			}
+			for (i = 0; i < upart.num_partitions; i++) {
+				pmtd->name  = ppart->name;
+				pmtd->size  =
+					ppart->partition_size;
+				usize += pmtd->size;
+				pmtd->offset =
+					ppart->partition_offset;
+				uoffset += pmtd->offset;
+				pmtd->mask_flags =
+					ppart->partition_mask;
+
+				ppart++;
+				pmtd++;
+			}
+			add_mtd_partitions(mtd, pmtd1,
+						upart.num_partitions);
+			if ((mtd->size - usize) > 0) {
+				free.name	= "FREE";
+				free.size	= mtd->size - usize;
+				free.offset	= usize;
+				free.mask_flags = 0;
+				add_mtd_partitions(mtd, &free, 1);
+			}
+			kfree(pmtd1);
+		break;
+	}
+	case MTDPARTITIONDELETE:
+	{
+		u_int32_t mtd_num;
+
+			if (copy_from_user(&mtd_num, argp,
+					sizeof(mtd_num))) {
+				ret = -EFAULT;
+				break;
+			}
+			pinfo1 = get_mtd_device(NULL,
+					mtd_num);
+
+			if (pinfo1 != NULL) {
+				put_mtd_device(pinfo1);
+				del_mtd_device(pinfo1);
+			}
+		break;
+	}
+	case MTDPARTITIONSETPERMISSION:
+	{
+		u_int32_t flags;
+		int dev_num;
+
+			if (copy_from_user(&flags, argp,
+					sizeof(flags))) {
+				ret = -EFAULT;
+				break;
+			}
+			dev_num = (flags & MTD_PART_DEV_NUM);
+			flags = (flags & MTD_PART_FLAGS) >> 16;
+			pinfo1 = get_mtd_device(NULL, dev_num);
+			pinfo1->flags = flags;
+		break;
+	}
+	case MTDPARTITIONMERGE:
+	{
+		u_int8_t part_num[2];
+
+			if (copy_from_user(part_num, argp, 2)) {
+				ret = -EFAULT;
+				break;
+			}
+			pinfo1 = get_mtd_device(NULL, part_num[0]);
+			pinfo2 = get_mtd_device(NULL, part_num[1]);
+			if ((pinfo1 != NULL) &&
+				(pinfo2 != NULL)) {
+				pinfo1->size +=	pinfo2->size;
+				put_mtd_device(pinfo2);
+				del_mtd_device(pinfo2);
+			}
+		break;
+	}
+#endif
+
 	}
 
 	default:
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index be51ae2..cfebc75 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -30,6 +30,19 @@ struct mtd_oob_buf64 {
 	__u64 usr_ptr;
 };
 
+struct user_mtd {
+	char name[32];
+	 __u64 partition_size;
+	 __u64 partition_offset;
+	 __u32 partition_mask;
+};
+
+struct user_mtd_info {
+	struct user_mtd *pst_user_partitions;
+	__u32 num_partitions;
+};
+
+
 #define MTD_ABSENT		0
 #define MTD_RAM			1
 #define MTD_ROM			2
@@ -110,7 +123,10 @@ struct otp_info {
 #define MEMERASE64		_IOW('M', 20, struct erase_info_user64)
 #define MEMWRITEOOB64		_IOWR('M', 21, struct mtd_oob_buf64)
 #define MEMREADOOB64		_IOWR('M', 22, struct mtd_oob_buf64)
-
+#define MTDPARTITIONCREATE      _IOW('M', 23, int)
+#define MTDPARTITIONDELETE      _IOW('M', 24, int)
+#define MTDPARTITIONSETPERMISSION _IOW('M', 26, int)
+#define MTDPARTITIONMERGE       _IOW('M', 27, int)
 /*
  * Obsolete legacy interface. Keep it in order not to break userspace
  * interfaces
