123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664 |
- --- 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) },
- @@ -537,6 +565,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) },
- @@ -561,6 +590,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) },
- @@ -582,6 +612,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) },
- @@ -593,7 +624,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) },
- @@ -649,32 +679,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);
- }
-
- @@ -709,11 +731,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;
- @@ -725,7 +742,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;
- }
- @@ -737,7 +754,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;
- @@ -746,7 +763,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;
-
- @@ -757,7 +774,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);
- @@ -785,11 +802,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);
- @@ -808,16 +820,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)
- @@ -830,7 +846,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);
- @@ -887,11 +903,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) {
- @@ -917,11 +933,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;
- }
-
- @@ -939,16 +950,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) {
- @@ -973,10 +992,10 @@ 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_MACRONIX ||
- - 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_MACRONIX ||
- + JEDEC_MFR(info) == CFI_MFR_SST) {
- write_enable(nor);
- write_sr(nor, 0);
- }
- @@ -991,7 +1010,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;
- }
- @@ -1002,9 +1021,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 */
- @@ -1045,7 +1063,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;
- @@ -1081,7 +1099,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:
- @@ -1102,7 +1120,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);
|