OneNAND: erase/read/write jffs2 commands
Subsystems (3)
RFC PATCH 1/1 OneNAND: erase/read/write jffs2 commands
Implement OneNAND related JFFS2 commands (based on NAND source code):
- onenand erase clean
- onenand read.jffs2
- onenand write.jffs2
It contains also "Fill in remaining MTD driver data for OneNAND" sent last week.
This patch must be applied after "JFFS2 command support on OneNAND" patch sent also previously.
I can submit a cumulative patch if needed.
---
common/cmd_onenand.c +59 -10
@@ -26,6 +26,11 @@int do_onenand (cmd_tbl_t * cmdtp,int flag,int argc,char *argv[]) {int ret =0 ; +#ifdef CFG_ONENAND_QUIET +int quiet =CFG_ONENAND_QUIET ; +#else +int quiet =0 ; +#endif switch (argc) {case 0 :
@@ -38,7 +43,7 @@onenand_init ();return 0 ; } -onenand_print_device_info (onenand_chip.device_id,1 ); +printf ("%s\n" , onenand_mtd.name);return 0 ;default :
@@ -51,7 +56,27 @@ulong block;char *endtail; -if (strncmp (argv[2 ],"block" ,5 ) ==0 ) { +if (strncmp (argv[2 ],"clean" ,5 ) ==0 ) { +ulong ofs =simple_strtoul (argv[3 ],NULL ,16 ); +size_t len =0 ; + +if (argc ==4 ) { + len = onenand_mtd.size - ofs; + }else { + len =simple_strtoul (argv[4 ],NULL ,16 ); + } + +onenand_erase_options_t opts; + +memset (&opts,0 ,sizeof (opts)); + opts.offset = ofs; + opts.length = len; + opts.jffs2 =1 ; + opts.quiet = quiet; +onenand_erase_opts (&onenand_mtd, &opts); + +return 0 ; + }else if (strncmp (argv[2 ],"block" ,5 ) ==0 ) { start =simple_strtoul (argv[3 ],NULL ,10 ); endtail =strchr (argv[3 ],'-' ); end =simple_strtoul (endtail +1 ,NULL ,10 );
@@ -88,14 +113,25 @@ulong ofs =simple_strtoul (argv[3 ],NULL ,16 );size_t len =simple_strtoul (argv[4 ],NULL ,16 );size_t retlen =0 ; -int oob =strncmp (argv[1 ],"read.oob" ,8 ) ?0 :1 ; -if (oob) +char *s =strchr (argv[1 ],'.' ); + +if (s !=NULL && !strncmp (s,".jffs2" ,6 )) { +onenand_rw_options_t opts; + +memset (&opts,0 ,sizeof (opts)); + opts.buffer = (u_char *) addr; + opts.length = len; + opts.offset = ofs; + opts.quiet = quiet; +onenand_read_opts (&onenand_mtd, &opts); + }else if (s !=NULL && !strncmp (s,".oob" ,4 )) {onenand_read_oob (&onenand_mtd, ofs, len, &retlen, (u_char *) addr); -else + }else {onenand_read (&onenand_mtd, ofs, len, &retlen, (u_char *) addr); + }printf ("Done\n" );return 0 ;
@@ -107,8 +143,23 @@size_t len =simple_strtoul (argv[4 ],NULL ,16 );size_t retlen =0 ; -onenand_write (&onenand_mtd, ofs, len, &retlen, - (u_char *) addr); +char *s =strchr (argv[1 ],'.' ); + +if (s !=NULL && !strncmp (s,".jffs2" ,6 )) { +onenand_rw_options_t opts; + +memset (&opts,0 ,sizeof (opts)); + opts.buffer = (u_char *) addr; + opts.length = len; + opts.offset = ofs; + opts.pad =1 ; + opts.blockalign =1 ; + opts.quiet = quiet; +onenand_write_opts (&onenand_mtd, &opts); + }else { +onenand_write (&onenand_mtd, ofs, len, &retlen, + (u_char *) addr); + }printf ("Done\n" );return 0 ;
@@ -153,9 +204,9 @@ onenand,6 ,1 , do_onenand,"onenand - OneNAND sub-system\n" ,"info - show available OneNAND devices\n" -"onenand read[.oob] addr ofs len - read data at ofs with len to addr\n" -"onenand write addr ofs len - write data at ofs with len from addr\n" -"onenand erase saddr eaddr - erase block start addr to end addr\n" + "onenand read[.jffs2][.oob] addr ofs len - read data at ofs with len to
addr\n"
+ "onenand write[.jffs2] addr ofs len - write data at ofs with len from addr\n"
+ "onenand erase [clean] saddr eaddr - erase block start addr to end addr\n"
"onenand block[.oob] addr block [page] [len] - "
"read data with (block [, page]) to addr"
);
include/onenand_uboot.h +43 -1
55 lines not on this page · raw message
drivers/mtd/onenand/onenand_uboot.c +517 -0
534 lines not on this page · raw message
drivers/mtd/onenand/onenand_base.c +26 -1
@@ -19,6 +19,7 @@#include <asm/io.h> #include <asm/errno.h> +#include <malloc.h> /* It should access 16-bit instead of 8-bit */ static inline void *memcpy_16 (void *dst,const void *src,unsigned int len)
@@ -894,6 +895,23 @@ }/** +* onenand_block_checkbad - [GENERIC] Check if a block is marked bad +* @param mtd MTD device structure +* @param ofs offset from device start +* @param getchip 0, if the chip is already selected +* @param allowbbt 1, if its allowed to access the bbt area +* +* Check, if the block is bad. Either by reading the bad block table or +* calling of the scan function. +*/ +int onenand_block_checkbad (struct mtd_info *mtd,loff_t ofs,int getchip, +int allowbbt) +{ +/* Return info from the table */ +return onenand_isbad_bbt (mtd, ofs, allowbbt); +} + +/** * onenand_erase - [MTD Interface] erase block(s) * @param mtd MTD device structure * @param instr erase instruction
@@ -947,7 +965,14 @@while (len) { -/* TODO Check badblock */ +/* Check if we have a bad block, we do not erase bad blocks */ +if (onenand_block_checkbad (mtd, addr,0 ,0 )) { +printk (KERN_WARNING "onenand_erase: " +"attempt to erase a bad block at addr 0x%08x\n" , + (unsigned int ) addr); + instr->state =MTD_ERASE_FAILED ; + goto erase_exit; + } this->command (mtd,ONENAND_CMD_ERASE , addr, block_size);
@@ -1006,30 +1031,39 @@* onenand_block_isbad - [MTD Interface] Check whether the block at the given
offset is bad
* @param mtd MTD device structure
* @param ofs offset relative to mtd start
+ *
+ * Check whether the block is bad
*/
int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs) {
- /*
- * TODO
- * 1. Bad block table (BBT)
- * -> using NAND BBT to support JFFS2
- * 2. Bad block management (BBM)
- * -> bad block replace scheme
- *
- * Currently we do nothing
- */
- return 0;
+ /* Check for invalid offset */
+ if (ofs > mtd->size)
+ return -EINVAL;
+
+ return onenand_block_checkbad(mtd, ofs, 1, 0);
}
/**
* onenand_block_markbad - [MTD Interface] Mark the block at the given offset
as bad
* @param mtd MTD device structure
* @param ofs offset relative to mtd start
+ *
+ * Mark the block as bad
*/
int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
- /* see above */
- return 0;
+ struct onenand_chip *this = mtd->priv;
+ int ret;
+
+ ret = onenand_block_isbad(mtd, ofs);
+ if (ret) {
+ /* If it was bad already, return success and do nothing */
+ if (ret > 0)
+ return 0;
+ return ret;
+ }
+
+ return this->block_markbad(mtd, ofs);
}
/**
@@ -1112,21 +1146,21 @@
*
* Print device ID
*/
-void onenand_print_device_info(int device, int verbose) +char * onenand_print_device_info(int device)
{
int vcc, demuxed, ddp, density;
-
- if (!verbose)
- return;
+ char *dev_info = malloc(80);
vcc = device & ONENAND_DEVICE_VCC_MASK;
demuxed = device & ONENAND_DEVICE_IS_DEMUX;
ddp = device & ONENAND_DEVICE_IS_DDP;
density = device >> ONENAND_DEVICE_DENSITY_SHIFT;
- printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n",
+ sprintf(dev_info, "%sOneNAND%s %dMB %sV 16-bit (0x%02x)",
demuxed ? "" : "Muxed ",
ddp ? "(DDP)" : "",
(16 << density), vcc ? "2.65/3.3" : "1.8", device);
+
+ return dev_info;
}
static const struct onenand_manufacturers onenand_manuf_ids[] = {
@@ -1205,7 +1239,7 @@
}
/* Flash device information */
- onenand_print_device_info(dev_id, 0);
+ mtd->name = onenand_print_device_info(dev_id);
this->device_id = dev_id;
density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
@@ -1241,6 +1275,20 @@
this->options |= ONENAND_CONT_LOCK;
}
+ /* Fill in remaining MTD driver data */
+ mtd->type = MTD_NANDFLASH;
+ mtd->flags = MTD_CAP_NANDFLASH;
+ mtd->erase = onenand_erase;
+ mtd->read = onenand_read;
+ mtd->write = onenand_write;
+ mtd->read_ecc = onenand_read_ecc;
+ mtd->write_ecc = onenand_write_ecc;
+ mtd->read_oob = onenand_read_oob;
+ mtd->write_oob = onenand_write_oob;
+ mtd->sync = onenand_sync;
+ mtd->block_isbad = onenand_block_isbad;
+ mtd->block_markbad = onenand_block_markbad;
+
return 0;
}
include/linux/mtd/onenand.h +1 -0
@@ -103,6 +103,7 @@unsigned short (*read_word) (void __iomem * addr);void (*write_word) (unsigned short value,void __iomem * addr);void (*mmcontrol) (struct mtd_info * mtd,int sync_read); +int (*block_markbad) (struct mtd_info *mtd,loff_t ofs);spinlock_t chip_lock;wait_queue_head_t wq;
drivers/mtd/onenand/onenand_bbt.c +1 -1
@@ -146,7 +146,7 @@* @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) +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;
RFC PATCH 1/1 OneNAND: erase/read/write jffs2 commands
Dear Fathi BOUDRA,
Quoted 4 lines · In message <[email protected]> you wrote:
Implement OneNAND related JFFS2 commands (based on NAND source code):
- onenand erase clean
- onenand read.jffs2
- onenand write.jffs2
...
Quoted 9 lines
common/cmd_onenand.c +1
-3@@ -153,9 +204,9 @@ onenand,6 ,1 , do_onenand,"onenand - OneNAND sub-system\n" ,"info - show available OneNAND devices\n" -"onenand read[.oob] addr ofs len - read data at ofs with len to addr\n" -"onenand write addr ofs len - write data at ofs with len from addr\n" -"onenand erase saddr eaddr - erase block start addr to end addr\n" + "onenand read[.jffs2][.oob] addr ofs len - read data at ofs with len toaddr\n"
^^^^^^^^^^^^^^
Line wrapped.
Please fix your mailer setup and resubmit.
Best regards,
Wolfgang Denk
Signature · 4 lines
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 Life. Don't talk to me about life. - Marvin the Paranoid Android