[PATCH] nvmem: core: Allow sub-register width nvmem_regmap_write()

Jonas Rebmann <[email protected]>
Newsgroups org.infradead.lists.barebox
Message-ID <[email protected]>
From: Ahmad Fatoum <[email protected]>

The previous implementation of nvmem_regmap_write() required the
supplied value to be a multiple of the register size defined by the
driver ("expect users to observe alignment").

This is however not respected by nvmem cell functions
nvmem_cell_prepare_write_buffer()/__nvmem_cell_entry_write() which
prepare the value buffer based on the "bits" supplied in the devicetree,
resulting in EINVAL errors if an nvmem cell with "bits" spanning less
bytes than val_bytes = DIV_ROUND_UP(config->val_bits, 8) of the nvmem
driver.

To resolve this, accept buffers shorter than val_bytes, and place them
correctly with regard to endianness.

Not-Signed-off-by: Ahmad Fatoum <[email protected]>
Signed-off-by: Jonas Rebmann <[email protected]>
---
Ahmad and me pair-programmed this on friday. Ahmad, can we have your
SoB?
---
 drivers/nvmem/regmap.c | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

diff --git a/drivers/nvmem/regmap.c b/drivers/nvmem/regmap.c
index 98e57909eb..22e667af17 100644
--- a/drivers/nvmem/regmap.c
+++ b/drivers/nvmem/regmap.c
@@ -12,16 +12,31 @@
 static int nvmem_regmap_write(void *ctx, unsigned offset, const void *val, size_t bytes)
 {
 	struct regmap *map = ctx;
+	unsigned int tmp;
 
-	/*
-	 * eFuse writes going through this function may be irreversible,
-	 * so expect users to observe alignment.
-	 */
-	if (bytes % regmap_get_val_bytes(map))
+	if (bytes > regmap_get_val_bytes(map)) {
+		if (bytes % regmap_get_val_bytes(map))
+			return -EINVAL;
+
+		return regmap_bulk_write(map, offset, val,
+					 bytes / regmap_get_val_bytes(map));
+	}
+
+	switch (bytes) {
+	case 1:
+		tmp = *(u8 *)val;
+		break;
+	case 2:
+		tmp = *(u16 *)val;
+		break;
+	case 4:
+		tmp = *(u32 *)val;
+		break;
+	default:
 		return -EINVAL;
+	}
 
-	return regmap_bulk_write(map, offset, val,
-				 bytes / regmap_get_val_bytes(map));
+	return regmap_write(map, offset, tmp);
 }
 
 static int nvmem_regmap_read(void *ctx, unsigned offset, void *buf, size_t bytes)

---
base-commit: f5956c772dc00837bad36fc66df8a53aae86558d
change-id: 20260525-short_nvmem_write-86a2114f6774

Best regards,
--  
Jonas Rebmann <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.