diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 4edff7d..cf9a21e 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -4,7 +4,7 @@ obj-y			:= component.o core.o bus.o dd.o syscore.o \
 			   driver.o class.o platform.o \
 			   cpu.o firmware.o init.o map.o devres.o \
 			   attribute_container.o transport_class.o \
-			   topology.o container.o track.o
+			   topology.o container.o track.o restrack.o
 obj-$(CONFIG_DEVTMPFS)	+= devtmpfs.o
 obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
 obj-y			+= power/
diff --git a/drivers/base/restrack.c b/drivers/base/restrack.c
new file mode 100644
index 0000000..e16d8ed
--- /dev/null
+++ b/drivers/base/restrack.c
@@ -0,0 +1,344 @@
+/*
+ * Resource tracking framework
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ * Andrzej Hajda <a.hajda@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * restrack framework allows to track presence of resources with dynamic life
+ * time. Typical example of such resources are all resources provided by device
+ * drivers, for example clocks, phys, regulators. Since drivers can be bound and
+ * unbound dynamically and unconditionally, resources provided by such drivers
+ * can appear and disappear at any time.
+ *
+ * To use restrack in consumer user should call one of *restrack_register
+ * functions. In the function arguments consumer should provide callback and
+ * description of resources which should be tracked. Each resource description
+ * should contain pointer to variable where restrack should store address of
+ * allocated resource and parameters describing specific resource, for example
+ * in case of clock it should be clock name and in case of gpio it should be
+ * gpio name and flags.
+ * The callback should have two arguments:
+ * - dev - device for which callback have been registered,
+ * - ret - return code.
+ * If callback is called with ret == 0 it means all tracked resources are
+ * present, allocated and provided resource pointers are set accordingly.
+ * In case ret == -EPROBE_DEFER it means all resources are present but at least
+ * one of the resources are to be removed after return form the callback.
+ *
+ * Simplified example of framework usage on LCD panel driver.
+ *
+ * static int lcd_probe(...)
+ * {
+ *	struct restrack *rtrack;
+ *
+ *	(...initialization w/o resource allocation ...)
+ *
+ *	rtrack = devm_restrack_register(dev, lcd_callback,
+ *		regulator_bulk_restrack_desc(&ctx->supplies[0]),
+ *		regulator_bulk_restrack_desc(&ctx->supplies[1]),
+ *		clk_restrack_desc(&ctx->pll_clk, "pll_clk"),
+ *		clk_restrack_desc(&ctx->bus_clk, "bus_clk"),
+ *		phy_restrack_desc(&ctx->phy, "dsim"),
+ *	);
+ *
+ *	return PTR_ERR_OR_NULL(rtrack);
+ * }
+ *
+ * void lcd_callback(struct device *dev, int ret)
+ * {
+ *	struct lcd_ctx *ctx = dev_get_drvdata(dev);
+ *
+ *	if (ret == 0)
+ *		drm_panel_add(&ctx->panel);
+ *	else if (ret == -EPROBE_DEFER)
+ *		drm_panel_remove(&ctx->panel);
+ *	else
+ *		dev_err(dev, "restrack error %d\n", ret);
+ * }
+ *
+ * Please note few things:
+ * 1. drm_panel_add calls restrack_up and drm_panel_remove calls restrack_down.
+ *    It is OK to call restrack framework from the callback.
+ * 2. In lcd_callback if ret is 0 or -EDEFER_PROBE all resources are valid, ie
+ *    driver for example can call clk_prepare_enable(ctx->pll_clk).
+ * 3. No mutexes are needed to protect lcd_ctx in lcd_callback call.
+ * 4. All resources are freed by restrack_unregister, which in this case is
+ *    called by devres framework.
+ *
+ * To add restrack support to specific framework following things should be
+ * defined:
+ * - structure describing resource with embedded restrack_desc structure,
+ * - at least one exported allocator of such structure,
+ * - few simple operations according to description of struct restrack_ops,
+ * - notifications about adding/removal of the resource.
+ * For details please look at existing implementations.
+ *
+ */
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/restrack.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/track.h>
+
+static DEFINE_TRACKER(restrack);
+
+struct restrack_ctx {
+	struct device *dev;
+	unsigned int count;
+	unsigned int get_count;
+	restrack_fn_t callback;
+	struct restrack_desc *desc[0];
+};
+
+/**
+ * restrack_up - notify that resource provider is up
+ * @type: resource type
+ * @id: resource id
+ * @data: @type dependent cookie, usually pointer to resource provider
+ */
+int restrack_up(unsigned long type, const void *id, void *data)
+{
+	return track_up(&restrack, type, id, data);
+}
+
+/**
+ * restrack_down - notify that resource provider is down
+ * @type: resource type
+ * @id: resource id
+ * @data: @type dependent cookie, usually pointer to resource provider
+ */
+int restrack_down(unsigned long type, const void *id, void *data)
+{
+	return track_down(&restrack, type, id, data);
+}
+
+static void restrack_itb_cb(struct track_block *itb, void *data, bool on)
+{
+	struct restrack_desc *desc;
+	struct restrack_ctx *ctx;
+	int i;
+
+	desc = container_of(itb, struct restrack_desc, itb);
+	ctx = desc->ctx;
+
+	for (i = 0; i < ctx->count; ++i) {
+		struct restrack_desc *d = ctx->desc[i];
+
+		if ((d->if_id != desc->if_id) ||
+		    (d->ops->if_type != desc->ops->if_type))
+			continue;
+
+		pr_debug("%s:%d: if_type=%ld on=%d res=%d/%d\n", __func__,
+			 __LINE__, d->ops->if_type, on, i, ctx->count);
+
+		if (on) {
+			if (!d->status)
+				continue;
+
+			d->status = d->ops->if_up(ctx->dev, d, data);
+
+			if (!d->status)
+				++ctx->get_count;
+
+			if (d->status == -EPROBE_DEFER)
+				continue;
+
+			if (d->status || ctx->get_count == ctx->count)
+				ctx->callback(ctx->dev, d->status);
+		} else {
+			if (!d->status) {
+				if (ctx->get_count-- == ctx->count)
+					ctx->callback(ctx->dev, -EPROBE_DEFER);
+				d->ops->if_down(ctx->dev, d, data);
+			}
+			d->status = -EPROBE_DEFER;
+		}
+	}
+}
+
+/* check if the same interface is present in previous restrack descriptors */
+static bool restrack_find_prev_if(struct restrack_ctx *ctx, int n)
+{
+	struct restrack_desc *desc = ctx->desc[n];
+	int i;
+
+	for (i = 0; i < n; ++i) {
+		struct restrack_desc *d = ctx->desc[i];
+
+		if (d->if_id == desc->if_id &&
+		    d->ops->if_type == desc->ops->if_type)
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ * restrack_unregister - unregister restrack callback
+ * @ctx: restrack context, previously allocated by __restrack_register
+ */
+
+void restrack_unregister(struct restrack_ctx *ctx)
+{
+	int i;
+
+	i = ctx->count;
+	while (i-- > 0) {
+		struct restrack_desc *desc = ctx->desc[i];
+
+		if (IS_ERR(desc))
+			continue;
+
+		if (restrack_find_prev_if(ctx, i))
+			continue;
+
+		track_unregister(&restrack, &desc->itb, desc->ops->if_type,
+				 desc->if_id);
+	}
+
+	i = ctx->count;
+	while (i-- > 0) {
+		struct restrack_desc *desc = ctx->desc[i];
+
+		if (IS_ERR(desc))
+			continue;
+
+		if (desc->ops->destroy)
+			desc->ops->destroy(ctx->dev, desc);
+		else
+			kfree(desc);
+	}
+
+	kfree(ctx);
+}
+
+/**
+ * __restrack_register - register resource tracker callback
+ * @dev: consumer device
+ * @callback: callback which will be called when:
+ *	- all tracked resources become available, with @ret = 0
+ *	- one of the resources becomes unavailable, with @ret = -EPROBE_DEFER,
+ *	- resource allocation errors, with @ret equal to this error
+ * @count: number of resource descriptors to track
+ * @descs: list of pointers to resource descriptors to track
+ *
+ * It can be called as follows:
+ *	struct restrack_desc *descriptors[] = {
+ *		regulator_bulk_restrack_desc(&ctx->supplies[0]),
+ *		regulator_bulk_restrack_desc(&ctx->supplies[1]),
+ *		clk_restrack_desc(&ctx->pll_clk, "pll_clk"),
+ *		clk_restrack_desc(&ctx->bus_clk, "bus_clk"),
+ *		phy_restrack_desc(&ctx->phy, "dsim"),
+ *	};
+ *	rtrack = __restrack_register(dev, callback,
+ *			ARRAY_SIZE(descriptors), descriptors);
+ */
+struct restrack_ctx *__restrack_register(struct device *dev, restrack_fn_t cb,
+		int count, struct restrack_desc **descriptors)
+{
+	struct restrack_ctx *ctx;
+	int ret, i;
+
+	ctx = kzalloc(sizeof(*ctx) + count * sizeof(ctx->desc[0]),
+			 GFP_KERNEL);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	ctx->dev = dev;
+	ctx->count = count;
+	ctx->callback = cb;
+	memcpy(ctx->desc, descriptors, count * sizeof(*descriptors));
+
+	for (i = 0; i < count; ++i) {
+		struct restrack_desc *desc = descriptors[i];
+
+		if (IS_ERR(desc)) {
+			ret = PTR_ERR(desc);
+			goto err_free;
+		}
+		INIT_LIST_HEAD(&desc->itb.list);
+		desc->itb.callback = restrack_itb_cb;
+		desc->ctx = ctx;
+		desc->status = -EPROBE_DEFER;
+		ret = desc->ops->init(dev, desc);
+		if (ret)
+			goto err_free;
+	}
+
+	/* Callbacks should be registered after all fields are initialized,
+	 * otherwise callback could access partially initialized data. */
+	for (i = 0; i < count; ++i) {
+		struct restrack_desc *desc = descriptors[i];
+		const struct restrack_ops *ops = desc->ops;
+
+		/* do not track the same interface twice */
+		if (restrack_find_prev_if(ctx, i))
+			continue;
+
+		ret = track_register(&restrack, &desc->itb, ops->if_type,
+				     desc->if_id);
+		if (ret)
+			goto err_free;
+	}
+
+	return ctx;
+
+err_free:
+	restrack_unregister(ctx);
+
+	return ERR_PTR(ret);
+}
+
+static void devm_restrack_release(struct device *dev, void *res)
+{
+	struct restrack_ctx **ptr = res;
+
+	if (!IS_ERR(*ptr))
+		restrack_unregister(*ptr);
+}
+
+/**
+ * __devm_restrack_register - devm version of __restrack_register
+ * @dev: consumer device
+ * @callback: callback which will be called when:
+ *	- all tracked resources become available, with @ret = 0
+ *	- one of the resources becomes unavailable, with @ret = -EPROBE_DEFER,
+ *	- resource allocation errors, with @ret equal to this error
+ * @count: number of resource descriptors to track
+ * @descs: list of pointers to resource descriptors to track
+ *
+ * It can be called as follows:
+ *	struct restrack_desc *descriptors[] = {
+ *		regulator_bulk_restrack_desc(&ctx->supplies[0]),
+ *		regulator_bulk_restrack_desc(&ctx->supplies[1]),
+ *		clk_restrack_desc(&ctx->pll_clk, "pll_clk"),
+ *		clk_restrack_desc(&ctx->bus_clk, "bus_clk"),
+ *		phy_restrack_desc(&ctx->phy, "dsim"),
+ *	};
+ *	rtrack = __devm_restrack_register(dev, callback,
+ *			ARRAY_SIZE(descriptors), descriptors);
+ */
+struct restrack_ctx *__devm_restrack_register(struct device *dev,
+		restrack_fn_t cb, int count, struct restrack_desc **descs)
+{
+	struct restrack_ctx **ptr;
+
+	ptr = devres_alloc(devm_restrack_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	/* It should be added before __restrack_register to keep correct order
+	 * of resources - restrack callback can also use devres framework.
+	 */
+	devres_add(dev, ptr);
+
+	*ptr = __restrack_register(dev, cb, count, descs);
+
+	return *ptr;
+}
+EXPORT_SYMBOL_GPL(__devm_restrack_register);
diff --git a/include/linux/restrack.h b/include/linux/restrack.h
new file mode 100644
index 0000000..6cf8144f
--- /dev/null
+++ b/include/linux/restrack.h
@@ -0,0 +1,137 @@
+#ifndef RESTRACK_H
+#define RESTRACK_H
+
+#include <linux/track.h>
+
+struct device;
+struct restrack_ctx;
+struct restrack_desc;
+
+int restrack_up(unsigned long type, const void *id, void *data);
+int restrack_down(unsigned long type, const void *id, void *data);
+
+/**
+ * struct restrack_ops - Resource tracker operations for specific resource
+ * @if_type: interface type of provider associated with given resource,
+ *	multiple restrack_ops per if_type are allowed
+ * @init: called by restrack_register to initialize device depended fields
+ *	of the resource descriptor
+ * @destroy: destroy resource descriptor
+ * @if_up: called when provider of given resource becomes available, usually
+ *	it should allocate the resource and fill the variable which was
+ *	provided by restrack_register.
+ * @if_down: called before provider of given resource becomes unavailable. It
+ *	should release the resource and set associated variable to
+ *	-EPROBE_DEFER.
+ *
+ * struct restrack_ops provides set of operations to handle resource specific
+ * operations. It translates resource names specific to consumer device to
+ * track interface id exposed by providers and translates back track
+ * notifications to callback convenient for device driver.
+ * @desc parameter provided in all callbacks is a pointer to common
+ * restrack_desc structure embedded in bigger structure which is usually
+ * allocated by resource specific allocator function.
+ * Callbacks should return 0 on success or error code.
+ */
+struct restrack_ops {
+	unsigned long if_type;
+	int (*init)(struct device *dev, struct restrack_desc *desc);
+	void (*destroy)(struct device *dev, struct restrack_desc *desc);
+	int (*if_up)(struct device *dev, struct restrack_desc *desc,
+		     void *data);
+	void (*if_down)(struct device *dev, struct restrack_desc *desc,
+			void *data);
+};
+
+#define restrack_desc_to_rd(_rd, _var) container_of(_var, typeof(*rd), desc)
+
+#define RESTRACK_DESC_ALLOC(_rd, _ops, _ptr, _name) \
+({ \
+	_rd = kzalloc(sizeof(*_rd), GFP_KERNEL); \
+	if (_rd) { \
+		*_ptr = ERR_PTR(-EPROBE_DEFER); \
+		_rd->ptr = _ptr; \
+		_rd->name = _name; \
+		_rd->desc.ops = &_ops; \
+	} \
+})
+
+/**
+ * struct restrack_desc - resource descriptor
+ * @ops: operations associated with the resource, filled by resource descriptor
+ *	 allocator
+ * @if_id: interface id associated with the resource, filled by @init operation
+ * @itb: iftrack block used by restrack core
+ * @ctx: restrack context used by restrack core
+ * @status: status of the descriptor, used by restrack core
+ */
+struct restrack_desc {
+	const struct restrack_ops *ops;
+	void *if_id;
+	struct track_block itb;
+	struct restrack_ctx *ctx;
+	int status;
+};
+
+typedef void (*restrack_fn_t)(struct device *dev, int ret);
+
+void restrack_unregister(struct restrack_ctx *ctx);
+struct restrack_ctx *__restrack_register(struct device *dev, restrack_fn_t cb,
+		int count, struct restrack_desc **descriptors);
+struct restrack_ctx *__devm_restrack_register(struct device *dev,
+		restrack_fn_t cb, int count,
+		struct restrack_desc **descriptors);
+
+/**
+ * restrack_register - register resource tracking callback
+ * @dev: consumer device
+ * @callback: callback which will be called when:
+ *	- all tracked resources become available, with @ret = 0
+ *	- one of the resources becomes unavailable, with @ret = -EPROBE_DEFER,
+ *	- resource allocation errors, with @ret equal to this error
+ * @descs: list of pointers to resource descriptors to track
+ *
+ * restrack_register is a wrapper macro around @__restrack_register. It can be
+ * called as follows:
+ *	ctx->rtrack = restrack_register(dev, callback,
+ *		regulator_bulk_restrack_desc(&ctx->supplies[0]),
+ *		regulator_bulk_restrack_desc(&ctx->supplies[1]),
+ *		clk_restrack_desc(&ctx->pll_clk, "pll_clk"),
+ *		clk_restrack_desc(&ctx->bus_clk, "bus_clk"),
+ *		phy_restrack_desc(&ctx->phy, "dsim"),
+ *	);
+ */
+#define restrack_register(dev, callback, descs...) \
+({ \
+	struct restrack_desc *desc[] = { descs }; \
+\
+	__restrack_register(dev, callback, ARRAY_SIZE(desc), desc); \
+})
+
+/**
+ * devm_restrack_register - devm version of restrack_register
+ * @dev: consumer device
+ * @callback: callback which will be called when:
+ *	- all tracked resources become available, with @ret = 0
+ *	- one of the resources becomes unavailable, with @ret = -EPROBE_DEFER,
+ *	- resource allocation errors, with @ret equal to this error
+ * @descs: list of pointers to resource descriptors to track
+ *
+ * restrack_register is a wrapper macro around @__restrack_register. It can be
+ * called as follows:
+ *	rtrack = devm_restrack_register(dev, callback,
+ *		regulator_bulk_restrack_desc(&ctx->supplies[0]),
+ *		regulator_bulk_restrack_desc(&ctx->supplies[1]),
+ *		clk_restrack_desc(&ctx->pll_clk, "pll_clk"),
+ *		clk_restrack_desc(&ctx->bus_clk, "bus_clk"),
+ *		phy_restrack_desc(&ctx->phy, "dsim"),
+ *	);
+ */
+#define devm_restrack_register(dev, callback, descs...) \
+({ \
+	struct restrack_desc *desc[] = { descs }; \
+\
+	__devm_restrack_register(dev, callback, ARRAY_SIZE(desc), desc); \
+})
+
+#endif /* RESTRACK_H */
