From nobody Sat Apr 11 07:59:45 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 102C4C25B06 for ; Sun, 14 Aug 2022 17:37:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239769AbiHNRhV (ORCPT ); Sun, 14 Aug 2022 13:37:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54700 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232048AbiHNRhL (ORCPT ); Sun, 14 Aug 2022 13:37:11 -0400 Received: from wout4-smtp.messagingengine.com (wout4-smtp.messagingengine.com [64.147.123.20]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2CB7218E32; Sun, 14 Aug 2022 10:37:11 -0700 (PDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.west.internal (Postfix) with ESMTP id B2BFF32005CA; Sun, 14 Aug 2022 13:37:09 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Sun, 14 Aug 2022 13:37:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sholland.org; h= cc:cc:content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm2; t=1660498629; x=1660585029; bh=49 dhIZfr5q8v+hGU8cuF1niSFm1wGL2iaQ0mMKaC1Us=; b=KMrjwpl8IyD45VewM0 dnahvq08KfsO25Cnb/NS7UvZIdllLvu08CkJfT1IJRn+RauKE5ROgPXzcLoAiPbz GG8x351g5x40BbTEE4fd1BN0E/bac9JP1l5OqMBTwLGNfmhczFib9iGTh3GLmy3V XmV69ZIXLPW74p1KKcwojNrkasQok2SPbX77ECRBQqtftiO/XGl4OmmMXzP24rlF yL9wxa8ipCWVvid7XN6jHf0uPnGWw9YYKeD61p1/nQTDW3TPodE7Rs7nHn/5ixTD U+IxN+38eMNvnJFEe6KGosSZWIrtOO2q79E05Fdf6kTIFHWVMvChvKmNFQfJ8X0X 1NDA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm1; t=1660498629; x=1660585029; bh=49dhIZfr5q8v+ hGU8cuF1niSFm1wGL2iaQ0mMKaC1Us=; b=RuQ9kyJ9nsUTo/A8HY226w+V00dU+ QdHGVJOLVr2M9qocaY5Z4cMX5XD9AMI1Fj08k47MlL0PjmsS7Ssu81c+vK7M3IaW 1RaxCyJBMvjjay4GWXNp0AOfg86Go3xI9DfuyJCPJ8KAeMwRxxxoYsPMDyCjH1Jo 1b/bUWAs6vSbgjAa0ib/ILDeujgYWhjpXw6d1FyXo07teXesVwvxA3y6X4xYjmoS ix6ASTAZXNv5ONtUw4V7GA2Zk7BeHKfnU3z0FhXHeYsOhJANAy6/J9TbEXOgB2j+ Dhavxe9oT/eil+udKtY7y8DRiCwp7pvobX0m0xf+0MgVOVr0Ej1vcUn7g== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrvdehtddgudduiecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpefhvfevufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefurghm uhgvlhcujfholhhlrghnugcuoehsrghmuhgvlhesshhhohhllhgrnhgurdhorhhgqeenuc ggtffrrghtthgvrhhnpedukeetueduhedtleetvefguddvvdejhfefudelgfduveeggeeh gfdufeeitdevteenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfh hrohhmpehsrghmuhgvlhesshhhohhllhgrnhgurdhorhhg X-ME-Proxy: Feedback-ID: i0ad843c9:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 14 Aug 2022 13:37:08 -0400 (EDT) From: Samuel Holland To: Srinivas Kandagatla , Chen-Yu Tsai , Jernej Skrabec Cc: Samuel Holland , Greg Kroah-Hartman , Krzysztof Kozlowski , Rob Herring , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-sunxi@lists.linux.dev Subject: [PATCH 4/4] nvmem: core: Support reading cells with >= 8 bit offsets Date: Sun, 14 Aug 2022 12:36:55 -0500 Message-Id: <20220814173656.11856-5-samuel@sholland.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220814173656.11856-1-samuel@sholland.org> References: <20220814173656.11856-1-samuel@sholland.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" For NVMEM devices with .stride > 1, some cell values may not be aligned to the device's stride. In this case, it is necessary to use bit_offset to access the cell. For example, to access the third byte of an NVMEM device with .stride =3D=3D 4, we need "bits =3D <16 8>;" in the devicetree. Implement this on the read side. The write side implementation would be more complicated, and it is not necessary for read-only NVMEM devices. For now, reject writes for these cells to avoid any incorrect behavior. Signed-off-by: Samuel Holland --- drivers/nvmem/core.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 1e3c754efd0d..309beba8c9f0 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -1373,63 +1373,67 @@ void nvmem_cell_put(struct nvmem_cell *cell) } EXPORT_SYMBOL_GPL(nvmem_cell_put); =20 -static void nvmem_shift_read_buffer_in_place(struct nvmem_cell_entry *cell= , void *buf) +static int nvmem_shift_read_buffer_in_place(struct nvmem_cell_entry *cell,= void *buf) { + int bit_offset =3D cell->bit_offset, bytes, i; u8 *p, *b; - int i, extra, bit_offset =3D cell->bit_offset; =20 p =3D b =3D buf; if (bit_offset) { + int byte_offset =3D bit_offset / BITS_PER_BYTE; + + b +=3D byte_offset; + bit_offset %=3D BITS_PER_BYTE; + bytes =3D cell->bytes - byte_offset; + /* First shift */ - *b++ >>=3D bit_offset; + *p =3D *b++ >> bit_offset; =20 /* setup rest of the bytes if any */ - for (i =3D 1; i < cell->bytes; i++) { + for (i =3D 1; i < bytes; i++) { /* Get bits from next byte and shift them towards msb */ - *p |=3D *b << (BITS_PER_BYTE - bit_offset); - - p =3D b; - *b++ >>=3D bit_offset; + *p++ |=3D *b << (BITS_PER_BYTE - bit_offset); + *p =3D *b++ >> bit_offset; } - } else { - /* point to the msb */ - p +=3D cell->bytes - 1; } =20 /* result fits in less bytes */ - extra =3D cell->bytes - DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE); - while (--extra >=3D 0) - *p-- =3D 0; + bytes =3D DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE); + p =3D buf + bytes; + memset(p, 0, cell->bytes - bytes); =20 /* clear msb bits if any leftover in the last byte */ if (cell->nbits % BITS_PER_BYTE) - *p &=3D GENMASK((cell->nbits % BITS_PER_BYTE) - 1, 0); + p[-1] &=3D GENMASK((cell->nbits % BITS_PER_BYTE) - 1, 0); + + return bytes; } =20 static int __nvmem_cell_read(struct nvmem_device *nvmem, struct nvmem_cell_entry *cell, void *buf, size_t *len, const char *id) { + int bytes =3D cell->bytes; int rc; =20 - rc =3D nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes); + rc =3D nvmem_reg_read(nvmem, cell->offset, buf, bytes); =20 if (rc) return rc; =20 /* shift bits in-place */ if (cell->bit_offset || cell->nbits) - nvmem_shift_read_buffer_in_place(cell, buf); + bytes =3D nvmem_shift_read_buffer_in_place(cell, buf); =20 if (nvmem->cell_post_process) { rc =3D nvmem->cell_post_process(nvmem->priv, id, - cell->offset, buf, cell->bytes); + cell->offset, buf, bytes); if (rc) return rc; } =20 if (len) - *len =3D cell->bytes; + *len =3D bytes; =20 return 0; } @@ -1526,6 +1530,7 @@ static int __nvmem_cell_entry_write(struct nvmem_cell= _entry *cell, void *buf, si int rc; =20 if (!nvmem || nvmem->read_only || + cell->bit_offset >=3D BITS_PER_BYTE || (cell->bit_offset =3D=3D 0 && len !=3D cell->bytes)) return -EINVAL; =20 --=20 2.35.1