diff --git a/arch/arm64/configs/seco_px30_d23-linux_defconfig b/arch/arm64/configs/seco_px30_d23-linux_defconfig
index f4a1ce68f84af5e8dc369c306585de7845e90236..0533200246e8cd873f0a928257a52f42060ba91c 100644
--- a/arch/arm64/configs/seco_px30_d23-linux_defconfig
+++ b/arch/arm64/configs/seco_px30_d23-linux_defconfig
@@ -170,6 +170,7 @@ CONFIG_ZRAM=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_EEPROM_AT24=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index f112c5bc082a57b1c5402f1d2a21907f80b36637..f2ba87db7e5eb84da2e6493de49310225fd89e60 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -15,14 +15,14 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
-#include <linux/sysfs.h>
 #include <linux/mod_devicetable.h>
 #include <linux/log2.h>
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
-#include <linux/of.h>
+#include <linux/property.h>
 #include <linux/acpi.h>
 #include <linux/i2c.h>
+#include <linux/nvmem-provider.h>
 #include <linux/platform_data/at24.h>
 
 /*
@@ -55,21 +55,31 @@
 
 struct at24_data {
 	struct at24_platform_data chip;
-	struct memory_accessor macc;
 	int use_smbus;
 	int use_smbus_write;
 
+	ssize_t (*read_func)(struct at24_data *, char *, unsigned int, size_t);
+	ssize_t (*write_func)(struct at24_data *,
+			      const char *, unsigned int, size_t);
+
 	/*
 	 * Lock protects against activities from other Linux tasks,
 	 * but not from changes by other I2C masters.
 	 */
 	struct mutex lock;
-	struct bin_attribute bin;
 
 	u8 *writebuf;
 	unsigned write_max;
 	unsigned num_addresses;
 
+	struct nvmem_config nvmem_config;
+	struct nvmem_device *nvmem;
+	struct nvmem_device *mac_nvmem;
+	struct nvmem_device *serial_nvmem;
+
+	struct nvmem_config mac_nvmem_config;
+	struct nvmem_config serial_nvmem_config;
+	struct nvmem_config user_nvmem_config;
 	/*
 	 * Some chips tie up multiple I2C addresses; dummy devices reserve
 	 * them for us, and we'll use them with SMBus calls.
@@ -98,6 +108,12 @@ static unsigned write_timeout = 25;
 module_param(write_timeout, uint, 0);
 MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)");
 
+#define SECO_MAC_OFFSET 0
+#define SECO_MAC_CHAR_LEN 12
+#define SECO_SERIAL_OFFSET 6
+#define SECO_SERIAL_CHAR_LEN 9
+#define SECO_RESERVED_BYTE 32
+
 #define AT24_SIZE_BYTELEN 5
 #define AT24_SIZE_FLAGS 8
 
@@ -108,25 +124,66 @@ MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)");
 	((1 << AT24_SIZE_FLAGS | (_flags)) 		\
 	    << AT24_SIZE_BYTELEN | ilog2(_len))
 
+/*
+ * Both reads and writes fail if the previous write didn't complete yet. This
+ * macro loops a few times waiting at least long enough for one entire page
+ * write to work while making sure that at least one iteration is run before
+ * checking the break condition.
+ *
+ * It takes two parameters: a variable in which the future timeout in jiffies
+ * will be stored and a temporary variable holding the time of the last
+ * iteration of processing the request. Both should be unsigned integers
+ * holding at least 32 bits.
+ */
+#define loop_until_timeout(tout, op_time)				\
+	for (tout = jiffies + msecs_to_jiffies(write_timeout), op_time = 0; \
+	     op_time ? time_before(op_time, tout) : true;		\
+	     usleep_range(1000, 1500), op_time = jiffies)
+
 static const struct i2c_device_id at24_ids[] = {
+    { "24aa025", AT24_DEVICE_MAGIC(2048 / 8, AT24_FLAG_SECO_PARTITION) },
 	/* needs 8 addresses as A0-A2 are ignored */
-	{ "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) },
+	{ "24c00",	AT24_DEVICE_MAGIC(128 / 8,	AT24_FLAG_TAKE8ADDR) },
 	/* old variants can't be handled with this generic entry! */
-	{ "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) },
-	{ "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) },
+	{ "24c01",	AT24_DEVICE_MAGIC(1024 / 8,	0) },
+	{ "24cs01",	AT24_DEVICE_MAGIC(16,
+				AT24_FLAG_SERIAL | AT24_FLAG_READONLY) },
+	{ "24c02",	AT24_DEVICE_MAGIC(2048 / 8,	0) },
+	{ "24cs02",	AT24_DEVICE_MAGIC(16,
+				AT24_FLAG_SERIAL | AT24_FLAG_READONLY) },
+	{ "24mac402",	AT24_DEVICE_MAGIC(48 / 8,
+				AT24_FLAG_MAC | AT24_FLAG_READONLY) },
+	{ "24mac602",	AT24_DEVICE_MAGIC(64 / 8,
+				AT24_FLAG_MAC | AT24_FLAG_READONLY) },
 	/* spd is a 24c02 in memory DIMMs */
-	{ "spd", AT24_DEVICE_MAGIC(2048 / 8,
-		AT24_FLAG_READONLY | AT24_FLAG_IRUGO) },
-	{ "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) },
+	{ "spd",	AT24_DEVICE_MAGIC(2048 / 8,
+				AT24_FLAG_READONLY | AT24_FLAG_IRUGO) },
+	{ "24c04",	AT24_DEVICE_MAGIC(4096 / 8,	0) },
+	{ "24cs04",	AT24_DEVICE_MAGIC(16,
+				AT24_FLAG_SERIAL | AT24_FLAG_READONLY) },
 	/* 24rf08 quirk is handled at i2c-core */
-	{ "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) },
-	{ "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) },
-	{ "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) },
-	{ "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) },
-	{ "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) },
-	{ "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) },
-	{ "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) },
-	{ "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16) },
+	{ "24c08",	AT24_DEVICE_MAGIC(8192 / 8,	0) },
+	{ "24cs08",	AT24_DEVICE_MAGIC(16,
+				AT24_FLAG_SERIAL | AT24_FLAG_READONLY) },
+	{ "24c16",	AT24_DEVICE_MAGIC(16384 / 8,	0) },
+	{ "24cs16",	AT24_DEVICE_MAGIC(16,
+				AT24_FLAG_SERIAL | AT24_FLAG_READONLY) },
+	{ "24c32",	AT24_DEVICE_MAGIC(32768 / 8,	AT24_FLAG_ADDR16) },
+	{ "24cs32",	AT24_DEVICE_MAGIC(16,
+				AT24_FLAG_ADDR16 |
+				AT24_FLAG_SERIAL |
+				AT24_FLAG_READONLY) },
+	{ "24c64",	AT24_DEVICE_MAGIC(65536 / 8,	AT24_FLAG_ADDR16) },
+	{ "24cs64",	AT24_DEVICE_MAGIC(16,
+				AT24_FLAG_ADDR16 |
+				AT24_FLAG_SERIAL |
+				AT24_FLAG_READONLY) },
+	{ "24c128",	AT24_DEVICE_MAGIC(131072 / 8,	AT24_FLAG_ADDR16) },
+	{ "24c256",	AT24_DEVICE_MAGIC(262144 / 8,	AT24_FLAG_ADDR16) },
+	{ "24c512",	AT24_DEVICE_MAGIC(524288 / 8,	AT24_FLAG_ADDR16) },
+	{ "24c1024",	AT24_DEVICE_MAGIC(1048576 / 8,	AT24_FLAG_ADDR16) },
+	{ "fm24c04", AT24_DEVICE_MAGIC(4096 / 8, AT24_FLAG_TAKE8ADDR) },
+	{ "fm24lc16", AT24_DEVICE_MAGIC(16384 / 8, AT24_FLAG_TAKE8ADDR) },
 	{ "at24", 0 },
 	{ /* END OF LIST */ }
 };
@@ -144,9 +201,22 @@ MODULE_DEVICE_TABLE(acpi, at24_acpi_ids);
  * This routine supports chips which consume multiple I2C addresses. It
  * computes the addressing information to be used for a given r/w request.
  * Assumes that sanity checks for offset happened at sysfs-layer.
+ *
+ * Slave address and byte offset derive from the offset. Always
+ * set the byte address; on a multi-master board, another master
+ * may have changed the chip's "current" address pointer.
+ *
+ * REVISIT some multi-address chips don't rollover page reads to
+ * the next slave address, so we may need to truncate the count.
+ * Those chips might need another quirk flag.
+ *
+ * If the real hardware used four adjacent 24c02 chips and that
+ * were misconfigured as one 24c08, that would be a similar effect:
+ * one "eeprom" file not four, but larger reads would fail when
+ * they crossed certain pages.
  */
 static struct i2c_client *at24_translate_offset(struct at24_data *at24,
-		unsigned *offset)
+						unsigned int *offset)
 {
 	unsigned i;
 
@@ -161,165 +231,234 @@ static struct i2c_client *at24_translate_offset(struct at24_data *at24,
 	return at24->client[i];
 }
 
-static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
-		unsigned offset, size_t count)
+static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf,
+				      unsigned int offset, size_t count)
+{
+	unsigned long timeout, read_time;
+	struct i2c_client *client;
+	int status;
+
+	client = at24_translate_offset(at24, &offset);
+
+	if (count > io_limit)
+		count = io_limit;
+
+	/* Smaller eeproms can work given some SMBus extension calls */
+	if (count > I2C_SMBUS_BLOCK_MAX)
+		count = I2C_SMBUS_BLOCK_MAX;
+
+	loop_until_timeout(timeout, read_time) {
+		status = i2c_smbus_read_i2c_block_data_or_emulated(client,
+								   offset,
+								   count, buf);
+
+		dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
+				count, offset, status, jiffies);
+
+		if (status == count)
+			return count;
+	}
+
+	return -ETIMEDOUT;
+}
+
+static ssize_t at24_eeprom_seco_read(struct at24_data *at24, char *buf,
+				    unsigned int offset, size_t count)
 {
-	struct i2c_msg msg[2];
-	u8 msgbuf[2];
 	struct i2c_client *client;
 	unsigned long timeout, read_time;
+	struct i2c_msg msg[2];
 	int status, i;
+	u8 msgbuf[2];
 
 	memset(msg, 0, sizeof(msg));
+	client = at24_translate_offset(at24, &offset);
+	if (count > io_limit)
+		count = io_limit;
 
 	/*
-	 * REVISIT some multi-address chips don't rollover page reads to
-	 * the next slave address, so we may need to truncate the count.
-	 * Those chips might need another quirk flag.
-	 *
-	 * If the real hardware used four adjacent 24c02 chips and that
-	 * were misconfigured as one 24c08, that would be a similar effect:
-	 * one "eeprom" file not four, but larger reads would fail when
-	 * they crossed certain pages.
+	 * When we have a better choice than SMBus calls, use a combined I2C
+	 * message. Write address; then read up to io_limit data bytes. Note
+	 * that read page rollover helps us here (unlike writes). msgbuf is
+	 * u8 and will cast to our needs.
 	 */
+	i = 0;
+	if (at24->chip.flags & AT24_FLAG_ADDR16)
+		msgbuf[i++] = offset >> 8;
+	msgbuf[i++] = offset;
 
-	/*
-	 * Slave address and byte offset derive from the offset. Always
-	 * set the byte address; on a multi-master board, another master
-	 * may have changed the chip's "current" address pointer.
-	 */
-	client = at24_translate_offset(at24, &offset);
+	msg[0].addr = client->addr;
+	msg[0].buf = msgbuf;
+	msg[0].len = i;
 
-	if (count > io_limit)
-		count = io_limit;
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].buf = buf;
+	msg[1].len = count;
 
-	if (at24->use_smbus) {
-		/* Smaller eeproms can work given some SMBus extension calls */
-		if (count > I2C_SMBUS_BLOCK_MAX)
-			count = I2C_SMBUS_BLOCK_MAX;
-	} else {
-		/*
-		 * When we have a better choice than SMBus calls, use a
-		 * combined I2C message. Write address; then read up to
-		 * io_limit data bytes. Note that read page rollover helps us
-		 * here (unlike writes). msgbuf is u8 and will cast to our
-		 * needs.
-		 */
-		i = 0;
-		if (at24->chip.flags & AT24_FLAG_ADDR16)
-			msgbuf[i++] = offset >> 8;
-		msgbuf[i++] = offset;
-
-		msg[0].addr = client->addr;
-		msg[0].buf = msgbuf;
-		msg[0].len = i;
-
-		msg[1].addr = client->addr;
-		msg[1].flags = I2C_M_RD;
-		msg[1].buf = buf;
-		msg[1].len = count;
+	loop_until_timeout(timeout, read_time) {
+		status = i2c_transfer(client->adapter, msg, 2);
+		if (status == 2)
+			status = count;
+
+		dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
+				count, offset, status, jiffies);
+
+		if (status == count)
+			return count;
 	}
 
+	return -ETIMEDOUT;
+}
+
+static ssize_t at24_eeprom_read_i2c(struct at24_data *at24, char *buf,
+				    unsigned int offset, size_t count)
+{
+	unsigned long timeout, read_time;
+	struct i2c_client *client;
+	struct i2c_msg msg[2];
+	int status, i;
+	u8 msgbuf[2];
+
+
+	memset(msg, 0, sizeof(msg));
+	client = at24_translate_offset(at24, &offset);
+	if (count > io_limit)
+		count = io_limit;
+
 	/*
-	 * Reads fail if the previous write didn't complete yet. We may
-	 * loop a few times until this one succeeds, waiting at least
-	 * long enough for one entire page write to work.
+	 * When we have a better choice than SMBus calls, use a combined I2C
+	 * message. Write address; then read up to io_limit data bytes. Note
+	 * that read page rollover helps us here (unlike writes). msgbuf is
+	 * u8 and will cast to our needs.
 	 */
-	timeout = jiffies + msecs_to_jiffies(write_timeout);
-	do {
-		read_time = jiffies;
-		if (at24->use_smbus) {
-			status = i2c_smbus_read_i2c_block_data_or_emulated(client, offset,
-									   count, buf);
-		} else {
-			status = i2c_transfer(client->adapter, msg, 2);
-			if (status == 2)
-				status = count;
-		}
+	i = 0;
+	if (at24->chip.flags & AT24_FLAG_ADDR16)
+		msgbuf[i++] = offset >> 8;
+	msgbuf[i++] = offset;
+
+	msg[0].addr = client->addr;
+	msg[0].buf = msgbuf;
+	msg[0].len = i;
+
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].buf = buf;
+	msg[1].len = count;
+
+	loop_until_timeout(timeout, read_time) {
+		status = i2c_transfer(client->adapter, msg, 2);
+		if (status == 2)
+			status = count;
+
 		dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
 				count, offset, status, jiffies);
 
 		if (status == count)
 			return count;
-
-		/* REVISIT: at HZ=100, this is sloooow */
-		msleep(1);
-	} while (time_before(read_time, timeout));
+	}
 
 	return -ETIMEDOUT;
 }
 
-static ssize_t at24_read(struct at24_data *at24,
-		char *buf, loff_t off, size_t count)
+static ssize_t at24_eeprom_read_serial(struct at24_data *at24, char *buf,
+				       unsigned int offset, size_t count)
 {
-	ssize_t retval = 0;
+	unsigned long timeout, read_time;
+	struct i2c_client *client;
+	struct i2c_msg msg[2];
+	u8 addrbuf[2];
+	int status;
 
-	if (unlikely(!count))
-		return count;
+	client = at24_translate_offset(at24, &offset);
 
-	if (off + count > at24->chip.byte_len)
-		return -EINVAL;
+	memset(msg, 0, sizeof(msg));
+	msg[0].addr = client->addr;
+	msg[0].buf = addrbuf;
 
 	/*
-	 * Read data from chip, protecting against concurrent updates
-	 * from this host, but not from other I2C masters.
+	 * The address pointer of the device is shared between the regular
+	 * EEPROM array and the serial number block. The dummy write (part of
+	 * the sequential read protocol) ensures the address pointer is reset
+	 * to the desired position.
 	 */
-	mutex_lock(&at24->lock);
+	if (at24->chip.flags & AT24_FLAG_ADDR16) {
+		/*
+		 * For 16 bit address pointers, the word address must contain
+		 * a '10' sequence in bits 11 and 10 regardless of the
+		 * intended position of the address pointer.
+		 */
+		addrbuf[0] = 0x08;
+		addrbuf[1] = offset;
+		msg[0].len = 2;
+	} else {
+		/*
+		 * Otherwise the word address must begin with a '10' sequence,
+		 * regardless of the intended address.
+		 */
+		addrbuf[0] = 0x80 + offset;
+		msg[0].len = 1;
+	}
 
-	while (count) {
-		ssize_t	status;
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].buf = buf;
+	msg[1].len = count;
 
-		status = at24_eeprom_read(at24, buf, off, count);
-		if (status <= 0) {
-			if (retval == 0)
-				retval = status;
-			break;
-		}
-		buf += status;
-		off += status;
-		count -= status;
-		retval += status;
+	loop_until_timeout(timeout, read_time) {
+		status = i2c_transfer(client->adapter, msg, 2);
+		if (status == 2)
+			return count;
 	}
 
-	mutex_unlock(&at24->lock);
-
-	return retval;
+	return -ETIMEDOUT;
 }
 
-static ssize_t at24_bin_read(struct file *filp, struct kobject *kobj,
-		struct bin_attribute *attr,
-		char *buf, loff_t off, size_t count)
+static ssize_t at24_eeprom_read_mac(struct at24_data *at24, char *buf,
+				    unsigned int offset, size_t count)
 {
-	struct at24_data *at24;
+	unsigned long timeout, read_time;
+	struct i2c_client *client;
+	struct i2c_msg msg[2];
+	u8 addrbuf[2];
+	int status;
 
-	at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
-	return at24_read(at24, buf, off, count);
-}
+	client = at24_translate_offset(at24, &offset);
 
+	memset(msg, 0, sizeof(msg));
+	msg[0].addr = client->addr;
+	msg[0].buf = addrbuf;
+	/* EUI-48 starts from 0x9a, EUI-64 from 0x98 */
+	addrbuf[0] = 0xa0 - at24->chip.byte_len + offset;
+	msg[0].len = 1;
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].buf = buf;
+	msg[1].len = count;
+
+	loop_until_timeout(timeout, read_time) {
+		status = i2c_transfer(client->adapter, msg, 2);
+		if (status == 2)
+			return count;
+	}
+
+	return -ETIMEDOUT;
+}
 
 /*
  * Note that if the hardware write-protect pin is pulled high, the whole
  * chip is normally write protected. But there are plenty of product
  * variants here, including OTP fuses and partial chip protect.
  *
- * We only use page mode writes; the alternative is sloooow. This routine
- * writes at most one page.
+ * We only use page mode writes; the alternative is sloooow. These routines
+ * write at most one page.
  */
-static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf,
-		unsigned offset, size_t count)
+
+static size_t at24_adjust_write_count(struct at24_data *at24,
+				      unsigned int offset, size_t count)
 {
-	struct i2c_client *client;
-	struct i2c_msg msg;
-	ssize_t status = 0;
-	unsigned long timeout, write_time;
 	unsigned next_page;
 
-	if (offset + count > at24->chip.byte_len)
-		return -EINVAL;
-
-	/* Get corresponding I2C address and adjust offset */
-	client = at24_translate_offset(at24, &offset);
-
 	/* write_max is at most a page */
 	if (count > at24->write_max)
 		count = at24->write_max;
@@ -329,153 +468,374 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf,
 	if (offset + count > next_page)
 		count = next_page - offset;
 
-	/* If we'll use I2C calls for I/O, set up the message */
-	if (!at24->use_smbus) {
-		int i = 0;
+	return count;
+}
+
+static ssize_t at24_eeprom_write_smbus_block(struct at24_data *at24,
+					     const char *buf,
+					     unsigned int offset, size_t count)
+{
+	unsigned long timeout, write_time;
+	struct i2c_client *client;
+	ssize_t status = 0;
+
+	client = at24_translate_offset(at24, &offset);
+	count = at24_adjust_write_count(at24, offset, count);
 
-		msg.addr = client->addr;
-		msg.flags = 0;
+	loop_until_timeout(timeout, write_time) {
+		status = i2c_smbus_write_i2c_block_data(client,
+							offset, count, buf);
+		if (status == 0)
+			status = count;
 
-		/* msg.buf is u8 and casts will mask the values */
-		msg.buf = at24->writebuf;
-		if (at24->chip.flags & AT24_FLAG_ADDR16)
-			msg.buf[i++] = offset >> 8;
+		dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n",
+				count, offset, status, jiffies);
 
-		msg.buf[i++] = offset;
-		memcpy(&msg.buf[i], buf, count);
-		msg.len = i + count;
+		if (status == count)
+			return count;
 	}
 
-	/*
-	 * Writes fail if the previous one didn't complete yet. We may
-	 * loop a few times until this one succeeds, waiting at least
-	 * long enough for one entire page write to work.
-	 */
-	timeout = jiffies + msecs_to_jiffies(write_timeout);
-	do {
-		write_time = jiffies;
-		if (at24->use_smbus_write) {
-			switch (at24->use_smbus_write) {
-			case I2C_SMBUS_I2C_BLOCK_DATA:
-				status = i2c_smbus_write_i2c_block_data(client,
-						offset, count, buf);
-				break;
-			case I2C_SMBUS_BYTE_DATA:
-				status = i2c_smbus_write_byte_data(client,
-						offset, buf[0]);
-				break;
-			}
-
-			if (status == 0)
-				status = count;
-		} else {
-			status = i2c_transfer(client->adapter, &msg, 1);
-			if (status == 1)
-				status = count;
-		}
+	return -ETIMEDOUT;
+}
+
+static ssize_t at24_eeprom_write_smbus_byte(struct at24_data *at24,
+					    const char *buf,
+					    unsigned int offset, size_t count)
+{
+	unsigned long timeout, write_time;
+	struct i2c_client *client;
+	ssize_t status = 0;
+
+	client = at24_translate_offset(at24, &offset);
+
+	loop_until_timeout(timeout, write_time) {
+		status = i2c_smbus_write_byte_data(client, offset, buf[0]);
+		if (status == 0)
+			status = count;
+
 		dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n",
 				count, offset, status, jiffies);
 
 		if (status == count)
 			return count;
+	}
+
+	return -ETIMEDOUT;
+}
+
+static ssize_t at24_eeprom_seco_write(struct at24_data *at24, const char *buf,
+				     unsigned int offset, size_t count)
+{
+	unsigned long timeout, write_time;
+	struct i2c_client *client;
+	struct i2c_msg msg;
+	ssize_t status = 0;
+	int i = 0;
+
+	client = at24_translate_offset(at24, &offset);
+	count = at24_adjust_write_count(at24, offset, count);
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+
+	/* msg.buf is u8 and casts will mask the values */
+	msg.buf = at24->writebuf;
+	if (at24->chip.flags & AT24_FLAG_ADDR16)
+		msg.buf[i++] = offset >> 8;
 
-		/* REVISIT: at HZ=100, this is sloooow */
-		msleep(1);
-	} while (time_before(write_time, timeout));
+	msg.buf[i++] = offset;
+	memcpy(&msg.buf[i], buf, count);
+	msg.len = i + count;
+
+	loop_until_timeout(timeout, write_time) {
+		status = i2c_transfer(client->adapter, &msg, 1);
+		if (status == 1)
+			status = count;
+
+
+		dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n",
+				count, offset, status, jiffies);
+
+		if (status == count)
+			return count;
+	}
+
+	return -ETIMEDOUT;
+}
+static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf,
+				     unsigned int offset, size_t count)
+{
+	unsigned long timeout, write_time;
+	struct i2c_client *client;
+	struct i2c_msg msg;
+	ssize_t status = 0;
+	int i = 0;
+
+	client = at24_translate_offset(at24, &offset);
+	count = at24_adjust_write_count(at24, offset, count);
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+
+	/* msg.buf is u8 and casts will mask the values */
+	msg.buf = at24->writebuf;
+	if (at24->chip.flags & AT24_FLAG_ADDR16)
+		msg.buf[i++] = offset >> 8;
+
+	msg.buf[i++] = offset;
+	memcpy(&msg.buf[i], buf, count);
+	msg.len = i + count;
+
+	loop_until_timeout(timeout, write_time) {
+		status = i2c_transfer(client->adapter, &msg, 1);
+		if (status == 1)
+			status = count;
+
+		dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n",
+				count, offset, status, jiffies);
+
+		if (status == count)
+			return count;
+	}
 
 	return -ETIMEDOUT;
 }
 
-static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off,
-			  size_t count)
+static int at24_serial_read(void *priv, unsigned int off, void *val, size_t count)
 {
-	ssize_t retval = 0;
+	struct at24_data *at24 = priv;
+	char *buf = val;
 
-	if (unlikely(!count))
-		return count;
+	off = 0;
 
 	/*
-	 * Write data to chip, protecting against concurrent updates
+	 * Read data from chip, protecting against concurrent updates
 	 * from this host, but not from other I2C masters.
 	 */
 	mutex_lock(&at24->lock);
 
 	while (count) {
-		ssize_t	status;
+		int	status;
 
-		status = at24_eeprom_write(at24, buf, off, count);
-		if (status <= 0) {
-			if (retval == 0)
-				retval = status;
-			break;
+		status = at24->read_func(at24, buf, 6, 9);
+		if (status < 0) {
+			mutex_unlock(&at24->lock);
+			return status;
 		}
 		buf += status;
 		off += status;
 		count -= status;
-		retval += status;
 	}
 
 	mutex_unlock(&at24->lock);
 
-	return retval;
+	return 0;
 }
 
-static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj,
-		struct bin_attribute *attr,
-		char *buf, loff_t off, size_t count)
+static int at24_mac_read(void *priv, unsigned int off, void *val, size_t count)
 {
-	struct at24_data *at24;
+	struct at24_data *at24 = priv;
+	char *buf = val;
+ 	char buf1[2];
+ 	char buf2[6];
+    int i;
+
+	off = 0;
+
+	/*
+	 * Read data from chip, protecting against concurrent updates
+	 * from this host, but not from other I2C masters.
+	 */
+	mutex_lock(&at24->lock);
+
+	while (count) {
+		int	status;
+
+		status = at24->read_func(at24, buf2, 0, 6);
+		if (status < 0) {
+			mutex_unlock(&at24->lock);
+			return status;
+		}
+		buf += status;
+		off += status;
+		count -= status;
+	}
+
+	mutex_unlock(&at24->lock);
+
+    for (i=0; i < 6; i++) {
+        sprintf(buf1, "%x%x", (buf2[i] & 0xF0) >> 4, buf2[i] & 0xF);
+        if (i == 0)
+            sprintf(buf, "%s", buf1);
+        else
+            sprintf(buf, "%s%s", buf, buf1);
+    }
+    sprintf(val, "%s", buf);
 
-	at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
-	return at24_write(at24, buf, off, count);
+	return 0;
 }
 
-/*-------------------------------------------------------------------------*/
+static int at24_read(void *priv, unsigned int off, void *val, size_t count)
+{
+	struct at24_data *at24 = priv;
+	char *buf = val;
 
-/*
- * This lets other kernel code access the eeprom data. For example, it
- * might hold a board's Ethernet address, or board-specific calibration
- * data generated on the manufacturing floor.
- */
+	if (unlikely(!count))
+		return count;
+
+	if (off + count > at24->chip.byte_len)
+		return -EINVAL;
+
+	/*
+	 * Read data from chip, protecting against concurrent updates
+	 * from this host, but not from other I2C masters.
+	 */
+	mutex_lock(&at24->lock);
+
+	while (count) {
+		int	status;
+
+		status = at24->read_func(at24, buf, off, count);
+		if (status < 0) {
+			mutex_unlock(&at24->lock);
+			return status;
+		}
+		buf += status;
+		off += status;
+		count -= status;
+	}
+
+	mutex_unlock(&at24->lock);
 
-static ssize_t at24_macc_read(struct memory_accessor *macc, char *buf,
-			 off_t offset, size_t count)
+	return 0;
+}
+
+static int at24_serial_write(void *priv, unsigned int off, void *val, size_t count)
 {
-	struct at24_data *at24 = container_of(macc, struct at24_data, macc);
+	struct at24_data *at24 = priv;
+	char *buf = val;
+    int status;
+
+	if (count != (SECO_SERIAL_CHAR_LEN))
+		return -EINVAL;
 
-	return at24_read(at24, buf, offset, count);
+	if (buf[SECO_SERIAL_CHAR_LEN] != '\0')
+		return -EINVAL;
+
+	if ((buf[0] != 'k') && (buf[0] != 'K'))
+		return -EINVAL;
+
+	/*
+	 * Write data to chip, protecting against concurrent updates
+	 * from this host, but not from other I2C masters.
+	 */
+	mutex_lock(&at24->lock);
+
+	status = at24->write_func(at24, buf, SECO_SERIAL_OFFSET, SECO_SERIAL_CHAR_LEN);
+	if (status < 0) {
+		mutex_unlock(&at24->lock);
+		return status;
+	}
+	mutex_unlock(&at24->lock);
+
+	return 0;
 }
 
-static ssize_t at24_macc_write(struct memory_accessor *macc, const char *buf,
-			  off_t offset, size_t count)
+static int at24_mac_write(void *priv, unsigned int off, void *val, size_t count)
 {
-	struct at24_data *at24 = container_of(macc, struct at24_data, macc);
+	struct at24_data *at24 = priv;
+	char *buf = val;
+ 	char buf1[2];
+ 	char buf2[6];
+    int i, status;
+
+	if (count != (SECO_MAC_CHAR_LEN))
+		return -EINVAL;
+
+	if (buf[SECO_MAC_CHAR_LEN] != '\0')
+		return -EINVAL;
+
+    for (i=0; i < 6; i++) {
+        sprintf(buf1, "%c%c", buf[i*2], buf[1 + i*2]);
+
+		if (!(((buf[i*2] >= '0') && (buf[i*2] <= '9')) || ((buf[i*2] >= 0x61) && (buf[i*2] <= 0x66)) || ((buf[i*2] >= 0x41) && (buf[i*2] <= 0x46))))
+		  return -EINVAL;
+		if (!(((buf[1 + i*2] >= '0') && (buf[1 + i*2] <= '9')) || ((buf[1 + i*2] >= 'a') && (buf[1 + i*2] <= 'f')) || ((buf[1 + i*2] >= 'A') && (buf[1 + i*2] <= 'F'))))
+		  return -EINVAL;
+        buf2[i] = (unsigned int)simple_strtoul(buf1, NULL, 16);
+    }
+
+	/*
+	 * Write data to chip, protecting against concurrent updates
+	 * from this host, but not from other I2C masters.
+	 */
+	mutex_lock(&at24->lock);
 
-	return at24_write(at24, buf, offset, count);
+	status = at24->write_func(at24, buf2, SECO_MAC_OFFSET, SECO_MAC_CHAR_LEN/2);
+	if (status < 0) {
+		mutex_unlock(&at24->lock);
+		return status;
+	}
+	mutex_unlock(&at24->lock);
+
+	return 0;
 }
 
-/*-------------------------------------------------------------------------*/
+static int at24_write(void *priv, unsigned int off, void *val, size_t count)
+{
+	struct at24_data *at24 = priv;
+	char *buf = val;
+
+	if (unlikely(!count))
+		return -EINVAL;
+
+	if (off + count > at24->chip.byte_len)
+		return -EINVAL;
+
+	/*
+	 * Write data to chip, protecting against concurrent updates
+	 * from this host, but not from other I2C masters.
+	 */
+	mutex_lock(&at24->lock);
 
-#ifdef CONFIG_OF
-static void at24_get_ofdata(struct i2c_client *client,
-		struct at24_platform_data *chip)
+	while (count) {
+		int status;
+
+		status = at24->write_func(at24, buf, off, count);
+		if (status < 0) {
+			mutex_unlock(&at24->lock);
+			return status;
+		}
+		buf += status;
+		off += status;
+		count -= status;
+	}
+
+	mutex_unlock(&at24->lock);
+
+	return 0;
+}
+
+static void at24_get_pdata(struct device *dev, struct at24_platform_data *chip)
 {
-	const __be32 *val;
-	struct device_node *node = client->dev.of_node;
-
-	if (node) {
-		if (of_get_property(node, "read-only", NULL))
-			chip->flags |= AT24_FLAG_READONLY;
-		val = of_get_property(node, "pagesize", NULL);
-		if (val)
-			chip->page_size = be32_to_cpup(val);
+	int err;
+	u32 val;
+
+	if (device_property_present(dev, "read-only"))
+		chip->flags |= AT24_FLAG_READONLY;
+
+	err = device_property_read_u32(dev, "pagesize", &val);
+	if (!err) {
+		chip->page_size = val;
+	} else {
+		/*
+		 * This is slow, but we can't know all eeproms, so we better
+		 * play safe. Specifying custom eeprom-types via platform_data
+		 * is recommended anyhow.
+		 */
+		chip->page_size = 1;
 	}
 }
-#else
-static void at24_get_ofdata(struct i2c_client *client,
-		struct at24_platform_data *chip)
-{ }
-#endif /* CONFIG_OF */
 
 static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
@@ -487,6 +847,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	struct at24_data *at24;
 	int err;
 	unsigned i, num_addresses;
+	u8 test_byte;
 
 	if (client->dev.platform_data) {
 		chip = *(struct at24_platform_data *)client->dev.platform_data;
@@ -506,15 +867,8 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN));
 		magic >>= AT24_SIZE_BYTELEN;
 		chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS);
-		/*
-		 * This is slow, but we can't know all eeproms, so we better
-		 * play safe. Specifying custom eeprom-types via platform_data
-		 * is recommended anyhow.
-		 */
-		chip.page_size = 1;
 
-		/* update chipdata if OF is present */
-		at24_get_ofdata(client, &chip);
+		at24_get_pdata(&client->dev, &chip);
 
 		chip.setup = NULL;
 		chip.context = NULL;
@@ -531,6 +885,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		dev_warn(&client->dev,
 			"page_size looks suspicious (no power of 2)!\n");
 
+	/*
+	 * REVISIT: the size of the EUI-48 byte array is 6 in at24mac402, while
+	 * the call to ilog2() in AT24_DEVICE_MAGIC() rounds it down to 4.
+	 *
+	 * Eventually we'll get rid of the magic values altoghether in favor of
+	 * real structs, but for now just manually set the right size.
+	 */
+	if (chip.flags & AT24_FLAG_MAC && chip.byte_len == 4)
+		chip.byte_len = 6;
+
 	/* Use I2C operations unless we're stuck with SMBus extensions. */
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		if (chip.flags & AT24_FLAG_ADDR16)
@@ -548,10 +912,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		} else {
 			return -EPFNOSUPPORT;
 		}
-	}
 
-	/* Use I2C operations unless we're stuck with SMBus extensions. */
-	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		if (i2c_check_functionality(client->adapter,
 				I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
 			use_smbus_write = I2C_SMBUS_I2C_BLOCK_DATA;
@@ -579,17 +940,34 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	at24->chip = chip;
 	at24->num_addresses = num_addresses;
 
-	/*
-	 * Export the EEPROM bytes through sysfs, since that's convenient.
-	 * By default, only root should see the data (maybe passwords etc)
-	 */
-	sysfs_bin_attr_init(&at24->bin);
-	at24->bin.attr.name = "eeprom";
-	at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR;
-	at24->bin.read = at24_bin_read;
-	at24->bin.size = chip.byte_len;
+	if ((chip.flags & AT24_FLAG_SERIAL) && (chip.flags & AT24_FLAG_MAC)) {
+		dev_err(&client->dev,
+			"invalid device data - cannot have both AT24_FLAG_SERIAL & AT24_FLAG_MAC.");
+		return -EINVAL;
+	}
 
-	at24->macc.read = at24_macc_read;
+	if (chip.flags & AT24_FLAG_SERIAL) {
+		at24->read_func = at24_eeprom_read_serial;
+	} else if (chip.flags & AT24_FLAG_MAC) {
+		at24->read_func = at24_eeprom_read_mac;
+	} else if (chip.flags & AT24_FLAG_SECO_PARTITION) {
+		at24->read_func = at24_eeprom_seco_read;
+	} else {
+		at24->read_func = at24->use_smbus ? at24_eeprom_read_smbus
+						  : at24_eeprom_read_i2c;
+	}
+
+	if (at24->use_smbus) {
+		if (at24->use_smbus_write == I2C_SMBUS_I2C_BLOCK_DATA)
+			at24->write_func = at24_eeprom_write_smbus_block;
+		else
+			at24->write_func = at24_eeprom_write_smbus_byte;
+	} else {
+	    if (chip.flags & AT24_FLAG_SECO_PARTITION)
+		    at24->write_func = at24_eeprom_seco_write;
+	    else
+		    at24->write_func = at24_eeprom_write_i2c;
+	}
 
 	writable = !(chip.flags & AT24_FLAG_READONLY);
 	if (writable) {
@@ -597,11 +975,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 			unsigned write_max = chip.page_size;
 
-			at24->macc.write = at24_macc_write;
-
-			at24->bin.write = at24_bin_write;
-			at24->bin.attr.mode |= S_IWUSR;
-
 			if (write_max > io_limit)
 				write_max = io_limit;
 			if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
@@ -633,14 +1006,89 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		}
 	}
 
-	err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin);
-	if (err)
-		goto err_clients;
-
 	i2c_set_clientdata(client, at24);
 
-	dev_info(&client->dev, "%zu byte %s EEPROM, %s, %u bytes/write\n",
-		at24->bin.size, client->name,
+	/*
+	 * Perform a one-byte test read to verify that the
+	 * chip is functional.
+	 */
+	err = at24_read(at24, 0, &test_byte, 1);
+	if (err) {
+		err = -ENODEV;
+		goto err_clients;
+	}
+
+    if (chip.flags & AT24_FLAG_SECO_PARTITION) {
+        at24->serial_nvmem_config.name = "serial_seco";
+        at24->serial_nvmem_config.dev = &client->dev;
+        at24->serial_nvmem_config.read_only = false;
+        at24->serial_nvmem_config.root_only = true;
+        at24->serial_nvmem_config.owner = THIS_MODULE;
+        at24->serial_nvmem_config.compat = false;
+        at24->serial_nvmem_config.base_dev = &client->dev;
+        at24->serial_nvmem_config.reg_read = at24_serial_read;
+        at24->serial_nvmem_config.reg_write = at24_serial_write;
+        at24->serial_nvmem_config.priv = at24;
+        at24->serial_nvmem_config.stride = 1;
+        at24->serial_nvmem_config.word_size = 1;
+        at24->serial_nvmem_config.size = SECO_SERIAL_CHAR_LEN;
+
+
+	    at24->serial_nvmem = nvmem_register(&at24->serial_nvmem_config);
+
+
+        if (IS_ERR(at24->nvmem)) {
+            err = PTR_ERR(at24->nvmem);
+            goto err_clients;
+        }
+
+        at24->mac_nvmem_config.name = "mac_seco";
+        at24->mac_nvmem_config.dev = &client->dev;
+        at24->mac_nvmem_config.read_only = false;
+        at24->mac_nvmem_config.root_only = true;
+        at24->mac_nvmem_config.owner = THIS_MODULE;
+        at24->mac_nvmem_config.compat = false;
+        at24->mac_nvmem_config.base_dev = &client->dev;
+        at24->mac_nvmem_config.reg_read = at24_mac_read;
+        at24->mac_nvmem_config.reg_write = at24_mac_write;
+        at24->mac_nvmem_config.priv = at24;
+        at24->mac_nvmem_config.stride = 1;
+        at24->mac_nvmem_config.word_size = 1;
+        at24->mac_nvmem_config.size = SECO_MAC_CHAR_LEN;
+
+
+	    at24->mac_nvmem = nvmem_register(&at24->mac_nvmem_config);
+
+
+        if (IS_ERR(at24->mac_nvmem)) {
+            err = PTR_ERR(at24->mac_nvmem);
+            goto err_clients;
+        }
+    } else {
+        at24->nvmem_config.name = dev_name(&client->dev);
+        at24->nvmem_config.dev = &client->dev;
+        at24->nvmem_config.read_only = !writable;
+        at24->nvmem_config.root_only = true;
+        at24->nvmem_config.owner = THIS_MODULE;
+        at24->nvmem_config.compat = true;
+        at24->nvmem_config.base_dev = &client->dev;
+        at24->nvmem_config.reg_read = at24_read;
+        at24->nvmem_config.reg_write = at24_write;
+        at24->nvmem_config.priv = at24;
+        at24->nvmem_config.stride = 1;
+        at24->nvmem_config.word_size = 1;
+        at24->nvmem_config.size = chip.byte_len;
+        
+        at24->nvmem = nvmem_register(&at24->nvmem_config);
+
+        if (IS_ERR(at24->nvmem)) {
+            err = PTR_ERR(at24->nvmem);
+            goto err_clients;
+        }
+    }
+
+	dev_info(&client->dev, "%u byte %s EEPROM, %s, %u bytes/write\n",
+		chip.byte_len, client->name,
 		writable ? "writable" : "read-only", at24->write_max);
 	if (use_smbus == I2C_SMBUS_WORD_DATA ||
 	    use_smbus == I2C_SMBUS_BYTE_DATA) {
@@ -651,7 +1099,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 	/* export data to kernel code */
 	if (chip.setup)
-		chip.setup(&at24->macc, chip.context);
+		chip.setup(at24->nvmem, chip.context);
 
 	return 0;
 
@@ -669,7 +1117,8 @@ static int at24_remove(struct i2c_client *client)
 	int i;
 
 	at24 = i2c_get_clientdata(client);
-	sysfs_remove_bin_file(&client->dev.kobj, &at24->bin);
+
+	nvmem_unregister(at24->nvmem);
 
 	for (i = 1; i < at24->num_addresses; i++)
 		i2c_unregister_device(at24->client[i]);
diff --git a/include/linux/platform_data/at24.h b/include/linux/platform_data/at24.h
index c42aa89d34eeb46ff0ec5f4e68229ad1fa0fad2a..aa3c96189fae781120f20bf15a2097e842c3eb68 100644
--- a/include/linux/platform_data/at24.h
+++ b/include/linux/platform_data/at24.h
@@ -9,7 +9,8 @@
 #define _LINUX_AT24_H
 
 #include <linux/types.h>
-#include <linux/memory.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/bitops.h>
 
 /**
  * struct at24_platform_data - data to set up at24 (generic eeprom) driver
@@ -17,7 +18,7 @@
  * @page_size: number of byte which can be written in one go
  * @flags: tunable options, check AT24_FLAG_* defines
  * @setup: an optional callback invoked after eeprom is probed; enables kernel
-	code to access eeprom via memory_accessor, see example
+	code to access eeprom via nvmem, see example
  * @context: optional parameter passed to setup()
  *
  * If you set up a custom eeprom type, please double-check the parameters.
@@ -26,13 +27,13 @@
  *
  * An example in pseudo code for a setup() callback:
  *
- * void get_mac_addr(struct memory_accessor *mem_acc, void *context)
+ * void get_mac_addr(struct nvmem_device *nvmem, void *context)
  * {
  *	u8 *mac_addr = ethernet_pdata->mac_addr;
  *	off_t offset = context;
  *
  *	// Read MAC addr from EEPROM
- *	if (mem_acc->read(mem_acc, mac_addr, offset, ETH_ALEN) == ETH_ALEN)
+ *	if (nvmem_device_read(nvmem, offset, ETH_ALEN, mac_addr) == ETH_ALEN)
  *		pr_info("Read MAC addr from EEPROM: %pM\n", mac_addr);
  * }
  *
@@ -43,13 +44,18 @@ struct at24_platform_data {
 	u32		byte_len;		/* size (sum of all addr) */
 	u16		page_size;		/* for writes */
 	u8		flags;
-#define AT24_FLAG_ADDR16	0x80	/* address pointer is 16 bit */
-#define AT24_FLAG_READONLY	0x40	/* sysfs-entry will be read-only */
-#define AT24_FLAG_IRUGO		0x20	/* sysfs-entry will be world-readable */
-#define AT24_FLAG_TAKE8ADDR	0x10	/* take always 8 addresses (24c00) */
+#define AT24_FLAG_ADDR16	BIT(7)	/* address pointer is 16 bit */
+#define AT24_FLAG_READONLY	BIT(6)	/* sysfs-entry will be read-only */
+#define AT24_FLAG_IRUGO		BIT(5)	/* sysfs-entry will be world-readable */
+#define AT24_FLAG_TAKE8ADDR	BIT(4)	/* take always 8 addresses (24c00) */
+#define AT24_FLAG_SERIAL	BIT(3)	/* factory-programmed serial number */
+#define AT24_FLAG_MAC		BIT(2)	/* factory-programmed mac address */
+#define AT24_FLAG_SECO_PARTITION	BIT(1)	/* Seco eeprom partitioning reserve first 32 byte */
 
-	void		(*setup)(struct memory_accessor *, void *context);
+
+	void		(*setup)(struct nvmem_device *nvmem, void *context);
 	void		*context;
 };
 
 #endif /* _LINUX_AT24_H */
+