- Fix mtd erase with mtdpart (Marek Behún) - NXP fspi driver fixes (Kuldeep Singh)
This commit is contained in:
commit
355d1e24f6
@ -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;
|
||||
|
@ -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, ®s->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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -446,27 +446,16 @@ 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;
|
||||
}
|
||||
if (ret && instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
|
||||
instr->fail_addr -= mtd->offset;
|
||||
|
||||
instr->addr -= mtd->offset;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_erase_callback);
|
||||
|
||||
static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
return mtd->parent->_lock(mtd->parent, ofs + mtd->offset, len);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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) },
|
||||
|
@ -304,18 +304,6 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -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);
|
||||
|
@ -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,
|
||||
|
4
env/onenand.c
vendored
4
env/onenand.c
vendored
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user