2016-10-28 16:18:23 +00:00
|
|
|
From 034dd6241b55ab2256eecb845e941fa9b45da38e Mon Sep 17 00:00:00 2001
|
|
|
|
From: Yunhui Cui <yunhui.cui@nxp.com>
|
|
|
|
Date: Thu, 28 Apr 2016 17:03:57 +0800
|
|
|
|
Subject: [PATCH 110/113] mtd: spi-nor: fsl-quad: add flash S25FS extra
|
|
|
|
support
|
|
|
|
|
|
|
|
[context adjustment]
|
|
|
|
not apply changes of arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
|
|
|
|
|
|
|
|
There are some boards have the same QSPI controller but have
|
|
|
|
different vendor flash, So, the controller can use the same
|
|
|
|
compatible and share the driver, just for a different flash to do
|
|
|
|
the appropriate adaptation. Based on this, we need add the vendor
|
|
|
|
field in spi-nor, Because we will use the field to distribute
|
|
|
|
corresponding LUT for different flash operations.
|
|
|
|
|
|
|
|
Signed-off-by: Yunhui Cui <yunhui.cui@nxp.com>
|
|
|
|
Signed-off-by: Pratiyush Mohan Srivastava <pratiyush.srivastava@nxp.com>
|
|
|
|
Signed-off-by: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>
|
|
|
|
Integrated-by: Jiang Yutang <yutang.jiang@nxp.com>
|
|
|
|
---
|
|
|
|
drivers/mtd/spi-nor/fsl-quadspi.c | 47 ++++++++++++++++++++++++++++++-------
|
|
|
|
drivers/mtd/spi-nor/spi-nor.c | 5 ++--
|
|
|
|
include/linux/mtd/spi-nor.h | 1 +
|
|
|
|
3 files changed, 42 insertions(+), 11 deletions(-)
|
|
|
|
|
|
|
|
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
|
|
|
|
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
|
|
|
|
@@ -213,6 +213,9 @@
|
|
|
|
|
|
|
|
#define QUADSPI_MIN_IOMAP SZ_4M
|
|
|
|
|
|
|
|
+#define FLASH_VENDOR_SPANSION_FS "s25fs"
|
|
|
|
+#define SPANSION_S25FS_FAMILY (1 << 1)
|
|
|
|
+
|
|
|
|
enum fsl_qspi_devtype {
|
|
|
|
FSL_QUADSPI_VYBRID,
|
|
|
|
FSL_QUADSPI_IMX6SX,
|
|
|
|
@@ -329,6 +332,18 @@ static inline int has_added_amba_base_in
|
|
|
|
return q->devtype_data->driver_data & QUADSPI_AMBA_BASE_INTERNAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
+static u32 fsl_get_nor_vendor(struct spi_nor *nor)
|
|
|
|
+{
|
|
|
|
+ u32 vendor_id;
|
|
|
|
+
|
|
|
|
+ if (nor->vendor) {
|
|
|
|
+ if (memcmp(nor->vendor, FLASH_VENDOR_SPANSION_FS,
|
|
|
|
+ sizeof(FLASH_VENDOR_SPANSION_FS) - 1))
|
|
|
|
+ vendor_id = SPANSION_S25FS_FAMILY;
|
|
|
|
+ }
|
|
|
|
+ return vendor_id;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
/*
|
|
|
|
* R/W functions for big- or little-endian registers:
|
|
|
|
* The qSPI controller's endian is independent of the CPU core's endian.
|
|
|
|
@@ -394,13 +409,15 @@ static void fsl_qspi_init_lut(struct fsl
|
|
|
|
int rxfifo = q->devtype_data->rxfifo;
|
|
|
|
u32 lut_base;
|
|
|
|
int i;
|
|
|
|
- const struct fsl_qspi_devtype_data *devtype_data = q->devtype_data;
|
|
|
|
+ u32 vendor;
|
|
|
|
|
|
|
|
struct spi_nor *nor = &q->nor[0];
|
|
|
|
u8 addrlen = (nor->addr_width == 3) ? ADDR24BIT : ADDR32BIT;
|
|
|
|
u8 read_op = nor->read_opcode;
|
|
|
|
u8 read_dm = nor->read_dummy;
|
|
|
|
|
|
|
|
+ vendor = fsl_get_nor_vendor(nor);
|
|
|
|
+
|
|
|
|
fsl_qspi_unlock_lut(q);
|
|
|
|
|
|
|
|
/* Clear all the LUT table */
|
|
|
|
@@ -418,12 +435,25 @@ static void fsl_qspi_init_lut(struct fsl
|
|
|
|
LUT1(FSL_READ, PAD1, rxfifo),
|
|
|
|
base + QUADSPI_LUT(lut_base + 1));
|
|
|
|
} else if (nor->flash_read == SPI_NOR_QUAD) {
|
|
|
|
- qspi_writel(q, LUT0(CMD, PAD1, read_op) |
|
|
|
|
- LUT1(ADDR, PAD1, addrlen),
|
|
|
|
- base + QUADSPI_LUT(lut_base));
|
|
|
|
- qspi_writel(q, LUT0(DUMMY, PAD1, read_dm) |
|
|
|
|
- LUT1(FSL_READ, PAD4, rxfifo),
|
|
|
|
- base + QUADSPI_LUT(lut_base + 1));
|
|
|
|
+ if (q->nor_size == 0x4000000) {
|
|
|
|
+ read_op = 0xEC;
|
|
|
|
+ qspi_writel(q,
|
|
|
|
+ LUT0(CMD, PAD1, read_op) | LUT1(ADDR, PAD4, addrlen),
|
|
|
|
+ base + QUADSPI_LUT(lut_base));
|
|
|
|
+ qspi_writel(q,
|
|
|
|
+ LUT0(MODE, PAD4, 0xff) | LUT1(DUMMY, PAD4, read_dm),
|
|
|
|
+ base + QUADSPI_LUT(lut_base + 1));
|
|
|
|
+ qspi_writel(q,
|
|
|
|
+ LUT0(FSL_READ, PAD4, rxfifo),
|
|
|
|
+ base + QUADSPI_LUT(lut_base + 2));
|
|
|
|
+ } else {
|
|
|
|
+ qspi_writel(q, LUT0(CMD, PAD1, read_op) |
|
|
|
|
+ LUT1(ADDR, PAD1, addrlen),
|
|
|
|
+ base + QUADSPI_LUT(lut_base));
|
|
|
|
+ qspi_writel(q, LUT0(DUMMY, PAD1, read_dm) |
|
|
|
|
+ LUT1(FSL_READ, PAD4, rxfifo),
|
|
|
|
+ base + QUADSPI_LUT(lut_base + 1));
|
|
|
|
+ }
|
|
|
|
} else if (nor->flash_read == SPI_NOR_DDR_QUAD) {
|
|
|
|
/* read mode : 1-4-4, such as Spansion s25fl128s. */
|
|
|
|
qspi_writel(q, LUT0(CMD, PAD1, read_op)
|
|
|
|
@@ -510,7 +540,8 @@ static void fsl_qspi_init_lut(struct fsl
|
|
|
|
* use the same value 0x65. But it indicates different meaning.
|
|
|
|
*/
|
|
|
|
lut_base = SEQID_RDAR_OR_RD_EVCR * 4;
|
|
|
|
- if (devtype_data->devtype == FSL_QUADSPI_LS2080A) {
|
|
|
|
+
|
|
|
|
+ if (vendor == SPANSION_S25FS_FAMILY) {
|
|
|
|
/*
|
|
|
|
* Read any device register.
|
|
|
|
* Used for Spansion S25FS-S family flash only.
|
|
|
|
--- a/drivers/mtd/spi-nor/spi-nor.c
|
|
|
|
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
2016-11-01 11:21:15 +00:00
|
|
|
@@ -797,7 +797,6 @@ static const struct flash_info spi_nor_i
|
2016-10-28 16:18:23 +00:00
|
|
|
{ "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
|
|
|
{ "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
|
|
|
{ "s25fs256s1", INFO6(0x010219, 0x4d0181, 64 * 1024, 512, 0)},
|
|
|
|
- { "s25fs512s", INFO6(0x010220, 0x4d0081, 128 * 1024, 512, 0)},
|
|
|
|
{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
|
|
|
|
{ "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
|
|
|
{ "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
2016-11-01 11:21:15 +00:00
|
|
|
@@ -964,11 +963,9 @@ static int spansion_s25fs_disable_4kb_er
|
2016-10-28 16:18:23 +00:00
|
|
|
ret = nor->read_reg(nor, SPINOR_OP_SPANSION_RDAR, &cr3v, 1);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
-/*
|
|
|
|
if (!(cr3v & CR3V_4KB_ERASE_UNABLE))
|
|
|
|
return -EPERM;
|
|
|
|
|
|
|
|
-*/
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-01 11:21:15 +00:00
|
|
|
@@ -1335,6 +1332,8 @@ int spi_nor_scan(struct spi_nor *nor, co
|
2016-10-28 16:18:23 +00:00
|
|
|
|
|
|
|
if (!mtd->name)
|
|
|
|
mtd->name = dev_name(dev);
|
|
|
|
+ if (info->name)
|
|
|
|
+ nor->vendor = info->name;
|
|
|
|
mtd->priv = nor;
|
|
|
|
mtd->type = MTD_NORFLASH;
|
|
|
|
mtd->writesize = 1;
|
|
|
|
--- a/include/linux/mtd/spi-nor.h
|
|
|
|
+++ b/include/linux/mtd/spi-nor.h
|
|
|
|
@@ -172,6 +172,7 @@ struct spi_nor {
|
|
|
|
bool sst_write_second;
|
|
|
|
u32 flags;
|
|
|
|
u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];
|
|
|
|
+ char *vendor;
|
|
|
|
|
|
|
|
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
|
|
|
|
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
|