drivers/mtd/spi-nor/swp.c

Source file repositories/reference/linux-study-clean/drivers/mtd/spi-nor/swp.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/spi-nor/swp.c
Extension
.c
Size
18296 bytes
Lines
654
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

if (!cmp) {
			/* No protection */
			*ofs = 0;
			*len = 0;
		} else {
			/* Full protection */
			*ofs = 0;
			*len = nor->params->size;
		}
		return;
	}

	min_prot_len = spi_nor_get_min_prot_length_sr(nor);
	*len = min_prot_len << (bp - 1);
	if (*len > nor->params->size)
		*len = nor->params->size;

	if (cmp)
		*len = nor->params->size - *len;

	if (!cmp) {
		if (tb)
			*ofs = 0;
		else
			*ofs = nor->params->size - *len;
	} else {
		if (tb)
			*ofs = nor->params->size - *len;
		else
			*ofs = 0;
	}
}

/*
 * Return true if the entire region is locked (if @locked is true) or unlocked
 * (if @locked is false); false otherwise.
 */
static bool spi_nor_check_lock_status_sr(struct spi_nor *nor, loff_t ofs,
					 u64 len, const u8 *sr, bool locked)
{
	loff_t lock_offs, lock_offs_max, offs_max;
	u64 lock_len;

	if (!len)
		return true;

	spi_nor_get_locked_range_sr(nor, sr, &lock_offs, &lock_len);

	lock_offs_max = lock_offs + lock_len;
	offs_max = ofs + len;

	if (locked)
		/* Requested range is a sub-range of locked range */
		return (offs_max <= lock_offs_max) && (ofs >= lock_offs);
	else
		/* Requested range does not overlap with locked range */
		return (ofs >= lock_offs_max) || (offs_max <= lock_offs);
}

bool spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, u64 len, const u8 *sr)
{
	return spi_nor_check_lock_status_sr(nor, ofs, len, sr, true);
}

static bool spi_nor_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, u64 len,
				   const u8 *sr)
{
	return spi_nor_check_lock_status_sr(nor, ofs, len, sr, false);
}

static int spi_nor_sr_set_bp_mask(struct spi_nor *nor, u8 *sr, u8 pow)
{
	u8 mask = spi_nor_get_sr_bp_mask(nor);
	u8 val = pow << SR_BP_SHIFT;

	if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3)
		val = (val & ~SR_BP3) | SR_BP3_BIT6;

	if (val & ~mask)
		return -EINVAL;

	sr[0] |= val;

	return 0;
}

static int spi_nor_build_sr(struct spi_nor *nor, const u8 *old_sr, u8 *new_sr,
			    u8 pow, bool use_top, bool cmp)
{
	u8 bp_mask = spi_nor_get_sr_bp_mask(nor);

Annotation

Implementation Notes