summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/onenand.c9
-rw-r--r--drivers/mtd/altera_qspi.c3
-rw-r--r--drivers/mtd/cfi_mtd.c1
-rw-r--r--drivers/mtd/mtdconcat.c11
-rw-r--r--drivers/mtd/mtdcore.c8
-rw-r--r--drivers/mtd/mtdpart.c23
-rw-r--r--drivers/mtd/nand/raw/nand_base.c4
-rw-r--r--drivers/mtd/nand/spi/macronix.c10
-rw-r--r--drivers/mtd/onenand/onenand_base.c3
-rw-r--r--drivers/mtd/spi/sf_mtd.c1
-rw-r--r--drivers/mtd/spi/spi-nor-core.c65
-rw-r--r--drivers/mtd/spi/spi-nor-ids.c13
-rw-r--r--drivers/mtd/ubi/io.c13
-rw-r--r--drivers/spi/nxp_fspi.c77
-rw-r--r--env/onenand.c4
-rw-r--r--fs/yaffs2/yaffs_mtdif.c1
-rw-r--r--include/linux/mtd/mtd.h11
-rw-r--r--include/nand.h1
-rw-r--r--include/spi_flash.h9
19 files changed, 159 insertions, 108 deletions
diff --git a/cmd/onenand.c b/cmd/onenand.c
index 852ed5c7b2..592985a7ee 100644
--- a/cmd/onenand.c
+++ b/cmd/onenand.c
@@ -186,9 +186,7 @@ next:
static int onenand_block_erase(u32 start, u32 size, int force)
{
struct onenand_chip *this = mtd->priv;
- struct erase_info instr = {
- .callback = NULL,
- };
+ struct erase_info instr = {};
loff_t ofs;
int ret;
int blocksize = 1 << this->erase_shift;
@@ -219,10 +217,7 @@ static int onenand_block_erase(u32 start, u32 size, int force)
static int onenand_block_test(u32 start, u32 size)
{
struct onenand_chip *this = mtd->priv;
- struct erase_info instr = {
- .callback = NULL,
- .priv = 0,
- };
+ struct erase_info instr = {};
int blocks;
loff_t ofs;
diff --git a/drivers/mtd/altera_qspi.c b/drivers/mtd/altera_qspi.c
index 7bac599a54..d31391f36a 100644
--- a/drivers/mtd/altera_qspi.c
+++ b/drivers/mtd/altera_qspi.c
@@ -153,7 +153,6 @@ static int altera_qspi_erase(struct mtd_info *mtd, struct erase_info *instr)
putc('\n');
instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
instr->state = MTD_ERASE_FAILED;
- mtd_erase_callback(instr);
return -EIO;
}
flash = pdata->base + addr;
@@ -177,7 +176,6 @@ static int altera_qspi_erase(struct mtd_info *mtd, struct erase_info *instr)
writel(stat, &regs->isr); /* clear isr */
instr->fail_addr = addr;
instr->state = MTD_ERASE_FAILED;
- mtd_erase_callback(instr);
return -EIO;
}
if (flash_verbose)
@@ -189,7 +187,6 @@ static int altera_qspi_erase(struct mtd_info *mtd, struct erase_info *instr)
addr += mtd->erasesize;
}
instr->state = MTD_ERASE_DONE;
- mtd_erase_callback(instr);
return 0;
}
diff --git a/drivers/mtd/cfi_mtd.c b/drivers/mtd/cfi_mtd.c
index 78293caa2f..2295bb7220 100644
--- a/drivers/mtd/cfi_mtd.c
+++ b/drivers/mtd/cfi_mtd.c
@@ -58,7 +58,6 @@ static int cfi_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
}
instr->state = MTD_ERASE_DONE;
- mtd_erase_callback(instr);
return 0;
}
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 684bc94998..af3c4765c4 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -338,14 +338,6 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
return -EINVAL;
}
-static void concat_erase_callback(struct erase_info *instr)
-{
- /* Nothing to do here in U-Boot */
-#ifndef __UBOOT__
- wake_up((wait_queue_head_t *) instr->priv);
-#endif
-}
-
static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase)
{
int err;
@@ -358,7 +350,6 @@ static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase)
init_waitqueue_head(&waitq);
erase->mtd = mtd;
- erase->callback = concat_erase_callback;
erase->priv = (unsigned long) &waitq;
/*
@@ -498,8 +489,6 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
if (err)
return err;
- if (instr->callback)
- instr->callback(instr);
return 0;
}
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 9496903e86..1d45fb55c7 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -906,13 +906,6 @@ void __put_mtd_device(struct mtd_info *mtd)
}
EXPORT_SYMBOL_GPL(__put_mtd_device);
-/*
- * Erase is an asynchronous operation. Device drivers are supposed
- * to call instr->callback() whenever the operation completes, even
- * if it completes with a failure.
- * Callers are supposed to pass a callback function and wait for it
- * to be called before writing to the block.
- */
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
{
if (instr->addr > mtd->size || instr->len > mtd->size - instr->addr)
@@ -922,7 +915,6 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
if (!instr->len) {
instr->state = MTD_ERASE_DONE;
- mtd_erase_callback(instr);
return 0;
}
return mtd->_erase(mtd, instr);
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index aa58f722da..a435ce6d07 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -446,26 +446,15 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
int ret;
instr->addr += mtd->offset;
+
ret = mtd->parent->_erase(mtd->parent, instr);
- if (ret) {
- if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
- instr->fail_addr -= mtd->offset;
- instr->addr -= mtd->offset;
- }
- return ret;
-}
+ if (ret && instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
+ instr->fail_addr -= mtd->offset;
-void mtd_erase_callback(struct erase_info *instr)
-{
- if (instr->mtd->_erase == part_erase) {
- if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
- instr->fail_addr -= instr->mtd->offset;
- instr->addr -= instr->mtd->offset;
- }
- if (instr->callback)
- instr->callback(instr);
+ instr->addr -= mtd->offset;
+
+ return ret;
}
-EXPORT_SYMBOL_GPL(mtd_erase_callback);
static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index b533683dfe..f7616985d9 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -3602,10 +3602,6 @@ erase_exit:
chip->select_chip(mtd, -1);
nand_release_device(mtd);
- /* Do call back function */
- if (!ret)
- mtd_erase_callback(instr);
-
/* Return more or less happy */
return ret;
}
diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
index f4a8e81639..6d643a8000 100644
--- a/drivers/mtd/nand/spi/macronix.c
+++ b/drivers/mtd/nand/spi/macronix.c
@@ -14,6 +14,8 @@
#include <linux/mtd/spinand.h>
#define SPINAND_MFR_MACRONIX 0xC2
+#define MACRONIX_ECCSR_MASK 0x0F
+
static SPINAND_OP_VARIANTS(read_cache_variants,
SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
@@ -59,7 +61,13 @@ static int mx35lf1ge4ab_get_eccsr(struct spinand_device *spinand, u8 *eccsr)
SPI_MEM_OP_DUMMY(1, 1),
SPI_MEM_OP_DATA_IN(1, eccsr, 1));
- return spi_mem_exec_op(spinand->slave, &op);
+ int ret = spi_mem_exec_op(spinand->slave, &op);
+
+ if (ret)
+ return ret;
+
+ *eccsr &= MACRONIX_ECCSR_MASK;
+ return 0;
}
static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand,
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 46aeef258d..56e1858de4 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1836,9 +1836,6 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
erase_exit:
ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
- /* Do call back function */
- if (!ret)
- mtd_erase_callback(instr);
/* Deselect and wake up anyone waiting on the device */
onenand_release_device(mtd);
diff --git a/drivers/mtd/spi/sf_mtd.c b/drivers/mtd/spi/sf_mtd.c
index 04de868080..0aed28a52b 100644
--- a/drivers/mtd/spi/sf_mtd.c
+++ b/drivers/mtd/spi/sf_mtd.c
@@ -46,7 +46,6 @@ static int spi_flash_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
}
instr->state = MTD_ERASE_DONE;
- mtd_erase_callback(instr);
return 0;
}
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index f1b4e5ea8e..4388a08a90 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -908,30 +908,40 @@ static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ bool addr_known = false;
u32 addr, len, rem;
- int ret;
+ int ret, err;
dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr,
(long long)instr->len);
- if (!instr->len)
- return 0;
-
div_u64_rem(instr->len, mtd->erasesize, &rem);
- if (rem)
- return -EINVAL;
+ if (rem) {
+ ret = -EINVAL;
+ goto err;
+ }
addr = instr->addr;
len = instr->len;
+ instr->state = MTD_ERASING;
+ addr_known = true;
+
while (len) {
WATCHDOG_RESET();
+ if (ctrlc()) {
+ addr_known = false;
+ ret = -EINTR;
+ goto erase_err;
+ }
#ifdef CONFIG_SPI_FLASH_BAR
ret = write_bar(nor, addr);
if (ret < 0)
- return ret;
+ goto erase_err;
#endif
- write_enable(nor);
+ ret = write_enable(nor);
+ if (ret < 0)
+ goto erase_err;
ret = spi_nor_erase_sector(nor, addr);
if (ret < 0)
@@ -945,11 +955,24 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
goto erase_err;
}
+ addr_known = false;
erase_err:
#ifdef CONFIG_SPI_FLASH_BAR
- ret = clean_bar(nor);
+ err = clean_bar(nor);
+ if (!ret)
+ ret = err;
#endif
- write_disable(nor);
+ err = write_disable(nor);
+ if (!ret)
+ ret = err;
+
+err:
+ if (ret) {
+ instr->fail_addr = addr_known ? addr : MTD_FAIL_ADDR_UNKNOWN;
+ instr->state = MTD_ERASE_FAILED;
+ } else {
+ instr->state = MTD_ERASE_DONE;
+ }
return ret;
}
@@ -1665,9 +1688,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
- if (!len)
- return 0;
-
for (i = 0; i < len; ) {
ssize_t written;
loff_t addr = to + i;
@@ -3224,6 +3244,21 @@ static struct spi_nor_fixups s25hx_t_fixups = {
.post_bfpt = s25hx_t_post_bfpt_fixup,
.post_sfdp = s25hx_t_post_sfdp_fixup,
};
+
+static int s25fl256l_setup(struct spi_nor *nor, const struct flash_info *info,
+ const struct spi_nor_flash_parameter *params)
+{
+ return -ENOTSUPP; /* Bank Address Register is not supported */
+}
+
+static void s25fl256l_default_init(struct spi_nor *nor)
+{
+ nor->setup = s25fl256l_setup;
+}
+
+static struct spi_nor_fixups s25fl256l_fixups = {
+ .default_init = s25fl256l_default_init,
+};
#endif
#ifdef CONFIG_SPI_FLASH_S28HS512T
@@ -3646,6 +3681,10 @@ void spi_nor_set_fixups(struct spi_nor *nor)
break;
}
}
+
+ if (CONFIG_IS_ENABLED(SPI_FLASH_BAR) &&
+ !strcmp(nor->info->name, "s25fl256l"))
+ nor->fixups = &s25fl256l_fixups;
#endif
#ifdef CONFIG_SPI_FLASH_S28HS512T
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index 0bff52d5f2..3ae7bb1ed7 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -122,6 +122,11 @@ const struct flash_info spi_nor_ids[] = {
SECT_4K | SPI_NOR_DUAL_READ |
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
},
+ {
+ INFO("gd25lq256d", 0xc86019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+ },
#endif
#ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */
/* ISSI */
@@ -133,6 +138,8 @@ const struct flash_info spi_nor_ids[] = {
SECT_4K | SPI_NOR_DUAL_READ) },
{ INFO("is25lp256", 0x9d6019, 0, 64 * 1024, 512,
SECT_4K | SPI_NOR_DUAL_READ) },
+ { INFO("is25lp512", 0x9d601a, 0, 64 * 1024, 1024,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ INFO("is25wp032", 0x9d7016, 0, 64 * 1024, 64,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ INFO("is25wp064", 0x9d7017, 0, 64 * 1024, 128,
@@ -142,6 +149,8 @@ const struct flash_info spi_nor_ids[] = {
{ INFO("is25wp256", 0x9d7019, 0, 64 * 1024, 512,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_4B_OPCODES) },
+ { INFO("is25wp512", 0x9d701a, 0, 64 * 1024, 1024,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
#endif
#ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */
/* Macronix */
@@ -186,7 +195,7 @@ const struct flash_info spi_nor_ids[] = {
{ 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) },
{ INFO6("mt25qu512a", 0x20bb20, 0x104400, 64 * 1024, 1024,
- SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES |
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES |
USE_FSR) },
{ INFO("n25q512a", 0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
{ INFO6("mt25ql512a", 0x20ba20, 0x104400, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
@@ -195,6 +204,7 @@ const struct flash_info spi_nor_ids[] = {
{ 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) },
{ 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
{ INFO("mt35xu512aba", 0x2c5b1a, 0, 128 * 1024, 512, USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ) },
#endif /* CONFIG_SPI_FLASH_MT35XU */
@@ -227,6 +237,7 @@ const struct flash_info spi_nor_ids[] = {
{ INFO("s25fl208k", 0x014014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ) },
{ INFO("s25fl064l", 0x016017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
{ INFO("s25fl128l", 0x016018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("s25fl256l", 0x016019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
{ INFO6("s25hl512t", 0x342a1a, 0x0f0390, 256 * 1024, 256,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES |
USE_CLSR) },
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index b8b878b918..14be95b74b 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -305,18 +305,6 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
}
/**
- * erase_callback - MTD erasure call-back.
- * @ei: MTD erase information object.
- *
- * Note, even though MTD erase interface is asynchronous, all the current
- * implementations are synchronous anyway.
- */
-static void erase_callback(struct erase_info *ei)
-{
- wake_up_interruptible((wait_queue_head_t *)ei->priv);
-}
-
-/**
* do_sync_erase - synchronously erase a physical eraseblock.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to erase
@@ -346,7 +334,6 @@ retry:
ei.mtd = ubi->mtd;
ei.addr = (loff_t)pnum * ubi->peb_size;
ei.len = ubi->peb_size;
- ei.callback = erase_callback;
ei.priv = (unsigned long)&wq;
err = mtd_erase(ubi->mtd, &ei);
diff --git a/drivers/spi/nxp_fspi.c b/drivers/spi/nxp_fspi.c
index bba7a330e0..b7c922b1df 100644
--- a/drivers/spi/nxp_fspi.c
+++ b/drivers/spi/nxp_fspi.c
@@ -41,6 +41,11 @@
#include <spi.h>
#include <spi-mem.h>
#include <asm/io.h>
+#ifdef CONFIG_FSL_LAYERSCAPE
+#include <asm/arch/clock.h>
+#include <asm/arch/soc.h>
+#include <asm/arch/speed.h>
+#endif
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/sizes.h>
@@ -304,6 +309,9 @@
#define POLL_TOUT 5000
#define NXP_FSPI_MAX_CHIPSELECT 4
+/* Access flash memory using IP bus only */
+#define FSPI_QUIRK_USE_IP_ONLY BIT(0)
+
struct nxp_fspi_devtype_data {
unsigned int rxfifo;
unsigned int txfifo;
@@ -312,7 +320,7 @@ struct nxp_fspi_devtype_data {
bool little_endian;
};
-static const struct nxp_fspi_devtype_data lx2160a_data = {
+static struct nxp_fspi_devtype_data lx2160a_data = {
.rxfifo = SZ_512, /* (64 * 64 bits) */
.txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
@@ -320,7 +328,7 @@ static const struct nxp_fspi_devtype_data lx2160a_data = {
.little_endian = true, /* little-endian */
};
-static const struct nxp_fspi_devtype_data imx8mm_data = {
+static struct nxp_fspi_devtype_data imx8mm_data = {
.rxfifo = SZ_512, /* (64 * 64 bits) */
.txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
@@ -335,9 +343,14 @@ struct nxp_fspi {
u32 memmap_phy;
u32 memmap_phy_size;
struct clk clk, clk_en;
- const struct nxp_fspi_devtype_data *devtype_data;
+ struct nxp_fspi_devtype_data *devtype_data;
};
+static inline int needs_ip_only(struct nxp_fspi *f)
+{
+ return f->devtype_data->quirks & FSPI_QUIRK_USE_IP_ONLY;
+}
+
/*
* R/W functions for big- or little-endian registers:
* The FSPI controller's endianness is independent of
@@ -521,8 +534,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
for (i = 0; i < ARRAY_SIZE(lutval); i++)
fspi_writel(f, lutval[i], base + FSPI_LUT_REG(i));
- dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x]\n",
- op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3]);
+ dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x], size: 0x%08x\n",
+ op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3], op->data.nbytes);
/* lock LUT */
fspi_writel(f, FSPI_LUTKEY_VALUE, f->iobase + FSPI_LUTKEY);
@@ -769,12 +782,14 @@ static int nxp_fspi_exec_op(struct spi_slave *slave,
nxp_fspi_prepare_lut(f, op);
/*
- * If we have large chunks of data, we read them through the AHB bus
- * by accessing the mapped memory. In all other cases we use
- * IP commands to access the flash.
+ * If we have large chunks of data, we read them through the AHB bus by
+ * accessing the mapped memory. In all other cases we use IP commands
+ * to access the flash. Read via AHB bus may be corrupted due to
+ * existence of an errata and therefore discard AHB read in such cases.
*/
if (op->data.nbytes > (f->devtype_data->rxfifo - 4) &&
- op->data.dir == SPI_MEM_DATA_IN) {
+ op->data.dir == SPI_MEM_DATA_IN &&
+ !needs_ip_only(f)) {
nxp_fspi_read_ahb(f, op);
} else {
if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT)
@@ -808,9 +823,42 @@ static int nxp_fspi_adjust_op_size(struct spi_slave *slave,
op->data.nbytes = ALIGN_DOWN(op->data.nbytes, 8);
}
+ /* Limit data bytes to RX FIFO in case of IP read only */
+ if (needs_ip_only(f) &&
+ op->data.dir == SPI_MEM_DATA_IN &&
+ op->data.nbytes > f->devtype_data->rxfifo)
+ op->data.nbytes = f->devtype_data->rxfifo;
+
return 0;
}
+#ifdef CONFIG_FSL_LAYERSCAPE
+static void erratum_err050568(struct nxp_fspi *f)
+{
+ struct sys_info sysinfo;
+ u32 svr = 0, freq = 0;
+
+ /* Check for LS1028A variants */
+ svr = SVR_SOC_VER(get_svr());
+ if (svr != SVR_LS1017A ||
+ svr != SVR_LS1018A ||
+ svr != SVR_LS1027A ||
+ svr != SVR_LS1028A) {
+ dev_dbg(f->dev, "Errata applicable only for LS1028A variants\n");
+ return;
+ }
+
+ /* Read PLL frequency */
+ get_sys_info(&sysinfo);
+ freq = sysinfo.freq_systembus / 1000000; /* Convert to MHz */
+ dev_dbg(f->dev, "svr: %08x, Frequency: %dMhz\n", svr, freq);
+
+ /* Use IP bus only if PLL is 300MHz */
+ if (freq == 300)
+ f->devtype_data->quirks |= FSPI_QUIRK_USE_IP_ONLY;
+}
+#endif
+
static int nxp_fspi_default_setup(struct nxp_fspi *f)
{
void __iomem *base = f->iobase;
@@ -831,6 +879,17 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
return ret;
#endif
+#ifdef CONFIG_FSL_LAYERSCAPE
+ /*
+ * ERR050568: Flash access by FlexSPI AHB command may not work with
+ * platform frequency equal to 300 MHz on LS1028A.
+ * LS1028A reuses LX2160A compatible entry. Make errata applicable for
+ * Layerscape LS1028A platform family.
+ */
+ if (device_is_compatible(f->dev, "nxp,lx2160a-fspi"))
+ erratum_err050568(f);
+#endif
+
/* Reset the module */
/* w1c register, wait unit clear */
ret = fspi_readl_poll_tout(f, f->iobase + FSPI_MCR0,
diff --git a/env/onenand.c b/env/onenand.c
index c8da3ff811..1faa2cb62a 100644
--- a/env/onenand.c
+++ b/env/onenand.c
@@ -73,9 +73,7 @@ static int env_onenand_save(void)
#endif
loff_t env_addr = CONFIG_ENV_ADDR;
size_t retlen;
- struct erase_info instr = {
- .callback = NULL,
- };
+ struct erase_info instr = {};
ret = env_export(&env_new);
if (ret)
diff --git a/fs/yaffs2/yaffs_mtdif.c b/fs/yaffs2/yaffs_mtdif.c
index d338f9aa91..50fed2d4b1 100644
--- a/fs/yaffs2/yaffs_mtdif.c
+++ b/fs/yaffs2/yaffs_mtdif.c
@@ -145,7 +145,6 @@ int nandmtd_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber)
ei.len = dev->data_bytes_per_chunk * dev->param.chunks_per_block;
ei.time = 1000;
ei.retries = 2;
- ei.callback = NULL;
ei.priv = (u_long) dev;
/* Todo finish off the ei if required */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 3b302fb8c3..7455400981 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -51,7 +51,6 @@ struct erase_info {
u_long retries;
unsigned dev;
unsigned cell;
- void (*callback) (struct erase_info *self);
u_long priv;
u_char state;
struct erase_info *next;
@@ -535,16 +534,6 @@ extern int unregister_mtd_user (struct mtd_notifier *old);
#endif
void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);
-#ifdef CONFIG_MTD_PARTITIONS
-void mtd_erase_callback(struct erase_info *instr);
-#else
-static inline void mtd_erase_callback(struct erase_info *instr)
-{
- if (instr->callback)
- instr->callback(instr);
-}
-#endif
-
static inline int mtd_is_bitflip(int err) {
return err == -EUCLEAN;
}
diff --git a/include/nand.h b/include/nand.h
index 75c605193a..09dbda4e81 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -69,7 +69,6 @@ static inline int nand_erase(struct mtd_info *info, loff_t off, size_t size)
instr.mtd = info;
instr.addr = off;
instr.len = size;
- instr.callback = 0;
return mtd_erase(info, &instr);
}
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 3d747c925b..4d4ae89c19 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -165,6 +165,9 @@ static inline int spi_flash_read(struct spi_flash *flash, u32 offset,
struct mtd_info *mtd = &flash->mtd;
size_t retlen;
+ if (!len)
+ return 0;
+
return mtd->_read(mtd, offset, len, &retlen, buf);
}
@@ -174,6 +177,9 @@ static inline int spi_flash_write(struct spi_flash *flash, u32 offset,
struct mtd_info *mtd = &flash->mtd;
size_t retlen;
+ if (!len)
+ return 0;
+
return mtd->_write(mtd, offset, len, &retlen, buf);
}
@@ -188,6 +194,9 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset,
return -EINVAL;
}
+ if (!len)
+ return 0;
+
memset(&instr, 0, sizeof(instr));
instr.addr = offset;
instr.len = len;