diff --git a/Makefile b/Makefile
index 42f2b02..7f6e007 100644
--- a/Makefile
+++ b/Makefile
@@ -337,6 +337,9 @@ LIBS-y += api/libapi.o
 LIBS-y += post/libpost.o
 LIBS-y += test/libtest.o
 
+LIBS-$(CONFIG_DM) += common/dm/libdm.o
+LIBS-$(CONFIG_DM) += drivers/demo/libdemo.o
+
 ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TI814X),)
 LIBS-y += $(CPUDIR)/omap-common/libomap-common.o
 endif
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index 0c022f1..321bc0d 100644
--- a/arch/sandbox/include/asm/io.h
+++ b/arch/sandbox/include/asm/io.h
@@ -54,6 +54,6 @@ static inline void unmap_sysmem(const void *vaddr)
 }
 
 /* Map from a pointer to our RAM buffer */
-phys_addr_t map_to_sysmem(void *ptr);
+phys_addr_t map_to_sysmem(const void *ptr);
 
 #endif
diff --git a/arch/sandbox/include/asm/types.h b/arch/sandbox/include/asm/types.h
index 2316c2d..07c2986 100644
--- a/arch/sandbox/include/asm/types.h
+++ b/arch/sandbox/include/asm/types.h
@@ -64,8 +64,8 @@ typedef unsigned long long u64;
 #define BITS_PER_LONG	CONFIG_SANDBOX_BITS_PER_LONG
 
 typedef unsigned long dma_addr_t;
-typedef unsigned long phys_addr_t;
-typedef unsigned long phys_size_t;
+typedef u32 phys_addr_t;
+typedef u32 phys_size_t;
 
 #endif /* __KERNEL__ */
 
diff --git a/common/Makefile b/common/Makefile
index 0e0fff1..680ad01 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -85,6 +85,7 @@ COBJS-$(CONFIG_CMD_CONSOLE) += cmd_console.o
 COBJS-$(CONFIG_CMD_CPLBINFO) += cmd_cplbinfo.o
 COBJS-$(CONFIG_DATAFLASH_MMC_SELECT) += cmd_dataflash_mmc_mux.o
 COBJS-$(CONFIG_CMD_DATE) += cmd_date.o
+COBJS-$(CONFIG_CMD_DEMO) += cmd_demo.o
 COBJS-$(CONFIG_CMD_SOUND) += cmd_sound.o
 ifdef CONFIG_4xx
 COBJS-$(CONFIG_CMD_SETGETDCR) += cmd_dcr.o
diff --git a/common/board_r.c b/common/board_r.c
index f801e41..436ae83 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -66,7 +66,9 @@
 #ifdef CONFIG_X86
 #include <asm/init_helpers.h>
 #endif
+#include <dm-demo.h>
 #include <linux/compiler.h>
+#include <linux/err.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -269,6 +271,57 @@ static int initr_malloc(void)
 	return 0;
 }
 
+static int initr_dm(void)
+{
+	dm_init();
+	static const struct dm_demo_cdata red_square = {
+		.colour = "red",
+		.sides = 4.
+	};
+	static const struct dm_demo_cdata green_triangle = {
+		.colour = "green",
+		.sides = 3.
+	};
+	static const struct dm_demo_cdata yellow_hexagon = {
+		.colour = "yellow",
+		.sides = 6.
+	};
+	static const struct driver_info info[] = {
+		{
+			.name = "demo_shape_drv",
+			.platform_data = &red_square,
+		},
+		{
+			.name = "demo_simple_drv",
+			.platform_data = &red_square,
+		},
+		{
+			.name = "demo_shape_drv",
+			.platform_data = &green_triangle,
+		},
+		{
+			.name = "demo_simple_drv",
+			.platform_data = &yellow_hexagon,
+		},
+		{
+			.name = "demo_shape_drv",
+			.platform_data = &yellow_hexagon,
+		},
+	};
+	struct device *root = get_root_instance();
+	struct device *demo1;
+
+	demo1 = driver_bind(root, &info[0]);
+	if (IS_ERR(demo1))
+		printf("Demo bind failed: %ld\n", PTR_ERR(demo1));
+	driver_bind(demo1, &info[1]);
+	driver_bind(root, &info[2]);
+	driver_bind(root, &info[3]);
+	driver_bind(root, &info[4]);
+
+	return 0;
+}
+
 __weak int power_init_board(void)
 {
 	return 0;
@@ -765,6 +818,9 @@ init_fnc_t init_sequence_r[] = {
 #endif
 	initr_barrier,
 	initr_malloc,
+#ifdef CONFIG_DM
+	initr_dm,
+#endif
 #ifdef CONFIG_ARCH_EARLY_INIT_R
 	arch_early_init_r,
 #endif
diff --git a/common/cmd_demo.c b/common/cmd_demo.c
new file mode 100644
index 0000000..657a541
--- /dev/null
+++ b/common/cmd_demo.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2013 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@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 <dm-demo.h>
+#include <asm/io.h>
+
+struct device *demo_dev;
+
+static int do_demo_hello(cmd_tbl_t *cmdtp, int flag, int argc,
+			 char * const argv[])
+{
+	int ch = '@';
+
+	if (argc)
+		ch = *argv[0];
+
+	return demo_hello(demo_dev, ch);
+}
+
+static int do_demo_status(cmd_tbl_t *cmdtp, int flag, int argc,
+			  char * const argv[])
+{
+	int status;
+	int ret;
+
+	ret = demo_status(demo_dev, &status);
+	if (ret)
+		return ret;
+
+	printf("Status: %d\n", status);
+
+	return 0;
+}
+
+int do_demo_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct uclass *class;
+	struct device *dev;
+	int i = 0;
+
+	class = class_get_instance(UCLASS_DEMO);
+	if (!class)
+		return -ENOMEM;
+
+	puts("Demo class entries:\n");
+
+	list_for_each_entry(dev, &class->class_node, class_node) {
+		printf("entry %d - instance %08x, ops %08x, platform_data %08x\n",
+		       i++, map_to_sysmem(dev),
+		       map_to_sysmem(dev->driver->ops),
+		       map_to_sysmem(dev->info->platform_data));
+	}
+
+	return 0;
+}
+
+static cmd_tbl_t demo_commands[] = {
+	U_BOOT_CMD_MKENT(list, 0, 1, do_demo_list, "", ""),
+	U_BOOT_CMD_MKENT(hello, 2, 1, do_demo_hello, "", ""),
+	U_BOOT_CMD_MKENT(status, 1, 1, do_demo_status, "", ""),
+};
+
+static int do_demo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	cmd_tbl_t *demo_cmd;
+	int devnum = 0;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+	demo_cmd = find_cmd_tbl(argv[1], demo_commands,
+				ARRAY_SIZE(demo_commands));
+	argc -= 2;
+	argv += 2;
+	if (!demo_cmd || argc > demo_cmd->maxargs)
+		return CMD_RET_USAGE;
+
+	if (argc) {
+		devnum = simple_strtoul(argv[0], NULL, 10);
+		demo_dev = uclass_get_child(UCLASS_DEMO, devnum);
+		if (!demo_dev) {
+			puts("Device not found\n");
+			return 1;
+		}
+
+		ret = driver_activate(demo_dev);
+		if (ret)
+			return cmd_process_error(cmdtp, ret);
+	}
+
+	argc--;
+	argv++;
+	ret = demo_cmd->cmd(demo_cmd, flag, argc, argv);
+	return cmd_process_error(demo_cmd, ret);
+}
+
+U_BOOT_CMD(
+	demo,   4,      1,      do_demo,
+	"Driver model (dm) demo operations",
+	"list            List available demo devices\n"
+	"hello <num>     Say hello\n"
+	"status <num>    Get demo device status"
+);
diff --git a/common/command.c b/common/command.c
index 305a236..70faa60 100644
--- a/common/command.c
+++ b/common/command.c
@@ -554,3 +554,13 @@ enum command_ret_t cmd_process(int flag, int argc, char * const argv[],
 		rc = cmd_usage(cmdtp);
 	return rc;
 }
+
+int cmd_process_error(cmd_tbl_t *cmdtp, int err)
+{
+	if (err) {
+		printf("Command '%s' failed: Error %d\n", cmdtp->name, err);
+		return 1;
+	}
+
+	return 0;
+}
diff --git a/common/dm/Makefile b/common/dm/Makefile
new file mode 100644
index 0000000..982a3d5
--- /dev/null
+++ b/common/dm/Makefile
@@ -0,0 +1,40 @@
+# 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 $(TOPDIR)/config.mk
+
+LIB	:= $(obj)libdm.o
+
+COBJS	:= debug.o driver.o lists.o tree.o root.o uclass.o
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/common/dm/debug.c b/common/dm/debug.c
new file mode 100644
index 0000000..cb36fb4
--- /dev/null
+++ b/common/dm/debug.c
@@ -0,0 +1,137 @@
+/*
+ * (C) Copyright 2012
+ * Marek Vasut <marex@denx.de>
+ *
+ * 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 <errno.h>
+#include <asm/io.h>
+#include <dm/debug.h>
+#include <dm/manager.h>
+#include <dm/structures.h>
+#include <dm/uclass.h>
+
+static int display_succ(struct device *in, char *buf)
+{
+	int len;
+	int ip = 0;
+	char local[16];
+	struct device *pos, *n, *prev = NULL;
+
+	printf("%s- %s @ %08x", buf, in->info->name, map_to_sysmem(in));
+	if (in->flags & DM_FLAG_ACTIVATED)
+		puts(" - activated");
+	puts("\n");
+
+	if (list_empty(&in->succ))
+		return 0;
+
+	len = strlen(buf);
+	strncpy(local, buf, sizeof(local));
+	snprintf(local + len, 2, "|");
+	if (len && local[len - 1] == '`')
+		local[len - 1] = ' ';
+
+	list_for_each_entry_safe(pos, n, &in->succ, sibling) {
+		if (ip++)
+			display_succ(prev, local);
+		prev = pos;
+	}
+
+	snprintf(local + len, 2, "`");
+	display_succ(prev, local);
+
+	return 0;
+}
+
+int dm_dump_all()
+{
+	struct device *root;
+
+	root = get_root_instance();
+	printf("ROOT %08x\n", map_to_sysmem(root));
+	return dm_dump(root);
+}
+
+int dm_dump(struct device *dev)
+{
+	if (!dev)
+		return -EINVAL;
+	return display_succ(dev, "");
+}
+
+static int dm_dump_classs(void)
+{
+	struct uclass *class;
+	int count, num;
+	int id;
+
+	for (id = 0; id < UCLASS_COUNT; id++) {
+		class = class_get_instance(id);
+		if (!class)
+			continue;
+
+		count = uclass_get_count(id);
+		printf("class %d: %d instances\n", id, count);
+		for (num = 0; num < count; num++) {
+			struct device *inst;
+
+			inst = uclass_get_child(id, num);
+			printf("   %08x:\n", map_to_sysmem(inst));
+		}
+		puts("\n");
+	}
+
+	return 0;
+}
+
+static int do_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct device *root;
+
+	if (argc != 2)
+		return -EINVAL;
+	if (!strncmp(argv[1], "dump", 4))
+		return dm_dump_all();
+
+	if (!strncmp(argv[1], "remove", 6)) {
+		root = get_root_instance();
+		return driver_remove(root);
+	}
+
+	if (!strncmp(argv[1], "unbind", 6)) {
+		root = get_root_instance();
+		return driver_unbind(root);
+	}
+
+	if (!strcmp(argv[1], "class"))
+		return dm_dump_classs();
+
+	return -EINVAL;
+}
+
+U_BOOT_CMD(
+	dm,	2,	1,	do_dm,
+	"Driver model ops",
+	"dump         dump driver model tree\n"
+	"class         Dump list of instances for each class"
+);
diff --git a/common/dm/driver.c b/common/dm/driver.c
new file mode 100644
index 0000000..597feab
--- /dev/null
+++ b/common/dm/driver.c
@@ -0,0 +1,374 @@
+/*
+ * (C) Copyright 2013 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@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 <malloc.h>
+#include <dm/manager.h>
+#include <linux/err.h>
+#include <linux/list.h>
+
+/*
+ * List management functions
+ */
+
+/**
+ * driver_add_child() - Connect one driver under another
+ * @parent:	Parent driver, under which will the driver be connected
+ * @child:	Child driver, which is to be connected under the parent
+ */
+static void driver_add_child(struct device *parent, struct device *child)
+{
+	list_add_tail(&child->sibling, &parent->succ);
+}
+
+/**
+ * driver_remove_child() - Unbind driver's child from the driver
+ * @parent:	The parent device, from which the child is unbound
+ * @child:	The child device, which is being unbound
+ */
+static void driver_remove_child(struct device *parent, struct device *child)
+{
+	list_del(&child->sibling);
+}
+
+/**
+ * driver_driver_reloc() - Relocate driver's children
+ * @old:	Instance of the old driver
+ * @new:	Instance of the new driver
+ *
+ * Relocate the children of a driver. The supplied old device
+ * contains the list of a children, usually generated during the
+ * pre-relocation stage, whereas the new device contains no
+ * children nodes yet. The new device is usually created at
+ * the post-relocation stage. The nodes from old instance are relocated
+ * and connected under the new instance.
+ */
+static int driver_driver_reloc(struct device *old,
+				struct device *new)
+{
+	struct device *pos, *n;
+	struct device *inst;
+
+	list_for_each_entry_safe(pos, n, &old->succ, sibling) {
+		inst = driver_relocate(pos, new);
+		if (IS_ERR(inst))
+			return PTR_ERR(inst);
+		driver_add_child(new, inst);
+	}
+
+	return 0;
+}
+
+/**
+ * driver_chld_unbind() - Unbind all driver's children from the driver
+ * @dev:	The driver that is to be stripped of off children
+ */
+static int driver_chld_unbind(struct device *dev)
+{
+	struct device *pos, *n;
+	int ret;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (list_empty(&dev->succ))
+		return 0;
+
+	list_for_each_entry_safe(pos, n, &dev->succ, sibling) {
+		ret = driver_unbind(pos);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * driver_chld_remove() - Stop all driver's children
+ * @dev:	The driver whose children are to be stopped
+ */
+static int driver_chld_remove(struct device *dev)
+{
+	struct device *pos, *n;
+	int ret;
+
+	if (!dev)
+		return -EINVAL;
+
+	list_for_each_entry_safe(pos, n, &dev->succ, sibling) {
+		ret = driver_remove(pos);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Driver management functions
+ */
+
+/**
+ * driver_bind() - Instantiate and connect a driver under a parent one
+ * @parent:	The parent driver, under which the new driver will be connected
+ * @info:	Information about the driver to be probed
+ *
+ * Make a new instance of a driver based on data passed by the user. This
+ * instance is then connected under the parent driver. The driver is not yet
+ * started after being bound, it's only present in the driver tree.
+ *
+ * Returns the instance of a new driver on success, NULL on error.
+ */
+struct device *driver_bind(struct device *parent,
+			   const struct driver_info *info)
+{
+	struct device *dev;
+	struct u_boot_driver *drv;
+	int ret = 0;
+
+	if (!info || !parent) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	dev = calloc(1, sizeof(struct device));
+	if (!dev) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	INIT_LIST_HEAD(&dev->sibling);
+	INIT_LIST_HEAD(&dev->succ);
+	INIT_LIST_HEAD(&dev->class_node);
+	dev->info = info;
+	dev->bus = parent;
+	drv = get_driver_by_instance(dev);
+
+	if (!drv) {
+		ret = -ENOENT;
+		goto fail_free;
+	}
+	dev->driver = drv;
+
+	/* put dev into parents successor list */
+	driver_add_child(parent, dev);
+
+	ret = uclass_bind(drv->id, dev);
+	if (ret)
+		goto fail_bind;
+
+	/* if we fail to bind we remove device from successors and free it */
+	if (drv->bind) {
+		ret = drv->bind(dev);
+		if (ret)
+			goto fail_bind;
+	}
+
+	return dev;
+
+fail_bind:
+	driver_remove_child(parent, dev);
+fail_free:
+	free(dev);
+fail:
+	return ERR_PTR(ret);
+}
+
+/**
+ * driver_activate() - Start a driver
+ * @i:		Instance of a driver that is to be started
+ *
+ * This function runs the .probe() function, which initializes the hardware.
+ * The hardware and all it's predecessors are started by this function.
+ */
+int driver_activate(struct device *inst)
+{
+	struct u_boot_driver *drv;
+	int ret;
+
+	if (!inst)
+		return -EINVAL;
+
+	drv = get_driver_by_instance(inst);
+	if (!drv)
+		return -ENOENT;
+
+	if (inst->flags & DM_FLAG_ACTIVATED)
+		return 0;
+
+	/* Allocate private data if requested */
+	if (drv->priv_data_size) {
+		inst->priv = calloc(1, drv->priv_data_size);
+		if (!inst->priv)
+			return -ENOMEM;
+	}
+
+	if (inst->bus) {
+		ret = driver_activate(inst->bus);
+		if (ret)
+			goto err;
+	}
+
+	if (drv->probe) {
+		ret = drv->probe(inst);
+		if (ret)
+			goto err;
+	}
+
+	inst->flags |= DM_FLAG_ACTIVATED;
+	return 0;
+err:
+	if (drv->priv_data_size)
+		free(inst->priv);
+
+	return ret;
+}
+
+/**
+ * driver_relocate() - Relocate an instance of a driver
+ * @dev:	The instance of a driver to be relocated
+ * @bus:	The instance of a new parent of this driver
+ *
+ * Relocate an instance of a driver and it's children. The new
+ * instance of a driver is allocated and connected under the
+ * already-relocated parent/bus. The children of the old driver
+ * are relocated afterwards as well.
+ */
+struct device *driver_relocate(struct device *dev, struct device *bus)
+{
+	struct u_boot_driver *ops;
+	struct device *new_dev;
+	int ret;
+
+	if (!dev)
+		return NULL;
+
+	ops = get_driver_by_instance(dev);
+	if (!ops || !ops->reloc)
+		return NULL;
+
+	new_dev = calloc(1, sizeof(struct device));
+	if (!new_dev)
+		return NULL;
+
+	INIT_LIST_HEAD(&new_dev->sibling);
+	INIT_LIST_HEAD(&new_dev->succ);
+	new_dev->flags = dev->flags;
+	new_dev->bus = bus;
+	new_dev->info = dev->info;
+	/* FIXME: handle driver_info in dynamic memory */
+	new_dev->priv = NULL;
+
+	/* relocate the instance */
+	ret = ops->reloc(new_dev, dev);
+	if (ret)
+		goto err;
+
+	ret = driver_driver_reloc(dev, new_dev);
+	if (ret)
+		goto err;
+
+	return new_dev;
+
+err:
+	free(new_dev);
+	return NULL;
+};
+
+/**
+ * driver_unbind() - Unbind driver from it's parent
+ * @dev:	The driver to be unbound
+ *
+ * Disconnect a driver from it's parent. The driver must be deactived,
+ * otherwise this function fails and doesn't unbind the driver.
+ */
+int driver_unbind(struct device *dev)
+{
+	struct u_boot_driver *ops;
+	int ret;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (dev->flags & DM_FLAG_ACTIVATED)
+		return -EINVAL;
+
+	ops = get_driver_by_instance(dev);
+	if (!ops)
+		return -EINVAL;
+
+	ret = driver_chld_unbind(dev);
+	if (ret)
+		return ret;
+
+	if (ops->unbind) {
+		ret = ops->unbind(dev);
+		if (ret)
+			return ret;
+	}
+
+	if (dev->bus)
+		driver_remove_child(dev->bus, dev);
+
+	return 0;
+}
+
+/**
+ * driver_remove() - Disable the driver and it's children
+ * @dev:	The instance of a driver to be disabled
+ *
+ * Deconfigure the hardware and all it's children.
+ */
+int driver_remove(struct device *dev)
+{
+	struct u_boot_driver *ops;
+	int ret;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (!(dev->flags & DM_FLAG_ACTIVATED))
+		return 0;
+
+	ops = get_driver_by_instance(dev);
+	if (!ops)
+		return -EINVAL;
+
+	ret = driver_chld_remove(dev);
+	if (ret)
+		return ret;
+
+	if (ops->remove) {
+		ret = ops->remove(dev);
+		if (ret)
+			return ret;
+	}
+
+	if (dev->driver->priv_data_size)
+		free(dev->priv);
+
+	dev->flags &= ~DM_FLAG_ACTIVATED;
+
+	return ret;
+}
diff --git a/common/dm/lists.c b/common/dm/lists.c
new file mode 100644
index 0000000..f914143
--- /dev/null
+++ b/common/dm/lists.c
@@ -0,0 +1,138 @@
+/*
+ * (C) Copyright 2012
+ * Marek Vasut <marex@denx.de>
+ *
+ * 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 <dm/manager.h>
+
+/**
+ * get_driver_by_instance() - Return u_boot_driver classsponding to instance
+ * instance:	Instance of the driver
+ *
+ * This function returns pointer to an u_boot_driver, which is base for the
+ * supplied instance of a driver. Returns NULL on error.
+ */
+struct u_boot_driver *get_driver_by_instance(struct device *i)
+{
+	struct u_boot_driver *drv =
+		ll_entry_start(struct u_boot_driver, driver);
+	const int n_ents = ll_entry_count(struct u_boot_driver, driver);
+	struct u_boot_driver *entry;
+	const char *name;
+	int len;
+
+	if (!i || !drv || !n_ents)
+		return NULL;
+
+	name = i->info->name;
+	len = strlen(name);
+
+	for (entry = drv; entry != drv + n_ents; entry++) {
+		if (strncmp(name, entry->name, len))
+			continue;
+
+		/* Full match */
+		if (len == strlen(entry->name))
+			return entry;
+	}
+
+	/* Not found */
+	return NULL;
+}
+
+/**
+ * get_usb_driver_by_ids() - Return u_boot_driver based on USB IDs
+ * major:	USB major ID
+ * minor:	USB minor ID
+ *
+ * This function finds an u_boot_driver inside the U-Boot USB driver list
+ * based on the USB's major and minor IDs. Returns pointer to the driver on
+ * success, NULL on error.
+ */
+struct u_boot_driver *get_usb_driver_by_ids(uint16_t major, uint16_t minor)
+{
+	struct u_boot_driver *drv =
+		ll_entry_start(struct u_boot_driver, driver);
+	const int n_ents = ll_entry_count(struct u_boot_driver, driver);
+	struct u_boot_driver *entry;
+	struct usb_ids *ids;
+	int i;
+
+	if (!drv || !n_ents)
+		return NULL;
+
+	/* First walk the ID tables */
+	for (entry = drv; entry != drv + n_ents; entry++) {
+		i = 0;
+		ids = entry->aux_data;
+		for (;;) {
+			if (!ids->ids[i].major && !ids->ids[i].minor)
+				break;
+
+			if (ids->ids[i].major != major) {
+				i++;
+				continue;
+			}
+
+			if (ids->ids[i].minor != minor) {
+				i++;
+				continue;
+			}
+
+			return entry;
+		}
+	}
+
+	/* Next, try the match functions */
+	for (entry = drv; entry != drv + n_ents; entry++) {
+		ids = entry->aux_data;
+		if (ids->match && ids->match())
+			return entry;
+	}
+
+	/* No driver found */
+	return NULL;
+}
+
+/**
+ * get_class_by_id() - Return U_BOOT_CLASS based on ID of the class
+ * id:		ID of the class
+ *
+ * This function returns the pointer to U_BOOT_CLASS, which is the class's
+ * base structure based on the ID of the class. Returns NULL on error.
+ */
+struct u_boot_class *get_class_by_id(enum uclass_id id)
+{
+	struct u_boot_class *class =
+		ll_entry_start(struct u_boot_class, class);
+	const int n_ents = ll_entry_count(struct u_boot_class, class);
+	struct u_boot_class *entry;
+
+	if ((id == UCLASS_INVALID) || !class)
+		return NULL;
+
+	for (entry = class; entry != class + n_ents; entry++) {
+		if (entry->id == id)
+			return entry;
+	}
+
+	return NULL;
+}
diff --git a/common/dm/root.c b/common/dm/root.c
new file mode 100644
index 0000000..3a569ef
--- /dev/null
+++ b/common/dm/root.c
@@ -0,0 +1,101 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@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 <dm/structures.h>
+#include <dm/manager.h>
+#include <malloc.h>
+#include <errno.h>
+#include <linux/list.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct driver_info root_info = {
+	.name		= "root_driver",
+};
+
+/**
+ * create_root_instance() - Instantiate the root driver
+ *
+ * Create instance of the root driver, the root of the driver tree.
+ * This root driver is pointed to by the global data. Returns 0 on
+ * success, negative value on error.
+ */
+static int create_root_instance(void)
+{
+	struct device *di;
+
+	if (gd->dm_root) {
+		puts("Virtual root driver already exists!\n");
+		return -EINVAL;
+	}
+
+	di = calloc(1, sizeof(struct device));
+	if (di == NULL)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&di->sibling);
+	INIT_LIST_HEAD(&di->succ);
+	di->info = &root_info;
+	gd->dm_root = di;
+
+	return 0;
+}
+
+/**
+ * get_root_instance() - Return pointer to the top of the driver tree
+ *
+ * This function returns pointer to the root node of the driver tree,
+ * in case this root wasn't created yet, reports it and returns NULL.
+ */
+struct device *get_root_instance(void)
+{
+	if (!gd->dm_root) {
+		puts("Virtual root driver does not exist!\n");
+		return NULL;
+	}
+
+	return gd->dm_root;
+}
+
+/**
+ * dm_init() - Initialize Driver Model structures
+ *
+ * This function will initialize roots of driver tree and class tree.
+ * This needs to be called before anything uses the DM
+ */
+int dm_init(void)
+{
+	int retval = 0;
+
+	retval = create_root_instance();
+	if (retval)
+		hang();
+
+	INIT_LIST_HEAD(&gd->class_root);
+
+	return retval;
+}
+
+U_BOOT_DRIVER(__root_driver) = {
+	.name	= "root_driver",
+};
diff --git a/common/dm/tree.c b/common/dm/tree.c
new file mode 100644
index 0000000..bd08b06
--- /dev/null
+++ b/common/dm/tree.c
@@ -0,0 +1,71 @@
+/*
+ * (C) Copyright 2012
+ * Viktor Krivak <viktor.krivak@gmail.com>
+ * Pavel Herrmann <morpheus.ibis@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 <dm/manager.h>
+#include <dm/structures.h>
+#include <linux/list.h>
+#include <malloc.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct node {
+	struct list_head list;
+	enum uclass_id key;
+	struct uclass class;
+};
+
+/**
+ * classs_relocate() - Relocate classs from early init memory
+ *
+ * Allocate new memory for each class, copy key and call reloc function found
+ * in specific class ops. Return 0 if succeeded.
+ */
+int classs_relocate(void)
+{
+	struct u_boot_class *ops;
+	struct node *node;
+	struct node *new;
+	struct list_head new_head;
+	INIT_LIST_HEAD(&new_head);
+	list_for_each_entry(node, &gd->class_root, list) {
+		ops = get_class_by_id(node->key);
+		if (!ops)
+			panic("%s: No ops\n", __func__);
+		new = malloc(sizeof(*new));
+		if (!new)
+			panic("%s: Unable to allocate memory!", __func__);
+		new->key = node->key;
+		/* No reloc method. It is strage but not error */
+		if (!ops->reloc)
+			continue;
+		if (!ops->reloc(&new->class, &node->class))
+			list_add_tail(&new->list, &new_head);
+		else
+			panic("%s: Relocation of class fail!", __func__);
+	}
+	gd->class_root = new_head;
+	return 0;
+}
+
diff --git a/common/dm/uclass.c b/common/dm/uclass.c
new file mode 100644
index 0000000..97430b2
--- /dev/null
+++ b/common/dm/uclass.c
@@ -0,0 +1,227 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@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 <malloc.h>
+#include <dm/manager.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * search() - Search class by key in list
+ * @key:	Key used to search apropriet class instance
+ *
+ * Linear search in list and if found something, replace it at beginning
+ * of the list and return class instance inside node.
+ * If nothing was found return NULL.
+ */
+static struct uclass *class_search(enum uclass_id key)
+{
+	struct uclass *inst;
+
+	list_for_each_entry(inst, &gd->class_root, succ) {
+		if (inst->dm_class->id == key)
+			return inst;
+	}
+	return NULL;
+}
+
+/**
+ * class_add_instance() - Create and add new class in list
+ * @key: Key used to init class instance
+ *
+ * Call init_node to create class instance and its container structure.
+ * After that add this class to list.
+ */
+static struct uclass *class_add_instance(enum uclass_id key)
+{
+	struct u_boot_class *cls;
+	struct uclass *inst;
+
+	cls = get_class_by_id(key);
+	if (!cls)
+		panic("Cannot find class for id %d\n", key);
+	inst = calloc(1, sizeof(*inst));
+	inst->dm_class = cls;
+	INIT_LIST_HEAD(&inst->succ);
+	INIT_LIST_HEAD(&inst->class_node);
+	list_add(&inst->succ, &gd->class_root);
+
+	return inst;
+}
+
+/**
+ * class_get_instance() - Return or create class by key
+ * @key:	Search class with this key or create new one
+ *
+ * Try to find class in list structure. If fail create a new class and place it
+ * in list. If fail to create new class, return NULL. Otherwise return
+ * pointer to designated class.
+ */
+struct uclass *class_get_instance(enum uclass_id key)
+{
+	struct uclass *instance;
+
+	instance = class_search(key);
+	if (!instance)
+		instance = class_add_instance(key);
+	return instance;
+}
+
+/**
+ * uclass_get_count() - Return number of registered children with class
+ * @id:		ID of the class
+ *
+ * Count the number of members registered with this class and return
+ * the value. Negative value is returned in case of failure.
+ */
+int uclass_get_count(enum uclass_id id)
+{
+	struct uclass *class;
+	struct device *inst;
+	int count = 0;
+
+	class = class_get_instance(id);
+	if (!class)
+		return -ENOMEM;
+
+	list_for_each_entry(inst, &class->class_node, class_node)
+		count++;
+
+	return count;
+}
+
+/**
+ * uclass_get_child() - Return n-th child of class
+ * @id:		ID of the class
+ * @index:	Position of the child in class's list
+ *
+ * Return the instance pointer of a child at the given index or
+ * return NULL on error.
+ */
+struct device *uclass_get_child(enum uclass_id id, int index)
+{
+	struct uclass *class;
+	struct device *inst;
+
+	class = class_get_instance(id);
+	if (!class)
+		return NULL;
+
+	list_for_each_entry(inst, &class->class_node, class_node) {
+		if (!index--)
+			return inst;
+	}
+
+	return NULL;
+}
+
+/**
+ * uclass_bind() - Associate driver with a class
+ * @id:		ID of the class
+ * @dev:	Pointer to the driver's instance
+ * @ops:	Structure carrying operations this driver provides to the class
+ *
+ * Connect the driver into class's list of drivers. Returns 0 on success,
+ * negative value on error.
+ */
+int uclass_bind(enum uclass_id id, struct device *dev)
+{
+	struct uclass *class;
+	struct u_boot_class *class_ops;
+	int ret;
+
+	class = class_get_instance(id);
+	if (!class)
+		return -ENOMEM;
+
+	class_ops = get_class_by_id(id);
+	if (!class_ops)
+		return -ENOENT;
+	if (class_ops->ops)
+		return -EINVAL;
+
+	list_add_tail(&dev->class_node, &class->class_node);
+
+	if (class_ops->bind) {
+		ret = class_ops->bind(class, dev);
+		if (ret) {
+			list_del(&dev->class_node);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * uclass_unbind() - Deassociate driver with a class
+ * @id:		ID of the class
+ * @dev:	Pointer to the driver's instance
+ *
+ * Disconnect the driver from class's list of drivers.
+ * Returns 0 on success, negative value on error.
+ */
+int uclass_unbind(enum uclass_id id, struct device *dev)
+{
+	struct uclass *class;
+	struct u_boot_class *class_ops;
+
+	class = class_get_instance(id);
+	if (!class)
+		return -ENOMEM;
+
+	class_ops = get_class_by_id(id);
+	if (!class_ops)
+		return -ENOENT;
+
+	return class_ops->unbind(class, dev);
+}
+
+/**
+ * uclass_replace() - Replace instance of a driver with another in class's list
+ * @id:		ID of the class
+ * @new:	Pointer to the driver's new instance
+ * @old:	Pointer to the driver's old instance
+ *
+ * Replace old instance of a driver, usually pre-relocation one, in the list
+ * of drivers associated with a class with a new one, usually a post-relocation
+ * one. All of the internal state of the class associated with the old instance
+ * is preserved.
+ *
+ * Returns 0 on success, negative value on error.
+ */
+int uclass_replace(enum uclass_id id, struct device *new, struct device *old)
+{
+	struct uclass *class;
+	struct u_boot_class *class_ops;
+
+	class = class_get_instance(id);
+	if (!class)
+		return -ENOMEM;
+
+	class_ops = get_class_by_id(id);
+	if (!class_ops)
+		return -ENOENT;
+
+	return class_ops->replace(class, new, old);
+}
diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt
new file mode 100644
index 0000000..e077220
--- /dev/null
+++ b/doc/driver-model/README.txt
@@ -0,0 +1,307 @@
+Driver Model RFC
+================
+
+This README contains information about an early RFC implementation of
+driver model. The original work was done by:
+
+   Marek Vasut <marex@denx.de>
+   Pavel Herrmann <morpheus.ibis@gmail.com>
+   Viktor Křivák <viktor.krivak@gmail.com>
+   Tomas Hlavacek <tmshlvck@gmail.com>
+
+The code was taken from branch dm at:
+
+   git://git.denx.de/u-boot-marex.git
+
+You can find a test version of the code used here in branch dm2 at:
+
+   http://git.denx.de/u-boot-x86.git
+
+(Branch dm contains the original implementation)
+
+
+The goal of this effort is to get a very basic implementation into
+the U-Boot source tree quickly - something which people can build on,
+rather than something that solves all of the problems immediately.
+The only driver support that I am planning to add is GPIO, because
+it is simple, but non-trivial, and much of the work is already done
+by the people above.
+
+NOTE: This code is an early incoherent, inconsistent and largely
+incorrect draft. Please use it for making comments on the approach.
+Some knowledge of the existing driver model design is helpful.
+
+NOTE: Please read the above note again.
+
+
+How to try it
+-------------
+
+Build U-Boot sandbox and run it:
+
+   make sandbox_config
+   make
+   ./u-boot
+
+   (type 'reset' to exit U-Boot)
+
+
+The only available device class (uclass) is 'demo'. This uclass handles
+saying hello, and reporting its status. There are two drivers in this
+uclass:
+
+   - simple: Just prints a message for hello, doesn't implement status
+   - shape: Prints shapes and reports number of characters printed as status
+
+The demo class is pretty simple, but not trivial. The intention is that it
+can be used for testing, so it will implement all driver model features and
+provide 100% code coverage of them. It does have multiple drivers, it
+handles parameter data and platform_data (data which tells the driver how
+to operate on a particular platform) and it uses private driver data.
+
+To try it, see the example session below:
+
+=>demo hello 1
+probe from 07981110
+Hello '@' from 07981110: red 4
+=>demo status 2
+Status: 0
+=>demo hello 2
+g
+r@
+e@@
+e@@@
+n@@@@
+g@@@@@
+=>demo status 2
+Status: 21
+=>demo hello 4 ^
+  y^^^
+ e^^^^^
+l^^^^^^^
+l^^^^^^^
+ o^^^^^
+  w^^^
+=>demo status 4
+Status: 36
+=>
+
+
+What is going on?
+-----------------
+
+Let's start at the top. The demo command is in common/cmd_demo.c. It does
+the usual command procesing and then:
+
+	struct device *demo_dev;
+
+	demo_dev = uclass_get_child(UCLASS_DEMO, devnum);
+
+UCLASS_DEMO means the class of devices which implement 'demo'. Other
+classes might be MMC, or GPIO, hashing or serial. The idea is that the
+devices in the class all share a particular way of working. The class
+presents a unified view of all these devices to U-Boot.
+
+This function looks up the device for the demo uclass. Given a device
+number we can find the device because all devices have registered with
+the UCLASS_DEMO uclass.
+
+Having found the device, we activate it with:
+
+	ret = driver_activate(demo_dev);
+
+This is because all devices are inactive until used in U-Boot. The exact
+mechanism of activating a driver will hopefully change. For example, i
+may be possible to combine uclass_get_child() and driver_activate().
+
+Now that we have the device we can do things like:
+
+	return demo_hello(demo_dev, ch);
+
+This function is in the demo uclass. It takes care of calling the 'hello'
+method of the relevant driver. Bearing in mind that there are two drivers,
+this particular device may use one or other of them.
+
+The code for demo_hello() is in drivers/demo/demo-uclass.c:
+
+int demo_hello(struct device *dev, int ch)
+{
+	const struct demo_ops *ops = device_get_ops(dev);
+
+	if (!ops->hello)
+		return -ENOSYS;
+
+	return ops->hello(dev, ch);
+}
+
+As you can see it just calls the relevant driver method. One of these is
+in drivers/demo/demo-simple.c:
+
+static int simple_hello(struct device *dev, int ch)
+{
+	const struct dm_demo_cdata *pdata = dev->info->platform_data;
+
+	printf("Hello '%c' from %08x: %s %d\n", ch, map_to_sysmem(dev),
+	       pdata->colour, pdata->sides);
+
+	return 0;
+}
+
+
+So that is a trip from top to bottom but it leaves a lot of topics to
+address.
+
+
+Declaring Drivers
+-----------------
+
+A driver declaration looks something like this (see
+drivers/demo/demo-shape.c):
+
+static const struct demo_ops simple_ops = {
+	.hello = shape_hello,
+	.status = shape_status,
+};
+
+U_BOOT_DRIVER(demo_shape_drv) = {
+	.name	= "demo_shape_drv",
+	.id	= UCLASS_DEMO,
+	.ops	= &simple_ops,
+	.priv_data_size = sizeof(struct shape_data),
+};
+
+
+This driver has two methods (hello and status) and requires a bit
+of private data (accessible through dev->priv once the driver has
+been probed). It is a member of UCLASS_DEMO so will register itself
+there.
+
+In U_BOOT_DRIVER it is also possible to specify special methods for probe,
+and bind, and these are called at appropriate times. For many drivers
+it is hoped that only 'probe' and 'remove' will be needed.
+
+The U_BOOT_DRIVER macro creates a data structure accessible from C,
+so driver model can find the drivers that are available.
+
+
+Platform Data
+-------------
+
+Where does the platform data come from? See common/board_r.c which
+sets up a table of driver names and their associated platform data.
+The data can be interpreted by the drivers however they like - it is
+basically a communication scheme between the board-specific code and
+the generic drivers, which are intended to work on any board.
+
+Drivers can acceess their data via dev->info->platform_data. Here is
+the declaration for the platform data, which would normally appear
+in the board file.
+
+	static const struct dm_demo_cdata red_square = {
+		.colour = "red",
+		.sides = 4.
+	};
+	static const struct driver_info info[] = {
+		{
+			.name = "demo_shape_drv",
+			.platform_data = &red_square,
+		},
+	};
+
+	demo1 = driver_bind(root, &info[0]);
+
+
+Device Tree
+-----------
+
+This is not yet implemented but will be before this work leaves RFC status.
+We will use device tree to specify the platform data and activated drivers.
+In other words we replace the above code with the following device tree
+fragment:
+
+	red-square {
+		compatible = "demo-shape";
+		colour = "red";
+		sides = <4>;
+	};
+
+
+Driver model will look after creating a new device and feeding the device
+node into it. The driver itself will decode the device tree node and
+produce its own platform_data from it.
+
+
+Declaring Uclasses
+------------------
+
+The demo uclass is declared like this:
+
+U_BOOT_CLASS(demo) = {
+	.id		= UCLASS_DEMO,
+};
+
+It is also possible to specify special methods for probe, etc. The uclass
+numbering comes from include/dm/uclass.h.
+
+
+Data Structures
+---------------
+
+Driver model uses a doubly-linked list as the basic data structure. Some
+nodes have several lists running through them. Creating a more efficient
+data structure might be worthwhile in some rare cases, once we understand
+what the bottlenecks are.
+
+
+Changes so far
+--------------
+
+The documenation in this direction is out of data and until the patch
+is in more solid form I have avoided updating it. This implementation
+uses a very similar approach, but makes at least the following changes:
+
+- Tried to agressively remove boilerplate, so that for most drivers there
+is little or no 'driver model' code to write.
+- Moved some data from code into data structure - e.g. store a pointer to
+the driver operations structure in the driver, rather than passing it
+to the driver bind function.
+- Rename some structures to make them more similar to Linux (struct device
+instead of struct instance, struct platform_data, etc.)
+- Change the name 'core' to 'uclass', meaning U-Boot class. It seems that
+this concept relates to a class of drivers (or a subsystem). We shouldn't
+use 'class' since it is a C++ reserved word, so U-Boot class (uclass) seems
+better than 'core'.
+- Remove 'struct driver_instance' and just use a single 'struct device'.
+This removes a level of indirection that doesn't seem necessary.
+
+
+Proposed additional changes
+---------------------------
+
+- Build in device tree support, to avoid the need for platform_data
+- Possibly remove the concept of driver relocation, and just make it
+possible for the new driver (created after relocation) to access the old
+driver data. I feel that relocation is a very special case and will only
+apply to a few drivers, many of which can/will just re-init anyway. So
+the overhead of dealing with this might not be worth it. This is TBD
+though.
+- Implement for GPIO subsystem. An implementation is already done in the
+driver model tree
+
+
+Things to punt for later
+------------------------
+
+- SPL support - this will have to be present before many drivers can be
+converted, but it seems like we can add it once we are happy with the
+core implementation.
+- Pre-relocation support - similar story
+
+That is not to say that no thinking has gone into these - in fact there
+is quite a lot there. However, getting these right is non-trivial and
+there is a high cost associated with going down the wrong path.
+
+
+Simon Glass
+sjg@chromium.org
+April 2013
diff --git a/drivers/demo/Makefile b/drivers/demo/Makefile
new file mode 100644
index 0000000..60a2b88
--- /dev/null
+++ b/drivers/demo/Makefile
@@ -0,0 +1,44 @@
+# 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 $(TOPDIR)/config.mk
+
+LIB	:= $(obj)libdemo.o
+
+COBJS-$(CONFIG_DM_DEMO) += demo-uclass.o
+COBJS-$(CONFIG_DM_DEMO_SIMPLE) += demo-simple.o
+COBJS-$(CONFIG_DM_DEMO_SHAPE) += demo-shape.o
+
+COBJS	:= $(COBJS-y)
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/demo/demo-shape.c b/drivers/demo/demo-shape.c
new file mode 100644
index 0000000..b72fcba
--- /dev/null
+++ b/drivers/demo/demo-shape.c
@@ -0,0 +1,106 @@
+/*
+ * (C) Copyright 2013 Google, Inc
+ *
+ * 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 <dm-demo.h>
+#include <asm/io.h>
+#include <dm/manager.h>
+
+/* Shape size */
+#define WIDTH	8
+#define HEIGHT	6
+
+struct shape_data {
+	int num_chars;	/* Number of non-space characters output so far */
+};
+
+/* Crazy little function to draw shapes on the console */
+static int shape_hello(struct device *dev, int ch)
+{
+	const struct dm_demo_cdata *pdata = dev->info->platform_data;
+	struct shape_data *data = dev->priv;
+	static const struct shape {
+		int start;
+		int end;
+		int dstart;
+		int dend;
+	} shapes[3] = {
+		{ 0, 1, 0, 1 },
+		{ 0, WIDTH, 0, 0 },
+		{ HEIGHT / 2 - 1, WIDTH - HEIGHT / 2 + 1, -1, 1},
+	};
+	struct shape shape;
+	unsigned int index;
+	int line, pos, inside;
+	const char *colour = pdata->colour;
+	int first = 0;
+
+	index = (pdata->sides / 2) - 1;
+	if (index >= ARRAY_SIZE(shapes))
+		return -EIO;
+	shape = shapes[index];
+
+	for (line = 0; line < HEIGHT; line++) {
+		first = 1;
+		for (pos = 0; pos < WIDTH; pos++) {
+			inside = pos >= shape.start && pos < shape.end;
+			if (inside) {
+				putc(first ? *colour++ : ch);
+				data->num_chars++;
+				first = 0;
+				if (!*colour)
+					colour = pdata->colour;
+			} else {
+				putc(' ');
+			}
+		}
+		putc('\n');
+		shape.start += shape.dstart;
+		shape.end += shape.dend;
+		if (shape.start < 0) {
+			shape.dstart = -shape.dstart;
+			shape.dend = -shape.dend;
+			shape.start += shape.dstart;
+			shape.end += shape.dend;
+		}
+	}
+
+	return 0;
+}
+
+static int shape_status(struct device *dev, int *status)
+{
+	struct shape_data *data = dev->priv;
+
+	*status = data->num_chars;
+	return 0;
+}
+
+static const struct demo_ops simple_ops = {
+	.hello = shape_hello,
+	.status = shape_status,
+};
+
+U_BOOT_DRIVER(demo_shape_drv) = {
+	.name	= "demo_shape_drv",
+	.id	= UCLASS_DEMO,
+	.ops	= &simple_ops,
+	.priv_data_size = sizeof(struct shape_data),
+};
diff --git a/drivers/demo/demo-simple.c b/drivers/demo/demo-simple.c
new file mode 100644
index 0000000..e0c55f3
--- /dev/null
+++ b/drivers/demo/demo-simple.c
@@ -0,0 +1,82 @@
+/*
+ * (C) Copyright 2013 Google, Inc
+ *
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * 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 <dm-demo.h>
+#include <asm/io.h>
+#include <dm/manager.h>
+
+static int simple_hello(struct device *dev, int ch)
+{
+	const struct dm_demo_cdata *pdata = dev->info->platform_data;
+
+	printf("Hello '%c' from %08x: %s %d\n", ch, map_to_sysmem(dev),
+	       pdata->colour, pdata->sides);
+
+	return 0;
+}
+
+static const struct demo_ops simple_ops = {
+	.hello = simple_hello,
+};
+
+static int simple_bind(struct device *dev)
+{
+	printf("bind from %08x\n", map_to_sysmem(dev));
+	return 0;
+}
+
+static int simple_probe(struct device *dev)
+{
+	printf("probe from %08x\n", map_to_sysmem(dev));
+	return 0;
+}
+
+static int simple_reloc(struct device *new, struct device *old)
+{
+	printf("reloc to %08x from %08x\n", map_to_sysmem(new),
+	       map_to_sysmem(old));
+	return 0;
+}
+
+static int simple_remove(struct device *dev)
+{
+	printf("remove from %08x\n", map_to_sysmem(dev));
+	return 0;
+}
+
+static int simple_unbind(struct device *dev)
+{
+	printf("unbind from %08x\n", map_to_sysmem(dev));
+	return 0;
+}
+
+U_BOOT_DRIVER(demo_simple_drv) = {
+	.name	= "demo_simple_drv",
+	.id	= UCLASS_DEMO,
+	.ops	= &simple_ops,
+	.bind	= simple_bind,
+	.probe	= simple_probe,
+	.reloc	= simple_reloc,
+	.remove	= simple_remove,
+	.unbind	= simple_unbind,
+};
diff --git a/drivers/demo/demo-uclass.c b/drivers/demo/demo-uclass.c
new file mode 100644
index 0000000..a5a3367
--- /dev/null
+++ b/drivers/demo/demo-uclass.c
@@ -0,0 +1,52 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@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 <malloc.h>
+#include <dm-demo.h>
+#include <asm/io.h>
+#include <dm/manager.h>
+#include <linux/list.h>
+
+U_BOOT_CLASS(demo) = {
+	.id		= UCLASS_DEMO,
+};
+
+int demo_hello(struct device *dev, int ch)
+{
+	const struct demo_ops *ops = device_get_ops(dev);
+
+	if (!ops->hello)
+		return -ENOSYS;
+
+	return ops->hello(dev, ch);
+}
+
+int demo_status(struct device *dev, int *status)
+{
+	const struct demo_ops *ops = device_get_ops(dev);
+
+	if (!ops->status)
+		return -ENOSYS;
+
+	return ops->status(dev, status);
+}
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 5416f46..4425284 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -24,6 +24,9 @@
 
 #ifndef __ASM_GENERIC_GBL_DATA_H
 #define __ASM_GENERIC_GBL_DATA_H
+
+#include <linux/list.h>
+
 /*
  * The following data structure is placed in some memory which is
  * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
@@ -80,6 +83,12 @@ typedef struct global_data {
 	unsigned long start_addr_sp;	/* start_addr_stackpointer */
 	unsigned long reloc_off;
 	struct global_data *new_gd;	/* relocated global data */
+
+#ifdef CONFIG_DM
+	struct device	*dm_root;	/* Root instance for Driver Model */
+	struct list_head class_root;	/* Head of core tree */
+#endif
+
 	const void *fdt_blob;	/* Our device tree, NULL if none */
 	void *new_fdt;		/* Relocated FDT */
 	unsigned long fdt_size;	/* Space reserved for relocated FDT */
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index bfedbe4..ead3515 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -94,4 +94,24 @@ int gpio_get_value(unsigned gpio);
  * @return 0 if ok, -1 on error
  */
 int gpio_set_value(unsigned gpio, int value);
+
+/*
+ * Driver model GPIO operations, refer to functions above for description.
+ * These function copy the old API.
+ *
+ * This is trying to be close to Linux GPIO API. Once the U-Boot uses the
+ * new DM GPIO API, this should be really easy to flip over to the Linux
+ * GPIO API-alike interface.
+ */
+struct dm_gpio_ops {
+	int	base;
+	u16	ngpio;
+	int	(*gpio_request)(unsigned gpio, const char *label);
+	int	(*gpio_free)(unsigned gpio);
+	int	(*gpio_direction_input)(unsigned gpio);
+	int	(*gpio_direction_output)(unsigned gpio, int value);
+	int	(*gpio_get_value)(unsigned gpio);
+	int	(*gpio_set_value)(unsigned gpio, int value);
+};
+
 #endif	/* _ASM_GENERIC_GPIO_H_ */
diff --git a/include/command.h b/include/command.h
index 65692fd..445c9e8 100644
--- a/include/command.h
+++ b/include/command.h
@@ -80,6 +80,8 @@ extern int var_complete(int argc, char * const argv[], char last_char, int maxv,
 extern int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp);
 #endif
 
+int cmd_process_error(cmd_tbl_t *cmdtp, int err);
+
 /*
  * Monitor Command
  *
diff --git a/include/common.h b/include/common.h
index 28aa4b9..bdf598f 100644
--- a/include/common.h
+++ b/include/common.h
@@ -911,7 +911,7 @@ static inline void unmap_sysmem(const void *vaddr)
 {
 }
 
-static inline phys_addr_t map_to_sysmem(void *ptr)
+static inline phys_addr_t map_to_sysmem(const void *ptr)
 {
 	return (phys_addr_t)(uintptr_t)ptr;
 }
diff --git a/include/config_fallbacks.h b/include/config_fallbacks.h
index e59ee96..c91a383 100644
--- a/include/config_fallbacks.h
+++ b/include/config_fallbacks.h
@@ -53,4 +53,12 @@
 #define HAVE_BLOCK_DEVICE
 #endif
 
+#ifdef CONFIG_DM
+/* For now, enable the driver model demo command */
+#define CONFIG_DM_DEMO
+#define CONFIG_CMD_DEMO
+#define CONFIG_DM_DEMO_SIMPLE
+#define CONFIG_DM_DEMO_SHAPE
+#endif
+
 #endif	/* __CONFIG_FALLBACKS_H */
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 788207d..76c4398 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -22,6 +22,8 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
+#define CONFIG_DM
+
 /* Number of bits in a C 'long' on this architecture */
 #define CONFIG_SANDBOX_BITS_PER_LONG	64
 
diff --git a/include/dm-demo.h b/include/dm-demo.h
new file mode 100644
index 0000000..3bfac5a
--- /dev/null
+++ b/include/dm-demo.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ * 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 __DM_DEMO_H
+#define __DM_DEMO_H
+
+#include <dm.h>
+
+/**
+ * struct dm_demo_cdata - configuration data for demo instance
+ *
+ * @colour: Color of the demo
+ * @sides: Numbers of sides
+ */
+struct dm_demo_cdata {
+	const char *colour;
+	int sides;
+};
+
+struct demo_ops {
+	int (*hello)(struct device *i, int ch);
+	int (*status)(struct device *i, int *status);
+};
+
+int demo_hello(struct device *i, int ch);
+int demo_status(struct device *i, int *status);
+int demo_list(void);
+
+#endif
diff --git a/include/dm.h b/include/dm.h
new file mode 100644
index 0000000..6af3900
--- /dev/null
+++ b/include/dm.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 Google, Inc
+ *
+ * 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 _DM_H_
+#define _DM_H
+
+#include <dm/manager.h>
+#include <dm/structures.h>
+#include <dm/uclass.h>
+
+#endif
diff --git a/include/dm/debug.h b/include/dm/debug.h
new file mode 100644
index 0000000..3f5ea7b
--- /dev/null
+++ b/include/dm/debug.h
@@ -0,0 +1,33 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@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 _DM_DEBUG_H_
+#define _DM_DEBUG_H_ 1
+
+#include <dm/structures.h>
+
+int dm_dump_all(void);
+int dm_dump(struct device *i);
+
+#endif
diff --git a/include/dm/manager.h b/include/dm/manager.h
new file mode 100644
index 0000000..fcc001e
--- /dev/null
+++ b/include/dm/manager.h
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@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 _DM_MANAGER_H_
+#define _DM_MANAGER_H_
+
+#include <dm/uclass.h>
+#include <dm/structures.h>
+
+/* find-and-add function for the class tree */
+struct uclass *class_get_instance(enum uclass_id id);
+struct u_boot_class *get_class_by_id(enum uclass_id id);
+
+/* class API wrappers */
+int uclass_get_count(enum uclass_id id);
+struct device *uclass_get_child(enum uclass_id id, int index);
+int uclass_bind(enum uclass_id id, struct device *dev);
+int uclass_unbind(enum uclass_id id, struct device *dev);
+int uclass_replace(enum uclass_id id, struct device *new, struct device *old);
+
+/* driver manager API */
+struct device *driver_bind(struct device *parent,
+	const struct driver_info *info);
+int driver_activate(struct device *i);
+int driver_remove(struct device *i);
+int driver_unbind(struct device *dev);
+struct u_boot_driver *get_driver_by_instance(struct device *i);
+
+/* relocation stuff */
+struct device *driver_relocate(struct device *dev, struct device *bus);
+int classs_relocate(void);
+
+/* tree creation helpers */
+int dm_init(void);
+struct device *get_root_instance(void);
+
+#endif
diff --git a/include/dm/structures.h b/include/dm/structures.h
new file mode 100644
index 0000000..32ca832
--- /dev/null
+++ b/include/dm/structures.h
@@ -0,0 +1,97 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ * Marek Vasut <marex@denx.de>
+ *
+ * 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 _DM_STRUCTURES_H_
+#define _DM_STRUCTURES_H_
+
+#include <common.h>
+#include <errno.h>
+#include <linker_lists.h>
+#include <dm/uclass.h>
+#include <linux/list.h>
+
+struct driver_info {
+	const char	*name;
+	const void	*platform_data;
+};
+
+#define DM_FLAG_ACTIVATED 1
+
+struct device {
+	struct u_boot_driver	*driver;
+	const struct driver_info *info;
+	struct device		*bus;
+	void			*priv;
+	struct list_head	class_node;	/* attach instances to class */
+	struct list_head	succ;		/* list of all instances */
+	struct list_head	sibling;	/* siblings */
+	uint32_t		flags;
+};
+
+#define device_get_ops(dev)	(dev->driver->ops)
+
+/* structures for driver manager */
+
+enum aux_data_type {
+	U_BOOT_DRIVER_AUX_NONE = 0,
+	U_BOOT_DRIVER_AUX_USB,
+	U_BOOT_DRIVER_AUX_PCI,
+};
+
+struct u_boot_driver {
+	char		*name;
+	enum		uclass_id id;
+	int		(*bind)(struct device *i);
+	int		(*probe)(struct device *i);
+	int		(*reloc)(struct device *new, struct device *old);
+	int		(*remove)(struct device *i);
+	int		(*unbind)(struct device *i);
+	int		priv_data_size;
+	const void	*ops;	/* driver-specific operations */
+	enum aux_data_type aux_data_type;
+	void		*aux_data;
+};
+
+struct usb_ids {
+	int			(*match)(void);
+	struct	{
+		uint16_t	major;
+		uint16_t	minor;
+	} ids[];
+};
+
+/*
+ * The USB driver has special needs, hence the separate type of driver.
+ * Yet, the struct u_boot_driver must be located at the first place, so the
+ * generic searching functions can be used.
+ */
+struct u_boot_usb_driver {
+	struct u_boot_driver	driver;
+	struct usb_ids		*ids;
+};
+
+#define U_BOOT_DRIVER(__name)						\
+	ll_entry_declare(struct u_boot_driver, __name, driver)
+
+#endif
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
new file mode 100644
index 0000000..ce040e7
--- /dev/null
+++ b/include/dm/uclass.h
@@ -0,0 +1,62 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@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 _DM_UCLASS_H
+#define _DM_UCLASS_H
+
+#include <linux/list.h>
+
+/* TODO: this could be compile-time generated */
+enum uclass_id {
+	UCLASS_GPIO = 0,
+	UCLASS_DEMO,
+
+	UCLASS_COUNT,
+	UCLASS_INVALID = -1,
+};
+
+struct uclass {
+	void			*priv;
+	struct u_boot_class	*dm_class;
+	struct list_head	class_node;	/* instances for this class */
+	struct list_head	succ;
+};
+
+struct device;
+
+struct u_boot_class {
+	enum uclass_id	id;
+	int		(*bind)(struct uclass *class, struct device *dev);
+	int		(*unbind)(struct uclass *class, struct device *dev);
+	int		(*init)(struct uclass *class);
+	int		(*reloc)(struct uclass *new, struct uclass *old);
+	int		(*destroy)(struct uclass *class);
+	int		(*replace)(struct uclass *class, struct device *new,
+				   struct device *old);
+	const void	*ops;	/* class-specific operations */
+};
+
+#define U_BOOT_CLASS(__name)						\
+	ll_entry_declare(struct u_boot_class, __name, class)
+
+#endif
