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