From: Varshini Rajendran <varshini.rajendran@microchip.com>
To: <ehristev@kernel.org>, <jic23@kernel.org>,
<dlechner@baylibre.com>, <nuno.sa@analog.com>, <andy@kernel.org>,
<robh@kernel.org>, <krzk+dt@kernel.org>, <conor+dt@kernel.org>,
<nicolas.ferre@microchip.com>, <alexandre.belloni@bootlin.com>,
<claudiu.beznea@tuxon.dev>, <srini@kernel.org>,
<marcelo.schmitt@analog.com>, <radu.sabau@analog.com>,
<Jonathan.Santos@analog.com>, <jorge.marques@analog.com>,
<joshua.crofts1@gmail.com>, <jishnu.prakash@oss.qualcomm.com>,
<antoniu.miclaus@analog.com>, <varshini.rajendran@microchip.com>,
<mazziesaccount@gmail.com>, <linux-iio@vger.kernel.org>,
<devicetree@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
<linux-kernel@vger.kernel.org>
Subject: [PATCH v4 08/16] nvmem: microchip-otpc: nvmem: microchip-otpc: add tag-based packet lookup
Date: Mon, 27 Jul 2026 17:56:25 +0530 [thread overview]
Message-ID: <20260727122633.117435-9-varshini.rajendran@microchip.com> (raw)
In-Reply-To: <20260727122633.117435-1-varshini.rajendran@microchip.com>
Add support for accessing OTP packets by their tag which is a FourCC
while preserving backward compatibility with the existing ID-based
lookup.
The OTP memory layout can vary across devices and may change over time,
making the packet ID approach unreliable when the memory map is not
known in advance. The packet tag provides a reliable way to identify
and access packets without prior knowledge of the OTP memory layout.
Two offset encodings are now supported:
1. Legacy ID-based: offset = OTP_PKT(id) = id * 4
Used in DT as: reg = <OTP_PKT(1) 76>;
2. TAG-based: offset = 4-byte ASCII packet tag (FourCC)
Used in DT as: reg = <0x41435354 0x4c>; (tag "ACST")
The driver resolves offsets matching valid legacy selectors (multiples
of 4 within the packet count) through ID lookup, falling back to tag
lookup for other valid values. This ensures existing device trees
continue to work while enabling new tag-based access. During probe,
packet meta data including the tag is read and cached.
The stride of the nvmem memory is set to 1 in order to support tag based
offsets, comment in the header file is updated accordingly.
Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
---
drivers/nvmem/microchip-otpc.c | 117 ++++++++++++++++--
.../nvmem/microchip,sama7g5-otpc.h | 4 +-
2 files changed, 110 insertions(+), 11 deletions(-)
diff --git a/drivers/nvmem/microchip-otpc.c b/drivers/nvmem/microchip-otpc.c
index df979e8549fd..a17f82afdc37 100644
--- a/drivers/nvmem/microchip-otpc.c
+++ b/drivers/nvmem/microchip-otpc.c
@@ -23,6 +23,8 @@
#define MCHP_OTPC_SR_READ BIT(6)
#define MCHP_OTPC_HR (0x20)
#define MCHP_OTPC_HR_SIZE GENMASK(15, 8)
+#define MCHP_OTPC_HR_PACKET GENMASK(2, 0)
+#define MCHP_OTPC_HR_PACKET_REGULAR 1
#define MCHP_OTPC_DR (0x24)
#define MCHP_OTPC_NAME "mchp-otpc"
@@ -47,11 +49,13 @@ struct mchp_otpc {
* @list: list head
* @id: packet ID
* @offset: packet offset (in words) in OTP memory
+ * @tag: 4-byte ASCII (FourCC) tag of the packet
*/
struct mchp_otpc_packet {
struct list_head list;
u32 id;
u32 offset;
+ u32 tag;
};
static struct mchp_otpc_packet *mchp_otpc_id_to_packet(struct mchp_otpc *otpc,
@@ -70,6 +74,52 @@ static struct mchp_otpc_packet *mchp_otpc_id_to_packet(struct mchp_otpc *otpc,
return NULL;
}
+static struct mchp_otpc_packet *mchp_otpc_tag_to_packet(struct mchp_otpc *otpc, u32 tag)
+{
+ struct mchp_otpc_packet *packet;
+
+ list_for_each_entry(packet, &otpc->packets, list) {
+ if (packet->tag == tag)
+ return packet;
+ }
+
+ return NULL;
+}
+
+static bool mchp_otpc_is_valid_fourcc(u32 tag)
+{
+ int i;
+ u8 c;
+
+ for (i = 0; i < 4; i++) {
+ c = (tag >> (i * 8)) & 0xff;
+ if (c < 0x20 || c > 0x7e)
+ return false;
+ }
+
+ return true;
+}
+
+static struct mchp_otpc_packet *mchp_otpc_resolve_packet(struct mchp_otpc *otpc, u32 off)
+{
+ /*
+ * Legacy id based packet access: offset = id * 4
+ * Inside the driver we use continuous unsigned integer numbers
+ * for packet id, thus divide off by 4 before passing it to
+ * mchp_otpc_id_to_packet().
+ */
+ u32 remainder = off % 4;
+ u32 id = off / 4;
+
+ if (!remainder && id < otpc->npackets)
+ return mchp_otpc_id_to_packet(otpc, id);
+
+ /*
+ * TAG-based packet access: offset is a 4-byte ASCII tag (FourCC)
+ */
+ return mchp_otpc_tag_to_packet(otpc, off);
+}
+
static int mchp_otpc_prepare_read(struct mchp_otpc *otpc,
unsigned int offset)
{
@@ -140,8 +190,29 @@ static int mchp_otpc_prepare_read(struct mchp_otpc *otpc,
* offset returned by hardware.
*
* For this, the read function will return the first requested bytes in the
- * packet. The user will have to be aware of the memory footprint before doing
- * the read request.
+ * packet.
+ *
+ * Two offset encodings are supported:
+ *
+ * 1. Legacy ID-based: offset = OTP_PKT(id) = id * 4
+ * Used in DT as: reg = <OTP_PKT(1) 76>;
+ * 2. TAG-based: offset = 4-byte ASCII packet tag (FourCC)
+ * Used in DT as: reg = <0x41435354 0x4c>; (tag "ACST")
+ *
+ * To use the legacy ID based packet lookup the user will have to be aware of
+ * the memory footprint before doing the read request.
+ *
+ * But by using the TAG based packet lookup, the user won't have to be aware
+ * of the memory footprint before doing the read request since this driver has
+ * it abstracted and taken care of.
+ *
+ * Practically, there is no way of knowing the mapping of the OTP memory table
+ * in advance for every device. But by using the packet tag - the identifier
+ * ASCII value (FourCC), the packets can be recognized without being aware of the
+ * flashed OTP memory map table and the payload can be acquired reliably.
+ *
+ * While the legacy ID based lookup is still supported, TAG based approach is
+ * recommended.
*/
static int mchp_otpc_read(void *priv, unsigned int off, void *val,
size_t bytes)
@@ -154,12 +225,11 @@ static int mchp_otpc_read(void *priv, unsigned int off, void *val,
int ret, payload_size;
/*
- * We reach this point with off being multiple of stride = 4 to
- * be able to cross the subsystem. Inside the driver we use continuous
- * unsigned integer numbers for packet id, thus divide off by 4
- * before passing it to mchp_otpc_id_to_packet().
+ * From this point the offset has to be translated into the actual
+ * packet. For this we traverse the table of contents stored in a list
+ * "packet" based on the access type - packet id or tag.
*/
- packet = mchp_otpc_id_to_packet(otpc, off / 4);
+ packet = mchp_otpc_resolve_packet(otpc, off);
if (!packet)
return -EINVAL;
offset = packet->offset;
@@ -190,10 +260,25 @@ static int mchp_otpc_read(void *priv, unsigned int off, void *val,
return 0;
}
+static int mchp_otpc_read_packet_tag(struct mchp_otpc *otpc, unsigned int offset,
+ unsigned int *tag)
+{
+ int ret;
+
+ ret = mchp_otpc_prepare_read(otpc, offset);
+ if (ret)
+ return ret;
+
+ writel_relaxed(0, otpc->base + MCHP_OTPC_AR);
+ *tag = readl_relaxed(otpc->base + MCHP_OTPC_DR);
+
+ return 0;
+}
+
static int mchp_otpc_init_packets_list(struct mchp_otpc *otpc, u32 *size)
{
struct mchp_otpc_packet *packet;
- u32 word, word_pos = 0, id = 0, npackets = 0, payload_size;
+ u32 word, word_pos = 0, id = 0, npackets = 0, payload_size, type;
int ret;
INIT_LIST_HEAD(&otpc->packets);
@@ -215,6 +300,20 @@ static int mchp_otpc_init_packets_list(struct mchp_otpc *otpc, u32 *size)
packet->id = id++;
packet->offset = word_pos;
+ type = FIELD_GET(MCHP_OTPC_HR_PACKET, word);
+
+ if (type == MCHP_OTPC_HR_PACKET_REGULAR) {
+ ret = mchp_otpc_read_packet_tag(otpc, packet->offset,
+ &packet->tag);
+ if (ret)
+ return ret;
+
+ if (!mchp_otpc_is_valid_fourcc(packet->tag))
+ packet->tag = 0;
+ } else {
+ packet->tag = 0;
+ }
+
INIT_LIST_HEAD(&packet->list);
list_add_tail(&packet->list, &otpc->packets);
@@ -236,7 +335,7 @@ static struct nvmem_config mchp_nvmem_config = {
.type = NVMEM_TYPE_OTP,
.read_only = true,
.word_size = 4,
- .stride = 4,
+ .stride = 1,
.reg_read = mchp_otpc_read,
};
diff --git a/include/dt-bindings/nvmem/microchip,sama7g5-otpc.h b/include/dt-bindings/nvmem/microchip,sama7g5-otpc.h
index f570b23165a2..5f72e75ad091 100644
--- a/include/dt-bindings/nvmem/microchip,sama7g5-otpc.h
+++ b/include/dt-bindings/nvmem/microchip,sama7g5-otpc.h
@@ -4,8 +4,8 @@
#define _DT_BINDINGS_NVMEM_MICROCHIP_OTPC_H
/*
- * Need to have it as a multiple of 4 as NVMEM memory is registered with
- * stride = 4.
+ * Need to have it as a multiple of 4 for the legacy id based packet
+ * access.
*/
#define OTP_PKT(id) ((id) * 4)
--
2.34.1
next prev parent reply other threads:[~2026-07-27 12:28 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-27 12:26 [PATCH v4 00/16] Add thermal management support for sama7d65 Varshini Rajendran
2026-07-27 12:26 ` [PATCH v4 01/16] dt-bindings: iio: adc: at91-sama5d2: document sama7d65 Varshini Rajendran
2026-07-27 12:26 ` [PATCH v4 02/16] iio: adc: at91-sama5d2_adc: use cleanup.h for NVMEM buffer Varshini Rajendran
2026-07-27 12:36 ` sashiko-bot
2026-07-27 12:26 ` [PATCH v4 03/16] iio: adc: at91-sama5d2_adc: rework temp calibration layout handling Varshini Rajendran
2026-07-27 12:39 ` sashiko-bot
2026-07-27 12:26 ` [PATCH v4 04/16] iio: adc: at91-sama5d2_adc: add condition to validate calibration data Varshini Rajendran
2026-07-27 12:42 ` sashiko-bot
2026-07-27 12:26 ` [PATCH v4 05/16] iio: adc: at91-sama5d2_adc: remove unnecessary casts in of_device_id Varshini Rajendran
2026-07-27 12:26 ` [PATCH v4 06/16] iio: adc: at91-sama5d2_adc: adapt the driver for sama7d65 Varshini Rajendran
2026-07-27 12:41 ` sashiko-bot
2026-07-27 12:26 ` [PATCH v4 07/16] dt-bindings: nvmem: microchip,sama7g5-otpc: add sama7d65 and dt node example Varshini Rajendran
2026-07-27 12:41 ` sashiko-bot
2026-07-27 12:26 ` Varshini Rajendran [this message]
2026-07-27 12:44 ` [PATCH v4 08/16] nvmem: microchip-otpc: nvmem: microchip-otpc: add tag-based packet lookup sashiko-bot
2026-07-27 12:26 ` [PATCH v4 09/16] nvmem: microchip-otpc: nvmem: add emulation mode and OTP access validation Varshini Rajendran
2026-07-27 12:39 ` sashiko-bot
2026-07-27 12:26 ` [PATCH v4 10/16] ARM: dts: microchip: sama7d65: add cpu opps Varshini Rajendran
2026-07-27 12:26 ` [PATCH v4 11/16] ARM: dts: microchip: sama7d65: Add ADC node Varshini Rajendran
2026-07-27 12:26 ` [PATCH v4 12/16] ARM: dts: microchip: sama7d65_curiosity: Enable ADC, DVFS Varshini Rajendran
2026-07-27 12:26 ` [PATCH v4 13/16] ARM: dts: microchip: sama7d65: add otpc node Varshini Rajendran
2026-07-27 12:44 ` sashiko-bot
2026-07-27 12:26 ` [PATCH v4 14/16] ARM: dts: microchip: sama7d65: add cells for temperature calibration Varshini Rajendran
2026-07-27 12:50 ` sashiko-bot
2026-07-27 12:26 ` [PATCH v4 15/16] ARM: dts: microchip: sama7d65: add temperature sensor Varshini Rajendran
2026-07-27 12:45 ` sashiko-bot
2026-07-27 12:26 ` [PATCH v4 16/16] ARM: dts: microchip: sama7d65: add thermal zones node Varshini Rajendran
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260727122633.117435-9-varshini.rajendran@microchip.com \
--to=varshini.rajendran@microchip.com \
--cc=Jonathan.Santos@analog.com \
--cc=alexandre.belloni@bootlin.com \
--cc=andy@kernel.org \
--cc=antoniu.miclaus@analog.com \
--cc=claudiu.beznea@tuxon.dev \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dlechner@baylibre.com \
--cc=ehristev@kernel.org \
--cc=jic23@kernel.org \
--cc=jishnu.prakash@oss.qualcomm.com \
--cc=jorge.marques@analog.com \
--cc=joshua.crofts1@gmail.com \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=marcelo.schmitt@analog.com \
--cc=mazziesaccount@gmail.com \
--cc=nicolas.ferre@microchip.com \
--cc=nuno.sa@analog.com \
--cc=radu.sabau@analog.com \
--cc=robh@kernel.org \
--cc=srini@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox