Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Claudiu Beznea <claudiu.beznea@tuxon.dev>
To: Varshini Rajendran <varshini.rajendran@microchip.com>,
	eugen.hristev@linaro.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,
	srini@kernel.org, linux-iio@vger.kernel.org,
	devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH 02/15] nvmem: microchip-otpc: rework to access packets based on tag
Date: Sun, 14 Sep 2025 18:42:43 +0300	[thread overview]
Message-ID: <3a3a3e2c-2156-40bb-9233-fc2e6320eaa6@tuxon.dev> (raw)
In-Reply-To: <20250804100219.63325-3-varshini.rajendran@microchip.com>

Hi, Varshini,

On 8/4/25 13:02, Varshini Rajendran wrote:
> Rework the driver to change the packet access technique based on the TAG
> instead of the currently in use "id".
> 
> Since there is no way of knowing the OTP memory mapping in advance or the
> changes it can go through with time, the id based approach is not reliable.
> Accessing the packets based on the associated tags is a fail-proof
> approach. This method is aided by adding a table of contents to store the
> payload information which makes it easier to traverse through the OTP
> memory and read the data of the intended packet. The stride of the nvmem
> device is adjusted to 1 to support the TAG being treated as an offset.
> The only reliable way to recognize a packet without being aware of the
> flashed contents of the OTP memory is the TAG of the packet.
> 
> Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
> ---
>  drivers/nvmem/microchip-otpc.c | 130 +++++++++++++++++++++++++--------
>  1 file changed, 101 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/nvmem/microchip-otpc.c b/drivers/nvmem/microchip-otpc.c
> index df979e8549fd..e922c882af72 100644
> --- a/drivers/nvmem/microchip-otpc.c
> +++ b/drivers/nvmem/microchip-otpc.c
> @@ -18,16 +18,27 @@
>  #define MCHP_OTPC_CR_READ		BIT(6)
>  #define MCHP_OTPC_MR			(0x4)
>  #define MCHP_OTPC_MR_ADDR		GENMASK(31, 16)
> +#define MCHP_OTPC_MR_EMUL		BIT(7)
>  #define MCHP_OTPC_AR			(0x8)
>  #define MCHP_OTPC_SR			(0xc)
>  #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_TYPE	GENMASK(2, 0)
>  #define MCHP_OTPC_DR			(0x24)
>  
>  #define MCHP_OTPC_NAME			"mchp-otpc"
>  #define MCHP_OTPC_SIZE			(11 * 1024)
>  
> +enum packet_type {
> +	PACKET_TYPE_REGULAR = 1,
> +	PACKET_TYPE_KEY	= 2,
> +	PACKET_TYPE_BOOT_CONFIG = 3,
> +	PACKET_TYPE_SECURE_BOOT_CONFIG = 4,
> +	PACKET_TYPE_HARDWARE_CONFIG = 5,
> +	PACKET_TYPE_CUSTOM = 6,

You can drop unused packet types.

> +};
> +
>  /**
>   * struct mchp_otpc - OTPC private data structure
>   * @base: base address
> @@ -42,6 +53,25 @@ struct mchp_otpc {
>  	u32 npackets;
>  };
>  
> +/**
> + * struct mchp_otpc_payload_info - OTP packet's payload information
> + *				retrieved from the packet's header
> + * @id: driver assigned packet ID
> + * @packet_offset: offset address of the packet to be written in the
> + *			register OTPC_MR.ADDR to access the packet
> + * @payload_length: length of the packet's payload
> + * @packet_type: type of the packet
> + * @packet_tag: TAG corresponding to the packet. Applicable for most
> + *		of the regular packets
> + */
> +struct mchp_otpc_payload_info {
> +	u32 id;
> +	u32 packet_offset;

Can you keep packet specific members in struct mchp_otpc_packet?

> +	u32 payload_length;
> +	u32 packet_type;
> +	u32 packet_tag;

Will this technique limit the number of packets that can be in memory? I
think this is not an issue with the current devices? What about the upcomming?

> +};
> +
>  /**
>   * struct mchp_otpc_packet - OTPC packet data structure
>   * @list: list head
> @@ -50,20 +80,16 @@ struct mchp_otpc {
>   */
>  struct mchp_otpc_packet {
>  	struct list_head list;
> -	u32 id;
> -	u32 offset;
> +	struct mchp_otpc_payload_info payload_info;

Warning: ../drivers/nvmem/microchip-otpc.c:83 struct member 'payload_info'
not described in 'mchp_otpc_packet'

>  };
>  
> -static struct mchp_otpc_packet *mchp_otpc_id_to_packet(struct mchp_otpc *otpc,
> -						       u32 id)
> +static struct mchp_otpc_packet *mchp_otpc_tag_to_packet(struct mchp_otpc *otpc,
> +							u32 tag)
>  {
>  	struct mchp_otpc_packet *packet;
>  
> -	if (id >= otpc->npackets)
> -		return NULL;
> -
>  	list_for_each_entry(packet, &otpc->packets, list) {
> -		if (packet->id == id)
> +		if (packet->payload_info.packet_tag == tag)
>  			return packet;
>  	}
>  
> @@ -140,8 +166,27 @@ 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. The user won't have to be aware of the memory footprint before doing
> + * the read request since it is abstracted and taken care by this driver.
> + *
> + * There is no way of knowing the Mapping of the OTP memory table in advance. In
> + * this read function the offset requested is treated as the identifier string
> + * i.e., Packet TAG, to acquire the payload with reliability. The packet Tag
> + * is the only way to recognize a packet without being aware of the flashed
> + * OTP memory map table.
> + */
> +
> +/**
> + * mchp_otpc_read() - Read the OTP packets and fill the buffer based on the TAG
> + *		      of the packet treated as the offset.
> + * @priv: Pointer to device structure.
> + * @off: offset of the OTP packet to be read. In this case, the TAG of the
> + *	 corresponding packet.
> + * @val: Pointer to data buffer
> + * @bytes: length of the buffer
> + *
> + * A value of zero will be returned on success, a negative errno will be
> + * returned in error cases.
>   */
>  static int mchp_otpc_read(void *priv, unsigned int off, void *val,
>  			  size_t bytes)
> @@ -154,30 +199,23 @@ 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 packet tag received as the offset has to be translated
> +	 * into the actual packet. For this we traverse the table of contents stored
> +	 * in a list "packet" and look for the tag.
>  	 */
> -	packet = mchp_otpc_id_to_packet(otpc, off / 4);
> +
> +	packet = mchp_otpc_tag_to_packet(otpc, off);
>  	if (!packet)
>  		return -EINVAL;

If one would want to read the full content of the memory will this function
return first time offset will not corresond to a valid packet?

> -	offset = packet->offset;
> +	offset = packet->payload_info.packet_offset;
>  
> -	while (len < bytes) {
> +	if (len < bytes) {

The approach now is that a single packet can be read at a moment, right? Is
this intended?

>  		ret = mchp_otpc_prepare_read(otpc, offset);
>  		if (ret)
>  			return ret;
>  
> -		/* Read and save header content. */
> -		*buf++ = readl_relaxed(otpc->base + MCHP_OTPC_HR);
> -		len += sizeof(*buf);
> -		offset++;
> -		if (len >= bytes)
> -			break;
> -

Dropping this will not return the header content anymore. Is this intended?

>  		/* Read and save payload content. */
> -		payload_size = FIELD_GET(MCHP_OTPC_HR_SIZE, *(buf - 1));
> +		payload_size = packet->payload_info.payload_length;
>  		writel_relaxed(0UL, otpc->base + MCHP_OTPC_AR);
>  		do {
>  			*buf++ = readl_relaxed(otpc->base + MCHP_OTPC_DR);
> @@ -190,6 +228,20 @@ 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 *val)

This exceeed 100 chars.

> +{
> +	int ret;
> +
> +	ret = mchp_otpc_prepare_read(otpc, offset);
> +	if (ret)
> +		return ret;
> +
> +	writel_relaxed(0UL, otpc->base + MCHP_OTPC_AR);
> +	*val = 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;
> @@ -213,8 +265,15 @@ static int mchp_otpc_init_packets_list(struct mchp_otpc *otpc, u32 *size)
>  		if (!packet)
>  			return -ENOMEM;
>  
> -		packet->id = id++;
> -		packet->offset = word_pos;
> +		packet->payload_info.id = id++;
> +		packet->payload_info.packet_offset = word_pos;
> +		packet->payload_info.payload_length = payload_size;
> +		packet->payload_info.packet_type = FIELD_GET(MCHP_OTPC_HR_PACKET_TYPE, word);
> +
> +		if (packet->payload_info.packet_type == PACKET_TYPE_REGULAR)
> +			ret = mchp_otpc_read_packet_tag(otpc, packet->payload_info.packet_offset,
> +							&packet->payload_info.packet_tag);
> +
>  		INIT_LIST_HEAD(&packet->list);
>  		list_add_tail(&packet->list, &otpc->packets);
>  
> @@ -236,7 +295,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,
>  };
>  
> @@ -244,8 +303,9 @@ static int mchp_otpc_probe(struct platform_device *pdev)
>  {
>  	struct nvmem_device *nvmem;
>  	struct mchp_otpc *otpc;
> -	u32 size;
> +	u32 size, tmp;
>  	int ret;
> +	bool emul_enable;
>  
>  	otpc = devm_kzalloc(&pdev->dev, sizeof(*otpc), GFP_KERNEL);
>  	if (!otpc)
> @@ -256,10 +316,22 @@ static int mchp_otpc_probe(struct platform_device *pdev)
>  		return PTR_ERR(otpc->base);
>  
>  	otpc->dev = &pdev->dev;
> +
> +	tmp = readl_relaxed(otpc->base + MCHP_OTPC_MR);
> +	emul_enable = tmp & MCHP_OTPC_MR_EMUL;
> +	if (emul_enable)
> +		dev_info(otpc->dev, "Emulation mode enabled\n");

Can you update the commit with the meaning of these?

> +
>  	ret = mchp_otpc_init_packets_list(otpc, &size);
>  	if (ret)
>  		return ret;
>  
> +	if (size == 0) {
> +		dev_err(otpc->dev, "Cannot access OTP memory !\n");

Space before !

> +		if (!emul_enable)
> +			dev_err(otpc->dev, "Boot packet not configured & Emulation mode not enabled !\n");

Do you still want to register the driver in case size == 0?

Thank you,
Claudiu

> +	}
> +
>  	mchp_nvmem_config.dev = otpc->dev;
>  	mchp_nvmem_config.add_legacy_fixed_of_cells = true;
>  	mchp_nvmem_config.size = size;



  parent reply	other threads:[~2025-09-14 15:42 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-04 10:02 [PATCH 00/15] Add thermal management support for sama7d65 Varshini Rajendran
2025-08-04 10:02 ` [PATCH 01/15] ARM: dts: microchip: sama7d65: add cpu opps Varshini Rajendran
2025-08-04 10:02 ` [PATCH 02/15] nvmem: microchip-otpc: rework to access packets based on tag Varshini Rajendran
2025-08-04 13:05   ` Andy Shevchenko
2025-08-04 17:49   ` kernel test robot
2025-08-05  6:50   ` Krzysztof Kozlowski
2025-09-14 15:42   ` Claudiu Beznea [this message]
2025-08-04 10:02 ` [PATCH 03/15] dt-bindings: microchip-otpc: update dt node example Varshini Rajendran
2025-08-05  6:49   ` Krzysztof Kozlowski
2025-08-04 10:02 ` [PATCH 04/15] iio: adc: at91-sama5d2_adc: update calibration index, validation condition Varshini Rajendran
2025-08-04 13:11   ` Andy Shevchenko
2025-08-06 15:26   ` Jonathan Cameron
2025-09-14 15:43   ` Claudiu Beznea
2025-08-04 10:02 ` [PATCH 05/15] ARM: dts: microchip: sama7g5: add packet tag as offset for calib Varshini Rajendran
2025-08-05  6:51   ` Krzysztof Kozlowski
2025-08-04 10:02 ` [PATCH 06/15] dt-bindings: nvmem: microchip-otpc: remove stride details Varshini Rajendran
2025-08-05  6:54   ` Krzysztof Kozlowski
2025-08-04 10:02 ` [PATCH 07/15] iio: adc: at91-sama5d2_adc: add temp init function as callback Varshini Rajendran
2025-08-04 13:13   ` Andy Shevchenko
2025-08-04 10:02 ` [PATCH 08/15] dt-bindings: iio: adc: at91-sama5d2: document sama7d65 Varshini Rajendran
2025-08-05  6:55   ` Krzysztof Kozlowski
2025-08-04 10:02 ` [PATCH 09/15] iio: adc: at91-sama5d2_adc: adapt the driver for sama7d65 Varshini Rajendran
2025-08-04 13:19   ` Andy Shevchenko
2025-08-06 15:31   ` Jonathan Cameron
2025-08-04 10:02 ` [PATCH 10/15] ARM: dts: microchip: sama7d65: add node for the ADC Varshini Rajendran
2025-08-04 10:02 ` [PATCH 11/15] dt-bindings: microchip-otpc: document sama7d65 Varshini Rajendran
2025-08-05  6:53   ` Krzysztof Kozlowski
2025-08-04 10:02 ` [PATCH 12/15] ARM: dts: microchip: sama7d65: add otpc node Varshini Rajendran
2025-08-04 10:02 ` [PATCH 13/15] ARM: dts: microchip: sama7d65: add cells for temperature calibration Varshini Rajendran
2025-08-04 10:02 ` [PATCH 14/15] ARM: dts: microchip: sama7d65: add temperature sensor Varshini Rajendran
2025-08-04 10:02 ` [PATCH 15/15] 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=3a3a3e2c-2156-40bb-9233-fc2e6320eaa6@tuxon.dev \
    --to=claudiu.beznea@tuxon.dev \
    --cc=alexandre.belloni@bootlin.com \
    --cc=andy@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dlechner@baylibre.com \
    --cc=eugen.hristev@linaro.org \
    --cc=jic23@kernel.org \
    --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=nicolas.ferre@microchip.com \
    --cc=nuno.sa@analog.com \
    --cc=robh@kernel.org \
    --cc=srini@kernel.org \
    --cc=varshini.rajendran@microchip.com \
    /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