[MTD] [NAND] nandsim: support random page read command
Commit 3d45955962
("subpage read feature
as a way to improve performance") broke nandsim because nandsim does not
support the "random page read" NAND command. This patch adds
corresponding support.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
parent
96d8b647cf
commit
74216be41a
|
@ -207,13 +207,16 @@ MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the I
|
||||||
#define STATE_CMD_READID 0x0000000A /* read ID */
|
#define STATE_CMD_READID 0x0000000A /* read ID */
|
||||||
#define STATE_CMD_ERASE2 0x0000000B /* sector erase second command */
|
#define STATE_CMD_ERASE2 0x0000000B /* sector erase second command */
|
||||||
#define STATE_CMD_RESET 0x0000000C /* reset */
|
#define STATE_CMD_RESET 0x0000000C /* reset */
|
||||||
|
#define STATE_CMD_RNDOUT 0x0000000D /* random output command */
|
||||||
|
#define STATE_CMD_RNDOUTSTART 0x0000000E /* random output start command */
|
||||||
#define STATE_CMD_MASK 0x0000000F /* command states mask */
|
#define STATE_CMD_MASK 0x0000000F /* command states mask */
|
||||||
|
|
||||||
/* After an address is input, the simulator goes to one of these states */
|
/* After an address is input, the simulator goes to one of these states */
|
||||||
#define STATE_ADDR_PAGE 0x00000010 /* full (row, column) address is accepted */
|
#define STATE_ADDR_PAGE 0x00000010 /* full (row, column) address is accepted */
|
||||||
#define STATE_ADDR_SEC 0x00000020 /* sector address was accepted */
|
#define STATE_ADDR_SEC 0x00000020 /* sector address was accepted */
|
||||||
#define STATE_ADDR_ZERO 0x00000030 /* one byte zero address was accepted */
|
#define STATE_ADDR_COLUMN 0x00000030 /* column address was accepted */
|
||||||
#define STATE_ADDR_MASK 0x00000030 /* address states mask */
|
#define STATE_ADDR_ZERO 0x00000040 /* one byte zero address was accepted */
|
||||||
|
#define STATE_ADDR_MASK 0x00000070 /* address states mask */
|
||||||
|
|
||||||
/* Durind data input/output the simulator is in these states */
|
/* Durind data input/output the simulator is in these states */
|
||||||
#define STATE_DATAIN 0x00000100 /* waiting for data input */
|
#define STATE_DATAIN 0x00000100 /* waiting for data input */
|
||||||
|
@ -240,7 +243,7 @@ MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the I
|
||||||
#define ACTION_OOBOFF 0x00600000 /* add to address OOB offset */
|
#define ACTION_OOBOFF 0x00600000 /* add to address OOB offset */
|
||||||
#define ACTION_MASK 0x00700000 /* action mask */
|
#define ACTION_MASK 0x00700000 /* action mask */
|
||||||
|
|
||||||
#define NS_OPER_NUM 12 /* Number of operations supported by the simulator */
|
#define NS_OPER_NUM 13 /* Number of operations supported by the simulator */
|
||||||
#define NS_OPER_STATES 6 /* Maximum number of states in operation */
|
#define NS_OPER_STATES 6 /* Maximum number of states in operation */
|
||||||
|
|
||||||
#define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */
|
#define OPT_ANY 0xFFFFFFFF /* any chip supports this operation */
|
||||||
|
@ -373,7 +376,10 @@ static struct nandsim_operations {
|
||||||
{OPT_ANY, {STATE_CMD_READID, STATE_ADDR_ZERO, STATE_DATAOUT_ID, STATE_READY}},
|
{OPT_ANY, {STATE_CMD_READID, STATE_ADDR_ZERO, STATE_DATAOUT_ID, STATE_READY}},
|
||||||
/* Large page devices read page */
|
/* Large page devices read page */
|
||||||
{OPT_LARGEPAGE, {STATE_CMD_READ0, STATE_ADDR_PAGE, STATE_CMD_READSTART | ACTION_CPY,
|
{OPT_LARGEPAGE, {STATE_CMD_READ0, STATE_ADDR_PAGE, STATE_CMD_READSTART | ACTION_CPY,
|
||||||
STATE_DATAOUT, STATE_READY}}
|
STATE_DATAOUT, STATE_READY}},
|
||||||
|
/* Large page devices random page read */
|
||||||
|
{OPT_LARGEPAGE, {STATE_CMD_RNDOUT, STATE_ADDR_COLUMN, STATE_CMD_RNDOUTSTART | ACTION_CPY,
|
||||||
|
STATE_DATAOUT, STATE_READY}},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct weak_block {
|
struct weak_block {
|
||||||
|
@ -937,12 +943,18 @@ static char *get_state_name(uint32_t state)
|
||||||
return "STATE_CMD_ERASE2";
|
return "STATE_CMD_ERASE2";
|
||||||
case STATE_CMD_RESET:
|
case STATE_CMD_RESET:
|
||||||
return "STATE_CMD_RESET";
|
return "STATE_CMD_RESET";
|
||||||
|
case STATE_CMD_RNDOUT:
|
||||||
|
return "STATE_CMD_RNDOUT";
|
||||||
|
case STATE_CMD_RNDOUTSTART:
|
||||||
|
return "STATE_CMD_RNDOUTSTART";
|
||||||
case STATE_ADDR_PAGE:
|
case STATE_ADDR_PAGE:
|
||||||
return "STATE_ADDR_PAGE";
|
return "STATE_ADDR_PAGE";
|
||||||
case STATE_ADDR_SEC:
|
case STATE_ADDR_SEC:
|
||||||
return "STATE_ADDR_SEC";
|
return "STATE_ADDR_SEC";
|
||||||
case STATE_ADDR_ZERO:
|
case STATE_ADDR_ZERO:
|
||||||
return "STATE_ADDR_ZERO";
|
return "STATE_ADDR_ZERO";
|
||||||
|
case STATE_ADDR_COLUMN:
|
||||||
|
return "STATE_ADDR_COLUMN";
|
||||||
case STATE_DATAIN:
|
case STATE_DATAIN:
|
||||||
return "STATE_DATAIN";
|
return "STATE_DATAIN";
|
||||||
case STATE_DATAOUT:
|
case STATE_DATAOUT:
|
||||||
|
@ -973,6 +985,7 @@ static int check_command(int cmd)
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
|
||||||
case NAND_CMD_READ0:
|
case NAND_CMD_READ0:
|
||||||
|
case NAND_CMD_READ1:
|
||||||
case NAND_CMD_READSTART:
|
case NAND_CMD_READSTART:
|
||||||
case NAND_CMD_PAGEPROG:
|
case NAND_CMD_PAGEPROG:
|
||||||
case NAND_CMD_READOOB:
|
case NAND_CMD_READOOB:
|
||||||
|
@ -982,7 +995,8 @@ static int check_command(int cmd)
|
||||||
case NAND_CMD_READID:
|
case NAND_CMD_READID:
|
||||||
case NAND_CMD_ERASE2:
|
case NAND_CMD_ERASE2:
|
||||||
case NAND_CMD_RESET:
|
case NAND_CMD_RESET:
|
||||||
case NAND_CMD_READ1:
|
case NAND_CMD_RNDOUT:
|
||||||
|
case NAND_CMD_RNDOUTSTART:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case NAND_CMD_STATUS_MULTI:
|
case NAND_CMD_STATUS_MULTI:
|
||||||
|
@ -1021,6 +1035,10 @@ static uint32_t get_state_by_command(unsigned command)
|
||||||
return STATE_CMD_ERASE2;
|
return STATE_CMD_ERASE2;
|
||||||
case NAND_CMD_RESET:
|
case NAND_CMD_RESET:
|
||||||
return STATE_CMD_RESET;
|
return STATE_CMD_RESET;
|
||||||
|
case NAND_CMD_RNDOUT:
|
||||||
|
return STATE_CMD_RNDOUT;
|
||||||
|
case NAND_CMD_RNDOUTSTART:
|
||||||
|
return STATE_CMD_RNDOUTSTART;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_ERR("get_state_by_command: unknown command, BUG\n");
|
NS_ERR("get_state_by_command: unknown command, BUG\n");
|
||||||
|
@ -1582,6 +1600,11 @@ static void switch_state(struct nandsim *ns)
|
||||||
ns->regs.num = 1;
|
ns->regs.num = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case STATE_ADDR_COLUMN:
|
||||||
|
/* Column address is always 2 bytes */
|
||||||
|
ns->regs.num = ns->geom.pgaddrbytes - ns->geom.secaddrbytes;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
NS_ERR("switch_state: BUG! unknown address state\n");
|
NS_ERR("switch_state: BUG! unknown address state\n");
|
||||||
}
|
}
|
||||||
|
@ -1693,15 +1716,21 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Check that the command byte is correct */
|
||||||
* Chip might still be in STATE_DATAOUT
|
if (check_command(byte)) {
|
||||||
* (if OPT_AUTOINCR feature is supported), STATE_DATAOUT_STATUS or
|
NS_ERR("write_byte: unknown command %#x\n", (uint)byte);
|
||||||
* STATE_DATAOUT_STATUS_M state. If so, switch state.
|
return;
|
||||||
*/
|
}
|
||||||
|
|
||||||
if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS
|
if (NS_STATE(ns->state) == STATE_DATAOUT_STATUS
|
||||||
|| NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M
|
|| NS_STATE(ns->state) == STATE_DATAOUT_STATUS_M
|
||||||
|| ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT))
|
|| NS_STATE(ns->state) == STATE_DATAOUT) {
|
||||||
|
int row = ns->regs.row;
|
||||||
|
|
||||||
switch_state(ns);
|
switch_state(ns);
|
||||||
|
if (byte == NAND_CMD_RNDOUT)
|
||||||
|
ns->regs.row = row;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if chip is expecting command */
|
/* Check if chip is expecting command */
|
||||||
if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) {
|
if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) {
|
||||||
|
@ -1715,12 +1744,6 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
|
||||||
switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
|
switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the command byte is correct */
|
|
||||||
if (check_command(byte)) {
|
|
||||||
NS_ERR("write_byte: unknown command %#x\n", (uint)byte);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_DBG("command byte corresponding to %s state accepted\n",
|
NS_DBG("command byte corresponding to %s state accepted\n",
|
||||||
get_state_name(get_state_by_command(byte)));
|
get_state_name(get_state_by_command(byte)));
|
||||||
ns->regs.command = byte;
|
ns->regs.command = byte;
|
||||||
|
|
Loading…
Reference in New Issue