Commit 3f554003 authored by Richard Weinberger's avatar Richard Weinberger

Merge tag 'spi-nor/for-5.8' of...

Merge tag 'spi-nor/for-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux into mtd/next

SPI NOR core changes:
- add, update support and fix few flashes
- prepare BFPT parsing for JESD216 rev D
- kernel doc fixes
parents a8dfb61d e8aec15d
# SPDX-License-Identifier: GPL-2.0-only
menuconfig MTD_SPI_NOR
tristate "SPI-NOR device support"
tristate "SPI NOR device support"
depends on MTD
depends on MTD && SPI_MASTER
select SPI_MEM
help
This is the framework for the SPI NOR which can be used by the SPI
device drivers and the SPI-NOR device driver.
device drivers and the SPI NOR device driver.
if MTD_SPI_NOR
......
......@@ -21,11 +21,11 @@ config SPI_CADENCE_QUADSPI
Flash as an MTD device.
config SPI_HISI_SFC
tristate "Hisilicon FMC SPI-NOR Flash Controller(SFC)"
tristate "Hisilicon FMC SPI NOR Flash Controller(SFC)"
depends on ARCH_HISI || COMPILE_TEST
depends on HAS_IOMEM
help
This enables support for HiSilicon FMC SPI-NOR flash controller.
This enables support for HiSilicon FMC SPI NOR flash controller.
config SPI_NXP_SPIFI
tristate "NXP SPI Flash Interface (SPIFI)"
......
......@@ -727,7 +727,7 @@ static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip)
/*
* TODO: Adjust clocks if fast read is supported and interpret
* SPI-NOR flags to adjust controller settings.
* SPI NOR flags to adjust controller settings.
*/
if (chip->nor.read_proto == SNOR_PROTO_1_1_1) {
if (chip->nor.read_dummy == 0)
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* HiSilicon FMC SPI-NOR flash controller driver
* HiSilicon FMC SPI NOR flash controller driver
*
* Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd.
*/
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* SPI-NOR driver for NXP SPI Flash Interface (SPIFI)
* SPI NOR driver for NXP SPI Flash Interface (SPIFI)
*
* Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
*
......
......@@ -499,7 +499,7 @@ int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr)
* the flash is ready for new commands.
* @nor: pointer to 'struct spi_nor'.
*
* Return: 0 on success, -errno otherwise.
* Return: 1 if ready, 0 if not ready, -errno on errors.
*/
static int spi_nor_xsr_ready(struct spi_nor *nor)
{
......@@ -542,7 +542,7 @@ static void spi_nor_clear_sr(struct spi_nor *nor)
* for new commands.
* @nor: pointer to 'struct spi_nor'.
*
* Return: 0 on success, -errno otherwise.
* Return: 1 if ready, 0 if not ready, -errno on errors.
*/
static int spi_nor_sr_ready(struct spi_nor *nor)
{
......@@ -606,7 +606,7 @@ static void spi_nor_clear_fsr(struct spi_nor *nor)
* ready for new commands.
* @nor: pointer to 'struct spi_nor'.
*
* Return: 0 on success, -errno otherwise.
* Return: 1 if ready, 0 if not ready, -errno on errors.
*/
static int spi_nor_fsr_ready(struct spi_nor *nor)
{
......@@ -640,14 +640,14 @@ static int spi_nor_fsr_ready(struct spi_nor *nor)
return -EIO;
}
return nor->bouncebuf[0] & FSR_READY;
return !!(nor->bouncebuf[0] & FSR_READY);
}
/**
* spi_nor_ready() - Query the flash to see if it is ready for new commands.
* @nor: pointer to 'struct spi_nor'.
*
* Return: 0 on success, -errno otherwise.
* Return: 1 if ready, 0 if not ready, -errno on errors.
*/
static int spi_nor_ready(struct spi_nor *nor)
{
......@@ -2469,7 +2469,7 @@ static int spi_nor_select_read(struct spi_nor *nor,
nor->read_proto = read->proto;
/*
* In the spi-nor framework, we don't need to make the difference
* In the SPI NOR framework, we don't need to make the difference
* between mode clock cycles and wait state clock cycles.
* Indeed, the value of the mode clock cycles is used by a QSPI
* flash memory to know whether it should enter or leave its 0-4-4
......@@ -2675,7 +2675,7 @@ static int spi_nor_setup(struct spi_nor *nor,
/**
* spi_nor_manufacturer_init_params() - Initialize the flash's parameters and
* settings based on MFR register and ->default_init() hook.
* @nor: pointer to a 'struct spi-nor'.
* @nor: pointer to a 'struct spi_nor'.
*/
static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
{
......@@ -2690,7 +2690,7 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
/**
* spi_nor_sfdp_init_params() - Initialize the flash's parameters and settings
* based on JESD216 SFDP standard.
* @nor: pointer to a 'struct spi-nor'.
* @nor: pointer to a 'struct spi_nor'.
*
* The method has a roll-back mechanism: in case the SFDP parsing fails, the
* legacy flash parameters and settings will be restored.
......@@ -2712,7 +2712,7 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
/**
* spi_nor_info_init_params() - Initialize the flash's parameters and settings
* based on nor->info data.
* @nor: pointer to a 'struct spi-nor'.
* @nor: pointer to a 'struct spi_nor'.
*/
static void spi_nor_info_init_params(struct spi_nor *nor)
{
......@@ -2841,7 +2841,7 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
/**
* spi_nor_init_params() - Initialize the flash's parameters and settings.
* @nor: pointer to a 'struct spi-nor'.
* @nor: pointer to a 'struct spi_nor'.
*
* The flash parameters and settings are initialized based on a sequence of
* calls that are ordered by priority:
......@@ -3126,7 +3126,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
/*
* Make sure the XSR_RDY flag is set before calling
* spi_nor_wait_till_ready(). Xilinx S3AN share MFR
* with Atmel spi-nor
* with Atmel SPI NOR.
*/
if (info->flags & SPI_NOR_XSR_RDY)
nor->flags |= SNOR_F_READY_XSR_RDY;
......
......@@ -63,10 +63,16 @@ static const struct flash_info macronix_parts[] = {
.fixups = &mx25l25635_fixups },
{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512,
SECT_4K | SPI_NOR_4B_OPCODES) },
{ "mx25u51245g", INFO(0xc2253a, 0, 64 * 1024, 1024,
SECT_4K | SPI_NOR_DUAL_READ |
SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
{ "mx25v8035f", INFO(0xc22314, 0, 64 * 1024, 16,
SECT_4K | SPI_NOR_DUAL_READ |
SPI_NOR_QUAD_READ) },
{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
{ "mx25l51245g", INFO(0xc2201a, 0, 64 * 1024, 1024,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_4B_OPCODES) },
{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_4B_OPCODES) },
......
......@@ -29,7 +29,9 @@ static const struct flash_info st_parts[] = {
{ "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128,
SECT_4K | SPI_NOR_QUAD_READ) },
{ "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256,
SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6) },
{ "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256,
SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
{ "mt25ql256a", INFO6(0x20ba19, 0x104400, 64 * 1024, 512,
......@@ -59,6 +61,8 @@ static const struct flash_info st_parts[] = {
SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6) },
{ "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048,
SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6 |
NO_CHIP_ERASE) },
{ "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048,
SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
......
......@@ -21,10 +21,6 @@
#define SFDP_4BAIT_ID 0xff84 /* 4-byte Address Instruction Table */
#define SFDP_SIGNATURE 0x50444653U
#define SFDP_JESD216_MAJOR 1
#define SFDP_JESD216_MINOR 0
#define SFDP_JESD216A_MINOR 5
#define SFDP_JESD216B_MINOR 6
struct sfdp_header {
u32 signature; /* Ox50444653U <=> "SFDP" */
......@@ -437,7 +433,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
struct sfdp_bfpt bfpt;
size_t len;
int i, cmd, err;
u32 addr;
u32 addr, val;
u16 half;
u8 erase_mask;
......@@ -460,6 +456,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
/* Number of address bytes. */
switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) {
case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY:
case BFPT_DWORD1_ADDRESS_BYTES_3_OR_4:
nor->addr_width = 3;
break;
......@@ -472,21 +469,21 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
}
/* Flash Memory Density (in bits). */
params->size = bfpt.dwords[BFPT_DWORD(2)];
if (params->size & BIT(31)) {
params->size &= ~BIT(31);
val = bfpt.dwords[BFPT_DWORD(2)];
if (val & BIT(31)) {
val &= ~BIT(31);
/*
* Prevent overflows on params->size. Anyway, a NOR of 2^64
* bits is unlikely to exist so this error probably means
* the BFPT we are reading is corrupted/wrong.
*/
if (params->size > 63)
if (val > 63)
return -EINVAL;
params->size = 1ULL << params->size;
params->size = 1ULL << val;
} else {
params->size++;
params->size = val + 1;
}
params->size >>= 3; /* Convert to bytes. */
......@@ -548,15 +545,15 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
SNOR_ERASE_TYPE_MASK;
/* Stop here if not JESD216 rev A or later. */
if (bfpt_header->length < BFPT_DWORD_MAX)
if (bfpt_header->length == BFPT_DWORD_MAX_JESD216)
return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt,
params);
/* Page size: this field specifies 'N' so the page size = 2^N bytes. */
params->page_size = bfpt.dwords[BFPT_DWORD(11)];
params->page_size &= BFPT_DWORD11_PAGE_SIZE_MASK;
params->page_size >>= BFPT_DWORD11_PAGE_SIZE_SHIFT;
params->page_size = 1U << params->page_size;
val = bfpt.dwords[BFPT_DWORD(11)];
val &= BFPT_DWORD11_PAGE_SIZE_MASK;
val >>= BFPT_DWORD11_PAGE_SIZE_SHIFT;
params->page_size = 1U << val;
/* Quad Enable Requirements. */
switch (bfpt.dwords[BFPT_DWORD(15)] & BFPT_DWORD15_QER_MASK) {
......@@ -604,6 +601,11 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
return -EINVAL;
}
/* Stop here if not JESD216 rev C or later. */
if (bfpt_header->length == BFPT_DWORD_MAX_JESD216B)
return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt,
params);
return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt, params);
}
......
......@@ -7,14 +7,20 @@
#ifndef __LINUX_MTD_SFDP_H
#define __LINUX_MTD_SFDP_H
/* SFDP revisions */
#define SFDP_JESD216_MAJOR 1
#define SFDP_JESD216_MINOR 0
#define SFDP_JESD216A_MINOR 5
#define SFDP_JESD216B_MINOR 6
/* Basic Flash Parameter Table */
/*
* JESD216 rev B defines a Basic Flash Parameter Table of 16 DWORDs.
* JESD216 rev D defines a Basic Flash Parameter Table of 20 DWORDs.
* They are indexed from 1 but C arrays are indexed from 0.
*/
#define BFPT_DWORD(i) ((i) - 1)
#define BFPT_DWORD_MAX 16
#define BFPT_DWORD_MAX 20
struct sfdp_bfpt {
u32 dwords[BFPT_DWORD_MAX];
......@@ -22,6 +28,7 @@ struct sfdp_bfpt {
/* The first version of JESD216 defined only 9 DWORDs. */
#define BFPT_DWORD_MAX_JESD216 9
#define BFPT_DWORD_MAX_JESD216B 16
/* 1st DWORD. */
#define BFPT_DWORD1_FAST_READ_1_1_2 BIT(16)
......
......@@ -8,6 +8,27 @@
#include "core.h"
static int
s25fs_s_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt,
struct spi_nor_flash_parameter *params)
{
/*
* The S25FS-S chip family reports 512-byte pages in BFPT but
* in reality the write buffer still wraps at the safe default
* of 256 bytes. Overwrite the page size advertised by BFPT
* to get the writes working.
*/
params->page_size = 256;
return 0;
}
static struct spi_nor_fixups s25fs_s_fixups = {
.post_bfpt = s25fs_s_post_bfpt_fixups,
};
static const struct flash_info spansion_parts[] = {
/* Spansion/Cypress -- single (large) sector size only, at least
* for the chips listed here (without boot sectors).
......@@ -22,16 +43,27 @@ static const struct flash_info spansion_parts[] = {
{ "s25fl128s1", INFO6(0x012018, 0x4d0180, 64 * 1024, 256,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
USE_CLSR) },
{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
{ "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
USE_CLSR) },
{ "s25fl256s0", INFO6(0x010219, 0x4d0080, 256 * 1024, 128,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
USE_CLSR) },
{ "s25fl256s1", INFO6(0x010219, 0x4d0180, 64 * 1024, 512,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
USE_CLSR) },
{ "s25fl512s", INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_HAS_LOCK | USE_CLSR) },
{ "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256,
{ "s25fs128s1", INFO6(0x012018, 0x4d0181, 64 * 1024, 256,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR)
.fixups = &s25fs_s_fixups, },
{ "s25fs256s0", INFO6(0x010219, 0x4d0081, 256 * 1024, 128,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
USE_CLSR) },
{ "s25fs256s1", INFO6(0x010219, 0x4d0181, 64 * 1024, 512,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
USE_CLSR) },
{ "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR)
.fixups = &s25fs_s_fixups, },
{ "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
{ "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
......@@ -70,6 +102,8 @@ static const struct flash_info spansion_parts[] = {
{ "s25fl256l", INFO(0x016019, 0, 64 * 1024, 512,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_4B_OPCODES) },
{ "cy15x104q", INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1,
SPI_NOR_NO_ERASE) },
};
static void spansion_post_sfdp_fixups(struct spi_nor *nor)
......
......@@ -8,6 +8,31 @@
#include "core.h"
static int
w25q256_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
const struct sfdp_bfpt *bfpt,
struct spi_nor_flash_parameter *params)
{
/*
* 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 struct spi_nor_fixups w25q256_fixups = {
.post_bfpt = w25q256_post_bfpt_fixups,
};
static const struct flash_info winbond_parts[] = {
/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
{ "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) },
......@@ -53,8 +78,8 @@ static const struct flash_info winbond_parts[] = {
{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
{ "w25q256", INFO(0xef4019, 0, 64 * 1024, 512,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_4B_OPCODES) },
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
.fixups = &w25q256_fixups },
{ "w25q256jvm", INFO(0xef7019, 0, 64 * 1024, 512,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "w25q256jw", INFO(0xef6019, 0, 64 * 1024, 512,
......
......@@ -20,6 +20,7 @@
*/
/* Flash opcodes. */
#define SPINOR_OP_WRDI 0x04 /* Write disable */
#define SPINOR_OP_WREN 0x06 /* Write enable */
#define SPINOR_OP_RDSR 0x05 /* Read status register */
#define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */
......@@ -80,7 +81,6 @@
/* Used for SST flashes only. */
#define SPINOR_OP_BP 0x02 /* Byte program */
#define SPINOR_OP_WRDI 0x04 /* Write disable */
#define SPINOR_OP_AAI_WP 0xad /* Auto address increment word program */
/* Used for S3AN flashes only */
......@@ -302,7 +302,7 @@ struct spi_nor;
* @read: read data from the SPI NOR.
* @write: write data to the SPI NOR.
* @erase: erase a sector of the SPI NOR at the offset @offs; if
* not provided by the driver, spi-nor will send the erase
* not provided by the driver, SPI NOR will send the erase
* opcode via write_reg().
*/
struct spi_nor_controller_ops {
......@@ -327,16 +327,16 @@ struct spi_nor_manufacturer;
struct spi_nor_flash_parameter;
/**
* struct spi_nor - Structure for defining a the SPI NOR layer
* @mtd: point to a mtd_info structure
* struct spi_nor - Structure for defining the SPI NOR layer
* @mtd: an mtd_info structure
* @lock: the lock for the read/write/erase/lock/unlock operations
* @dev: point to a spi device, or a spi nor controller device.
* @spimem: point to the spi mem device
* @dev: pointer to an SPI device or an SPI NOR controller device
* @spimem: pointer to the SPI memory device
* @bouncebuf: bounce buffer used when the buffer passed by the MTD
* layer is not DMA-able
* @bouncebuf_size: size of the bounce buffer
* @info: spi-nor part JDEC MFR id and other info
* @manufacturer: spi-nor manufacturer
* @info: SPI NOR part JEDEC MFR ID and other info
* @manufacturer: SPI NOR manufacturer
* @page_size: the page size of the SPI NOR
* @addr_width: number of address bytes
* @erase_opcode: the opcode for erasing a sector
......@@ -344,17 +344,17 @@ struct spi_nor_flash_parameter;
* @read_dummy: the dummy needed by the read operation
* @program_opcode: the program opcode
* @sst_write_second: used by the SST write operation
* @flags: flag options for the current SPI-NOR (SNOR_F_*)
* @flags: flag options for the current SPI NOR (SNOR_F_*)
* @read_proto: the SPI protocol for read operations
* @write_proto: the SPI protocol for write operations
* @reg_proto the SPI protocol for read_reg/write_reg/erase operations
* @reg_proto: the SPI protocol for read_reg/write_reg/erase operations
* @controller_ops: SPI NOR controller driver specific operations.
* @params: [FLASH-SPECIFIC] SPI-NOR flash parameters and settings.
* @params: [FLASH-SPECIFIC] SPI NOR flash parameters and settings.
* The structure includes legacy flash parameters and
* settings that can be overwritten by the spi_nor_fixups
* hooks, or dynamically when parsing the SFDP tables.
* @dirmap: pointers to struct spi_mem_dirmap_desc for reads/writes.
* @priv: the private data
* @priv: pointer to the private data
*/
struct spi_nor {
struct mtd_info mtd;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment