[{"id":3649992,"web_url":"http://patchwork.ozlabs.org/comment/3649992/","msgid":"<3fe5e11d-7240-c577-64fc-062d5c5e4d6a@gmail.com>","list_archive_url":null,"date":"2026-02-13T15:34:33","subject":"Re: [PATCH v2 2/6] misc: Add support for bit fields in NVMEM cells","submitter":{"id":64621,"url":"http://patchwork.ozlabs.org/api/people/64621/","name":"Sean Anderson","email":"seanga2@gmail.com"},"content":"On 2/13/26 06:27, Aswin Murugan wrote:\n> NVMEM cells currently only support byte-level access. Many hardware\n> registers pack multiple fields into single bytes, requiring bit-level\n> granularity. For example, Qualcomm PMIC PON registers store a 7-bit\n> reboot reason field within a single byte, with bit 0 reserved for other\n> purposes.\n> \n> Add support for the optional 'bits' property in NVMEM cell device tree\n> bindings. This property specifies <bit_offset num_bits> to define a bit\n> field within the cell's register space.\n> \n> Implement multi-byte bit field support by porting bit manipulation\n> algorithms from the Linux kernel driver [1]:\n> \n> 1. nvmem_shift_read_buffer_in_place() - Extract bit fields from raw\n>     bytes by shifting and masking across byte boundaries. Handles fields\n>     that span multiple bytes.\n> \n> 2. nvmem_cell_prepare_write_buffer() - Perform Read-Modify-Write to\n>     preserve bits outside the target field. Read current values, mask to\n>     preserve adjacent bits, and combine with new value.\n> \n> Example device tree usage:\n>          reboot-reason@48 {\n>                  reg = <0x48 0x01>;\n>                  bits = <0x01 0x07>;  /* 7 bits starting at bit 1 */\n>          };\n> \n> This reads bits [7:1] from the byte at offset 0x48, leaving bit 0\n> untouched during write operations.\n> \n> Cells without the 'bits' property continue to work unchanged, ensuring\n> backward compatibility with existing device trees.\n> \n> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/nvmem/core.c\n> \n> Signed-off-by: Aswin Murugan <aswin.murugan@oss.qualcomm.com>\n\nThis seems like it adds a lot of calculations; have you looked at the size\nincrease? Maybe this should be a separate config, since the feature does not\nseem too common.\n\nActually, I think we could reduce the complexity quite a bit by refusing\nto process bits longer than a ulong. A quick grep through Linux's dts shows\nthat the largest bits is <6 12>. I don't really see any reason we need to\nsupport arbitrary bit extraction.\n\nThere should also be a test for this. The existing code is lightly tested by\nchecking that mac addresses are loaded correctly. Maybe you can extend\ntest/dm/reboot-mode.c.\n\n> ---\n>   drivers/misc/nvmem.c | 241 ++++++++++++++++++++++++++++++++++++++++---\n>   include/nvmem.h      |   4 +\n>   2 files changed, 231 insertions(+), 14 deletions(-)\n> \n> diff --git a/drivers/misc/nvmem.c b/drivers/misc/nvmem.c\n> index 33e80858565..6a75c326189 100644\n> --- a/drivers/misc/nvmem.c\n> +++ b/drivers/misc/nvmem.c\n> @@ -12,52 +12,251 @@\n>   #include <dm/ofnode.h>\n>   #include <dm/read.h>\n>   #include <dm/uclass.h>\n> +#include <linux/bitops.h>\n> +#include <linux/kernel.h>\n> +\n> +/**\n> + * nvmem_shift_read_buffer_in_place() - Shift read buffer to extract bit field\n> + * @cell: NVMEM cell with bit field information\n> + * @buf: Buffer containing raw bytes read from NVMEM\n> + *\n> + * This function shifts and masks the buffer to extract only the bits specified\n> + * by cell->bit_offset and cell->nbits. It handles bit fields that span multiple\n> + * bytes by shifting bits across byte boundaries.\n> + *\n> + */\n> +static void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf)\n> +{\n> +\tu8 *prev_byte, *buf_ptr;\n> +\tint i, extra, bit_offset = cell->bit_offset;\n> +\tint bytes_needed;\n> +\n> +\tbytes_needed = DIV_ROUND_UP(cell->nbits + cell->bit_offset, BITS_PER_BYTE);\n> +\n> +\tprev_byte = buf_ptr = buf;\n> +\tif (bit_offset) {\n> +\t\t/* First byte: shift right by bit_offset */\n> +\t\t*buf_ptr++ >>= bit_offset;\n> +\n> +\t\t/* Process remaining bytes, combining bits across boundaries */\n> +\t\tfor (i = 1; i < bytes_needed; i++) {\n> +\t\t\t/* Get bits from next byte and shift them towards MSB */\n> +\t\t\t*prev_byte |= *buf_ptr << (BITS_PER_BYTE - bit_offset);\n> +\n> +\t\t\tprev_byte = buf_ptr;\n> +\t\t\t*buf_ptr++ >>= bit_offset;\n> +\t\t}\n> +\t} else {\n> +\t\t/* Point to the MSB */\n> +\t\tprev_byte += bytes_needed - 1;\n> +\t}\n> +\n> +\t/* Clear extra bytes if result fits in fewer bytes */\n> +\textra = bytes_needed - DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE);\n> +\twhile (--extra >= 0)\n> +\t\t*prev_byte-- = 0;\n> +\n> +\t/* Clear MSB bits if any leftover in the last byte */\n> +\tif (cell->nbits % BITS_PER_BYTE)\n> +\t\t*prev_byte &= GENMASK((cell->nbits % BITS_PER_BYTE) - 1, 0);\n> +}\n> +\n> +/**\n> + * nvmem_cell_prepare_write_buffer() - Prepare buffer for writing bit field\n> + * @cell: NVMEM cell with bit field information\n> + * @buf: Buffer containing value to write\n> + * @size: Size of buf\n> + * @data: Output buffer with prepared data for writing\n> + *\n> + * This function performs Read-Modify-Write to preserve bits outside the\n> + * specified bit field. It reads current values, modifies only the target\n> + * bits, and prepares the complete bytes for writing back.\n> + *\n> + * Return: 0 on success, negative error code on failure\n> + */\n> +static int nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,\n> +\t\t\t\t\t   const void *buf, size_t size,\n> +\t\t\t\t\t   u8 *data)\n> +{\n> +\tint i, rc, nbits, bit_offset = cell->bit_offset;\n> +\tint bytes_needed;\n> +\tu8 current_val, *prev_byte, *buf_ptr, prev_byte_val, prev_bits;\n> +\n> +\tnbits = cell->nbits;\n> +\tbytes_needed = DIV_ROUND_UP(nbits + bit_offset, BITS_PER_BYTE);\n> +\n> +\tmemcpy(data, buf, size);\n> +\tprev_byte = buf_ptr = data;\n> +\n> +\tif (bit_offset) {\n> +\t\tprev_byte_val = *buf_ptr;\n> +\t\t*buf_ptr <<= bit_offset;\n> +\n> +\t\t/* Setup the first byte with LSB bits from NVMEM */\n> +\t\tswitch (cell->nvmem->driver->id) {\n> +\t\tcase UCLASS_I2C_EEPROM:\n> +\t\t\trc = i2c_eeprom_read(cell->nvmem, cell->offset, &current_val, 1);\n> +\t\t\tbreak;\n> +\t\tcase UCLASS_MISC:\n> +\t\t\trc = misc_read(cell->nvmem, cell->offset, &current_val, 1);\n> +\t\t\tif (rc < 0)\n> +\t\t\t\treturn rc;\n> +\t\t\tif (rc != 1)\n> +\t\t\t\treturn -EIO;\n> +\t\t\trc = 0;\n> +\t\t\tbreak;\n> +\t\tcase UCLASS_RTC:\n> +\t\t\trc = dm_rtc_read(cell->nvmem, cell->offset, &current_val, 1);\n> +\t\t\tbreak;\n> +\t\tdefault:\n> +\t\t\treturn -ENOSYS;\n> +\t\t}\n\nCan you use nvmem_cell_read for this to reduce duplication?\n\n> +\n> +\t\tif (rc)\n> +\t\t\treturn rc;\n> +\n> +\t\t*buf_ptr++ |= GENMASK(bit_offset - 1, 0) & current_val;\n> +\n> +\t\t/* Setup rest of the bytes if any */\n> +\t\tfor (i = 1; i < bytes_needed; i++) {\n> +\t\t\t/* Get last byte bits and shift them towards LSB */\n> +\t\t\tprev_bits = prev_byte_val >> (BITS_PER_BYTE - 1 - bit_offset);\n> +\t\t\tprev_byte_val = *buf_ptr;\n> +\t\t\tprev_byte = buf_ptr;\n> +\t\t\t*buf_ptr <<= bit_offset;\n> +\t\t\t*buf_ptr++ |= prev_bits;\n> +\t\t}\n> +\t}\n> +\n> +\t/* If it's not end on byte boundary */\n> +\tif ((nbits + bit_offset) % BITS_PER_BYTE) {\n> +\t\t/* Setup the last byte with MSB bits from NVMEM */\n> +\t\tswitch (cell->nvmem->driver->id) {\n> +\t\tcase UCLASS_I2C_EEPROM:\n> +\t\t\trc = i2c_eeprom_read(cell->nvmem,\n> +\t\t\t\t\t     cell->offset + bytes_needed - 1,\n> +\t\t\t\t\t     &current_val, 1);\n> +\t\t\tbreak;\n> +\t\tcase UCLASS_MISC:\n> +\t\t\trc = misc_read(cell->nvmem,\n> +\t\t\t\t       cell->offset + bytes_needed - 1,\n> +\t\t\t\t       &current_val, 1);\n> +\t\t\tif (rc < 0)\n> +\t\t\t\treturn rc;\n> +\t\t\tif (rc != 1)\n> +\t\t\t\treturn -EIO;\n> +\t\t\trc = 0;\n> +\t\t\tbreak;\n> +\t\tcase UCLASS_RTC:\n> +\t\t\trc = dm_rtc_read(cell->nvmem,\n> +\t\t\t\t\t cell->offset + bytes_needed - 1,\n> +\t\t\t\t\t &current_val, 1);\n> +\t\t\tbreak;\n> +\t\tdefault:\n> +\t\t\treturn -ENOSYS;\n> +\t\t}\n> +\n> +\t\tif (rc)\n> +\t\t\treturn rc;\n> +\n> +\t\t*prev_byte |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & current_val;\n> +\t}\n> +\n> +\treturn 0;\n> +}\n>   \n>   int nvmem_cell_read(struct nvmem_cell *cell, void *buf, size_t size)\n>   {\n> +\tu8 data[size];\n\nNo alloca.\n\n> +\tint bytes_needed;\n> +\tint ret;\n> +\n>   \tdev_dbg(cell->nvmem, \"%s: off=%u size=%zu\\n\", __func__, cell->offset, size);\n\nPlease update these.\n\n> +\n>   \tif (size != cell->size)\n>   \t\treturn -EINVAL;\n>   \n> +\t/* Calculate how many bytes we need to read */\n> +\tif (cell->nbits > 0) {\n\njust if (cell->nbits) for clarity please\n\n(ditto for elsewhere)\n\n> +\t\tbytes_needed = DIV_ROUND_UP(cell->nbits + cell->bit_offset, BITS_PER_BYTE);\n> +\t\tif (bytes_needed > sizeof(data))\n> +\t\t\treturn -EINVAL;\n> +\t} else {\n> +\t\tbytes_needed = size;\n\nThis should always be true even when nbits != 0, as bits specifies the offset/size\n\"within the address range specified by reg.\" This will allow you to use the original buffer.\n\n> +\t}\n> +\n>   \tswitch (cell->nvmem->driver->id) {\n>   \tcase UCLASS_I2C_EEPROM:\n> -\t\treturn i2c_eeprom_read(cell->nvmem, cell->offset, buf, size);\n> -\tcase UCLASS_MISC: {\n> -\t\tint ret = misc_read(cell->nvmem, cell->offset, buf, size);\n> -\n> +\t\tret = i2c_eeprom_read(cell->nvmem, cell->offset, data, bytes_needed);\n> +\t\tbreak;\n> +\tcase UCLASS_MISC:\n> +\t\tret = misc_read(cell->nvmem, cell->offset, data, bytes_needed);\n>   \t\tif (ret < 0)\n>   \t\t\treturn ret;\n> -\t\tif (ret != size)\n> +\t\tif (ret != bytes_needed)\n>   \t\t\treturn -EIO;\n> -\t\treturn 0;\n> -\t}\n> +\t\tret = 0;\n> +\t\tbreak;\n>   \tcase UCLASS_RTC:\n> -\t\treturn dm_rtc_read(cell->nvmem, cell->offset, buf, size);\n> +\t\tret = dm_rtc_read(cell->nvmem, cell->offset, data, bytes_needed);\n> +\t\tbreak;\n>   \tdefault:\n>   \t\treturn -ENOSYS;\n>   \t}\n> +\n> +\tif (ret)\n> +\t\treturn ret;\n> +\n> +\tif (cell->nbits > 0) {\n> +\t\t/* Extract bit field from raw bytes */\n> +\t\tnvmem_shift_read_buffer_in_place(cell, data);\n> +\t\t/* Copy only the bytes containing the bit field result */\n> +\t\tmemcpy(buf, data, DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE));\n> +\t} else {\n> +\t\tmemcpy(buf, data, size);\n> +\t}\n> +\n> +\treturn 0;\n>   }\n>   \n>   int nvmem_cell_write(struct nvmem_cell *cell, const void *buf, size_t size)\n>   {\n> +\tu8 data[size];\n\nAgain, no alloca. Limit the size for cells with bits and you can use a static\nallocation on the stack.\n\n> +\tint bytes_needed;\n> +\tint ret;\n> +\n>   \tdev_dbg(cell->nvmem, \"%s: off=%u size=%zu\\n\", __func__, cell->offset, size);\n> +\n>   \tif (size != cell->size)\n>   \t\treturn -EINVAL;\n>   \n> +\tif (cell->nbits > 0) {\n> +\t\tbytes_needed = DIV_ROUND_UP(cell->nbits + cell->bit_offset, BITS_PER_BYTE);\n> +\t\tif (bytes_needed > sizeof(data))\n> +\t\t\treturn -EINVAL;\n> +\n> +\t\t/* Prepare write buffer with Read-Modify-Write */\n> +\t\tret = nvmem_cell_prepare_write_buffer(cell, buf, size, data);\n> +\t\tif (ret)\n> +\t\t\treturn ret;\n> +\t} else {\n> +\t\tbytes_needed = size;\n> +\t\tmemcpy(data, buf, size);\n> +\t}\n> +\n>   \tswitch (cell->nvmem->driver->id) {\n>   \tcase UCLASS_I2C_EEPROM:\n> -\t\treturn i2c_eeprom_write(cell->nvmem, cell->offset, buf, size);\n> +\t\treturn i2c_eeprom_write(cell->nvmem, cell->offset, data, bytes_needed);\n>   \tcase UCLASS_MISC: {\n> -\t\tint ret = misc_write(cell->nvmem, cell->offset, buf, size);\n> -\n> +\t\tret = misc_write(cell->nvmem, cell->offset, data, bytes_needed);\n>   \t\tif (ret < 0)\n>   \t\t\treturn ret;\n> -\t\tif (ret != size)\n> +\t\tif (ret != bytes_needed)\n>   \t\t\treturn -EIO;\n>   \t\treturn 0;\n>   \t}\n>   \tcase UCLASS_RTC:\n> -\t\treturn dm_rtc_write(cell->nvmem, cell->offset, buf, size);\n> +\t\treturn dm_rtc_write(cell->nvmem, cell->offset, data, bytes_needed);\n>   \tdefault:\n>   \t\treturn -ENOSYS;\n>   \t}\n> @@ -121,13 +320,27 @@ int nvmem_cell_get_by_index(struct udevice *dev, int index,\n>   \n>   \toffset = ofnode_get_addr_size_index_notrans(args.node, 0, &size);\n>   \tif (offset == FDT_ADDR_T_NONE || size == FDT_SIZE_T_NONE) {\n> -\t\tdev_dbg(cell->nvmem, \"missing address or size for %s\\n\",\n> +\t\tdev_err(cell->nvmem, \"missing address or size for %s\\n\",\n>   \t\t\tofnode_get_name(args.node));\n>   \t\treturn -EINVAL;\n>   \t}\n>   \n>   \tcell->offset = offset;\n>   \tcell->size = size;\n> +\n> +\tret = ofnode_read_u32_index(args.node, \"bits\", 0, &cell->bit_offset);\n> +\tif (ret) {\n> +\t\tcell->bit_offset = 0;\n> +\t\tcell->nbits = 0;\n> +\t} else {\n> +\t\tret = ofnode_read_u32_index(args.node, \"bits\", 1, &cell->nbits);\n> +\t\tif (ret)\n> +\t\t\treturn -EINVAL;\n> +\n> +\t\tif (cell->bit_offset + cell->nbits > cell->size * 8)\n> +\t\t\treturn -EINVAL;\n> +\t}\n> +\n>   \treturn 0;\n>   }\n>   \n> diff --git a/include/nvmem.h b/include/nvmem.h\n> index e6a8a98828b..dd82122f16f 100644\n> --- a/include/nvmem.h\n> +++ b/include/nvmem.h\n> @@ -26,11 +26,15 @@\n>    * @nvmem: The backing storage device\n>    * @offset: The offset of the cell from the start of @nvmem\n>    * @size: The size of the cell, in bytes\n> + * @bit_offset: Bit offset within the cell (0 for byte-level access)\n> + * @nbits: Number of bits to use (0 for byte-level access)\n>    */\n>   struct nvmem_cell {\n>   \tstruct udevice *nvmem;\n>   \tunsigned int offset;\n>   \tsize_t size;\n> +\tunsigned int bit_offset;\n> +\tunsigned int nbits;\n>   };\n\nPlease also update the documentation for read/write.\n\n>   struct udevice;","headers":{"Return-Path":"<u-boot-bounces@lists.denx.de>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20230601 header.b=byPObsKF;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)","phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=gmail.com","phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de","phobos.denx.de;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.b=\"byPObsKF\";\n\tdkim-atps=neutral","phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=gmail.com","phobos.denx.de;\n spf=pass smtp.mailfrom=seanga2@gmail.com"],"Received":["from phobos.denx.de (phobos.denx.de\n [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fCGSK6VJbz1xr1\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 14 Feb 2026 02:34:41 +1100 (AEDT)","from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id CBAF483CB5;\n\tFri, 13 Feb 2026 16:34:39 +0100 (CET)","by phobos.denx.de (Postfix, from userid 109)\n id F002983C4B; Fri, 13 Feb 2026 16:34:38 +0100 (CET)","from mail-qk1-x72d.google.com (mail-qk1-x72d.google.com\n [IPv6:2607:f8b0:4864:20::72d])\n (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id 3349D83CEE\n for <u-boot@lists.denx.de>; Fri, 13 Feb 2026 16:34:36 +0100 (CET)","by mail-qk1-x72d.google.com with SMTP id\n af79cd13be357-8cb403b7c75so13633985a.2\n for <u-boot@lists.denx.de>; Fri, 13 Feb 2026 07:34:36 -0800 (PST)","from ?IPV6:2600:4040:4476:3800:2d8:61ff:fe7c:5d59?\n ([2600:4040:4476:3800:2d8:61ff:fe7c:5d59])\n by smtp.gmail.com with ESMTPSA id\n 6a1803df08f44-8971cc823a4sm62690376d6.8.2026.02.13.07.34.33\n (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n Fri, 13 Feb 2026 07:34:34 -0800 (PST)"],"X-Spam-Checker-Version":"SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de","X-Spam-Level":"","X-Spam-Status":"No, score=-3.2 required=5.0 tests=BAYES_00,DKIM_SIGNED,\n DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_GMAIL_RCVD,\n FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,NICE_REPLY_A,\n RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham\n autolearn_force=no version=3.4.2","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20230601; t=1770996875; x=1771601675; darn=lists.denx.de;\n h=content-transfer-encoding:in-reply-to:from:references:cc:to\n :content-language:subject:user-agent:mime-version:date:message-id\n :from:to:cc:subject:date:message-id:reply-to;\n bh=SpkKQ0GeILRrNrVPwGmB8P/O9IkweoueMY2+YrehFCg=;\n b=byPObsKF8i6PA9/foO/b/egrO2SiKw5fWU7q7k6FRGfczgyL218inxL0xHFYZK8/9t\n rYzLLXnb8Bw+tf1/uEVMqjLrLyBlyvNN7bQB18uNy+pmzErHEVAn2QPOOLxuKNxAyyHM\n HVPpeKreJ3dANJfCPzPKketJsiXfARymtFABXCSmLthPCPLUTOPisHpgqUvohSruHXt6\n b5eU2Agwni52lx70Onlcs0YIvmpTF0MjXsv+8eTi80njQg7Q2ciiCKZRxowBhXELpJxI\n UFgQNjO82EodeEbXLD2l8ZczW4WHzpKMjbG1eQI6JvxHoATsuTXLvCfYWxtpBPWori2s\n Qggg==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1770996875; x=1771601675;\n h=content-transfer-encoding:in-reply-to:from:references:cc:to\n :content-language:subject:user-agent:mime-version:date:message-id\n :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id\n :reply-to;\n bh=SpkKQ0GeILRrNrVPwGmB8P/O9IkweoueMY2+YrehFCg=;\n b=FrJr3I+kYjhvHnrOMji2ibcH4UtFyw3goZYgsNCyFRlejaLcK6cE7K/At6tz9bnm07\n 0yfMCQeeIPZWc6nb26Aj7upms4uYMf1Zoc2l1G2V0BRfr6dxEv5ioq1LPNaOVRz5ydnN\n kkqOQxo/5gQD4xnUVlGlqMSY7XH4KNHEgZWDE03BB65WAoYyJIoilDKpAX4aljUuY2lW\n cPcW2aqTkVRJLuCkQiXnOaHK2Xm0qy11FT+561Qtoa3YL5pMiPRvwEOs+aiVPmkgzmRE\n C6wzf6LZJerPba1U71J2yFs5mrJxP6NwoMd8IuiLdH+VwnHk+BD8BlzgHy4Zb0DyskrI\n TmYA==","X-Forwarded-Encrypted":"i=1;\n AJvYcCWIsLSzTB4fpJrjZaAlq/BgqIq0CzmuMEPfxK6X0n/VsJ4OUVuNdALH1MeBOcyOv/D90CDzEQs=@lists.denx.de","X-Gm-Message-State":"AOJu0YyAESBYQrrPN1ZTNTBHzPCPtBKXIE20GzQjVZQ4yZpJ3Yrji/BA\n zviKA/vHtGFbbS4Yp1YiGZWm8b+vQj+tx09DfBaBtq8E3JnD/uQpkwPU","X-Gm-Gg":"AZuq6aJ1l5bGjzL5NTJW9smGU1PU3jx6Llm4PcqsXyvT9+2SJxvJ7MWjVENjwhBR0Aa\n AQvld7BvCg7mgKoA/vwNhoneX9NWUyk/gdjYsnn1Wniwx273h+aKGbnFrNnCP1YiLfsZV4jDzz5\n XYj9ckQrFN8AY4s/f0JrXuiNN5/ljuzqJRgW4CtaTf0m8/hFmL4RWNxTTrcN8eLrIR6a/epe4uk\n /qziv3Mw31Op0CMpZaf9+xjz3HSy2h0zwqH6gvcTgBypFGxt2qB4Jzt0liXOo78Ab1nSoxCjMzv\n 5lNzVr4amwMoK5YwL80Qn+vqNS6Xh1m1XUSagEblHrcFg4cihJpqhPqHFLLww0t+wHZApkzCtb5\n oJ7QufchkeXU14V2ubW9WxOEmTumakpdjHB7VVUggtjKcp/N5uazXuErYoB52MQLhK6NBuWR6Z0\n X2az7CUXoE9YpjBwNg5goId1lKhVPEwKJpPk9A8Epk+gfMLWwj2I0TkhOKs02N3YbStq8=","X-Received":"by 2002:a05:6214:4f05:b0:897:1d50:2336 with SMTP id\n 6a1803df08f44-897347ccd64mr31787026d6.6.1770996874726;\n Fri, 13 Feb 2026 07:34:34 -0800 (PST)","Message-ID":"<3fe5e11d-7240-c577-64fc-062d5c5e4d6a@gmail.com>","Date":"Fri, 13 Feb 2026 10:34:33 -0500","MIME-Version":"1.0","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101\n Thunderbird/91.11.0","Subject":"Re: [PATCH v2 2/6] misc: Add support for bit fields in NVMEM cells","Content-Language":"en-US","To":"Aswin Murugan <aswin.murugan@oss.qualcomm.com>, u-boot@lists.denx.de,\n sumit.garg@kernel.org, casey.connolly@linaro.org, u-boot-qcom@groups.io","Cc":"trini@konsulko.com, marek.vasut+renesas@mailbox.org,\n neil.armstrong@linaro.org, peng.fan@nxp.com, quentin.schulz@cherry.de,\n n-francis@ti.com, xypron.glpk@gmx.de, h-vm@ti.com, justin@tidylabs.net,\n jamie.gibbons@microchip.com, ycliang@andestech.com, me@samcday.com,\n sughosh.ganu@arm.com, gchan9527@gmail.com, ilias.apalodimas@linaro.org","References":"<20260213112717.1256823-1-aswin.murugan@oss.qualcomm.com>\n <20260213112717.1256823-3-aswin.murugan@oss.qualcomm.com>","From":"Sean Anderson <seanga2@gmail.com>","In-Reply-To":"<20260213112717.1256823-3-aswin.murugan@oss.qualcomm.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","X-BeenThere":"u-boot@lists.denx.de","X-Mailman-Version":"2.1.39","Precedence":"list","List-Id":"U-Boot discussion <u-boot.lists.denx.de>","List-Unsubscribe":"<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>","List-Archive":"<https://lists.denx.de/pipermail/u-boot/>","List-Post":"<mailto:u-boot@lists.denx.de>","List-Help":"<mailto:u-boot-request@lists.denx.de?subject=help>","List-Subscribe":"<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>","Errors-To":"u-boot-bounces@lists.denx.de","Sender":"\"U-Boot\" <u-boot-bounces@lists.denx.de>","X-Virus-Scanned":"clamav-milter 0.103.8 at phobos.denx.de","X-Virus-Status":"Clean"}},{"id":3651240,"web_url":"http://patchwork.ozlabs.org/comment/3651240/","msgid":"<497f7e07-3a5c-4a7a-b2bb-9016d6927ba4@oss.qualcomm.com>","list_archive_url":null,"date":"2026-02-17T19:05:35","subject":"Re: [PATCH v2 2/6] misc: Add support for bit fields in NVMEM cells","submitter":{"id":90811,"url":"http://patchwork.ozlabs.org/api/people/90811/","name":"Aswin Murugan","email":"aswin.murugan@oss.qualcomm.com"},"content":"Hi Sean,\n\nThanks for your feedback.\n\nTo address stack smashing, which occurs when the cell size is larger \nthan 4 bytes, I will revert the `nvmem_cell_read()` call in \n`reboot_mode_get()` to pass `sizeof(*mode)` as the size, consistent with \nthe original implementation.\n\nInside `nvmem_cell_read()`, will modify the validation check. Instead of \nenforcing `size == cell->size`, will check if `cell->size` is within the \npassed `size` (i.e., `cell->size <= size`) to correctly support our \n1-byte read case where the buffer is 4 bytes.\nAlso, i2c_eeprom_read() and misc_read() will continue to request a read \nfor cell->size instead of the passed buffer size, ensuring we only read \nthe valid data from the hardware.\n\nRegarding the bit field logic, as you suggested will simplify the \nbit‑field handling to max u32 size, which significantly reduces the code \ncomplexity. Given this simplification, is it still necessary to keep \nthis bit‑manipulation logic behind a separate config option?\n\nKindly confirm if this approach aligns with your expectations.\n\n\nThanks,\nAswin\n\n\nOn 2/13/2026 9:04 PM, Sean Anderson wrote:\n> On 2/13/26 06:27, Aswin Murugan wrote:\n>> NVMEM cells currently only support byte-level access. Many hardware\n>> registers pack multiple fields into single bytes, requiring bit-level\n>> granularity. For example, Qualcomm PMIC PON registers store a 7-bit\n>> reboot reason field within a single byte, with bit 0 reserved for other\n>> purposes.\n>>\n>> Add support for the optional 'bits' property in NVMEM cell device tree\n>> bindings. This property specifies <bit_offset num_bits> to define a bit\n>> field within the cell's register space.\n>>\n>> Implement multi-byte bit field support by porting bit manipulation\n>> algorithms from the Linux kernel driver [1]:\n>>\n>> 1. nvmem_shift_read_buffer_in_place() - Extract bit fields from raw\n>>     bytes by shifting and masking across byte boundaries. Handles fields\n>>     that span multiple bytes.\n>>\n>> 2. nvmem_cell_prepare_write_buffer() - Perform Read-Modify-Write to\n>>     preserve bits outside the target field. Read current values, mask to\n>>     preserve adjacent bits, and combine with new value.\n>>\n>> Example device tree usage:\n>>          reboot-reason@48 {\n>>                  reg = <0x48 0x01>;\n>>                  bits = <0x01 0x07>;  /* 7 bits starting at bit 1 */\n>>          };\n>>\n>> This reads bits [7:1] from the byte at offset 0x48, leaving bit 0\n>> untouched during write operations.\n>>\n>> Cells without the 'bits' property continue to work unchanged, ensuring\n>> backward compatibility with existing device trees.\n>>\n>> [1] \n>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/nvmem/core.c\n>>\n>> Signed-off-by: Aswin Murugan <aswin.murugan@oss.qualcomm.com>\n>\n> This seems like it adds a lot of calculations; have you looked at the \n> size\n> increase? Maybe this should be a separate config, since the feature \n> does not\n> seem too common.\n>\n> Actually, I think we could reduce the complexity quite a bit by refusing\n> to process bits longer than a ulong. A quick grep through Linux's dts \n> shows\n> that the largest bits is <6 12>. I don't really see any reason we need to\n> support arbitrary bit extraction.\n>\n> There should also be a test for this. The existing code is lightly \n> tested by\n> checking that mac addresses are loaded correctly. Maybe you can extend\n> test/dm/reboot-mode.c.\n>\n>> ---\n>>   drivers/misc/nvmem.c | 241 ++++++++++++++++++++++++++++++++++++++++---\n>>   include/nvmem.h      |   4 +\n>>   2 files changed, 231 insertions(+), 14 deletions(-)\n>>\n>> diff --git a/drivers/misc/nvmem.c b/drivers/misc/nvmem.c\n>> index 33e80858565..6a75c326189 100644\n>> --- a/drivers/misc/nvmem.c\n>> +++ b/drivers/misc/nvmem.c\n>> @@ -12,52 +12,251 @@\n>>   #include <dm/ofnode.h>\n>>   #include <dm/read.h>\n>>   #include <dm/uclass.h>\n>> +#include <linux/bitops.h>\n>> +#include <linux/kernel.h>\n>> +\n>> +/**\n>> + * nvmem_shift_read_buffer_in_place() - Shift read buffer to extract \n>> bit field\n>> + * @cell: NVMEM cell with bit field information\n>> + * @buf: Buffer containing raw bytes read from NVMEM\n>> + *\n>> + * This function shifts and masks the buffer to extract only the \n>> bits specified\n>> + * by cell->bit_offset and cell->nbits. It handles bit fields that \n>> span multiple\n>> + * bytes by shifting bits across byte boundaries.\n>> + *\n>> + */\n>> +static void nvmem_shift_read_buffer_in_place(struct nvmem_cell \n>> *cell, void *buf)\n>> +{\n>> +    u8 *prev_byte, *buf_ptr;\n>> +    int i, extra, bit_offset = cell->bit_offset;\n>> +    int bytes_needed;\n>> +\n>> +    bytes_needed = DIV_ROUND_UP(cell->nbits + cell->bit_offset, \n>> BITS_PER_BYTE);\n>> +\n>> +    prev_byte = buf_ptr = buf;\n>> +    if (bit_offset) {\n>> +        /* First byte: shift right by bit_offset */\n>> +        *buf_ptr++ >>= bit_offset;\n>> +\n>> +        /* Process remaining bytes, combining bits across boundaries */\n>> +        for (i = 1; i < bytes_needed; i++) {\n>> +            /* Get bits from next byte and shift them towards MSB */\n>> +            *prev_byte |= *buf_ptr << (BITS_PER_BYTE - bit_offset);\n>> +\n>> +            prev_byte = buf_ptr;\n>> +            *buf_ptr++ >>= bit_offset;\n>> +        }\n>> +    } else {\n>> +        /* Point to the MSB */\n>> +        prev_byte += bytes_needed - 1;\n>> +    }\n>> +\n>> +    /* Clear extra bytes if result fits in fewer bytes */\n>> +    extra = bytes_needed - DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE);\n>> +    while (--extra >= 0)\n>> +        *prev_byte-- = 0;\n>> +\n>> +    /* Clear MSB bits if any leftover in the last byte */\n>> +    if (cell->nbits % BITS_PER_BYTE)\n>> +        *prev_byte &= GENMASK((cell->nbits % BITS_PER_BYTE) - 1, 0);\n>> +}\n>> +\n>> +/**\n>> + * nvmem_cell_prepare_write_buffer() - Prepare buffer for writing \n>> bit field\n>> + * @cell: NVMEM cell with bit field information\n>> + * @buf: Buffer containing value to write\n>> + * @size: Size of buf\n>> + * @data: Output buffer with prepared data for writing\n>> + *\n>> + * This function performs Read-Modify-Write to preserve bits outside \n>> the\n>> + * specified bit field. It reads current values, modifies only the \n>> target\n>> + * bits, and prepares the complete bytes for writing back.\n>> + *\n>> + * Return: 0 on success, negative error code on failure\n>> + */\n>> +static int nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,\n>> +                       const void *buf, size_t size,\n>> +                       u8 *data)\n>> +{\n>> +    int i, rc, nbits, bit_offset = cell->bit_offset;\n>> +    int bytes_needed;\n>> +    u8 current_val, *prev_byte, *buf_ptr, prev_byte_val, prev_bits;\n>> +\n>> +    nbits = cell->nbits;\n>> +    bytes_needed = DIV_ROUND_UP(nbits + bit_offset, BITS_PER_BYTE);\n>> +\n>> +    memcpy(data, buf, size);\n>> +    prev_byte = buf_ptr = data;\n>> +\n>> +    if (bit_offset) {\n>> +        prev_byte_val = *buf_ptr;\n>> +        *buf_ptr <<= bit_offset;\n>> +\n>> +        /* Setup the first byte with LSB bits from NVMEM */\n>> +        switch (cell->nvmem->driver->id) {\n>> +        case UCLASS_I2C_EEPROM:\n>> +            rc = i2c_eeprom_read(cell->nvmem, cell->offset, \n>> &current_val, 1);\n>> +            break;\n>> +        case UCLASS_MISC:\n>> +            rc = misc_read(cell->nvmem, cell->offset, &current_val, 1);\n>> +            if (rc < 0)\n>> +                return rc;\n>> +            if (rc != 1)\n>> +                return -EIO;\n>> +            rc = 0;\n>> +            break;\n>> +        case UCLASS_RTC:\n>> +            rc = dm_rtc_read(cell->nvmem, cell->offset, \n>> &current_val, 1);\n>> +            break;\n>> +        default:\n>> +            return -ENOSYS;\n>> +        }\n>\n> Can you use nvmem_cell_read for this to reduce duplication?\n>\n>> +\n>> +        if (rc)\n>> +            return rc;\n>> +\n>> +        *buf_ptr++ |= GENMASK(bit_offset - 1, 0) & current_val;\n>> +\n>> +        /* Setup rest of the bytes if any */\n>> +        for (i = 1; i < bytes_needed; i++) {\n>> +            /* Get last byte bits and shift them towards LSB */\n>> +            prev_bits = prev_byte_val >> (BITS_PER_BYTE - 1 - \n>> bit_offset);\n>> +            prev_byte_val = *buf_ptr;\n>> +            prev_byte = buf_ptr;\n>> +            *buf_ptr <<= bit_offset;\n>> +            *buf_ptr++ |= prev_bits;\n>> +        }\n>> +    }\n>> +\n>> +    /* If it's not end on byte boundary */\n>> +    if ((nbits + bit_offset) % BITS_PER_BYTE) {\n>> +        /* Setup the last byte with MSB bits from NVMEM */\n>> +        switch (cell->nvmem->driver->id) {\n>> +        case UCLASS_I2C_EEPROM:\n>> +            rc = i2c_eeprom_read(cell->nvmem,\n>> +                         cell->offset + bytes_needed - 1,\n>> +                         &current_val, 1);\n>> +            break;\n>> +        case UCLASS_MISC:\n>> +            rc = misc_read(cell->nvmem,\n>> +                       cell->offset + bytes_needed - 1,\n>> +                       &current_val, 1);\n>> +            if (rc < 0)\n>> +                return rc;\n>> +            if (rc != 1)\n>> +                return -EIO;\n>> +            rc = 0;\n>> +            break;\n>> +        case UCLASS_RTC:\n>> +            rc = dm_rtc_read(cell->nvmem,\n>> +                     cell->offset + bytes_needed - 1,\n>> +                     &current_val, 1);\n>> +            break;\n>> +        default:\n>> +            return -ENOSYS;\n>> +        }\n>> +\n>> +        if (rc)\n>> +            return rc;\n>> +\n>> +        *prev_byte |= GENMASK(7, (nbits + bit_offset) % \n>> BITS_PER_BYTE) & current_val;\n>> +    }\n>> +\n>> +    return 0;\n>> +}\n>>     int nvmem_cell_read(struct nvmem_cell *cell, void *buf, size_t size)\n>>   {\n>> +    u8 data[size];\n>\n> No alloca.\n>\n>> +    int bytes_needed;\n>> +    int ret;\n>> +\n>>       dev_dbg(cell->nvmem, \"%s: off=%u size=%zu\\n\", __func__, \n>> cell->offset, size);\n>\n> Please update these.\n>\n>> +\n>>       if (size != cell->size)\n>>           return -EINVAL;\n>>   +    /* Calculate how many bytes we need to read */\n>> +    if (cell->nbits > 0) {\n>\n> just if (cell->nbits) for clarity please\n>\n> (ditto for elsewhere)\n>\n>> +        bytes_needed = DIV_ROUND_UP(cell->nbits + cell->bit_offset, \n>> BITS_PER_BYTE);\n>> +        if (bytes_needed > sizeof(data))\n>> +            return -EINVAL;\n>> +    } else {\n>> +        bytes_needed = size;\n>\n> This should always be true even when nbits != 0, as bits specifies the \n> offset/size\n> \"within the address range specified by reg.\" This will allow you to \n> use the original buffer.\n>\n>> +    }\n>> +\n>>       switch (cell->nvmem->driver->id) {\n>>       case UCLASS_I2C_EEPROM:\n>> -        return i2c_eeprom_read(cell->nvmem, cell->offset, buf, size);\n>> -    case UCLASS_MISC: {\n>> -        int ret = misc_read(cell->nvmem, cell->offset, buf, size);\n>> -\n>> +        ret = i2c_eeprom_read(cell->nvmem, cell->offset, data, \n>> bytes_needed);\n>> +        break;\n>> +    case UCLASS_MISC:\n>> +        ret = misc_read(cell->nvmem, cell->offset, data, bytes_needed);\n>>           if (ret < 0)\n>>               return ret;\n>> -        if (ret != size)\n>> +        if (ret != bytes_needed)\n>>               return -EIO;\n>> -        return 0;\n>> -    }\n>> +        ret = 0;\n>> +        break;\n>>       case UCLASS_RTC:\n>> -        return dm_rtc_read(cell->nvmem, cell->offset, buf, size);\n>> +        ret = dm_rtc_read(cell->nvmem, cell->offset, data, \n>> bytes_needed);\n>> +        break;\n>>       default:\n>>           return -ENOSYS;\n>>       }\n>> +\n>> +    if (ret)\n>> +        return ret;\n>> +\n>> +    if (cell->nbits > 0) {\n>> +        /* Extract bit field from raw bytes */\n>> +        nvmem_shift_read_buffer_in_place(cell, data);\n>> +        /* Copy only the bytes containing the bit field result */\n>> +        memcpy(buf, data, DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE));\n>> +    } else {\n>> +        memcpy(buf, data, size);\n>> +    }\n>> +\n>> +    return 0;\n>>   }\n>>     int nvmem_cell_write(struct nvmem_cell *cell, const void *buf, \n>> size_t size)\n>>   {\n>> +    u8 data[size];\n>\n> Again, no alloca. Limit the size for cells with bits and you can use a \n> static\n> allocation on the stack.\n>\n>> +    int bytes_needed;\n>> +    int ret;\n>> +\n>>       dev_dbg(cell->nvmem, \"%s: off=%u size=%zu\\n\", __func__, \n>> cell->offset, size);\n>> +\n>>       if (size != cell->size)\n>>           return -EINVAL;\n>>   +    if (cell->nbits > 0) {\n>> +        bytes_needed = DIV_ROUND_UP(cell->nbits + cell->bit_offset, \n>> BITS_PER_BYTE);\n>> +        if (bytes_needed > sizeof(data))\n>> +            return -EINVAL;\n>> +\n>> +        /* Prepare write buffer with Read-Modify-Write */\n>> +        ret = nvmem_cell_prepare_write_buffer(cell, buf, size, data);\n>> +        if (ret)\n>> +            return ret;\n>> +    } else {\n>> +        bytes_needed = size;\n>> +        memcpy(data, buf, size);\n>> +    }\n>> +\n>>       switch (cell->nvmem->driver->id) {\n>>       case UCLASS_I2C_EEPROM:\n>> -        return i2c_eeprom_write(cell->nvmem, cell->offset, buf, size);\n>> +        return i2c_eeprom_write(cell->nvmem, cell->offset, data, \n>> bytes_needed);\n>>       case UCLASS_MISC: {\n>> -        int ret = misc_write(cell->nvmem, cell->offset, buf, size);\n>> -\n>> +        ret = misc_write(cell->nvmem, cell->offset, data, \n>> bytes_needed);\n>>           if (ret < 0)\n>>               return ret;\n>> -        if (ret != size)\n>> +        if (ret != bytes_needed)\n>>               return -EIO;\n>>           return 0;\n>>       }\n>>       case UCLASS_RTC:\n>> -        return dm_rtc_write(cell->nvmem, cell->offset, buf, size);\n>> +        return dm_rtc_write(cell->nvmem, cell->offset, data, \n>> bytes_needed);\n>>       default:\n>>           return -ENOSYS;\n>>       }\n>> @@ -121,13 +320,27 @@ int nvmem_cell_get_by_index(struct udevice \n>> *dev, int index,\n>>         offset = ofnode_get_addr_size_index_notrans(args.node, 0, \n>> &size);\n>>       if (offset == FDT_ADDR_T_NONE || size == FDT_SIZE_T_NONE) {\n>> -        dev_dbg(cell->nvmem, \"missing address or size for %s\\n\",\n>> +        dev_err(cell->nvmem, \"missing address or size for %s\\n\",\n>>               ofnode_get_name(args.node));\n>>           return -EINVAL;\n>>       }\n>>         cell->offset = offset;\n>>       cell->size = size;\n>> +\n>> +    ret = ofnode_read_u32_index(args.node, \"bits\", 0, \n>> &cell->bit_offset);\n>> +    if (ret) {\n>> +        cell->bit_offset = 0;\n>> +        cell->nbits = 0;\n>> +    } else {\n>> +        ret = ofnode_read_u32_index(args.node, \"bits\", 1, \n>> &cell->nbits);\n>> +        if (ret)\n>> +            return -EINVAL;\n>> +\n>> +        if (cell->bit_offset + cell->nbits > cell->size * 8)\n>> +            return -EINVAL;\n>> +    }\n>> +\n>>       return 0;\n>>   }\n>>   diff --git a/include/nvmem.h b/include/nvmem.h\n>> index e6a8a98828b..dd82122f16f 100644\n>> --- a/include/nvmem.h\n>> +++ b/include/nvmem.h\n>> @@ -26,11 +26,15 @@\n>>    * @nvmem: The backing storage device\n>>    * @offset: The offset of the cell from the start of @nvmem\n>>    * @size: The size of the cell, in bytes\n>> + * @bit_offset: Bit offset within the cell (0 for byte-level access)\n>> + * @nbits: Number of bits to use (0 for byte-level access)\n>>    */\n>>   struct nvmem_cell {\n>>       struct udevice *nvmem;\n>>       unsigned int offset;\n>>       size_t size;\n>> +    unsigned int bit_offset;\n>> +    unsigned int nbits;\n>>   };\n>\n> Please also update the documentation for read/write.\n>\n>>   struct udevice;\n>","headers":{"Return-Path":"<u-boot-bounces@lists.denx.de>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.a=rsa-sha256\n header.s=qcppdkim1 header.b=RaU5TvrK;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com\n header.a=rsa-sha256 header.s=google header.b=fB1gaF+z;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)","phobos.denx.de;\n dmarc=none (p=none dis=none) header.from=oss.qualcomm.com","phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de","phobos.denx.de;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=qualcomm.com header.i=@qualcomm.com\n header.b=\"RaU5TvrK\";\n\tdkim=pass (2048-bit key;\n unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com\n header.b=\"fB1gaF+z\";\n\tdkim-atps=neutral","phobos.denx.de; dmarc=none (p=none dis=none)\n header.from=oss.qualcomm.com","phobos.denx.de;\n spf=pass smtp.mailfrom=aswin.murugan@oss.qualcomm.com"],"Received":["from phobos.denx.de (phobos.denx.de\n [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fFpyD285Kz1xpl\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 18 Feb 2026 06:05:56 +1100 (AEDT)","from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id BF6F483C32;\n\tTue, 17 Feb 2026 20:05:52 +0100 (CET)","by phobos.denx.de (Postfix, from userid 109)\n id 7846483981; Tue, 17 Feb 2026 20:05:51 +0100 (CET)","from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com\n [205.220.180.131])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id 8231083B99\n for <u-boot@lists.denx.de>; Tue, 17 Feb 2026 20:05:48 +0100 (CET)","from pps.filterd (m0279873.ppops.net [127.0.0.1])\n by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id\n 61HFU9tQ2319712\n for <u-boot@lists.denx.de>; Tue, 17 Feb 2026 19:05:47 GMT","from mail-pl1-f199.google.com (mail-pl1-f199.google.com\n [209.85.214.199])\n by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ccu1erqbv-1\n (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT)\n for <u-boot@lists.denx.de>; Tue, 17 Feb 2026 19:05:46 +0000 (GMT)","by mail-pl1-f199.google.com with SMTP id\n d9443c01a7336-2a7701b6353so60857155ad.3\n for <u-boot@lists.denx.de>; Tue, 17 Feb 2026 11:05:46 -0800 (PST)","from [192.168.1.10] ([223.178.81.193])\n by smtp.gmail.com with ESMTPSA id\n 98e67ed59e1d1-3567ebc34c4sm21083758a91.13.2026.02.17.11.05.37\n (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n Tue, 17 Feb 2026 11:05:44 -0800 (PST)"],"X-Spam-Checker-Version":"SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de","X-Spam-Level":"","X-Spam-Status":"No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,\n DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED,\n RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED,\n SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2","DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h=\n cc:content-transfer-encoding:content-type:date:from:in-reply-to\n :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=\n poIAiFI+EMcc4x3/jLfN996Ap1dpXOkq23nelXsdcnU=; b=RaU5TvrKe4P6+JsP\n +OXFJmPrqFeVao+8uLJCVTxFjkojE3dlV3HRIaqDRPQxLISGnQEhIX3b+TtdeAoZ\n UpBop4QVKBB2ZPBCZNI3FnbOQvytVpPeZhbNSnkY3grNXXmNPP9SNNVBvyvbMdpr\n dSOt2XjlylkWBKwz9sxQaLEEC8OfVDlnZnznErYPE+wwG8OE0tBWPLkMTIH+3xjK\n JIVzjbwFd5ppae8Py6be0j2ePY6VCJEtEV9nrh3jrlaLpYYgdVfsRk/PtChSC3WK\n qjbMlwZ67dWojeZ4I5SeAr01I9rJrX3WHlZKunh0jk2PtyuXg6hnJCgpzgUGOMNg\n OaYctg==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=oss.qualcomm.com; s=google; t=1771355146; x=1771959946; darn=lists.denx.de;\n h=content-transfer-encoding:in-reply-to:from:content-language\n :references:cc:to:subject:user-agent:mime-version:date:message-id\n :from:to:cc:subject:date:message-id:reply-to;\n bh=poIAiFI+EMcc4x3/jLfN996Ap1dpXOkq23nelXsdcnU=;\n b=fB1gaF+zYqcDuMi3TBGtwXlc6p1O34r41kfAhfP5gTkNQvLmGSatluXpM7+rrNjsJA\n qbT2TkBLBYuzs0BOEDL48DAQS23Jt0RfNKYdTBWNkeMuDcYwaPci6lghq9RSrwP+fmuj\n yMgSPr/We5fdnXVBIPEXikdyoy2dEI+mkdC0galknk49d6rHmvNcwpw/VG4kkmRHRfTe\n GHE//PMQpZ+vcOVhwVsgKnbkz3s9xS62PYmI9Bj3p552KnoZIAj5ySkcVXtlGL6+kvnv\n pV8Hq009/1g5I8OO1lqn4rgfEF+/rAYwwXv6c2TTfdB0t3TZnqbf5twVqV4Ru0n801YY\n oRUw=="],"X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1771355146; x=1771959946;\n h=content-transfer-encoding:in-reply-to:from:content-language\n :references:cc:to:subject:user-agent:mime-version:date:message-id\n :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id\n :reply-to;\n bh=poIAiFI+EMcc4x3/jLfN996Ap1dpXOkq23nelXsdcnU=;\n b=n8vEeOw4338+KW6LTzeqrllw+s3jT+TSQK+nmUxaKeMTluDp4f4/Tw9TWp3RAG12Yb\n bWKIo1llY/c99l/McACKUeaY1NeLrhsEqBB4tZV5og8mKnhgmsG0Ixsqfk+O+AYTkio6\n PC54iyREV4HgKoHzi1OYNDMriDBpWXf+KsvMrn1A6ecIeYoNj23g+Rie6XxK2PBOkCaQ\n dcd9CIe7wFfEQp80UHXuZb+JFnBU0Xl3JviWEqAqkffQ0eCDK1VnfBg62WlYtta7jppP\n bmxDvnOSJABT6EDfRCpY+qu7WPyK49QEkBWULHjWgWt5ftAfZwzVRx05Qc7zEYzFJ+kr\n H4GQ==","X-Forwarded-Encrypted":"i=1;\n AJvYcCVmfFe8eLkx2/UQp0nm+8EijwN79ZvgPICGPLojSpj+K58FmZi6jw6cNCJKLEnW+kEcNwRmxrs=@lists.denx.de","X-Gm-Message-State":"AOJu0YzZlcUIDYdvNr9qAO9VDdAxjwLBpll6OAN9awHyacJw3NfssNx9\n upfFFykLj04G+ZxR8YlCELRvY/Y/kjmwCi8c+hi2ntPMwHAtK0PtmwKR/Z8e6ZB3PjHHPgV79bg\n +Yid5zL9mpQBJzVUO1qPCzEwbjcZf9/G7cCsmkoyQoPqX7F5WD8UdQmQW","X-Gm-Gg":"AZuq6aLKbT48NxswxPNFxRtIz5jfjjgoMsMit7/UecNJoHDLc9vmX7O/D6z5oQ5+Jk5\n 7gQLN8BLOKUduSjceobK5wd/YyEQyTwhHKBpeGZIjcxPMBxpnfSFr+pSF9XRqgLmhSiwhR6imQb\n rfu7TaZhrtWArsyThmdxMsAgKZIIdb2WX4aZnwaEmCELeTONP+8R0YyEwx3DUBDEGvtCLUAcds3\n ZpIeHTCzTIQMSAPRJcff48AnYQBVE7baCols5Ir8ZnAcRbSbSHIZPHQyfvPyi9+DAuwU0BCWL7g\n 0qjnFZztP5Gi+BgtB/0crXpyCpakiZgXHiq+yv0EEKNO25W2audfSDRtNGO+vuC75/1v8M1lhcC\n HpMvuCTnV3tp6DxsJDelOqKSkHrXzc6/d+qTTKZ1hW8B7NPmdlnU+aA==","X-Received":["by 2002:a17:90b:4b83:b0:356:8719:f5b8 with SMTP id\n 98e67ed59e1d1-35844fc0929mr11072237a91.29.1771355145249;\n Tue, 17 Feb 2026 11:05:45 -0800 (PST)","by 2002:a17:90b:4b83:b0:356:8719:f5b8 with SMTP id\n 98e67ed59e1d1-35844fc0929mr11072203a91.29.1771355144682;\n Tue, 17 Feb 2026 11:05:44 -0800 (PST)"],"Message-ID":"<497f7e07-3a5c-4a7a-b2bb-9016d6927ba4@oss.qualcomm.com>","Date":"Wed, 18 Feb 2026 00:35:35 +0530","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v2 2/6] misc: Add support for bit fields in NVMEM cells","To":"Sean Anderson <seanga2@gmail.com>","Cc":"trini@konsulko.com, marek.vasut+renesas@mailbox.org,\n neil.armstrong@linaro.org, peng.fan@nxp.com, quentin.schulz@cherry.de,\n n-francis@ti.com, xypron.glpk@gmx.de, h-vm@ti.com, justin@tidylabs.net,\n jamie.gibbons@microchip.com, ycliang@andestech.com, me@samcday.com,\n sughosh.ganu@arm.com, gchan9527@gmail.com, ilias.apalodimas@linaro.org,\n u-boot-qcom@groups.io, u-boot@lists.denx.de, sumit.garg@kernel.org,\n casey.connolly@linaro.org","References":"<20260213112717.1256823-1-aswin.murugan@oss.qualcomm.com>\n <20260213112717.1256823-3-aswin.murugan@oss.qualcomm.com>\n <3fe5e11d-7240-c577-64fc-062d5c5e4d6a@gmail.com>","Content-Language":"en-US","From":"Aswin Murugan <aswin.murugan@oss.qualcomm.com>","In-Reply-To":"<3fe5e11d-7240-c577-64fc-062d5c5e4d6a@gmail.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-Authority-Analysis":"v=2.4 cv=LfsxKzfi c=1 sm=1 tr=0 ts=6994bc0a cx=c_pps\n a=JL+w9abYAAE89/QcEU+0QA==:117 a=8sQKdzLGWpe9X/dURiXpGA==:17\n a=IkcTkHD0fZMA:10 a=HzLeVaNsDn8A:10 a=s4-Qcg_JpJYA:10\n a=VkNPw1HP01LnGYTKEx00:22 a=Mpw57Om8IfrbqaoTuvik:22 a=GgsMoib0sEa3-_RKJdDe:22\n a=VwQbUJbxAAAA:8 a=EUspDBNiAAAA:8 a=iRf3lNkDPbpjM-yYXwwA:9 a=3ZKOabzyN94A:10\n a=QEXdDO2ut3YA:10 a=324X-CrmTo6CU4MGRt3R:22","X-Proofpoint-GUID":"9ljf8u6Y7N1h7rbHDWeKzOMSp6ZqsUyK","X-Proofpoint-Spam-Details-Enc":"AW1haW4tMjYwMjE3MDE1NiBTYWx0ZWRfXwcSJa5V8sftR\n 7dkTDAMLBu+Q4z4a3JtDDFbHlotfPzDkmGHlpouLdVFtmrvomDUjNf0p/IFOCPBI5zlnf4ledET\n VQ7BAzE4P16SKcB/atm21avmxPLRwCliWqe4E9DbF6iQxet5OqM0T1ATJxCorkMvR+axcdEq0oI\n Ns8QfmbfdNh/mJ9siDHSCWZXw2JwO3J7Iri3NvKh8oeaPFbR6jkykjCTS5Y1GKufCU/9QmCaz7x\n Eaq0iNlnD4Z3PdLOCYjSwc/ozaZ9gssVrsQgp1dGFCgu39kx6QkkEOaA5gsXRaZOki7ew33zsY4\n cCYl/ZxhCYUaOmodSvpxZgoFW8R30jNsPtRF2HeV2Fz6RDHYaLPZTbRWoEwMi7v7A3fAKuH2O29\n CZhj8xumdnpr+yOE/o0k5+FLjTJ72tqIuuQag67wAyPmQWwtt9jc62cew2EuAB+5444O9tD71cZ\n F0NV4202whbxo3fpoRA==","X-Proofpoint-ORIG-GUID":"9ljf8u6Y7N1h7rbHDWeKzOMSp6ZqsUyK","X-Proofpoint-Virus-Version":"vendor=baseguard\n engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.51,FMLib:17.12.100.49\n definitions=2026-02-17_03,2026-02-16_04,2025-10-01_01","X-Proofpoint-Spam-Details":"rule=outbound_notspam policy=outbound score=0\n malwarescore=0 bulkscore=0 clxscore=1015 spamscore=0 suspectscore=0\n lowpriorityscore=0 priorityscore=1501 impostorscore=0 phishscore=0\n adultscore=0 classifier=typeunknown authscore=0 authtc= authcc=\n route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000\n definitions=main-2602170156","X-BeenThere":"u-boot@lists.denx.de","X-Mailman-Version":"2.1.39","Precedence":"list","List-Id":"U-Boot discussion <u-boot.lists.denx.de>","List-Unsubscribe":"<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>","List-Archive":"<https://lists.denx.de/pipermail/u-boot/>","List-Post":"<mailto:u-boot@lists.denx.de>","List-Help":"<mailto:u-boot-request@lists.denx.de?subject=help>","List-Subscribe":"<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>","Errors-To":"u-boot-bounces@lists.denx.de","Sender":"\"U-Boot\" <u-boot-bounces@lists.denx.de>","X-Virus-Scanned":"clamav-milter 0.103.8 at phobos.denx.de","X-Virus-Status":"Clean"}},{"id":3651347,"web_url":"http://patchwork.ozlabs.org/comment/3651347/","msgid":"<96a3a5e8-a853-b766-a013-d3db6bfce117@gmail.com>","list_archive_url":null,"date":"2026-02-18T02:07:50","subject":"Re: [PATCH v2 2/6] misc: Add support for bit fields in NVMEM cells","submitter":{"id":64621,"url":"http://patchwork.ozlabs.org/api/people/64621/","name":"Sean Anderson","email":"seanga2@gmail.com"},"content":"On 2/17/26 14:05, Aswin Murugan wrote:\n> Hi Sean,\n> \n> Thanks for your feedback.\n> To address stack smashing, which occurs when the cell size is larger than 4 bytes, I will revert the `nvmem_cell_read()` call in `reboot_mode_get()` to pass `sizeof(*mode)` as the size, consistent with the original implementation.\n> \n> Inside `nvmem_cell_read()`, will modify the validation check. Instead of enforcing `size == cell->size`, will check if `cell->size` is within the passed `size` (i.e., `cell->size <= size`) to correctly support our 1-byte read case where the buffer is 4 bytes.\n\nThen don't we need to zero out the rest of the buffer?\n\nI would expect the check to be\n\nif ((cell->bit_offset && size > cell->size) || size != cell->size)\n\treturn -EINVAL;\n\n> Also, i2c_eeprom_read() and misc_read() will continue to request a read for cell->size instead of the passed buffer size, ensuring we only read the valid data from the hardware.\n> \n> Regarding the bit field logic, as you suggested will simplify the bit‑field handling to max u32 size, which significantly reduces the code complexity. Given this simplification, is it still necessary to keep this bit‑manipulation logic behind a separate config option?\n\nI think it's likely. You can check the growth with scripts/bloat-o-meter in\nLinux. Since this is mainly for U-Boot proper I'd say a couple hundred bytes\nis reasonable for this feature.\n\n> Kindly confirm if this approach aligns with your expectations.\n\nPlease remember to reply on the bottom :)\n\n--Sean\n\n> On 2/13/2026 9:04 PM, Sean Anderson wrote:\n>> On 2/13/26 06:27, Aswin Murugan wrote:\n>>> NVMEM cells currently only support byte-level access. Many hardware\n>>> registers pack multiple fields into single bytes, requiring bit-level\n>>> granularity. For example, Qualcomm PMIC PON registers store a 7-bit\n>>> reboot reason field within a single byte, with bit 0 reserved for other\n>>> purposes.\n>>>\n>>> Add support for the optional 'bits' property in NVMEM cell device tree\n>>> bindings. This property specifies <bit_offset num_bits> to define a bit\n>>> field within the cell's register space.\n>>>\n>>> Implement multi-byte bit field support by porting bit manipulation\n>>> algorithms from the Linux kernel driver [1]:\n>>>\n>>> 1. nvmem_shift_read_buffer_in_place() - Extract bit fields from raw\n>>>     bytes by shifting and masking across byte boundaries. Handles fields\n>>>     that span multiple bytes.\n>>>\n>>> 2. nvmem_cell_prepare_write_buffer() - Perform Read-Modify-Write to\n>>>     preserve bits outside the target field. Read current values, mask to\n>>>     preserve adjacent bits, and combine with new value.\n>>>\n>>> Example device tree usage:\n>>>          reboot-reason@48 {\n>>>                  reg = <0x48 0x01>;\n>>>                  bits = <0x01 0x07>;  /* 7 bits starting at bit 1 */\n>>>          };\n>>>\n>>> This reads bits [7:1] from the byte at offset 0x48, leaving bit 0\n>>> untouched during write operations.\n>>>\n>>> Cells without the 'bits' property continue to work unchanged, ensuring\n>>> backward compatibility with existing device trees.\n>>>\n>>> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/nvmem/core.c\n>>>\n>>> Signed-off-by: Aswin Murugan <aswin.murugan@oss.qualcomm.com>\n>>\n>> This seems like it adds a lot of calculations; have you looked at the size\n>> increase? Maybe this should be a separate config, since the feature does not\n>> seem too common.\n>>\n>> Actually, I think we could reduce the complexity quite a bit by refusing\n>> to process bits longer than a ulong. A quick grep through Linux's dts shows\n>> that the largest bits is <6 12>. I don't really see any reason we need to\n>> support arbitrary bit extraction.\n>>\n>> There should also be a test for this. The existing code is lightly tested by\n>> checking that mac addresses are loaded correctly. Maybe you can extend\n>> test/dm/reboot-mode.c.\n>>\n>>> ---\n>>>   drivers/misc/nvmem.c | 241 ++++++++++++++++++++++++++++++++++++++++---\n>>>   include/nvmem.h      |   4 +\n>>>   2 files changed, 231 insertions(+), 14 deletions(-)\n>>>\n>>> diff --git a/drivers/misc/nvmem.c b/drivers/misc/nvmem.c\n>>> index 33e80858565..6a75c326189 100644\n>>> --- a/drivers/misc/nvmem.c\n>>> +++ b/drivers/misc/nvmem.c\n>>> @@ -12,52 +12,251 @@\n>>>   #include <dm/ofnode.h>\n>>>   #include <dm/read.h>\n>>>   #include <dm/uclass.h>\n>>> +#include <linux/bitops.h>\n>>> +#include <linux/kernel.h>\n>>> +\n>>> +/**\n>>> + * nvmem_shift_read_buffer_in_place() - Shift read buffer to extract bit field\n>>> + * @cell: NVMEM cell with bit field information\n>>> + * @buf: Buffer containing raw bytes read from NVMEM\n>>> + *\n>>> + * This function shifts and masks the buffer to extract only the bits specified\n>>> + * by cell->bit_offset and cell->nbits. It handles bit fields that span multiple\n>>> + * bytes by shifting bits across byte boundaries.\n>>> + *\n>>> + */\n>>> +static void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf)\n>>> +{\n>>> +    u8 *prev_byte, *buf_ptr;\n>>> +    int i, extra, bit_offset = cell->bit_offset;\n>>> +    int bytes_needed;\n>>> +\n>>> +    bytes_needed = DIV_ROUND_UP(cell->nbits + cell->bit_offset, BITS_PER_BYTE);\n>>> +\n>>> +    prev_byte = buf_ptr = buf;\n>>> +    if (bit_offset) {\n>>> +        /* First byte: shift right by bit_offset */\n>>> +        *buf_ptr++ >>= bit_offset;\n>>> +\n>>> +        /* Process remaining bytes, combining bits across boundaries */\n>>> +        for (i = 1; i < bytes_needed; i++) {\n>>> +            /* Get bits from next byte and shift them towards MSB */\n>>> +            *prev_byte |= *buf_ptr << (BITS_PER_BYTE - bit_offset);\n>>> +\n>>> +            prev_byte = buf_ptr;\n>>> +            *buf_ptr++ >>= bit_offset;\n>>> +        }\n>>> +    } else {\n>>> +        /* Point to the MSB */\n>>> +        prev_byte += bytes_needed - 1;\n>>> +    }\n>>> +\n>>> +    /* Clear extra bytes if result fits in fewer bytes */\n>>> +    extra = bytes_needed - DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE);\n>>> +    while (--extra >= 0)\n>>> +        *prev_byte-- = 0;\n>>> +\n>>> +    /* Clear MSB bits if any leftover in the last byte */\n>>> +    if (cell->nbits % BITS_PER_BYTE)\n>>> +        *prev_byte &= GENMASK((cell->nbits % BITS_PER_BYTE) - 1, 0);\n>>> +}\n>>> +\n>>> +/**\n>>> + * nvmem_cell_prepare_write_buffer() - Prepare buffer for writing bit field\n>>> + * @cell: NVMEM cell with bit field information\n>>> + * @buf: Buffer containing value to write\n>>> + * @size: Size of buf\n>>> + * @data: Output buffer with prepared data for writing\n>>> + *\n>>> + * This function performs Read-Modify-Write to preserve bits outside the\n>>> + * specified bit field. It reads current values, modifies only the target\n>>> + * bits, and prepares the complete bytes for writing back.\n>>> + *\n>>> + * Return: 0 on success, negative error code on failure\n>>> + */\n>>> +static int nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,\n>>> +                       const void *buf, size_t size,\n>>> +                       u8 *data)\n>>> +{\n>>> +    int i, rc, nbits, bit_offset = cell->bit_offset;\n>>> +    int bytes_needed;\n>>> +    u8 current_val, *prev_byte, *buf_ptr, prev_byte_val, prev_bits;\n>>> +\n>>> +    nbits = cell->nbits;\n>>> +    bytes_needed = DIV_ROUND_UP(nbits + bit_offset, BITS_PER_BYTE);\n>>> +\n>>> +    memcpy(data, buf, size);\n>>> +    prev_byte = buf_ptr = data;\n>>> +\n>>> +    if (bit_offset) {\n>>> +        prev_byte_val = *buf_ptr;\n>>> +        *buf_ptr <<= bit_offset;\n>>> +\n>>> +        /* Setup the first byte with LSB bits from NVMEM */\n>>> +        switch (cell->nvmem->driver->id) {\n>>> +        case UCLASS_I2C_EEPROM:\n>>> +            rc = i2c_eeprom_read(cell->nvmem, cell->offset, &current_val, 1);\n>>> +            break;\n>>> +        case UCLASS_MISC:\n>>> +            rc = misc_read(cell->nvmem, cell->offset, &current_val, 1);\n>>> +            if (rc < 0)\n>>> +                return rc;\n>>> +            if (rc != 1)\n>>> +                return -EIO;\n>>> +            rc = 0;\n>>> +            break;\n>>> +        case UCLASS_RTC:\n>>> +            rc = dm_rtc_read(cell->nvmem, cell->offset, &current_val, 1);\n>>> +            break;\n>>> +        default:\n>>> +            return -ENOSYS;\n>>> +        }\n>>\n>> Can you use nvmem_cell_read for this to reduce duplication?\n>>\n>>> +\n>>> +        if (rc)\n>>> +            return rc;\n>>> +\n>>> +        *buf_ptr++ |= GENMASK(bit_offset - 1, 0) & current_val;\n>>> +\n>>> +        /* Setup rest of the bytes if any */\n>>> +        for (i = 1; i < bytes_needed; i++) {\n>>> +            /* Get last byte bits and shift them towards LSB */\n>>> +            prev_bits = prev_byte_val >> (BITS_PER_BYTE - 1 - bit_offset);\n>>> +            prev_byte_val = *buf_ptr;\n>>> +            prev_byte = buf_ptr;\n>>> +            *buf_ptr <<= bit_offset;\n>>> +            *buf_ptr++ |= prev_bits;\n>>> +        }\n>>> +    }\n>>> +\n>>> +    /* If it's not end on byte boundary */\n>>> +    if ((nbits + bit_offset) % BITS_PER_BYTE) {\n>>> +        /* Setup the last byte with MSB bits from NVMEM */\n>>> +        switch (cell->nvmem->driver->id) {\n>>> +        case UCLASS_I2C_EEPROM:\n>>> +            rc = i2c_eeprom_read(cell->nvmem,\n>>> +                         cell->offset + bytes_needed - 1,\n>>> +                         &current_val, 1);\n>>> +            break;\n>>> +        case UCLASS_MISC:\n>>> +            rc = misc_read(cell->nvmem,\n>>> +                       cell->offset + bytes_needed - 1,\n>>> +                       &current_val, 1);\n>>> +            if (rc < 0)\n>>> +                return rc;\n>>> +            if (rc != 1)\n>>> +                return -EIO;\n>>> +            rc = 0;\n>>> +            break;\n>>> +        case UCLASS_RTC:\n>>> +            rc = dm_rtc_read(cell->nvmem,\n>>> +                     cell->offset + bytes_needed - 1,\n>>> +                     &current_val, 1);\n>>> +            break;\n>>> +        default:\n>>> +            return -ENOSYS;\n>>> +        }\n>>> +\n>>> +        if (rc)\n>>> +            return rc;\n>>> +\n>>> +        *prev_byte |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & current_val;\n>>> +    }\n>>> +\n>>> +    return 0;\n>>> +}\n>>>     int nvmem_cell_read(struct nvmem_cell *cell, void *buf, size_t size)\n>>>   {\n>>> +    u8 data[size];\n>>\n>> No alloca.\n>>\n>>> +    int bytes_needed;\n>>> +    int ret;\n>>> +\n>>>       dev_dbg(cell->nvmem, \"%s: off=%u size=%zu\\n\", __func__, cell->offset, size);\n>>\n>> Please update these.\n>>\n>>> +\n>>>       if (size != cell->size)\n>>>           return -EINVAL;\n>>>   +    /* Calculate how many bytes we need to read */\n>>> +    if (cell->nbits > 0) {\n>>\n>> just if (cell->nbits) for clarity please\n>>\n>> (ditto for elsewhere)\n>>\n>>> +        bytes_needed = DIV_ROUND_UP(cell->nbits + cell->bit_offset, BITS_PER_BYTE);\n>>> +        if (bytes_needed > sizeof(data))\n>>> +            return -EINVAL;\n>>> +    } else {\n>>> +        bytes_needed = size;\n>>\n>> This should always be true even when nbits != 0, as bits specifies the offset/size\n>> \"within the address range specified by reg.\" This will allow you to use the original buffer.\n>>\n>>> +    }\n>>> +\n>>>       switch (cell->nvmem->driver->id) {\n>>>       case UCLASS_I2C_EEPROM:\n>>> -        return i2c_eeprom_read(cell->nvmem, cell->offset, buf, size);\n>>> -    case UCLASS_MISC: {\n>>> -        int ret = misc_read(cell->nvmem, cell->offset, buf, size);\n>>> -\n>>> +        ret = i2c_eeprom_read(cell->nvmem, cell->offset, data, bytes_needed);\n>>> +        break;\n>>> +    case UCLASS_MISC:\n>>> +        ret = misc_read(cell->nvmem, cell->offset, data, bytes_needed);\n>>>           if (ret < 0)\n>>>               return ret;\n>>> -        if (ret != size)\n>>> +        if (ret != bytes_needed)\n>>>               return -EIO;\n>>> -        return 0;\n>>> -    }\n>>> +        ret = 0;\n>>> +        break;\n>>>       case UCLASS_RTC:\n>>> -        return dm_rtc_read(cell->nvmem, cell->offset, buf, size);\n>>> +        ret = dm_rtc_read(cell->nvmem, cell->offset, data, bytes_needed);\n>>> +        break;\n>>>       default:\n>>>           return -ENOSYS;\n>>>       }\n>>> +\n>>> +    if (ret)\n>>> +        return ret;\n>>> +\n>>> +    if (cell->nbits > 0) {\n>>> +        /* Extract bit field from raw bytes */\n>>> +        nvmem_shift_read_buffer_in_place(cell, data);\n>>> +        /* Copy only the bytes containing the bit field result */\n>>> +        memcpy(buf, data, DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE));\n>>> +    } else {\n>>> +        memcpy(buf, data, size);\n>>> +    }\n>>> +\n>>> +    return 0;\n>>>   }\n>>>     int nvmem_cell_write(struct nvmem_cell *cell, const void *buf, size_t size)\n>>>   {\n>>> +    u8 data[size];\n>>\n>> Again, no alloca. Limit the size for cells with bits and you can use a static\n>> allocation on the stack.\n>>\n>>> +    int bytes_needed;\n>>> +    int ret;\n>>> +\n>>>       dev_dbg(cell->nvmem, \"%s: off=%u size=%zu\\n\", __func__, cell->offset, size);\n>>> +\n>>>       if (size != cell->size)\n>>>           return -EINVAL;\n>>>   +    if (cell->nbits > 0) {\n>>> +        bytes_needed = DIV_ROUND_UP(cell->nbits + cell->bit_offset, BITS_PER_BYTE);\n>>> +        if (bytes_needed > sizeof(data))\n>>> +            return -EINVAL;\n>>> +\n>>> +        /* Prepare write buffer with Read-Modify-Write */\n>>> +        ret = nvmem_cell_prepare_write_buffer(cell, buf, size, data);\n>>> +        if (ret)\n>>> +            return ret;\n>>> +    } else {\n>>> +        bytes_needed = size;\n>>> +        memcpy(data, buf, size);\n>>> +    }\n>>> +\n>>>       switch (cell->nvmem->driver->id) {\n>>>       case UCLASS_I2C_EEPROM:\n>>> -        return i2c_eeprom_write(cell->nvmem, cell->offset, buf, size);\n>>> +        return i2c_eeprom_write(cell->nvmem, cell->offset, data, bytes_needed);\n>>>       case UCLASS_MISC: {\n>>> -        int ret = misc_write(cell->nvmem, cell->offset, buf, size);\n>>> -\n>>> +        ret = misc_write(cell->nvmem, cell->offset, data, bytes_needed);\n>>>           if (ret < 0)\n>>>               return ret;\n>>> -        if (ret != size)\n>>> +        if (ret != bytes_needed)\n>>>               return -EIO;\n>>>           return 0;\n>>>       }\n>>>       case UCLASS_RTC:\n>>> -        return dm_rtc_write(cell->nvmem, cell->offset, buf, size);\n>>> +        return dm_rtc_write(cell->nvmem, cell->offset, data, bytes_needed);\n>>>       default:\n>>>           return -ENOSYS;\n>>>       }\n>>> @@ -121,13 +320,27 @@ int nvmem_cell_get_by_index(struct udevice *dev, int index,\n>>>         offset = ofnode_get_addr_size_index_notrans(args.node, 0, &size);\n>>>       if (offset == FDT_ADDR_T_NONE || size == FDT_SIZE_T_NONE) {\n>>> -        dev_dbg(cell->nvmem, \"missing address or size for %s\\n\",\n>>> +        dev_err(cell->nvmem, \"missing address or size for %s\\n\",\n>>>               ofnode_get_name(args.node));\n>>>           return -EINVAL;\n>>>       }\n>>>         cell->offset = offset;\n>>>       cell->size = size;\n>>> +\n>>> +    ret = ofnode_read_u32_index(args.node, \"bits\", 0, &cell->bit_offset);\n>>> +    if (ret) {\n>>> +        cell->bit_offset = 0;\n>>> +        cell->nbits = 0;\n>>> +    } else {\n>>> +        ret = ofnode_read_u32_index(args.node, \"bits\", 1, &cell->nbits);\n>>> +        if (ret)\n>>> +            return -EINVAL;\n>>> +\n>>> +        if (cell->bit_offset + cell->nbits > cell->size * 8)\n>>> +            return -EINVAL;\n>>> +    }\n>>> +\n>>>       return 0;\n>>>   }\n>>>   diff --git a/include/nvmem.h b/include/nvmem.h\n>>> index e6a8a98828b..dd82122f16f 100644\n>>> --- a/include/nvmem.h\n>>> +++ b/include/nvmem.h\n>>> @@ -26,11 +26,15 @@\n>>>    * @nvmem: The backing storage device\n>>>    * @offset: The offset of the cell from the start of @nvmem\n>>>    * @size: The size of the cell, in bytes\n>>> + * @bit_offset: Bit offset within the cell (0 for byte-level access)\n>>> + * @nbits: Number of bits to use (0 for byte-level access)\n>>>    */\n>>>   struct nvmem_cell {\n>>>       struct udevice *nvmem;\n>>>       unsigned int offset;\n>>>       size_t size;\n>>> +    unsigned int bit_offset;\n>>> +    unsigned int nbits;\n>>>   };\n>>\n>> Please also update the documentation for read/write.\n>>\n>>>   struct udevice;\n>>","headers":{"Return-Path":"<u-boot-bounces@lists.denx.de>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20230601 header.b=hrCHLDZR;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)","phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=gmail.com","phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de","phobos.denx.de;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.b=\"hrCHLDZR\";\n\tdkim-atps=neutral","phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=gmail.com","phobos.denx.de;\n spf=pass smtp.mailfrom=seanga2@gmail.com"],"Received":["from phobos.denx.de (phobos.denx.de\n [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fG2TW3Xpzz1xvq\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 18 Feb 2026 14:45:19 +1100 (AEDT)","from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 45BCB83AA9;\n\tWed, 18 Feb 2026 04:45:09 +0100 (CET)","by phobos.denx.de (Postfix, from userid 109)\n id EB2138063E; Wed, 18 Feb 2026 04:45:07 +0100 (CET)","from mail-oi1-x234.google.com (mail-oi1-x234.google.com\n [IPv6:2607:f8b0:4864:20::234])\n (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id DA75383AA9\n for <u-boot@lists.denx.de>; Wed, 18 Feb 2026 04:45:04 +0100 (CET)","by mail-oi1-x234.google.com with SMTP id\n 5614622812f47-463a6c4a535so71719b6e.1\n for <u-boot@lists.denx.de>; Tue, 17 Feb 2026 19:45:04 -0800 (PST)","from ?IPV6:2600:4040:4476:3800:2d8:61ff:fe7c:5d59?\n ([2600:4040:4476:3800:2d8:61ff:fe7c:5d59])\n by smtp.gmail.com with ESMTPSA id\n 6a1803df08f44-8971cca7299sm200753336d6.22.2026.02.17.18.07.50\n (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n Tue, 17 Feb 2026 18:07:51 -0800 (PST)"],"X-Spam-Checker-Version":"SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de","X-Spam-Level":"","X-Spam-Status":"No, score=-3.8 required=5.0 tests=BAYES_00,DKIM_SIGNED,\n DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_GMAIL_RCVD,\n FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,NICE_REPLY_A,\n RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=ham\n autolearn_force=no version=3.4.2","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20230601; t=1771386303; x=1771991103; darn=lists.denx.de;\n h=content-transfer-encoding:in-reply-to:from:references:cc:to\n :content-language:subject:user-agent:mime-version:date:message-id\n :from:to:cc:subject:date:message-id:reply-to;\n bh=PmjOAd+5f8hMjB1DELo6pP2hboNIm8+/rppz16hfwTM=;\n b=hrCHLDZRwhU8If/1WDFlOtP7fnKM2Qp4Rb81bH52jqBG5r5O+lAptYef5F+peg5eae\n A9clPzK/n1O15iG0crisNSN55IUqLBESs0/WqlKC2SW8nTawpzVZQVoId1zg3DJoSH0f\n ebR8pWTUESlYSL+msJOjBSsaK8xJRDPv+8p68a3Pk1Klneiq9Jo6MBDd3GE1jisVxe1t\n ZPGKhK6X9vpcK/WE+EkVQzRrLJ8JFwNypybEJ8NBt6KiRgxBG0TMEAHV/uU2BOOjOWWu\n LG1aXAUOf5rJGedq0cnapHT9X1aGbWcUOSpyhenZcjUtNYjkviZi/4NDt/VdxSbgIzFR\n PruQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1771386303; x=1771991103;\n h=content-transfer-encoding:in-reply-to:from:references:cc:to\n :content-language:subject:user-agent:mime-version:date:message-id\n :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id\n :reply-to;\n bh=PmjOAd+5f8hMjB1DELo6pP2hboNIm8+/rppz16hfwTM=;\n b=KirEriDkCsyXymr0+mX8ZhAWBjbc0UhJ2yK7FYKLzqtvKORQxNd2xuzcdYpKhY4GZ7\n 0UV6DYbLjrRlCfyiy8zrphFkYHSE50E6BvMLsfGkCqhpyTpAIGY5FNdphk6YaKc7DlJ4\n rl3YSBckkyYU4rdLlp4BXk+QH+ispEXT84WRXSZYlpwwbXmTBdNnS+0jl15S9kL8iJ17\n zsQqaVIkgQ1NOcsBJz+aCZONhQ7JAtO0xdoSslLO88ySAhdvz88jQsuNcoQZRONQpr88\n jpdP251YSgnat4yCoqn+j7H4JK/p2sp2O+R4CfBO0KIBzhRuAV8ypUGqnd8PPU6gcxoM\n SsqQ==","X-Forwarded-Encrypted":"i=1;\n AJvYcCX1HgBkIct/Ajzg3fTNciYMkOsLAoVOzNg2biCE59dPNbaLCJb6rEvFWw4IkIGEYcYB19eTUBQ=@lists.denx.de","X-Gm-Message-State":"AOJu0YzmBFHHDhsWdcUIHyWpYvU8eABnYaWT4MdU1j7haEKWrACX/8AI\n 1tqSAuDxusQtJTsaV2/CkupgthxFidvUBU+hFcSwx9gkDw+a/n8G3bWiittDGQ==","X-Gm-Gg":"AZuq6aKFf/wPL7Dz66kzjG+1NcxjH41SoXk6ZNMp3mAxQH0QaeeKlCZNm2QwNgwUQes\n E0wTQkQ8zGTpHt2MfpJDlJ2Ho7PQAKSN0ZwhYNW0z55RLip5getuCR6/PRLNnLFoIODAMAfaB7Y\n p+SEDxOB3T9TD7qsIQEdU2iglQNhCk9f+97gFGRJXKP6jqswy1LjQtyu2b+ZsnyIAhyvieuZIE+\n Fo+mUhqYrKL9AdjsL9V1u8/hZEqebLnnjbHKAYii3C3N26t/yfVLGnqQ4DR+2iz71BfxWlEmNjC\n 90bPhNKOgHdJLqFGSKZNBolanhsTZuU5VgUtdkwjOlXp9paiXVjbABUitwCtoZ8YZFs45eYrnZk\n iRMKyyLH2yFYIjxtuU6km4lSy0NX5mw+PLjN0CJ10o1ws9uOFKVLFXlKmw89CcBjBNp5sDPeDDN\n BiW8U+TGP5WGo3HEAFR5nhjTepokGqRFTjU7/jvbwlmefmWPoLsLgJZ4Jcg5er2UL3xOs=","X-Received":"by 2002:a05:622a:1182:b0:4ee:1063:d0f3 with SMTP id\n d75a77b69052e-506a6b40c62mr166162411cf.11.1771380471707;\n Tue, 17 Feb 2026 18:07:51 -0800 (PST)","Message-ID":"<96a3a5e8-a853-b766-a013-d3db6bfce117@gmail.com>","Date":"Tue, 17 Feb 2026 21:07:50 -0500","MIME-Version":"1.0","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101\n Thunderbird/91.11.0","Subject":"Re: [PATCH v2 2/6] misc: Add support for bit fields in NVMEM cells","Content-Language":"en-US","To":"Aswin Murugan <aswin.murugan@oss.qualcomm.com>","Cc":"trini@konsulko.com, marek.vasut+renesas@mailbox.org,\n neil.armstrong@linaro.org, peng.fan@nxp.com, quentin.schulz@cherry.de,\n n-francis@ti.com, xypron.glpk@gmx.de, h-vm@ti.com, justin@tidylabs.net,\n jamie.gibbons@microchip.com, ycliang@andestech.com, me@samcday.com,\n sughosh.ganu@arm.com, gchan9527@gmail.com, ilias.apalodimas@linaro.org,\n u-boot-qcom@groups.io, u-boot@lists.denx.de, sumit.garg@kernel.org,\n casey.connolly@linaro.org","References":"<20260213112717.1256823-1-aswin.murugan@oss.qualcomm.com>\n <20260213112717.1256823-3-aswin.murugan@oss.qualcomm.com>\n <3fe5e11d-7240-c577-64fc-062d5c5e4d6a@gmail.com>\n <497f7e07-3a5c-4a7a-b2bb-9016d6927ba4@oss.qualcomm.com>","From":"Sean Anderson <seanga2@gmail.com>","In-Reply-To":"<497f7e07-3a5c-4a7a-b2bb-9016d6927ba4@oss.qualcomm.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"base64","X-BeenThere":"u-boot@lists.denx.de","X-Mailman-Version":"2.1.39","Precedence":"list","List-Id":"U-Boot discussion <u-boot.lists.denx.de>","List-Unsubscribe":"<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>","List-Archive":"<https://lists.denx.de/pipermail/u-boot/>","List-Post":"<mailto:u-boot@lists.denx.de>","List-Help":"<mailto:u-boot-request@lists.denx.de?subject=help>","List-Subscribe":"<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>","Errors-To":"u-boot-bounces@lists.denx.de","Sender":"\"U-Boot\" <u-boot-bounces@lists.denx.de>","X-Virus-Scanned":"clamav-milter 0.103.8 at phobos.denx.de","X-Virus-Status":"Clean"}},{"id":3651921,"web_url":"http://patchwork.ozlabs.org/comment/3651921/","msgid":"<23fa6538-d69b-4f59-9e36-f3cf2c6dd543@oss.qualcomm.com>","list_archive_url":null,"date":"2026-02-19T11:24:06","subject":"Re: [PATCH v2 2/6] misc: Add support for bit fields in NVMEM cells","submitter":{"id":90811,"url":"http://patchwork.ozlabs.org/api/people/90811/","name":"Aswin Murugan","email":"aswin.murugan@oss.qualcomm.com"},"content":"Hi Sean,\n\nOn 2/18/2026 7:37 AM, Sean Anderson wrote:\n> On 2/17/26 14:05, Aswin Murugan wrote:\n>> Hi Sean,\n>>\n>> Thanks for your feedback.\n>> To address stack smashing, which occurs when the cell size is larger \n>> than 4 bytes, I will revert the `nvmem_cell_read()` call in \n>> `reboot_mode_get()` to pass `sizeof(*mode)` as the size, consistent \n>> with the original implementation.\n>>\n>> Inside `nvmem_cell_read()`, will modify the validation check. Instead \n>> of enforcing `size == cell->size`, will check if `cell->size` is \n>> within the passed `size` (i.e., `cell->size <= size`) to correctly \n>> support our 1-byte read case where the buffer is 4 bytes.\n>\n> Then don't we need to zero out the rest of the buffer?\n>\n> I would expect the check to be\n>\n> if ((cell->bit_offset && size > cell->size) || size != cell->size)\n>     return -EINVAL;\n>\n>> Also, i2c_eeprom_read() and misc_read() will continue to request a \n>> read for cell->size instead of the passed buffer size, ensuring we \n>> only read the valid data from the hardware.\n>>\n>> Regarding the bit field logic, as you suggested will simplify the \n>> bit‑field handling to max u32 size, which significantly reduces the \n>> code complexity. Given this simplification, is it still necessary to \n>> keep this bit‑manipulation logic behind a separate config option?\n>\n> I think it's likely. You can check the growth with \n> scripts/bloat-o-meter in\n> Linux. Since this is mainly for U-Boot proper I'd say a couple hundred \n> bytes\n> is reasonable for this feature.\n>\n>> Kindly confirm if this approach aligns with your expectations. \n>\n> Please remember to reply on the bottom :)\n>\n> --Sean\n\nThe suggested check will fail for our case, we always pass size = \nsizeof(u32) = 4 bytes regardless of the actual cell size.\n\nExample: 1-byte cell with 7-bit field\n\ncell->size = 1, bit_offset = 1, nbits = 7, size = 4\n\nWith suggested check: if ((cell->bit_offset && size > cell->size) || \nsize != cell->size) -> (1 && 4 > 1) || 4 != 1 -> TRUE -> rejects valid case\n\nIf we have a check as below:\n\nif (size < cell->size) -> 4 < 1 -> FALSE -> correctly allows\n\nThen if cell has nbits set, bit field bounds can be validated separately \nas follows:\n\nbytes_needed = DIV_ROUND_UP(7+1, 8)\n\nif (bytes_needed > cell->size || bytes_needed > sizeof(u32) || size != \nsizeof(u32))\n\nThis validates:\n\n  * bytes_needed > cell->size: Bit field doesn't exceed actual cell size\n  * bytes_needed > sizeof(u32): Bit field doesn't exceed maximum\n    supported size\n  * size != sizeof(u32): Buffer size is correct for bit field operations\n\nThanks\n\nAswin","headers":{"Return-Path":"<u-boot-bounces@lists.denx.de>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.a=rsa-sha256\n header.s=qcppdkim1 header.b=fRmSeySW;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com\n header.a=rsa-sha256 header.s=google header.b=gT1HZGEQ;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)","phobos.denx.de;\n dmarc=none (p=none dis=none) header.from=oss.qualcomm.com","phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de","phobos.denx.de;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=qualcomm.com header.i=@qualcomm.com\n header.b=\"fRmSeySW\";\n\tdkim=pass (2048-bit key;\n unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com\n header.b=\"gT1HZGEQ\";\n\tdkim-atps=neutral","phobos.denx.de; dmarc=none (p=none dis=none)\n header.from=oss.qualcomm.com","phobos.denx.de;\n spf=pass smtp.mailfrom=aswin.murugan@oss.qualcomm.com"],"Received":["from phobos.denx.de (phobos.denx.de\n [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fGrct0nypz1xpl\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 19 Feb 2026 22:24:29 +1100 (AEDT)","from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 3807483A47;\n\tThu, 19 Feb 2026 12:24:21 +0100 (CET)","by phobos.denx.de (Postfix, from userid 109)\n id C5E2883AA9; Thu, 19 Feb 2026 12:24:20 +0100 (CET)","from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com\n [205.220.168.131])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id 72BFE83936\n for <u-boot@lists.denx.de>; Thu, 19 Feb 2026 12:24:18 +0100 (CET)","from pps.filterd (m0279863.ppops.net [127.0.0.1])\n by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id\n 61J47m0C422068\n for <u-boot@lists.denx.de>; Thu, 19 Feb 2026 11:24:16 GMT","from mail-pl1-f199.google.com (mail-pl1-f199.google.com\n [209.85.214.199])\n by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4cd76e48sr-1\n (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT)\n for <u-boot@lists.denx.de>; Thu, 19 Feb 2026 11:24:16 +0000 (GMT)","by mail-pl1-f199.google.com with SMTP id\n d9443c01a7336-2a77040ede0so9941865ad.2\n for <u-boot@lists.denx.de>; Thu, 19 Feb 2026 03:24:16 -0800 (PST)","from [10.152.202.155] ([202.46.23.19])\n by smtp.gmail.com with ESMTPSA id\n d9443c01a7336-2ad1aadc729sm149797475ad.64.2026.02.19.03.24.08\n (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n Thu, 19 Feb 2026 03:24:14 -0800 (PST)"],"X-Spam-Checker-Version":"SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de","X-Spam-Level":"","X-Spam-Status":"No, score=-0.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,\n DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,KHOP_DYNAMIC,\n RCVD_IN_DNSWL_BLOCKED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,\n RCVD_IN_VALIDITY_RPBL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=no\n autolearn_force=no version=3.4.2","DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h=\n cc:content-transfer-encoding:content-type:date:from:in-reply-to\n :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=\n Drf1WU7UhH3YH/q+kEl60Y5tVH6fLlujPap7kZvasEs=; b=fRmSeySW4Lji2H72\n +H4NsIi/XiMEEp1463SZXwm4U/tZ8E+a/ofv6Tiu94PghNg11rI/nom1V1L8uWvf\n Up2qGrcgu5yZaqepzEo2YAWKYFA09E/IExI3oEgBIQX5LD2bakKcJWjvQXr/GZZv\n b/arSh9n4W0GBbyvvF+v4g3kajhm0NvSkjM6satEcRja89/vVFinjeBFFm04RZ7I\n RYgFP6aSN1TGywex0rDYyG+fFW8W0hDAuG+isNzd9jOfAif6gyg7PtpVkyrM8Ozn\n WbFtggahQOc7B1SWLFt2bMctP4FHfxl8rhtHq9Dy2M2IZoazBR/UJiA9If3OFqB5\n ZjtWJA==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=oss.qualcomm.com; s=google; t=1771500256; x=1772105056; darn=lists.denx.de;\n h=content-transfer-encoding:in-reply-to:from:content-language\n :references:cc:to:subject:user-agent:mime-version:date:message-id\n :from:to:cc:subject:date:message-id:reply-to;\n bh=Drf1WU7UhH3YH/q+kEl60Y5tVH6fLlujPap7kZvasEs=;\n b=gT1HZGEQgRMYqNsOUiWKTJA0hatlTpyAN2sBN1MXh19F+guEGlUmUW0fCXYp8isicz\n /GjPrtdlpbKl6ITM/jIViq2OwROq+xZAndLzmorRaivEjkbdkHbGw7NZJMdZBesIkNlt\n FPaNv4SUVBsXNBIprDi3oTng1Z55cE+qnm7wwbUVbZfp3qEpWpIC47kHzEAygIenNP/J\n I5yJahX5AsieyTLhZ9hDcO5YbUd8Awh+nRJLz357IKxsag6olZHu2usR6xPbB1Y2Sl+1\n uyKYL6LQULXdzVM/2yCIslOOXgKrbEzN7uIM6S5cWKFYw5PXP+wBcgvXQCzT9eAPt7Ce\n mm9g=="],"X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1771500256; x=1772105056;\n h=content-transfer-encoding:in-reply-to:from:content-language\n :references:cc:to:subject:user-agent:mime-version:date:message-id\n :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id\n :reply-to;\n bh=Drf1WU7UhH3YH/q+kEl60Y5tVH6fLlujPap7kZvasEs=;\n b=JF1SbR3mCHM89c530yQGDqiKjIpHEFVMS9slWAqoO7e8b5Oi6oqmnjNj4LAYibhy6q\n t9R5WluZpk5kZjgOfUPoi/EvELliScAHNJyndP8DIOWTnQ2GcCWBXDt9Drht2P+QMDt2\n 3vyKWTapaI9wwxdx95ZQrrt5lzbUEWUOzgaxs/ySBOHThuaKDC4OL5zwgU3oOlf8P0mM\n BJyjRJQHVtrA9nh/xKCbk6IFhDB6Z/iJKitRFwgQ8+gOLch/OBNfNNaa/aZfZI/5m6Ls\n Bfzkd1VvEcytmuGec3t0CVx5WoZ1/rKTjd+DYpMoWwetry2CxpnxmlGPq+KoWkaN0w8P\n 4HaA==","X-Forwarded-Encrypted":"i=1;\n AJvYcCVgVJy+GVvxQtZkDReSMqbDlfJ35WGXp4mO3q8rJUaZl0dTHBYmp7T7kjKgkuIu7iuFeprdEKU=@lists.denx.de","X-Gm-Message-State":"AOJu0YzJTqzISJTM+vONWO6HjNAZ2R+GW4wAowX6MrK54/P+zIOF/Hf4\n pAUKP2s1WNmB+LQlyG/K/elPGWrad6mQ0lZyidnSN+FzQdf9mroXEWzs0EMc6ueeIwXRoJU0o1k\n 7Zo7qPoGuTPtrzD/PyD1/hxZVIGPMdaTgGNtowS976RkebUPn2+852mc7","X-Gm-Gg":"AZuq6aKxsLAP5T+hLVPSejyhoxTBAQanso38b79G+StQVchR41cLRUrTA/urY6Sm9UW\n iXvLU1WsB4YHdXayNTgTD/WiB0xXgVwkMAd7YriImdQK///xP4XOBuZKJnFnzWrgK/dO73cIeP2\n YJJWrnlBOpEssA+SZCZQH5GiE7lcDowKIOJZJWX9pYo97xJtgGnh4MmifHkraFr9XMhe05xizcd\n IUS0QqZsaPBHpxRgf0k0ycnfR5MPRPbnh/4SLBCY0VYFBaKzWcQ/8G6VNxRAyiy+vFmzVLHwM2O\n dFy8y6YMhg6tbZxg2yayGmhlr+X8jKPBtTy384Oso/X5fUbiC+kIp9PUVM+Zv/rKrbYNr0eXZId\n tHIp6cKle0d7kh+n5+uBohoUQB7/GHQwZ0JKS+V8BXeDe3qHKU00X5Q==","X-Received":["by 2002:a17:902:ebc3:b0:2a9:5ef2:f788 with SMTP id\n d9443c01a7336-2ad50f5f5ccmr53766745ad.37.1771500255551;\n Thu, 19 Feb 2026 03:24:15 -0800 (PST)","by 2002:a17:902:ebc3:b0:2a9:5ef2:f788 with SMTP id\n d9443c01a7336-2ad50f5f5ccmr53766355ad.37.1771500254993;\n Thu, 19 Feb 2026 03:24:14 -0800 (PST)"],"Message-ID":"<23fa6538-d69b-4f59-9e36-f3cf2c6dd543@oss.qualcomm.com>","Date":"Thu, 19 Feb 2026 16:54:06 +0530","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v2 2/6] misc: Add support for bit fields in NVMEM cells","To":"Sean Anderson <seanga2@gmail.com>","Cc":"trini@konsulko.com, marek.vasut+renesas@mailbox.org,\n neil.armstrong@linaro.org, peng.fan@nxp.com, quentin.schulz@cherry.de,\n n-francis@ti.com, xypron.glpk@gmx.de, h-vm@ti.com, justin@tidylabs.net,\n jamie.gibbons@microchip.com, ycliang@andestech.com, me@samcday.com,\n sughosh.ganu@arm.com, gchan9527@gmail.com, ilias.apalodimas@linaro.org,\n u-boot-qcom@groups.io, u-boot@lists.denx.de, sumit.garg@kernel.org,\n casey.connolly@linaro.org","References":"<20260213112717.1256823-1-aswin.murugan@oss.qualcomm.com>\n <20260213112717.1256823-3-aswin.murugan@oss.qualcomm.com>\n <3fe5e11d-7240-c577-64fc-062d5c5e4d6a@gmail.com>\n <497f7e07-3a5c-4a7a-b2bb-9016d6927ba4@oss.qualcomm.com>\n <96a3a5e8-a853-b766-a013-d3db6bfce117@gmail.com>","Content-Language":"en-US","From":"Aswin Murugan <aswin.murugan@oss.qualcomm.com>","In-Reply-To":"<96a3a5e8-a853-b766-a013-d3db6bfce117@gmail.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-Authority-Analysis":"v=2.4 cv=OKsqHCaB c=1 sm=1 tr=0 ts=6996f2e0 cx=c_pps\n a=JL+w9abYAAE89/QcEU+0QA==:117 a=j4ogTh8yFefVWWEFDRgCtg==:17\n a=IkcTkHD0fZMA:10 a=HzLeVaNsDn8A:10 a=s4-Qcg_JpJYA:10\n a=VkNPw1HP01LnGYTKEx00:22 a=Mpw57Om8IfrbqaoTuvik:22 a=GgsMoib0sEa3-_RKJdDe:22\n a=3a11mvtZPsPdW_w_N7UA:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10\n a=324X-CrmTo6CU4MGRt3R:22","X-Proofpoint-Spam-Details-Enc":"AW1haW4tMjYwMjE5MDEwNCBTYWx0ZWRfX6gtt2ctf/ir+\n HL8/yXer/WB9GaZQFSZNRmpwT/nLUm1atL61c2ZjS/AoweNJ2dWtmT8A3K/0Qvyu1O9Lpe2hgF3\n 2DAI68k5f8uvd6qXuQh1x4qc51A1NxgKs0D4Z0SHe/vD6iA5TmC5JjUqGm5ZrSnaW8kN07op8xN\n /4/K58C//hAOaGCcxnRabFxlm8OsT61ZA5LCZM10WWqvn+hGxys6KnIMoSqmmKOMtHevN+Zc9hP\n Kyahz4aoVjtvV8iklyn9ZSXRLN2+AWkkDl41QDEtYUQp6X+yq3IuWmWAq3c1kzVUTk+UpMtAIza\n K3VmgBpJnv01mropb7i35quTSw49WBQxf8AhkrTM3lOenVU40h0G4zZQ4ZyQSK2WbKVeiAMdnJi\n zoFTvm3un+RnXF/xs1WcYQEQkvTLn0MzufIeuDaKfcQDVZgfZEM0876EmViJvSk4ZntMgTfjIlK\n evSOGYI4rdh7WRg28FA==","X-Proofpoint-GUID":"lCYTD-RmORR7_Ow0CrlA2OiuQbo7w3nC","X-Proofpoint-ORIG-GUID":"lCYTD-RmORR7_Ow0CrlA2OiuQbo7w3nC","X-Proofpoint-Virus-Version":"vendor=baseguard\n engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.51,FMLib:17.12.100.49\n definitions=2026-02-19_03,2026-02-18_01,2025-10-01_01","X-Proofpoint-Spam-Details":"rule=outbound_notspam policy=outbound score=0\n malwarescore=0 bulkscore=0 impostorscore=0 adultscore=0 suspectscore=0\n clxscore=1015 spamscore=0 lowpriorityscore=0 phishscore=0 priorityscore=1501\n classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0\n reason=mlx scancount=1 engine=8.22.0-2601150000 definitions=main-2602190104","X-BeenThere":"u-boot@lists.denx.de","X-Mailman-Version":"2.1.39","Precedence":"list","List-Id":"U-Boot discussion <u-boot.lists.denx.de>","List-Unsubscribe":"<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>","List-Archive":"<https://lists.denx.de/pipermail/u-boot/>","List-Post":"<mailto:u-boot@lists.denx.de>","List-Help":"<mailto:u-boot-request@lists.denx.de?subject=help>","List-Subscribe":"<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>","Errors-To":"u-boot-bounces@lists.denx.de","Sender":"\"U-Boot\" <u-boot-bounces@lists.denx.de>","X-Virus-Scanned":"clamav-milter 0.103.8 at phobos.denx.de","X-Virus-Status":"Clean"}},{"id":3652390,"web_url":"http://patchwork.ozlabs.org/comment/3652390/","msgid":"<2b329216-f2f8-88b4-f63d-370d3640e4e7@gmail.com>","list_archive_url":null,"date":"2026-02-20T04:04:45","subject":"Re: [PATCH v2 2/6] misc: Add support for bit fields in NVMEM cells","submitter":{"id":64621,"url":"http://patchwork.ozlabs.org/api/people/64621/","name":"Sean Anderson","email":"seanga2@gmail.com"},"content":"On 2/19/26 06:24, Aswin Murugan wrote:\n> Hi Sean,\n> \n> On 2/18/2026 7:37 AM, Sean Anderson wrote:\n>> On 2/17/26 14:05, Aswin Murugan wrote:\n>>> Hi Sean,\n>>>\n>>> Thanks for your feedback.\n>>> To address stack smashing, which occurs when the cell size is larger than 4 bytes, I will revert the `nvmem_cell_read()` call in `reboot_mode_get()` to pass `sizeof(*mode)` as the size, consistent with the original implementation.\n>>>\n>>> Inside `nvmem_cell_read()`, will modify the validation check. Instead of enforcing `size == cell->size`, will check if `cell->size` is within the passed `size` (i.e., `cell->size <= size`) to correctly support our 1-byte read case where the buffer is 4 bytes.\n>>\n>> Then don't we need to zero out the rest of the buffer?\n>>\n>> I would expect the check to be\n>>\n>> if ((cell->bit_offset && size > cell->size) || size != cell->size)\n>>     return -EINVAL;\n>>\n>>> Also, i2c_eeprom_read() and misc_read() will continue to request a read for cell->size instead of the passed buffer size, ensuring we only read the valid data from the hardware.\n>>>\n>>> Regarding the bit field logic, as you suggested will simplify the bit‑field handling to max u32 size, which significantly reduces the code complexity. Given this simplification, is it still necessary to keep this bit‑manipulation logic behind a separate config option?\n>>\n>> I think it's likely. You can check the growth with scripts/bloat-o-meter in\n>> Linux. Since this is mainly for U-Boot proper I'd say a couple hundred bytes\n>> is reasonable for this feature.\n>>\n>>> Kindly confirm if this approach aligns with your expectations. \n>>\n>> Please remember to reply on the bottom :)\n>>\n>> --Sean\n> \n> The suggested check will fail for our case, we always pass size = sizeof(u32) = 4 bytes regardless of the actual cell size.\n> \n> Example: 1-byte cell with 7-bit field\n> \n> cell->size = 1, bit_offset = 1, nbits = 7, size = 4\n> \n> With suggested check: if ((cell->bit_offset && size > cell->size) || size != cell->size) -> (1 && 4 > 1) || 4 != 1 -> TRUE -> rejects valid case\n> \n> If we have a check as below:\n> \n> if (size < cell->size) -> 4 < 1 -> FALSE -> correctly allows\n> \n> Then if cell has nbits set, bit field bounds can be validated separately as follows:\n> \n> bytes_needed = DIV_ROUND_UP(7+1, 8)\n> \n> if (bytes_needed > cell->size || bytes_needed > sizeof(u32) || size != sizeof(u32))\n> \n> This validates:\n> \n>   * bytes_needed > cell->size: Bit field doesn't exceed actual cell size\n>   * bytes_needed > sizeof(u32): Bit field doesn't exceed maximum\n>     supported size\n>   * size != sizeof(u32): Buffer size is correct for bit field operations\n\nYeah, but it's important to ensure size == cell->size for normal bitfields. We don't want to allow e.g.\nsupplying a 4-byte cell for a mac address. We probably don't want to allow storing e.g. 0xdeadbeef in a\ncell of size 2 either...\n\n--Sean","headers":{"Return-Path":"<u-boot-bounces@lists.denx.de>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20230601 header.b=HCqTdo9E;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=85.214.62.61; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)","phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=gmail.com","phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de","phobos.denx.de;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.b=\"HCqTdo9E\";\n\tdkim-atps=neutral","phobos.denx.de;\n dmarc=pass (p=none dis=none) header.from=gmail.com","phobos.denx.de;\n spf=pass smtp.mailfrom=seanga2@gmail.com"],"Received":["from phobos.denx.de (phobos.denx.de [85.214.62.61])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fHGqB5NR4z1xvS\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 20 Feb 2026 15:04:54 +1100 (AEDT)","from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 563CD83946;\n\tFri, 20 Feb 2026 05:04:51 +0100 (CET)","by phobos.denx.de (Postfix, from userid 109)\n id B46AF83AA9; Fri, 20 Feb 2026 05:04:50 +0100 (CET)","from mail-qv1-xf2f.google.com (mail-qv1-xf2f.google.com\n [IPv6:2607:f8b0:4864:20::f2f])\n (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id 956018366F\n for <u-boot@lists.denx.de>; Fri, 20 Feb 2026 05:04:48 +0100 (CET)","by mail-qv1-xf2f.google.com with SMTP id\n 6a1803df08f44-895498f3819so2594696d6.3\n for <u-boot@lists.denx.de>; Thu, 19 Feb 2026 20:04:48 -0800 (PST)","from ?IPV6:2600:4040:4476:3800:2d8:61ff:fe7c:5d59?\n ([2600:4040:4476:3800:2d8:61ff:fe7c:5d59])\n by smtp.gmail.com with ESMTPSA id\n 6a1803df08f44-8971c8e60a0sm224849426d6.0.2026.02.19.20.04.46\n (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n Thu, 19 Feb 2026 20:04:46 -0800 (PST)"],"X-Spam-Checker-Version":"SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de","X-Spam-Level":"","X-Spam-Status":"No, score=-1.4 required=5.0 tests=BAYES_00,DKIM_SIGNED,\n DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_GMAIL_RCVD,\n FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,NICE_REPLY_A,\n RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS autolearn=no\n autolearn_force=no version=3.4.2","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20230601; t=1771560287; x=1772165087; darn=lists.denx.de;\n h=content-transfer-encoding:in-reply-to:from:references:cc:to\n :content-language:subject:user-agent:mime-version:date:message-id\n :from:to:cc:subject:date:message-id:reply-to;\n bh=LibYZpVRGCdbwWUQoCy6W+Xr8sG8HdPyASgkptpoZz4=;\n b=HCqTdo9EwC/MEIgyJMb6jqPIIdEguQmZeYZisR075TOO1xjrdYrEjGb/RiMaH0U+GY\n z4WTChq1qcR5AWRLk2rRl0ZhQOGf+TA0KNMWknHOk2NRZ80VPZ6hhdV+HgZOZdNMdYQR\n TBdxPuj1nTcK0WqAWuH+ytUJ2b5W5dThkQBSAgF6SBUCymi+etpuO/uHvJM8FPWsae8x\n mF9pxVSqELkLGcScwFFWaV/PKAg3grQpWteRiQUPpx4BT0ahV/CJsmn3SvBjkSK0SV2c\n KLDQ7A75dd0rlD6j2EyJbDOrIObATXvCLB8GXFAiDeXuKUvVaS6Rl5LBurTirb+JVvfr\n udzw==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1771560287; x=1772165087;\n h=content-transfer-encoding:in-reply-to:from:references:cc:to\n :content-language:subject:user-agent:mime-version:date:message-id\n :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id\n :reply-to;\n bh=LibYZpVRGCdbwWUQoCy6W+Xr8sG8HdPyASgkptpoZz4=;\n b=OPxt/1fCRmqSra5kTVGxYjGO2cMC8WYwraSoUWLFLnZXEU/mw0vkxnvQKlayEi/28Q\n WRf15U9oge+kkDAEkzICE2VKZCUYzlomelawxLwI8wfz/DV0DG0ZwcPbu1arNP9M6ASb\n ON4l+jmyjdPCu5uFNXxFm9MvRE8gCNzFrYXyExKy8W7w7DyNu/QDphjdjatBXJPsX+pA\n p61jxCxEtoYs4diJrRxvgwNiI+UK0JpplbB0D53okxZPNziYIlphDIS1jai8OFoAhrfb\n dPgQvK+U+9/gw/bmFwwjEvqhDgkKmhyG3tFkmC/wG21v7pSEB22ljV7stEeR+VrMIqN7\n 0vHQ==","X-Forwarded-Encrypted":"i=1;\n AJvYcCVUjAESu2OK2eLE08uw7SiskJ5ZN0BgmT+j8MGb45QMAs+cJdCYK16IclGzijwemiCNk6Pt5x0=@lists.denx.de","X-Gm-Message-State":"AOJu0YxS21qsXEWkMfjREcLvbh/w635J+Eg60w2QvwiVelhXT2uw8kFe\n YoEbAoQ4rOpijUTgTPDWFlD3VBSytL26vIQxbIH2R2phZNP5q/Jt1QL5","X-Gm-Gg":"AZuq6aLdLF30KVqTDlscBUAPDTzeN0Lc37TxkprY9zBE3+FsD+sKpEkD4DXnZHEuwQG\n F/PGIP7P3USA51jzq0BEEV2rJHVQwge2nlskB6bLThNCLtctrYerIdjoz93yV8foUzpC8ORq/AP\n HZfk+0Bzfra5b8zL8b7pp8q9FRI7C3i9p8sHWEEY7JumRhZAA21nrkGswGO3HO+TZHKZxdSawg9\n T3BE2YWIZ7vq/EPaHCiW35WIYZPiQ2nQxkXtP2iiApPYl7T46DJ2begn+ogZUFPQPQGwIjRWviq\n qy8aYJQoyk1gs5KC7Vma2DZOJqhMWiOMmLZpFsw/gXrxOj0tB1o0uqFo92h8GGNS9wB4lGq7I7E\n JjnysjIcFdEIeKMGBqzHI7kvfTVkk2CEQVlC8RQ9fiTfGgGyftU7jLhonM1XimCVUzLTcCiF+5V\n SsW3pTTDp9nHvZaYUm08D7hQYL3+AnGARMQFlwDSMzNdfXZxN4GsIpk2WO2BWFIx3MqhQ=","X-Received":"by 2002:a05:6214:6014:b0:894:9d67:7329 with SMTP id\n 6a1803df08f44-897346fe806mr234325296d6.2.1771560287120;\n Thu, 19 Feb 2026 20:04:47 -0800 (PST)","Message-ID":"<2b329216-f2f8-88b4-f63d-370d3640e4e7@gmail.com>","Date":"Thu, 19 Feb 2026 23:04:45 -0500","MIME-Version":"1.0","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101\n Thunderbird/91.11.0","Subject":"Re: [PATCH v2 2/6] misc: Add support for bit fields in NVMEM cells","Content-Language":"en-US","To":"Aswin Murugan <aswin.murugan@oss.qualcomm.com>","Cc":"trini@konsulko.com, marek.vasut+renesas@mailbox.org,\n neil.armstrong@linaro.org, peng.fan@nxp.com, quentin.schulz@cherry.de,\n n-francis@ti.com, xypron.glpk@gmx.de, h-vm@ti.com, justin@tidylabs.net,\n jamie.gibbons@microchip.com, ycliang@andestech.com, me@samcday.com,\n sughosh.ganu@arm.com, gchan9527@gmail.com, ilias.apalodimas@linaro.org,\n u-boot-qcom@groups.io, u-boot@lists.denx.de, sumit.garg@kernel.org,\n casey.connolly@linaro.org","References":"<20260213112717.1256823-1-aswin.murugan@oss.qualcomm.com>\n <20260213112717.1256823-3-aswin.murugan@oss.qualcomm.com>\n <3fe5e11d-7240-c577-64fc-062d5c5e4d6a@gmail.com>\n <497f7e07-3a5c-4a7a-b2bb-9016d6927ba4@oss.qualcomm.com>\n <96a3a5e8-a853-b766-a013-d3db6bfce117@gmail.com>\n <23fa6538-d69b-4f59-9e36-f3cf2c6dd543@oss.qualcomm.com>","From":"Sean Anderson <seanga2@gmail.com>","In-Reply-To":"<23fa6538-d69b-4f59-9e36-f3cf2c6dd543@oss.qualcomm.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"base64","X-BeenThere":"u-boot@lists.denx.de","X-Mailman-Version":"2.1.39","Precedence":"list","List-Id":"U-Boot discussion <u-boot.lists.denx.de>","List-Unsubscribe":"<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>","List-Archive":"<https://lists.denx.de/pipermail/u-boot/>","List-Post":"<mailto:u-boot@lists.denx.de>","List-Help":"<mailto:u-boot-request@lists.denx.de?subject=help>","List-Subscribe":"<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>","Errors-To":"u-boot-bounces@lists.denx.de","Sender":"\"U-Boot\" <u-boot-bounces@lists.denx.de>","X-Virus-Scanned":"clamav-milter 0.103.8 at phobos.denx.de","X-Virus-Status":"Clean"}}]