diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig index 81156c893b6..ccc06d8e5f8 100644 --- a/drivers/eeprom/Kconfig +++ b/drivers/eeprom/Kconfig @@ -41,6 +41,15 @@ config EE24XX_FREQUENCY default 100000 depends on I2C_EE_24XX +config AT24CS_UUID + bool "Device driver support for Atmel AT24CSxx UUID" + default n + depends on I2C_EE_24XX + ---help--- + The Atmel AT24CSxx family have a 128-bit UUID which appears as + another I2C slave whose address is offset from the EEPROM by +8. + This option registers a char device driver with the ".uuid" suffix. + endif # I2C_EE_24XX endif # EEPROM diff --git a/drivers/eeprom/i2c_xx24xx.c b/drivers/eeprom/i2c_xx24xx.c index 982bb7f89c9..11c19d85e33 100644 --- a/drivers/eeprom/i2c_xx24xx.c +++ b/drivers/eeprom/i2c_xx24xx.c @@ -92,6 +92,7 @@ #include #include #include +#include #include #include @@ -161,6 +162,11 @@ static ssize_t ee24xx_write(FAR struct file *filep, FAR const char *buffer, static int ee24xx_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +#ifdef CONFIG_AT24CS_UUID +static ssize_t at24cs_read_uuid(FAR struct file *filep, FAR char *buffer, + size_t buflen); +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -210,6 +216,19 @@ static const struct file_operations ee24xx_fops = NULL /* poll */ }; +#ifdef CONFIG_AT24CS_UUID +static const struct file_operations at24cs_uuid_fops = +{ + ee24xx_open, /* piggyback on the ee24xx_open */ + ee24xx_close, /* piggyback on the ee24xx_close */ + at24cs_read_uuid, /* read */ + NULL, /* write */ + NULL, /* seek */ + NULL, /* ioctl */ + NULL /* poll */ +}; +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -540,6 +559,79 @@ done: return ret; } +#ifdef CONFIG_AT24CS_UUID +/**************************************************************************** + * Name: at24cs_read_uuid + ****************************************************************************/ +#define UUID_SIZE 16 + +static ssize_t at24cs_read_uuid(FAR struct file *filep, FAR char *buffer, + size_t len) +{ + FAR struct ee24xx_dev_s *eedev; + FAR struct inode *inode = filep->f_inode; + struct i2c_msg_s msgs[2]; + uint8_t regindx; + int ret; + + DEBUGASSERT(inode && inode->i_private); + eedev = (FAR struct ee24xx_dev_s *)inode->i_private; + + ee24xx_semtake(eedev); + + /* trim len if read would go beyond end of device */ + + if ((filep->f_pos + len) > UUID_SIZE) + { + len = UUID_SIZE - filep->f_pos; + } + + if (len == 0) + { + /* We are at end of file */ + + ret = 0; + goto done; + } + + /* Write data address */ + + finfo("READ %d bytes at pos %d\n", len, filep->f_pos); + + regindx = 0x80; /* reg index of UUID[0] */ + + msgs[0].frequency = eedev->freq; + msgs[0].addr = eedev->addr + 8; /* slave addr of UUID */ + msgs[0].flags = 0; + msgs[0].buffer = ®indx; + msgs[0].length = 1; + + /* Read data */ + + msgs[1].frequency = msgs[0].frequency; + msgs[1].addr = msgs[0].addr; + msgs[1].flags = I2C_M_READ; + msgs[1].buffer = (uint8_t *)buffer; + msgs[1].length = len; + + ret = I2C_TRANSFER(eedev->i2c, msgs, 2); + if (ret < 0) + { + goto done; + } + + ret = len; + + /* Update the file position */ + + filep->f_pos += len; + +done: + ee24xx_semgive(eedev); + return ret; +} +#endif + /**************************************************************************** * Name: ee24xx_write ****************************************************************************/ @@ -705,6 +797,10 @@ int ee24xx_initialize(FAR struct i2c_master_s *bus, uint8_t devaddr, FAR char *devname, int devtype, int readonly) { FAR struct ee24xx_dev_s *eedev; +#ifdef CONFIG_AT24CS_UUID + FAR char *uuidname; + int ret; +#endif /* Check device type early */ @@ -759,7 +855,7 @@ int ee24xx_initialize(FAR struct i2c_master_s *bus, uint8_t devaddr, ferr("Device 24xx1025 is not supported for the moment, TODO.\n"); eedev->haddrshift = 2; - free(eedev); + kmm_free(eedev); return -ENODEV; } } @@ -768,5 +864,29 @@ int ee24xx_initialize(FAR struct i2c_master_s *bus, uint8_t devaddr, devname, eedev->size, eedev->pgsize, eedev->addrlen, eedev->readonly ? "readonly" : ""); +#ifdef CONFIG_AT24CS_UUID + uuidname = kmm_zalloc(strlen(devname) + 8); + if (!uuidname) + { + return -ENOMEM; + } + + /* register the UUID I2C slave with the same name as the parent + * EEPROM chip, but with the ".uuid" suffix + */ + + strcpy(uuidname, devname); + strcat(uuidname, ".uuid"); + ret = register_driver(uuidname, &at24cs_uuid_fops, 0444, eedev); + + kmm_free(uuidname); + + if (OK != ret) + { + ferr("register uuid failed, ret = %d\n", ret); + return ret; + } +#endif + return register_driver(devname, &ee24xx_fops, 0666, eedev); }