diff -urN linux/Makefile uClinux-2.0.38.1pre7-mtd/Makefile
--- linux/Makefile	Fri Feb  2 12:52:30 2001
+++ uClinux-2.0.38.1pre7-mtd/Makefile	Fri Feb  2 12:57:59 2001
@@ -162,6 +162,10 @@
 DRIVERS := $(DRIVERS) drivers/sbus/sbus.a
 endif
 
+ifdef CONFIG_MTD
+DRIVERS := $(DRIVERS) drivers/mtd/mtdlink.o
+endif
+
 include arch/$(ARCH)/Makefile
 
 .S.s:
diff -urN linux/arch/armnommu/config.in uClinux-2.0.38.1pre7-mtd/arch/armnommu/config.in
--- linux/arch/armnommu/config.in	Fri Feb  2 12:52:30 2001
+++ uClinux-2.0.38.1pre7-mtd/arch/armnommu/config.in	Fri Feb  2 12:57:59 2001
@@ -72,6 +72,8 @@
 fi
 endmenu
 
+source drivers/mtd/Config.in
+
 source arch/armnommu/drivers/block/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
diff -urN linux/arch/m68knommu/config.in uClinux-2.0.38.1pre7-mtd/arch/m68knommu/config.in
--- linux/arch/m68knommu/config.in	Fri Feb  2 12:52:38 2001
+++ uClinux-2.0.38.1pre7-mtd/arch/m68knommu/config.in	Fri Feb  2 13:19:07 2001
@@ -143,6 +143,8 @@
 
 endmenu
 
+source drivers/mtd/Config.in
+
 #
 # Block device driver configuration
 #
diff -urN linux/drivers/Makefile uClinux-2.0.38.1pre7-mtd/drivers/Makefile
--- linux/drivers/Makefile	Mon Apr 22 09:59:39 1996
+++ uClinux-2.0.38.1pre7-mtd/drivers/Makefile	Fri Feb  2 12:57:59 2001
@@ -9,7 +9,7 @@
 
 SUB_DIRS     := block char net #streams
 MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) pci sbus scsi sound cdrom isdn
+ALL_SUB_DIRS := $(SUB_DIRS) pci sbus scsi sound cdrom isdn mtd
 
 ifdef CONFIG_PCI
 SUB_DIRS += pci
@@ -55,6 +55,15 @@
 ifeq ($(CONFIG_AP1000),y)
 SUB_DIRS += ap1000
 ALL_SUB_DIRS += ap1000
+endif
+
+ifeq ($(CONFIG_MTD),y)
+SUB_DIRS += mtd
+MOD_SUB_DIRS += mtd
+else
+  ifeq ($(CONFIG_MTD),m)
+  MOD_SUB_DIRS += mtd
+  endif
 endif
 
 include $(TOPDIR)/Rules.make
diff -urN linux/drivers/block/genhd.c uClinux-2.0.38.1pre7-mtd/drivers/block/genhd.c
--- linux/drivers/block/genhd.c	Fri Feb  2 12:52:41 2001
+++ uClinux-2.0.38.1pre7-mtd/drivers/block/genhd.c	Fri Feb  2 13:06:07 2001
@@ -51,6 +51,8 @@
 
 extern int chr_dev_init(void);
 extern int blk_dev_init(void);
+extern void init_mtd(void);
+
 #ifdef CONFIG_BLK_DEV_DAC960
 extern void DAC960_Initialize(void);
 #endif
@@ -775,6 +777,9 @@
 
 	chr_dev_init();
 	blk_dev_init();
+#ifdef CONFIG_MTD
+        init_mtd();
+#endif
 	sti();
 #ifdef CONFIG_BLK_DEV_DAC960
 	DAC960_Initialize();
diff -urN linux/include/linux/list.h uClinux-2.0.38.1pre7-mtd/include/linux/list.h
--- linux/include/linux/list.h	Thu Jan  1 01:00:00 1970
+++ uClinux-2.0.38.1pre7-mtd/include/linux/list.h	Fri Feb  2 12:57:59 2001
@@ -0,0 +1,154 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+#ifdef __KERNEL__
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+	struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries. 
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_add(struct list_head * new,
+	struct list_head * prev,
+	struct list_head * next)
+{
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static __inline__ void list_add(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static __inline__ void __list_del(struct list_head * prev,
+				  struct list_head * next)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
+ */
+static __inline__ void list_del(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static __inline__ void list_del_init(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	INIT_LIST_HEAD(entry); 
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static __inline__ int list_empty(struct list_head *head)
+{
+	return head->next == head;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static __inline__ void list_splice(struct list_head *list, struct list_head *head)
+{
+	struct list_head *first = list->next;
+
+	if (first != list) {
+		struct list_head *last = list->prev;
+		struct list_head *at = head->next;
+
+		first->prev = head;
+		head->next = first;
+
+		last->next = at;
+		at->prev = last;
+	}
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:	the &struct list_head pointer.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+/**
+ * list_for_each	-	iterate over a list
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @head:	the head for your list.
+ */
+#define list_for_each(pos, head) \
+	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#endif /* __KERNEL__ */
+
+#endif
diff -urN kernel/include/asm-m68knommu/io.h kernel-mtd/include/asm-m68knommu/io.h
--- kernel/include/asm-m68knommu/io.h	Mon Oct 30 22:40:06 2000
+++ kernel-mtd/include/asm-m68knommu/io.h	Sun Mar 11 18:14:49 2001
@@ -21,6 +21,15 @@
 #define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b))
 #define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
 
+/* needed for MTD */
+#define __raw_writeb(val,addr)          writeb(val,addr)
+#define __raw_writew(val,addr)          writew(val,addr)
+#define __raw_writel(val,addr)         	writel(val,addr)
+
+#define __raw_readb(addr)               readb(addr)
+#define __raw_readw(addr)               readw(addr)
+#define __raw_readl(addr)               readl(addr)
+
 #if 0
 
 /* There is no difference between I/O and memory on 68k, these are the same */
