mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 1/3] string: add strim for ONFI code
@ 2012-07-05 10:22 Eric Bénard
  2012-07-05 10:22 ` [PATCH 2/3] nand_base: add ONFI flash detection Eric Bénard
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Eric Bénard @ 2012-07-05 10:22 UTC (permalink / raw)
  To: barebox

Signed-off-by: Eric Bénard <eric@eukrea.com>
---
 include/linux/string.h |    3 +++
 lib/string.c           |   39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/include/linux/string.h b/include/linux/string.h
index 62d743e..afd0aa6 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -93,6 +93,9 @@ extern int memcmp(const void *,const void *,__kernel_size_t);
 #ifndef __HAVE_ARCH_MEMCHR
 extern void * memchr(const void *,int,__kernel_size_t);
 #endif
+extern char * skip_spaces(const char *);
+
+extern char *strim(char *);
 
 #ifdef __cplusplus
 }
diff --git a/lib/string.c b/lib/string.c
index 2865088..db4f2ae 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -567,3 +567,42 @@ void *memchr(const void *s, int c, size_t n)
 #endif
 EXPORT_SYMBOL(memchr);
 
+/**
+ * skip_spaces - Removes leading whitespace from @str.
+ * @str: The string to be stripped.
+ *
+ * Returns a pointer to the first non-whitespace character in @str.
+ */
+char *skip_spaces(const char *str)
+{
+	while (isspace(*str))
+		++str;
+	return (char *)str;
+}
+
+/**
+ * strim - Removes leading and trailing whitespace from @s.
+ * @s: The string to be stripped.
+ *
+ * Note that the first trailing whitespace is replaced with a %NUL-terminator
+ * in the given string @s. Returns a pointer to the first non-whitespace
+ * character in @s.
+ */
+char *strim(char *s)
+{
+	size_t size;
+	char *end;
+
+	s = skip_spaces(s);
+	size = strlen(s);
+	if (!size)
+		return s;
+
+	end = s + size - 1;
+	while (end >= s && isspace(*end))
+		end--;
+	*(end + 1) = '\0';
+
+	return s;
+}
+EXPORT_SYMBOL(strim);
-- 
1.7.7.6


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

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

* [PATCH 2/3] nand_base: add ONFI flash detection
  2012-07-05 10:22 [PATCH 1/3] string: add strim for ONFI code Eric Bénard
@ 2012-07-05 10:22 ` Eric Bénard
  2012-07-05 19:02   ` Sascha Hauer
  2012-07-05 10:22 ` [PATCH 3/3] nand_imx: update to support onfi & 4k flashs Eric Bénard
  2012-07-09  7:30 ` [PATCH 1/3] string: add strim for ONFI code Sascha Hauer
  2 siblings, 1 reply; 6+ messages in thread
From: Eric Bénard @ 2012-07-05 10:22 UTC (permalink / raw)
  To: barebox

the code is taken from linux & u-boot implementations
Validated on an i.MX53 which gives the following log :
ONFI flash detected ... ONFI param page 0 valid
NAND device: Manufacturer ID: 0x2c, Chip ID: 0x38 (Micron MT29F8G08ABABAWP), page size: 4096, OOB size: 224

Signed-off-by: Eric Bénard <eric@eukrea.com>
---
 drivers/mtd/nand/nand_base.c |  174 ++++++++++++++++++++++++++++++++++++------
 include/linux/mtd/mtd-abi.h  |    7 +-
 include/linux/mtd/nand.h     |   74 ++++++++++++++++++-
 3 files changed, 226 insertions(+), 29 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index c4eca0d..a5bf757 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1027,6 +1027,108 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
 }
 
 /*
+ * sanitize ONFI strings so we can safely print them
+ */
+static void sanitize_string(char *s, size_t len)
+{
+	ssize_t i;
+
+	/* null terminate */
+	s[len - 1] = 0;
+
+	/* remove non printable chars */
+	for (i = 0; i < len - 1; i++) {
+		if (s[i] < ' ' || s[i] > 127)
+			s[i] = '?';
+	}
+
+	/* remove trailing spaces */
+	strim(s);
+}
+
+static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
+{
+	int i;
+	while (len--) {
+		crc ^= *p++ << 8;
+		for (i = 0; i < 8; i++)
+			crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
+	}
+
+	return crc;
+}
+
+/*
+ * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise
+ */
+static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
+					int *busw)
+{
+	struct nand_onfi_params *p = &chip->onfi_params;
+	int i;
+	int val;
+
+	/* try ONFI for unknow chip or LP */
+	chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
+	if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
+		chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
+		return 0;
+
+	printk(KERN_INFO "ONFI flash detected ... ");
+	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
+	for (i = 0; i < 3; i++) {
+		chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
+		if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
+				le16_to_cpu(p->crc)) {
+			printk(KERN_INFO "ONFI param page %d valid\n", i);
+			break;
+		}
+	}
+
+	if (i == 3) {
+		printk(KERN_INFO "no valid ONFI param page found\n");
+		return 0;
+	}
+
+	/* check version */
+	val = le16_to_cpu(p->revision);
+	if (val & (1 << 5))
+		chip->onfi_version = 23;
+	else if (val & (1 << 4))
+		chip->onfi_version = 22;
+	else if (val & (1 << 3))
+		chip->onfi_version = 21;
+	else if (val & (1 << 2))
+		chip->onfi_version = 20;
+	else if (val & (1 << 1))
+		chip->onfi_version = 10;
+	else
+		chip->onfi_version = 0;
+
+	if (!chip->onfi_version) {
+		printk(KERN_INFO "unsupported ONFI version: %d\n", val);
+		return 0;
+	}
+
+	sanitize_string(p->manufacturer, sizeof(p->manufacturer));
+	sanitize_string(p->model, sizeof(p->model));
+	if (!mtd->name)
+		mtd->name = p->model;
+	mtd->writesize = le32_to_cpu(p->byte_per_page);
+	mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
+	mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
+	chip->chipsize = (uint64_t)le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
+	*busw = 0;
+	if (le16_to_cpu(p->features) & 1)
+		*busw = NAND_BUSWIDTH_16;
+
+	chip->options &= ~NAND_CHIPOPTIONS_MSK;
+	chip->options |= NAND_NO_READRDY & NAND_CHIPOPTIONS_MSK;
+
+	return 1;
+}
+
+/*
  * 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,
@@ -1036,6 +1138,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	struct nand_flash_dev *type = NULL;
 	int i, dev_id, maf_idx;
 	int tmp_id, tmp_manf;
+	int ret;
 
 	/* Select the device */
 	chip->select_chip(mtd, 0);
@@ -1081,9 +1184,16 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 		}
 	}
 
+	chip->onfi_version = 0;
 	if (!type) {
-		printk(KERN_ERR "NAND type unknown: %02x,%02x\n", *maf_id, dev_id);
-		return ERR_PTR(-ENODEV);
+		/* Check is chip is ONFI compliant */
+		ret = nand_flash_detect_onfi(mtd, chip, &busw);
+		if (ret)
+			goto ident_done;
+		else {
+			printk(KERN_ERR "NAND type unknown: %02x,%02x\n", *maf_id, dev_id);
+			return ERR_PTR(-ENODEV);
+		}
 	}
 
 	if (!mtd->name)
@@ -1126,17 +1236,39 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 			break;
 	}
 
+	/* Get chip options, preserve non chip based options */
+	chip->options &= ~NAND_CHIPOPTIONS_MSK;
+	chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
+
+	/* Check if chip is a not a samsung device. Do not clear the
+	 * options for chips which are not having an extended id.
+	 */
+	if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
+		chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
+
+ident_done:
+	/*
+	 * Set chip as a default. Board drivers can override it, if necessary
+	 */
+	chip->options |= NAND_NO_AUTOINCR;
+
+	/* Try to identify manufacturer */
+	for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) {
+		if (nand_manuf_ids[maf_idx].id == *maf_id)
+			break;
+	}
+
 	/*
 	 * Check, if buswidth is correct. Hardware drivers should set
 	 * chip correct !
 	 */
 	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);
+			" 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
+			dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
 		printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
-		       (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
-		       busw ? 16 : 8);
+			(chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
+			busw ? 16 : 8);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -1147,27 +1279,17 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 
 	chip->bbt_erase_shift = chip->phys_erase_shift =
 		ffs(mtd->erasesize) - 1;
-	chip->chip_shift = ffs(chip->chipsize) - 1;
+	if (chip->chipsize & 0xffffffff)
+		chip->chip_shift = ffs((unsigned)chip->chipsize) - 1;
+	else {
+		chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32));
+		chip->chip_shift += 32 - 1;
+	}
 
 	/* Set the bad block position */
 	chip->badblockpos = mtd->writesize > 512 ?
 		NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
 
-	/* Get chip options, preserve non chip based options */
-	chip->options &= ~NAND_CHIPOPTIONS_MSK;
-	chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
-
-	/*
-	 * Set chip as a default. Board drivers can override it, if necessary
-	 */
-	chip->options |= NAND_NO_AUTOINCR;
-
-	/* Check if chip is a not a samsung device. Do not clear the
-	 * options for chips which are not having an extended id.
-	 */
-	if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
-		chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
-
 #ifdef CONFIG_MTD_WRITE
 	/* Check for AND chips with 4 page planes */
 	if (chip->options & NAND_4PAGE_ARRAY)
@@ -1179,9 +1301,11 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
 		chip->cmdfunc = nand_command_lp;
 
-	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, type->name);
+	printk("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s),"
+		" page size: %d, OOB size: %d\n",
+		*maf_id, dev_id, nand_manuf_ids[maf_idx].name,
+		chip->onfi_version ? chip->onfi_params.model : type->name,
+		mtd->writesize, mtd->oobsize);
 
 	return type;
 }
diff --git a/include/linux/mtd/mtd-abi.h b/include/linux/mtd/mtd-abi.h
index 33e1fe2..90dee7e 100644
--- a/include/linux/mtd/mtd-abi.h
+++ b/include/linux/mtd/mtd-abi.h
@@ -115,16 +115,17 @@ struct nand_oobfree {
 	uint32_t length;
 };
 
-#define MTD_MAX_OOBFREE_ENTRIES	8
+#define MTD_MAX_OOBFREE_ENTRIES_LARGE  32
+#define MTD_MAX_ECCPOS_ENTRIES_LARGE   128 /* FIXME : understand why 448 is not working */
 /*
  * ECC layout control structure. Exported to userspace for
  * diagnosis and to allow creation of raw images
  */
 struct nand_ecclayout {
 	uint32_t eccbytes;
-	uint32_t eccpos[64];
+	uint32_t eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE];
 	uint32_t oobavail;
-	struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
+	struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE];
 };
 
 /**
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 2a1c4ff..4a492b5 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -80,6 +80,7 @@ extern void nand_wait_ready(struct mtd_info *mtd);
 #define NAND_CMD_RNDIN		0x85
 #define NAND_CMD_READID		0x90
 #define NAND_CMD_ERASE2		0xd0
+#define NAND_CMD_PARAM		0xec
 #define NAND_CMD_RESET		0xff
 
 /* Extended commands for large page devices */
@@ -217,6 +218,70 @@ typedef enum {
 /* Keep gcc happy */
 struct nand_chip;
 
+struct nand_onfi_params {
+	/* rev info and features block */
+	/* 'O' 'N' 'F' 'I'  */
+	u8 sig[4];
+	__le16 revision;
+	__le16 features;
+	__le16 opt_cmd;
+	u8 reserved[22];
+
+	/* manufacturer information block */
+	char manufacturer[12];
+	char model[20];
+	u8 jedec_id;
+	__le16 date_code;
+	u8 reserved2[13];
+
+	/* memory organization block */
+	__le32 byte_per_page;
+	__le16 spare_bytes_per_page;
+	__le32 data_bytes_per_ppage;
+	__le16 spare_bytes_per_ppage;
+	__le32 pages_per_block;
+	__le32 blocks_per_lun;
+	u8 lun_count;
+	u8 addr_cycles;
+	u8 bits_per_cell;
+	__le16 bb_per_lun;
+	__le16 block_endurance;
+	u8 guaranteed_good_blocks;
+	__le16 guaranteed_block_endurance;
+	u8 programs_per_page;
+	u8 ppage_attr;
+	u8 ecc_bits;
+	u8 interleaved_bits;
+	u8 interleaved_ops;
+	u8 reserved3[13];
+
+	/* electrical parameter block */
+	u8 io_pin_capacitance_max;
+	__le16 async_timing_mode;
+	__le16 program_cache_timing_mode;
+	__le16 t_prog;
+	__le16 t_bers;
+	__le16 t_r;
+	__le16 t_ccs;
+	__le16 src_sync_timing_mode;
+	__le16 src_ssync_features;
+	__le16 clk_pin_capacitance_typ;
+	__le16 io_pin_capacitance_typ;
+	__le16 input_pin_capacitance_typ;
+	u8 input_pin_capacitance_max;
+	u8 driver_strenght_support;
+	__le16 t_int_r;
+	__le16 t_ald;
+	u8 reserved4[7];
+
+	/* vendor */
+	u8 reserved5[90];
+
+	__le16 crc;
+} __attribute__((packed));
+
+#define ONFI_CRC_BASE	0x4F4E
+
 /**
  * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
  * @lock:               protection lock
@@ -347,6 +412,10 @@ struct nand_buffers {
  * @pagemask:		[INTERN] page number mask = number of (pages / chip) - 1
  * @pagebuf:		[INTERN] holds the pagenumber which is currently in data_buf
  * @subpagesize:	[INTERN] holds the subpagesize
+ * @onfi_version:	[INTERN] holds the chip ONFI version (BCD encoded),
+ *			non 0 if ONFI supported.
+ * @onfi_params:	[INTERN] holds the ONFI page parameter when ONFI is
+ *			supported, 0 otherwise.
  * @ecclayout:		[REPLACEABLE] the default ecc placement scheme
  * @bbt:		[INTERN] bad block table pointer
  * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash lookup
@@ -391,13 +460,16 @@ struct nand_chip {
 	int		bbt_erase_shift;
 	int		chip_shift;
 	int		numchips;
-	unsigned long	chipsize;
+	uint64_t	chipsize;
 	int		pagemask;
 	int		pagebuf;
 	int		subpagesize;
 	uint8_t		cellinfo;
 	int		badblockpos;
 
+	int onfi_version;
+	struct nand_onfi_params onfi_params;
+
 	nand_state_t	state;
 
 	uint8_t		*oob_poi;
-- 
1.7.7.6


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

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

* [PATCH 3/3] nand_imx: update to support onfi & 4k flashs
  2012-07-05 10:22 [PATCH 1/3] string: add strim for ONFI code Eric Bénard
  2012-07-05 10:22 ` [PATCH 2/3] nand_base: add ONFI flash detection Eric Bénard
@ 2012-07-05 10:22 ` Eric Bénard
  2012-07-09  7:30 ` [PATCH 1/3] string: add strim for ONFI code Sascha Hauer
  2 siblings, 0 replies; 6+ messages in thread
From: Eric Bénard @ 2012-07-05 10:22 UTC (permalink / raw)
  To: barebox

- add CMD_PARAM and read_param to get the ONFI structure
- fix OOB size for flash with 224 OOB on i.MX51/3
- add the same ecc layout as the one in the kernel for
  4k page flashs

Tested on an i.MX53.

Signed-off-by: Eric Bénard <eric@eukrea.com>
---
 drivers/mtd/nand/nand_imx.c |   98 ++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 93 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index e75ffbc..83b49e3 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -106,6 +106,7 @@ struct imx_nand_host {
 	void			(*send_addr)(struct imx_nand_host *, uint16_t);
 	void			(*send_page)(struct imx_nand_host *, unsigned int);
 	void			(*send_read_id)(struct imx_nand_host *);
+	void			(*send_read_param)(struct imx_nand_host *);
 	uint16_t		(*get_dev_status)(struct imx_nand_host *);
 	int			(*check_int)(struct imx_nand_host *);
 };
@@ -154,6 +155,31 @@ static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
 	}
 };
 
+/* OOB description for 4096 byte pages with 128 byte OOB */
+static struct nand_ecclayout nandv2_hw_eccoob_4k = {
+	.eccbytes = 8 * 9,
+	.eccpos = {
+		7,  8,  9, 10, 11, 12, 13, 14, 15,
+		23, 24, 25, 26, 27, 28, 29, 30, 31,
+		39, 40, 41, 42, 43, 44, 45, 46, 47,
+		55, 56, 57, 58, 59, 60, 61, 62, 63,
+		71, 72, 73, 74, 75, 76, 77, 78, 79,
+		87, 88, 89, 90, 91, 92, 93, 94, 95,
+		103, 104, 105, 106, 107, 108, 109, 110, 111,
+		119, 120, 121, 122, 123, 124, 125, 126, 127,
+	},
+	.oobfree = {
+		{.offset = 2, .length = 4},
+		{.offset = 16, .length = 7},
+		{.offset = 32, .length = 7},
+		{.offset = 48, .length = 7},
+		{.offset = 64, .length = 7},
+		{.offset = 80, .length = 7},
+		{.offset = 96, .length = 7},
+		{.offset = 112, .length = 7},
+	}
+};
+
 static void memcpy32(void *trg, const void *src, int size)
 {
 	int i;
@@ -335,6 +361,16 @@ static void send_read_id_v3(struct imx_nand_host *host)
 	memcpy(host->data_buf, host->main_area0, 16);
 }
 
+static void send_read_param_v3(struct imx_nand_host *host)
+{
+	/* Read ID into main buffer */
+	writel(NFC_OUTPUT, NFC_V3_LAUNCH);
+
+	wait_op_done(host);
+
+	memcpy(host->data_buf, host->main_area0, 1024);
+}
+
 static void send_read_id_v1_v2(struct imx_nand_host *host)
 {
 	struct nand_chip *this = &host->nand;
@@ -363,6 +399,34 @@ static void send_read_id_v1_v2(struct imx_nand_host *host)
 	memcpy32(host->data_buf, host->main_area0, 16);
 }
 
+/* FIXME : to check on real HW */
+static void send_read_param_v1_v2(struct imx_nand_host *host)
+{
+	struct nand_chip *this = &host->nand;
+
+	/* NANDFC buffer 0 is used for device ID output */
+	writew(0x0, host->regs + NFC_V1_V2_BUF_ADDR);
+
+	writew(NFC_OUTPUT, host->regs + NFC_V1_V2_CONFIG2);
+
+	/* Wait for operation to complete */
+	wait_op_done(host);
+
+	if (this->options & NAND_BUSWIDTH_16) {
+		volatile u16 *mainbuf = host->main_area0;
+
+		/*
+		 * Pack the every-other-byte result for 16-bit ID reads
+		 * into every-byte as the generic code expects and various
+		 * chips implement.
+		 */
+
+		mainbuf[0] = (mainbuf[0] & 0xff) | ((mainbuf[1] & 0xff) << 8);
+		mainbuf[1] = (mainbuf[2] & 0xff) | ((mainbuf[3] & 0xff) << 8);
+		mainbuf[2] = (mainbuf[4] & 0xff) | ((mainbuf[5] & 0xff) << 8);
+	}
+	memcpy32(host->data_buf, host->main_area0, 1024);
+}
 /*
  * This function requests the NANDFC to perform a read of the
  * NAND device status and returns the current status.
@@ -579,6 +643,10 @@ static void imx_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len)
 
 	n = min(n, len);
 
+	/* handle the read param special case */
+	if ((mtd->writesize == 0) && (len != 0))
+		n = len;
+
 	memcpy(buf, host->data_buf + col, n);
 
 	host->buf_start += n;
@@ -677,8 +745,11 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
 		 * layers perform a read/write buf operation,
 		 * we will used the saved column adress to index into
 		 * the full page.
+		 *
+		 * The colum address must be sent to the flash in
+		 * order to get the ONFI header (0x20)
 		 */
-		host->send_addr(host, 0);
+		host->send_addr(host, column);
 		if (host->pagesize_2k)
 			/* another col addr cycle for 2k page */
 			host->send_addr(host, 0);
@@ -790,9 +861,11 @@ static void preset_v3(struct mtd_info *mtd)
 
 	writel(0, NFC_V3_IPC);
 
+	/* if the flash has a 224 oob, the NFC must be configured to 218 */
 	config2 = NFC_V3_CONFIG2_ONE_CYCLE |
 		NFC_V3_CONFIG2_2CMD_PHASES |
-		NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
+		NFC_V3_CONFIG2_SPAS(((mtd->oobsize > 218) ?
+			218 : mtd->oobsize) >> 1) |
 		NFC_V3_CONFIG2_ST_CMD(0x70) |
 		NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
 
@@ -944,8 +1017,15 @@ static void imx_nand_command(struct mtd_info *mtd, unsigned command,
 	case NAND_CMD_READID:
 		host->send_cmd(host, command);
 		mxc_do_addr_cycle(mtd, column, page_addr);
-		host->buf_start = 0;
 		host->send_read_id(host);
+		host->buf_start = 0;
+		break;
+
+	case NAND_CMD_PARAM:
+		host->send_cmd(host, command);
+		mxc_do_addr_cycle(mtd, column, page_addr);
+		host->send_read_param(host);
+		host->buf_start = 0;
 		break;
 
 	case NAND_CMD_ERASE1:
@@ -1024,7 +1104,7 @@ static int __init imxnd_probe(struct device_d *dev)
 	struct mtd_info *mtd;
 	struct imx_nand_platform_data *pdata = dev->platform_data;
 	struct imx_nand_host *host;
-	struct nand_ecclayout *oob_smallpage, *oob_largepage;
+	struct nand_ecclayout *oob_smallpage, *oob_largepage, *oob_4kpage;
 	int err = 0;
 
 #ifdef CONFIG_ARCH_IMX27
@@ -1047,6 +1127,7 @@ static int __init imxnd_probe(struct device_d *dev)
 		host->send_addr = send_addr_v1_v2;
 		host->send_page = send_page_v1_v2;
 		host->send_read_id = send_read_id_v1_v2;
+		host->send_read_param = send_read_param_v1_v2; /* FIXME : to check */
 		host->get_dev_status = get_dev_status_v1_v2;
 		host->check_int = check_int_v1_v2;
 	}
@@ -1059,6 +1140,7 @@ static int __init imxnd_probe(struct device_d *dev)
 		host->spare_len = 64;
 		oob_smallpage = &nandv2_hw_eccoob_smallpage;
 		oob_largepage = &nandv2_hw_eccoob_largepage;
+		oob_4kpage = &nandv2_hw_eccoob_4k; /* FIXME : to check */
 	} else if (nfc_is_v1()) {
 		host->base = dev_request_mem_region(dev, 0);
 		host->main_area0 = host->base;
@@ -1067,6 +1149,7 @@ static int __init imxnd_probe(struct device_d *dev)
 		host->spare_len = 16;
 		oob_smallpage = &nandv1_hw_eccoob_smallpage;
 		oob_largepage = &nandv1_hw_eccoob_largepage;
+		oob_4kpage = &nandv1_hw_eccoob_smallpage; /* FIXME : to check  */
 	} else if (nfc_is_v3_2()) {
 		host->regs_ip = dev_request_mem_region(dev, 0);
 		host->base = dev_request_mem_region(dev, 1);
@@ -1086,10 +1169,12 @@ static int __init imxnd_probe(struct device_d *dev)
 		host->send_addr = send_addr_v3;
 		host->send_page = send_page_v3;
 		host->send_read_id = send_read_id_v3;
+		host->send_read_param = send_read_param_v3;
 		host->get_dev_status = get_dev_status_v3;
 		host->check_int = check_int_v3;
 		oob_smallpage = &nandv2_hw_eccoob_smallpage;
 		oob_largepage = &nandv2_hw_eccoob_largepage;
+		oob_4kpage = &nandv2_hw_eccoob_4k;
 	}
 
 	host->dev = dev;
@@ -1161,7 +1246,10 @@ static int __init imxnd_probe(struct device_d *dev)
 	imx_nand_set_layout(mtd->writesize, pdata->width == 2 ? 16 : 8);
 
 	if (mtd->writesize >= 2048) {
-		this->ecc.layout = oob_largepage;
+		if (mtd->writesize == 2048)
+			this->ecc.layout = oob_largepage;
+		else
+			this->ecc.layout = oob_4kpage;
 		host->pagesize_2k = 1;
 		if (nfc_is_v21())
 			writew(NFC_V2_SPAS_SPARESIZE(64), host->regs + NFC_V2_SPAS);
-- 
1.7.7.6


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

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

* Re: [PATCH 2/3] nand_base: add ONFI flash detection
  2012-07-05 10:22 ` [PATCH 2/3] nand_base: add ONFI flash detection Eric Bénard
@ 2012-07-05 19:02   ` Sascha Hauer
  2012-07-05 20:32     ` Eric Bénard
  0 siblings, 1 reply; 6+ messages in thread
From: Sascha Hauer @ 2012-07-05 19:02 UTC (permalink / raw)
  To: Eric Bénard; +Cc: barebox

On Thu, Jul 05, 2012 at 12:22:46PM +0200, Eric Bénard wrote:
> the code is taken from linux & u-boot implementations
> Validated on an i.MX53 which gives the following log :
> ONFI flash detected ... ONFI param page 0 valid
> NAND device: Manufacturer ID: 0x2c, Chip ID: 0x38 (Micron MT29F8G08ABABAWP), page size: 4096, OOB size: 224
> 
> Signed-off-by: Eric Bénard <eric@eukrea.com>
> ---
>  drivers/mtd/nand/nand_base.c |  174 ++++++++++++++++++++++++++++++++++++------
>  include/linux/mtd/mtd-abi.h  |    7 +-
>  include/linux/mtd/nand.h     |   74 ++++++++++++++++++-
>  3 files changed, 226 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
>  #ifdef CONFIG_MTD_WRITE
>  	/* Check for AND chips with 4 page planes */
>  	if (chip->options & NAND_4PAGE_ARRAY)
> @@ -1179,9 +1301,11 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
>  	if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
>  		chip->cmdfunc = nand_command_lp;
>  
> -	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, type->name);
> +	printk("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s),"
> +		" page size: %d, OOB size: %d\n",
> +		*maf_id, dev_id, nand_manuf_ids[maf_idx].name,
> +		chip->onfi_version ? chip->onfi_params.model : type->name,
> +		mtd->writesize, mtd->oobsize);

Do we need to output writesize and oobsize here? 'devinfo nand0' will
give the same information.

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 |

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

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

* Re: [PATCH 2/3] nand_base: add ONFI flash detection
  2012-07-05 19:02   ` Sascha Hauer
@ 2012-07-05 20:32     ` Eric Bénard
  0 siblings, 0 replies; 6+ messages in thread
From: Eric Bénard @ 2012-07-05 20:32 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Hi Sascha,

Le Thu, 5 Jul 2012 21:02:40 +0200,
Sascha Hauer <s.hauer@pengutronix.de> a écrit :
> > -	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, type->name);
> > +	printk("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s),"
> > +		" page size: %d, OOB size: %d\n",
> > +		*maf_id, dev_id, nand_manuf_ids[maf_idx].name,
> > +		chip->onfi_version ? chip->onfi_params.model : type->name,
> > +		mtd->writesize, mtd->oobsize);
> 
> Do we need to output writesize and oobsize here? 'devinfo nand0' will
> give the same information.
> 
that's the way it's done in the kernel so I imported the log update.

Eric

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

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

* Re: [PATCH 1/3] string: add strim for ONFI code
  2012-07-05 10:22 [PATCH 1/3] string: add strim for ONFI code Eric Bénard
  2012-07-05 10:22 ` [PATCH 2/3] nand_base: add ONFI flash detection Eric Bénard
  2012-07-05 10:22 ` [PATCH 3/3] nand_imx: update to support onfi & 4k flashs Eric Bénard
@ 2012-07-09  7:30 ` Sascha Hauer
  2 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2012-07-09  7:30 UTC (permalink / raw)
  To: Eric Bénard; +Cc: barebox

On Thu, Jul 05, 2012 at 12:22:45PM +0200, Eric Bénard wrote:
> Signed-off-by: Eric Bénard <eric@eukrea.com>
> ---
>  include/linux/string.h |    3 +++
>  lib/string.c           |   39 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 42 insertions(+), 0 deletions(-)

Applied all three

Sascha

> 
> diff --git a/include/linux/string.h b/include/linux/string.h
> index 62d743e..afd0aa6 100644
> --- a/include/linux/string.h
> +++ b/include/linux/string.h
> @@ -93,6 +93,9 @@ extern int memcmp(const void *,const void *,__kernel_size_t);
>  #ifndef __HAVE_ARCH_MEMCHR
>  extern void * memchr(const void *,int,__kernel_size_t);
>  #endif
> +extern char * skip_spaces(const char *);
> +
> +extern char *strim(char *);
>  
>  #ifdef __cplusplus
>  }
> diff --git a/lib/string.c b/lib/string.c
> index 2865088..db4f2ae 100644
> --- a/lib/string.c
> +++ b/lib/string.c
> @@ -567,3 +567,42 @@ void *memchr(const void *s, int c, size_t n)
>  #endif
>  EXPORT_SYMBOL(memchr);
>  
> +/**
> + * skip_spaces - Removes leading whitespace from @str.
> + * @str: The string to be stripped.
> + *
> + * Returns a pointer to the first non-whitespace character in @str.
> + */
> +char *skip_spaces(const char *str)
> +{
> +	while (isspace(*str))
> +		++str;
> +	return (char *)str;
> +}
> +
> +/**
> + * strim - Removes leading and trailing whitespace from @s.
> + * @s: The string to be stripped.
> + *
> + * Note that the first trailing whitespace is replaced with a %NUL-terminator
> + * in the given string @s. Returns a pointer to the first non-whitespace
> + * character in @s.
> + */
> +char *strim(char *s)
> +{
> +	size_t size;
> +	char *end;
> +
> +	s = skip_spaces(s);
> +	size = strlen(s);
> +	if (!size)
> +		return s;
> +
> +	end = s + size - 1;
> +	while (end >= s && isspace(*end))
> +		end--;
> +	*(end + 1) = '\0';
> +
> +	return s;
> +}
> +EXPORT_SYMBOL(strim);
> -- 
> 1.7.7.6
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox

-- 
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 |

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

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

end of thread, other threads:[~2012-07-09  7:30 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-05 10:22 [PATCH 1/3] string: add strim for ONFI code Eric Bénard
2012-07-05 10:22 ` [PATCH 2/3] nand_base: add ONFI flash detection Eric Bénard
2012-07-05 19:02   ` Sascha Hauer
2012-07-05 20:32     ` Eric Bénard
2012-07-05 10:22 ` [PATCH 3/3] nand_imx: update to support onfi & 4k flashs Eric Bénard
2012-07-09  7:30 ` [PATCH 1/3] string: add strim for ONFI code Sascha Hauer

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