| From 68e8078072e802e77134664f11d2ffbfbd2f8fbe Mon Sep 17 00:00:00 2001 |
| From: Brian Norris <computersforpeace@gmail.com> |
| Date: Thu, 18 Jul 2013 01:17:02 -0700 |
| Subject: mtd: nand: fix NAND_BUSWIDTH_AUTO for x16 devices |
| |
| From: Brian Norris <computersforpeace@gmail.com> |
| |
| commit 68e8078072e802e77134664f11d2ffbfbd2f8fbe upstream. |
| |
| The code for NAND_BUSWIDTH_AUTO is broken. According to Alexander: |
| |
| "I have a problem with attach NAND UBI in 16 bit mode. |
| NAND works fine if I specify NAND_BUSWIDTH_16 option, but not |
| working with NAND_BUSWIDTH_AUTO option. In second case NAND |
| chip is identifyed with ONFI." |
| |
| See his report for the rest of the details: |
| |
| http://lists.infradead.org/pipermail/linux-mtd/2013-July/047515.html |
| |
| Anyway, the problem is that nand_set_defaults() is called twice, we |
| intend it to reset the chip functions to their x16 buswidth verions |
| if the buswidth changed from x8 to x16; however, nand_set_defaults() |
| does exactly nothing if called a second time. |
| |
| Fix this by hacking nand_set_defaults() to reset the buswidth-dependent |
| functions if they were set to the x8 version the first time. Note that |
| this does not do anything to reset from x16 to x8, but that's not the |
| supported use case for NAND_BUSWIDTH_AUTO anyway. |
| |
| Signed-off-by: Brian Norris <computersforpeace@gmail.com> |
| Reported-by: Alexander Shiyan <shc_work@mail.ru> |
| Tested-by: Alexander Shiyan <shc_work@mail.ru> |
| Cc: Matthieu Castet <matthieu.castet@parrot.com> |
| Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> |
| Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/mtd/nand/nand_base.c | 8 +++++--- |
| 1 file changed, 5 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/mtd/nand/nand_base.c |
| +++ b/drivers/mtd/nand/nand_base.c |
| @@ -2793,7 +2793,9 @@ static void nand_set_defaults(struct nan |
| |
| if (!chip->select_chip) |
| chip->select_chip = nand_select_chip; |
| - if (!chip->read_byte) |
| + |
| + /* If called twice, pointers that depend on busw may need to be reset */ |
| + if (!chip->read_byte || chip->read_byte == nand_read_byte) |
| chip->read_byte = busw ? nand_read_byte16 : nand_read_byte; |
| if (!chip->read_word) |
| chip->read_word = nand_read_word; |
| @@ -2801,9 +2803,9 @@ static void nand_set_defaults(struct nan |
| chip->block_bad = nand_block_bad; |
| if (!chip->block_markbad) |
| chip->block_markbad = nand_default_block_markbad; |
| - if (!chip->write_buf) |
| + if (!chip->write_buf || chip->write_buf == nand_write_buf) |
| chip->write_buf = busw ? nand_write_buf16 : nand_write_buf; |
| - if (!chip->read_buf) |
| + if (!chip->read_buf || chip->read_buf == nand_read_buf) |
| chip->read_buf = busw ? nand_read_buf16 : nand_read_buf; |
| if (!chip->scan_bbt) |
| chip->scan_bbt = nand_default_bbt; |