[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <cfdff4f068c98feba252b28fb61de7629637dc45.camel@gmail.com>
Date: Thu, 14 Aug 2025 14:24:06 +0200
From: Alexander Sverdlin <alexander.sverdlin@...il.com>
To: Markus Heidelberg <m.heidelberg@....de>, Arnd Bergmann <arnd@...db.de>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>, devicetree@...r.kernel.org
Cc: Rob Herring <robh@...nel.org>, Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>, Christian Eggers <ceggers@...i.de>,
Jiri Prchal <jiri.prchal@...ignal.cz>, linux-kernel@...r.kernel.org
Subject: Re: [PATCH 2/3] eeprom: at25: support Cypress FRAMs without device
ID
On Thu, 2025-08-14 at 13:15 +0200, Markus Heidelberg wrote:
> 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@....de>
Reviewed-by: Alexander Sverdlin <alexander.sverdlin@...il.com>
> ---
> drivers/misc/eeprom/at25.c | 67 ++++++++++++++++++++------------------
> 1 file 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;
> }
> --
> 2.43.0
--
Alexander Sverdlin.
Powered by blists - more mailing lists