diff --git a/drivers/eeprom/core.c b/drivers/eeprom/core.c
index 243e466..75ae39c 100644
--- a/drivers/eeprom/core.c
+++ b/drivers/eeprom/core.c
@@ -11,6 +11,7 @@
 
 #include <linux/device.h>
 #include <linux/eeprom-provider.h>
+#include <linux/eeprom-consumer.h>
 #include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/idr.h>
@@ -31,6 +32,13 @@ struct eeprom_device {
 	atomic_t		users;
 };
 
+struct eeprom_cell {
+	struct eeprom_device *eeprom;
+	int nblocks;
+	int size;
+	struct eeprom_block blocks[0];
+};
+
 static DEFINE_MUTEX(eeprom_mutex);
 static DEFINE_IDA(eeprom_ida);
 
@@ -116,6 +124,37 @@ static struct class eeprom_class = {
 	.dev_release	= eeprom_release,
 };
 
+static int of_eeprom_match(struct device *dev, const void *eeprom_np)
+{
+	return dev->of_node == eeprom_np;
+}
+
+static struct eeprom_device *of_eeprom_find(struct device_node *eeprom_np)
+{
+	struct device *d;
+
+	if (!eeprom_np)
+		return NULL;
+
+	d = class_find_device(&eeprom_class, NULL, eeprom_np, of_eeprom_match);
+
+	return d ? to_eeprom(d) : NULL;
+}
+
+static int eeprom_match(struct device *dev, const void *data)
+{
+	return !strcmp(dev_name(dev), (const char *)data);
+}
+
+static struct eeprom_device *eeprom_find(const char *name)
+{
+	struct device *d;
+
+	d = class_find_device(&eeprom_class, NULL, (void *)name, eeprom_match);
+
+	return d ? to_eeprom(d) : NULL;
+}
+
 /**
  * eeprom_register(): Register a eeprom device for given eeprom.
  * Also creates an binary entry in /sys/class/eeprom/name-id/eeprom
@@ -189,6 +228,265 @@ int eeprom_unregister(struct eeprom_device *eeprom)
 }
 EXPORT_SYMBOL(eeprom_unregister);
 
+static struct eeprom_cell *eeprom_cell_sanity_check(struct eeprom_cell *cell)
+{
+	struct eeprom_device *eeprom = cell->eeprom;
+	int i;
+
+	/* byte aligned, no need to check for stride sanity */
+	if (eeprom->stride == 1)
+		return cell;
+
+	for (i = 0; i < cell->nblocks; i++) {
+		if (!IS_ALIGNED(cell->blocks[i].offset, eeprom->stride) ||
+		    !IS_ALIGNED(cell->blocks[i].count, eeprom->stride)) {
+			dev_err(&eeprom->dev,
+				"cell unaligned to eeprom stride %d\n",
+				eeprom->stride);
+			atomic_dec(&eeprom->users);
+			module_put(eeprom->owner);
+			kfree(cell);
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	return cell;
+}
+
+/**
+ * eeprom_cell_get(): Get eeprom cell of device form a given eeprom name
+ * and blocks.
+ *
+ * @ename: eeprom device name that needs to be looked-up.
+ * @blocks: eeprom blocks containing offset and length information.
+ * @nblocks: number of eeprom blocks.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct eeprom_cell.  The eeprom_cell will be freed by the
+ * eeprom_cell_put().
+ */
+struct eeprom_cell *eeprom_cell_get(const char *ename,
+				    struct eeprom_block *blocks, int nblocks)
+{
+	struct eeprom_cell *cell;
+	struct eeprom_device *eeprom = NULL;
+	int i;
+
+	mutex_lock(&eeprom_mutex);
+	eeprom = eeprom_find(ename);
+	if (!eeprom) {
+		mutex_unlock(&eeprom_mutex);
+		return ERR_PTR(-EPROBE_DEFER);
+	}
+	atomic_inc(&eeprom->users);
+
+	if (!try_module_get(eeprom->owner)) {
+		dev_err(&eeprom->dev,
+			"could not increase module refcount for cell %s\n",
+			ename);
+			mutex_unlock(&eeprom_mutex);
+		return ERR_PTR(-EINVAL);
+	}
+	mutex_unlock(&eeprom_mutex);
+
+	cell = kzalloc(sizeof(*cell) + nblocks * sizeof(*blocks), GFP_KERNEL);
+	if (!cell)
+		return ERR_PTR(-ENOMEM);
+
+	memcpy(cell->blocks, blocks, nblocks * sizeof(*blocks));
+	cell->nblocks = nblocks;
+	cell->eeprom = eeprom;
+	cell->size = 0;
+
+	for (i = 0; i < nblocks; i++)
+		cell->size += blocks[i].count;
+
+	return eeprom_cell_sanity_check(cell);
+}
+EXPORT_SYMBOL(eeprom_cell_get);
+
+/**
+ * of_eeprom_cell_get(): Get eeprom cell of device form a given index
+ *
+ * @dev: Device that will be interacted with
+ * @index: eeprom index in eeproms property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct eeprom_cell.  The eeprom_cell will be freed by the
+ * eeprom_cell_put().
+ */
+struct eeprom_cell *of_eeprom_cell_get(struct device *dev, int index)
+{
+	struct device_node *cell_np;
+	struct eeprom_cell *cell;
+	struct eeprom_device *eeprom = NULL;
+	int i, nblocks;
+	struct property *prop;
+	const __be32 *vp;
+	u32 pv;
+
+	if (!dev || !dev->of_node)
+		return ERR_PTR(-EINVAL);
+
+	cell_np = of_parse_phandle(dev->of_node, "eeproms", index);
+	if (!cell_np)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	mutex_lock(&eeprom_mutex);
+	eeprom = of_eeprom_find(cell_np->parent);
+	if (!eeprom) {
+		mutex_unlock(&eeprom_mutex);
+		return ERR_PTR(-EPROBE_DEFER);
+	}
+
+	atomic_inc(&eeprom->users);
+
+	if (!try_module_get(eeprom->owner)) {
+		dev_err(&eeprom->dev,
+			"could not increase module refcount for cell %d\n",
+			index);
+			mutex_unlock(&eeprom_mutex);
+		return ERR_PTR(-EINVAL);
+	}
+	mutex_unlock(&eeprom_mutex);
+
+	nblocks = of_property_count_u32_elems(cell_np, "reg") / 2;
+
+	cell = kzalloc(sizeof(*cell) + nblocks * sizeof(struct eeprom_block),
+		       GFP_KERNEL);
+	cell->nblocks = nblocks;
+	cell->eeprom = eeprom;
+	cell->size = 0;
+	i = 0;
+
+	of_property_for_each_u32(cell_np, "reg", prop, vp, pv) {
+		cell->blocks[i].offset = pv;
+		vp = of_prop_next_u32(prop, vp, &pv);
+		cell->blocks[i].count = pv;
+		cell->size += pv;
+		i++;
+	}
+
+	return eeprom_cell_sanity_check(cell);
+}
+EXPORT_SYMBOL(of_eeprom_cell_get);
+
+/**
+ * of_eeprom_cell_get_byname(): Get eeprom cell of device form a given name
+ *
+ * @dev: Device that will be interacted with
+ * @name: eeprom name in eeprom-names property.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct eeprom_cell.  The eeprom_cell will be freed by the
+ * eeprom_cell_put().
+ */
+struct eeprom_cell *of_eeprom_cell_get_byname(struct device *dev,
+					      const char *id)
+{
+	int index = 0;
+
+	if (!dev || !dev->of_node)
+		return ERR_PTR(-EINVAL);
+
+	if (id)
+		index = of_property_match_string(dev->of_node,
+						 "eeprom-names",
+						 id);
+	return of_eeprom_cell_get(dev, index);
+
+}
+EXPORT_SYMBOL(of_eeprom_cell_get_byname);
+
+/**
+ * eeprom_cell_put(): Release previously allocated eeprom cell.
+ *
+ * @cell: Previously allocated eeprom cell by eeprom_cell_get()
+ * or of_eeprom_cell_get() or of_eeprom_cell_get_byname().
+ */
+void eeprom_cell_put(struct eeprom_cell *cell)
+{
+	struct eeprom_device *eeprom = cell->eeprom;
+
+	atomic_dec(&eeprom->users);
+	module_put(eeprom->owner);
+	kfree(cell);
+}
+EXPORT_SYMBOL(eeprom_cell_put);
+
+/**
+ * eeprom_cell_read(): Read a given eeprom cell
+ *
+ * @cell: eeprom cell to be read.
+ * @len: pointer to length of cell which will be populated on successful read.
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a char * bufffer.  The buffer should be freed by the consumer with a
+ * kfree().
+ */
+char *eeprom_cell_read(struct eeprom_cell *cell, ssize_t *len)
+{
+	struct eeprom_device *eeprom = cell->eeprom;
+	char *buf;
+	int rc, i, offset = 0;
+
+	if (!eeprom || !eeprom->regmap)
+		return ERR_PTR(-EINVAL);
+
+	buf = kzalloc(cell->size, GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < cell->nblocks; i++) {
+		rc = regmap_bulk_read(eeprom->regmap, cell->blocks[i].offset,
+				      buf + offset,
+				      cell->blocks[i].count);
+
+		if (IS_ERR_VALUE(rc)) {
+			kfree(buf);
+			return ERR_PTR(rc);
+		}
+		offset += cell->blocks[i].count;
+	}
+
+	*len = cell->size;
+
+	return buf;
+}
+EXPORT_SYMBOL(eeprom_cell_read);
+
+/**
+ * eeprom_cell_write(): Write to a given eeprom cell
+ *
+ * @cell: eeprom cell to be written.
+ * @buf: Buffer to be written.
+ * @len: length of buffer to be written to eeprom cell.
+ *
+ * The return value will be an non zero on error or a zero on successful write.
+ */
+int eeprom_cell_write(struct eeprom_cell *cell, const char *buf, ssize_t len)
+{
+	struct eeprom_device *eeprom = cell->eeprom;
+	int i, rc, offset = 0;
+
+	if (!eeprom || !eeprom->regmap || len != cell->size)
+		return -EINVAL;
+
+	for (i = 0; i < cell->nblocks; i++) {
+		rc = regmap_bulk_write(eeprom->regmap, cell->blocks[i].offset,
+				 buf + offset,
+				 cell->blocks[i].count);
+
+		if (IS_ERR_VALUE(rc))
+			return rc;
+
+		offset += cell->blocks[i].count;
+	}
+
+	return len;
+}
+EXPORT_SYMBOL(eeprom_cell_write);
+
 static int eeprom_init(void)
 {
 	return class_register(&eeprom_class);
diff --git a/include/linux/eeprom-consumer.h b/include/linux/eeprom-consumer.h
new file mode 100644
index 0000000..e06f5e5
--- /dev/null
+++ b/include/linux/eeprom-consumer.h
@@ -0,0 +1,67 @@
+/*
+ * EEPROM framework consumer.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _LINUX_EEPROM_CONSUMER_H
+#define _LINUX_EEPROM_CONSUMER_H
+
+struct eeprom_cell;
+
+struct eeprom_block {
+	loff_t offset;
+	size_t count;
+};
+#ifdef CONFIG_EEPROM
+struct eeprom_cell *eeprom_cell_get(const char *ename,
+				    struct eeprom_block *blocks, int nblocks);
+void eeprom_cell_put(struct eeprom_cell *cell);
+char *eeprom_cell_read(struct eeprom_cell *cell, ssize_t *len);
+int eeprom_cell_write(struct eeprom_cell *cell, const char *buf, ssize_t len);
+#else
+
+static inline struct eeprom_cell *eeprom_cell_get(const char *ename,
+				    struct eeprom_block *blocks, int nblocks)
+{
+	return NULL;
+}
+
+static inline void eeprom_cell_put(struct eeprom_cell *cell)
+{
+}
+
+static inline char *eeprom_cell_read(struct eeprom_cell *cell, ssize_t *len)
+{
+	return NULL;
+}
+
+static inline int eeprom_cell_write(struct eeprom_cell *cell,
+				    const char *buf, ssize_t len)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_EEPROM */
+
+#if defined(CONFIG_EEPROM) && defined(CONFIG_OF)
+struct eeprom_cell *of_eeprom_cell_get(struct device *dev, int index);
+struct eeprom_cell *of_eeprom_cell_get_byname(struct device *dev,
+					      const char *name);
+#else
+static inline struct eeprom_cell *of_eeprom_cell_get(
+					struct device *dev, int index)
+{
+	return NULL;
+}
+static inline struct eeprom_cell *of_eeprom_cell_get_byname(struct device *dev,
+							    const char *name)
+{
+	return NULL;
+}
+#endif
+#endif  /* ifndef _LINUX_EEPROM_CONSUMER_H */
