diff options
Diffstat (limited to 'target/linux/layerscape/patches-4.14/818-qspi-support-layerscape.patch')
-rw-r--r-- | target/linux/layerscape/patches-4.14/818-qspi-support-layerscape.patch | 745 |
1 files changed, 0 insertions, 745 deletions
diff --git a/target/linux/layerscape/patches-4.14/818-qspi-support-layerscape.patch b/target/linux/layerscape/patches-4.14/818-qspi-support-layerscape.patch deleted file mode 100644 index 1546e4b6a7..0000000000 --- a/target/linux/layerscape/patches-4.14/818-qspi-support-layerscape.patch +++ /dev/null @@ -1,745 +0,0 @@ -From fe21ef44284a3aa6fd80448e4ab2e1e8a55fb926 Mon Sep 17 00:00:00 2001 -From: Biwen Li <biwen.li@nxp.com> -Date: Wed, 17 Apr 2019 18:58:59 +0800 -Subject: [PATCH] qspi: support layerscape - -This is an integrated patch of qspi for layerscape - -Signed-off-by: Abhimanyu Saini <abhimanyu.saini@nxp.com> -Signed-off-by: Biwen Li <biwen.li@nxp.com> -Signed-off-by: Chuanhua Han <chuanhua.han@nxp.com> -Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr> -Signed-off-by: Mark Brown <broonie@kernel.org> -Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> -Signed-off-by: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com> -Signed-off-by: Suresh Gupta <suresh.gupta@nxp.com> -Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -Signed-off-by: Yogesh Gaur <yogeshnarayan.gaur@nxp.com> ---- - drivers/mtd/spi-nor/fsl-quadspi.c | 444 +++++++++++++++++++----------- - drivers/mtd/spi-nor/spi-nor.c | 5 + - drivers/spi/spi-fsl-dspi.c | 4 +- - 3 files changed, 291 insertions(+), 162 deletions(-) - ---- a/drivers/mtd/spi-nor/fsl-quadspi.c -+++ b/drivers/mtd/spi-nor/fsl-quadspi.c -@@ -41,6 +41,7 @@ - #define QUADSPI_QUIRK_TKT253890 (1 << 2) - /* Controller cannot wake up from wait mode, TKT245618 */ - #define QUADSPI_QUIRK_TKT245618 (1 << 3) -+#define QUADSPI_ADDR_REMAP (1 << 4) - - /* The registers */ - #define QUADSPI_MCR 0x00 -@@ -183,7 +184,7 @@ - - /* Macros for constructing the LUT register. */ - #define LUT0(ins, pad, opr) \ -- (((opr) << OPRND0_SHIFT) | ((LUT_##pad) << PAD0_SHIFT) | \ -+ (((opr) << OPRND0_SHIFT) | ((pad) << PAD0_SHIFT) | \ - ((LUT_##ins) << INSTR0_SHIFT)) - - #define LUT1(ins, pad, opr) (LUT0(ins, pad, opr) << OPRND1_SHIFT) -@@ -193,27 +194,29 @@ - #define QUADSPI_LUT_NUM 64 - - /* SEQID -- we can have 16 seqids at most. */ --#define SEQID_READ 0 --#define SEQID_WREN 1 --#define SEQID_WRDI 2 --#define SEQID_RDSR 3 --#define SEQID_SE 4 --#define SEQID_CHIP_ERASE 5 --#define SEQID_PP 6 --#define SEQID_RDID 7 --#define SEQID_WRSR 8 --#define SEQID_RDCR 9 --#define SEQID_EN4B 10 --#define SEQID_BRWR 11 -+/* LUT0 programmed by bootloader, for run-time create entry for LUT seqid 1 */ -+#define SEQID_LUT0_BOOTLOADER 0 -+#define SEQID_LUT1_RUNTIME 1 -+#define SEQID_LUT2_AHBREAD 2 - - #define QUADSPI_MIN_IOMAP SZ_4M - -+enum fsl_qspi_ops { -+ FSL_QSPI_OPS_READ = 0, -+ FSL_QSPI_OPS_WRITE, -+ FSL_QSPI_OPS_ERASE, -+ FSL_QSPI_OPS_READ_REG, -+ FSL_QSPI_OPS_WRITE_REG, -+ FSL_QSPI_OPS_WRITE_BUF_REG, -+}; -+ - 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 { -@@ -267,6 +270,15 @@ static struct fsl_qspi_devtype_data ls10 - .driver_data = 0, - }; - -+static const struct fsl_qspi_devtype_data ls2080a_data = { -+ .devtype = FSL_QUADSPI_LS2080A, -+ .rxfifo = 128, -+ .txfifo = 64, -+ .ahb_buf_size = 1024, -+ .driver_data = QUADSPI_QUIRK_TKT253890 | QUADSPI_ADDR_REMAP, -+}; -+ -+ - #define FSL_QSPI_MAX_CHIP 4 - struct fsl_qspi { - struct spi_nor nor[FSL_QSPI_MAX_CHIP]; -@@ -310,6 +322,22 @@ static inline int needs_wakeup_wait_mode - } - - /* -+ * QSPI memory regions split into two parts: a 256MB region that is located -+ * in the least significant 4GB of the SoC address space and a 3.75GB region -+ * that is located above the least significant 4GB of the SoC address space. -+ * -+ * The 4GB QSPI address space map is shown below. -+ * -+ * SoC Address QSPI Address -+ * 0x00_2000_0000-0x00_2FFF_FFFF 0x00_0000_0000-0x00_0FFF_FFFF First 256MB -+ * 0x04_1000_0000-0x04_FFFF_FFFF 0x00_1000_0000-0x00_FFFF_FFFF Last 3.75GB -+ */ -+static inline int need_address_remap(struct fsl_qspi *q) -+{ -+ return q->devtype_data->driver_data & QUADSPI_ADDR_REMAP; -+} -+ -+/* - * R/W functions for big- or little-endian registers: - * The qSPI controller's endian is independent of the CPU core's endian. - * So far, although the CPU core is little-endian but the qSPI have two -@@ -368,137 +396,160 @@ static irqreturn_t fsl_qspi_irq_handler( - return IRQ_HANDLED; - } - --static void fsl_qspi_init_lut(struct fsl_qspi *q) -+static inline s8 pad_count(s8 pad_val) - { -+ s8 count = -1; -+ -+ if (!pad_val) -+ return 0; -+ -+ while (pad_val) { -+ pad_val >>= 1; -+ count++; -+ } -+ return count; -+} -+ -+/* -+ * Prepare LUT entry for the input cmd. -+ * Protocol info is present in instance of struct spi_nor, using which fields -+ * like cmd, data, addrlen along with pad info etc can be parsed. -+ */ -+static void fsl_qspi_prepare_lut(struct spi_nor *nor, -+ enum fsl_qspi_ops ops, u8 cmd) -+{ -+ struct fsl_qspi *q = nor->priv; - void __iomem *base = q->iobase; - int rxfifo = q->devtype_data->rxfifo; -+ int txfifo = q->devtype_data->txfifo; - u32 lut_base; -- int i; -+ u8 cmd_pad, addr_pad, data_pad, dummy_pad; -+ enum spi_nor_protocol protocol = 0; -+ u8 addrlen = 0; -+ u8 read_dm, opcode; -+ int stop_lut; -+ -+ read_dm = opcode = cmd_pad = addr_pad = data_pad = dummy_pad = 0; -+ -+ switch (ops) { -+ case FSL_QSPI_OPS_READ_REG: -+ case FSL_QSPI_OPS_WRITE_REG: -+ case FSL_QSPI_OPS_WRITE_BUF_REG: -+ opcode = cmd; -+ protocol = nor->reg_proto; -+ break; -+ case FSL_QSPI_OPS_READ: -+ opcode = cmd; -+ read_dm = nor->read_dummy; -+ protocol = nor->read_proto; -+ break; -+ case FSL_QSPI_OPS_WRITE: -+ opcode = cmd; -+ protocol = nor->write_proto; -+ break; -+ case FSL_QSPI_OPS_ERASE: -+ opcode = cmd; -+ break; -+ default: -+ dev_err(q->dev, "Unsupported operation 0x%.2x\n", ops); -+ return; -+ } -+ -+ if (protocol) { -+ cmd_pad = spi_nor_get_protocol_inst_nbits(protocol); -+ addr_pad = spi_nor_get_protocol_addr_nbits(protocol); -+ data_pad = spi_nor_get_protocol_data_nbits(protocol); -+ } -+ -+ dummy_pad = data_pad; - -- 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; -+ dev_dbg(q->dev, "ops:%x opcode:%x pad[cmd:%d, addr:%d, data:%d]\n", -+ ops, opcode, cmd_pad, addr_pad, data_pad); - - fsl_qspi_unlock_lut(q); - -- /* Clear all the LUT table */ -- for (i = 0; i < QUADSPI_LUT_NUM; i++) -- qspi_writel(q, 0, base + QUADSPI_LUT_BASE + i * 4); -- -- /* Read */ -- lut_base = SEQID_READ * 4; -- -- 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)); -- -- /* Write enable */ -- lut_base = SEQID_WREN * 4; -- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WREN), -- base + QUADSPI_LUT(lut_base)); -- -- /* Page Program */ -- lut_base = SEQID_PP * 4; -- -- 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)); -- -- /* Read Status */ -- lut_base = SEQID_RDSR * 4; -- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDSR) | -- LUT1(FSL_READ, PAD1, 0x1), -- base + QUADSPI_LUT(lut_base)); -- -- /* Erase a sector */ -- lut_base = SEQID_SE * 4; -- -- qspi_writel(q, LUT0(CMD, PAD1, nor->erase_opcode) | -- LUT1(ADDR, PAD1, addrlen), -- base + QUADSPI_LUT(lut_base)); -- -- /* Erase the whole chip */ -- lut_base = SEQID_CHIP_ERASE * 4; -- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_CHIP_ERASE), -- base + QUADSPI_LUT(lut_base)); -- -- /* READ ID */ -- lut_base = SEQID_RDID * 4; -- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDID) | -- LUT1(FSL_READ, PAD1, 0x8), -- base + QUADSPI_LUT(lut_base)); -- -- /* Write Register */ -- lut_base = SEQID_WRSR * 4; -- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WRSR) | -- LUT1(FSL_WRITE, PAD1, 0x2), -- base + QUADSPI_LUT(lut_base)); -- -- /* Read Configuration Register */ -- lut_base = SEQID_RDCR * 4; -- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDCR) | -- LUT1(FSL_READ, PAD1, 0x1), -- base + QUADSPI_LUT(lut_base)); -- -- /* Write disable */ -- lut_base = SEQID_WRDI * 4; -- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WRDI), -- base + QUADSPI_LUT(lut_base)); -- -- /* Enter 4 Byte Mode (Micron) */ -- lut_base = SEQID_EN4B * 4; -- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_EN4B), -- base + QUADSPI_LUT(lut_base)); -- -- /* Enter 4 Byte Mode (Spansion) */ -- lut_base = SEQID_BRWR * 4; -- qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_BRWR), -- base + QUADSPI_LUT(lut_base)); -+ /* Dynamic LUT */ -+ lut_base = SEQID_LUT1_RUNTIME * 4; -+ if (ops == FSL_QSPI_OPS_READ) -+ lut_base = SEQID_LUT2_AHBREAD * 4; -+ -+ /* default, STOP instruction to be programmed in (lut_base + 1) reg */ -+ stop_lut = 1; -+ switch (ops) { -+ case FSL_QSPI_OPS_READ_REG: -+ qspi_writel(q, LUT0(CMD, pad_count(cmd_pad), opcode) | -+ LUT1(FSL_READ, pad_count(data_pad), rxfifo), -+ base + QUADSPI_LUT(lut_base)); -+ break; -+ case FSL_QSPI_OPS_WRITE_REG: -+ qspi_writel(q, LUT0(CMD, pad_count(cmd_pad), opcode), -+ base + QUADSPI_LUT(lut_base)); -+ break; -+ case FSL_QSPI_OPS_WRITE_BUF_REG: -+ qspi_writel(q, LUT0(CMD, pad_count(cmd_pad), opcode) | -+ LUT1(FSL_WRITE, pad_count(data_pad), txfifo), -+ base + QUADSPI_LUT(lut_base)); -+ break; -+ case FSL_QSPI_OPS_READ: -+ case FSL_QSPI_OPS_WRITE: -+ case FSL_QSPI_OPS_ERASE: -+ /* Common for Read, Write and Erase ops. */ -+ -+ addrlen = (nor->addr_width == 3) ? ADDR24BIT : ADDR32BIT; -+ -+ qspi_writel(q, LUT0(CMD, pad_count(cmd_pad), opcode) | -+ LUT1(ADDR, pad_count(addr_pad), addrlen), -+ base + QUADSPI_LUT(lut_base)); -+ /* -+ * For Erase ops - Data and Dummy not required. -+ * For Write ops - Dummy not required. -+ */ - -- fsl_qspi_lock_lut(q); --} -+ if (ops == FSL_QSPI_OPS_READ) { - --/* Get the SEQID for the command */ --static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd) --{ -- switch (cmd) { -- case SPINOR_OP_READ_1_1_4: -- case SPINOR_OP_READ_1_1_4_4B: -- return SEQID_READ; -- case SPINOR_OP_WREN: -- return SEQID_WREN; -- case SPINOR_OP_WRDI: -- return SEQID_WRDI; -- case SPINOR_OP_RDSR: -- return SEQID_RDSR; -- case SPINOR_OP_SE: -- return SEQID_SE; -- case SPINOR_OP_CHIP_ERASE: -- return SEQID_CHIP_ERASE; -- case SPINOR_OP_PP: -- return SEQID_PP; -- case SPINOR_OP_RDID: -- return SEQID_RDID; -- case SPINOR_OP_WRSR: -- return SEQID_WRSR; -- case SPINOR_OP_RDCR: -- return SEQID_RDCR; -- case SPINOR_OP_EN4B: -- return SEQID_EN4B; -- case SPINOR_OP_BRWR: -- return SEQID_BRWR; -+ /* -+ * For cmds SPINOR_OP_READ and SPINOR_OP_READ_4B value -+ * of dummy cycles are 0. -+ */ -+ if (read_dm) -+ qspi_writel(q, -+ LUT0(DUMMY, pad_count(dummy_pad), -+ read_dm) | -+ LUT1(FSL_READ, pad_count(data_pad), -+ rxfifo), -+ base + QUADSPI_LUT(lut_base + 1)); -+ else -+ qspi_writel(q, -+ LUT0(FSL_READ, pad_count(data_pad), -+ rxfifo), -+ base + QUADSPI_LUT(lut_base + 1)); -+ -+ stop_lut = 2; -+ -+ /* TODO Add condition to check if READ is IP/AHB. */ -+ -+ /* For AHB read, add seqid in BFGENCR register. */ -+ qspi_writel(q, -+ SEQID_LUT2_AHBREAD << -+ QUADSPI_BFGENCR_SEQID_SHIFT, -+ q->iobase + QUADSPI_BFGENCR); -+ } -+ -+ if (ops == FSL_QSPI_OPS_WRITE) { -+ qspi_writel(q, LUT0(FSL_WRITE, pad_count(data_pad), 0), -+ base + QUADSPI_LUT(lut_base + 1)); -+ stop_lut = 2; -+ } -+ break; - default: -- if (cmd == q->nor[0].erase_opcode) -- return SEQID_SE; -- dev_err(q->dev, "Unsupported cmd 0x%.2x\n", cmd); -+ dev_err(q->dev, "Unsupported operation 0x%.2x\n", ops); - break; - } -- return -EINVAL; -+ -+ /* prepare LUT for STOP instruction. */ -+ qspi_writel(q, 0, base + QUADSPI_LUT(lut_base + stop_lut)); -+ -+ fsl_qspi_lock_lut(q); - } - - static int -@@ -508,6 +559,10 @@ fsl_qspi_runcmd(struct fsl_qspi *q, u8 c - int seqid; - u32 reg, reg2; - int err; -+ u32 memmap_phyadd = q->memmap_phy; -+ -+ if (need_address_remap(q)) -+ memmap_phyadd = 0; - - init_completion(&q->c); - dev_dbg(q->dev, "to 0x%.8x:0x%.8x, len:%d, cmd:%.2x\n", -@@ -516,7 +571,7 @@ 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, -+ qspi_writel(q, memmap_phyadd + q->chip_base_addr + addr, - base + QUADSPI_SFAR); - qspi_writel(q, QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS, - base + QUADSPI_RBCT); -@@ -533,7 +588,7 @@ fsl_qspi_runcmd(struct fsl_qspi *q, u8 c - } while (1); - - /* trigger the LUT now */ -- seqid = fsl_qspi_get_seqid(q, cmd); -+ seqid = SEQID_LUT1_RUNTIME; - qspi_writel(q, (seqid << QUADSPI_IPCR_SEQID_SHIFT) | len, - base + QUADSPI_IPCR); - -@@ -609,6 +664,7 @@ static ssize_t fsl_qspi_nor_write(struct - { - 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); -@@ -618,10 +674,18 @@ 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); -+ if(byts >= 4) -+ tmp = fsl_qspi_endian_xchg(q, *txbuf); -+ else { -+ memcpy(&tmp, txbuf, byts); -+ tmp = fsl_qspi_endian_xchg(q, tmp); -+ } -+ - qspi_writel(q, tmp, q->iobase + QUADSPI_TBDR); - txbuf++; -+ byts -= 4; - } - - /* fill the TXFIFO upto 16 bytes for i.MX7d */ -@@ -642,11 +706,15 @@ static void fsl_qspi_set_map_addr(struct - { - int nor_size = q->nor_size; - void __iomem *base = q->iobase; -+ u32 memmap_phyadd = q->memmap_phy; -+ -+ if (need_address_remap(q)) -+ memmap_phyadd = 0; - -- 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); -+ qspi_writel(q, nor_size + memmap_phyadd, base + QUADSPI_SFA1AD); -+ qspi_writel(q, nor_size * 2 + memmap_phyadd, base + QUADSPI_SFA2AD); -+ qspi_writel(q, nor_size * 3 + memmap_phyadd, base + QUADSPI_SFB1AD); -+ qspi_writel(q, nor_size * 4 + memmap_phyadd, base + QUADSPI_SFB2AD); - } - - /* -@@ -662,7 +730,7 @@ static void fsl_qspi_set_map_addr(struct - * causes the controller to clear the buffer, and use the sequence pointed - * by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash. - */ --static void fsl_qspi_init_abh_read(struct fsl_qspi *q) -+static void fsl_qspi_init_ahb_read(struct fsl_qspi *q) - { - void __iomem *base = q->iobase; - int seqid; -@@ -685,8 +753,8 @@ static void fsl_qspi_init_abh_read(struc - qspi_writel(q, 0, base + QUADSPI_BUF1IND); - qspi_writel(q, 0, base + QUADSPI_BUF2IND); - -- /* Set the default lut sequence for AHB Read. */ -- seqid = fsl_qspi_get_seqid(q, q->nor[0].read_opcode); -+ /* Set dynamic LUT entry as lut sequence for AHB Read . */ -+ seqid = SEQID_LUT2_AHBREAD; - qspi_writel(q, seqid << QUADSPI_BFGENCR_SEQID_SHIFT, - q->iobase + QUADSPI_BFGENCR); - } -@@ -729,7 +797,6 @@ static int fsl_qspi_nor_setup(struct fsl - void __iomem *base = q->iobase; - u32 reg; - int ret; -- - /* disable and unprepare clock to avoid glitch pass to controller */ - fsl_qspi_clk_disable_unprep(q); - -@@ -747,9 +814,6 @@ static int fsl_qspi_nor_setup(struct fsl - base + QUADSPI_MCR); - udelay(1); - -- /* Init the LUT table. */ -- fsl_qspi_init_lut(q); -- - /* Disable the module */ - qspi_writel(q, QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK, - base + QUADSPI_MCR); -@@ -770,6 +834,9 @@ static int fsl_qspi_nor_setup(struct fsl - /* enable the interrupt */ - qspi_writel(q, QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER); - -+ /* Init for AHB read */ -+ fsl_qspi_init_ahb_read(q); -+ - return 0; - } - -@@ -792,12 +859,6 @@ static int fsl_qspi_nor_setup_last(struc - if (ret) - return ret; - -- /* Init the LUT table again. */ -- fsl_qspi_init_lut(q); -- -- /* Init for AHB read */ -- fsl_qspi_init_abh_read(q); -- - return 0; - } - -@@ -807,6 +868,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 = &ls2080a_data, }, - { /* sentinel */ } - }; - MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids); -@@ -821,6 +883,7 @@ static int fsl_qspi_read_reg(struct spi_ - int ret; - struct fsl_qspi *q = nor->priv; - -+ fsl_qspi_prepare_lut(nor, FSL_QSPI_OPS_READ_REG, opcode); - ret = fsl_qspi_runcmd(q, opcode, 0, len); - if (ret) - return ret; -@@ -835,6 +898,8 @@ static int fsl_qspi_write_reg(struct spi - int ret; - - if (!buf) { -+ /* Prepare LUT for WRITE_REG cmd with input BUF as NULL. */ -+ fsl_qspi_prepare_lut(nor, FSL_QSPI_OPS_WRITE_REG, opcode); - ret = fsl_qspi_runcmd(q, opcode, 0, 1); - if (ret) - return ret; -@@ -843,6 +908,8 @@ static int fsl_qspi_write_reg(struct spi - fsl_qspi_invalid(q); - - } else if (len > 0) { -+ /* Prepare LUT for WRITE_REG cmd with input BUF non-NULL. */ -+ fsl_qspi_prepare_lut(nor, FSL_QSPI_OPS_WRITE_BUF_REG, opcode); - ret = fsl_qspi_nor_write(q, nor, opcode, 0, - (u32 *)buf, len); - if (ret > 0) -@@ -859,8 +926,11 @@ static ssize_t fsl_qspi_write(struct spi - size_t len, const u_char *buf) - { - struct fsl_qspi *q = nor->priv; -- ssize_t ret = fsl_qspi_nor_write(q, nor, nor->program_opcode, to, -- (u32 *)buf, len); -+ ssize_t ret; -+ -+ fsl_qspi_prepare_lut(nor, FSL_QSPI_OPS_WRITE, nor->program_opcode); -+ ret = fsl_qspi_nor_write(q, nor, nor->program_opcode, to, -+ (u32 *)buf, len); - - /* invalid the data in the AHB buffer. */ - fsl_qspi_invalid(q); -@@ -873,6 +943,8 @@ static ssize_t fsl_qspi_read(struct spi_ - struct fsl_qspi *q = nor->priv; - u8 cmd = nor->read_opcode; - -+ fsl_qspi_prepare_lut(nor, FSL_QSPI_OPS_READ, nor->read_opcode); -+ - /* if necessary,ioremap buffer before AHB read, */ - if (!q->ahb_addr) { - q->memmap_offs = q->chip_base_addr + from; -@@ -907,8 +979,9 @@ 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, -- len); -+ memcpy_fromio(buf, -+ q->ahb_addr + q->chip_base_addr + from - q->memmap_offs, -+ len); - - return len; - } -@@ -921,6 +994,7 @@ static int fsl_qspi_erase(struct spi_nor - dev_dbg(nor->dev, "%dKiB at 0x%08x:0x%08x\n", - nor->mtd.erasesize / 1024, q->chip_base_addr, (u32)offs); - -+ fsl_qspi_prepare_lut(nor, FSL_QSPI_OPS_ERASE, nor->erase_opcode); - ret = fsl_qspi_runcmd(q, nor->erase_opcode, offs, 0); - if (ret) - return ret; -@@ -958,17 +1032,14 @@ static void fsl_qspi_unprep(struct spi_n - - static int fsl_qspi_probe(struct platform_device *pdev) - { -- const struct spi_nor_hwcaps hwcaps = { -- .mask = SNOR_HWCAPS_READ_1_1_4 | -- SNOR_HWCAPS_PP, -- }; -+ struct spi_nor_hwcaps hwcaps; - struct device_node *np = pdev->dev.of_node; - struct device *dev = &pdev->dev; - struct fsl_qspi *q; - struct resource *res; - struct spi_nor *nor; - struct mtd_info *mtd; -- int ret, i = 0; -+ int ret, i = 0, value; - - q = devm_kzalloc(dev, sizeof(*q), GFP_KERNEL); - if (!q) -@@ -1041,6 +1112,10 @@ static int fsl_qspi_probe(struct platfor - - /* iterate the subnodes. */ - for_each_available_child_of_node(dev->of_node, np) { -+ /* Reset hwcaps mask to minimal caps for the slave node. */ -+ hwcaps.mask = SNOR_HWCAPS_READ | SNOR_HWCAPS_PP; -+ value = 0; -+ - /* skip the holes */ - if (!q->has_second_chip) - i *= 2; -@@ -1070,6 +1145,51 @@ static int fsl_qspi_probe(struct platfor - /* set the chip address for READID */ - fsl_qspi_set_base_addr(q, nor); - -+ /* -+ * If spi-rx-bus-width and spi-tx-bus-width not defined assign -+ * default hardware capabilities SNOR_HWCAPS_READ_1_1_4 and -+ * SNOR_HWCAPS_PP supported by the Quad-SPI controller. -+ */ -+ if (!of_property_read_u32(np, "spi-rx-bus-width", &value)) { -+ switch (value) { -+ case 1: -+ hwcaps.mask |= SNOR_HWCAPS_READ | -+ SNOR_HWCAPS_READ_FAST; -+ break; -+ case 2: -+ hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2 | -+ SNOR_HWCAPS_READ_1_2_2; -+ break; -+ case 4: -+ hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4 | -+ SNOR_HWCAPS_READ_1_4_4; -+ break; -+ default: -+ dev_err(dev, -+ "spi-rx-bus-width %d not supported\n", -+ value); -+ break; -+ } -+ } else -+ hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; -+ -+ if (!of_property_read_u32(np, "spi-tx-bus-width", &value)) { -+ switch (value) { -+ case 1: -+ hwcaps.mask |= SNOR_HWCAPS_PP; -+ break; -+ case 4: -+ hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4 | -+ SNOR_HWCAPS_PP_1_4_4; -+ break; -+ default: -+ dev_err(dev, -+ "spi-tx-bus-width %d not supported\n", -+ value); -+ break; -+ } -+ } -+ - ret = spi_nor_scan(nor, NULL, &hwcaps); - if (ret) - goto mutex_failed; -@@ -1098,6 +1218,8 @@ static int fsl_qspi_probe(struct platfor - if (nor->page_size > q->devtype_data->txfifo) - nor->page_size = q->devtype_data->txfifo; - -+ /*required for memory mapped AHB read*/ -+ fsl_qspi_prepare_lut(nor, FSL_QSPI_OPS_READ, nor->read_opcode); - i++; - } - -@@ -1106,6 +1228,8 @@ static int fsl_qspi_probe(struct platfor - if (ret) - goto last_init_failed; - -+ -+ - fsl_qspi_clk_disable_unprep(q); - return 0; - ---- a/drivers/mtd/spi-nor/spi-nor.c -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -1159,6 +1159,11 @@ 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) }, ---- a/drivers/spi/spi-fsl-dspi.c -+++ b/drivers/spi/spi-fsl-dspi.c -@@ -1024,8 +1024,8 @@ static int dspi_probe(struct platform_de - goto out_clk_put; - } - -- ret = devm_request_irq(&pdev->dev, dspi->irq, dspi_interrupt, 0, -- pdev->name, dspi); -+ ret = devm_request_irq(&pdev->dev, dspi->irq, dspi_interrupt, -+ IRQF_SHARED, pdev->name, dspi); - if (ret < 0) { - dev_err(&pdev->dev, "Unable to attach DSPI interrupt\n"); - goto out_clk_put; |