{"id":2220929,"url":"http://patchwork.ozlabs.org/api/1.2/patches/2220929/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/patch/20260408121841.186410-2-aswin.murugan@oss.qualcomm.com/","project":{"id":18,"url":"http://patchwork.ozlabs.org/api/1.2/projects/18/?format=json","name":"U-Boot","link_name":"uboot","list_id":"u-boot.lists.denx.de","list_email":"u-boot@lists.denx.de","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<20260408121841.186410-2-aswin.murugan@oss.qualcomm.com>","list_archive_url":null,"date":"2026-04-08T12:18:35","name":"[v4,1/7] misc: Add support for bit fields in NVMEM cells","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"a21e4182fbbe78b30d5154acb677c3ddc67122d0","submitter":{"id":90811,"url":"http://patchwork.ozlabs.org/api/1.2/people/90811/?format=json","name":"Aswin Murugan","email":"aswin.murugan@oss.qualcomm.com"},"delegate":{"id":151538,"url":"http://patchwork.ozlabs.org/api/1.2/users/151538/?format=json","username":"kcxt","first_name":"Casey","last_name":"Connolly","email":"casey.connolly@linaro.org"},"mbox":"http://patchwork.ozlabs.org/project/uboot/patch/20260408121841.186410-2-aswin.murugan@oss.qualcomm.com/mbox/","series":[{"id":499133,"url":"http://patchwork.ozlabs.org/api/1.2/series/499133/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/list/?series=499133","date":"2026-04-08T12:18:34","name":"qcom: Add NVMEM bitfield support and reboot���mode integration","version":4,"mbox":"http://patchwork.ozlabs.org/series/499133/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2220929/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2220929/checks/","tags":{},"related":[],"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=m8Y++KxK;\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=HE0tZlnB;\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=\"m8Y++KxK\";\n\tdkim=pass (2048-bit key;\n unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com\n header.b=\"HE0tZlnB\";\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)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4frMbR5LBQz1xy1\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 08 Apr 2026 22:20:35 +1000 (AEST)","from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id AC61884118;\n\tWed,  8 Apr 2026 14:20:33 +0200 (CEST)","by phobos.denx.de (Postfix, from userid 109)\n id 6FC028404A; Wed,  8 Apr 2026 14:20:32 +0200 (CEST)","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 C3B8584120\n for <u-boot@lists.denx.de>; Wed,  8 Apr 2026 14:20:29 +0200 (CEST)","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 638B29s1263342\n for <u-boot@lists.denx.de>; Wed, 8 Apr 2026 12:20:28 GMT","from mail-pg1-f198.google.com (mail-pg1-f198.google.com\n [209.85.215.198])\n by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4dd7t239mx-1\n (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT)\n for <u-boot@lists.denx.de>; Wed, 08 Apr 2026 12:20:27 +0000 (GMT)","by mail-pg1-f198.google.com with SMTP id\n 41be03b00d2f7-c709551ec08so10110677a12.3\n for <u-boot@lists.denx.de>; Wed, 08 Apr 2026 05:20:27 -0700 (PDT)","from hu-aswinm-blr.qualcomm.com\n (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com. [103.229.18.19])\n by smtp.gmail.com with ESMTPSA id\n d2e1a72fcca58-82cf9a24039sm20512602b3a.0.2026.04.08.05.20.17\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 08 Apr 2026 05:20:25 -0700 (PDT)"],"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 content-transfer-encoding:content-type:date:from:in-reply-to\n :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=\n 7gmz65N45KppacmQTZ8HP0PtbwNgWbJFVMftib9X0WU=; b=m8Y++KxKCwshQiaQ\n rzT1Ule9+1Xijyu5bIntZ2mlLBaJ4+oa1nIHmNrbBxwL0kzSptsiEXhDBZ0rxX2+\n fIqsaFdlNGXwyrZwvq1jD1CNSUM5sSIBvLOd93W/ttkCZDoUJ83pJ7nYq3XB23dr\n EeVRospVLqhky09ohiSn4BZ59TbCpA1xU14W3RSwX60j7RMxtowDQLd0pYtxDpJN\n Um+W2XlqRPKOaO+04LOD1oWOqWOTPUNprJ2MvTidsyQnrzSE2MdviIbR7MQSvOeq\n 1Jr1Vn5YETwgKh5E2SHWt9TLSPfgXVRaQzMNu5eojrhoQHW1Ic8LCg9IH891TJ4p\n +Nanyg==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=oss.qualcomm.com; s=google; t=1775650827; x=1776255627; darn=lists.denx.de;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:to:from:from:to:cc:subject:date:message-id\n :reply-to; bh=7gmz65N45KppacmQTZ8HP0PtbwNgWbJFVMftib9X0WU=;\n b=HE0tZlnB5kF8+SgdGSbdTZsGd1zjL4lnVGl6fi1tVtueoWf0oK9KTSrJGxoDkq+Kel\n Mr67o2iEvtJuntWVRJy6W1JEl0FhnDGqvM13nIPLdRlvYaNS7F0A+fspNK/ppuVirqQI\n jJaUGVoHqUIewGGOO3wQrGUo2Vf+UPfqetZtQU3OLPX1vcGETHX0v1tEBe3rDilnjXZs\n aW9m70gTM7gb8GHw9Re9uX0OvPlYt6YqNvPhwFCPTHOW2X24DZkWZgYexDfWQ9mCd1P8\n G+I5AFJha76QDQ9z/llowxyxf1Dv0NVxpX9JTGCmgPOZhUNulX1ckoBr0DkoFLamFD6G\n M24Q=="],"X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775650827; x=1776255627;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=7gmz65N45KppacmQTZ8HP0PtbwNgWbJFVMftib9X0WU=;\n b=d1r6IXzZoNK51wUVUwnIma67nQR2ePQi0W9rnFv2y5ssBc1/TTIxs7gevqRCyzdC54\n wcODN0DT6GKV+u7qSzVS0N1bD+dMc0EOGw7uASUx5Dc3vjgKzSwdMVKACetCeLriip5F\n qP6tpX2mL+cu4uULZNvwSdjgGU4hJ6z5MbyRf2RVORhHvHJ7AQLiVI3/G8h6nRCQmKTh\n A/XpmVgn++tt3bMx3ZLEil15/ibjeg4xz2S4gwy3ivw7wKFmpRrz+dzJ3srKSkfRd1eE\n nptEK6vvDvWBsd2wCoPBjgzxGNVsowrqOzlRnz542uTiMkKUMiDSBGaakNe5xoSdt+EC\n CNgA==","X-Forwarded-Encrypted":"i=1;\n AJvYcCXjP9zdtoN9k+HwcJSl7QVX8ibULv3aIpzGLKuFktklJeiLjTsvgbQJQNRnYnUuv8//vjjQBMc=@lists.denx.de","X-Gm-Message-State":"AOJu0Yzpv2p0SwSkFXPbM4CvJnAfdUkiPZ1Cce5ed61Hj0014sYLUQeC\n hR/dLepegymkRdgvF543qjMPnvtRa5djz6atIIxxvRHsWq3Q/218Twtx8F4NbfXQEer3jajeEfd\n FvodSYp9AyQXC/fE7M5Kp0IkrxUZeIxUNSaQ2fyo2cvu4ieZKcddQV+8I","X-Gm-Gg":"AeBDievmiTKUijc9x+blkHgxeJBU3iG5Ej3Y0+lYHIWZHHCop8LUEvSXaMGDrVwM4uj\n 9KwtAcG8p2o2kzrA1l+2FyUTWHbEGk8IqFKR2SJc8PdqiM1Ge47zjIEQxS+nxXy7VOmyBKBuxM+\n z7xT+qO0XuR1RM9o4m3kt1wxOUSsof4MeD/SGdcDU04TEgaSuH3vS6sy98ruLrTpukCauUDMy7j\n fMIg5jJPFAcSUQe4CKpQYQG/HhkZr+de1PWDkCL1sT/DAJ5oysluLWepwG/pRn1PjLe5rZQ0D4s\n XKt50lVf6bWt/Rb591uIrjY7O2rj6GhL/SSbTfVr5+dEUgtCDCRcH0VP3h6z8SCbkexcbQb2JZz\n XeTCyZgImSwhAt1NHZ+hKHZnwME+DA1NZwQ/UYBjhOWa2kkcZrZS1RKbqfRm7VTLP0ZXu0Xz6Yc\n QnZrbXMar0CgvdD7j9VSJTu550n8ZvRhBfG6suGI5P","X-Received":["by 2002:a05:6a00:418e:b0:82a:7893:e14f with SMTP id\n d2e1a72fcca58-82d0dbb9939mr21606511b3a.41.1775650826714;\n Wed, 08 Apr 2026 05:20:26 -0700 (PDT)","by 2002:a05:6a00:418e:b0:82a:7893:e14f with SMTP id\n d2e1a72fcca58-82d0dbb9939mr21606468b3a.41.1775650826151;\n Wed, 08 Apr 2026 05:20:26 -0700 (PDT)"],"From":"Aswin Murugan <aswin.murugan@oss.qualcomm.com>","To":"trini@konsulko.com, aswin.murugan@oss.qualcomm.com,\n casey.connolly@linaro.org, neil.armstrong@linaro.org,\n sumit.garg@kernel.org, sjg@chromium.org, seanga2@gmail.com,\n sughosh.ganu@arm.com, gchan9527@gmail.com, ilias.apalodimas@linaro.org,\n mkorpershoek@kernel.org, marek.vasut+renesas@mailbox.org,\n hs@nabladev.com, msp@baylibre.com, ravi@prevas.dk,\n dinesh.maniyam@altera.com, sajattack@postmarketos.org,\n peng.fan@nxp.com, quentin.schulz@cherry.de,\n jamie.gibbons@microchip.com, mateuslima.ti@gmail.com,\n justin@tidylabs.net, wens@kernel.org, n-francis@ti.com,\n ycliang@andestech.com, jerome.forissier@arm.com, clamor95@gmail.com,\n u-boot@lists.denx.de, u-boot-qcom@groups.io","Subject":"[PATCH v4 1/7] misc: Add support for bit fields in NVMEM cells","Date":"Wed,  8 Apr 2026 17:48:35 +0530","Message-Id":"<20260408121841.186410-2-aswin.murugan@oss.qualcomm.com>","X-Mailer":"git-send-email 2.34.1","In-Reply-To":"<20260408121841.186410-1-aswin.murugan@oss.qualcomm.com>","References":"<20260408121841.186410-1-aswin.murugan@oss.qualcomm.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","X-Authority-Analysis":"v=2.4 cv=De0nbPtW c=1 sm=1 tr=0 ts=69d6480b cx=c_pps\n a=Qgeoaf8Lrialg5Z894R3/Q==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17\n a=IkcTkHD0fZMA:10 a=A5OVakUREuEA:10 a=s4-Qcg_JpJYA:10\n a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=yOCtJkima9RkubShWh1s:22\n a=EUspDBNiAAAA:8 a=T-YsAnR6KVLXiY_LWkEA:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10\n a=x9snwWr2DeNwDh03kgHS:22","X-Proofpoint-Spam-Details-Enc":"AW1haW4tMjYwNDA4MDExMiBTYWx0ZWRfXxQVwbdIezp2q\n VdAByeWdzgUiynkMc0L5tB+xImyVX0Gk/pghWpmPS/dabk1SziwhKuBh95V5QOEhR8fLRweLEcb\n C1MtfwUuaWr5luDz8Bq85FXXx+VPQbY74BY+W8wgr4Jmsd9Waj9uP2rStx3yfJHy4YGXBPMuyYF\n mIZH6tBZU2Fj30NgPDnGubvANgth7KM6kcN5LUBVLOopoWaWq1AtM/8nqaPZgGlbalCo4maPbvm\n 2lW929TVwuxbR25rPylGs46Xa8o0PtpZXP4+wo1cAYWQa9m4UGsGeaEk9uOu+tSHjBNEMnoeRcB\n HFDXiGFWzfQ0BWPuV7JEC9cooHgcTUXOrQM/8wrHSDMziPdBWRRv7uvdBEnP3QH/3fWGBlIzSQr\n Kymfn25uySj2ezSsrH57G4dVcHGRGM7Zhxeubo73r7+4nEILB1J6yUz4bcjdZwfUCF3wdAbpfti\n MA4jA7voeP/tup6WxFA==","X-Proofpoint-ORIG-GUID":"qsYlJH8wwZ3lj9xUJNgfKa8XSVhgzGcv","X-Proofpoint-GUID":"qsYlJH8wwZ3lj9xUJNgfKa8XSVhgzGcv","X-Proofpoint-Virus-Version":"vendor=baseguard\n engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49\n definitions=2026-04-08_03,2026-04-08_01,2025-10-01_01","X-Proofpoint-Spam-Details":"rule=outbound_notspam policy=outbound score=0\n spamscore=0 clxscore=1015 bulkscore=0 phishscore=0 priorityscore=1501\n malwarescore=0 lowpriorityscore=0 suspectscore=0 impostorscore=0 adultscore=0\n classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0\n reason=mlx scancount=1 engine=8.22.0-2604010000 definitions=main-2604080112","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"},"content":"NVMEM cells currently only support byte-level access. Many hardware\nregisters pack multiple fields into single bytes, requiring bit-level\ngranularity. For example, Qualcomm PMIC PON registers store a 7-bit\nreboot reason field within a single byte, with bit 0 reserved for other\npurposes.\n\nAdd support for the optional 'bits' property in NVMEM cell device tree\nbindings. This property specifies <bit_offset num_bits> to define a bit\nfield within the cell's register space.\n\nImplement bit‑field handling in the driver to max u32 size\n\nExample device tree usage:\n        reboot-reason@48 {\n                reg = <0x48 0x01>;\n                bits = <1 7>;  /* 7 bits starting at bit 1 */\n        };\n\nThis reads bits [7:1] from the byte at offset 0x48, leaving bit 0\nuntouched during write operations.\n\nCells without the 'bits' property continue to work unchanged, ensuring\nbackward compatibility with existing device trees.\n\nSigned-off-by: Aswin Murugan <aswin.murugan@oss.qualcomm.com>\n---\nChanges in v4:\n1. Explicitly interpret hardware bytes as little-endian for bitfield operations to ensure\n   consistent behavior across architectures\n   Read path: Hardware LE → CPU native → bit extraction → return CPU native\n   Write path: CPU native → bit manipulation → convert to LE → write to hardware\n2. Removed const pointer write violation in nvmem_cell_write()\n3. Replaced unsafe bit shift expressions with GENMASK() macro to avoid undefined behavior\n   when nbits == 32\n4. Consolidated size validation logic for clarity\n\nChanges in v3:\n1. Simplified bit field handling to maximum u32 size (32 bits).\n2. Enforced strict size matching (size == cell->size) when nbits == 0.\n---\n drivers/misc/nvmem.c | 166 +++++++++++++++++++++++++++++++++++++------\n include/nvmem.h      |   4 ++\n 2 files changed, 148 insertions(+), 22 deletions(-)","diff":"diff --git a/drivers/misc/nvmem.c b/drivers/misc/nvmem.c\nindex 33e80858565..7cca34b09d5 100644\n--- a/drivers/misc/nvmem.c\n+++ b/drivers/misc/nvmem.c\n@@ -12,55 +12,163 @@\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+#include <asm/byteorder.h>\n \n-int nvmem_cell_read(struct nvmem_cell *cell, void *buf, size_t size)\n+/* Maximum supported NVMEM cell size */\n+#define MAX_NVMEM_CELL_SIZE sizeof(u32)  /* 4 bytes */\n+\n+/**\n+ * nvmem_cell_read_raw() - Read raw bytes from NVMEM cell without bit field extraction\n+ * @cell: NVMEM cell to read from\n+ * @buf: Buffer to store read data\n+ * @size: Size of buffer\n+ *\n+ * This is an internal helper that reads raw bytes from hardware without applying\n+ * bit field extraction. Used by both nvmem_cell_read() and nvmem_cell_write().\n+ * Caller must validate buffer size before calling this function.\n+ *\n+ * Return: Number of bytes read on success, negative error code on failure\n+ */\n+static int nvmem_cell_read_raw(struct nvmem_cell *cell, void *buf, size_t size)\n {\n-\tdev_dbg(cell->nvmem, \"%s: off=%u size=%zu\\n\", __func__, cell->offset, size);\n-\tif (size != cell->size)\n-\t\treturn -EINVAL;\n+\tint ret;\n+\n+\tmemset(buf, 0, size);\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, buf, cell->size);\n+\t\tbreak;\n+\tcase UCLASS_MISC:\n+\t\tret = misc_read(cell->nvmem, cell->offset, buf, cell->size);\n \t\tif (ret < 0)\n \t\t\treturn ret;\n-\t\tif (ret != size)\n+\t\tif (ret != cell->size)\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, buf, cell->size);\n+\t\tbreak;\n \tdefault:\n \t\treturn -ENOSYS;\n \t}\n+\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn cell->size;\n+}\n+\n+int nvmem_cell_read(struct nvmem_cell *cell, void *buf, size_t size)\n+{\n+\tint ret, bytes_needed;\n+\tu32 value;\n+\n+\tdev_dbg(cell->nvmem, \"%s: off=%u size=%zu\\n\", __func__, cell->offset, size);\n+\n+\tif (cell->nbits) {\n+\t\tif (size != MAX_NVMEM_CELL_SIZE) {\n+\t\t\tdev_dbg(cell->nvmem, \"bit field requires buffer size %d, got %zu\\n\",\n+\t\t\t\tMAX_NVMEM_CELL_SIZE, size);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tbytes_needed = DIV_ROUND_UP(cell->nbits + cell->bit_offset, BITS_PER_BYTE);\n+\t\tif (bytes_needed > cell->size || bytes_needed > MAX_NVMEM_CELL_SIZE) {\n+\t\t\tdev_dbg(cell->nvmem, \"bit field requires %d bytes, cell size %zu\\n\",\n+\t\t\t\tbytes_needed, cell->size);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t} else {\n+\t\tif (size != cell->size) {\n+\t\t\tdev_dbg(cell->nvmem, \"buffer size %zu must match cell size %zu\\n\",\n+\t\t\t\tsize, cell->size);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t}\n+\n+\tret = nvmem_cell_read_raw(cell, buf, size);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tif (cell->nbits) {\n+\t\tvalue = le32_to_cpu(*((__le32 *)buf));\n+\t\tvalue >>= cell->bit_offset;\n+\t\tvalue &= GENMASK(cell->nbits - 1, 0);\n+\t\t*(u32 *)buf = value;\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+\tint ret, bytes_needed;\n+\tu32 current, value, mask;\n+\n \tdev_dbg(cell->nvmem, \"%s: off=%u size=%zu\\n\", __func__, cell->offset, size);\n-\tif (size != cell->size)\n-\t\treturn -EINVAL;\n+\n+\tif (cell->nbits) {\n+\t\tif (size != MAX_NVMEM_CELL_SIZE) {\n+\t\t\tdev_dbg(cell->nvmem, \"bit field requires buffer size %d, got %zu\\n\",\n+\t\t\t\tMAX_NVMEM_CELL_SIZE, size);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tbytes_needed = DIV_ROUND_UP(cell->nbits + cell->bit_offset, BITS_PER_BYTE);\n+\t\tif (bytes_needed > cell->size || bytes_needed > MAX_NVMEM_CELL_SIZE) {\n+\t\t\tdev_dbg(cell->nvmem, \"bit field requires %d bytes, cell size %zu\\n\",\n+\t\t\t\tbytes_needed, cell->size);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tret = nvmem_cell_read_raw(cell, &current, sizeof(current));\n+\t\tif (ret < 0)\n+\t\t\treturn ret;\n+\n+\t\tcurrent = le32_to_cpu(*((__le32 *)&current));\n+\t\tvalue = *(const u32 *)buf;\n+\t\tvalue &= GENMASK(cell->nbits - 1, 0);\n+\t\tvalue <<= cell->bit_offset;\n+\n+\t\tmask = GENMASK(cell->nbits - 1, 0) << cell->bit_offset;\n+\n+\t\tcurrent = (current & ~mask) | value;\n+\t\tbuf = &current;\n+\t} else {\n+\t\tif (size != cell->size) {\n+\t\t\tdev_dbg(cell->nvmem, \"buffer size %zu must match cell size %zu\\n\",\n+\t\t\t\tsize, cell->size);\n+\t\t\treturn -EINVAL;\n+\t\t}\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-\tcase UCLASS_MISC: {\n-\t\tint ret = misc_write(cell->nvmem, cell->offset, buf, size);\n-\n+\t\tret = i2c_eeprom_write(cell->nvmem, cell->offset, buf, cell->size);\n+\t\tbreak;\n+\tcase UCLASS_MISC:\n+\t\tret = misc_write(cell->nvmem, cell->offset, buf, cell->size);\n \t\tif (ret < 0)\n \t\t\treturn ret;\n-\t\tif (ret != size)\n+\t\tif (ret != cell->size)\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_write(cell->nvmem, cell->offset, buf, size);\n+\t\tret = dm_rtc_write(cell->nvmem, cell->offset, buf, cell->size);\n+\t\tbreak;\n \tdefault:\n \t\treturn -ENOSYS;\n \t}\n+\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn 0;\n }\n \n /**\n@@ -128,6 +236,20 @@ int nvmem_cell_get_by_index(struct udevice *dev, int index,\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 \ndiff --git a/include/nvmem.h b/include/nvmem.h\nindex 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 \n struct udevice;\n","prefixes":["v4","1/7"]}