From 68904cb8fda3692c19fb39d3f99633c9d12efed7 Mon Sep 17 00:00:00 2001 From: Biwen Li Date: Wed, 12 Dec 2018 09:56:18 +0800 Subject: layerscape: drop kernel 4.9 support This patch is to drop kernel 4.9 support. Signed-off-by: Biwen Li Signed-off-by: Yangbo Lu --- .../401-mtd-spi-nor-support-layerscape.patch | 993 --------------------- 1 file changed, 993 deletions(-) delete mode 100644 target/linux/layerscape/patches-4.9/401-mtd-spi-nor-support-layerscape.patch (limited to 'target/linux/layerscape/patches-4.9/401-mtd-spi-nor-support-layerscape.patch') diff --git a/target/linux/layerscape/patches-4.9/401-mtd-spi-nor-support-layerscape.patch b/target/linux/layerscape/patches-4.9/401-mtd-spi-nor-support-layerscape.patch deleted file mode 100644 index 89139d93b8..0000000000 --- a/target/linux/layerscape/patches-4.9/401-mtd-spi-nor-support-layerscape.patch +++ /dev/null @@ -1,993 +0,0 @@ -From c03c545e064a81515fe109ddcc4ecb3895528e58 Mon Sep 17 00:00:00 2001 -From: Yangbo Lu -Date: Fri, 6 Jul 2018 15:32:05 +0800 -Subject: [PATCH] mtd: spi-nor: support layerscape - -This is an integrated patch for layerscape qspi support. - -Signed-off-by: Suresh Gupta -Signed-off-by: Yunhui Cui -Signed-off-by: mar.krzeminski -Signed-off-by: Alison Wang -Signed-off-by: Nobuhiro Iwamatsu -Signed-off-by: LABBE Corentin -Signed-off-by: Yuan Yao -Signed-off-by: Alexander Kurz -Signed-off-by: L. D. Pinney -Signed-off-by: Ash Benz -Signed-off-by: Yangbo Lu ---- - drivers/mtd/devices/m25p80.c | 3 +- - drivers/mtd/mtdchar.c | 2 +- - drivers/mtd/spi-nor/fsl-quadspi.c | 327 ++++++++++++++++++++++++------ - drivers/mtd/spi-nor/spi-nor.c | 141 ++++++++++++- - include/linux/mtd/spi-nor.h | 14 +- - 5 files changed, 416 insertions(+), 71 deletions(-) - ---- a/drivers/mtd/mtdchar.c -+++ b/drivers/mtd/mtdchar.c -@@ -455,7 +455,7 @@ static int mtdchar_readoob(struct file * - * data. For our userspace tools it is important to dump areas - * with ECC errors! - * For kernel internal usage it also might return -EUCLEAN -- * to signal the caller that a bitflip has occured and has -+ * to signal the caller that a bitflip has occurred and has - * been corrected by the ECC algorithm. - * - * Note: currently the standard NAND function, nand_read_oob_std, ---- a/drivers/mtd/spi-nor/fsl-quadspi.c -+++ b/drivers/mtd/spi-nor/fsl-quadspi.c -@@ -41,6 +41,8 @@ - #define QUADSPI_QUIRK_TKT253890 (1 << 2) - /* Controller cannot wake up from wait mode, TKT245618 */ - #define QUADSPI_QUIRK_TKT245618 (1 << 3) -+/* QSPI_AMBA_BASE is internally added by SOC design */ -+#define QUADSPI_AMBA_BASE_INTERNAL (0x10000) - - /* The registers */ - #define QUADSPI_MCR 0x00 -@@ -193,7 +195,7 @@ - #define QUADSPI_LUT_NUM 64 - - /* SEQID -- we can have 16 seqids at most. */ --#define SEQID_QUAD_READ 0 -+#define SEQID_READ 0 - #define SEQID_WREN 1 - #define SEQID_WRDI 2 - #define SEQID_RDSR 3 -@@ -205,15 +207,22 @@ - #define SEQID_RDCR 9 - #define SEQID_EN4B 10 - #define SEQID_BRWR 11 -+#define SEQID_RDAR_OR_RD_EVCR 12 -+#define SEQID_WRAR 13 -+#define SEQID_WD_EVCR 14 - - #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, - FSL_QUADSPI_IMX7D, - FSL_QUADSPI_IMX6UL, - FSL_QUADSPI_LS1021A, -+ FSL_QUADSPI_LS2080A, - }; - - struct fsl_qspi_devtype_data { -@@ -224,7 +233,7 @@ struct fsl_qspi_devtype_data { - int driver_data; - }; - --static struct fsl_qspi_devtype_data vybrid_data = { -+static const struct fsl_qspi_devtype_data vybrid_data = { - .devtype = FSL_QUADSPI_VYBRID, - .rxfifo = 128, - .txfifo = 64, -@@ -232,7 +241,7 @@ static struct fsl_qspi_devtype_data vybr - .driver_data = QUADSPI_QUIRK_SWAP_ENDIAN, - }; - --static struct fsl_qspi_devtype_data imx6sx_data = { -+static const struct fsl_qspi_devtype_data imx6sx_data = { - .devtype = FSL_QUADSPI_IMX6SX, - .rxfifo = 128, - .txfifo = 512, -@@ -241,7 +250,7 @@ static struct fsl_qspi_devtype_data imx6 - | QUADSPI_QUIRK_TKT245618, - }; - --static struct fsl_qspi_devtype_data imx7d_data = { -+static const struct fsl_qspi_devtype_data imx7d_data = { - .devtype = FSL_QUADSPI_IMX7D, - .rxfifo = 512, - .txfifo = 512, -@@ -250,7 +259,7 @@ static struct fsl_qspi_devtype_data imx7 - | QUADSPI_QUIRK_4X_INT_CLK, - }; - --static struct fsl_qspi_devtype_data imx6ul_data = { -+static const struct fsl_qspi_devtype_data imx6ul_data = { - .devtype = FSL_QUADSPI_IMX6UL, - .rxfifo = 128, - .txfifo = 512, -@@ -267,6 +276,14 @@ static struct fsl_qspi_devtype_data ls10 - .driver_data = 0, - }; - -+static struct fsl_qspi_devtype_data ls2080a_data = { -+ .devtype = FSL_QUADSPI_LS2080A, -+ .rxfifo = 128, -+ .txfifo = 64, -+ .ahb_buf_size = 1024, -+ .driver_data = QUADSPI_AMBA_BASE_INTERNAL | QUADSPI_QUIRK_TKT253890, -+}; -+ - #define FSL_QSPI_MAX_CHIP 4 - struct fsl_qspi { - struct spi_nor nor[FSL_QSPI_MAX_CHIP]; -@@ -282,6 +299,7 @@ struct fsl_qspi { - u32 nor_size; - u32 nor_num; - u32 clk_rate; -+ u32 ddr_smp; - unsigned int chip_base_addr; /* We may support two chips. */ - bool has_second_chip; - bool big_endian; -@@ -309,6 +327,23 @@ static inline int needs_wakeup_wait_mode - return q->devtype_data->driver_data & QUADSPI_QUIRK_TKT245618; - } - -+static inline int has_added_amba_base_internal(struct fsl_qspi *q) -+{ -+ 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. -@@ -331,6 +366,31 @@ static u32 qspi_readl(struct fsl_qspi *q - return ioread32(addr); - } - -+static inline u32 *u8tou32(u32 *dest, const u8 *src, size_t n) -+{ -+ size_t i; -+ *dest = 0; -+ -+ n = n > 4 ? 4 : n; -+ for (i = 0; i < n; i++) -+ *dest |= *src++ << i * 8; -+ -+ return dest; -+ -+} -+ -+static inline u8 *u32tou8(u8 *dest, const u32 *src, size_t n) -+{ -+ size_t i; -+ u8 *xdest = dest; -+ -+ n = n > 4 ? 4 : n; -+ for (i = 0; i < n; i++) -+ *xdest++ = *src >> i * 8; -+ -+ return dest; -+} -+ - /* - * An IC bug makes us to re-arrange the 32-bit data. - * The following chips, such as IMX6SLX, have fixed this bug. -@@ -373,8 +433,15 @@ static void fsl_qspi_init_lut(struct fsl - void __iomem *base = q->iobase; - int rxfifo = q->devtype_data->rxfifo; - u32 lut_base; -- u8 cmd, addrlen, dummy; - int i; -+ 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); - -@@ -382,24 +449,50 @@ static void fsl_qspi_init_lut(struct fsl - for (i = 0; i < QUADSPI_LUT_NUM; i++) - qspi_writel(q, 0, base + QUADSPI_LUT_BASE + i * 4); - -- /* Quad Read */ -- lut_base = SEQID_QUAD_READ * 4; -+ /* Read */ -+ lut_base = SEQID_READ * 4; - -- if (q->nor_size <= SZ_16M) { -- cmd = SPINOR_OP_READ_1_1_4; -- addrlen = ADDR24BIT; -- dummy = 8; -- } else { -- /* use the 4-byte address */ -- cmd = SPINOR_OP_READ_1_1_4; -- addrlen = ADDR32BIT; -- dummy = 8; -- } -- -- qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), -+ if (nor->flash_read == SPI_NOR_FAST) { -+ 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, PAD1, rxfifo), -+ base + QUADSPI_LUT(lut_base + 1)); -+ } else if (nor->flash_read == SPI_NOR_QUAD) { -+ 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(DUMMY, PAD1, dummy) | LUT1(FSL_READ, PAD4, rxfifo), -+ 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) -+ | LUT1(ADDR_DDR, PAD4, addrlen), -+ base + QUADSPI_LUT(lut_base)); -+ -+ qspi_writel(q, LUT0(MODE_DDR, PAD4, 0xff) -+ | LUT1(DUMMY, PAD1, read_dm), -+ base + QUADSPI_LUT(lut_base + 1)); -+ -+ qspi_writel(q, LUT0(FSL_READ_DDR, PAD4, rxfifo) -+ | LUT1(JMP_ON_CS, PAD1, 0), -+ base + QUADSPI_LUT(lut_base + 2)); -+ } - - /* Write enable */ - lut_base = SEQID_WREN * 4; -@@ -409,16 +502,8 @@ static void fsl_qspi_init_lut(struct fsl - /* Page Program */ - lut_base = SEQID_PP * 4; - -- if (q->nor_size <= SZ_16M) { -- cmd = SPINOR_OP_PP; -- addrlen = ADDR24BIT; -- } else { -- /* use the 4-byte address */ -- cmd = SPINOR_OP_PP; -- addrlen = ADDR32BIT; -- } -- -- qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), -+ qspi_writel(q, LUT0(CMD, PAD1, nor->program_opcode) | -+ LUT1(ADDR, PAD1, addrlen), - base + QUADSPI_LUT(lut_base)); - qspi_writel(q, LUT0(FSL_WRITE, PAD1, 0), - base + QUADSPI_LUT(lut_base + 1)); -@@ -432,10 +517,8 @@ static void fsl_qspi_init_lut(struct fsl - /* Erase a sector */ - lut_base = SEQID_SE * 4; - -- cmd = q->nor[0].erase_opcode; -- addrlen = q->nor_size <= SZ_16M ? ADDR24BIT : ADDR32BIT; -- -- qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), -+ qspi_writel(q, LUT0(CMD, PAD1, nor->erase_opcode) | -+ LUT1(ADDR, PAD1, addrlen), - base + QUADSPI_LUT(lut_base)); - - /* Erase the whole chip */ -@@ -476,6 +559,44 @@ static void fsl_qspi_init_lut(struct fsl - qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_BRWR), - base + QUADSPI_LUT(lut_base)); - -+ -+ /* -+ * Flash Micron and Spansion command confilict -+ * use the same value 0x65. But it indicates different meaning. -+ */ -+ lut_base = SEQID_RDAR_OR_RD_EVCR * 4; -+ -+ if (vendor == SPANSION_S25FS_FAMILY) { -+ /* -+ * Read any device register. -+ * Used for Spansion S25FS-S family flash only. -+ */ -+ qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_SPANSION_RDAR) | -+ LUT1(ADDR, PAD1, ADDR24BIT), -+ base + QUADSPI_LUT(lut_base)); -+ qspi_writel(q, LUT0(DUMMY, PAD1, 8) | LUT1(FSL_READ, PAD1, 1), -+ base + QUADSPI_LUT(lut_base + 1)); -+ } else { -+ qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RD_EVCR), -+ base + QUADSPI_LUT(lut_base)); -+ } -+ -+ /* -+ * Write any device register. -+ * Used for Spansion S25FS-S family flash only. -+ */ -+ lut_base = SEQID_WRAR * 4; -+ qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_SPANSION_WRAR) | -+ LUT1(ADDR, PAD1, ADDR24BIT), -+ base + QUADSPI_LUT(lut_base)); -+ qspi_writel(q, LUT0(FSL_WRITE, PAD1, 1), -+ base + QUADSPI_LUT(lut_base + 1)); -+ -+ /* Write EVCR register */ -+ lut_base = SEQID_WD_EVCR * 4; -+ qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WD_EVCR), -+ base + QUADSPI_LUT(lut_base)); -+ - fsl_qspi_lock_lut(q); - } - -@@ -483,8 +604,24 @@ static void fsl_qspi_init_lut(struct fsl - static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd) - { - switch (cmd) { -+ case SPINOR_OP_READ_1_4_4_D: -+ case SPINOR_OP_READ4_1_4_4_D: -+ case SPINOR_OP_READ4_1_1_4: - case SPINOR_OP_READ_1_1_4: -- return SEQID_QUAD_READ; -+ case SPINOR_OP_READ_FAST: -+ case SPINOR_OP_READ4_FAST: -+ return SEQID_READ; -+ /* -+ * Spansion & Micron use the same command value 0x65 -+ * Spansion: SPINOR_OP_SPANSION_RDAR, read any register. -+ * Micron: SPINOR_OP_RD_EVCR, -+ * read enhanced volatile configuration register. -+ * case SPINOR_OP_RD_EVCR: -+ */ -+ case SPINOR_OP_SPANSION_RDAR: -+ return SEQID_RDAR_OR_RD_EVCR; -+ case SPINOR_OP_SPANSION_WRAR: -+ return SEQID_WRAR; - case SPINOR_OP_WREN: - return SEQID_WREN; - case SPINOR_OP_WRDI: -@@ -496,6 +633,7 @@ static int fsl_qspi_get_seqid(struct fsl - case SPINOR_OP_CHIP_ERASE: - return SEQID_CHIP_ERASE; - case SPINOR_OP_PP: -+ case SPINOR_OP_PP_4B: - return SEQID_PP; - case SPINOR_OP_RDID: - return SEQID_RDID; -@@ -507,6 +645,8 @@ static int fsl_qspi_get_seqid(struct fsl - return SEQID_EN4B; - case SPINOR_OP_BRWR: - return SEQID_BRWR; -+ case SPINOR_OP_WD_EVCR: -+ return SEQID_WD_EVCR; - default: - if (cmd == q->nor[0].erase_opcode) - return SEQID_SE; -@@ -531,8 +671,11 @@ fsl_qspi_runcmd(struct fsl_qspi *q, u8 c - /* save the reg */ - reg = qspi_readl(q, base + QUADSPI_MCR); - -- qspi_writel(q, q->memmap_phy + q->chip_base_addr + addr, -- base + QUADSPI_SFAR); -+ if (has_added_amba_base_internal(q)) -+ qspi_writel(q, q->chip_base_addr + addr, base + QUADSPI_SFAR); -+ else -+ qspi_writel(q, q->memmap_phy + q->chip_base_addr + addr, -+ base + QUADSPI_SFAR); - qspi_writel(q, QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS, - base + QUADSPI_RBCT); - qspi_writel(q, reg | QUADSPI_MCR_CLR_RXF_MASK, base + QUADSPI_MCR); -@@ -582,10 +725,10 @@ static void fsl_qspi_read_data(struct fs - q->chip_base_addr, tmp); - - if (len >= 4) { -- *((u32 *)rxbuf) = tmp; -+ u32tou8(rxbuf, &tmp, 4); - rxbuf += 4; - } else { -- memcpy(rxbuf, &tmp, len); -+ u32tou8(rxbuf, &tmp, len); - break; - } - -@@ -619,11 +762,12 @@ static inline void fsl_qspi_invalid(stru - } - - static ssize_t fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor, -- u8 opcode, unsigned int to, u32 *txbuf, -+ u8 opcode, unsigned int to, u8 *txbuf, - unsigned count) - { - int ret, i, j; - u32 tmp; -+ u8 byts; - - dev_dbg(q->dev, "to 0x%.8x:0x%.8x, len : %d\n", - q->chip_base_addr, to, count); -@@ -633,10 +777,13 @@ static ssize_t fsl_qspi_nor_write(struct - qspi_writel(q, tmp | QUADSPI_MCR_CLR_TXF_MASK, q->iobase + QUADSPI_MCR); - - /* fill the TX data to the FIFO */ -+ byts = count; - for (j = 0, i = ((count + 3) / 4); j < i; j++) { -- tmp = fsl_qspi_endian_xchg(q, *txbuf); -+ u8tou32(&tmp, txbuf, byts); -+ tmp = fsl_qspi_endian_xchg(q, tmp); - qspi_writel(q, tmp, q->iobase + QUADSPI_TBDR); -- txbuf++; -+ txbuf += 4; -+ byts -= 4; - } - - /* fill the TXFIFO upto 16 bytes for i.MX7d */ -@@ -657,11 +804,43 @@ static void fsl_qspi_set_map_addr(struct - { - int nor_size = q->nor_size; - void __iomem *base = q->iobase; -+ u32 mem_base; -+ -+ if (has_added_amba_base_internal(q)) -+ mem_base = 0x0; -+ else -+ mem_base = q->memmap_phy; -+ -+ qspi_writel(q, nor_size + mem_base, base + QUADSPI_SFA1AD); -+ qspi_writel(q, nor_size * 2 + mem_base, base + QUADSPI_SFA2AD); -+ qspi_writel(q, nor_size * 3 + mem_base, base + QUADSPI_SFB1AD); -+ qspi_writel(q, nor_size * 4 + mem_base, base + QUADSPI_SFB2AD); -+} -+ -+/* -+ * enable controller ddr quad mode to support different -+ * vender flashes ddr quad mode. -+ */ -+static void set_ddr_quad_mode(struct fsl_qspi *q) -+{ -+ u32 reg, reg2; -+ -+ reg = qspi_readl(q, q->iobase + QUADSPI_MCR); -+ -+ /* Firstly, disable the module */ -+ qspi_writel(q, reg | QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); -+ -+ /* Set the Sampling Register for DDR */ -+ reg2 = qspi_readl(q, q->iobase + QUADSPI_SMPR); -+ reg2 &= ~QUADSPI_SMPR_DDRSMP_MASK; -+ reg2 |= (((q->ddr_smp) << QUADSPI_SMPR_DDRSMP_SHIFT) & -+ QUADSPI_SMPR_DDRSMP_MASK); -+ qspi_writel(q, reg2, q->iobase + QUADSPI_SMPR); -+ -+ /* Enable the module again (enable the DDR too) */ -+ reg |= QUADSPI_MCR_DDR_EN_MASK; -+ qspi_writel(q, reg, q->iobase + QUADSPI_MCR); - -- qspi_writel(q, nor_size + q->memmap_phy, base + QUADSPI_SFA1AD); -- qspi_writel(q, nor_size * 2 + q->memmap_phy, base + QUADSPI_SFA2AD); -- qspi_writel(q, nor_size * 3 + q->memmap_phy, base + QUADSPI_SFB1AD); -- qspi_writel(q, nor_size * 4 + q->memmap_phy, base + QUADSPI_SFB2AD); - } - - /* -@@ -704,6 +883,11 @@ static void fsl_qspi_init_abh_read(struc - seqid = fsl_qspi_get_seqid(q, q->nor[0].read_opcode); - qspi_writel(q, seqid << QUADSPI_BFGENCR_SEQID_SHIFT, - q->iobase + QUADSPI_BFGENCR); -+ -+ /* enable the DDR quad read */ -+ if (q->nor->flash_read == SPI_NOR_DDR_QUAD) -+ set_ddr_quad_mode(q); -+ - } - - /* This function was used to prepare and enable QSPI clock */ -@@ -822,6 +1006,7 @@ static const struct of_device_id fsl_qsp - { .compatible = "fsl,imx7d-qspi", .data = (void *)&imx7d_data, }, - { .compatible = "fsl,imx6ul-qspi", .data = (void *)&imx6ul_data, }, - { .compatible = "fsl,ls1021a-qspi", .data = (void *)&ls1021a_data, }, -+ { .compatible = "fsl,ls2080a-qspi", .data = (void *)&ls2080a_data, }, - { /* sentinel */ } - }; - MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids); -@@ -835,8 +1020,12 @@ static int fsl_qspi_read_reg(struct spi_ - { - int ret; - struct fsl_qspi *q = nor->priv; -+ u32 to = 0; - -- ret = fsl_qspi_runcmd(q, opcode, 0, len); -+ if (opcode == SPINOR_OP_SPANSION_RDAR) -+ u8tou32(&to, nor->cmd_buf, 4); -+ -+ ret = fsl_qspi_runcmd(q, opcode, to, len); - if (ret) - return ret; - -@@ -848,9 +1037,13 @@ static int fsl_qspi_write_reg(struct spi - { - struct fsl_qspi *q = nor->priv; - int ret; -+ u32 to = 0; -+ -+ if (opcode == SPINOR_OP_SPANSION_WRAR) -+ u8tou32(&to, nor->cmd_buf, 4); - - if (!buf) { -- ret = fsl_qspi_runcmd(q, opcode, 0, 1); -+ ret = fsl_qspi_runcmd(q, opcode, to, 1); - if (ret) - return ret; - -@@ -859,7 +1052,7 @@ static int fsl_qspi_write_reg(struct spi - - } else if (len > 0) { - ret = fsl_qspi_nor_write(q, nor, opcode, 0, -- (u32 *)buf, len); -+ buf, len); - if (ret > 0) - return 0; - } else { -@@ -875,7 +1068,7 @@ static ssize_t fsl_qspi_write(struct spi - { - struct fsl_qspi *q = nor->priv; - ssize_t ret = fsl_qspi_nor_write(q, nor, nor->program_opcode, to, -- (u32 *)buf, len); -+ (u8 *)buf, len); - - /* invalid the data in the AHB buffer. */ - fsl_qspi_invalid(q); -@@ -922,7 +1115,7 @@ static ssize_t fsl_qspi_read(struct spi_ - len); - - /* Read out the data directly from the AHB buffer.*/ -- memcpy(buf, q->ahb_addr + q->chip_base_addr + from - q->memmap_offs, -+ memcpy_toio(buf, q->ahb_addr + q->chip_base_addr + from - q->memmap_offs, - len); - - return len; -@@ -980,6 +1173,8 @@ static int fsl_qspi_probe(struct platfor - struct spi_nor *nor; - struct mtd_info *mtd; - int ret, i = 0; -+ int find_node; -+ enum read_mode mode = SPI_NOR_QUAD; - - q = devm_kzalloc(dev, sizeof(*q), GFP_KERNEL); - if (!q) -@@ -1027,6 +1222,12 @@ static int fsl_qspi_probe(struct platfor - goto clk_failed; - } - -+ /* find ddrsmp value */ -+ ret = of_property_read_u32(dev->of_node, "fsl,ddr-sampling-point", -+ &q->ddr_smp); -+ if (ret) -+ q->ddr_smp = 0; -+ - /* find the irq */ - ret = platform_get_irq(pdev, 0); - if (ret < 0) { -@@ -1050,6 +1251,7 @@ static int fsl_qspi_probe(struct platfor - - mutex_init(&q->lock); - -+ find_node = 0; - /* iterate the subnodes. */ - for_each_available_child_of_node(dev->of_node, np) { - /* skip the holes */ -@@ -1076,18 +1278,25 @@ static int fsl_qspi_probe(struct platfor - ret = of_property_read_u32(np, "spi-max-frequency", - &q->clk_rate); - if (ret < 0) -- goto mutex_failed; -+ continue; - - /* set the chip address for READID */ - fsl_qspi_set_base_addr(q, nor); - -- ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD); -+ ret = of_property_read_bool(np, "m25p,fast-read"); -+ mode = (ret) ? SPI_NOR_FAST : SPI_NOR_QUAD; -+ /* Can we enable the DDR Quad Read? */ -+ ret = of_property_read_bool(np, "ddr-quad-read"); - if (ret) -- goto mutex_failed; -+ mode = SPI_NOR_DDR_QUAD; -+ -+ ret = spi_nor_scan(nor, NULL, mode); -+ if (ret) -+ continue; - - ret = mtd_device_register(mtd, NULL, 0); - if (ret) -- goto mutex_failed; -+ continue; - - /* Set the correct NOR size now. */ - if (q->nor_size == 0) { -@@ -1110,8 +1319,12 @@ static int fsl_qspi_probe(struct platfor - nor->page_size = q->devtype_data->txfifo; - - i++; -+ find_node++; - } - -+ if (find_node == 0) -+ goto mutex_failed; -+ - /* finish the rest init. */ - ret = fsl_qspi_nor_setup_last(q); - if (ret) ---- a/drivers/mtd/spi-nor/spi-nor.c -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -40,6 +40,13 @@ - #define SPI_NOR_MAX_ID_LEN 6 - #define SPI_NOR_MAX_ADDR_WIDTH 4 - -+#define SPI_NOR_MICRON_WRITE_ENABLE 0x7f -+/* Added for S25FS-S family flash */ -+#define SPINOR_CONFIG_REG3_OFFSET 0x800004 -+#define CR3V_4KB_ERASE_UNABLE 0x8 -+#define SPINOR_S25FS_FAMILY_ID 0x81 -+ -+ - struct flash_info { - char *name; - -@@ -68,7 +75,8 @@ struct flash_info { - #define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */ - #define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */ - #define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */ --#define USE_FSR BIT(7) /* use flag status register */ -+#define USE_FSR BIT(13) /* use flag status register */ -+#define SPI_NOR_DDR_QUAD_READ BIT(7) /* Flash supports DDR Quad Read */ - #define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */ - #define SPI_NOR_HAS_TB BIT(9) /* - * Flash SR has Top/Bottom (TB) protect -@@ -85,9 +93,11 @@ struct flash_info { - * Use dedicated 4byte address op codes - * to support memory size above 128Mib. - */ -+#define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ - }; - - #define JEDEC_MFR(info) ((info)->id[0]) -+#define EXT_ID(info) ((info)->id[5]) - - static const struct flash_info *spi_nor_match_id(const char *name); - -@@ -132,7 +142,7 @@ static int read_fsr(struct spi_nor *nor) - /* - * Read configuration register, returning its value in the - * location. Return the configuration register value. -- * Returns negative if error occured. -+ * Returns negative if error occurred. - */ - static int read_cr(struct spi_nor *nor) - { -@@ -160,6 +170,8 @@ static inline int spi_nor_read_dummy_cyc - case SPI_NOR_DUAL: - case SPI_NOR_QUAD: - return 8; -+ case SPI_NOR_DDR_QUAD: -+ return 6; - case SPI_NOR_NORMAL: - return 0; - } -@@ -962,6 +974,8 @@ static const struct flash_info spi_nor_i - - /* ESMT */ - { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) }, -+ { "f25l32qa", INFO(0x8c4116, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) }, -+ { "f25l64qa", INFO(0x8c4117, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_HAS_LOCK) }, - - /* Everspin */ - { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -@@ -1021,12 +1035,15 @@ static const struct flash_info spi_nor_i - { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) }, - { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, - { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4, SECT_4K) }, -+ { "mx25u4035", INFO(0xc22533, 0, 64 * 1024, 8, SECT_4K) }, -+ { "mx25u8035", INFO(0xc22534, 0, 64 * 1024, 16, SECT_4K) }, - { "mx25u3235f", INFO(0xc22536, 0, 64 * 1024, 64, 0) }, - { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, - { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, - { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, - { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, -- { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, -+ { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K) }, - { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, - { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) }, - { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, -@@ -1040,10 +1057,11 @@ static const struct flash_info spi_nor_i - { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, - { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, - { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, -+ { "n25q256ax1", INFO(0x20bb19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, - { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, - { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, -- { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, -- { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, -+ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, -+ { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, - - /* PMC */ - { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, -@@ -1061,8 +1079,11 @@ static const struct flash_info spi_nor_i - { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, - { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, - { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, -- { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25fs256s1", INFO6(0x010219, 0x4d0181, 64 * 1024, 512, 0)}, -+ { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_QUAD_READ -+ | SPI_NOR_DDR_QUAD_READ) }, - { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)}, - { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, - { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, - { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, -@@ -1136,7 +1157,15 @@ static const struct flash_info spi_nor_i - { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, - { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, - { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, -+ { -+ "w25q16dw", INFO(0xef6015, 0, 64 * 1024, 32, -+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | -+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) -+ }, - { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "w25q20cl", INFO(0xef4012, 0, 64 * 1024, 4, SECT_4K) }, -+ { "w25q20bw", INFO(0xef5012, 0, 64 * 1024, 4, SECT_4K) }, -+ { "w25q20ew", INFO(0xef6012, 0, 64 * 1024, 4, SECT_4K) }, - { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, - { - "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, -@@ -1208,6 +1237,53 @@ static const struct flash_info *spi_nor_ - id[0], id[1], id[2]); - return ERR_PTR(-ENODEV); - } -+/* -+ * The S25FS-S family physical sectors may be configured as a -+ * hybrid combination of eight 4-kB parameter sectors -+ * at the top or bottom of the address space with all -+ * but one of the remaining sectors being uniform size. -+ * The Parameter Sector Erase commands (20h or 21h) must -+ * be used to erase the 4-kB parameter sectors individually. -+ * The Sector (uniform sector) Erase commands (D8h or DCh) -+ * must be used to erase any of the remaining -+ * sectors, including the portion of highest or lowest address -+ * sector that is not overlaid by the parameter sectors. -+ * The uniform sector erase command has no effect on parameter sectors. -+ */ -+static int spansion_s25fs_disable_4kb_erase(struct spi_nor *nor) -+{ -+ struct fsl_qspi *q; -+ u32 cr3v_addr = SPINOR_CONFIG_REG3_OFFSET; -+ u8 cr3v = 0x0; -+ int ret = 0x0; -+ -+ q = nor->priv; -+ -+ nor->cmd_buf[2] = cr3v_addr >> 16; -+ nor->cmd_buf[1] = cr3v_addr >> 8; -+ nor->cmd_buf[0] = cr3v_addr >> 0; -+ -+ ret = nor->read_reg(nor, SPINOR_OP_SPANSION_RDAR, &cr3v, 1); -+ if (ret) -+ return ret; -+ if (cr3v & CR3V_4KB_ERASE_UNABLE) -+ return 0; -+ ret = nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0); -+ if (ret) -+ return ret; -+ cr3v = CR3V_4KB_ERASE_UNABLE; -+ nor->program_opcode = SPINOR_OP_SPANSION_WRAR; -+ nor->write(nor, cr3v_addr, 1, &cr3v); -+ -+ 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; -+} -+ - - static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -@@ -1427,7 +1503,7 @@ static int macronix_quad_enable(struct s - * Write status Register and configuration register with 2 bytes - * The first byte will be written to the status register, while the - * second byte will be written to the configuration register. -- * Return negative if error occured. -+ * Return negative if error occurred. - */ - static int write_sr_cr(struct spi_nor *nor, u16 val) - { -@@ -1475,6 +1551,24 @@ static int spansion_quad_enable(struct s - return 0; - } - -+static int set_ddr_quad_mode(struct spi_nor *nor, const struct flash_info *info) -+{ -+ int status; -+ -+ switch (JEDEC_MFR(info)) { -+ case SNOR_MFR_SPANSION: -+ status = spansion_quad_enable(nor); -+ if (status) { -+ dev_err(nor->dev, "Spansion DDR quad-read not enabled\n"); -+ return status; -+ } -+ return status; -+ default: -+ return -EINVAL; -+ } -+} -+ -+ - static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info) - { - int status; -@@ -1621,9 +1715,25 @@ int spi_nor_scan(struct spi_nor *nor, co - write_sr(nor, 0); - spi_nor_wait_till_ready(nor); - } -+ if (JEDEC_MFR(info) == SNOR_MFR_MICRON) { -+ ret = read_sr(nor); -+ ret &= SPI_NOR_MICRON_WRITE_ENABLE; -+ -+ write_enable(nor); -+ write_sr(nor, ret); -+ } -+ -+ if (EXT_ID(info) == SPINOR_S25FS_FAMILY_ID) { -+ ret = spansion_s25fs_disable_4kb_erase(nor); -+ if (ret) -+ return ret; -+ } -+ - - 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; -@@ -1657,6 +1767,8 @@ int spi_nor_scan(struct spi_nor *nor, co - nor->flags |= SNOR_F_USE_FSR; - if (info->flags & SPI_NOR_HAS_TB) - nor->flags |= SNOR_F_HAS_SR_TB; -+ if (info->flags & NO_CHIP_ERASE) -+ nor->flags |= SNOR_F_NO_OP_CHIP_ERASE; - - #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS - /* prefer "small sector" erase if possible */ -@@ -1696,9 +1808,15 @@ int spi_nor_scan(struct spi_nor *nor, co - /* Some devices cannot do fast-read, no matter what DT tells us */ - if (info->flags & SPI_NOR_NO_FR) - nor->flash_read = SPI_NOR_NORMAL; -- -- /* Quad/Dual-read mode takes precedence over fast/normal */ -- if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { -+ /* DDR Quad/Quad/Dual-read mode takes precedence over fast/normal */ -+ if (mode == SPI_NOR_DDR_QUAD && info->flags & SPI_NOR_DDR_QUAD_READ) { -+ ret = set_ddr_quad_mode(nor, info); -+ if (ret) { -+ dev_err(dev, "DDR quad mode not supported\n"); -+ return ret; -+ } -+ nor->flash_read = SPI_NOR_DDR_QUAD; -+ } else if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { - ret = set_quad_mode(nor, info); - if (ret) { - dev_err(dev, "quad mode not supported\n"); -@@ -1711,6 +1829,9 @@ int spi_nor_scan(struct spi_nor *nor, co - - /* Default commands */ - switch (nor->flash_read) { -+ case SPI_NOR_DDR_QUAD: -+ nor->read_opcode = SPINOR_OP_READ4_1_4_4_D; -+ break; - case SPI_NOR_QUAD: - nor->read_opcode = SPINOR_OP_READ_1_1_4; - break; ---- a/include/linux/mtd/spi-nor.h -+++ b/include/linux/mtd/spi-nor.h -@@ -31,10 +31,10 @@ - - /* - * Note on opcode nomenclature: some opcodes have a format like -- * SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number -+ * SPINOR_OP_FUNCTION{4,}_x_y_z{_D}. The numbers x, y,and z stand for the number - * of I/O lines used for the opcode, address, and data (respectively). The - * FUNCTION has an optional suffix of '4', to represent an opcode which -- * requires a 4-byte (32-bit) address. -+ * requires a 4-byte (32-bit) address. The suffix of 'D' stands for the - */ - - /* Flash opcodes. */ -@@ -46,7 +46,9 @@ - #define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual Output SPI) */ - #define SPINOR_OP_READ_1_2_2 0xbb /* Read data bytes (Dual I/O SPI) */ - #define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad Output SPI) */ -+#define SPINOR_OP_READ_1_4_4_D 0xed /* Read data bytes (DDR Quad SPI) */ - #define SPINOR_OP_READ_1_4_4 0xeb /* Read data bytes (Quad I/O SPI) */ -+#define SPINOR_OP_READ4_1_4_4_D 0xee /* Read data bytes (DDR Quad SPI) */ - #define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */ - #define SPINOR_OP_PP_1_1_4 0x32 /* Quad page program */ - #define SPINOR_OP_PP_1_4_4 0x38 /* Quad page program */ -@@ -62,9 +64,11 @@ - /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ - #define SPINOR_OP_READ_4B 0x13 /* Read data bytes (low frequency) */ - #define SPINOR_OP_READ_FAST_4B 0x0c /* Read data bytes (high frequency) */ -+#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */ - #define SPINOR_OP_READ_1_1_2_4B 0x3c /* Read data bytes (Dual Output SPI) */ - #define SPINOR_OP_READ_1_2_2_4B 0xbc /* Read data bytes (Dual I/O SPI) */ - #define SPINOR_OP_READ_1_1_4_4B 0x6c /* Read data bytes (Quad Output SPI) */ -+#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */ - #define SPINOR_OP_READ_1_4_4_4B 0xec /* Read data bytes (Quad I/O SPI) */ - #define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */ - #define SPINOR_OP_PP_1_1_4_4B 0x34 /* Quad page program */ -@@ -94,6 +98,10 @@ - /* Used for Spansion flashes only. */ - #define SPINOR_OP_BRWR 0x17 /* Bank register write */ - -+/* Used for Spansion S25FS-S family flash only. */ -+#define SPINOR_OP_SPANSION_RDAR 0x65 /* Read any device register */ -+#define SPINOR_OP_SPANSION_WRAR 0x71 /* Write any device register */ -+ - /* Used for Micron flashes only. */ - #define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */ - #define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */ -@@ -124,6 +132,7 @@ enum read_mode { - SPI_NOR_FAST, - SPI_NOR_DUAL, - SPI_NOR_QUAD, -+ SPI_NOR_DDR_QUAD, - }; - - #define SPI_NOR_MAX_CMD_SIZE 8 -@@ -189,6 +198,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); -- cgit v1.2.3