diff options
Diffstat (limited to 'target/linux/layerscape/patches-4.4/1110-mtd-spi-nor-fsl-quad-add-flash-S25FS-extra-support.patch')
-rw-r--r-- | target/linux/layerscape/patches-4.4/1110-mtd-spi-nor-fsl-quad-add-flash-S25FS-extra-support.patch | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-4.4/1110-mtd-spi-nor-fsl-quad-add-flash-S25FS-extra-support.patch b/target/linux/layerscape/patches-4.4/1110-mtd-spi-nor-fsl-quad-add-flash-S25FS-extra-support.patch new file mode 100644 index 0000000000..2b21b11165 --- /dev/null +++ b/target/linux/layerscape/patches-4.4/1110-mtd-spi-nor-fsl-quad-add-flash-S25FS-extra-support.patch @@ -0,0 +1,157 @@ +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 +@@ -796,7 +796,6 @@ static const struct flash_info spi_nor_i + { "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) }, +@@ -963,11 +962,9 @@ static int spansion_s25fs_disable_4kb_er + 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; + } + +@@ -1334,6 +1331,8 @@ int spi_nor_scan(struct spi_nor *nor, co + + 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); |