* [U-Boot-Users] [PATCH 4/5] OneNAND support
@ 2007-09-07 1:01 Kyungmin Park
2007-09-08 23:05 ` Wolfgang Denk
0 siblings, 1 reply; 6+ messages in thread
From: Kyungmin Park @ 2007-09-07 1:01 UTC (permalink / raw)
To: u-boot
[PATCH] OneNAND support
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
diff --git a/drivers/onenand/onenand_bbt.c b/drivers/onenand/onenand_bbt.c
new file mode 100644
index 0000000..6a0eb57
--- /dev/null
+++ b/drivers/onenand/onenand_bbt.c
@@ -0,0 +1,260 @@
+/*
+ * linux/drivers/mtd/onenand/onenand_bbt.c
+ *
+ * Bad Block Table support for the OneNAND driver
+ *
+ * Copyright(c) 2005-2007 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * TODO:
+ * Split BBT core and chip specific BBT.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_CMD_ONENAND
+
+#include <linux/mtd/onenand.h>
+#include <malloc.h>
+
+/**
+ * check_short_pattern - [GENERIC] check if a pattern is in the buffer
+ * @param buf the buffer to search
+ * @param len the length of buffer to search
+ * @param paglen the pagelength
+ * @param td search pattern descriptor
+ *
+ * Check for a pattern at the given place. Used to search bad block
+ * tables and good / bad block identifiers. Same as check_pattern, but
+ * no optional empty check and the pattern is expected to start
+ * at offset 0.
+ */
+static int check_short_pattern(uint8_t * buf, int len, int paglen,
+ struct nand_bbt_descr *td)
+{
+ int i;
+ uint8_t *p = buf;
+
+ /* Compare the pattern */
+ for (i = 0; i < td->len; i++) {
+ if (p[i] != td->pattern[i])
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * create_bbt - [GENERIC] Create a bad block table by scanning the device
+ * @param mtd MTD device structure
+ * @param buf temporary buffer
+ * @param bd descriptor for the good/bad block search pattern
+ * @param chip create the table for a specific chip, -1 read all chips.
+ * Applies only if NAND_BBT_PERCHIP option is set
+ *
+ * Create a bad block table by scanning the device
+ * for the given good/bad block identify pattern
+ */
+static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
+ struct nand_bbt_descr *bd, int chip)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm = this->bbm;
+ int i, j, numblocks, len, scanlen;
+ int startblock;
+ loff_t from;
+ size_t readlen, ooblen;
+
+ printk(KERN_INFO "Scanning device for bad blocks\n");
+
+ len = 1;
+
+ /* We need only read few bytes from the OOB area */
+ scanlen = ooblen = 0;
+ readlen = bd->len;
+
+ /* chip == -1 case only */
+ /* Note that numblocks is 2 * (real numblocks) here;
+ * see i += 2 below as it makses shifting and masking less painful
+ */
+ numblocks = mtd->size >> (bbm->bbt_erase_shift - 1);
+ startblock = 0;
+ from = 0;
+
+ for (i = startblock; i < numblocks;) {
+ int ret;
+
+ for (j = 0; j < len; j++) {
+ size_t retlen;
+
+ /* No need to read pages fully,
+ * just read required OOB bytes */
+ ret =
+ onenand_read_oob(mtd,
+ from + j * mtd->oobblock +
+ bd->offs, readlen, &retlen,
+ &buf[0]);
+
+ if (ret)
+ return ret;
+
+ if (check_short_pattern
+ (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
+ bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
+ printk(KERN_WARNING
+ "Bad eraseblock %d@0x%08x\n", i >> 1,
+ (unsigned int)from);
+ break;
+ }
+ }
+ i += 2;
+ from += (1 << bbm->bbt_erase_shift);
+ }
+
+ return 0;
+}
+
+/**
+ * onenand_memory_bbt - [GENERIC] create a memory based bad block table
+ * @param mtd MTD device structure
+ * @param bd descriptor for the good/bad block search pattern
+ *
+ * The function creates a memory based bbt by scanning the device
+ * for manufacturer / software marked good / bad blocks
+ */
+static inline int onenand_memory_bbt(struct mtd_info *mtd,
+ struct nand_bbt_descr *bd)
+{
+ unsigned char data_buf[MAX_ONENAND_PAGESIZE];
+
+ bd->options &= ~NAND_BBT_SCANEMPTY;
+ return create_bbt(mtd, data_buf, bd, -1);
+}
+
+/**
+ * onenand_isbad_bbt - [OneNAND Interface] Check if a block is bad
+ * @param mtd MTD device structure
+ * @param offs offset in the device
+ * @param allowbbt allow access to bad block table region
+ */
+static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm = this->bbm;
+ int block;
+ uint8_t res;
+
+ /* Get block number * 2 */
+ block = (int)(offs >> (bbm->bbt_erase_shift - 1));
+ res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
+
+ DEBUG(MTD_DEBUG_LEVEL2,
+ "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
+ (unsigned int)offs, block >> 1, res);
+
+ switch ((int)res) {
+ case 0x00:
+ return 0;
+ case 0x01:
+ return 1;
+ case 0x02:
+ return allowbbt ? 0 : 1;
+ }
+
+ return 1;
+}
+
+/**
+ * onenand_scan_bbt - [OneNAND Interface] scan, find, read and maybe create bad block table(s)
+ * @param mtd MTD device structure
+ * @param bd descriptor for the good/bad block search pattern
+ *
+ * The function checks, if a bad block table(s) is/are already
+ * available. If not it scans the device for manufacturer
+ * marked good / bad blocks and writes the bad block table(s) to
+ * the selected place.
+ *
+ * The bad block table memory is allocated here. It must be freed
+ * by calling the onenand_free_bbt function.
+ *
+ */
+int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm = this->bbm;
+ int len, ret = 0;
+
+ len = mtd->size >> (this->erase_shift + 2);
+ /* Allocate memory (2bit per block) */
+ bbm->bbt = malloc(len);
+ if (!bbm->bbt) {
+ printk(KERN_ERR "onenand_scan_bbt: Out of memory\n");
+ return -ENOMEM;
+ }
+ /* Clear the memory bad block table */
+ memset(bbm->bbt, 0x00, len);
+
+ /* Set the bad block position */
+ bbm->badblockpos = ONENAND_BADBLOCK_POS;
+
+ /* Set erase shift */
+ bbm->bbt_erase_shift = this->erase_shift;
+
+ if (!bbm->isbad_bbt)
+ bbm->isbad_bbt = onenand_isbad_bbt;
+
+ /* Scan the device to build a memory based bad block table */
+ if ((ret = onenand_memory_bbt(mtd, bd))) {
+ printk(KERN_ERR
+ "onenand_scan_bbt: Can't scan flash and build the RAM-based BBT\n");
+ free(bbm->bbt);
+ bbm->bbt = NULL;
+ }
+
+ return ret;
+}
+
+/*
+ * Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks.
+ */
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr largepage_memorybased = {
+ .options = 0,
+ .offs = 0,
+ .len = 2,
+ .pattern = scan_ff_pattern,
+};
+
+/**
+ * onenand_default_bbt - [OneNAND Interface] Select a default bad block table for the device
+ * @param mtd MTD device structure
+ *
+ * This function selects the default bad block table
+ * support for the device and calls the onenand_scan_bbt function
+ */
+int onenand_default_bbt(struct mtd_info *mtd)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm;
+
+ this->bbm = malloc(sizeof(struct bbm_info));
+ if (!this->bbm)
+ return -ENOMEM;
+
+ bbm = this->bbm;
+
+ memset(bbm, 0, sizeof(struct bbm_info));
+
+ /* 1KB page has same configuration as 2KB page */
+ if (!bbm->badblock_pattern)
+ bbm->badblock_pattern = &largepage_memorybased;
+
+ return onenand_scan_bbt(mtd, bbm->badblock_pattern);
+}
+
+#endif /* CFG_CMD_ONENAND */
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [U-Boot-Users] [PATCH 4/5] OneNAND support
2007-09-07 1:01 [U-Boot-Users] [PATCH 4/5] OneNAND support Kyungmin Park
@ 2007-09-08 23:05 ` Wolfgang Denk
2007-09-10 1:19 ` Kyungmin Park
0 siblings, 1 reply; 6+ messages in thread
From: Wolfgang Denk @ 2007-09-08 23:05 UTC (permalink / raw)
To: u-boot
Hello,
in message <20070907010102.GA19979@party> you wrote:
> [PATCH] OneNAND support
>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
> diff --git a/drivers/onenand/onenand_bbt.c b/drivers/onenand/onenand_bbt.c
> new file mode 100644
> index 0000000..6a0eb57
> --- /dev/null
> +++ b/drivers/onenand/onenand_bbt.c
...
> + * check_short_pattern - [GENERIC] check if a pattern is in the buffer
> + * @param buf the buffer to search
> + * @param len the length of buffer to search
> + * @param paglen the pagelength
> + * @param td search pattern descriptor
> + *
> + * Check for a pattern at the given place. Used to search bad block
> + * tables and good / bad block identifiers. Same as check_pattern, but
> + * no optional empty check and the pattern is expected to start
> + * at offset 0.
> + */
> +static int check_short_pattern(uint8_t * buf, int len, int paglen,
> + struct nand_bbt_descr *td)
> +{
> + int i;
> + uint8_t *p = buf;
> +
> + /* Compare the pattern */
> + for (i = 0; i < td->len; i++) {
> + if (p[i] != td->pattern[i])
> + return -1;
> + }
> + return 0;
> +}
This should probably be replaced by a call to memmem() ?
> +/**
> + * onenand_memory_bbt - [GENERIC] create a memory based bad block table
> + * @param mtd MTD device structure
> + * @param bd descriptor for the good/bad block search pattern
> + *
> + * The function creates a memory based bbt by scanning the device
> + * for manufacturer / software marked good / bad blocks
> + */
> +static inline int onenand_memory_bbt(struct mtd_info *mtd,
> + struct nand_bbt_descr *bd)
> +{
> + unsigned char data_buf[MAX_ONENAND_PAGESIZE];
> +
> + bd->options &= ~NAND_BBT_SCANEMPTY;
> + return create_bbt(mtd, data_buf, bd, -1);
> +}
This scares me. What is data_buf[] being used for? You are aware that
it goes out of scope when that function returns?
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"There is no statute of limitations on stupidity."
- Randomly produced by a computer program called Markov3.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [U-Boot-Users] [PATCH 4/5] OneNAND support
2007-09-08 23:05 ` Wolfgang Denk
@ 2007-09-10 1:19 ` Kyungmin Park
2007-09-10 7:08 ` Wolfgang Denk
0 siblings, 1 reply; 6+ messages in thread
From: Kyungmin Park @ 2007-09-10 1:19 UTC (permalink / raw)
To: u-boot
> > + */
> > +static int check_short_pattern(uint8_t * buf, int len, int paglen,
> > + struct nand_bbt_descr *td)
> > +{
> > + int i;
> > + uint8_t *p = buf;
> > +
> > + /* Compare the pattern */
> > + for (i = 0; i < td->len; i++) {
> > + if (p[i] != td->pattern[i])
> > + return -1;
> > + }
> > + return 0;
> > +}
>
> This should probably be replaced by a call to memmem() ?
>
> > +/**
> > + * onenand_memory_bbt - [GENERIC] create a memory based bad block table
> > + * @param mtd MTD device structure
> > + * @param bd descriptor for the good/bad block search pattern
> > + *
> > + * The function creates a memory based bbt by scanning the device
> > + * for manufacturer / software marked good / bad blocks
> > + */
> > +static inline int onenand_memory_bbt(struct mtd_info *mtd,
> > + struct nand_bbt_descr *bd)
> > +{
> > + unsigned char data_buf[MAX_ONENAND_PAGESIZE];
> > +
> > + bd->options &= ~NAND_BBT_SCANEMPTY;
> > + return create_bbt(mtd, data_buf, bd, -1);
> > +}
>
> This scares me. What is data_buf[] being used for? You are aware that
> it goes out of scope when that function returns?
This BBT code is not yet implemented.
It's only scan the full blocks at boot time and display the bad blocks.
It's also next time work.
It will be changed at following using page_buf allocated at onenand_init code.
static inline int onenand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
{
struct onenand_chip *this = mtd->priv;
bd->options &= ~NAND_BBT_SCANEMPTY;
return create_bbt(mtd, this->page_buf, bd, -1);
}
Thank you,
Kyungmin Park
^ permalink raw reply [flat|nested] 6+ messages in thread
* [U-Boot-Users] [PATCH 4/5] OneNAND support
2007-09-10 1:19 ` Kyungmin Park
@ 2007-09-10 7:08 ` Wolfgang Denk
2007-09-10 7:28 ` Kyungmin Park
0 siblings, 1 reply; 6+ messages in thread
From: Wolfgang Denk @ 2007-09-10 7:08 UTC (permalink / raw)
To: u-boot
In message <002601c7f348$ae36a480$e1ac580a@swcenter.sec.samsung.co.kr> you wrote:
>
> > > +static int check_short_pattern(uint8_t * buf, int len, int paglen,
...
> > > + /* Compare the pattern */
> > > + for (i = 0; i < td->len; i++) {
> > > + if (p[i] != td->pattern[i])
> > > + return -1;
> > > + }
...
> > This should probably be replaced by a call to memmem() ?
...
> > > +static inline int onenand_memory_bbt(struct mtd_info *mtd,
...
> This BBT code is not yet implemented.
> It's only scan the full blocks at boot time and display the bad blocks.
>
> It's also next time work.
I see. OK.
What about using memmem() above?
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Quote from a recent meeting: "We are going to continue having these
meetings everyday until I find out why no work is getting done."
^ permalink raw reply [flat|nested] 6+ messages in thread
* [U-Boot-Users] [PATCH 4/5] OneNAND support
2007-09-10 7:08 ` Wolfgang Denk
@ 2007-09-10 7:28 ` Kyungmin Park
2007-09-10 18:44 ` Wolfgang Denk
0 siblings, 1 reply; 6+ messages in thread
From: Kyungmin Park @ 2007-09-10 7:28 UTC (permalink / raw)
To: u-boot
> -----Original Message-----
> From: wd at denx.de [mailto:wd at denx.de]
> Sent: Monday, September 10, 2007 4:09 PM
> To: kmpark at infradead.org
> Cc: u-boot-users at lists.sourceforge.net
> Subject: Re: [U-Boot-Users] [PATCH 4/5] OneNAND support
>
> In message <002601c7f348$ae36a480$e1ac580a@swcenter.sec.samsung.co.kr> you wrote:
> >
> > > > +static int check_short_pattern(uint8_t * buf, int len, int paglen,
> ...
> > > > + /* Compare the pattern */
> > > > + for (i = 0; i < td->len; i++) {
> > > > + if (p[i] != td->pattern[i])
> > > > + return -1;
> > > > + }
> ...
> > > This should probably be replaced by a call to memmem() ?
> ...
> > > > +static inline int onenand_memory_bbt(struct mtd_info *mtd,
> ...
> > This BBT code is not yet implemented.
> > It's only scan the full blocks at boot time and display the bad blocks.
> >
> > It's also next time work.
>
> I see. OK.
>
> What about using memmem() above?
>
It's also written in drivers/nand/nand_bbt.c.
Is there any reason to use it?
Maybe people are familiar with this code.
Thank you,
Kyungmin Park
--
static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
{
int i, end;
uint8_t *p = buf;
...snip...
/* Compare the pattern */
for (i = 0; i < td->len; i++) {
if (p[i] != td->pattern[i])
return -1;
}
...snip...
}
^ permalink raw reply [flat|nested] 6+ messages in thread
* [U-Boot-Users] [PATCH 4/5] OneNAND support
2007-09-10 7:28 ` Kyungmin Park
@ 2007-09-10 18:44 ` Wolfgang Denk
0 siblings, 0 replies; 6+ messages in thread
From: Wolfgang Denk @ 2007-09-10 18:44 UTC (permalink / raw)
To: u-boot
In message <002f01c7f37c$240db1c0$e1ac580a@swcenter.sec.samsung.co.kr> you wrote:
>
> > What about using memmem() above?
>
> It's also written in drivers/nand/nand_bbt.c.
> Is there any reason to use it?
> Maybe people are familiar with this code.
Maybe we should dump it there, too...
But OK, let's keep this for the next round...
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
THIS IS A 100% MATTER PRODUCT: In the Unlikely Event That This
Merchandise Should Contact Antimatter in Any Form, a Catastrophic
Explosion Will Result.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2007-09-10 18:44 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-07 1:01 [U-Boot-Users] [PATCH 4/5] OneNAND support Kyungmin Park
2007-09-08 23:05 ` Wolfgang Denk
2007-09-10 1:19 ` Kyungmin Park
2007-09-10 7:08 ` Wolfgang Denk
2007-09-10 7:28 ` Kyungmin Park
2007-09-10 18:44 ` Wolfgang Denk
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox