drivers/mtd/nand/spi/otp.c

Source file repositories/reference/linux-study-clean/drivers/mtd/nand/spi/otp.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/spi/otp.c
Extension
.c
Size
8901 bytes
Lines
363
Domain
Driver Families
Bucket
drivers/mtd
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2025, SaluteDevices. All Rights Reserved.
 *
 * Author: Martin Kurbanov <mmkurbanov@salutedevices.com>
 */

#include <linux/mtd/mtd.h>
#include <linux/mtd/spinand.h>

/**
 * spinand_otp_page_size() - Get SPI-NAND OTP page size
 * @spinand: the spinand device
 *
 * Return: the OTP page size.
 */
size_t spinand_otp_page_size(struct spinand_device *spinand)
{
	struct nand_device *nand = spinand_to_nand(spinand);

	return nanddev_page_size(nand) + nanddev_per_page_oobsize(nand);
}

static size_t spinand_otp_size(struct spinand_device *spinand,
			       const struct spinand_otp_layout *layout)
{
	return layout->npages * spinand_otp_page_size(spinand);
}

/**
 * spinand_fact_otp_size() - Get SPI-NAND factory OTP area size
 * @spinand: the spinand device
 *
 * Return: the OTP size.
 */
size_t spinand_fact_otp_size(struct spinand_device *spinand)
{
	return spinand_otp_size(spinand, &spinand->fact_otp->layout);
}

/**
 * spinand_user_otp_size() - Get SPI-NAND user OTP area size
 * @spinand: the spinand device
 *
 * Return: the OTP size.
 */
size_t spinand_user_otp_size(struct spinand_device *spinand)
{
	return spinand_otp_size(spinand, &spinand->user_otp->layout);
}

static int spinand_otp_check_bounds(struct spinand_device *spinand, loff_t ofs,
				    size_t len,
				    const struct spinand_otp_layout *layout)
{
	if (ofs < 0 || ofs + len > spinand_otp_size(spinand, layout))
		return -EINVAL;

	return 0;
}

static int spinand_user_otp_check_bounds(struct spinand_device *spinand,
					 loff_t ofs, size_t len)
{
	return spinand_otp_check_bounds(spinand, ofs, len,
					&spinand->user_otp->layout);
}

static int spinand_otp_rw(struct spinand_device *spinand, loff_t ofs,
			  size_t len, size_t *retlen, u8 *buf, bool is_write,
			  const struct spinand_otp_layout *layout)
{
	struct nand_page_io_req req = {};
	unsigned long long page;
	size_t copied = 0;
	size_t otp_pagesize = spinand_otp_page_size(spinand);
	int ret;

	if (!len)
		return 0;

	ret = spinand_otp_check_bounds(spinand, ofs, len, layout);
	if (ret)
		return ret;

	ret = spinand_upd_cfg(spinand, CFG_OTP_ENABLE, CFG_OTP_ENABLE);
	if (ret)
		return ret;

	page = ofs;

Annotation

Implementation Notes