123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986 |
- From a3757157751a8a5302ee5e11faf828dc5db02018 Mon Sep 17 00:00:00 2001
- From: Yangbo Lu <[email protected]>
- Date: Mon, 25 Sep 2017 10:53:50 +0800
- Subject: [PATCH] mtd: spi-nor: support layerscape
- This is a integrated patch for layerscape qspi support.
- Signed-off-by: Suresh Gupta <[email protected]>
- Signed-off-by: Yunhui Cui <[email protected]>
- Signed-off-by: mar.krzeminski <[email protected]>
- Signed-off-by: Alison Wang <[email protected]>
- Signed-off-by: Nobuhiro Iwamatsu <[email protected]>
- Signed-off-by: LABBE Corentin <[email protected]>
- Signed-off-by: Yuan Yao <[email protected]>
- Signed-off-by: Alexander Kurz <[email protected]>
- Signed-off-by: L. D. Pinney <[email protected]>
- Signed-off-by: Ash Benz <[email protected]>
- Signed-off-by: Yangbo Lu <[email protected]>
- ---
- drivers/mtd/mtdchar.c | 2 +-
- drivers/mtd/spi-nor/fsl-quadspi.c | 327 +++++++++++++++++++++++++++++++-------
- drivers/mtd/spi-nor/spi-nor.c | 136 ++++++++++++++--
- include/linux/mtd/spi-nor.h | 14 +-
- 4 files changed, 409 insertions(+), 70 deletions(-)
- --- a/drivers/mtd/mtdchar.c
- +++ b/drivers/mtd/mtdchar.c
- @@ -451,7 +451,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;
- }
- @@ -961,6 +973,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) },
- @@ -1014,12 +1028,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) },
- @@ -1033,10 +1050,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) },
- @@ -1054,8 +1072,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) },
- @@ -1130,6 +1151,9 @@ static const struct flash_info spi_nor_i
- { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) },
- { "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,
- @@ -1192,6 +1216,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)
- @@ -1411,7 +1482,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)
- {
- @@ -1459,6 +1530,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;
- @@ -1605,9 +1694,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;
- @@ -1641,6 +1746,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 */
- @@ -1680,9 +1787,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");
- @@ -1695,6 +1808,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);
|