From d3b63e5b4e484143953124522671b62c45bcf5e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 17 Dec 2014 14:53:25 +0000 Subject: bcm53xx: backport spi-nor changes and update bcm53xxspiflash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki git-svn-id: svn://svn.openwrt.org/openwrt/trunk@43738 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../patches-3.18/003-mtd-spi-nor-from-3.19.patch | 662 +++++++++++++++++++++ 1 file changed, 662 insertions(+) create mode 100644 target/linux/bcm53xx/patches-3.18/003-mtd-spi-nor-from-3.19.patch (limited to 'target/linux/bcm53xx/patches-3.18/003-mtd-spi-nor-from-3.19.patch') diff --git a/target/linux/bcm53xx/patches-3.18/003-mtd-spi-nor-from-3.19.patch b/target/linux/bcm53xx/patches-3.18/003-mtd-spi-nor-from-3.19.patch new file mode 100644 index 0000000000..2e5fa10a60 --- /dev/null +++ b/target/linux/bcm53xx/patches-3.18/003-mtd-spi-nor-from-3.19.patch @@ -0,0 +1,662 @@ +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -26,7 +26,38 @@ + /* Define max times to check status register before we give up. */ + #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ + +-#define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) ++#define SPI_NOR_MAX_ID_LEN 6 ++ ++struct flash_info { ++ /* ++ * This array stores the ID bytes. ++ * The first three bytes are the JEDIC ID. ++ * JEDEC ID zero means "no ID" (mostly older chips). ++ */ ++ u8 id[SPI_NOR_MAX_ID_LEN]; ++ u8 id_len; ++ ++ /* The size listed here is what works with SPINOR_OP_SE, which isn't ++ * necessarily called a "sector" by the vendor. ++ */ ++ unsigned sector_size; ++ u16 n_sectors; ++ ++ u16 page_size; ++ u16 addr_width; ++ ++ u16 flags; ++#define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */ ++#define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */ ++#define SST_WRITE 0x04 /* use SST byte programming */ ++#define SPI_NOR_NO_FR 0x08 /* Can't do fastread */ ++#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ ++#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ ++#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ ++#define USE_FSR 0x80 /* use flag status register */ ++}; ++ ++#define JEDEC_MFR(info) ((info)->id[0]) + + static const struct spi_device_id *spi_nor_match_id(const char *name); + +@@ -98,7 +129,7 @@ static inline int spi_nor_read_dummy_cyc + case SPI_NOR_FAST: + case SPI_NOR_DUAL: + case SPI_NOR_QUAD: +- return 1; ++ return 8; + case SPI_NOR_NORMAL: + return 0; + } +@@ -138,13 +169,14 @@ static inline struct spi_nor *mtd_to_spi + } + + /* Enable/disable 4-byte addressing mode. */ +-static inline int set_4byte(struct spi_nor *nor, u32 jedec_id, int enable) ++static inline int set_4byte(struct spi_nor *nor, struct flash_info *info, ++ int enable) + { + int status; + bool need_wren = false; + u8 cmd; + +- switch (JEDEC_MFR(jedec_id)) { ++ switch (JEDEC_MFR(info)) { + case CFI_MFR_ST: /* Micron, actually */ + /* Some Micron need WREN command; all will accept it */ + need_wren = true; +@@ -165,81 +197,74 @@ static inline int set_4byte(struct spi_n + return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1, 0); + } + } +- +-static int spi_nor_wait_till_ready(struct spi_nor *nor) ++static inline int spi_nor_sr_ready(struct spi_nor *nor) + { +- unsigned long deadline; +- int sr; +- +- deadline = jiffies + MAX_READY_WAIT_JIFFIES; +- +- do { +- cond_resched(); ++ int sr = read_sr(nor); ++ if (sr < 0) ++ return sr; ++ else ++ return !(sr & SR_WIP); ++} + +- sr = read_sr(nor); +- if (sr < 0) +- break; +- else if (!(sr & SR_WIP)) +- return 0; +- } while (!time_after_eq(jiffies, deadline)); ++static inline int spi_nor_fsr_ready(struct spi_nor *nor) ++{ ++ int fsr = read_fsr(nor); ++ if (fsr < 0) ++ return fsr; ++ else ++ return fsr & FSR_READY; ++} + +- return -ETIMEDOUT; ++static int spi_nor_ready(struct spi_nor *nor) ++{ ++ int sr, fsr; ++ sr = spi_nor_sr_ready(nor); ++ if (sr < 0) ++ return sr; ++ fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1; ++ if (fsr < 0) ++ return fsr; ++ return sr && fsr; + } + +-static int spi_nor_wait_till_fsr_ready(struct spi_nor *nor) ++/* ++ * Service routine to read status register until ready, or timeout occurs. ++ * Returns non-zero if error. ++ */ ++static int spi_nor_wait_till_ready(struct spi_nor *nor) + { + unsigned long deadline; +- int sr; +- int fsr; ++ int timeout = 0, ret; + + deadline = jiffies + MAX_READY_WAIT_JIFFIES; + +- do { ++ while (!timeout) { ++ if (time_after_eq(jiffies, deadline)) ++ timeout = 1; ++ ++ ret = spi_nor_ready(nor); ++ if (ret < 0) ++ return ret; ++ if (ret) ++ return 0; ++ + cond_resched(); ++ } + +- sr = read_sr(nor); +- if (sr < 0) { +- break; +- } else if (!(sr & SR_WIP)) { +- fsr = read_fsr(nor); +- if (fsr < 0) +- break; +- if (fsr & FSR_READY) +- return 0; +- } +- } while (!time_after_eq(jiffies, deadline)); ++ dev_err(nor->dev, "flash operation timed out\n"); + + return -ETIMEDOUT; + } + + /* +- * Service routine to read status register until ready, or timeout occurs. +- * Returns non-zero if error. +- */ +-static int wait_till_ready(struct spi_nor *nor) +-{ +- return nor->wait_till_ready(nor); +-} +- +-/* + * Erase the whole flash memory + * + * Returns 0 if successful, non-zero otherwise. + */ + static int erase_chip(struct spi_nor *nor) + { +- int ret; +- + dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd->size >> 10)); + +- /* Wait until finished previous write command. */ +- ret = wait_till_ready(nor); +- if (ret) +- return ret; +- +- /* Send write enable, then erase commands. */ +- write_enable(nor); +- + return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0); + } + +@@ -294,11 +319,17 @@ static int spi_nor_erase(struct mtd_info + + /* whole-chip erase? */ + if (len == mtd->size) { ++ write_enable(nor); ++ + if (erase_chip(nor)) { + ret = -EIO; + goto erase_err; + } + ++ ret = spi_nor_wait_till_ready(nor); ++ if (ret) ++ goto erase_err; ++ + /* REVISIT in some cases we could speed up erasing large regions + * by using SPINOR_OP_SE instead of SPINOR_OP_BE_4K. We may have set up + * to use "small sector erase", but that's not always optimal. +@@ -307,6 +338,8 @@ static int spi_nor_erase(struct mtd_info + /* "sector"-at-a-time erase */ + } else { + while (len) { ++ write_enable(nor); ++ + if (nor->erase(nor, addr)) { + ret = -EIO; + goto erase_err; +@@ -314,9 +347,15 @@ static int spi_nor_erase(struct mtd_info + + addr += mtd->erasesize; + len -= mtd->erasesize; ++ ++ ret = spi_nor_wait_till_ready(nor); ++ if (ret) ++ goto erase_err; + } + } + ++ write_disable(nor); ++ + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); + + instr->state = MTD_ERASE_DONE; +@@ -341,11 +380,6 @@ static int spi_nor_lock(struct mtd_info + if (ret) + return ret; + +- /* Wait until finished previous command */ +- ret = wait_till_ready(nor); +- if (ret) +- goto err; +- + status_old = read_sr(nor); + + if (offset < mtd->size - (mtd->size / 2)) +@@ -388,11 +422,6 @@ static int spi_nor_unlock(struct mtd_inf + if (ret) + return ret; + +- /* Wait until finished previous command */ +- ret = wait_till_ready(nor); +- if (ret) +- goto err; +- + status_old = read_sr(nor); + + if (offset+len > mtd->size - (mtd->size / 64)) +@@ -424,38 +453,34 @@ err: + return ret; + } + +-struct flash_info { +- /* JEDEC id zero means "no ID" (most older chips); otherwise it has +- * a high byte of zero plus three data bytes: the manufacturer id, +- * then a two byte device id. +- */ +- u32 jedec_id; +- u16 ext_id; +- +- /* The size listed here is what works with SPINOR_OP_SE, which isn't +- * necessarily called a "sector" by the vendor. +- */ +- unsigned sector_size; +- u16 n_sectors; +- +- u16 page_size; +- u16 addr_width; +- +- u16 flags; +-#define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */ +-#define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */ +-#define SST_WRITE 0x04 /* use SST byte programming */ +-#define SPI_NOR_NO_FR 0x08 /* Can't do fastread */ +-#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ +-#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ +-#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ +-#define USE_FSR 0x80 /* use flag status register */ +-}; +- ++/* Used when the "_ext_id" is two bytes at most */ + #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ + ((kernel_ulong_t)&(struct flash_info) { \ +- .jedec_id = (_jedec_id), \ +- .ext_id = (_ext_id), \ ++ .id = { \ ++ ((_jedec_id) >> 16) & 0xff, \ ++ ((_jedec_id) >> 8) & 0xff, \ ++ (_jedec_id) & 0xff, \ ++ ((_ext_id) >> 8) & 0xff, \ ++ (_ext_id) & 0xff, \ ++ }, \ ++ .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ ++ .sector_size = (_sector_size), \ ++ .n_sectors = (_n_sectors), \ ++ .page_size = 256, \ ++ .flags = (_flags), \ ++ }) ++ ++#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ ++ ((kernel_ulong_t)&(struct flash_info) { \ ++ .id = { \ ++ ((_jedec_id) >> 16) & 0xff, \ ++ ((_jedec_id) >> 8) & 0xff, \ ++ (_jedec_id) & 0xff, \ ++ ((_ext_id) >> 16) & 0xff, \ ++ ((_ext_id) >> 8) & 0xff, \ ++ (_ext_id) & 0xff, \ ++ }, \ ++ .id_len = 6, \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = 256, \ +@@ -507,6 +532,9 @@ static const struct spi_device_id spi_no + { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, + { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, + ++ /* Fujitsu */ ++ { "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) }, ++ + /* GigaDevice */ + { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, + { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, +@@ -532,6 +560,7 @@ static const struct spi_device_id spi_no + { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, + + /* Micron */ ++ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, + { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, + { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, + { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, +@@ -556,6 +585,7 @@ static const struct spi_device_id spi_no + { "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_QUAD_READ) }, + { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, + { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, + { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, +@@ -577,6 +607,7 @@ static const struct spi_device_id spi_no + { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) }, + { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) }, + { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, ++ { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, + + /* ST Microelectronics -- newer production may have feature updates */ + { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, +@@ -588,7 +619,6 @@ static const struct spi_device_id spi_no + { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, + { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, + { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, +- { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, + + { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, + { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, +@@ -644,32 +674,24 @@ static const struct spi_device_id spi_no + static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor) + { + int tmp; +- u8 id[5]; +- u32 jedec; +- u16 ext_jedec; ++ u8 id[SPI_NOR_MAX_ID_LEN]; + struct flash_info *info; + +- tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, 5); ++ tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); + if (tmp < 0) { + dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp); + return ERR_PTR(tmp); + } +- jedec = id[0]; +- jedec = jedec << 8; +- jedec |= id[1]; +- jedec = jedec << 8; +- jedec |= id[2]; +- +- ext_jedec = id[3] << 8 | id[4]; + + for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { + info = (void *)spi_nor_ids[tmp].driver_data; +- if (info->jedec_id == jedec) { +- if (info->ext_id == 0 || info->ext_id == ext_jedec) ++ if (info->id_len) { ++ if (!memcmp(info->id, id, info->id_len)) + return &spi_nor_ids[tmp]; + } + } +- dev_err(nor->dev, "unrecognized JEDEC id %06x\n", jedec); ++ dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %2x, %2x\n", ++ id[0], id[1], id[2]); + return ERR_PTR(-ENODEV); + } + +@@ -704,11 +726,6 @@ static int sst_write(struct mtd_info *mt + if (ret) + return ret; + +- /* Wait until finished previous write command. */ +- ret = wait_till_ready(nor); +- if (ret) +- goto time_out; +- + write_enable(nor); + + nor->sst_write_second = false; +@@ -720,7 +737,7 @@ static int sst_write(struct mtd_info *mt + + /* write one byte. */ + nor->write(nor, to, 1, retlen, buf); +- ret = wait_till_ready(nor); ++ ret = spi_nor_wait_till_ready(nor); + if (ret) + goto time_out; + } +@@ -732,7 +749,7 @@ static int sst_write(struct mtd_info *mt + + /* write two bytes. */ + nor->write(nor, to, 2, retlen, buf + actual); +- ret = wait_till_ready(nor); ++ ret = spi_nor_wait_till_ready(nor); + if (ret) + goto time_out; + to += 2; +@@ -741,7 +758,7 @@ static int sst_write(struct mtd_info *mt + nor->sst_write_second = false; + + write_disable(nor); +- ret = wait_till_ready(nor); ++ ret = spi_nor_wait_till_ready(nor); + if (ret) + goto time_out; + +@@ -752,7 +769,7 @@ static int sst_write(struct mtd_info *mt + nor->program_opcode = SPINOR_OP_BP; + nor->write(nor, to, 1, retlen, buf + actual); + +- ret = wait_till_ready(nor); ++ ret = spi_nor_wait_till_ready(nor); + if (ret) + goto time_out; + write_disable(nor); +@@ -780,11 +797,6 @@ static int spi_nor_write(struct mtd_info + if (ret) + return ret; + +- /* Wait until finished previous write command. */ +- ret = wait_till_ready(nor); +- if (ret) +- goto write_err; +- + write_enable(nor); + + page_offset = to & (nor->page_size - 1); +@@ -803,16 +815,20 @@ static int spi_nor_write(struct mtd_info + if (page_size > nor->page_size) + page_size = nor->page_size; + +- wait_till_ready(nor); ++ ret = spi_nor_wait_till_ready(nor); ++ if (ret) ++ goto write_err; ++ + write_enable(nor); + + nor->write(nor, to + i, page_size, retlen, buf + i); + } + } + ++ ret = spi_nor_wait_till_ready(nor); + write_err: + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); +- return 0; ++ return ret; + } + + static int macronix_quad_enable(struct spi_nor *nor) +@@ -825,7 +841,7 @@ static int macronix_quad_enable(struct s + nor->cmd_buf[0] = val | SR_QUAD_EN_MX; + nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); + +- if (wait_till_ready(nor)) ++ if (spi_nor_wait_till_ready(nor)) + return 1; + + ret = read_sr(nor); +@@ -875,11 +891,11 @@ static int spansion_quad_enable(struct s + return 0; + } + +-static int set_quad_mode(struct spi_nor *nor, u32 jedec_id) ++static int set_quad_mode(struct spi_nor *nor, struct flash_info *info) + { + int status; + +- switch (JEDEC_MFR(jedec_id)) { ++ switch (JEDEC_MFR(info)) { + case CFI_MFR_MACRONIX: + status = macronix_quad_enable(nor); + if (status) { +@@ -905,11 +921,6 @@ static int spi_nor_check(struct spi_nor + return -EINVAL; + } + +- if (!nor->read_id) +- nor->read_id = spi_nor_read_id; +- if (!nor->wait_till_ready) +- nor->wait_till_ready = spi_nor_wait_till_ready; +- + return 0; + } + +@@ -927,16 +938,24 @@ int spi_nor_scan(struct spi_nor *nor, co + if (ret) + return ret; + +- id = spi_nor_match_id(name); +- if (!id) ++ /* Try to auto-detect if chip name wasn't specified */ ++ if (!name) ++ id = spi_nor_read_id(nor); ++ else ++ id = spi_nor_match_id(name); ++ if (IS_ERR_OR_NULL(id)) + return -ENOENT; + + info = (void *)id->driver_data; + +- if (info->jedec_id) { ++ /* ++ * If caller has specified name of flash model that can normally be ++ * detected using JEDEC, let's verify it. ++ */ ++ if (name && info->id_len) { + const struct spi_device_id *jid; + +- jid = nor->read_id(nor); ++ jid = spi_nor_read_id(nor); + if (IS_ERR(jid)) { + return PTR_ERR(jid); + } else if (jid != id) { +@@ -961,9 +980,9 @@ int spi_nor_scan(struct spi_nor *nor, co + * up with the software protection bits set + */ + +- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ATMEL || +- JEDEC_MFR(info->jedec_id) == CFI_MFR_INTEL || +- JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) { ++ if (JEDEC_MFR(info) == CFI_MFR_ATMEL || ++ JEDEC_MFR(info) == CFI_MFR_INTEL || ++ JEDEC_MFR(info) == CFI_MFR_SST) { + write_enable(nor); + write_sr(nor, 0); + } +@@ -978,7 +997,7 @@ int spi_nor_scan(struct spi_nor *nor, co + mtd->_read = spi_nor_read; + + /* nor protection support for STmicro chips */ +- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { ++ if (JEDEC_MFR(info) == CFI_MFR_ST) { + mtd->_lock = spi_nor_lock; + mtd->_unlock = spi_nor_unlock; + } +@@ -989,9 +1008,8 @@ int spi_nor_scan(struct spi_nor *nor, co + else + mtd->_write = spi_nor_write; + +- if ((info->flags & USE_FSR) && +- nor->wait_till_ready == spi_nor_wait_till_ready) +- nor->wait_till_ready = spi_nor_wait_till_fsr_ready; ++ if (info->flags & USE_FSR) ++ nor->flags |= SNOR_F_USE_FSR; + + #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS + /* prefer "small sector" erase if possible */ +@@ -1032,7 +1050,7 @@ int spi_nor_scan(struct spi_nor *nor, co + + /* Quad/Dual-read mode takes precedence over fast/normal */ + if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { +- ret = set_quad_mode(nor, info->jedec_id); ++ ret = set_quad_mode(nor, info); + if (ret) { + dev_err(dev, "quad mode not supported\n"); + return ret; +@@ -1068,7 +1086,7 @@ int spi_nor_scan(struct spi_nor *nor, co + else if (mtd->size > 0x1000000) { + /* enable 4-byte addressing if the device exceeds 16MiB */ + nor->addr_width = 4; +- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { ++ if (JEDEC_MFR(info) == CFI_MFR_AMD) { + /* Dedicated 4-byte command set */ + switch (nor->flash_read) { + case SPI_NOR_QUAD: +@@ -1089,7 +1107,7 @@ int spi_nor_scan(struct spi_nor *nor, co + nor->erase_opcode = SPINOR_OP_SE_4B; + mtd->erasesize = info->sector_size; + } else +- set_4byte(nor, info->jedec_id, 1); ++ set_4byte(nor, info, 1); + } else { + nor->addr_width = 3; + } +--- a/include/linux/mtd/spi-nor.h ++++ b/include/linux/mtd/spi-nor.h +@@ -116,6 +116,10 @@ enum spi_nor_ops { + SPI_NOR_OPS_UNLOCK, + }; + ++enum spi_nor_option_flags { ++ SNOR_F_USE_FSR = BIT(0), ++}; ++ + /** + * struct spi_nor - Structure for defining a the SPI NOR layer + * @mtd: point to a mtd_info structure +@@ -129,6 +133,7 @@ enum spi_nor_ops { + * @program_opcode: the program opcode + * @flash_read: the mode of the read + * @sst_write_second: used by the SST write operation ++ * @flags: flag options for the current SPI-NOR (SNOR_F_*) + * @cfg: used by the read_xfer/write_xfer + * @cmd_buf: used by the write_reg + * @prepare: [OPTIONAL] do some preparations for the +@@ -139,9 +144,6 @@ enum spi_nor_ops { + * @write_xfer: [OPTIONAL] the writefundamental primitive + * @read_reg: [DRIVER-SPECIFIC] read out the register + * @write_reg: [DRIVER-SPECIFIC] write data to the register +- * @read_id: [REPLACEABLE] read out the ID data, and find +- * the proper spi_device_id +- * @wait_till_ready: [REPLACEABLE] wait till the NOR becomes ready + * @read: [DRIVER-SPECIFIC] read data from the SPI NOR + * @write: [DRIVER-SPECIFIC] write data to the SPI NOR + * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR +@@ -160,6 +162,7 @@ struct spi_nor { + u8 program_opcode; + enum read_mode flash_read; + bool sst_write_second; ++ u32 flags; + struct spi_nor_xfer_cfg cfg; + u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; + +@@ -172,8 +175,6 @@ struct spi_nor { + int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); + int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len, + int write_enable); +- const struct spi_device_id *(*read_id)(struct spi_nor *nor); +- int (*wait_till_ready)(struct spi_nor *nor); + + int (*read)(struct spi_nor *nor, loff_t from, + size_t len, size_t *retlen, u_char *read_buf); -- cgit v1.2.3