drivers/mtd/nand/spi/winbond.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/spi/winbond.c
Extension
.c
Size
26974 bytes
Lines
815
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) 2017 exceet electronics GmbH
 *
 * Authors:
 *	Frieder Schrempf <frieder.schrempf@exceet.de>
 *	Boris Brezillon <boris.brezillon@bootlin.com>
 */

#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/mtd/spinand.h>
#include <linux/units.h>
#include <linux/delay.h>

#define SPINAND_MFR_WINBOND		0xEF

#define WINBOND_CFG_HFREQ		BIT(0)
#define WINBOND_CFG_BUF_READ		BIT(3)

#define W25N04KV_STATUS_ECC_5_8_BITFLIPS	(3 << 4)
#define W25W35NXXJW_STATUS_ECC_MULT_UNCOR	(3 << 4)

#define W25N0XJW_SR4			0xD0
#define W25N0XJW_SR4_HS			BIT(2)

#define W35N01JW_VCR_IO_MODE_REG	0x00
#define W35N01JW_VCR_IO_MODE_SINGLE_SDR		0xFF
#define W35N01JW_VCR_IO_MODE_OCTAL_SDR		0xDF
#define W35N01JW_VCR_IO_MODE_OCTAL_DDR_DS	0xE7
#define W35N01JW_VCR_IO_MODE_OCTAL_DDR		0xC7
#define W35N01JW_VCR_DUMMY_CLOCK_REG	0x01

/*
 * Winbond chips ignore the address bytes during continuous reads, and
 * because the dummy cycles are enough they indicate dropping the
 * address cycles from the continuous read from cache variants. This is
 * very poorly supported by SPI controller drivers which are "wired" to
 * always at least provide the column. Keep using address cycles, but
 * reduce the number of dummy cycles accordingly.
 */
#define WINBOND_CONT_READ_FROM_CACHE_FAST_1S_1S_1S_OP(ndummy, buf, len, freq) \
	SPI_MEM_OP(SPI_MEM_OP_CMD(0x0b, 1),				\
		   SPI_MEM_OP_ADDR(1, 0, 1),				\
		   SPI_MEM_OP_DUMMY(ndummy - 1, 1),			\
		   SPI_MEM_OP_DATA_IN(len, buf, 1),			\
		   SPI_MEM_OP_MAX_FREQ(freq))

#define WINBOND_CONT_READ_FROM_CACHE_1S_1D_1D_OP(ndummy, buf, len, freq) \
	SPI_MEM_OP(SPI_MEM_OP_CMD(0x0d, 1),				\
		   SPI_MEM_DTR_OP_ADDR(2, 0, 1),			\
		   SPI_MEM_DTR_OP_DUMMY(ndummy, 1),			\
		   SPI_MEM_DTR_OP_DATA_IN(len, buf, 1),			\
		   SPI_MEM_OP_MAX_FREQ(freq))

#define WINBOND_CONT_READ_FROM_CACHE_1S_1S_2S_OP(ndummy, buf, len, freq) \
	SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1),				\
		   SPI_MEM_OP_ADDR(1, 0, 1),				\
		   SPI_MEM_OP_DUMMY(ndummy - 1, 1),			\
		   SPI_MEM_OP_DATA_IN(len, buf, 2),			\
		   SPI_MEM_OP_MAX_FREQ(freq))

#define WINBOND_CONT_READ_FROM_CACHE_1S_2S_2S_OP(ndummy, buf, len, freq) \
	SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1),				\
		   SPI_MEM_OP_ADDR(1, 0, 2),				\
		   SPI_MEM_OP_DUMMY(ndummy - 1, 2),			\
		   SPI_MEM_OP_DATA_IN(len, buf, 2),			\
		   SPI_MEM_OP_MAX_FREQ(freq))

#define WINBOND_CONT_READ_FROM_CACHE_1S_2D_2D_OP(ndummy, buf, len, freq) \
	SPI_MEM_OP(SPI_MEM_OP_CMD(0xbd, 1),				\
		   SPI_MEM_DTR_OP_ADDR(1, 0, 2),			\
		   SPI_MEM_DTR_OP_DUMMY(ndummy - 1, 2),			\
		   SPI_MEM_DTR_OP_DATA_IN(len, buf, 2),			\
		   SPI_MEM_OP_MAX_FREQ(freq))

#define WINBOND_CONT_READ_FROM_CACHE_1S_1S_4S_OP(ndummy, buf, len, freq) \
	SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1),				\
		   SPI_MEM_OP_ADDR(1, 0, 1),				\
		   SPI_MEM_OP_DUMMY(ndummy - 1, 1),			\
		   SPI_MEM_OP_DATA_IN(len, buf, 4),			\
		   SPI_MEM_OP_MAX_FREQ(freq))

#define WINBOND_CONT_READ_FROM_CACHE_1S_1D_4D_OP(ndummy, buf, len, freq) \
	SPI_MEM_OP(SPI_MEM_OP_CMD(0x6d, 1),				\
		   SPI_MEM_DTR_OP_ADDR(1, 0, 1),			\
		   SPI_MEM_DTR_OP_DUMMY(ndummy - 1, 1),			\
		   SPI_MEM_DTR_OP_DATA_IN(len, buf, 4),			\
		   SPI_MEM_OP_MAX_FREQ(freq))

Annotation

Implementation Notes