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

Jürgen Lambrecht juergen.lambrecht at gmail.com
Tue Jul 5 09:33:48 EDT 2011


- 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 at 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.
+
+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);
-- 
1.7.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/


More information about the linux-arm-kernel mailing list