drivers/mtd/spi-nor/winbond.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mtd/spi-nor/winbond.c
Extension
.c
Size
14171 bytes
Lines
506
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) 2005, Intec Automation Inc.
 * Copyright (C) 2014, Freescale Semiconductor, Inc.
 */

#include <linux/mtd/spi-nor.h>

#include "core.h"

#define WINBOND_NOR_OP_RDEAR	0xc8	/* Read Extended Address Register */
#define WINBOND_NOR_OP_WREAR	0xc5	/* Write Extended Address Register */
#define WINBOND_NOR_OP_SELDIE	0xc2	/* Select active die */

#define WINBOND_NOR_WREAR_OP(buf)					\
	SPI_MEM_OP(SPI_MEM_OP_CMD(WINBOND_NOR_OP_WREAR, 0),		\
		   SPI_MEM_OP_NO_ADDR,					\
		   SPI_MEM_OP_NO_DUMMY,					\
		   SPI_MEM_OP_DATA_OUT(1, buf, 0))

#define WINBOND_NOR_SELDIE_OP(buf)					\
	SPI_MEM_OP(SPI_MEM_OP_CMD(WINBOND_NOR_OP_SELDIE, 0),		\
		   SPI_MEM_OP_NO_ADDR,					\
		   SPI_MEM_OP_NO_DUMMY,					\
		   SPI_MEM_OP_DATA_OUT(1, buf, 0))

static int
w25q128_post_bfpt_fixups(struct spi_nor *nor,
			 const struct sfdp_parameter_header *bfpt_header,
			 const struct sfdp_bfpt *bfpt)
{
	/*
	 * Zetta ZD25Q128C is a clone of the Winbond device. But the encoded
	 * size is really wrong. It seems that they confused Mbit with MiB.
	 * Thus the flash is discovered as a 2MiB device.
	 */
	if (bfpt_header->major == SFDP_JESD216_MAJOR &&
	    bfpt_header->minor == SFDP_JESD216_MINOR &&
	    nor->params->size == SZ_2M &&
	    nor->params->erase_map.regions[0].size == SZ_2M) {
		nor->params->size = SZ_16M;
		nor->params->erase_map.regions[0].size = SZ_16M;
	}

	return 0;
}

static const struct spi_nor_fixups w25q128_fixups = {
	.post_bfpt = w25q128_post_bfpt_fixups,
};

static int
w25q256_post_bfpt_fixups(struct spi_nor *nor,
			 const struct sfdp_parameter_header *bfpt_header,
			 const struct sfdp_bfpt *bfpt)
{
	/*
	 * W25Q256JV supports 4B opcodes but W25Q256FV does not.
	 * Unfortunately, Winbond has re-used the same JEDEC ID for both
	 * variants which prevents us from defining a new entry in the parts
	 * table.
	 * To differentiate between W25Q256JV and W25Q256FV check SFDP header
	 * version: only JV has JESD216A compliant structure (version 5).
	 */
	if (bfpt_header->major == SFDP_JESD216_MAJOR &&
	    bfpt_header->minor == SFDP_JESD216A_MINOR)
		nor->flags |= SNOR_F_4B_OPCODES;

	return 0;
}

static const struct spi_nor_fixups w25q256_fixups = {
	.post_bfpt = w25q256_post_bfpt_fixups,
};

static int
winbond_rdcr_post_bfpt_fixup(struct spi_nor *nor,
			     const struct sfdp_parameter_header *bfpt_header,
			     const struct sfdp_bfpt *bfpt)
{
	/*
	 * W25H02NW, unlike its W25H512NW nor W25H01NW cousins, improperly sets
	 * the QE BFPT configuration bits, indicating a non readable CR. This is
	 * both incorrect and impractical, as the chip features a CMP bit for its
	 * locking scheme that lays in the Control Register, and needs to be read.
	 */
	nor->flags &= ~SNOR_F_NO_READ_CR;

	return 0;
}

Annotation

Implementation Notes