]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
eeprom: at25: support Cypress FRAMs without device ID
authorMarkus Heidelberg <m.heidelberg@cab.de>
Fri, 15 Aug 2025 09:58:37 +0000 (11:58 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 6 Sep 2025 13:58:23 +0000 (15:58 +0200)
Not all FRAM chips have a device ID and implement the corresponding read
command. For such chips this led to the following error on module
loading:

    at25 spi2.0: Error: no Cypress FRAM (id 00)

The device ID contains the memory size, so devices without this ID are
supported now by setting the size manually in Devicetree using the
"size" property.

Tested with FM25L16B and "size = <2048>;":

    at25 spi2.0: 2 KByte fm25 fram, pagesize 4096

According to Infineon/Cypress datasheets, these FRAMs have a device ID:

    FM25V01A
    FM25V02A
    FM25V05
    FM25V10
    FM25V20A
    FM25VN10

but these do not:

    FM25040B
    FM25640B
    FM25C160B
    FM25CL64B
    FM25L04B
    FM25L16B
    FM25W256

So all "FM25V*" FRAMs and only these have a device ID. The letter after
"FM25" (V/C/L/W) only describes the voltage range, though.

Link: https://lore.kernel.org/all/20250401133148.38330-1-m.heidelberg@cab.de/
Signed-off-by: Markus Heidelberg <m.heidelberg@cab.de>
Reviewed-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
Link: https://lore.kernel.org/r/20250815095839.4219-3-m.heidelberg@cab.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/eeprom/at25.c

index 2d0492867054f8ce08cd00765500372b541b7bb3..c90150f728369e9f45d74966f4c3eccef6aec3cb 100644 (file)
@@ -379,37 +379,49 @@ static int at25_fram_to_chip(struct device *dev, struct spi_eeprom *chip)
        struct at25_data *at25 = container_of(chip, struct at25_data, chip);
        u8 sernum[FM25_SN_LEN];
        u8 id[FM25_ID_LEN];
+       u32 val;
        int i;
 
        strscpy(chip->name, "fm25", sizeof(chip->name));
 
-       /* Get ID of chip */
-       fm25_aux_read(at25, id, FM25_RDID, FM25_ID_LEN);
-       /* There are inside-out FRAM variations, detect them and reverse the ID bytes */
-       if (id[6] == 0x7f && id[2] == 0xc2)
-               for (i = 0; i < ARRAY_SIZE(id) / 2; i++) {
-                       u8 tmp = id[i];
-                       int j = ARRAY_SIZE(id) - i - 1;
+       if (!device_property_read_u32(dev, "size", &val)) {
+               chip->byte_len = val;
+       } else {
+               /* Get ID of chip */
+               fm25_aux_read(at25, id, FM25_RDID, FM25_ID_LEN);
+               /* There are inside-out FRAM variations, detect them and reverse the ID bytes */
+               if (id[6] == 0x7f && id[2] == 0xc2)
+                       for (i = 0; i < ARRAY_SIZE(id) / 2; i++) {
+                               u8 tmp = id[i];
+                               int j = ARRAY_SIZE(id) - i - 1;
+
+                               id[i] = id[j];
+                               id[j] = tmp;
+                       }
+               if (id[6] != 0xc2) {
+                       dev_err(dev, "Error: no Cypress FRAM (id %02x)\n", id[6]);
+                       return -ENODEV;
+               }
 
-                       id[i] = id[j];
-                       id[j] = tmp;
+               switch (id[7]) {
+               case 0x21 ... 0x26:
+                       chip->byte_len = BIT(id[7] - 0x21 + 4) * 1024;
+                       break;
+               case 0x2a ... 0x30:
+                       /* CY15B116QN ... CY15B116QN */
+                       chip->byte_len = BIT(((id[7] >> 1) & 0xf) + 13);
+                       break;
+               default:
+                       dev_err(dev, "Error: unsupported size (id %02x)\n", id[7]);
+                       return -ENODEV;
                }
-       if (id[6] != 0xc2) {
-               dev_err(dev, "Error: no Cypress FRAM (id %02x)\n", id[6]);
-               return -ENODEV;
-       }
 
-       switch (id[7]) {
-       case 0x21 ... 0x26:
-               chip->byte_len = BIT(id[7] - 0x21 + 4) * 1024;
-               break;
-       case 0x2a ... 0x30:
-               /* CY15B116QN ... CY15B116QN */
-               chip->byte_len = BIT(((id[7] >> 1) & 0xf) + 13);
-               break;
-       default:
-               dev_err(dev, "Error: unsupported size (id %02x)\n", id[7]);
-               return -ENODEV;
+               if (id[8]) {
+                       fm25_aux_read(at25, sernum, FM25_RDSN, FM25_SN_LEN);
+                       /* Swap byte order */
+                       for (i = 0; i < FM25_SN_LEN; i++)
+                               at25->sernum[i] = sernum[FM25_SN_LEN - 1 - i];
+               }
        }
 
        if (chip->byte_len > 64 * 1024)
@@ -417,13 +429,6 @@ static int at25_fram_to_chip(struct device *dev, struct spi_eeprom *chip)
        else
                chip->flags |= EE_ADDR2;
 
-       if (id[8]) {
-               fm25_aux_read(at25, sernum, FM25_RDSN, FM25_SN_LEN);
-               /* Swap byte order */
-               for (i = 0; i < FM25_SN_LEN; i++)
-                       at25->sernum[i] = sernum[FM25_SN_LEN - 1 - i];
-       }
-
        chip->page_size = PAGE_SIZE;
        return 0;
 }