mirror of https://gitee.com/openkylin/linux.git
SPI NOR core changes:
- add, update support and fix few flashes - prepare BFPT parsing for JESD216 rev D - kernel doc fixes -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEHUIqys8OyG1eHf7fS1VPR6WNFOkFAl7U4hUACgkQS1VPR6WN FOkAjAf+Kxt87QGIOyQRybAhCJvHxRSiba+axmsM6dSn6+GoAPLRcxeW3fXOark6 gPlmY31+yFyGAGcUO/w51woc/NS4vicRhW+bxzcf/DSl88UJCZyr+G7QP14dcjQY Zts2+sa44tdmo+DdxKUxfs4t9xQFNXIvM2Y1Rlb8KsJGKP4xLyXs0R6a4Xgo5qEX wtMe2D+DoQ5rlnv98bDoaeRGkhq+n1aqt0zPLKHit1wcOEH7PseiwaKDIPhbTW0K sIdSrzEb8aEzVt9pLuRig9NLFlwYK7mpfjdnOoR5oKTl1nQI44hBjAU/dnTL67YP Bt/WNTaSwj/6XGhYA55+zxn5rJ3pQQ== =w6a9 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
3f5540032f
|
@ -1,12 +1,12 @@
|
||||||
# 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
|
||||||
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)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// 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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// 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)
|
||||||
* 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)
|
||||||
* 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)
|
||||||
* 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)
|
||||||
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,
|
||||||
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,
|
||||||
/**
|
/**
|
||||||
* 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)
|
||||||
/**
|
/**
|
||||||
* 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)
|
||||||
/**
|
/**
|
||||||
* 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)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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,
|
||||||
/*
|
/*
|
||||||
* 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[] = {
|
||||||
.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[] = {
|
||||||
{ "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[] = {
|
||||||
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 @@
|
||||||
#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,
|
||||||
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,
|
||||||
/* 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,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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,
|
||||||
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,
|
||||||
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 @@
|
||||||
#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 {
|
||||||
|
|
||||||
/* 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 @@
|
||||||
|
|
||||||
#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[] = {
|
||||||
{ "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 |
|
||||||
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
|
USE_CLSR) },
|
||||||
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,
|
{ "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[] = {
|
||||||
{ "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 @@
|
||||||
|
|
||||||
#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[] = {
|
||||||
{ "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 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* 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 @@
|
||||||
|
|
||||||
/* 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;
|
||||||
* @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;
|
||||||
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;
|
||||||
* @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;
|
||||||
|
|
Loading…
Reference in New Issue