It's required to handling opcode in spi drivers interface layer, m25p80 from spi-nor, becuase some spi-nor controller drivers like fsl_qspi have separate opcode's to handling the same operations.
Cc: Simon Glass <s...@chromium.org> Cc: Bin Meng <bmeng...@gmail.com> Cc: Mugunthan V N <mugunthan...@ti.com> Cc: Michal Simek <michal.si...@xilinx.com> Cc: Siva Durga Prasad Paladugu <siva...@xilinx.com> Signed-off-by: Jagan Teki <jt...@openedev.com> --- drivers/mtd/spi-nor/m25p80.c | 53 ++++++++++++++++++++++++++++-------- drivers/mtd/spi-nor/spi-nor.c | 62 +++++++------------------------------------ include/linux/mtd/spi-nor.h | 10 +++---- 3 files changed, 56 insertions(+), 69 deletions(-) diff --git a/drivers/mtd/spi-nor/m25p80.c b/drivers/mtd/spi-nor/m25p80.c index cf27ba0..560e5b2 100644 --- a/drivers/mtd/spi-nor/m25p80.c +++ b/drivers/mtd/spi-nor/m25p80.c @@ -17,14 +17,24 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/spi-nor.h> +#define MAX_CMD_SIZE 6 struct m25p { struct spi_slave *spi; struct spi_nor spi_nor; #ifndef CONFIG_DM_MTD_SPI_NOR struct mtd_info mtd; #endif + u8 command[MAX_CMD_SIZE]; }; +static void spi_nor_addr(u32 addr, u8 *cmd) +{ + /* cmd[0] is actual command */ + cmd[1] = addr >> 16; + cmd[2] = addr >> 8; + cmd[3] = addr >> 0; +} + static int m25p80_read_reg(struct spi_nor *nor, u8 cmd, u8 *val, int len) { struct m25p *flash = nor->priv; @@ -112,8 +122,8 @@ static int m25p80_read_mmap(struct spi_nor *nor, void *data, return ret; } -static int m25p80_read(struct spi_nor *nor, const u8 *cmd, size_t cmd_len, - void *data, size_t data_len) +static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len, + u_char *buf) { struct m25p *flash = nor->priv; struct spi_slave *spi = flash->spi; @@ -125,12 +135,16 @@ static int m25p80_read(struct spi_nor *nor, const u8 *cmd, size_t cmd_len, return ret; } + flash->command[0] = nor->read_opcode; + spi_nor_addr(from, flash->command); + if (nor->flags & SNOR_F_U_PAGE) spi->flags |= SPI_XFER_U_PAGE; - ret = spi_write_then_read(spi, cmd, cmd_len, NULL, data, data_len); + ret = spi_write_then_read(spi, flash->command, 4 + nor->read_dummy, + NULL, buf, len); if (ret < 0) { - debug("m25p80: error %d reading %x\n", ret, *cmd); + debug("m25p80: error %d reading %x\n", ret, flash->command[0]); return ret; } @@ -139,11 +153,12 @@ static int m25p80_read(struct spi_nor *nor, const u8 *cmd, size_t cmd_len, return ret; } -static int m25p80_write(struct spi_nor *nor, const u8 *cmd, size_t cmd_len, - const void *data, size_t data_len) +static int m25p80_write(struct spi_nor *nor, loff_t to, size_t len, + const u_char *buf) { struct m25p *flash = nor->priv; struct spi_slave *spi = flash->spi; + int cmd_sz = 4; int ret; ret = spi_claim_bus(spi); @@ -152,12 +167,22 @@ static int m25p80_write(struct spi_nor *nor, const u8 *cmd, size_t cmd_len, return ret; } + if (nor->program_opcode == SNOR_OP_AAI_WP) + cmd_sz = 1; + + flash->command[0] = nor->program_opcode; + spi_nor_addr(to, flash->command); + if (nor->flags & SNOR_F_U_PAGE) spi->flags |= SPI_XFER_U_PAGE; - ret = spi_write_then_read(spi, cmd, cmd_len, data, NULL, data_len); + debug("m25p80: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", + buf, flash->command[0], flash->command[1], flash->command[2], + flash->command[3], len); + + ret = spi_write_then_read(spi, flash->command, cmd_sz, buf, NULL, len); if (ret < 0) { - debug("m25p80: error %d writing %x\n", ret, *cmd); + debug("m25p80: error %d writing %x\n", ret, flash->command[0]); return ret; } @@ -166,7 +191,7 @@ static int m25p80_write(struct spi_nor *nor, const u8 *cmd, size_t cmd_len, return ret; } -static int m25p80_erase(struct spi_nor *nor, const u8 *cmd, size_t cmd_len) +static int m25p80_erase(struct spi_nor *nor, loff_t offset) { struct m25p *flash = nor->priv; struct spi_slave *spi = flash->spi; @@ -178,12 +203,18 @@ static int m25p80_erase(struct spi_nor *nor, const u8 *cmd, size_t cmd_len) return ret; } + flash->command[0] = nor->erase_opcode; + spi_nor_addr(offset, flash->command); + if (nor->flags & SNOR_F_U_PAGE) spi->flags |= SPI_XFER_U_PAGE; - ret = spi_write_then_read(spi, cmd, cmd_len, NULL, NULL, 0); + debug("m25p80: erase %2x %2x %2x %2x (%llx)\n", flash->command[0], + flash->command[1], flash->command[2], flash->command[3], offset); + + ret = spi_write_then_read(spi, flash->command, 4, NULL, NULL, 0); if (ret < 0) { - debug("m25p80: error %d writing %x\n", ret, *cmd); + debug("m25p80: error %d writing %x\n", ret, flash->command[0]); return ret; } diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 97f5eaa..cb9ab21 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -32,14 +32,6 @@ static inline int write_disable(struct spi_nor *nor) return nor->write_reg(nor, SNOR_OP_WRDI, NULL, 0); } -static void spi_nor_addr(u32 addr, u8 *cmd) -{ - /* cmd[0] is actual command */ - cmd[1] = addr >> 16; - cmd[2] = addr >> 8; - cmd[3] = addr >> 0; -} - static int read_sr(struct spi_nor *nor) { u8 sr; @@ -487,7 +479,6 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) { struct spi_nor *nor = mtd->priv; u32 addr, len, erase_addr; - u8 cmd[SNOR_MAX_CMD_SIZE]; uint32_t rem; int ret = -1; @@ -506,7 +497,6 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) } } - cmd[0] = nor->erase_opcode; while (len) { erase_addr = addr; @@ -519,14 +509,9 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) if (ret < 0) return ret; #endif - spi_nor_addr(erase_addr, cmd); - - debug("spi-nor: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], - cmd[2], cmd[3], erase_addr); - write_enable(nor); - ret = nor->erase(nor, cmd, sizeof(cmd)); + ret = nor->erase(nor, erase_addr); if (ret < 0) goto erase_err; @@ -556,7 +541,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t offset, size_t len, struct spi_nor *nor = mtd->priv; u32 byte_addr, page_size, write_addr; size_t chunk_len, actual; - u8 cmd[SNOR_MAX_CMD_SIZE]; int ret = -1; if (mtd->_is_locked) { @@ -569,7 +553,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t offset, size_t len, page_size = nor->page_size; - cmd[0] = nor->program_opcode; for (actual = 0; actual < len; actual += chunk_len) { write_addr = offset; @@ -589,15 +572,9 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t offset, size_t len, chunk_len = min(chunk_len, (size_t)nor->max_write_size); - spi_nor_addr(write_addr, cmd); - - debug("spi-nor: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", - buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); - write_enable(nor); - ret = nor->write(nor, cmd, sizeof(cmd), - buf + actual, chunk_len); + ret = nor->write(nor, write_addr, chunk_len, buf + actual); if (ret < 0) break; @@ -617,7 +594,6 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, { struct spi_nor *nor = mtd->priv; u32 remain_len, read_len, read_addr; - u8 cmd[SNOR_MAX_CMD_SIZE], cmdsz; int bank_sel = 0; int ret = -1; @@ -632,8 +608,6 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, return ret; } - cmdsz = SNOR_MAX_CMD_SIZE + nor->read_dummy; - cmd[0] = nor->read_opcode; while (len) { read_addr = from; @@ -654,9 +628,7 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, else read_len = remain_len; - spi_nor_addr(read_addr, cmd); - - ret = nor->read(nor, cmd, cmdsz, buf, read_len); + ret = nor->read(nor, read_addr, read_len, buf); if (ret < 0) break; @@ -674,21 +646,14 @@ static int sst_byte_write(struct spi_nor *nor, u32 offset, const void *buf, size_t *retlen) { int ret; - u8 cmd[4] = { - SNOR_OP_BP, - offset >> 16, - offset >> 8, - offset, - }; - - debug("spi-nor: 0x%p => cmd = { 0x%02x 0x%06x }\n", - buf, cmd[0], offset); ret = write_enable(nor); if (ret) return ret; - ret = nor->write(nor, cmd, sizeof(cmd), buf, 1); + nor->program_opcode = SNOR_OP_BP; + + ret = nor->write(nor, offset, 1, buf); if (ret) return ret; @@ -701,9 +666,8 @@ static int sst_write_wp(struct mtd_info *mtd, loff_t offset, size_t len, size_t *retlen, const u_char *buf) { struct spi_nor *nor = mtd->priv; - size_t actual, cmd_len; + size_t actual; int ret; - u8 cmd[4]; /* If the data is not word aligned, write out leading single byte */ actual = offset % 2; @@ -718,17 +682,10 @@ static int sst_write_wp(struct mtd_info *mtd, loff_t offset, size_t len, if (ret) goto done; - cmd_len = 4; - cmd[0] = SNOR_OP_AAI_WP; - cmd[1] = offset >> 16; - cmd[2] = offset >> 8; - cmd[3] = offset; - for (; actual < len - 1; actual += 2) { - debug("spi-nor: 0x%p => cmd = { 0x%02x 0x%06llx }\n", - buf + actual, cmd[0], offset); + nor->program_opcode = SNOR_OP_AAI_WP; - ret = nor->write(nor, cmd, cmd_len, buf + actual, 2); + ret = nor->write(nor, offset, 2, buf + actual); if (ret) { debug("spi-nor: sst word program failed\n"); break; @@ -738,7 +695,6 @@ static int sst_write_wp(struct mtd_info *mtd, loff_t offset, size_t len, if (ret) break; - cmd_len = 1; offset += 2; *retlen += 2; } diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 4749ff4..19a5dd0 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -224,11 +224,11 @@ struct spi_nor { int (*read_mmap)(struct spi_nor *nor, void *data, void *offset, size_t len); - int (*read)(struct spi_nor *nor, const u8 *opcode, size_t cmd_len, - void *data, size_t data_len); - int (*write)(struct spi_nor *nor, const u8 *cmd, size_t cmd_len, - const void *data, size_t data_len); - int (*erase)(struct spi_nor *nor, const u8 *cmd, size_t cmd_len); + int (*read)(struct spi_nor *nor, loff_t from, size_t len, + u_char *read_buf); + int (*write)(struct spi_nor *nor, loff_t to, size_t len, + const u_char *write_buf); + int (*erase)(struct spi_nor *nor, loff_t offs); int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len); int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); -- 1.9.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot