Subject: [PATCH] omap3 nand : use NAND_BUSWIDTH_AUTO

From: Matthieu CASTET <[email-masked]>
Date: Thu, 7 Feb 2013 09:59:25 +0100

This allow to clean the omap nand driver that were trying in x8 and x16 bits
mode.

This also make work onfi detection on beagleboard :

Before :
[    1.954803] NAND device: Manufacturer ID: 0x2c, Chip ID: 0xba (Micron NAND 256MiB 1,8V 16-bit), page size: 2048, OOB size: 64

After :
[    1.914825] ONFI param page 0 valid
[    1.919158] ONFI flash detected
[    1.922515] NAND device: Manufacturer ID: 0x2c, Chip ID: 0xba (Micron MT29F2G16ABD), page size: 2048, OOB size: 64

platform data devsize is renamed bussize. It now indicate the maximun size of
the nand bus.

Signed-off-by: Matthieu CASTET <[email-masked]>
---
 arch/arm/mach-omap2/board-3630sdp.c          |    2 +-
 arch/arm/mach-omap2/board-devkit8000.c       |    2 +-
 arch/arm/mach-omap2/board-flash.c            |    8 ++---
 arch/arm/mach-omap2/board-igep0020.c         |    2 +-
 arch/arm/mach-omap2/board-omap3beagle.c      |    2 +-
 arch/arm/mach-omap2/board-omap3evm.c         |    2 +-
 arch/arm/mach-omap2/board-omap3pandora.c     |    2 +-
 arch/arm/mach-omap2/board-omap3touchbook.c   |    2 +-
 arch/arm/mach-omap2/board-zoom.c             |    2 +-
 arch/arm/mach-omap2/gpmc-nand.c              |    5 ---
 drivers/mtd/nand/omap2.c                     |   45 +++++++++++++++-----------
 include/linux/platform_data/mtd-nand-omap2.h |    7 +++-
 12 files changed, 44 insertions(+), 37 deletions(-)

diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 050aaa7..34c0cb8 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -197,7 +197,7 @@ static void __init omap_sdp_init(void)
 				  h8mbx00u0mer0em_sdrc_params);
 	zoom_display_init();
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16);
+	board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_OMAP_BUS_16);
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
 }
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 7667eb7..06ef8a1 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -625,7 +625,7 @@ static void __init devkit8000_init(void)
 	usbhs_init(&usbhs_bdata);
 	board_nand_init(devkit8000_nand_partitions,
 			ARRAY_SIZE(devkit8000_nand_partitions), NAND_CS,
-			NAND_BUSWIDTH_16, NULL);
+			NAND_OMAP_BUS_16, NULL);
 	omap_twl4030_audio_init("omap3beagle");
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index c33adea..457b6b9 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -132,12 +132,12 @@ static struct omap_nand_platform_data board_nand_data;
 
 void
 __init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
-				int nand_type, struct gpmc_timings *gpmc_t)
+				int bus_type, struct gpmc_timings *gpmc_t)
 {
 	board_nand_data.cs		= cs;
 	board_nand_data.parts		= nand_parts;
 	board_nand_data.nr_parts	= nr_parts;
-	board_nand_data.devsize		= nand_type;
+	board_nand_data.bussize		= bus_type;
 
 	board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT;
 	gpmc_nand_init(&board_nand_data, gpmc_t);
@@ -184,7 +184,7 @@ unmap:
  * @return - void.
  */
 void __init board_flash_init(struct flash_partitions partition_info[],
-			char chip_sel_board[][GPMC_CS_NUM], int nand_type)
+			char chip_sel_board[][GPMC_CS_NUM], int bus_type)
 {
 	u8		cs = 0;
 	u8		norcs = GPMC_CS_NUM + 1;
@@ -238,5 +238,5 @@ void __init board_flash_init(struct flash_partitions partition_info[],
 	else
 		board_nand_init(partition_info[2].parts,
 			partition_info[2].nr_parts, nandcs,
-			nand_type, nand_default_timings);
+			bus_type, nand_default_timings);
 }
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 0f24cb8..5a2bf03 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -174,7 +174,7 @@ static void __init igep_flash_init(void)
 		pr_info("IGEP: initializing NAND memory device\n");
 		board_nand_init(igep_flash_partitions,
 				ARRAY_SIZE(igep_flash_partitions),
-				0, NAND_BUSWIDTH_16, nand_default_timings);
+				0, NAND_OMAP_BUS_16, nand_default_timings);
 	} else if (mux == IGEP_SYSBOOT_ONENAND) {
 		pr_info("IGEP: initializing OneNAND memory device\n");
 		board_onenand_init(igep_flash_partitions,
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 22c483d..133491b 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -523,7 +523,7 @@ static void __init omap3_beagle_init(void)
 	usbhs_init(&usbhs_bdata);
 	board_nand_init(omap3beagle_nand_partitions,
 			ARRAY_SIZE(omap3beagle_nand_partitions), NAND_CS,
-			NAND_BUSWIDTH_16, NULL);
+			NAND_OMAP_BUS_16, NULL);
 	omap_twl4030_audio_init("omap3beagle");
 
 	/* Ensure msecure is mux'd to be able to set the RTC. */
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 54647d6..67b6821 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -737,7 +737,7 @@ static void __init omap3_evm_init(void)
 	usbhs_init(&usbhs_bdata);
 	board_nand_init(omap3evm_nand_partitions,
 			ARRAY_SIZE(omap3evm_nand_partitions), NAND_CS,
-			NAND_BUSWIDTH_16, NULL);
+			NAND_OMAP_BUS_16, NULL);
 
 	omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL);
 	omap3evm_init_smsc911x();
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index a53a668..635c5bf 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -82,7 +82,7 @@ static struct mtd_partition omap3pandora_nand_partitions[] = {
 
 static struct omap_nand_platform_data pandora_nand_data = {
 	.cs		= 0,
-	.devsize	= NAND_BUSWIDTH_16,
+	.bussize	= NAND_OMAP_BUS_16,
 	.xfer_type	= NAND_OMAP_PREFETCH_DMA,
 	.parts		= omap3pandora_nand_partitions,
 	.nr_parts	= ARRAY_SIZE(omap3pandora_nand_partitions),
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 263cb9c..a96d46d 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -369,7 +369,7 @@ static void __init omap3_touchbook_init(void)
 	usbhs_init(&usbhs_bdata);
 	board_nand_init(omap3touchbook_nand_partitions,
 			ARRAY_SIZE(omap3touchbook_nand_partitions), NAND_CS,
-			NAND_BUSWIDTH_16, NULL);
+			NAND_OMAP_BUS_16, NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index d7fa31e..1f6599f 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -114,7 +114,7 @@ static void __init omap_zoom_init(void)
 
 	board_nand_init(zoom_nand_partitions,
 			ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS,
-			NAND_BUSWIDTH_16, nand_default_timings);
+			NAND_OMAP_BUS_16, nand_default_timings);
 	zoom_debugboard_init();
 	zoom_peripherals_init();
 
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index db969a5..6e1d5ca 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -74,11 +74,6 @@ static int omap2_nand_gpmc_retime(
 	t.cs_wr_off = gpmc_t->cs_wr_off;
 	t.wr_cycle = gpmc_t->wr_cycle;
 
-	/* Configure GPMC */
-	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
-	else
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0);
 	gpmc_cs_configure(gpmc_nand_data->cs,
 			GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND);
 	gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_WP, 0);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 0002d5e..fae828b 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -27,6 +27,9 @@
 #include <linux/bch.h>
 #endif
 
+/* FIXME gpmc.h header is not public */
+#include "../gpmc.h"
+
 #include <linux/platform_data/mtd-nand-omap2.h>
 
 #define	DRIVER_NAME	"omap2-nand"
@@ -1357,7 +1360,7 @@ static int omap_nand_probe(struct platform_device *pdev)
 	info->mtd.name		= dev_name(&pdev->dev);
 	info->mtd.owner		= THIS_MODULE;
 
-	info->nand.options	= pdata->devsize;
+	info->nand.options	= NAND_BUSWIDTH_AUTO;
 	info->nand.options	|= NAND_SKIP_BBTSCAN;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1409,13 +1412,8 @@ static int omap_nand_probe(struct platform_device *pdev)
 		break;
 
 	case NAND_OMAP_POLLED:
-		if (info->nand.options & NAND_BUSWIDTH_16) {
-			info->nand.read_buf   = omap_read_buf16;
-			info->nand.write_buf  = omap_write_buf16;
-		} else {
-			info->nand.read_buf   = omap_read_buf8;
-			info->nand.write_buf  = omap_write_buf8;
-		}
+		info->nand.read_buf   = omap_read_buf8;
+		info->nand.write_buf  = omap_write_buf8;
 		break;
 
 	case NAND_OMAP_PREFETCH_DMA:
@@ -1491,6 +1489,26 @@ static int omap_nand_probe(struct platform_device *pdev)
 		goto out_release_mem_region;
 	}
 
+	gpmc_cs_configure(info->gpmc_cs, GPMC_CONFIG_DEV_SIZE, 0);
+	if (nand_scan_ident(&info->mtd, 1, NULL)) {
+		err = -ENXIO;
+		goto out_release_mem_region;
+	}
+
+	/* update for 16 bits device */
+	if (info->nand.options & NAND_BUSWIDTH_16) {
+		if (!(pdata->bussize & NAND_OMAP_BUS_16)) {
+			dev_err(&pdev->dev, "detected x16 flash, but board only support x8 flash\n");
+			err = -ENXIO;
+			goto out_release_mem_region;
+		}
+		gpmc_cs_configure(info->gpmc_cs, GPMC_CONFIG_DEV_SIZE, 1);
+		if (pdata->xfer_type == NAND_OMAP_POLLED) {
+			info->nand.read_buf   = omap_read_buf16;
+			info->nand.write_buf  = omap_write_buf16;
+		}
+	}
+
 	/* select the ecc type */
 	if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_DEFAULT)
 		info->nand.ecc.mode = NAND_ECC_SOFT;
@@ -1512,17 +1530,6 @@ static int omap_nand_probe(struct platform_device *pdev)
 		}
 	}
 
-	/* DIP switches on some boards change between 8 and 16 bit
-	 * bus widths for flash.  Try the other width if the first try fails.
-	 */
-	if (nand_scan_ident(&info->mtd, 1, NULL)) {
-		info->nand.options ^= NAND_BUSWIDTH_16;
-		if (nand_scan_ident(&info->mtd, 1, NULL)) {
-			err = -ENXIO;
-			goto out_release_mem_region;
-		}
-	}
-
 	/* rom code layout */
 	if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE) {
 
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index 24d32ca..d801c7a 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -51,13 +51,18 @@ struct gpmc_nand_regs {
 	void __iomem	*gpmc_bch_result3[GPMC_BCH_NUM_REMAINDER];
 };
 
+enum nand_bussize {
+	NAND_OMAP_BUS_8,
+	NAND_OMAP_BUS_16,
+};
+
 struct omap_nand_platform_data {
 	int			cs;
 	struct mtd_partition	*parts;
 	int			nr_parts;
 	bool			dev_ready;
 	enum nand_io		xfer_type;
-	int			devsize;
+	enum nand_bussize		bussize;
 	enum omap_ecc           ecc_opt;
 	struct gpmc_nand_regs	reg;
 };
-- 
1.7.10.4