summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Heidelberg <m.heidelberg@cab.de>2025-08-15 11:58:37 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-09-06 15:58:23 +0200
commit1b434ed000cd474f074e62e8ab876f87449bb4ac (patch)
treec074c8aed21e05e375034e17e46d87535150f8df
parent534c702c3c234665ca2fe426a9fbb12281e55d55 (diff)
eeprom: at25: support Cypress FRAMs without device ID
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>
-rw-r--r--drivers/misc/eeprom/at25.c67
1 files changed, 36 insertions, 31 deletions
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 2d0492867054..c90150f72836 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -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;
}