diff --git a/Makefile b/Makefile
index dbc4b70..8a29b0c 100644
--- a/Makefile
+++ b/Makefile
@@ -337,6 +337,8 @@ LIBS-y += api/libapi.o
 LIBS-y += post/libpost.o
 LIBS-y += test/libtest.o
 
+LIBS-$(CONFIG_DM) += common/dm/libdm.o
+
 ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TI814X),)
 LIBS-y += $(CPUDIR)/omap-common/libomap-common.o
 endif
diff --git a/common/dm/Makefile b/common/dm/Makefile
new file mode 100644
index 0000000..b6ca712
--- /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	:= device.o lists.o root.o uclass.o util.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/device.c b/common/dm/device.c
new file mode 100644
index 0000000..efdc7e8
--- /dev/null
+++ b/common/dm/device.c
@@ -0,0 +1,370 @@
+/*
+ * Device manager
+ *
+ * (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 <common.h>
+#include <malloc.h>
+#include <dm/device.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/platform_data.h>
+#include <dm/uclass.h>
+#include <dm/uclass-internal.h>
+#include <dm/util.h>
+#include <linux/err.h>
+#include <linux/list.h>
+
+/**
+ * device_chld_unbind() - Unbind all device's children from the device
+ * @dev:	The device that is to be stripped of its children
+ * @return 0 on success, -ve on error
+ */
+static int device_chld_unbind(struct device *dev)
+{
+	struct device *pos, *n;
+	int ret;
+
+	assert(dev);
+
+	list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
+		ret = device_unbind(pos);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * device_chld_remove() - Stop all device's children
+ * @dev:	The device whose children are to be removed
+ * @return 0 on success, -ve on error
+ */
+static int device_chld_remove(struct device *dev)
+{
+	struct device *pos, *n;
+	int ret;
+
+	assert(dev);
+
+	list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
+		ret = device_remove(pos);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * device_bind() - Instantiate and connect a driver under a parent one
+ * @parent:	The parent driver, under which the new driver will be connected
+ * @drv:	Driver to use for this device
+ * @name:	Name of device
+ * @platform_data:	Platform data for this device, provided by the board,
+ *		and used to tell the driver about its IO address and so on
+ *		If there is none, this is NULL.
+ * @of_offset:	Device tree node that is attached to this device, or -1 if none
+ * @devp:	Returns a pointer to the newly created device, or NULL on error
+ * @return 0 on success, -ve on error
+ *
+ * Make a new device based on data passed by the user. This device is then
+ * connected under the parent driver. The device is not yet started after
+ * being bound, its only present in the driver tree.
+ */
+int device_bind(struct device *parent, struct driver *drv, const char *name,
+		void *platform_data, int of_offset, struct device **devp)
+{
+	struct device *dev;
+	struct uclass *uc;
+	int ret = 0;
+
+	*devp = NULL;
+	if (!name)
+		return -EINVAL;
+
+	ret = uclass_get(drv->id, &uc);
+	if (ret)
+		return ret;
+
+	dev = calloc(1, sizeof(struct device));
+	if (!dev)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&dev->sibling_node);
+	INIT_LIST_HEAD(&dev->child_head);
+	INIT_LIST_HEAD(&dev->uclass_node);
+	dev->platform_data = platform_data;
+	dev->name = name;
+	dev->of_offset = of_offset;
+	dev->parent = parent;
+	dev->driver = drv;
+	dev->uclass = uc;
+
+	/* put dev into parent's successor list */
+	if (parent)
+		list_add_tail(&dev->sibling_node, &parent->child_head);
+
+	ret = uclass_bind_device(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) {
+			if (uclass_unbind_device(dev)) {
+				dm_warn("Failed to unbind dev '%s' on error path\n",
+					dev->name);
+			}
+			goto fail_bind;
+		}
+	}
+	if (parent)
+		dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
+	*devp = dev;
+
+	return 0;
+
+fail_bind:
+	list_del(&dev->sibling_node);
+	free(dev);
+	return ret;
+}
+
+/**
+ * device_bind_by_name() - Create a device by name
+ * @parent:	The parent driver, under which the new device will be connected
+ * @info:	Information about the driver and platform_data to use
+ * @devp:	Returns a pointer to the newly created device, or NULL on error
+ * @return 0 on success, -ve on error
+ *
+ * Make a new device based on data passed by the user. This device is then
+ * connected under the parent device. The device is not yet started (probed)
+ * after being bound; it is merely present in the driver tree.
+ */
+int device_bind_by_name(struct device *parent, const struct driver_info *info,
+			struct device **devp)
+{
+	struct driver *drv;
+
+	drv = lists_driver_lookup_name(info->name);
+	if (!drv)
+		return -ENOENT;
+
+	return device_bind(parent, drv, info->name,
+			   (void *)info->platform_data, -1, devp);
+}
+
+/**
+ * device_unbind() - Unbind driver from its parent
+ * @dev:	The driver to be unbound
+ * @return 0 on success, -ve on error
+ *
+ * Disconnect a driver from its parent. The driver must be already removed,
+ * otherwise this function fails and doesn't unbind the driver.
+ */
+int device_unbind(struct device *dev)
+{
+	struct driver *drv;
+	int ret;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (dev->flags & DM_FLAG_ACTIVATED)
+		return -EINVAL;
+
+	drv = dev->driver;
+	assert(drv);
+
+	if (drv->unbind) {
+		ret = drv->unbind(dev);
+		if (ret)
+			return ret;
+	}
+
+	ret = device_chld_unbind(dev);
+	if (ret)
+		return ret;
+
+	ret = uclass_unbind_device(dev);
+	if (ret)
+		return ret;
+
+	if (dev->parent)
+		list_del(&dev->sibling_node);
+	free(dev);
+
+	return 0;
+}
+
+/**
+ * device_probe() - Start a device
+ * @dev:	Device that is to be started
+ * @return 0 on success, -ve on error
+ *
+ * This function runs the device's probe() function, which initializes the
+ * hardware. The hardware and all its predecessors are started by this
+ * function.
+ */
+int device_probe(struct device *dev)
+{
+	struct driver *drv;
+	int size;
+	int ret;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (dev->flags & DM_FLAG_ACTIVATED)
+		return 0;
+
+	drv = dev->driver;
+	assert(drv);
+
+	/* Allocate private data and platform_data if requested */
+	if (drv->priv_size) {
+		dev->priv = calloc(1, drv->priv_size);
+		if (!dev->priv)
+			return -ENOMEM;
+	}
+	/* Allocate private data if requested */
+	if (drv->platform_data_size) {
+		dev->platform_data = calloc(1, drv->platform_data_size);
+		if (!dev->platform_data)
+			return -ENOMEM;
+	}
+	size = dev->uclass->uc_drv->per_device_priv_size;
+	if (size) {
+		dev->uclass_priv = calloc(1, size);
+		if (!dev->uclass_priv)
+			return -ENOMEM;
+	}
+
+	/* Ensure all parents are probed */
+	if (dev->parent) {
+		ret = device_probe(dev->parent);
+		if (ret)
+			goto fail;
+	}
+
+	if (drv->probe) {
+		ret = drv->probe(dev);
+		if (ret)
+			goto fail;
+	}
+
+	dev->flags |= DM_FLAG_ACTIVATED;
+
+	ret = uclass_post_probe_device(dev);
+	if (ret) {
+		dev->flags &= ~DM_FLAG_ACTIVATED;
+		goto fail_uclass;
+	}
+
+	return 0;
+fail_uclass:
+	if (device_remove(dev)) {
+		dm_warn("%s: Device '%s' failed to remove on error path\n",
+			__func__, dev->name);
+	}
+fail:
+	if (drv->priv_size) {
+		free(dev->priv);
+		dev->priv = NULL;
+	}
+
+	return ret;
+}
+
+/**
+ * device_remove() - Disable the device and its children
+ * @dev:	The device to be disabled
+ * @return 0 on success, -ve on error
+ *
+ * Deconfigure the hardware and all its children.
+ */
+int device_remove(struct device *dev)
+{
+	struct driver *drv;
+	int size;
+	int ret;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (!(dev->flags & DM_FLAG_ACTIVATED))
+		return 0;
+
+	drv = dev->driver;
+	assert(drv);
+
+	ret = uclass_pre_remove_device(dev);
+	if (ret)
+		return ret;
+
+	ret = device_chld_remove(dev);
+	if (ret)
+		goto err;
+
+	if (drv->remove) {
+		ret = drv->remove(dev);
+		if (ret)
+			goto err_remove;
+	}
+
+	if (dev->driver->priv_size) {
+		free(dev->priv);
+		dev->priv = NULL;
+	}
+	if (dev->driver->platform_data_size) {
+		free(dev->platform_data);
+		dev->platform_data = NULL;
+	}
+	size = dev->uclass->uc_drv->per_device_priv_size;
+	if (size) {
+		free(dev->uclass_priv);
+		dev->uclass_priv = NULL;
+	}
+
+	dev->flags &= ~DM_FLAG_ACTIVATED;
+
+	return 0;
+
+err_remove:
+	/* We can't put the children back */
+	dm_warn("%s: Device '%s' failed to remove, but children are gone\n",
+		__func__, dev->name);
+err:
+	ret = uclass_post_probe_device(dev);
+	if (ret) {
+		dm_warn("%s: Device '%s' failed to post_probe on error path\n",
+			__func__, dev->name);
+	}
+
+	return ret;
+}
diff --git a/common/dm/lists.c b/common/dm/lists.c
new file mode 100644
index 0000000..02bcb50
--- /dev/null
+++ b/common/dm/lists.c
@@ -0,0 +1,181 @@
+/*
+ * (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 <errno.h>
+#include <dm/device.h>
+#include <dm/device-internal.h>
+#include <dm/platform_data.h>
+#include <dm/uclass.h>
+#include <dm/util.h>
+#include <linux/compiler.h>
+
+/**
+ * lists_driver_lookup_name() - Return u_boot_driver corresponding 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 driver *lists_driver_lookup_name(const char *name)
+{
+	struct driver *drv =
+		ll_entry_start(struct driver, driver);
+	const int n_ents = ll_entry_count(struct driver, driver);
+	struct driver *entry;
+	int len;
+
+	if (!drv || !n_ents)
+		return NULL;
+
+	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;
+}
+
+/**
+ * lists_uclass_lookup() - Return uclass_driver based on ID of the class
+ * id:		ID of the class
+ *
+ * This function returns the pointer to uclass_driver, which is the class's
+ * base structure based on the ID of the class. Returns NULL on error.
+ */
+struct uclass_driver *lists_uclass_lookup(enum uclass_id id)
+{
+	struct uclass_driver *uclass =
+		ll_entry_start(struct uclass_driver, uclass);
+	const int n_ents = ll_entry_count(struct uclass_driver, uclass);
+	struct uclass_driver *entry;
+
+	if ((id == UCLASS_INVALID) || !uclass)
+		return NULL;
+
+	for (entry = uclass; entry != uclass + n_ents; entry++) {
+		if (entry->id == id)
+			return entry;
+	}
+
+	return NULL;
+}
+
+int lists_bind_drivers(struct device *parent)
+{
+	struct driver_info *info =
+		ll_entry_start(struct driver_info, driver_info);
+	const int n_ents = ll_entry_count(struct driver_info, driver_info);
+	struct driver_info *entry;
+	struct device *dev;
+	int result = 0;
+	int ret;
+
+	for (entry = info; entry != info + n_ents; entry++) {
+		ret = device_bind_by_name(parent, entry, &dev);
+		if (ret) {
+			dm_warn("No match for driver '%s'\n", entry->name);
+			if (!result || ret != -ENOENT)
+				result = ret;
+		}
+	}
+
+	return result;
+}
+
+/**
+ * driver_check_compatible() - Check if a driver is compatible with this node
+ *
+ * @param blob:		Device tree pointer
+ * @param offset:	Offset of node in device tree
+ * @param of_matchL	List of compatible strings to match
+ * @return 0 if there is a match, -ENOENT if no match, -ENODEV if the node
+ * does not have a compatible string, other error <0 if there is a device
+ * tree error
+ */
+static int driver_check_compatible(const void *blob, int offset,
+				   const struct device_id *of_match)
+{
+	int ret;
+
+	if (!of_match)
+		return -ENOENT;
+
+	while (of_match->compatible) {
+		ret = fdt_node_check_compatible(blob, offset,
+						of_match->compatible);
+		if (!ret)
+			return 0;
+		else if (ret == -FDT_ERR_NOTFOUND)
+			return -ENODEV;
+		else if (ret < 0)
+			return -EINVAL;
+		of_match++;
+	}
+
+	return -ENOENT;
+}
+
+int lists_bind_fdt(struct device *parent, const void *blob, int offset)
+{
+	struct driver *driver = ll_entry_start(struct driver, driver);
+	const int n_ents = ll_entry_count(struct driver, driver);
+	struct driver *entry;
+	struct device *dev;
+	const char *name;
+	int result = 0;
+	int ret;
+
+	dm_dbg("bind node %s\n", fdt_get_name(blob, offset, NULL));
+	for (entry = driver; entry != driver + n_ents; entry++) {
+		ret = driver_check_compatible(blob, offset, entry->of_match);
+		if (ret == -ENOENT) {
+			continue;
+		} else if (ret == -ENODEV) {
+			break;
+		} else if (ret) {
+			dm_warn("Device tree error at offset %d\n", offset);
+			if (!result || ret != -ENOENT)
+				result = ret;
+			break;
+		}
+
+		name = fdt_get_name(blob, offset, NULL);
+		dm_dbg("   - found match at '%s'\n", entry->name);
+		ret = device_bind(parent, entry, name, NULL, offset, &dev);
+		if (ret) {
+			dm_warn("No match for driver '%s'\n", entry->name);
+			if (!result || ret != -ENOENT)
+				result = ret;
+		}
+	}
+
+	return result;
+}
diff --git a/common/dm/root.c b/common/dm/root.c
new file mode 100644
index 0000000..bba793a
--- /dev/null
+++ b/common/dm/root.c
@@ -0,0 +1,124 @@
+/*
+ * (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 <errno.h>
+#include <malloc.h>
+#include <dm/device.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/platform_data.h>
+#include <dm/uclass.h>
+#include <dm/util.h>
+#include <linux/list.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct driver_info root_info = {
+	.name		= "root_driver",
+};
+
+/**
+ * dm_root() - 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 *dm_root(void)
+{
+	if (!gd->dm_root) {
+		dm_warn("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 ret;
+
+	if (gd->dm_root) {
+		dm_warn("Virtual root driver already exists!\n");
+		return -EINVAL;
+	}
+	INIT_LIST_HEAD(&gd->uclass_root);
+
+	ret = device_bind_by_name(NULL, &root_info, &gd->dm_root);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int dm_scan_platform_data(void)
+{
+	int ret;
+
+	ret = lists_bind_drivers(gd->dm_root);
+	if (ret == -ENOENT) {
+		dm_warn("Some drivers were not found\n");
+		ret = 0;
+	}
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int dm_scan_fdt(const void *blob)
+{
+	int offset = 0;
+	int ret = 0, err;
+	int depth = 0;
+
+	do {
+		offset = fdt_next_node(blob, offset, &depth);
+		if (offset > 0 && depth == 1) {
+			err = lists_bind_fdt(gd->dm_root, blob, offset);
+			if (err && !ret)
+				ret = err;
+		}
+	} while (offset > 0);
+
+	if (ret)
+		dm_warn("Some drivers failed to bind\n");
+
+	return ret;
+}
+
+U_BOOT_DRIVER(root_driver) = {
+	.name	= "root_driver",
+	.id	= UCLASS_ROOT,
+};
+
+UCLASS_DRIVER(root) = {
+	.name	= "root",
+	.id	= UCLASS_ROOT,
+};
diff --git a/common/dm/uclass.c b/common/dm/uclass.c
new file mode 100644
index 0000000..4ff308e
--- /dev/null
+++ b/common/dm/uclass.c
@@ -0,0 +1,362 @@
+/*
+ * (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 <errno.h>
+#include <malloc.h>
+#include <dm/device.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/uclass.h>
+#include <dm/uclass-internal.h>
+#include <dm/util.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * uclass_find() - Find uclass by its id
+ * @id:		Id to serach for
+ * @return pointer to uclass, or NULL if not found
+ */
+struct uclass *uclass_find(enum uclass_id key)
+{
+	struct uclass *uc;
+
+	/*
+	 * TODO(sjg@chromium.org): Optimise this, perhaps moving the found
+	 * node to the start of the list, or creating a linear array mapping
+	 * id to node.
+	 */
+	list_for_each_entry(uc, &gd->uclass_root, sibling_node) {
+		if (uc->uc_drv->id == key)
+			return uc;
+	}
+
+	return NULL;
+}
+
+/**
+ * uclass_add() - Create new uclass in list
+ * @id: Id number to create
+ * @ucp: Returns pointer to uclass, or NULL on error
+ * @return 0 on success, -ve on error
+ *
+ * The new uclass is added to the list. There must be only one uclass for
+ * each id.
+ */
+static int uclass_add(enum uclass_id id, struct uclass **ucp)
+{
+	struct uclass_driver *uc_drv;
+	struct uclass *uc;
+	int ret;
+
+	*ucp = NULL;
+	uc_drv = lists_uclass_lookup(id);
+	if (!uc_drv) {
+		dm_warn("Cannot find uclass for id %d: please add the UCLASS_DRIVER() declaration for this UCLASS_... id\n",
+			id);
+		return -ENOENT;
+	}
+	if (uc_drv->ops) {
+		dm_warn("No ops for uclass id %d\n", id);
+		return -EINVAL;
+	}
+	uc = calloc(1, sizeof(*uc));
+	if (!uc)
+		return -ENOMEM;
+	if (uc_drv->priv_size) {
+		uc->priv = calloc(1, uc_drv->priv_size);
+		if (!uc->priv) {
+			ret = -ENOMEM;
+			goto fail_mem;
+		}
+	}
+	uc->uc_drv = uc_drv;
+	INIT_LIST_HEAD(&uc->sibling_node);
+	INIT_LIST_HEAD(&uc->dev_head);
+	list_add(&uc->sibling_node, &gd->uclass_root);
+
+	if (uc_drv->init) {
+		ret = uc_drv->init(uc);
+		if (ret)
+			goto fail;
+	}
+
+	*ucp = uc;
+
+	return 0;
+fail:
+	if (uc_drv->priv_size) {
+		free(uc->priv);
+		uc->priv = NULL;
+	}
+	list_del(&uc->sibling_node);
+fail_mem:
+	free(uc);
+
+	return ret;
+}
+
+int uclass_destroy(struct uclass *uc)
+{
+	struct uclass_driver *uc_drv;
+	struct device *dev, *tmp;
+	int ret;
+
+	list_for_each_entry_safe(dev, tmp, &uc->dev_head, uclass_node) {
+		ret = device_remove(dev);
+		if (ret)
+			return ret;
+		ret = device_unbind(dev);
+		if (ret)
+			return ret;
+	}
+
+	uc_drv = uc->uc_drv;
+	if (uc_drv->destroy)
+		uc_drv->destroy(uc);
+	list_del(&uc->sibling_node);
+	if (uc_drv->priv_size)
+		free(uc->priv);
+	free(uc);
+
+	return 0;
+}
+
+/**
+ * uclass_get() - Return or create uclass by id
+ * @id:	Search uclass with this id or create new one
+ * @ucp: Returns pointer to uclass, or NULL on error
+ * @return 0 on success, -ve on error
+ *
+ * Try to find uclass in list structure. If fail create a new uclass and place
+ * it in list.
+ */
+int uclass_get(enum uclass_id id, struct uclass **ucp)
+{
+	struct uclass *uc;
+
+	*ucp = NULL;
+	uc = uclass_find(id);
+	if (!uc)
+		return uclass_add(id, ucp);
+	*ucp = uc;
+
+	return 0;
+}
+
+/**
+ * uclass_find_device() - Return n-th child of uclass
+ * @id:		Id number of the uclass
+ * @index:	Position of the child in uclass's list
+ * #devp:	Returns pointer to device, or NULL on error
+ *
+ * The device is not prepared for use - this is an internal function
+ *
+ * Return the uclass pointer of a child at the given index or
+ * return NULL on error.
+ */
+int uclass_find_device(enum uclass_id id, int index, struct device **devp)
+{
+	struct uclass *uc;
+	struct device *dev;
+	int ret;
+
+	*devp = NULL;
+	ret = uclass_get(id, &uc);
+	if (ret)
+		return ret;
+
+	list_for_each_entry(dev, &uc->dev_head, uclass_node) {
+		if (!index--) {
+			*devp = dev;
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
+/**
+ * uclass_get_device() - Return n-th child of uclass
+ * @id:		Id number of the uclass
+ * @index:	Position of the child in uclass's list
+ *
+ * The device is prepared for use (probed) if needed.
+ *
+ * Return the uclass pointer of a child at the given index or
+ * return NULL on error.
+ */
+int uclass_get_device(enum uclass_id id, int index, struct device **devp)
+{
+	struct device *dev;
+	int ret;
+
+	*devp = NULL;
+	ret = uclass_find_device(id, index, &dev);
+	if (ret)
+		return ret;
+
+	ret = device_probe(dev);
+	if (ret)
+		return ret;
+
+	*devp = dev;
+
+	return 0;
+}
+
+int uclass_first_device(enum uclass_id id, struct device **devp)
+{
+	struct uclass *uc;
+	struct device *dev;
+	int ret;
+
+	*devp = NULL;
+	ret = uclass_get(id, &uc);
+	if (ret)
+		return ret;
+	if (list_empty(&uc->dev_head))
+		return 0;
+
+	dev = list_first_entry(&uc->dev_head, struct device, uclass_node);
+	ret = device_probe(dev);
+	if (ret)
+		return ret;
+	*devp = dev;
+
+	return 0;
+}
+
+int uclass_next_device(struct device **devp)
+{
+	struct device *dev = *devp;
+	int ret;
+
+	*devp = NULL;
+	if (list_is_last(&dev->uclass_node, &dev->uclass->dev_head))
+		return 0;
+
+	dev = list_entry(dev->uclass_node.next, struct device, uclass_node);
+	ret = device_probe(dev);
+	if (ret)
+		return ret;
+	*devp = dev;
+
+	return 0;
+}
+
+/**
+ * uclass_bind_device() - Associate device with a uclass
+ * @dev:	Pointer to the device
+ *
+ * Connect the device into uclass's list of devices. Returns 0 on success,
+ * negative value on error.
+ */
+int uclass_bind_device(struct device *dev)
+{
+	struct uclass *uc;
+	int ret;
+
+	uc = dev->uclass;
+
+	list_add_tail(&dev->uclass_node, &uc->dev_head);
+
+	if (uc->uc_drv->post_bind) {
+		ret = uc->uc_drv->post_bind(dev);
+		if (ret) {
+			list_del(&dev->uclass_node);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * uclass_unbind_device() - Deassociate device with a uclass
+ * @dev:	Pointer to the device
+ *
+ * Disconnect the device from uclass's list of devices.
+ * Returns 0 on success, negative value on error.
+ */
+int uclass_unbind_device(struct device *dev)
+{
+	struct uclass *uc;
+	int ret;
+
+	uc = dev->uclass;
+	if (uc->uc_drv->pre_unbind) {
+		ret = uc->uc_drv->pre_unbind(dev);
+		if (ret)
+			return ret;
+	}
+
+	list_del(&dev->uclass_node);
+	return 0;
+}
+
+/**
+ * uclass_post_probe_device() - Deal with a device that has just been probed
+ * @dev:	Pointer to the device
+ *
+ * Perform any post-processing of a probed device that is needed by the
+ * uclass. Returns 0 on success,negative value on error.
+ */
+int uclass_post_probe_device(struct device *dev)
+{
+	struct uclass_driver *uc_drv = dev->uclass->uc_drv;
+
+	if (uc_drv->post_probe)
+		return uc_drv->post_probe(dev);
+
+	return 0;
+}
+
+/**
+ * uclass_pre_remove_device() - Handle a device which is about to be removed
+ * @dev:	Pointer to the device
+ *
+ * Perform any pre-processing of a device that is about to be removed.
+ * Returns 0 on success, negative value on error.
+ */
+int uclass_pre_remove_device(struct device *dev)
+{
+	struct uclass_driver *uc_drv;
+	struct uclass *uc;
+	int ret;
+
+	uc = dev->uclass;
+	uc_drv = uc->uc_drv;
+	if (uc->uc_drv->pre_remove) {
+		ret = uc->uc_drv->pre_remove(dev);
+		if (ret)
+			return ret;
+	}
+	if (uc_drv->per_device_priv_size) {
+		free(dev->uclass_priv);
+		dev->uclass_priv = NULL;
+	}
+
+	return 0;
+}
diff --git a/common/dm/util.c b/common/dm/util.c
new file mode 100644
index 0000000..01ffde6
--- /dev/null
+++ b/common/dm/util.c
@@ -0,0 +1,50 @@
+/*
+ * (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 <vsprintf.h>
+
+void dm_warn(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	vprintf(fmt, args);
+	va_end(args);
+}
+
+void dm_dbg(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	vprintf(fmt, args);
+	va_end(args);
+}
+
+int list_count_items(struct list_head *head)
+{
+	struct list_head *node;
+	int count = 0;
+
+	list_for_each(node, head)
+		count++;
+
+	return count;
+}
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 5416f46..f952d9a 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -24,6 +24,7 @@
 
 #ifndef __ASM_GENERIC_GBL_DATA_H
 #define __ASM_GENERIC_GBL_DATA_H
+
 /*
  * The following data structure is placed in some memory which is
  * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
@@ -37,6 +38,8 @@
  */
 
 #ifndef __ASSEMBLY__
+#include <linux/list.h>
+
 typedef struct global_data {
 	bd_t *bd;
 	unsigned long flags;
@@ -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 uclass_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/dm.h b/include/dm.h
new file mode 100644
index 0000000..4dec8fd
--- /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/device.h>
+#include <dm/platform_data.h>
+#include <dm/uclass.h>
+
+#endif
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
new file mode 100644
index 0000000..b760d5c
--- /dev/null
+++ b/include/dm/device-internal.h
@@ -0,0 +1,38 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ * Marek Vasut <marex@denx.de>
+ *
+ * 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_DEVICE_INTERNAL_H
+#define _DM_DEVICE_INTERNAL_H
+
+struct device;
+
+/* driver manager API */
+int device_bind(struct device *parent, struct driver *drv,
+		const char *name, void *platform_data, int of_offset,
+		struct device **devp);
+int device_bind_by_name(struct device *parent, const struct driver_info *info,
+			struct device **devp);
+
+int device_probe(struct device *dev);
+int device_remove(struct device *dev);
+int device_unbind(struct device *dev);
+
+#endif
diff --git a/include/dm/device.h b/include/dm/device.h
new file mode 100644
index 0000000..f1d3760
--- /dev/null
+++ b/include/dm/device.h
@@ -0,0 +1,72 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ * Marek Vasut <marex@denx.de>
+ *
+ * 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_DEVICE_H
+#define _DM_DEVICE_H
+
+#include <dm/uclass-id.h>
+#include <linker_lists.h>
+#include <linux/list.h>
+
+struct driver_info;
+
+#define DM_FLAG_ACTIVATED 1
+
+struct device {
+	struct driver *driver;
+	const char *name;
+	void *platform_data;
+	int of_offset;
+	struct device *parent;
+	void *priv;
+	struct uclass *uclass;
+	void *uclass_priv;
+	struct list_head uclass_node;	/* attach devices to class */
+	struct list_head child_head;	/* list of child devices */
+	struct list_head sibling_node;	/* siblings */
+	uint32_t flags;
+};
+
+#define device_get_ops(dev)	(dev->driver->ops)
+#define device_active(dev)	((dev)->flags & DM_FLAG_ACTIVATED)
+
+struct device_id {
+	const char *compatible;
+	ulong data;
+};
+
+struct driver {
+	char *name;
+	enum uclass_id id;
+	const struct device_id *of_match;
+	int (*bind)(struct device *dev);
+	int (*probe)(struct device *dev);
+	int (*remove)(struct device *dev);
+	int (*unbind)(struct device *dev);
+	int priv_size;
+	int platform_data_size;
+	const void *ops;	/* driver-specific operations */
+};
+
+#define U_BOOT_DRIVER(__name)						\
+	ll_entry_declare(struct driver, __name, driver)
+
+#endif
diff --git a/include/dm/lists.h b/include/dm/lists.h
new file mode 100644
index 0000000..8909202
--- /dev/null
+++ b/include/dm/lists.h
@@ -0,0 +1,37 @@
+/*
+ * (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_LISTS_H_
+#define _DM_LISTS_H_
+
+#include <dm/uclass-id.h>
+
+struct driver *lists_driver_lookup_name(const char *name);
+
+struct uclass_driver *lists_uclass_lookup(enum uclass_id id);
+
+int lists_bind_drivers(struct device *parent);
+
+int lists_bind_fdt(struct device *parent, const void *blob, int offset);
+
+#endif
diff --git a/include/dm/platform_data.h b/include/dm/platform_data.h
new file mode 100644
index 0000000..5420c03
--- /dev/null
+++ b/include/dm/platform_data.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 Google, Inc
+ *
+ * (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_PLATFORM_DATA_H
+#define _DM_PLATFORM_DATA_H
+
+struct driver_info {
+	const char	*name;
+	const void	*platform_data;
+};
+
+#define U_BOOT_DEVICE(__name)						\
+	ll_entry_declare(struct driver_info, __name, driver_info)
+
+#endif
diff --git a/include/dm/root.h b/include/dm/root.h
new file mode 100644
index 0000000..9c3e732
--- /dev/null
+++ b/include/dm/root.h
@@ -0,0 +1,38 @@
+/*
+ * (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_ROOT_H_
+#define _DM_ROOT_H_
+
+struct device;
+
+/* tree creation helpers */
+struct device *dm_root(void);
+
+int dm_scan_platform_data(void);
+
+int dm_scan_fdt(const void *blob);
+
+int dm_init(void);
+
+#endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
new file mode 100644
index 0000000..9248ca5
--- /dev/null
+++ b/include/dm/uclass-id.h
@@ -0,0 +1,42 @@
+/*
+ * (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_ID_H
+#define _DM_UCLASS_ID_H
+
+/* TODO: this could be compile-time generated */
+enum uclass_id {
+	/* These are used internally by driver model */
+	UCLASS_ROOT = 0,
+	UCLASS_DEMO,
+	UCLASS_TEST,
+	UCLASS_TEST_FDT,
+
+	/* U-Boot uclasses start here */
+	UCLASS_GPIO,
+
+	UCLASS_COUNT,
+	UCLASS_INVALID = -1,
+};
+
+#endif
diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h
new file mode 100644
index 0000000..9424763
--- /dev/null
+++ b/include/dm/uclass-internal.h
@@ -0,0 +1,36 @@
+/*
+ * (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_INTERNAL_H
+#define _DM_UCLASS_INTERNAL_H
+
+int uclass_find_device(enum uclass_id id, int index, struct device **devp);
+
+int uclass_bind_device(struct device *dev);
+int uclass_unbind_device(struct device *dev);
+int uclass_post_probe_device(struct device *dev);
+int uclass_pre_remove_device(struct device *dev);
+struct uclass *uclass_find(enum uclass_id key);
+int uclass_destroy(struct uclass *uc);
+
+#endif
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
new file mode 100644
index 0000000..4f210b8
--- /dev/null
+++ b/include/dm/uclass.h
@@ -0,0 +1,74 @@
+/*
+ * (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 <dm/uclass-id.h>
+#include <linux/list.h>
+
+struct uclass {
+	void *priv;
+	struct uclass_driver *uc_drv;
+	struct list_head dev_head;	/* devices in this class */
+	struct list_head sibling_node;	/* next uclsas */
+};
+
+struct device;
+
+/* Linker list uclass description */
+struct uclass_driver {
+	const char *name;
+	enum uclass_id id;
+	int (*post_bind)(struct device *dev);
+	int (*pre_unbind)(struct device *dev);
+	int (*post_probe)(struct device *dev);
+	int (*pre_remove)(struct device *dev);
+	int (*init)(struct uclass *class);
+	int (*destroy)(struct uclass *class);
+	int priv_size;
+	int per_device_priv_size;
+	const void *ops;	/* class-specific operations */
+};
+
+#define UCLASS_DRIVER(__name)						\
+	ll_entry_declare(struct uclass_driver, __name, uclass)
+
+/* uclass API wrappers */
+int uclass_get(enum uclass_id key, struct uclass **ucp);
+
+int uclass_get_device(enum uclass_id id, int index, struct device **ucp);
+
+int uclass_first_device(enum uclass_id id, struct device **devp);
+
+int uclass_next_device(struct device **devp);
+
+#define uclass_foreach_dev(pos, head)					\
+	for (pos = list_entry((&(uc)->dev_head)->next, typeof(*pos),	\
+			uclass_node);					\
+	     prefetch(pos->uclass_node.next),				\
+			&pos->uclass_node != (&(uc)->dev_head);		\
+	     pos = list_entry(pos->uclass_node.next, typeof(*pos),	\
+			uclass_node))
+
+#endif
diff --git a/include/dm/util.h b/include/dm/util.h
new file mode 100644
index 0000000..0b41907
--- /dev/null
+++ b/include/dm/util.h
@@ -0,0 +1,42 @@
+/*
+ * (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
+ */
+
+#ifndef __DM_UTIL_H
+
+void dm_warn(const char *fmt, ...);
+
+#ifdef DEBUG
+void dm_dbg(const char *fmt, ...);
+#else
+static inline void dm_dbg(const char *fmt, ...)
+{
+}
+#endif
+
+struct list_head;
+
+/**
+ * list_count_items() - Count number of items in a list
+ *
+ * @param head:		Head of list
+ * @return number of items, or 0 if empty
+ */
+int list_count_items(struct list_head *head);
+
+#endif
