mirror of
https://github.com/AsahiLinux/u-boot
synced 2025-02-17 22:49:02 +00:00
Fix OneNAND read_oob/write_oob functions compatability
Also sync with kernel OneNAND codes Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Scott Wood <scottwood@freescale.com>
This commit is contained in:
parent
8d765456c1
commit
bfd7f38614
7 changed files with 785 additions and 241 deletions
|
@ -85,15 +85,25 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||||
ulong addr = simple_strtoul(argv[2], NULL, 16);
|
ulong addr = simple_strtoul(argv[2], NULL, 16);
|
||||||
ulong ofs = simple_strtoul(argv[3], NULL, 16);
|
ulong ofs = simple_strtoul(argv[3], NULL, 16);
|
||||||
size_t len = simple_strtoul(argv[4], 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;
|
int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1;
|
||||||
|
struct mtd_oob_ops ops;
|
||||||
|
|
||||||
if (oob)
|
ops.mode = MTD_OOB_PLACE;
|
||||||
onenand_read_oob(&onenand_mtd, ofs, len,
|
|
||||||
&retlen, (u_char *) addr);
|
if (oob) {
|
||||||
else
|
ops.len = 0;
|
||||||
onenand_read(&onenand_mtd, ofs, len, &retlen,
|
ops.datbuf = NULL;
|
||||||
(u_char *) addr);
|
ops.ooblen = len;
|
||||||
|
ops.oobbuf = (u_char *) addr;
|
||||||
|
} else {
|
||||||
|
ops.len = len;
|
||||||
|
ops.datbuf = (u_char *) addr;
|
||||||
|
ops.ooblen = 0;
|
||||||
|
ops.oobbuf = NULL;
|
||||||
|
}
|
||||||
|
ops.retlen = ops.oobretlen = 0;
|
||||||
|
|
||||||
|
onenand_mtd.read_oob(&onenand_mtd, ofs, &ops);
|
||||||
printf("Done\n");
|
printf("Done\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -117,9 +127,12 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||||
ulong block = simple_strtoul(argv[3], NULL, 10);
|
ulong block = simple_strtoul(argv[3], NULL, 10);
|
||||||
ulong page = simple_strtoul(argv[4], NULL, 10);
|
ulong page = simple_strtoul(argv[4], NULL, 10);
|
||||||
size_t len = simple_strtol(argv[5], NULL, 10);
|
size_t len = simple_strtol(argv[5], NULL, 10);
|
||||||
size_t retlen = 0;
|
|
||||||
ulong ofs;
|
ulong ofs;
|
||||||
int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1;
|
int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1;
|
||||||
|
struct mtd_oob_ops ops;
|
||||||
|
|
||||||
|
ops.mode = MTD_OOB_PLACE;
|
||||||
|
|
||||||
|
|
||||||
ofs = block << onenand_chip.erase_shift;
|
ofs = block << onenand_chip.erase_shift;
|
||||||
if (page)
|
if (page)
|
||||||
|
@ -127,17 +140,21 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||||
|
|
||||||
if (!len) {
|
if (!len) {
|
||||||
if (oob)
|
if (oob)
|
||||||
len = 64;
|
ops.ooblen = 64;
|
||||||
else
|
else
|
||||||
len = 512;
|
ops.len = 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oob)
|
if (oob) {
|
||||||
onenand_read_oob(&onenand_mtd, ofs, len,
|
ops.datbuf = NULL;
|
||||||
&retlen, (u_char *) addr);
|
ops.oobbuf = (u_char *) addr;
|
||||||
else
|
} else {
|
||||||
onenand_read(&onenand_mtd, ofs, len, &retlen,
|
ops.datbuf = (u_char *) addr;
|
||||||
(u_char *) addr);
|
ops.oobbuf = NULL;
|
||||||
|
}
|
||||||
|
ops.retlen = ops.oobretlen = 0;
|
||||||
|
|
||||||
|
onenand_read_oob(&onenand_mtd, ofs, &ops);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -68,6 +68,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
|
||||||
int startblock;
|
int startblock;
|
||||||
loff_t from;
|
loff_t from;
|
||||||
size_t readlen, ooblen;
|
size_t readlen, ooblen;
|
||||||
|
struct mtd_oob_ops ops;
|
||||||
|
|
||||||
printk(KERN_INFO "Scanning device for bad blocks\n");
|
printk(KERN_INFO "Scanning device for bad blocks\n");
|
||||||
|
|
||||||
|
@ -85,25 +86,26 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
|
||||||
startblock = 0;
|
startblock = 0;
|
||||||
from = 0;
|
from = 0;
|
||||||
|
|
||||||
|
ops.mode = MTD_OOB_PLACE;
|
||||||
|
ops.ooblen = readlen;
|
||||||
|
ops.oobbuf = buf;
|
||||||
|
ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
|
||||||
|
|
||||||
for (i = startblock; i < numblocks;) {
|
for (i = startblock; i < numblocks;) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
for (j = 0; j < len; j++) {
|
for (j = 0; j < len; j++) {
|
||||||
size_t retlen;
|
|
||||||
|
|
||||||
/* No need to read pages fully,
|
/* No need to read pages fully,
|
||||||
* just read required OOB bytes */
|
* just read required OOB bytes */
|
||||||
ret = onenand_read_oob(mtd,
|
ret = onenand_bbt_read_oob(mtd,
|
||||||
from + j * mtd->writesize +
|
from + j * mtd->writesize +
|
||||||
bd->offs, readlen, &retlen,
|
bd->offs, &ops);
|
||||||
&buf[0]);
|
|
||||||
|
|
||||||
if (ret && ret != -EAGAIN) {
|
/* If it is a initial bad block, just ignore it */
|
||||||
printk("ret = %d\n", ret);
|
if (ret == ONENAND_BBT_READ_FATAL_ERROR)
|
||||||
return ret;
|
return -EIO;
|
||||||
}
|
|
||||||
|
|
||||||
if (check_short_pattern
|
if (ret || check_short_pattern
|
||||||
(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
|
(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
|
||||||
bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
|
bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
|
|
|
@ -97,6 +97,13 @@ struct nand_bbt_descr {
|
||||||
*/
|
*/
|
||||||
#define ONENAND_BADBLOCK_POS 0
|
#define ONENAND_BADBLOCK_POS 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bad block scanning errors
|
||||||
|
*/
|
||||||
|
#define ONENAND_BBT_READ_ERROR 1
|
||||||
|
#define ONENAND_BBT_READ_ECC_ERROR 2
|
||||||
|
#define ONENAND_BBT_READ_FATAL_ERROR 4
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct bbt_info - [GENERIC] Bad Block Table data structure
|
* struct bbt_info - [GENERIC] Bad Block Table data structure
|
||||||
* @param bbt_erase_shift [INTERN] number of address bits in a bbt entry
|
* @param bbt_erase_shift [INTERN] number of address bits in a bbt entry
|
||||||
|
|
|
@ -75,6 +75,7 @@ struct onenand_chip {
|
||||||
unsigned int page_shift;
|
unsigned int page_shift;
|
||||||
unsigned int ppb_shift; /* Pages per block shift */
|
unsigned int ppb_shift; /* Pages per block shift */
|
||||||
unsigned int page_mask;
|
unsigned int page_mask;
|
||||||
|
unsigned int writesize;
|
||||||
|
|
||||||
unsigned int bufferram_index;
|
unsigned int bufferram_index;
|
||||||
struct onenand_bufferram bufferram[MAX_BUFFERRAM];
|
struct onenand_bufferram bufferram[MAX_BUFFERRAM];
|
||||||
|
@ -93,25 +94,39 @@ struct onenand_chip {
|
||||||
int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
|
int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
|
||||||
int (*scan_bbt)(struct mtd_info *mtd);
|
int (*scan_bbt)(struct mtd_info *mtd);
|
||||||
|
|
||||||
spinlock_t chip_lock;
|
|
||||||
wait_queue_head_t wq;
|
|
||||||
int state;
|
int state;
|
||||||
|
unsigned char *page_buf;
|
||||||
|
unsigned char *oob_buf;
|
||||||
|
|
||||||
struct nand_oobinfo *autooob;
|
struct nand_oobinfo *autooob;
|
||||||
|
struct nand_ecclayout *ecclayout;
|
||||||
|
|
||||||
void *bbm;
|
void *bbm;
|
||||||
|
|
||||||
void *priv;
|
void *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper macros
|
||||||
|
*/
|
||||||
#define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index)
|
#define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index)
|
||||||
#define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1)
|
#define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1)
|
||||||
#define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)
|
#define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)
|
||||||
|
#define ONENAND_SET_PREV_BUFFERRAM(this) (this->bufferram_index ^= 1)
|
||||||
|
#define ONENAND_SET_BUFFERRAM0(this) (this->bufferram_index = 0)
|
||||||
|
#define ONENAND_SET_BUFFERRAM1(this) (this->bufferram_index = 1)
|
||||||
|
|
||||||
|
#define ONENAND_IS_DDP(this) \
|
||||||
|
(this->device_id & ONENAND_DEVICE_IS_DDP)
|
||||||
|
|
||||||
|
#define ONENAND_IS_2PLANE(this) (0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Options bits
|
* Options bits
|
||||||
*/
|
*/
|
||||||
#define ONENAND_CONT_LOCK (0x0001)
|
#define ONENAND_CONT_LOCK (0x0001)
|
||||||
|
#define ONENAND_PAGEBUF_ALLOC (0x1000)
|
||||||
|
#define ONENAND_OOBBUF_ALLOC (0x2000)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OneNAND Flash Manufacturer ID Codes
|
* OneNAND Flash Manufacturer ID Codes
|
||||||
|
@ -129,4 +144,7 @@ struct onenand_manufacturers {
|
||||||
char *name;
|
char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
|
||||||
|
struct mtd_oob_ops *ops);
|
||||||
|
|
||||||
#endif /* __LINUX_MTD_ONENAND_H */
|
#endif /* __LINUX_MTD_ONENAND_H */
|
||||||
|
|
|
@ -83,6 +83,8 @@
|
||||||
* Start Address 1 F100h (R/W)
|
* Start Address 1 F100h (R/W)
|
||||||
*/
|
*/
|
||||||
#define ONENAND_DDP_SHIFT (15)
|
#define ONENAND_DDP_SHIFT (15)
|
||||||
|
#define ONENAND_DDP_CHIP0 (0)
|
||||||
|
#define ONENAND_DDP_CHIP1 (1 << ONENAND_DDP_SHIFT)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start Address 8 F107h (R/W)
|
* Start Address 8 F107h (R/W)
|
||||||
|
|
|
@ -16,23 +16,17 @@
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
struct kvec {
|
|
||||||
void *iov_base;
|
|
||||||
size_t iov_len;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef int spinlock_t;
|
|
||||||
typedef int wait_queue_head_t;
|
|
||||||
|
|
||||||
struct mtd_info;
|
struct mtd_info;
|
||||||
struct erase_info;
|
struct erase_info;
|
||||||
|
|
||||||
|
extern struct mtd_info onenand_mtd;
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
extern void onenand_init(void);
|
extern void onenand_init(void);
|
||||||
extern int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
|
extern int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t * retlen, u_char * buf);
|
size_t * retlen, u_char * buf);
|
||||||
extern int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
|
extern int onenand_read_oob(struct mtd_info *mtd, loff_t from,
|
||||||
size_t * retlen, u_char * buf);
|
struct mtd_oob_ops *ops);
|
||||||
extern int onenand_write(struct mtd_info *mtd, loff_t from, size_t len,
|
extern int onenand_write(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t * retlen, const u_char * buf);
|
size_t * retlen, const u_char * buf);
|
||||||
extern int onenand_erase(struct mtd_info *mtd, struct erase_info *instr);
|
extern int onenand_erase(struct mtd_info *mtd, struct erase_info *instr);
|
||||||
|
|
Loading…
Add table
Reference in a new issue