summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/eeprom/at24.c42
-rw-r--r--include/linux/platform_data/at24.h1
2 files changed, 43 insertions, 0 deletions
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 3b27ff14876c..04e91e331fc5 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -139,6 +139,10 @@ static const struct i2c_device_id at24_ids[] = {
{ "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) },
@@ -347,6 +351,36 @@ static ssize_t at24_eeprom_read_serial(struct at24_data *at24, char *buf,
return -ETIMEDOUT;
}
+static ssize_t at24_eeprom_read_mac(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];
+ u8 addrbuf[2];
+ int status;
+
+ client = at24_translate_offset(at24, &offset);
+
+ memset(msg, 0, sizeof(msg));
+ msg[0].addr = client->addr;
+ msg[0].buf = addrbuf;
+ addrbuf[0] = 0x90 + 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
@@ -648,8 +682,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
at24->chip = chip;
at24->num_addresses = num_addresses;
+ 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;
+ }
+
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 {
at24->read_func = at24->use_smbus ? at24_eeprom_read_smbus
: at24_eeprom_read_i2c;
diff --git a/include/linux/platform_data/at24.h b/include/linux/platform_data/at24.h
index d59587473aed..271a4e25af67 100644
--- a/include/linux/platform_data/at24.h
+++ b/include/linux/platform_data/at24.h
@@ -49,6 +49,7 @@ struct at24_platform_data {
#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 */
void (*setup)(struct nvmem_device *nvmem, void *context);
void *context;