Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Markus Heidelberg and committed by
Greg Kroah-Hartman
1b434ed0 534c702c

+36 -31
+36 -31
drivers/misc/eeprom/at25.c
··· 379 379 struct at25_data *at25 = container_of(chip, struct at25_data, chip); 380 380 u8 sernum[FM25_SN_LEN]; 381 381 u8 id[FM25_ID_LEN]; 382 + u32 val; 382 383 int i; 383 384 384 385 strscpy(chip->name, "fm25", sizeof(chip->name)); 385 386 386 - /* Get ID of chip */ 387 - fm25_aux_read(at25, id, FM25_RDID, FM25_ID_LEN); 388 - /* There are inside-out FRAM variations, detect them and reverse the ID bytes */ 389 - if (id[6] == 0x7f && id[2] == 0xc2) 390 - for (i = 0; i < ARRAY_SIZE(id) / 2; i++) { 391 - u8 tmp = id[i]; 392 - int j = ARRAY_SIZE(id) - i - 1; 387 + if (!device_property_read_u32(dev, "size", &val)) { 388 + chip->byte_len = val; 389 + } else { 390 + /* Get ID of chip */ 391 + fm25_aux_read(at25, id, FM25_RDID, FM25_ID_LEN); 392 + /* There are inside-out FRAM variations, detect them and reverse the ID bytes */ 393 + if (id[6] == 0x7f && id[2] == 0xc2) 394 + for (i = 0; i < ARRAY_SIZE(id) / 2; i++) { 395 + u8 tmp = id[i]; 396 + int j = ARRAY_SIZE(id) - i - 1; 393 397 394 - id[i] = id[j]; 395 - id[j] = tmp; 398 + id[i] = id[j]; 399 + id[j] = tmp; 400 + } 401 + if (id[6] != 0xc2) { 402 + dev_err(dev, "Error: no Cypress FRAM (id %02x)\n", id[6]); 403 + return -ENODEV; 396 404 } 397 - if (id[6] != 0xc2) { 398 - dev_err(dev, "Error: no Cypress FRAM (id %02x)\n", id[6]); 399 - return -ENODEV; 400 - } 401 405 402 - switch (id[7]) { 403 - case 0x21 ... 0x26: 404 - chip->byte_len = BIT(id[7] - 0x21 + 4) * 1024; 405 - break; 406 - case 0x2a ... 0x30: 407 - /* CY15B116QN ... CY15B116QN */ 408 - chip->byte_len = BIT(((id[7] >> 1) & 0xf) + 13); 409 - break; 410 - default: 411 - dev_err(dev, "Error: unsupported size (id %02x)\n", id[7]); 412 - return -ENODEV; 406 + switch (id[7]) { 407 + case 0x21 ... 0x26: 408 + chip->byte_len = BIT(id[7] - 0x21 + 4) * 1024; 409 + break; 410 + case 0x2a ... 0x30: 411 + /* CY15B116QN ... CY15B116QN */ 412 + chip->byte_len = BIT(((id[7] >> 1) & 0xf) + 13); 413 + break; 414 + default: 415 + dev_err(dev, "Error: unsupported size (id %02x)\n", id[7]); 416 + return -ENODEV; 417 + } 418 + 419 + if (id[8]) { 420 + fm25_aux_read(at25, sernum, FM25_RDSN, FM25_SN_LEN); 421 + /* Swap byte order */ 422 + for (i = 0; i < FM25_SN_LEN; i++) 423 + at25->sernum[i] = sernum[FM25_SN_LEN - 1 - i]; 424 + } 413 425 } 414 426 415 427 if (chip->byte_len > 64 * 1024) 416 428 chip->flags |= EE_ADDR3; 417 429 else 418 430 chip->flags |= EE_ADDR2; 419 - 420 - if (id[8]) { 421 - fm25_aux_read(at25, sernum, FM25_RDSN, FM25_SN_LEN); 422 - /* Swap byte order */ 423 - for (i = 0; i < FM25_SN_LEN; i++) 424 - at25->sernum[i] = sernum[FM25_SN_LEN - 1 - i]; 425 - } 426 431 427 432 chip->page_size = PAGE_SIZE; 428 433 return 0;