[U-Boot] [PATCH v7 76/87] mtd: spi-nor: Move opcode handling in m25p80
Jagan Teki
jteki at openedev.com
Tue Mar 22 08:38:28 CET 2016
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 <sjg at chromium.org>
Cc: Bin Meng <bmeng.cn at gmail.com>
Cc: Mugunthan V N <mugunthanvnm at ti.com>
Cc: Michal Simek <michal.simek at xilinx.com>
Cc: Siva Durga Prasad Paladugu <sivadur at xilinx.com>
Signed-off-by: Jagan Teki <jteki at 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
More information about the U-Boot
mailing list