diff mbox

Add 'config IMX_NFC_V1_BISWAP' to swap the Bad block Indicator, and use for imx27pdk nand support.

Message ID 1309872828-13942-1-git-send-email-J.Lambrecht@televic.com
State New
Headers show

Commit Message

=?UTF-8?q?J=C3=BCrgen=20Lambrecht?= July 5, 2011, 1:33 p.m. UTC
- Swap the BI-byte on position 0x7D0 with a data byte at 0x835.  To fix a bug
  in Freescale imx NFC v1 SoC's for 2K page NAND flashes: imx27 and imx31.
  Warning: The same solution needs to be applied to the boot loader and the
  flash programmer.
- Enable NAND support for the imx27pdk (3ds), and use BISWAP.

Signed-off-by: Jürgen Lambrecht <J.Lambrecht@televic.com>
---
 arch/arm/mach-imx/Kconfig         |   30 ++++++++++++++++++++++++++++--
 arch/arm/mach-imx/mach-mx27_3ds.c |   14 ++++++++++++++
 drivers/mtd/nand/mxc_nand.c       |   29 +++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 2 deletions(-)

Comments

Baruch Siach July 5, 2011, 3:52 p.m. UTC | #1
Hi Jürgen,

Please add Sascha Hauer <kernel@pengutronix.de> to Cc on i.MX related patches.  
See the MAINTAINERS file.

On Tue, Jul 05, 2011 at 03:33:48PM +0200, Jürgen Lambrecht wrote:
> - Swap the BI-byte on position 0x7D0 with a data byte at 0x835.  To fix a bug
>   in Freescale imx NFC v1 SoC's for 2K page NAND flashes: imx27 and imx31.
>   Warning: The same solution needs to be applied to the boot loader and the
>   flash programmer.
> - Enable NAND support for the imx27pdk (3ds), and use BISWAP.
> 
> Signed-off-by: Jürgen Lambrecht <J.Lambrecht@televic.com>
> ---
>  arch/arm/mach-imx/Kconfig         |   30 ++++++++++++++++++++++++++++--
>  arch/arm/mach-imx/mach-mx27_3ds.c |   14 ++++++++++++++
>  drivers/mtd/nand/mxc_nand.c       |   29 +++++++++++++++++++++++++++++
>  3 files changed, 71 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index 0519dd7..e8b16a9 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -274,7 +274,7 @@ config MACH_EUKREA_MBIMX27_BASEBOARD
>  endchoice
>  
>  config MACH_MX27_3DS
> -	bool "MX27PDK platform"
> +	bool "MX27PDK (3DS) platform"

This change is not related to this patch.

>  	select SOC_IMX27
>  	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
>  	select IMX_HAVE_PLATFORM_IMX2_WDT
> @@ -284,13 +284,39 @@ config MACH_MX27_3DS
>  	select IMX_HAVE_PLATFORM_IMX_UART
>  	select IMX_HAVE_PLATFORM_MXC_EHCI
>  	select IMX_HAVE_PLATFORM_MXC_MMC
> +	select IMX_HAVE_PLATFORM_MXC_NAND
>  	select IMX_HAVE_PLATFORM_SPI_IMX
>  	select MXC_DEBUG_BOARD
>  	select MXC_ULPI if USB_ULPI
>  	help
> -	  Include support for MX27PDK platform. This includes specific
> +	  Include support for MX27PDK (3DS) platform. This includes specific

Ditto.

>  	  configurations for the board and its peripherals.
>  
> +config MACH_MXC_NAND_USE_BBT

The name of this option should indicate somehow that it's an i.MX27 specific 
hack.

> +	bool "Make the MXC NAND driver use the in flash Bad Block Table"
> +	depends on MACH_MX27_3DS
> +	depends on MTD_NAND_MXC
> +	help
> +	  Enable this if you want that the MXC NAND driver uses the in flash
> +	  Bad Block Table to know what blocks are bad instead of scanning the
> +	  entire flash looking for bad block markers.
> +
> +config IMX_NFC_V1_BISWAP
> +	bool "Make the MXC 2kB-page NAND driver swap the Bad Block Indicator"
> +	depends on MACH_MX27_3DS

Not PDK 3DS specific. Should be 'depends on SOC_IMX27 || SOC_IMX31'.

> +	depends on MTD_NAND_MXC
> +	help
> +	  Enable this if you want that the MXC NAND driver swaps the Bad Block
> +	  Indicator (BBI) byte. The IMX NFC v1 (present in IMX27 and IMX31)
> +	  contains a bug for 2kB-page flashes: the 2kB page is read out in
> +	  4x512B chunks, so also the spare area is read out in 4
> +	  chunks. Therefore the data area and the spare area becomes
> +	  mixed. This causes a problem for the factory programmed BBI: it
> +	  appears in the data area instead of the spare area, and is
> +	  overwritten. This patch swaps that byte to the "real" spare
> +	  area. WARNING: then also the bootloader and the flash programmer must
> +	  be patched!!
> +
>  config MACH_IMX27_VISSTRIM_M10
>  	bool "Vista Silicon i.MX27 Visstrim_m10"
>  	select SOC_IMX27
> diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
> index 526cbe1..84114aa 100644
> --- a/arch/arm/mach-imx/mach-mx27_3ds.c
> +++ b/arch/arm/mach-imx/mach-mx27_3ds.c
> @@ -40,6 +40,7 @@
>  #include <mach/ulpi.h>
>  #include <mach/irqs.h>
>  #include <mach/3ds_debugboard.h>
> +#include <mach/mxc_nand.h>
>  
>  #include "devices-imx27.h"
>  
> @@ -369,6 +370,18 @@ static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
>  	},
>  };
>  
> +/*
> + * NAND Flash
> + */
> +static const struct mxc_nand_platform_data
> +mx27_3ds_nand_board_info __initconst = {
> +	.width		= 1,
> +	.hw_ecc		= 1,
> +#ifdef MACH_MXC_NAND_USE_BBT

CONFIG_MACH_MXC_NAND_USE_BBT ?

> +	.flash_bbt	= 1,
> +#endif
> +};
> +
>  static const struct imxi2c_platform_data mx27_3ds_i2c0_data __initconst = {
>  	.bitrate = 100000,
>  };
> @@ -380,6 +393,7 @@ static void __init mx27pdk_init(void)
>  	mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
>  		"mx27pdk");
>  	mx27_3ds_sdhc1_enable_level_translator();
> +	imx27_add_mxc_nand(&mx27_3ds_nand_board_info);

This should also be in a separate patch.

>  	imx27_add_imx_uart0(&uart_pdata);
>  	imx27_add_fec(NULL);
>  	imx27_add_imx_keypad(&mx27_3ds_keymap_data);
> diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
> index 90df34c..83f54d6 100644
> --- a/drivers/mtd/nand/mxc_nand.c
> +++ b/drivers/mtd/nand/mxc_nand.c
> @@ -612,6 +612,30 @@ static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
>  	return 0;
>  }
>  
> +/*
> + * Swap the BI-byte on position 0x7D0 with a data byte at 0x835.
> + * To fix a bug in NFC v1 SoC's for 2K page NAND flashes: imx27 and imx31.
> + * Warning: The same solution needs to be applied to the boot loader and the
> + * flash programmer.
> + */
> +#ifdef CONFIG_IMX_NFC_V1_BISWAP
> +static void imx_bi_swap(struct mtd_info *mtd)
> +{
> +	struct nand_chip *nand_chip = mtd->priv;
> +	struct mxc_nand_host *host = nand_chip->priv;
> +	unsigned short temp1, temp2, new_temp1;
> +
> +	temp1 = *((volatile unsigned short*)(host->main_area0 + 0x7D0));
> +	temp2 = *((volatile unsigned short*)(host->main_area0 + 0x834));
> +	new_temp1 = (temp1 & 0xFF00) | (temp2 >> 8);
> +	temp2 = (temp2 & 0x00FF) | (temp1 << 8);
> +	*((volatile unsigned short*)(host->main_area0 + 0x7D0)) = new_temp1;
> +	*((volatile unsigned short*)(host->main_area0 + 0x834)) = temp2;
> +}
> +#else
> +static inline void imx_bi_swap(struct mtd_info *mtd) {}
> +#endif
> +
>  static u_char mxc_nand_read_byte(struct mtd_info *mtd)
>  {
>  	struct nand_chip *nand_chip = mtd->priv;
> @@ -971,6 +995,9 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
>  
>  		host->send_page(mtd, NFC_OUTPUT);
>  
> +		if ((mtd->writesize > 512) && nfc_is_v1())
> +			imx_bi_swap(mtd);
> +
>  		memcpy(host->data_buf, host->main_area0, mtd->writesize);
>  		copy_spare(mtd, true);
>  		break;
> @@ -989,6 +1016,8 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
>  	case NAND_CMD_PAGEPROG:
>  		memcpy(host->main_area0, host->data_buf, mtd->writesize);
>  		copy_spare(mtd, false);
> +		if ((mtd->writesize > 512) && nfc_is_v1())
> +			imx_bi_swap(mtd);
>  		host->send_page(mtd, NFC_INPUT);
>  		host->send_cmd(host, command, true);
>  		mxc_do_addr_cycle(mtd, column, page_addr);

baruch
Artem Bityutskiy July 6, 2011, 7:06 a.m. UTC | #2
Hi,

On Tue, 2011-07-05 at 15:33 +0200, Jürgen Lambrecht wrote:
> - Swap the BI-byte on position 0x7D0 with a data byte at 0x835.  To fix a bug
>   in Freescale imx NFC v1 SoC's for 2K page NAND flashes: imx27 and imx31.
>   Warning: The same solution needs to be applied to the boot loader and the
>   flash programmer.
> - Enable NAND support for the imx27pdk (3ds), and use BISWAP.

Sounds like 2 independent changes in one patch - please, split on 2
patches.

> +config MACH_MXC_NAND_USE_BBT
> +	bool "Make the MXC NAND driver use the in flash Bad Block Table"
> +	depends on MACH_MX27_3DS
> +	depends on MTD_NAND_MXC
> +	help
> +	  Enable this if you want that the MXC NAND driver uses the in flash
> +	  Bad Block Table to know what blocks are bad instead of scanning the
> +	  entire flash looking for bad block markers.

Sorry, but we have tons of NAND drivers, and if each driver will have a
config option for "BBT or scanning", our configuration menu will blow
up :-)

Really, it does not make sense to make this a config option - the BBT
should be detected automatically, and if it is present and correct -
scanning should not be done, otherwise, we should fall back to scanning.
And this should be a feature of the NAND base support. Please, look at
this and change the NAND base support if needed.

> +config IMX_NFC_V1_BISWAP
> +	bool "Make the MXC 2kB-page NAND driver swap the Bad Block Indicator"
> +	depends on MACH_MX27_3DS
> +	depends on MTD_NAND_MXC
> +	help
> +	  Enable this if you want that the MXC NAND driver swaps the Bad Block
> +	  Indicator (BBI) byte. The IMX NFC v1 (present in IMX27 and IMX31)
> +	  contains a bug for 2kB-page flashes: the 2kB page is read out in
> +	  4x512B chunks, so also the spare area is read out in 4
> +	  chunks. Therefore the data area and the spare area becomes
> +	  mixed. This causes a problem for the factory programmed BBI: it
> +	  appears in the data area instead of the spare area, and is
> +	  overwritten. This patch swaps that byte to the "real" spare
> +	  area. WARNING: then also the bootloader and the flash programmer must
> +	  be patched!!

Sorry, but again, things like this should be automatically detected -
check the versions and some other magic ids and decide dynamically
whether to swap or not. If it is impossible, then this information
should be taken from the device tree (which does not exist yet, but
people are working on this).

In any case, the rule of thumb is to think twice before adding a kenel
config option - we have too many of them already.
Sascha Hauer July 6, 2011, 8:09 a.m. UTC | #3
On Tue, Jul 05, 2011 at 03:33:48PM +0200, Jürgen Lambrecht wrote:
> - Swap the BI-byte on position 0x7D0 with a data byte at 0x835.  To fix a bug
>   in Freescale imx NFC v1 SoC's for 2K page NAND flashes: imx27 and imx31.
>   Warning: The same solution needs to be applied to the boot loader and the
>   flash programmer.
> - Enable NAND support for the imx27pdk (3ds), and use BISWAP.
> 
> Signed-off-by: Jürgen Lambrecht <J.Lambrecht@televic.com>
> ---
>  arch/arm/mach-imx/Kconfig         |   30 ++++++++++++++++++++++++++++--
>  arch/arm/mach-imx/mach-mx27_3ds.c |   14 ++++++++++++++
>  drivers/mtd/nand/mxc_nand.c       |   29 +++++++++++++++++++++++++++++
>  3 files changed, 71 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index 0519dd7..e8b16a9 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -274,7 +274,7 @@ config MACH_EUKREA_MBIMX27_BASEBOARD
>  endchoice
>  
>  config MACH_MX27_3DS
> -	bool "MX27PDK platform"
> +	bool "MX27PDK (3DS) platform"
>  	select SOC_IMX27
>  	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
>  	select IMX_HAVE_PLATFORM_IMX2_WDT
> @@ -284,13 +284,39 @@ config MACH_MX27_3DS
>  	select IMX_HAVE_PLATFORM_IMX_UART
>  	select IMX_HAVE_PLATFORM_MXC_EHCI
>  	select IMX_HAVE_PLATFORM_MXC_MMC
> +	select IMX_HAVE_PLATFORM_MXC_NAND
>  	select IMX_HAVE_PLATFORM_SPI_IMX
>  	select MXC_DEBUG_BOARD
>  	select MXC_ULPI if USB_ULPI
>  	help
> -	  Include support for MX27PDK platform. This includes specific
> +	  Include support for MX27PDK (3DS) platform. This includes specific
>  	  configurations for the board and its peripherals.
>  
> +config MACH_MXC_NAND_USE_BBT
> +	bool "Make the MXC NAND driver use the in flash Bad Block Table"
> +	depends on MACH_MX27_3DS
> +	depends on MTD_NAND_MXC
> +	help
> +	  Enable this if you want that the MXC NAND driver uses the in flash
> +	  Bad Block Table to know what blocks are bad instead of scanning the
> +	  entire flash looking for bad block markers.

Besides the fact that we have too many kconfig options there's another
problem. We try to build kernels which run on as many boards as
possible. Adding options like this limit a kernel for a particular
usecase (bbt vs. scanning)

> +
> +config IMX_NFC_V1_BISWAP
> +	bool "Make the MXC 2kB-page NAND driver swap the Bad Block Indicator"
> +	depends on MACH_MX27_3DS
> +	depends on MTD_NAND_MXC
> +	help
> +	  Enable this if you want that the MXC NAND driver swaps the Bad Block
> +	  Indicator (BBI) byte. The IMX NFC v1 (present in IMX27 and IMX31)
> +	  contains a bug for 2kB-page flashes: the 2kB page is read out in
> +	  4x512B chunks, so also the spare area is read out in 4
> +	  chunks. Therefore the data area and the spare area becomes
> +	  mixed. This causes a problem for the factory programmed BBI: it
> +	  appears in the data area instead of the spare area, and is
> +	  overwritten. This patch swaps that byte to the "real" spare
> +	  area. WARNING: then also the bootloader and the flash programmer must
> +	  be patched!!

I don't like this approach. IMO some code should be run on a virgin
flash which is aware of this issue and creates a correct bad block
table. You run this once and forget about this afterwards and every
kernel/bootloader can run without patching. Otherwise if you accidently
or intentionally start an older (unpatched) kernel your Nand gets
corrupted.

Also, my comment above applies here too. You added a 'depends on the
board I care of', but usually my kernels have all available boards
compiled in. So I can select this option and it will change the
behaviour of all boards I might run the kernel on, not only the
ones you depend on above.

Sascha
Wolfram Sang July 6, 2011, 9:06 a.m. UTC | #4
> +	temp1 = *((volatile unsigned short*)(host->main_area0 + 0x7D0));
> +	temp2 = *((volatile unsigned short*)(host->main_area0 + 0x834));
> +	new_temp1 = (temp1 & 0xFF00) | (temp2 >> 8);
> +	temp2 = (temp2 & 0x00FF) | (temp1 << 8);
> +	*((volatile unsigned short*)(host->main_area0 + 0x7D0)) = new_temp1;
> +	*((volatile unsigned short*)(host->main_area0 + 0x834)) = temp2;

Please use proper io-accessors and no magic values in V2.
Jürgen Lambrecht July 6, 2011, 9:06 a.m. UTC | #5
On 07/06/2011 10:09 AM, Sascha Hauer wrote:
>
> On Tue, Jul 05, 2011 at 03:33:48PM +0200, Jürgen Lambrecht wrote:
> > - Swap the BI-byte on position 0x7D0 with a data byte at 0x835.  To
> fix a bug
> >   in Freescale imx NFC v1 SoC's for 2K page NAND flashes: imx27 and
> imx31.
> >   Warning: The same solution needs to be applied to the boot loader
> and the
> >   flash programmer.
> > - Enable NAND support for the imx27pdk (3ds), and use BISWAP.
> >
> > Signed-off-by: Jürgen Lambrecht <J.Lambrecht@televic.com>
> > ---
> >  arch/arm/mach-imx/Kconfig         |   30 ++++++++++++++++++++++++++++--
> >  arch/arm/mach-imx/mach-mx27_3ds.c |   14 ++++++++++++++
> >  drivers/mtd/nand/mxc_nand.c       |   29 +++++++++++++++++++++++++++++
> >  3 files changed, 71 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> > index 0519dd7..e8b16a9 100644
> > --- a/arch/arm/mach-imx/Kconfig
> > +++ b/arch/arm/mach-imx/Kconfig
> > @@ -274,7 +274,7 @@ config MACH_EUKREA_MBIMX27_BASEBOARD
> >  endchoice
> >
> >  config MACH_MX27_3DS
> > -     bool "MX27PDK platform"
> > +     bool "MX27PDK (3DS) platform"
> >       select SOC_IMX27
> >       select IMX_HAVE_PLATFORM_FSL_USB2_UDC
> >       select IMX_HAVE_PLATFORM_IMX2_WDT
> > @@ -284,13 +284,39 @@ config MACH_MX27_3DS
> >       select IMX_HAVE_PLATFORM_IMX_UART
> >       select IMX_HAVE_PLATFORM_MXC_EHCI
> >       select IMX_HAVE_PLATFORM_MXC_MMC
> > +     select IMX_HAVE_PLATFORM_MXC_NAND
> >       select IMX_HAVE_PLATFORM_SPI_IMX
> >       select MXC_DEBUG_BOARD
> >       select MXC_ULPI if USB_ULPI
> >       help
> > -       Include support for MX27PDK platform. This includes specific
> > +       Include support for MX27PDK (3DS) platform. This includes
> specific
> >         configurations for the board and its peripherals.
> >
> > +config MACH_MXC_NAND_USE_BBT
> > +     bool "Make the MXC NAND driver use the in flash Bad Block Table"
> > +     depends on MACH_MX27_3DS
> > +     depends on MTD_NAND_MXC
> > +     help
> > +       Enable this if you want that the MXC NAND driver uses the in
> flash
> > +       Bad Block Table to know what blocks are bad instead of
> scanning the
> > +       entire flash looking for bad block markers.
>
> Besides the fact that we have too many kconfig options there's another
> problem. We try to build kernels which run on as many boards as
> possible. Adding options like this limit a kernel for a particular
> usecase (bbt vs. scanning)
>
Indeed. I just copied it from MACH_MX31_3DS_MXC_NAND_USE_BBT, and 
thought it was good to do the same.
If I want to use it, better just do it without that option, as other 
_3ds boards do (and davinci and atmel also do in another way).
I will remove the option in a separate nand patch for imx27pdk.

Regards,
Jürgen
[snip]
Jürgen Lambrecht July 6, 2011, 9:30 a.m. UTC | #6
On 07/06/2011 10:09 AM, Sascha Hauer wrote:
> On Tue, Jul 05, 2011 at 03:33:48PM +0200, Jürgen Lambrecht wrote:
> > - Swap the BI-byte on position 0x7D0 with a data byte at 0x835.  To 
> fix a bug
> >   in Freescale imx NFC v1 SoC's for 2K page NAND flashes: imx27 and 
> imx31.
> >   Warning: The same solution needs to be applied to the boot loader 
> and the
> >   flash programmer.
> > - Enable NAND support for the imx27pdk (3ds), and use BISWAP.
> >
> > Signed-off-by: Jürgen Lambrecht <J.Lambrecht@televic.com>
> > ---
> >  arch/arm/mach-imx/Kconfig         |   30 ++++++++++++++++++++++++++++--
> >  arch/arm/mach-imx/mach-mx27_3ds.c |   14 ++++++++++++++
> >  drivers/mtd/nand/mxc_nand.c       |   29 +++++++++++++++++++++++++++++
> >  3 files changed, 71 insertions(+), 2 deletions(-)
> >
> [snip]
>
> > +
> > +config IMX_NFC_V1_BISWAP
> > +     bool "Make the MXC 2kB-page NAND driver swap the Bad Block 
> Indicator"
> > +     depends on MACH_MX27_3DS
> > +     depends on MTD_NAND_MXC
> > +     help
> > +       Enable this if you want that the MXC NAND driver swaps the 
> Bad Block
> > +       Indicator (BBI) byte. The IMX NFC v1 (present in IMX27 and 
> IMX31)
> > +       contains a bug for 2kB-page flashes: the 2kB page is read out in
> > +       4x512B chunks, so also the spare area is read out in 4
> > +       chunks. Therefore the data area and the spare area becomes
> > +       mixed. This causes a problem for the factory programmed BBI: it
> > +       appears in the data area instead of the spare area, and is
> > +       overwritten. This patch swaps that byte to the "real" spare
> > +       area. WARNING: then also the bootloader and the flash 
> programmer must
> > +       be patched!!
>
> I don't like this approach. IMO some code should be run on a virgin
> flash which is aware of this issue and creates a correct bad block
> table. You run this once and forget about this afterwards and every
> kernel/bootloader can run without patching. Otherwise if you accidently
> or intentionally start an older (unpatched) kernel your Nand gets
> corrupted.
>
I see 3 solutions: rely on the quality of the NAND flash driver (1), 
patch the SW (2) or patch the HW (3).

1. A normal NAND flash driver relies on the ECC to detect a 
(potentially) bad block. But a factory bad block can have more bad bits 
that the specified ECC bits.
    Solution is to check after each write if the data was written 
reliable: a write/read-back policy. (linux kernel option: Device Drivers 
-> MTD support -> NAND Device Support -> Verify NAND page writes)
    This will of course slow-down writing a lot.
2. The Freescale solution: patch the SW:
       1. flash programmer
       2. boot-loader NAND driver
       3. OS NAND driver
3. For the HW patch, a special SW must be written that must be executed 
before the board is programmed. That special SW must run in RAM and copy 
the BBI byte to the "swapped" place, so that after swapping, the BBI is 
at the good place. Then the SW must not be patched.
    Risk: if this step is skipped, the factory BBI information is lost, 
and if the SW has no write/read-back policy (solution 1), data will be 
lost in some point in time.

Your solution is (3), but for the linux rootfs partition only, using the 
BBT. Of course bootloader partitions and the linux kernel binary are not 
written often, but I read (several times, and also been told) that even 
when only reading a nand flash it can become bad!
I still have to investigate this for how to solve this in the bootloader..

Because of the risk, and to have a fast solution, we went for solution (2).
But if no one else is interested in this solution, I guess there is no 
point trying to get it accepted.

> Also, my comment above applies here too. You added a 'depends on the
> board I care of', but usually my kernels have all available boards
> compiled in. So I can select this option and it will change the
> behaviour of all boards I might run the kernel on, not only the
> ones you depend on above.
Ok, i should then find a better way to do it.
But, the mxc_nand.c code contains this to protect it: 'if 
((mtd->writesize > 512) && nfc_is_v1())'.
Am I correct that all nfc-v1's have that bug, so only imx27 and imx51?
The application note we finally got from freescale only mentions "FSL 
IMX NFC".

regards,
juergen
>
> Sascha
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
Lothar Waßmann July 6, 2011, 11:48 a.m. UTC | #7
Hi,

Lambrecht Jürgen writes:
> On 07/06/2011 10:09 AM, Sascha Hauer wrote:
> > On Tue, Jul 05, 2011 at 03:33:48PM +0200, Jürgen Lambrecht wrote:
> > > - Swap the BI-byte on position 0x7D0 with a data byte at 0x835.  To 
> > fix a bug
> > >   in Freescale imx NFC v1 SoC's for 2K page NAND flashes: imx27 and 
> > imx31.
> > >   Warning: The same solution needs to be applied to the boot loader 
> > and the
> > >   flash programmer.
> > > - Enable NAND support for the imx27pdk (3ds), and use BISWAP.
> > >
> > > Signed-off-by: Jürgen Lambrecht <J.Lambrecht@televic.com>
> > > ---
> > >  arch/arm/mach-imx/Kconfig         |   30 ++++++++++++++++++++++++++++--
> > >  arch/arm/mach-imx/mach-mx27_3ds.c |   14 ++++++++++++++
> > >  drivers/mtd/nand/mxc_nand.c       |   29 +++++++++++++++++++++++++++++
> > >  3 files changed, 71 insertions(+), 2 deletions(-)
> > >
> > [snip]
> >
> > > +
> > > +config IMX_NFC_V1_BISWAP
> > > +     bool "Make the MXC 2kB-page NAND driver swap the Bad Block 
> > Indicator"
> > > +     depends on MACH_MX27_3DS
> > > +     depends on MTD_NAND_MXC
> > > +     help
> > > +       Enable this if you want that the MXC NAND driver swaps the 
> > Bad Block
> > > +       Indicator (BBI) byte. The IMX NFC v1 (present in IMX27 and 
> > IMX31)
> > > +       contains a bug for 2kB-page flashes: the 2kB page is read out in
> > > +       4x512B chunks, so also the spare area is read out in 4
> > > +       chunks. Therefore the data area and the spare area becomes
> > > +       mixed. This causes a problem for the factory programmed BBI: it
> > > +       appears in the data area instead of the spare area, and is
> > > +       overwritten. This patch swaps that byte to the "real" spare
> > > +       area. WARNING: then also the bootloader and the flash 
> > programmer must
> > > +       be patched!!
> >
> > I don't like this approach. IMO some code should be run on a virgin
> > flash which is aware of this issue and creates a correct bad block
> > table. You run this once and forget about this afterwards and every
> > kernel/bootloader can run without patching. Otherwise if you accidently
> > or intentionally start an older (unpatched) kernel your Nand gets
> > corrupted.
> >
> I see 3 solutions: rely on the quality of the NAND flash driver (1), 
> patch the SW (2) or patch the HW (3).
> 
> 1. A normal NAND flash driver relies on the ECC to detect a 
> (potentially) bad block. But a factory bad block can have more bad bits 
> that the specified ECC bits.
>     Solution is to check after each write if the data was written 
> reliable: a write/read-back policy. (linux kernel option: Device Drivers 
> -> MTD support -> NAND Device Support -> Verify NAND page writes)
>     This will of course slow-down writing a lot.
> 2. The Freescale solution: patch the SW:
>        1. flash programmer
>        2. boot-loader NAND driver
>        3. OS NAND driver
> 3. For the HW patch, a special SW must be written that must be executed 
> before the board is programmed. That special SW must run in RAM and copy 
> the BBI byte to the "swapped" place, so that after swapping, the BBI is 
> at the good place. Then the SW must not be patched.
>     Risk: if this step is skipped, the factory BBI information is lost, 
> and if the SW has no write/read-back policy (solution 1), data will be 
> lost in some point in time.
> 
That's nonsense. You cannot copy a byte inside a page that is not
programmable (that's what Bad Blocks are).
You only need to check the byte in a well known location once and
create a BBT in flash that carries the bad block information. After
that you need not check for any bad block markers any more, but simply
use the BBT.
Since you need to program the bootloader with some external tool
anyway, that tool is the right instance to do the bad block scan and
create the BBT.
That's what we at Ka-Ro are doing since the early days of the i.MX27
for all our i.MX boards.

> Your solution is (3), but for the linux rootfs partition only, using the 
> BBT. Of course bootloader partitions and the linux kernel binary are not 
> written often, but I read (several times, and also been told) that even 
> when only reading a nand flash it can become bad!
> I still have to investigate this for how to solve this in the bootloader..
> 
You are mixing up two different things. The Bad block markers in
certain locations in the OOB area mark 'Factory bad blocks'
i.e. blocks that are already bad when you apply power to the flash for
the first time. The manufacturer guarantees that initial bad blocks
can be detected by checking those locations for a non-FF value.
There is no guarantee that you may be able to write any specific value
to a certain byte in a block that has turned bad due to wearout or
whatever at any later time. Thus bad blocks that appear due to wearout
should be kept track of in the BBT, not by writing any 'bad block
markers' to the defective blocks themselves.

> > Also, my comment above applies here too. You added a 'depends on the
> > board I care of', but usually my kernels have all available boards
> > compiled in. So I can select this option and it will change the
> > behaviour of all boards I might run the kernel on, not only the
> > ones you depend on above.
> Ok, i should then find a better way to do it.
> But, the mxc_nand.c code contains this to protect it: 'if 
> ((mtd->writesize > 512) && nfc_is_v1())'.
> Am I correct that all nfc-v1's have that bug, so only imx27 and imx51?
> The application note we finally got from freescale only mentions "FSL 
> IMX NFC".
>
It's not exactly a bug (which would be possible to get fixed), but an
inherent feature of the controller which handles NAND flash with a
page size larger than 512 byte like it has n pages of 512 byte.


Lothar Waßmann
Artem Bityutskiy July 6, 2011, 11:56 a.m. UTC | #8
On Wed, 2011-07-06 at 13:48 +0200, Lothar Waßmann wrote:
> You are mixing up two different things. The Bad block markers in
> certain locations in the OOB area mark 'Factory bad blocks'
> i.e. blocks that are already bad when you apply power to the flash for
> the first time. The manufacturer guarantees that initial bad blocks
> can be detected by checking those locations for a non-FF value.
> There is no guarantee that you may be able to write any specific value
> to a certain byte in a block that has turned bad due to wearout or
> whatever at any later time. Thus bad blocks that appear due to wearout
> should be kept track of in the BBT, not by writing any 'bad block
> markers' to the defective blocks themselves. 

That's a good point. In practice, though, many systems do not have a
separate BBT and they write a bad block marker to the OOB area of the
first page, or the second if the first page cannot be written. This
works. But yes, in theory, if an eraseblock became bad, there is a
possibility that you cannot write to the OOB areas anymore. However, as
I said, in practice, one of the OOBs is still writable. Hmm... Any
comments or practical observations?
Sascha Hauer July 6, 2011, 12:05 p.m. UTC | #9
On Wed, Jul 06, 2011 at 11:30:00AM +0200, Lambrecht Jürgen wrote:
> On 07/06/2011 10:09 AM, Sascha Hauer wrote:
> > On Tue, Jul 05, 2011 at 03:33:48PM +0200, Jürgen Lambrecht wrote:
> > > - Swap the BI-byte on position 0x7D0 with a data byte at 0x835.  To 
> > fix a bug
> > >   in Freescale imx NFC v1 SoC's for 2K page NAND flashes: imx27 and 
> > imx31.
> > >   Warning: The same solution needs to be applied to the boot loader 
> > and the
> > >   flash programmer.
> > > - Enable NAND support for the imx27pdk (3ds), and use BISWAP.
> > >
> > > Signed-off-by: Jürgen Lambrecht <J.Lambrecht@televic.com>
> > > ---
> > >  arch/arm/mach-imx/Kconfig         |   30 ++++++++++++++++++++++++++++--
> > >  arch/arm/mach-imx/mach-mx27_3ds.c |   14 ++++++++++++++
> > >  drivers/mtd/nand/mxc_nand.c       |   29 +++++++++++++++++++++++++++++
> > >  3 files changed, 71 insertions(+), 2 deletions(-)
> > >
> > [snip]
> >
> > > +
> > > +config IMX_NFC_V1_BISWAP
> > > +     bool "Make the MXC 2kB-page NAND driver swap the Bad Block 
> > Indicator"
> > > +     depends on MACH_MX27_3DS
> > > +     depends on MTD_NAND_MXC
> > > +     help
> > > +       Enable this if you want that the MXC NAND driver swaps the 
> > Bad Block
> > > +       Indicator (BBI) byte. The IMX NFC v1 (present in IMX27 and 
> > IMX31)
> > > +       contains a bug for 2kB-page flashes: the 2kB page is read out in
> > > +       4x512B chunks, so also the spare area is read out in 4
> > > +       chunks. Therefore the data area and the spare area becomes
> > > +       mixed. This causes a problem for the factory programmed BBI: it
> > > +       appears in the data area instead of the spare area, and is
> > > +       overwritten. This patch swaps that byte to the "real" spare
> > > +       area. WARNING: then also the bootloader and the flash 
> > programmer must
> > > +       be patched!!
> >
> > I don't like this approach. IMO some code should be run on a virgin
> > flash which is aware of this issue and creates a correct bad block
> > table. You run this once and forget about this afterwards and every
> > kernel/bootloader can run without patching. Otherwise if you accidently
> > or intentionally start an older (unpatched) kernel your Nand gets
> > corrupted.
> >
> I see 3 solutions: rely on the quality of the NAND flash driver (1), 
> patch the SW (2) or patch the HW (3).
> 
> 1. A normal NAND flash driver relies on the ECC to detect a 
> (potentially) bad block. But a factory bad block can have more bad bits 
> that the specified ECC bits.
>     Solution is to check after each write if the data was written 
> reliable: a write/read-back policy. (linux kernel option: Device Drivers 
> -> MTD support -> NAND Device Support -> Verify NAND page writes)
>     This will of course slow-down writing a lot.
> 2. The Freescale solution: patch the SW:
>        1. flash programmer
>        2. boot-loader NAND driver
>        3. OS NAND driver
> 3. For the HW patch, a special SW must be written that must be executed 
> before the board is programmed. That special SW must run in RAM and copy 
> the BBI byte to the "swapped" place, so that after swapping, the BBI is 
> at the good place. Then the SW must not be patched.
>     Risk: if this step is skipped, the factory BBI information is lost, 
> and if the SW has no write/read-back policy (solution 1), data will be 
> lost in some point in time.
> 
> Your solution is (3), but for the linux rootfs partition only, using the 
> BBT. Of course bootloader partitions and the linux kernel binary are not 
> written often, but I read (several times, and also been told) that even 
> when only reading a nand flash it can become bad!
> I still have to investigate this for how to solve this in the bootloader..
> 
> Because of the risk, and to have a fast solution, we went for solution (2).
> But if no one else is interested in this solution, I guess there is no 
> point trying to get it accepted.
> 
> > Also, my comment above applies here too. You added a 'depends on the
> > board I care of', but usually my kernels have all available boards
> > compiled in. So I can select this option and it will change the
> > behaviour of all boards I might run the kernel on, not only the
> > ones you depend on above.
> Ok, i should then find a better way to do it.
> But, the mxc_nand.c code contains this to protect it: 'if 
> ((mtd->writesize > 512) && nfc_is_v1())'.

This is the correct way to limit the fix to the correct versions of the
nand controller, but that's not what I tried to say. You might want
to use solution (2) for your board whereas I want to use solution (3)
for my boards. With the Kconfig approach it would not be possible for
us to use the same kernel binary.

> Am I correct that all nfc-v1's have that bug, so only imx27 and imx51?
> The application note we finally got from freescale only mentions "FSL 
> IMX NFC".

s/imx51/imx31/.

Yes, only imx27 and imx31 a affected by this bug.

Sascha
Lothar Waßmann July 6, 2011, 12:25 p.m. UTC | #10
Sascha Hauer writes:
> On Wed, Jul 06, 2011 at 11:30:00AM +0200, Lambrecht Jürgen wrote:
> > On 07/06/2011 10:09 AM, Sascha Hauer wrote:
> > > On Tue, Jul 05, 2011 at 03:33:48PM +0200, Jürgen Lambrecht wrote:
> > > > - Swap the BI-byte on position 0x7D0 with a data byte at 0x835.  To 
> > > fix a bug
> > > >   in Freescale imx NFC v1 SoC's for 2K page NAND flashes: imx27 and 
> > > imx31.
> > > >   Warning: The same solution needs to be applied to the boot loader 
> > > and the
> > > >   flash programmer.
> > > > - Enable NAND support for the imx27pdk (3ds), and use BISWAP.
> > > >
> > > > Signed-off-by: Jürgen Lambrecht <J.Lambrecht@televic.com>
> > > > ---
> > > >  arch/arm/mach-imx/Kconfig         |   30 ++++++++++++++++++++++++++++--
> > > >  arch/arm/mach-imx/mach-mx27_3ds.c |   14 ++++++++++++++
> > > >  drivers/mtd/nand/mxc_nand.c       |   29 +++++++++++++++++++++++++++++
> > > >  3 files changed, 71 insertions(+), 2 deletions(-)
> > > >
> > > [snip]
> > >
> > > > +
> > > > +config IMX_NFC_V1_BISWAP
> > > > +     bool "Make the MXC 2kB-page NAND driver swap the Bad Block 
> > > Indicator"
> > > > +     depends on MACH_MX27_3DS
> > > > +     depends on MTD_NAND_MXC
> > > > +     help
> > > > +       Enable this if you want that the MXC NAND driver swaps the 
> > > Bad Block
> > > > +       Indicator (BBI) byte. The IMX NFC v1 (present in IMX27 and 
> > > IMX31)
> > > > +       contains a bug for 2kB-page flashes: the 2kB page is read out in
> > > > +       4x512B chunks, so also the spare area is read out in 4
> > > > +       chunks. Therefore the data area and the spare area becomes
> > > > +       mixed. This causes a problem for the factory programmed BBI: it
> > > > +       appears in the data area instead of the spare area, and is
> > > > +       overwritten. This patch swaps that byte to the "real" spare
> > > > +       area. WARNING: then also the bootloader and the flash 
> > > programmer must
> > > > +       be patched!!
> > >
> > > I don't like this approach. IMO some code should be run on a virgin
> > > flash which is aware of this issue and creates a correct bad block
> > > table. You run this once and forget about this afterwards and every
> > > kernel/bootloader can run without patching. Otherwise if you accidently
> > > or intentionally start an older (unpatched) kernel your Nand gets
> > > corrupted.
> > >
> > I see 3 solutions: rely on the quality of the NAND flash driver (1), 
> > patch the SW (2) or patch the HW (3).
> > 
> > 1. A normal NAND flash driver relies on the ECC to detect a 
> > (potentially) bad block. But a factory bad block can have more bad bits 
> > that the specified ECC bits.
> >     Solution is to check after each write if the data was written 
> > reliable: a write/read-back policy. (linux kernel option: Device Drivers 
> > -> MTD support -> NAND Device Support -> Verify NAND page writes)
> >     This will of course slow-down writing a lot.
> > 2. The Freescale solution: patch the SW:
> >        1. flash programmer
> >        2. boot-loader NAND driver
> >        3. OS NAND driver
> > 3. For the HW patch, a special SW must be written that must be executed 
> > before the board is programmed. That special SW must run in RAM and copy 
> > the BBI byte to the "swapped" place, so that after swapping, the BBI is 
> > at the good place. Then the SW must not be patched.
> >     Risk: if this step is skipped, the factory BBI information is lost, 
> > and if the SW has no write/read-back policy (solution 1), data will be 
> > lost in some point in time.
> > 
> > Your solution is (3), but for the linux rootfs partition only, using the 
> > BBT. Of course bootloader partitions and the linux kernel binary are not 
> > written often, but I read (several times, and also been told) that even 
> > when only reading a nand flash it can become bad!
> > I still have to investigate this for how to solve this in the bootloader..
> > 
> > Because of the risk, and to have a fast solution, we went for solution (2).
> > But if no one else is interested in this solution, I guess there is no 
> > point trying to get it accepted.
> > 
> > > Also, my comment above applies here too. You added a 'depends on the
> > > board I care of', but usually my kernels have all available boards
> > > compiled in. So I can select this option and it will change the
> > > behaviour of all boards I might run the kernel on, not only the
> > > ones you depend on above.
> > Ok, i should then find a better way to do it.
> > But, the mxc_nand.c code contains this to protect it: 'if 
> > ((mtd->writesize > 512) && nfc_is_v1())'.
> 
> This is the correct way to limit the fix to the correct versions of the
> nand controller, but that's not what I tried to say. You might want
> to use solution (2) for your board whereas I want to use solution (3)
> for my boards. With the Kconfig approach it would not be possible for
> us to use the same kernel binary.
> 
> > Am I correct that all nfc-v1's have that bug, so only imx27 and imx51?
> > The application note we finally got from freescale only mentions "FSL 
> > IMX NFC".
> 
> s/imx51/imx31/.
> 
> Yes, only imx27 and imx31 a affected by this bug.
> 
Are you sure? As mentioned in my other mail in this thread that's an
inherent side effect of the way how the i.MX flash controllers handle
the large page flash, not a bug of a certain silicon that could be
fixed somehow.

i.MX51, i.MX28 also have the same problem!


Lothar Waßmann
Jürgen Lambrecht July 6, 2011, 12:39 p.m. UTC | #11
On 07/06/2011 01:48 PM, Lothar Waßmann wrote:
>

> Hi,

>

> Lambrecht Jürgen writes:

> > On 07/06/2011 10:09 AM, Sascha Hauer wrote:

> > > On Tue, Jul 05, 2011 at 03:33:48PM +0200, Jürgen Lambrecht wrote:

> > > > - Swap the BI-byte on position 0x7D0 with a data byte at 0x835.  To

> > > fix a bug

> > > >   in Freescale imx NFC v1 SoC's for 2K page NAND flashes: imx27 and

> > > imx31.

> > > >   Warning: The same solution needs to be applied to the boot loader

> > > and the

> > > >   flash programmer.

> > > > - Enable NAND support for the imx27pdk (3ds), and use BISWAP.

> > > >

> > > > Signed-off-by: Jürgen Lambrecht <J.Lambrecht@televic.com>

> > > > ---

> > > >  arch/arm/mach-imx/Kconfig         |   30 

> ++++++++++++++++++++++++++++--

> > > >  arch/arm/mach-imx/mach-mx27_3ds.c |   14 ++++++++++++++

> > > >  drivers/mtd/nand/mxc_nand.c       |   29 

> +++++++++++++++++++++++++++++

> > > >  3 files changed, 71 insertions(+), 2 deletions(-)

> > > >

> > > [snip]

> > >

> > > > +

> > > > +config IMX_NFC_V1_BISWAP

> > > > +     bool "Make the MXC 2kB-page NAND driver swap the Bad Block

> > > Indicator"

> > > > +     depends on MACH_MX27_3DS

> > > > +     depends on MTD_NAND_MXC

> > > > +     help

> > > > +       Enable this if you want that the MXC NAND driver swaps the

> > > Bad Block

> > > > +       Indicator (BBI) byte. The IMX NFC v1 (present in IMX27 and

> > > IMX31)

> > > > +       contains a bug for 2kB-page flashes: the 2kB page is 

> read out in

> > > > +       4x512B chunks, so also the spare area is read out in 4

> > > > +       chunks. Therefore the data area and the spare area becomes

> > > > +       mixed. This causes a problem for the factory programmed 

> BBI: it

> > > > +       appears in the data area instead of the spare area, and is

> > > > +       overwritten. This patch swaps that byte to the "real" spare

> > > > +       area. WARNING: then also the bootloader and the flash

> > > programmer must

> > > > +       be patched!!

> > >

> > > I don't like this approach. IMO some code should be run on a virgin

> > > flash which is aware of this issue and creates a correct bad block

> > > table. You run this once and forget about this afterwards and every

> > > kernel/bootloader can run without patching. Otherwise if you 

> accidently

> > > or intentionally start an older (unpatched) kernel your Nand gets

> > > corrupted.

> > >

> > I see 3 solutions: rely on the quality of the NAND flash driver (1),

> > patch the SW (2) or patch the HW (3).

> >

> > 1. A normal NAND flash driver relies on the ECC to detect a

> > (potentially) bad block. But a factory bad block can have more bad bits

> > that the specified ECC bits.

> >     Solution is to check after each write if the data was written

> > reliable: a write/read-back policy. (linux kernel option: Device Drivers

> > -> MTD support -> NAND Device Support -> Verify NAND page writes)

> >     This will of course slow-down writing a lot.

> > 2. The Freescale solution: patch the SW:

> >        1. flash programmer

> >        2. boot-loader NAND driver

> >        3. OS NAND driver

> > 3. For the HW patch, a special SW must be written that must be executed

> > before the board is programmed. That special SW must run in RAM and copy

> > the BBI byte to the "swapped" place, so that after swapping, the BBI is

> > at the good place. Then the SW must not be patched.

> >     Risk: if this step is skipped, the factory BBI information is lost,

> > and if the SW has no write/read-back policy (solution 1), data will be

> > lost in some point in time.

> >

> That's nonsense. You cannot copy a byte inside a page that is not

> programmable (that's what Bad Blocks are).

>

No, a Factory Bad Block is a block that when tested under worst-case 
conditions has more erroneous bits that the ECC correctable ones. So 
anyhow only those bits cannot be written, and under normal conditions 
(room temperature..) it is best possible that all bits are again ok (my 
Micron datasheets even warns that you should not erase a Factory Bad 
Block, because there is a risk that it succeeds, hence also erasing the 
bad block mark).

But having investigated the matter further that i already had done, you 
are indeed right that my 3d solution is a bit wrong: it may not be 
possible to write that "swapped" place. But then the next page of the 
block can be taken, as there are many pages, and only a few bad bits, 
that will work.
>

> You only need to check the byte in a well known location once and

> create a BBT in flash that carries the bad block information. After

> that you need not check for any bad block markers any more, but simply

> use the BBT.

> Since you need to program the bootloader with some external tool

> anyway, that tool is the right instance to do the bad block scan and

> create the BBT.

> That's what we at Ka-Ro are doing since the early days of the i.MX27

> for all our i.MX boards.

>

Seems indeed the best solution. (but we took another solution because of 
time, and being new to linux)
But am I right that the BBT is a file-system dependent meta data?
>

>

> > Your solution is (3), but for the linux rootfs partition only, using the

> > BBT. Of course bootloader partitions and the linux kernel binary are not

> > written often, but I read (several times, and also been told) that even

> > when only reading a nand flash it can become bad!

> > I still have to investigate this for how to solve this in the 

> bootloader..

> >

> You are mixing up two different things. The Bad block markers in

> certain locations in the OOB area mark 'Factory bad blocks'

> i.e. blocks that are already bad when you apply power to the flash for

> the first time. The manufacturer guarantees that initial bad blocks

> can be detected by checking those locations for a non-FF value.

> There is no guarantee that you may be able to write any specific value

> to a certain byte in a block that has turned bad due to wearout or

> whatever at any later time. Thus bad blocks that appear due to wearout

> should be kept track of in the BBT, not by writing any 'bad block

> markers' to the defective blocks themselves.

>

Same remark: not completely right: only some bits are wrong (number of 
ECC bits +1, and as you do not touch the block anymore, no more bits 
will get corrupted).
But indeed the byte of the bad-block-marker location in the first page 
could contain erroneous bits. And to comment on Artem Bityutskiy's mail, 
then the next page of that (bad) block can be tried (and so on), finally 
it will work. But then of course the flash file system must be designed 
to do that.
However, I agree that bad blocks should be kept track of in the BBT.
>

>

> > > Also, my comment above applies here too. You added a 'depends on the

> > > board I care of', but usually my kernels have all available boards

> > > compiled in. So I can select this option and it will change the

> > > behaviour of all boards I might run the kernel on, not only the

> > > ones you depend on above.

> > Ok, i should then find a better way to do it.

> > But, the mxc_nand.c code contains this to protect it: 'if

> > ((mtd->writesize > 512) && nfc_is_v1())'.

> > Am I correct that all nfc-v1's have that bug, so only imx27 and imx51?

> > The application note we finally got from freescale only mentions "FSL

> > IMX NFC".

> >

> It's not exactly a bug (which would be possible to get fixed), but an

> inherent feature of the controller which handles NAND flash with a

> page size larger than 512 byte like it has n pages of 512 byte.

>

OK, a "hardware bug" then (can be fixed with a re-write of the 
VHDL/Verilog code of the NFC, giving v2). It seems to me Freescale tried 
to enhance their 512B-page controller with to possibility to also handle 
2kB pages, but they forgot about the Factory Bad Block byte (n=4 only).
So to reply to your next mail: only the imx27 and imx31 (thanks sascha, 
it was a typo to mention 51) have the NFC v1, I believe all the others 
have NFC v2, which are fixed.

Kind regards,
Jürgen
>

>

>

> Lothar Waßmann

> --

> ___________________________________________________________

>

> Ka-Ro electronics GmbH | Pascalstraße 22 | D - 52076 Aachen

> Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10

> Geschäftsführer: Matthias Kaussen

> Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

>

> www.karo-electronics.de | info@karo-electronics.de

> ___________________________________________________________

>



-- 
Jürgen Lambrecht
R&D Associate
Tel: +32 (0)51 303045    Fax: +32 (0)51 310670
http://www.televic-rail.com
Televic Rail NV - Leo Bekaertlaan 1 - 8870 Izegem - Belgium
Company number 0825.539.581 - RPR Kortrijk
Lothar Waßmann July 6, 2011, 1:53 p.m. UTC | #12
Hi,

Lambrecht Jürgen writes:
> On 07/06/2011 01:48 PM, Lothar Waßmann wrote:
> > > Am I correct that all nfc-v1's have that bug, so only imx27 and imx51?
> > > The application note we finally got from freescale only mentions "FSL
> > > IMX NFC".
> > >
> > It's not exactly a bug (which would be possible to get fixed), but an
> > inherent feature of the controller which handles NAND flash with a
> > page size larger than 512 byte like it has n pages of 512 byte.
> >
> OK, a "hardware bug" then (can be fixed with a re-write of the 
> VHDL/Verilog code of the NFC, giving v2). It seems to me Freescale tried 
> to enhance their 512B-page controller with to possibility to also handle 
> 2kB pages, but they forgot about the Factory Bad Block byte (n=4 only).
> So to reply to your next mail: only the imx27 and imx31 (thanks sascha, 
> it was a typo to mention 51) have the NFC v1, I believe all the others 
> have NFC v2, which are fixed.
> 
How do you come to that conclusion? All the controllers share the same
flash buffer layout and map it to the actual flash data in the same
way. Thus the problem exists for all of them.
And the original Freescale code for i.MX5 et al. handles the bad block
markers in the same way as for i.MX2 or i.MX3.


Lothar Waßmann
Sascha Hauer July 6, 2011, 4:29 p.m. UTC | #13
On Wed, Jul 06, 2011 at 03:53:05PM +0200, Lothar Waßmann wrote:
> Hi,
> 
> Lambrecht Jürgen writes:
> > On 07/06/2011 01:48 PM, Lothar Waßmann wrote:
> > > > Am I correct that all nfc-v1's have that bug, so only imx27 and imx51?
> > > > The application note we finally got from freescale only mentions "FSL
> > > > IMX NFC".
> > > >
> > > It's not exactly a bug (which would be possible to get fixed), but an
> > > inherent feature of the controller which handles NAND flash with a
> > > page size larger than 512 byte like it has n pages of 512 byte.
> > >
> > OK, a "hardware bug" then (can be fixed with a re-write of the 
> > VHDL/Verilog code of the NFC, giving v2). It seems to me Freescale tried 
> > to enhance their 512B-page controller with to possibility to also handle 
> > 2kB pages, but they forgot about the Factory Bad Block byte (n=4 only).
> > So to reply to your next mail: only the imx27 and imx31 (thanks sascha, 
> > it was a typo to mention 51) have the NFC v1, I believe all the others 
> > have NFC v2, which are fixed.
> > 
> How do you come to that conclusion?

I remember fsl code which does this only for the v1 controller, but I
can't find this anymore, so maybe my mind fooled me.
Have you checked this somehow that it is indeed swapped for all
controllers or do you believe the fsl code?

> All the controllers share the same
> flash buffer layout and map it to the actual flash data in the same
> way. Thus the problem exists for all of them.
> And the original Freescale code for i.MX5 et al. handles the bad block
> markers in the same way as for i.MX2 or i.MX3.

Indeed :(

>From what I've seen neither barebox nor the kernel nor u-boot handle
this in Mainline versions. I think we have to do something.

Maybe we can handle this in a way that when no bad block table is
present we create one with the correct values? This way we could
eliminate the problem at least on boards with virgin flashes.

This whole topic totally sucks. Whatever we do now we end up with
corrupted flashes in one way or the other.

BTW the Bootrom code expects non swapped flash layout, so applying
a swap patch makes it impossible to update the bootloader in NAND.
Maybe that's the reason the FSL code has this disable_bi_swap sysfs
attribute in it.

Not calling this a bug makes me think you work for the Freescale
marketing department ;)

Sascha
Lothar Waßmann July 6, 2011, 4:48 p.m. UTC | #14
Hi,

Sascha Hauer writes:
> On Wed, Jul 06, 2011 at 03:53:05PM +0200, Lothar Waßmann wrote:
[...]
> Not calling this a bug makes me think you work for the Freescale
> marketing department ;)
> 
A bug can normally be fixed somehow. This 'feature' is an inherent
design flaw from the 'broken-by-design' category that cannot easily
be fixed. That's why I wouldn't call it a bug.


Lothar Waßmann
Gaëtan Carlier Aug. 8, 2012, 4:11 p.m. UTC | #15
Hi,

On 07/06/2011 02:05 PM, Sascha Hauer wrote:
> On Wed, Jul 06, 2011 at 11:30:00AM +0200, Lambrecht Jürgen wrote:
>> On 07/06/2011 10:09 AM, Sascha Hauer wrote:
>>> On Tue, Jul 05, 2011 at 03:33:48PM +0200, Jürgen Lambrecht wrote:
>>>> - Swap the BI-byte on position 0x7D0 with a data byte at 0x835.  To
>>> fix a bug
>>>>    in Freescale imx NFC v1 SoC's for 2K page NAND flashes: imx27 and
>>> imx31.
>>>>    Warning: The same solution needs to be applied to the boot loader
>>> and the
>>>>    flash programmer.
>>>> - Enable NAND support for the imx27pdk (3ds), and use BISWAP.
>>>>
>>>> Signed-off-by: Jürgen Lambrecht <J.Lambrecht@televic.com>
>>>> ---
>>>>   arch/arm/mach-imx/Kconfig         |   30 ++++++++++++++++++++++++++++--
>>>>   arch/arm/mach-imx/mach-mx27_3ds.c |   14 ++++++++++++++
>>>>   drivers/mtd/nand/mxc_nand.c       |   29 +++++++++++++++++++++++++++++
>>>>   3 files changed, 71 insertions(+), 2 deletions(-)
>>>>
>>> [snip]
>>>
>>>> +
>>>> +config IMX_NFC_V1_BISWAP
>>>> +     bool "Make the MXC 2kB-page NAND driver swap the Bad Block
>>> Indicator"
>>>> +     depends on MACH_MX27_3DS
>>>> +     depends on MTD_NAND_MXC
>>>> +     help
>>>> +       Enable this if you want that the MXC NAND driver swaps the
>>> Bad Block
>>>> +       Indicator (BBI) byte. The IMX NFC v1 (present in IMX27 and
>>> IMX31)
>>>> +       contains a bug for 2kB-page flashes: the 2kB page is read out in
>>>> +       4x512B chunks, so also the spare area is read out in 4
>>>> +       chunks. Therefore the data area and the spare area becomes
>>>> +       mixed. This causes a problem for the factory programmed BBI: it
>>>> +       appears in the data area instead of the spare area, and is
>>>> +       overwritten. This patch swaps that byte to the "real" spare
>>>> +       area. WARNING: then also the bootloader and the flash
>>> programmer must
>>>> +       be patched!!
>>>
>>> I don't like this approach. IMO some code should be run on a virgin
>>> flash which is aware of this issue and creates a correct bad block
>>> table. You run this once and forget about this afterwards and every
>>> kernel/bootloader can run without patching. Otherwise if you accidently
>>> or intentionally start an older (unpatched) kernel your Nand gets
>>> corrupted.
>>>
>> I see 3 solutions: rely on the quality of the NAND flash driver (1),
>> patch the SW (2) or patch the HW (3).
>>
>> 1. A normal NAND flash driver relies on the ECC to detect a
>> (potentially) bad block. But a factory bad block can have more bad bits
>> that the specified ECC bits.
>>      Solution is to check after each write if the data was written
>> reliable: a write/read-back policy. (linux kernel option: Device Drivers
>> -> MTD support -> NAND Device Support -> Verify NAND page writes)
>>      This will of course slow-down writing a lot.
>> 2. The Freescale solution: patch the SW:
>>         1. flash programmer
>>         2. boot-loader NAND driver
>>         3. OS NAND driver
>> 3. For the HW patch, a special SW must be written that must be executed
>> before the board is programmed. That special SW must run in RAM and copy
>> the BBI byte to the "swapped" place, so that after swapping, the BBI is
>> at the good place. Then the SW must not be patched.
>>      Risk: if this step is skipped, the factory BBI information is lost,
>> and if the SW has no write/read-back policy (solution 1), data will be
>> lost in some point in time.
>>
>> Your solution is (3), but for the linux rootfs partition only, using the
>> BBT. Of course bootloader partitions and the linux kernel binary are not
>> written often, but I read (several times, and also been told) that even
>> when only reading a nand flash it can become bad!
>> I still have to investigate this for how to solve this in the bootloader..
>>
>> Because of the risk, and to have a fast solution, we went for solution (2).
>> But if no one else is interested in this solution, I guess there is no
>> point trying to get it accepted.
>>
>>> Also, my comment above applies here too. You added a 'depends on the
>>> board I care of', but usually my kernels have all available boards
>>> compiled in. So I can select this option and it will change the
>>> behaviour of all boards I might run the kernel on, not only the
>>> ones you depend on above.
>> Ok, i should then find a better way to do it.
>> But, the mxc_nand.c code contains this to protect it: 'if
>> ((mtd->writesize > 512) && nfc_is_v1())'.
>
> This is the correct way to limit the fix to the correct versions of the
> nand controller, but that's not what I tried to say. You might want
> to use solution (2) for your board whereas I want to use solution (3)
> for my boards. With the Kconfig approach it would not be possible for
> us to use the same kernel binary.
A few years ago, I assist to a training done by Adeneo France (partner 
of Freescale). They gave us the sources (Bootloader + Kernel 2.6.22) 
that include patches to swap bytes. So all of my work is now based with 
the swap of bytes done by NFC driver in bootloader and Kernel.
I use OpenOCD to program NAND and the NFC driver that I send us also 
include this patch. Now in OpenOCD 6.0rc1, there is an option to enable 
or not the biswap at runtime (openocd command line).
So is there a way to add this option as module parameter and enable the 
biswap via command-line at kernel boot. Is this solution better than 
Kconfig ?
I really need this biswap patch otherwise my previous work will be 
broken. If you told me that module parameter is an acceptable way to 
implement this workaround, I will write the patch.

>
>> Am I correct that all nfc-v1's have that bug, so only imx27 and imx51?
>> The application note we finally got from freescale only mentions "FSL
>> IMX NFC".
>
> s/imx51/imx31/.
>
> Yes, only imx27 and imx31 a affected by this bug.
>
> Sascha
>

Thanks,
Gaëtan Carlier
diff mbox

Patch

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 0519dd7..e8b16a9 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -274,7 +274,7 @@  config MACH_EUKREA_MBIMX27_BASEBOARD
 endchoice
 
 config MACH_MX27_3DS
-	bool "MX27PDK platform"
+	bool "MX27PDK (3DS) platform"
 	select SOC_IMX27
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
@@ -284,13 +284,39 @@  config MACH_MX27_3DS
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_MMC
+	select IMX_HAVE_PLATFORM_MXC_NAND
 	select IMX_HAVE_PLATFORM_SPI_IMX
 	select MXC_DEBUG_BOARD
 	select MXC_ULPI if USB_ULPI
 	help
-	  Include support for MX27PDK platform. This includes specific
+	  Include support for MX27PDK (3DS) platform. This includes specific
 	  configurations for the board and its peripherals.
 
+config MACH_MXC_NAND_USE_BBT
+	bool "Make the MXC NAND driver use the in flash Bad Block Table"
+	depends on MACH_MX27_3DS
+	depends on MTD_NAND_MXC
+	help
+	  Enable this if you want that the MXC NAND driver uses the in flash
+	  Bad Block Table to know what blocks are bad instead of scanning the
+	  entire flash looking for bad block markers.
+
+config IMX_NFC_V1_BISWAP
+	bool "Make the MXC 2kB-page NAND driver swap the Bad Block Indicator"
+	depends on MACH_MX27_3DS
+	depends on MTD_NAND_MXC
+	help
+	  Enable this if you want that the MXC NAND driver swaps the Bad Block
+	  Indicator (BBI) byte. The IMX NFC v1 (present in IMX27 and IMX31)
+	  contains a bug for 2kB-page flashes: the 2kB page is read out in
+	  4x512B chunks, so also the spare area is read out in 4
+	  chunks. Therefore the data area and the spare area becomes
+	  mixed. This causes a problem for the factory programmed BBI: it
+	  appears in the data area instead of the spare area, and is
+	  overwritten. This patch swaps that byte to the "real" spare
+	  area. WARNING: then also the bootloader and the flash programmer must
+	  be patched!!
+
 config MACH_IMX27_VISSTRIM_M10
 	bool "Vista Silicon i.MX27 Visstrim_m10"
 	select SOC_IMX27
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index 526cbe1..84114aa 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -40,6 +40,7 @@ 
 #include <mach/ulpi.h>
 #include <mach/irqs.h>
 #include <mach/3ds_debugboard.h>
+#include <mach/mxc_nand.h>
 
 #include "devices-imx27.h"
 
@@ -369,6 +370,18 @@  static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
 	},
 };
 
+/*
+ * NAND Flash
+ */
+static const struct mxc_nand_platform_data
+mx27_3ds_nand_board_info __initconst = {
+	.width		= 1,
+	.hw_ecc		= 1,
+#ifdef MACH_MXC_NAND_USE_BBT
+	.flash_bbt	= 1,
+#endif
+};
+
 static const struct imxi2c_platform_data mx27_3ds_i2c0_data __initconst = {
 	.bitrate = 100000,
 };
@@ -380,6 +393,7 @@  static void __init mx27pdk_init(void)
 	mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
 		"mx27pdk");
 	mx27_3ds_sdhc1_enable_level_translator();
+	imx27_add_mxc_nand(&mx27_3ds_nand_board_info);
 	imx27_add_imx_uart0(&uart_pdata);
 	imx27_add_fec(NULL);
 	imx27_add_imx_keypad(&mx27_3ds_keymap_data);
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 90df34c..83f54d6 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -612,6 +612,30 @@  static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 	return 0;
 }
 
+/*
+ * Swap the BI-byte on position 0x7D0 with a data byte at 0x835.
+ * To fix a bug in NFC v1 SoC's for 2K page NAND flashes: imx27 and imx31.
+ * Warning: The same solution needs to be applied to the boot loader and the
+ * flash programmer.
+ */
+#ifdef CONFIG_IMX_NFC_V1_BISWAP
+static void imx_bi_swap(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	unsigned short temp1, temp2, new_temp1;
+
+	temp1 = *((volatile unsigned short*)(host->main_area0 + 0x7D0));
+	temp2 = *((volatile unsigned short*)(host->main_area0 + 0x834));
+	new_temp1 = (temp1 & 0xFF00) | (temp2 >> 8);
+	temp2 = (temp2 & 0x00FF) | (temp1 << 8);
+	*((volatile unsigned short*)(host->main_area0 + 0x7D0)) = new_temp1;
+	*((volatile unsigned short*)(host->main_area0 + 0x834)) = temp2;
+}
+#else
+static inline void imx_bi_swap(struct mtd_info *mtd) {}
+#endif
+
 static u_char mxc_nand_read_byte(struct mtd_info *mtd)
 {
 	struct nand_chip *nand_chip = mtd->priv;
@@ -971,6 +995,9 @@  static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 
 		host->send_page(mtd, NFC_OUTPUT);
 
+		if ((mtd->writesize > 512) && nfc_is_v1())
+			imx_bi_swap(mtd);
+
 		memcpy(host->data_buf, host->main_area0, mtd->writesize);
 		copy_spare(mtd, true);
 		break;
@@ -989,6 +1016,8 @@  static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 	case NAND_CMD_PAGEPROG:
 		memcpy(host->main_area0, host->data_buf, mtd->writesize);
 		copy_spare(mtd, false);
+		if ((mtd->writesize > 512) && nfc_is_v1())
+			imx_bi_swap(mtd);
 		host->send_page(mtd, NFC_INPUT);
 		host->send_cmd(host, command, true);
 		mxc_do_addr_cycle(mtd, column, page_addr);