diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index e8f7436..b556794 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -231,7 +231,7 @@
 		CALL(sys_mincore)
 /* 220 */	CALL(sys_madvise)
 		CALL(ABI(sys_fcntl64, sys_oabi_fcntl64))
-		CALL(sys_ni_syscall) /* TUX */
+		CALL(sys_mhelper) /* TUX */
 		CALL(sys_ni_syscall)
 		CALL(sys_gettid)
 /* 225 */	CALL(ABI(sys_readahead, sys_oabi_readahead))
diff --git a/kernel/Makefile b/kernel/Makefile
index 14f4d45..897a0c8 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -8,7 +8,7 @@ obj-y     = sched.o fork.o exec_domain.o
 	    signal.o sys.o kmod.o workqueue.o pid.o \
 	    rcupdate.o extable.o params.o posix-timers.o \
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
-	    hrtimer.o rwsem.o latency.o nsproxy.o srcu.o
+	    hrtimer.o rwsem.o latency.o nsproxy.o srcu.o mhelper.o
 
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
 obj-y += time/
diff --git a/kernel/mhelper.c b/kernel/mhelper.c
new file mode 100644
index 0000000..4a596f3
--- /dev/null
+++ b/kernel/mhelper.c
@@ -0,0 +1,113 @@
+
+#include <linux/linkage.h>
+#include <asm/errno.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/uaccess.h>
+#include <asm/mach/map.h>
+
+#include "mhelper.h"
+
+
+
+#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, S3C2410_PA_##x, S3C24XX_SZ_##x, MT_DEVICE }
+
+struct map_desc mhelper_iodesc[] = {
+        IODESC_ENT(IRQ),
+        IODESC_ENT(MEMCTRL),
+        IODESC_ENT(USBHOST),
+        IODESC_ENT(DMA),
+        IODESC_ENT(CLKPWR),
+        IODESC_ENT(LCD),
+        IODESC_ENT(NAND),
+        IODESC_ENT(UART),
+        IODESC_ENT(TIMER),
+        IODESC_ENT(USBDEV),
+        IODESC_ENT(WATCHDOG),
+        IODESC_ENT(IIC),
+        IODESC_ENT(IIS),
+        IODESC_ENT(GPIO),
+        IODESC_ENT(RTC),
+        IODESC_ENT(ADC),
+        IODESC_ENT(SPI),
+        IODESC_ENT(SDI),
+};
+
+#define       IODESC_SIZE     (sizeof(mhelper_iodesc)/sizeof(struct map_desc))
+	
+static inline unsigned long
+map_io_to_va(unsigned long addr)
+{
+	int index;
+
+      for (index=0; index<IODESC_SIZE; index++) {
+               unsigned long phys = __pfn_to_phys(mhelper_iodesc[index].pfn);
+               unsigned long len = mhelper_iodesc[index].length;
+
+		if ((addr >= phys) & (addr < phys+len))
+			break;
+	}
+      if (index < IODESC_SIZE) {
+               unsigned long phys = __pfn_to_phys(mhelper_iodesc[index].pfn);
+               unsigned long virt = mhelper_iodesc[index].virtual;
+
+		return (addr - phys + virt);
+	}
+	return 0;
+}
+
+
+extern asmlinkage long
+sys_mhelper(uint32_t cmd, uint32_t addr, uint32_t value)
+{
+	unsigned long vaddr = 0;
+	int verb;
+
+	if (!(vaddr = map_io_to_va(addr)))
+		return -ENXIO;
+
+
+	verb = (cmd & OPT_VERB);	
+	cmd &= ~OPT_VERB;
+
+        switch (cmd) {
+
+	case CMD_READ_B:
+		value = __raw_readb(vaddr);
+		if (verb)
+			printk("0x%08x: 0x%02x (%d)\n", 
+				addr, value, value);
+		break;
+	case CMD_READ_W:
+		value = __raw_readw(vaddr);
+		if (verb)
+			printk("0x%08x: 0x%04x (%d)\n", 
+				addr, value, value);
+		break;
+	case CMD_READ_L:
+		value = __raw_readl(vaddr);
+		if (verb)
+			printk("0x%08x: 0x%08x (%d)\n", 
+				addr, value, value);
+		break;
+
+	case CMD_WRITE_B:
+		__raw_writeb(value, vaddr);
+		break;
+	case CMD_WRITE_W:
+		__raw_writew(value, vaddr);
+		break;
+	case CMD_WRITE_L:
+		__raw_writel(value, vaddr);
+		break;
+
+	default:
+		return -EINVAL;
+		break;
+	}
+
+	return verb?0:value;
+}
+
diff --git a/kernel/mhelper.h b/kernel/mhelper.h
new file mode 100644
index 0000000..df73297
--- /dev/null
+++ b/kernel/mhelper.h
@@ -0,0 +1,24 @@
+
+#define CAT_READ	0x10
+#define CAT_WRITE	0x20
+
+#define CAT_BYTE	0x01
+#define CAT_WORD	0x02
+#define CAT_LONG	0x03
+
+#define	OPT_VERB	0x80
+
+
+enum {
+	CMD_VERSION = 0,
+
+	CMD_READ_B  = 0x11,
+	CMD_READ_W,
+	CMD_READ_L,
+
+	CMD_WRITE_B = 0x21,
+	CMD_WRITE_W,
+	CMD_WRITE_L,
+
+};
+
