mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 0/3] nand: autodetect buswith
@ 2012-07-24 14:39 Jan Weitzel
  2012-07-24 14:39 ` [PATCH 1/3] nand: base: Add autodetect buswidth Jan Weitzel
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jan Weitzel @ 2012-07-24 14:39 UTC (permalink / raw)
  To: barebox

Add flag NAND_BUSWIDTH_UNKNOWN to allow the nand driver to detect the buswidth.
Driver must provide callback set_buswidth which configure buswidth set in
(struct nand_chip) nand->options

Jan Weitzel (3):
  nand: base: Add autodetect buswidth
  OMAP GPMC NAND: add set_buswidth callback
  PCA-A_XL2 PCM049: Use autodetection for NAND width

 arch/arm/boards/pcm049/board.c            |    4 +-
 arch/arm/boards/phycard-a-xl2/pca-a-xl2.c |    3 +-
 arch/arm/mach-omap/devices-gpmc-nand.c    |    8 ++---
 arch/arm/mach-omap/gpmc.c                 |   19 ++++++++++++
 arch/arm/mach-omap/include/mach/gpmc.h    |    8 +++++
 drivers/mtd/nand/nand_base.c              |   45 ++++++++++++++++++++++++++--
 drivers/mtd/nand/nand_omap_gpmc.c         |   43 ++++++++++++++++++++++++---
 include/linux/mtd/nand.h                  |    4 ++
 8 files changed, 117 insertions(+), 17 deletions(-)


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] nand: base: Add autodetect buswidth
  2012-07-24 14:39 [PATCH 0/3] nand: autodetect buswith Jan Weitzel
@ 2012-07-24 14:39 ` Jan Weitzel
  2012-07-24 14:39 ` [PATCH 2/3] OMAP GPMC NAND: add set_buswidth callback Jan Weitzel
  2012-07-24 14:39 ` [PATCH 3/3] PCA-A_XL2 PCM049: Use autodetection for NAND width Jan Weitzel
  2 siblings, 0 replies; 4+ messages in thread
From: Jan Weitzel @ 2012-07-24 14:39 UTC (permalink / raw)
  To: barebox

If a 16bit NAND is attached, but configured with 8bit nand_base will fail.
Add a flag NAND_BUSWIDTH_UNKNOWN and callback set_buswidth to allow it to
change the configuration to 16bit.

Signed-off-by: Jan Weitzel <j.weitzel@phytec.de>
---
 drivers/mtd/nand/nand_base.c |   45 ++++++++++++++++++++++++++++++++++++++---
 include/linux/mtd/nand.h     |    4 +++
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index c4eca0d..055c710 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1027,6 +1027,23 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
 }
 
 /*
+ * Override defaults with 16 bit ones
+ */
+static void nand_set_defaults16(struct nand_chip *chip)
+{
+	if (chip->read_byte == nand_read_byte)
+		chip->read_byte = nand_read_byte16;
+#ifdef CONFIG_MTD_WRITE
+	if (chip->write_buf == nand_write_buf)
+		chip->write_buf = nand_write_buf16;
+#endif
+	if (chip->read_buf == nand_read_buf)
+		chip->read_buf = nand_read_buf16;
+	if (chip->verify_buf == nand_verify_buf)
+		chip->verify_buf = nand_verify_buf16;
+}
+
+/*
  * Get the flash and manufacturer id and lookup if the type is supported
  */
 static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
@@ -1128,9 +1145,12 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 
 	/*
 	 * Check, if buswidth is correct. Hardware drivers should set
-	 * chip correct !
+	 * chip correct or ask for autodetection!
 	 */
-	if (busw != (chip->options & NAND_BUSWIDTH_16)) {
+	if (chip->options & NAND_BUSWIDTH_UNKNOWN) {
+		printk(KERN_INFO "NAND bus width %d bit detected\n",
+		       (type->options & NAND_BUSWIDTH_16) ? 16 : 8);
+	} else if (busw != (chip->options & NAND_BUSWIDTH_16)) {
 		printk(KERN_INFO "NAND device: Manufacturer ID:"
 		       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
 		       dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
@@ -1202,8 +1222,18 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)
 	struct nand_chip *chip = mtd->priv;
 	struct nand_flash_dev *type;
 
-	/* Get buswidth to select the correct functions */
-	busw = chip->options & NAND_BUSWIDTH_16;
+	if (chip->options & NAND_BUSWIDTH_UNKNOWN) {
+		if (!chip->set_buswidth) {
+			chip->options &= ~NAND_BUSWIDTH_UNKNOWN;
+			printk(KERN_WARNING "Buswidth unknown, but no callback to fix it.\n");
+		}
+		/* Detect NAND with 8bit buswidth*/
+		busw = 0;
+	} else {
+		/* Get buswidth to select the correct functions */
+		busw = chip->options & NAND_BUSWIDTH_16;
+	}
+
 	/* Set the default functions */
 	nand_set_defaults(chip, busw);
 
@@ -1216,6 +1246,13 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)
 		return PTR_ERR(type);
 	}
 
+	if (chip->options & NAND_BUSWIDTH_UNKNOWN) {
+		chip->set_buswidth(mtd, chip);
+		if (chip->options & NAND_BUSWIDTH_16)
+			/* Change buswidth to 16 bit*/
+			nand_set_defaults16(chip);
+	}
+
 	/* Check for a chip array */
 	for (i = 1; i < maxchips; i++) {
 		chip->select_chip(mtd, i);
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 8e20876..184fc69 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -192,6 +192,8 @@ typedef enum {
 /* This option is defined if the board driver allocates its own buffers
    (e.g. because it needs them DMA-coherent */
 #define NAND_OWN_BUFFERS	0x00040000
+/* Buswitdh is currently unknown */
+#define NAND_BUSWIDTH_UNKNOWN	0x00080000
 /* Options set by nand scan */
 /* Nand scan has allocated controller struct */
 #define NAND_CONTROLLER_ALLOC	0x80000000
@@ -358,6 +360,7 @@ struct nand_buffers {
  * @errstat:		[OPTIONAL] hardware specific function to perform additional error status checks
  *			(determine if errors are correctable)
  * @write_page:		[REPLACEABLE] High-level page write function
+ * @set_buswidth:	[BOARDSPECIFIC] hardware specific function to configure buswidth
  */
 struct nand_chip {
 
@@ -382,6 +385,7 @@ struct nand_chip {
 	int		(*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
 	int		(*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
 				      const uint8_t *buf, int page, int cached, int raw);
+	int		(*set_buswidth)(struct mtd_info *mtd, struct nand_chip *this);
 
 	int		chip_delay;
 	unsigned int	options;
-- 
1.7.0.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/3] OMAP GPMC NAND: add set_buswidth callback
  2012-07-24 14:39 [PATCH 0/3] nand: autodetect buswith Jan Weitzel
  2012-07-24 14:39 ` [PATCH 1/3] nand: base: Add autodetect buswidth Jan Weitzel
@ 2012-07-24 14:39 ` Jan Weitzel
  2012-07-24 14:39 ` [PATCH 3/3] PCA-A_XL2 PCM049: Use autodetection for NAND width Jan Weitzel
  2 siblings, 0 replies; 4+ messages in thread
From: Jan Weitzel @ 2012-07-24 14:39 UTC (permalink / raw)
  To: barebox

If buswidth is not configured in platformdata (=0) set NAND_BUSWIDTH_UNKNOWN
flag to allow nand_base to autodetect the setting.

Signed-off-by: Jan Weitzel <j.weitzel@phytec.de>
---
 arch/arm/mach-omap/devices-gpmc-nand.c |    8 ++---
 arch/arm/mach-omap/gpmc.c              |   19 ++++++++++++++
 arch/arm/mach-omap/include/mach/gpmc.h |    8 ++++++
 drivers/mtd/nand/nand_omap_gpmc.c      |   43 ++++++++++++++++++++++++++++---
 4 files changed, 68 insertions(+), 10 deletions(-)

diff --git a/arch/arm/mach-omap/devices-gpmc-nand.c b/arch/arm/mach-omap/devices-gpmc-nand.c
index 54625ca..8a867f6 100644
--- a/arch/arm/mach-omap/devices-gpmc-nand.c
+++ b/arch/arm/mach-omap/devices-gpmc-nand.c
@@ -36,9 +36,6 @@
 #include <mach/gpmc.h>
 #include <mach/gpmc_nand.h>
 
-#define GPMC_CONF1_VALx8	0x00000800
-#define GPMC_CONF1_VALx16	0x00001800
-
 /** NAND platform specific settings settings */
 static struct gpmc_nand_platform_data nand_plat = {
 	.cs = 0,
@@ -57,9 +54,10 @@ int gpmc_generic_nand_devices_init(int cs, int width,
 	nand_plat.cs = cs;
 
 	if (width == 16)
-		nand_cfg->cfg[0] = GPMC_CONF1_VALx16;
+		nand_cfg->cfg[0] = GPMC_CONFIG1_DEVICETYPE_NAND |
+					GPMC_CONFIG1_DEVICESIZE_16;
 	else
-		nand_cfg->cfg[0] = GPMC_CONF1_VALx8;
+		nand_cfg->cfg[0] = GPMC_CONFIG1_DEVICETYPE_NAND;
 
 	nand_plat.device_width = width;
 	nand_plat.ecc_mode = eccmode;
diff --git a/arch/arm/mach-omap/gpmc.c b/arch/arm/mach-omap/gpmc.c
index 92a8ae0..b3fa56c 100644
--- a/arch/arm/mach-omap/gpmc.c
+++ b/arch/arm/mach-omap/gpmc.c
@@ -125,3 +125,22 @@ void gpmc_cs_config(char cs, struct gpmc_config *config)
 	mdelay(1);		/* Settling time */
 }
 EXPORT_SYMBOL(gpmc_cs_config);
+
+void gpmc_get_config(char cs, struct gpmc_config *config)
+{
+	unsigned int reg = GPMC_REG(CONFIG1_0) + (cs * GPMC_CONFIG_CS_SIZE);
+	unsigned int cfg7;
+	unsigned char i;
+
+	/* Read the CFG1-6 regs */
+	for (i = 0; i < 6; i++) {
+		config->cfg[i] = readl(reg);
+		reg += GPMC_CONFIG_REG_OFF;
+	}
+
+	cfg7 = readl(reg);
+
+	config->size = (cfg7 >> 8) & 0xf;
+	config->base = (cfg7 & 0x3F) << 24;
+}
+EXPORT_SYMBOL(gpmc_get_config);
diff --git a/arch/arm/mach-omap/include/mach/gpmc.h b/arch/arm/mach-omap/include/mach/gpmc.h
index 3ddc5f5..84260fc 100644
--- a/arch/arm/mach-omap/include/mach/gpmc.h
+++ b/arch/arm/mach-omap/include/mach/gpmc.h
@@ -140,6 +140,11 @@
 
 #define NAND_WP_BIT		0x00000010
 
+#define GPMC_CONFIG1_DEVICESIZE(val)	((val & 3) << 12)
+#define GPMC_CONFIG1_DEVICESIZE_16	GPMC_CONFIG1_DEVICESIZE(1)
+#define GPMC_CONFIG1_DEVICETYPE(val)	((val & 3) << 10)
+#define GPMC_CONFIG1_DEVICETYPE_NAND	GPMC_CONFIG1_DEVICETYPE(2)
+
 #ifndef __ASSEMBLY__
 
 /** Generic GPMC configuration structure to be used to configure a
@@ -157,6 +162,9 @@ void gpmc_generic_init(unsigned int cfg);
 /** Configuration for a specific chip select */
 void gpmc_cs_config(char cs, struct gpmc_config *config);
 
+/** Get Configuration for a specific chip select */
+void gpmc_get_config(char cs, struct gpmc_config *config);
+
 #endif
 
 #endif /* __ASM_ARCH_OMAP_GPMC_H */
diff --git a/drivers/mtd/nand/nand_omap_gpmc.c b/drivers/mtd/nand/nand_omap_gpmc.c
index d55dcaa..63aae81 100644
--- a/drivers/mtd/nand/nand_omap_gpmc.c
+++ b/drivers/mtd/nand/nand_omap_gpmc.c
@@ -803,6 +803,28 @@ static int omap_gpmc_eccmode_set(struct device_d *dev, struct param_d *param, co
 	return omap_gpmc_eccmode(oinfo, i);
 }
 
+static int gpmc_set_buswidth(struct mtd_info *mtd, struct nand_chip *nand)
+{
+	struct gpmc_nand_info *oinfo = nand->priv;
+	struct gpmc_nand_platform_data *pdata = oinfo->pdata;
+	struct gpmc_config cfg;
+
+	gpmc_get_config(oinfo->gpmc_cs, &cfg);
+
+	if (nand->options & NAND_BUSWIDTH_16)
+		cfg.cfg[0] = GPMC_CONFIG1_DEVICETYPE_NAND |
+				GPMC_CONFIG1_DEVICESIZE_16;
+	else
+		cfg.cfg[0] = GPMC_CONFIG1_DEVICETYPE_NAND;
+
+	pdata->device_width = (nand->options & NAND_BUSWIDTH_16) ? 16 : 8;
+	dev_dbg(oinfo->pdev, "set buswidth to %d bit\n", pdata->device_width);
+
+	gpmc_cs_config(oinfo->gpmc_cs, &cfg);
+
+	return 0;
+}
+
 /**
  * @brief nand device probe.
  *
@@ -836,6 +858,7 @@ static int gpmc_nand_probe(struct device_d *pdev)
 
 	nand = &oinfo->nand;
 	nand->priv = (void *)oinfo;
+	nand->set_buswidth = gpmc_set_buswidth;
 
 	minfo = &oinfo->minfo;
 	minfo->priv = (void *)nand;
@@ -854,14 +877,23 @@ static int gpmc_nand_probe(struct device_d *pdev)
 	oinfo->gpmc_address = (void *)(cs_base + GPMC_CS_NAND_ADDRESS);
 	oinfo->gpmc_data = (void *)(cs_base + GPMC_CS_NAND_DATA);
 	oinfo->timeout = pdata->max_timeout;
-	dev_dbg(pdev, "GPMC base=0x%p cmd=0x%p address=0x%p data=0x%p cs_base=0x%p\n",
+	dev_dbg(pdev, "GPMC base=0x%p cmd=0x%p address=0x%p data=0x%p "
+		"cs_base=0x%p buswidth=%d\n",
 		oinfo->gpmc_base, oinfo->gpmc_command, oinfo->gpmc_address,
-		oinfo->gpmc_data, cs_base);
+		oinfo->gpmc_data, cs_base, pdata->device_width);
 
-	/* If we are 16 bit dev, our gpmc config tells us that */
-	if ((readl(cs_base) & 0x3000) == 0x1000) {
-		dev_dbg(pdev, "16 bit dev\n");
+	switch (pdata->device_width) {
+	case 0:
+		nand->options |= NAND_BUSWIDTH_UNKNOWN;
+		break;
+	case 8:
+		break;
+	case 16:
 		nand->options |= NAND_BUSWIDTH_16;
+		break;
+	default:
+		err = -EINVAL;
+		goto out_release_mem;
 	}
 
 	/* Same data register for in and out */
@@ -938,6 +970,7 @@ static int gpmc_nand_probe(struct device_d *pdev)
 		llp = &ecc_lp_x16;
 		break;
 	default:
+		dev_dbg(pdev, "buswidth %d unknown\n", pdata->device_width);
 		err = -EINVAL;
 		goto out_release_mem;
 	}
-- 
1.7.0.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 3/3] PCA-A_XL2 PCM049: Use autodetection for NAND width
  2012-07-24 14:39 [PATCH 0/3] nand: autodetect buswith Jan Weitzel
  2012-07-24 14:39 ` [PATCH 1/3] nand: base: Add autodetect buswidth Jan Weitzel
  2012-07-24 14:39 ` [PATCH 2/3] OMAP GPMC NAND: add set_buswidth callback Jan Weitzel
@ 2012-07-24 14:39 ` Jan Weitzel
  2 siblings, 0 replies; 4+ messages in thread
From: Jan Weitzel @ 2012-07-24 14:39 UTC (permalink / raw)
  To: barebox


Signed-off-by: Jan Weitzel <j.weitzel@phytec.de>
---
 arch/arm/boards/pcm049/board.c            |    4 ++--
 arch/arm/boards/phycard-a-xl2/pca-a-xl2.c |    3 ++-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boards/pcm049/board.c b/arch/arm/boards/pcm049/board.c
index 8718d2b..006e924 100644
--- a/arch/arm/boards/pcm049/board.c
+++ b/arch/arm/boards/pcm049/board.c
@@ -111,9 +111,9 @@ static int pcm049_devices_init(void)
 
 	pcm049_network_init();
 
-	gpmc_generic_nand_devices_init(0, 8,
+	/* Autodetect buswidth */
+	gpmc_generic_nand_devices_init(0, 0,
 			OMAP_ECC_BCH8_CODE_HW, &omap4_nand_cfg);
-
 #ifdef CONFIG_PARTITION
 	devfs_add_partition("nand0", 0x00000, SZ_128K, PARTITION_FIXED, "xload_raw");
 	dev_add_bb_dev("xload_raw", "xload");
diff --git a/arch/arm/boards/phycard-a-xl2/pca-a-xl2.c b/arch/arm/boards/phycard-a-xl2/pca-a-xl2.c
index 9bbb054..f246f86 100644
--- a/arch/arm/boards/phycard-a-xl2/pca-a-xl2.c
+++ b/arch/arm/boards/phycard-a-xl2/pca-a-xl2.c
@@ -124,7 +124,8 @@ static int pcaaxl2_devices_init(void)
 
 	pcaaxl2_network_init();
 
-	gpmc_generic_nand_devices_init(0, 16,
+	/* Autodetect buswidth */
+	gpmc_generic_nand_devices_init(0, 0,
 			OMAP_ECC_BCH8_CODE_HW, &omap4_nand_cfg);
 
 #ifdef CONFIG_PARTITION
-- 
1.7.0.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-07-24 14:40 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-24 14:39 [PATCH 0/3] nand: autodetect buswith Jan Weitzel
2012-07-24 14:39 ` [PATCH 1/3] nand: base: Add autodetect buswidth Jan Weitzel
2012-07-24 14:39 ` [PATCH 2/3] OMAP GPMC NAND: add set_buswidth callback Jan Weitzel
2012-07-24 14:39 ` [PATCH 3/3] PCA-A_XL2 PCM049: Use autodetection for NAND width Jan Weitzel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox