Message ID | 20171108160027.18718-1-miquel.raynal@free-electrons.com |
---|---|
State | Accepted |
Delegated to: | Boris Brezillon |
Headers | show |
Series | [v2] mtd: nand: fix interpretation of NAND_CMD_NONE in nand_command[_lp]() | expand |
On Wed, 8 Nov 2017 17:00:27 +0100 Miquel Raynal <miquel.raynal@free-electrons.com> wrote: > Some drivers (like nand_hynix.c) call ->cmdfunc() with NAND_CMD_NONE > and a column address and expect the controller to only send address > cycles. Right now, the default ->cmdfunc() implementations provided by > the core do not filter out the command cycle in this case and forwards > the request to the controller driver through the ->cmd_ctrl() method. > The thing is, NAND controller drivers can get this wrong and send a > command cycle with a NAND_CMD_NONE opcode and since NAND_CMD_NONE is > -1, and the command field is usually casted to an u8, we end up sending > the 0xFF command which is actually a RESET operation. > > Add conditions in nand_command[_lp]() functions to sending the initial > command cycle when command == NAND_CMD_NONE. Applied. Thanks, Boris > > Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com> > --- > > Hello, > > Changes since v1: > - Commit message rewording. > - Added a case for NAND_CMD_NONE in the switch statement of each > function to avoid unnecesary wait. > > Thanks, > Miquèl > > > drivers/mtd/nand/nand_base.c | 9 +++++++-- > 1 file changed, 7 insertions(+), 2 deletions(-) > > diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c > index e48bf8260f54..074b67571bfc 100644 > --- a/drivers/mtd/nand/nand_base.c > +++ b/drivers/mtd/nand/nand_base.c > @@ -710,7 +710,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, > chip->cmd_ctrl(mtd, readcmd, ctrl); > ctrl &= ~NAND_CTRL_CHANGE; > } > - chip->cmd_ctrl(mtd, command, ctrl); > + if (command != NAND_CMD_NONE) > + chip->cmd_ctrl(mtd, command, ctrl); > > /* Address cycle, when necessary */ > ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE; > @@ -738,6 +739,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, > */ > switch (command) { > > + case NAND_CMD_NONE: > case NAND_CMD_PAGEPROG: > case NAND_CMD_ERASE1: > case NAND_CMD_ERASE2: > @@ -831,7 +833,9 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, > } > > /* Command latch cycle */ > - chip->cmd_ctrl(mtd, command, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); > + if (command != NAND_CMD_NONE) > + chip->cmd_ctrl(mtd, command, > + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); > > if (column != -1 || page_addr != -1) { > int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE; > @@ -866,6 +870,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, > */ > switch (command) { > > + case NAND_CMD_NONE: > case NAND_CMD_CACHEDPROG: > case NAND_CMD_PAGEPROG: > case NAND_CMD_ERASE1:
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index e48bf8260f54..074b67571bfc 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -710,7 +710,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, chip->cmd_ctrl(mtd, readcmd, ctrl); ctrl &= ~NAND_CTRL_CHANGE; } - chip->cmd_ctrl(mtd, command, ctrl); + if (command != NAND_CMD_NONE) + chip->cmd_ctrl(mtd, command, ctrl); /* Address cycle, when necessary */ ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE; @@ -738,6 +739,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, */ switch (command) { + case NAND_CMD_NONE: case NAND_CMD_PAGEPROG: case NAND_CMD_ERASE1: case NAND_CMD_ERASE2: @@ -831,7 +833,9 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, } /* Command latch cycle */ - chip->cmd_ctrl(mtd, command, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + if (command != NAND_CMD_NONE) + chip->cmd_ctrl(mtd, command, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); if (column != -1 || page_addr != -1) { int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE; @@ -866,6 +870,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, */ switch (command) { + case NAND_CMD_NONE: case NAND_CMD_CACHEDPROG: case NAND_CMD_PAGEPROG: case NAND_CMD_ERASE1:
Some drivers (like nand_hynix.c) call ->cmdfunc() with NAND_CMD_NONE and a column address and expect the controller to only send address cycles. Right now, the default ->cmdfunc() implementations provided by the core do not filter out the command cycle in this case and forwards the request to the controller driver through the ->cmd_ctrl() method. The thing is, NAND controller drivers can get this wrong and send a command cycle with a NAND_CMD_NONE opcode and since NAND_CMD_NONE is -1, and the command field is usually casted to an u8, we end up sending the 0xFF command which is actually a RESET operation. Add conditions in nand_command[_lp]() functions to sending the initial command cycle when command == NAND_CMD_NONE. Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com> --- Hello, Changes since v1: - Commit message rewording. - Added a case for NAND_CMD_NONE in the switch statement of each function to avoid unnecesary wait. Thanks, Miquèl drivers/mtd/nand/nand_base.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)