mirror of
https://github.com/u-boot/u-boot.git
synced 2025-05-09 03:21:51 +00:00
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-spi into next
- spi_nor_read_sfdp_dma_unsafe (Vaishnav) - w25q01/02 (Jim)
This commit is contained in:
commit
cd908ba186
11 changed files with 210 additions and 7 deletions
|
@ -1,4 +1,5 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o
|
||||
spinand-objs := core.o esmt.o gigadevice.o macronix.o micron.o paragon.o
|
||||
spinand-objs += toshiba.o winbond.o
|
||||
obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
|
||||
|
|
|
@ -828,6 +828,7 @@ static const struct spinand_manufacturer *spinand_manufacturers[] = {
|
|||
¶gon_spinand_manufacturer,
|
||||
&toshiba_spinand_manufacturer,
|
||||
&winbond_spinand_manufacturer,
|
||||
&esmt_c8_spinand_manufacturer,
|
||||
};
|
||||
|
||||
static int spinand_manufacturer_match(struct spinand_device *spinand,
|
||||
|
|
137
drivers/mtd/nand/spi/esmt.c
Normal file
137
drivers/mtd/nand/spi/esmt.c
Normal file
|
@ -0,0 +1,137 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Author:
|
||||
* Chuanhong Guo <gch981213@gmail.com> - the main driver logic
|
||||
* Martin Kurbanov <mmkurbanov@sberdevices.ru> - OOB layout
|
||||
*/
|
||||
|
||||
#ifndef __UBOOT__
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#endif
|
||||
#include <linux/mtd/spinand.h>
|
||||
|
||||
/* ESMT uses GigaDevice 0xc8 JECDEC ID on some SPI NANDs */
|
||||
#define SPINAND_MFR_ESMT_C8 0xc8
|
||||
|
||||
static SPINAND_OP_VARIANTS(read_cache_variants,
|
||||
SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
|
||||
SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
|
||||
SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
|
||||
SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
|
||||
|
||||
static SPINAND_OP_VARIANTS(write_cache_variants,
|
||||
SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
|
||||
SPINAND_PROG_LOAD(true, 0, NULL, 0));
|
||||
|
||||
static SPINAND_OP_VARIANTS(update_cache_variants,
|
||||
SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
|
||||
SPINAND_PROG_LOAD(false, 0, NULL, 0));
|
||||
|
||||
/*
|
||||
* OOB spare area map (64 bytes)
|
||||
*
|
||||
* Bad Block Markers
|
||||
* filled by HW and kernel Reserved
|
||||
* | +-----------------------+-----------------------+
|
||||
* | | | |
|
||||
* | | OOB free data Area |non ECC protected |
|
||||
* | +-------------|-----+-----------------|-----+-----------------|-----+
|
||||
* | | | | | | | |
|
||||
* +-|---|----------+--|-----|--------------+--|-----|--------------+--|-----|--------------+
|
||||
* | | | section0 | | | section1 | | | section2 | | | section3 |
|
||||
* +-v-+-v-+---+----+--v--+--v--+-----+-----+--v--+--v--+-----+-----+--v--+--v--+-----+-----+
|
||||
* | | | | | | | | | | | | | | | | |
|
||||
* |0:1|2:3|4:7|8:15|16:17|18:19|20:23|24:31|32:33|34:35|36:39|40:47|48:49|50:51|52:55|56:63|
|
||||
* | | | | | | | | | | | | | | | | |
|
||||
* +---+---+-^-+--^-+-----+-----+--^--+--^--+-----+-----+--^--+--^--+-----+-----+--^--+--^--+
|
||||
* | | | | | | | |
|
||||
* | +----------------|-----+-----------------|-----+-----------------|-----+
|
||||
* | ECC Area|(Main + Spare) - filled|by ESMT NAND HW |
|
||||
* | | | |
|
||||
* +---------------------+-----------------------+-----------------------+
|
||||
* OOB ECC protected Area - not used due to
|
||||
* partial programming from some filesystems
|
||||
* (like JFFS2 with cleanmarkers)
|
||||
*/
|
||||
|
||||
#define ESMT_OOB_SECTION_COUNT 4
|
||||
#define ESMT_OOB_SECTION_SIZE(nand) \
|
||||
(nanddev_per_page_oobsize(nand) / ESMT_OOB_SECTION_COUNT)
|
||||
#define ESMT_OOB_FREE_SIZE(nand) \
|
||||
(ESMT_OOB_SECTION_SIZE(nand) / 2)
|
||||
#define ESMT_OOB_ECC_SIZE(nand) \
|
||||
(ESMT_OOB_SECTION_SIZE(nand) - ESMT_OOB_FREE_SIZE(nand))
|
||||
#define ESMT_OOB_BBM_SIZE 2
|
||||
|
||||
static int f50l1g41lb_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
struct nand_device *nand = mtd_to_nanddev(mtd);
|
||||
|
||||
if (section >= ESMT_OOB_SECTION_COUNT)
|
||||
return -ERANGE;
|
||||
|
||||
region->offset = section * ESMT_OOB_SECTION_SIZE(nand) +
|
||||
ESMT_OOB_FREE_SIZE(nand);
|
||||
region->length = ESMT_OOB_ECC_SIZE(nand);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int f50l1g41lb_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
struct nand_device *nand = mtd_to_nanddev(mtd);
|
||||
|
||||
if (section >= ESMT_OOB_SECTION_COUNT)
|
||||
return -ERANGE;
|
||||
|
||||
/*
|
||||
* Reserve space for bad blocks markers (section0) and
|
||||
* reserved bytes (sections 1-3)
|
||||
*/
|
||||
region->offset = section * ESMT_OOB_SECTION_SIZE(nand) + 2;
|
||||
|
||||
/* Use only 2 non-protected ECC bytes per each OOB section */
|
||||
region->length = 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mtd_ooblayout_ops f50l1g41lb_ooblayout = {
|
||||
.ecc = f50l1g41lb_ooblayout_ecc,
|
||||
.rfree = f50l1g41lb_ooblayout_free,
|
||||
};
|
||||
|
||||
static const struct spinand_info esmt_c8_spinand_table[] = {
|
||||
SPINAND_INFO("F50L1G41LB",
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01),
|
||||
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
|
||||
NAND_ECCREQ(1, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
0,
|
||||
SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)),
|
||||
SPINAND_INFO("F50D1G41LB",
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x11),
|
||||
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
|
||||
NAND_ECCREQ(1, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
0,
|
||||
SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)),
|
||||
};
|
||||
|
||||
static const struct spinand_manufacturer_ops esmt_spinand_manuf_ops = {
|
||||
};
|
||||
|
||||
const struct spinand_manufacturer esmt_c8_spinand_manufacturer = {
|
||||
.id = SPINAND_MFR_ESMT_C8,
|
||||
.name = "ESMT",
|
||||
.chips = esmt_c8_spinand_table,
|
||||
.nchips = ARRAY_SIZE(esmt_c8_spinand_table),
|
||||
.ops = &esmt_spinand_manuf_ops,
|
||||
};
|
|
@ -176,6 +176,11 @@ config SPI_FLASH_MACRONIX
|
|||
help
|
||||
Add support for various Macronix SPI flash chips (MX25Lxxx)
|
||||
|
||||
config SPI_FLASH_SILICONKAISER
|
||||
bool "Silicon Kaiser SPI flash support"
|
||||
help
|
||||
Add support for various Silicon Kaiser SPI flash chips (SK25Lxxx)
|
||||
|
||||
config SPI_FLASH_SPANSION
|
||||
bool "Spansion SPI flash support"
|
||||
help
|
||||
|
|
|
@ -2089,6 +2089,36 @@ read_err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* spi_nor_read_sfdp_dma_unsafe() - read Serial Flash Discoverable Parameters.
|
||||
* @nor: pointer to a 'struct spi_nor'
|
||||
* @addr: offset in the SFDP area to start reading data from
|
||||
* @len: number of bytes to read
|
||||
* @buf: buffer where the SFDP data are copied into
|
||||
*
|
||||
* Wrap spi_nor_read_sfdp() using a kmalloc'ed bounce buffer as @buf is now not
|
||||
* guaranteed to be dma-safe.
|
||||
*
|
||||
* Return: -ENOMEM if kmalloc() fails, the return code of spi_nor_read_sfdp()
|
||||
* otherwise.
|
||||
*/
|
||||
static int spi_nor_read_sfdp_dma_unsafe(struct spi_nor *nor, u32 addr,
|
||||
size_t len, void *buf)
|
||||
{
|
||||
void *dma_safe_buf;
|
||||
int ret;
|
||||
|
||||
dma_safe_buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!dma_safe_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = spi_nor_read_sfdp(nor, addr, len, dma_safe_buf);
|
||||
memcpy(buf, dma_safe_buf, len);
|
||||
kfree(dma_safe_buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Fast Read settings. */
|
||||
|
||||
static void
|
||||
|
@ -2262,7 +2292,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
|
|||
bfpt_header->length * sizeof(u32));
|
||||
addr = SFDP_PARAM_HEADER_PTP(bfpt_header);
|
||||
memset(&bfpt, 0, sizeof(bfpt));
|
||||
err = spi_nor_read_sfdp(nor, addr, len, &bfpt);
|
||||
err = spi_nor_read_sfdp_dma_unsafe(nor, addr, len, &bfpt);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -2588,7 +2618,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
|
|||
int i, err;
|
||||
|
||||
/* Get the SFDP header. */
|
||||
err = spi_nor_read_sfdp(nor, 0, sizeof(header), &header);
|
||||
err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(header), &header);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
|
|
@ -200,6 +200,11 @@ const struct flash_info spi_nor_ids[] = {
|
|||
SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES)},
|
||||
{INFO("gd55lx02g", 0xc8681C, 0, 64 * 1024, 4096, SECT_4K |
|
||||
SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES)},
|
||||
{
|
||||
INFO("gd55lb02ge", 0xc8671c, 0, 64 * 1024, 4096,
|
||||
SECT_4K | SPI_NOR_QUAD_READ |
|
||||
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */
|
||||
/* ISSI */
|
||||
|
@ -287,6 +292,10 @@ const struct flash_info spi_nor_ids[] = {
|
|||
{ INFO("mx25uw6345g", 0xc28437, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPI_FLASH_SILICONKAISER
|
||||
{ INFO("sk25lp128", 0x257018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */
|
||||
/* Micron */
|
||||
{ INFO("n25q016a", 0x20bb15, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_QUAD_READ) },
|
||||
|
@ -300,6 +309,7 @@ const struct flash_info spi_nor_ids[] = {
|
|||
{ INFO("n25q256a", 0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_FSR) },
|
||||
{ INFO6("mt25qu256a", 0x20bb19, 0x104400, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | USE_FSR) },
|
||||
{ INFO("n25q256ax1", 0x20bb19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ | USE_FSR) },
|
||||
{ INFO("mt25qu128ab", 0x20bb18, 0, 64 * 1024, 256, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
|
||||
{ INFO6("mt25qu512a", 0x20bb20, 0x104400, 64 * 1024, 1024,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES |
|
||||
USE_FSR) },
|
||||
|
@ -309,6 +319,7 @@ const struct flash_info spi_nor_ids[] = {
|
|||
{ INFO("n25q00", 0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
|
||||
{ INFO("n25q00a", 0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
|
||||
{ INFO("mt25ql01g", 0x21ba20, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
|
||||
{ INFO6("mt25qu01g", 0x20bb21, 0x104400, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE | SPI_NOR_4B_OPCODES) },
|
||||
{ INFO("mt25qu02g", 0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
|
||||
{ INFO("mt25ql02g", 0x20ba22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE | SPI_NOR_4B_OPCODES) },
|
||||
#ifdef CONFIG_SPI_FLASH_MT35XU
|
||||
|
@ -513,6 +524,16 @@ const struct flash_info spi_nor_ids[] = {
|
|||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
|
||||
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
|
||||
},
|
||||
{
|
||||
INFO("w25q01jvfim", 0xef7021, 0, 64 * 1024, 2048,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
|
||||
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
|
||||
},
|
||||
{
|
||||
INFO("w25q02jv", 0xef7022, 0, 64 * 1024, 4096,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
|
||||
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
|
||||
},
|
||||
{ INFO("w25q80", 0xef5014, 0, 64 * 1024, 16, SECT_4K) },
|
||||
{ INFO("w25q80bl", 0xef4014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
{ INFO("w25q16cl", 0xef4015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
|
@ -566,6 +587,8 @@ const struct flash_info spi_nor_ids[] = {
|
|||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
|
||||
{ INFO("xt25q01g", 0x0b601B, 0, 64 * 1024, 2048,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
|
||||
{ INFO("xt55q02g", 0x0b601C, 0, 64 * 1024, 4096,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
|
||||
/* adding these wide voltage QSPI flash parts */
|
||||
{ INFO("xt25w512", 0x0b651A, 0, 64 * 1024, 1024,
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
|
||||
|
|
|
@ -295,7 +295,7 @@ static int bcm63xx_hsspi_xfer_dummy_cs(struct udevice *dev, unsigned int data_by
|
|||
|
||||
/* transfer loop */
|
||||
while (data_bytes > 0) {
|
||||
size_t curr_step = min(step_size, data_bytes);
|
||||
size_t curr_step = min(step_size, (size_t)data_bytes);
|
||||
int ret;
|
||||
|
||||
/* copy tx data */
|
||||
|
|
|
@ -39,6 +39,11 @@ __weak int cadence_qspi_versal_flash_reset(struct udevice *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
__weak ofnode cadence_qspi_get_subnode(struct udevice *dev)
|
||||
{
|
||||
return dev_read_first_subnode(dev);
|
||||
}
|
||||
|
||||
static int cadence_spi_write_speed(struct udevice *bus, uint hz)
|
||||
{
|
||||
struct cadence_spi_priv *priv = dev_get_priv(bus);
|
||||
|
@ -400,7 +405,7 @@ static int cadence_spi_of_to_plat(struct udevice *bus)
|
|||
plat->is_dma = dev_read_bool(bus, "cdns,is-dma");
|
||||
|
||||
/* All other parameters are embedded in the child node */
|
||||
subnode = dev_read_first_subnode(bus);
|
||||
subnode = cadence_qspi_get_subnode(bus);
|
||||
if (!ofnode_valid(subnode)) {
|
||||
printf("Error: subnode with SPI flash config missing!\n");
|
||||
return -ENODEV;
|
||||
|
|
|
@ -304,6 +304,7 @@ int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv,
|
|||
int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_priv *priv);
|
||||
int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg);
|
||||
int cadence_qspi_versal_flash_reset(struct udevice *dev);
|
||||
ofnode cadence_qspi_get_subnode(struct udevice *dev);
|
||||
void cadence_qspi_apb_enable_linear_mode(bool enable);
|
||||
|
||||
#endif /* __CADENCE_QSPI_H__ */
|
||||
|
|
|
@ -171,8 +171,7 @@ static unsigned int cadence_qspi_wait_idle(void *reg_base)
|
|||
}
|
||||
|
||||
/* Timeout, still in busy mode. */
|
||||
printf("QSPI: QSPI is still busy after poll for %d times.\n",
|
||||
CQSPI_REG_RETRY);
|
||||
printf("QSPI: QSPI is still busy after poll for %d ms.\n", timeout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -250,6 +250,7 @@ extern const struct spinand_manufacturer micron_spinand_manufacturer;
|
|||
extern const struct spinand_manufacturer paragon_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer toshiba_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer winbond_spinand_manufacturer;
|
||||
extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer;
|
||||
|
||||
/**
|
||||
* struct spinand_op_variants - SPI NAND operation variants
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue