[MTD] DOC: Fixup read functions and do a little cleanup
The NAND rework resulted in non ECC based reads. Fix it up and do a bit of cleanup while at it. Pointed out by Adrian Bunk. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
a39727f212
commit
7f8a894066
3 changed files with 211 additions and 319 deletions
|
@ -55,10 +55,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char *buf);
|
size_t *retlen, u_char *buf);
|
||||||
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
size_t *retlen, const u_char *buf);
|
size_t *retlen, const u_char *buf);
|
||||||
static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
|
||||||
size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
|
|
||||||
static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
|
|
||||||
size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
|
|
||||||
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
|
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
|
||||||
struct mtd_oob_ops *ops);
|
struct mtd_oob_ops *ops);
|
||||||
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
|
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
|
||||||
|
@ -614,18 +610,11 @@ EXPORT_SYMBOL_GPL(DoC2k_init);
|
||||||
|
|
||||||
static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
|
static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t * retlen, u_char * buf)
|
size_t * retlen, u_char * buf)
|
||||||
{
|
|
||||||
/* Just a special case of doc_read_ecc */
|
|
||||||
return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
|
||||||
size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel)
|
|
||||||
{
|
{
|
||||||
struct DiskOnChip *this = mtd->priv;
|
struct DiskOnChip *this = mtd->priv;
|
||||||
void __iomem *docptr = this->virtadr;
|
void __iomem *docptr = this->virtadr;
|
||||||
struct Nand *mychip;
|
struct Nand *mychip;
|
||||||
unsigned char syndrome[6];
|
unsigned char syndrome[6], eccbuf[6];
|
||||||
volatile char dummy;
|
volatile char dummy;
|
||||||
int i, len256 = 0, ret=0;
|
int i, len256 = 0, ret=0;
|
||||||
size_t left = len;
|
size_t left = len;
|
||||||
|
@ -673,15 +662,9 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,
|
DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP,
|
||||||
CDSN_CTRL_ECC_IO);
|
CDSN_CTRL_ECC_IO);
|
||||||
|
|
||||||
if (eccbuf) {
|
|
||||||
/* Prime the ECC engine */
|
/* Prime the ECC engine */
|
||||||
WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
|
WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
|
||||||
WriteDOC(DOC_ECC_EN, docptr, ECCConf);
|
WriteDOC(DOC_ECC_EN, docptr, ECCConf);
|
||||||
} else {
|
|
||||||
/* disable the ECC engine */
|
|
||||||
WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
|
|
||||||
WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* treat crossing 256-byte sector for 2M x 8bits devices */
|
/* treat crossing 256-byte sector for 2M x 8bits devices */
|
||||||
if (this->page256 && from + len > (from | 0xff) + 1) {
|
if (this->page256 && from + len > (from | 0xff) + 1) {
|
||||||
|
@ -698,7 +681,6 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
/* Let the caller know we completed it */
|
/* Let the caller know we completed it */
|
||||||
*retlen += len;
|
*retlen += len;
|
||||||
|
|
||||||
if (eccbuf) {
|
|
||||||
/* Read the ECC data through the DiskOnChip ECC logic */
|
/* Read the ECC data through the DiskOnChip ECC logic */
|
||||||
/* Note: this will work even with 2M x 8bit devices as */
|
/* Note: this will work even with 2M x 8bit devices as */
|
||||||
/* they have 8 bytes of OOB per 256 page. mf. */
|
/* they have 8 bytes of OOB per 256 page. mf. */
|
||||||
|
@ -722,8 +704,9 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
#ifdef ECC_DEBUG
|
#ifdef ECC_DEBUG
|
||||||
printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
|
printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
|
||||||
#endif
|
#endif
|
||||||
/* Read the ECC syndrom through the DiskOnChip ECC logic.
|
/* Read the ECC syndrom through the DiskOnChip ECC
|
||||||
These syndrome will be all ZERO when there is no error */
|
logic. These syndrome will be all ZERO when there
|
||||||
|
is no error */
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
syndrome[i] =
|
syndrome[i] =
|
||||||
ReadDOC(docptr, ECCSyndrome0 + i);
|
ReadDOC(docptr, ECCSyndrome0 + i);
|
||||||
|
@ -734,9 +717,11 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
printk(KERN_ERR "Errors corrected: %x\n", nb_errors);
|
printk(KERN_ERR "Errors corrected: %x\n", nb_errors);
|
||||||
#endif
|
#endif
|
||||||
if (nb_errors < 0) {
|
if (nb_errors < 0) {
|
||||||
/* We return error, but have actually done the read. Not that
|
/* We return error, but have actually done the
|
||||||
this can be told to user-space, via sys_read(), but at least
|
read. Not that this can be told to
|
||||||
MTD-aware stuff can know about it by checking *retlen */
|
user-space, via sys_read(), but at least
|
||||||
|
MTD-aware stuff can know about it by
|
||||||
|
checking *retlen */
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -749,7 +734,6 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
|
|
||||||
/* disable the ECC engine */
|
/* disable the ECC engine */
|
||||||
WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
|
WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
|
||||||
}
|
|
||||||
|
|
||||||
/* according to 11.4.1, we need to wait for the busy line
|
/* according to 11.4.1, we need to wait for the busy line
|
||||||
* drop if we read to the end of the page. */
|
* drop if we read to the end of the page. */
|
||||||
|
@ -770,18 +754,11 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
|
|
||||||
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
size_t * retlen, const u_char * buf)
|
size_t * retlen, const u_char * buf)
|
||||||
{
|
|
||||||
char eccbuf[6];
|
|
||||||
return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
|
|
||||||
size_t * retlen, const u_char * buf,
|
|
||||||
u_char * eccbuf, struct nand_oobinfo *oobsel)
|
|
||||||
{
|
{
|
||||||
struct DiskOnChip *this = mtd->priv;
|
struct DiskOnChip *this = mtd->priv;
|
||||||
int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */
|
int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */
|
||||||
void __iomem *docptr = this->virtadr;
|
void __iomem *docptr = this->virtadr;
|
||||||
|
unsigned char eccbuf[6];
|
||||||
volatile char dummy;
|
volatile char dummy;
|
||||||
int len256 = 0;
|
int len256 = 0;
|
||||||
struct Nand *mychip;
|
struct Nand *mychip;
|
||||||
|
@ -835,15 +812,9 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
DoC_Command(this, NAND_CMD_SEQIN, 0);
|
DoC_Command(this, NAND_CMD_SEQIN, 0);
|
||||||
DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO);
|
DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO);
|
||||||
|
|
||||||
if (eccbuf) {
|
|
||||||
/* Prime the ECC engine */
|
/* Prime the ECC engine */
|
||||||
WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
|
WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
|
||||||
WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
|
WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
|
||||||
} else {
|
|
||||||
/* disable the ECC engine */
|
|
||||||
WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
|
|
||||||
WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* treat crossing 256-byte sector for 2M x 8bits devices */
|
/* treat crossing 256-byte sector for 2M x 8bits devices */
|
||||||
if (this->page256 && to + len > (to | 0xff) + 1) {
|
if (this->page256 && to + len > (to | 0xff) + 1) {
|
||||||
|
@ -873,9 +844,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
|
|
||||||
DoC_WriteBuf(this, &buf[len256], len - len256);
|
DoC_WriteBuf(this, &buf[len256], len - len256);
|
||||||
|
|
||||||
if (eccbuf) {
|
WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr, CDSNControl);
|
||||||
WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr,
|
|
||||||
CDSNControl);
|
|
||||||
|
|
||||||
if (DoC_is_Millennium(this)) {
|
if (DoC_is_Millennium(this)) {
|
||||||
WriteDOC(0, docptr, NOP);
|
WriteDOC(0, docptr, NOP);
|
||||||
|
@ -904,8 +873,6 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
(long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
|
(long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
|
||||||
eccbuf[4], eccbuf[5]);
|
eccbuf[4], eccbuf[5]);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
DoC_Command(this, NAND_CMD_PAGEPROG, 0);
|
DoC_Command(this, NAND_CMD_PAGEPROG, 0);
|
||||||
|
|
||||||
DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
|
DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
|
||||||
|
|
|
@ -37,12 +37,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char *buf);
|
size_t *retlen, u_char *buf);
|
||||||
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
size_t *retlen, const u_char *buf);
|
size_t *retlen, const u_char *buf);
|
||||||
static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
|
||||||
size_t *retlen, u_char *buf, u_char *eccbuf,
|
|
||||||
struct nand_oobinfo *oobsel);
|
|
||||||
static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
|
|
||||||
size_t *retlen, const u_char *buf, u_char *eccbuf,
|
|
||||||
struct nand_oobinfo *oobsel);
|
|
||||||
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
|
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
|
||||||
struct mtd_oob_ops *ops);
|
struct mtd_oob_ops *ops);
|
||||||
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
|
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
|
||||||
|
@ -396,18 +390,10 @@ EXPORT_SYMBOL_GPL(DoCMil_init);
|
||||||
|
|
||||||
static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
|
static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char *buf)
|
size_t *retlen, u_char *buf)
|
||||||
{
|
|
||||||
/* Just a special case of doc_read_ecc */
|
|
||||||
return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
|
|
||||||
size_t *retlen, u_char *buf, u_char *eccbuf,
|
|
||||||
struct nand_oobinfo *oobsel)
|
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
volatile char dummy;
|
volatile char dummy;
|
||||||
unsigned char syndrome[6];
|
unsigned char syndrome[6], eccbuf[6];
|
||||||
struct DiskOnChip *this = mtd->priv;
|
struct DiskOnChip *this = mtd->priv;
|
||||||
void __iomem *docptr = this->virtadr;
|
void __iomem *docptr = this->virtadr;
|
||||||
struct Nand *mychip = &this->chips[from >> (this->chipshift)];
|
struct Nand *mychip = &this->chips[from >> (this->chipshift)];
|
||||||
|
@ -437,15 +423,9 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00);
|
DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00);
|
||||||
DoC_WaitReady(docptr);
|
DoC_WaitReady(docptr);
|
||||||
|
|
||||||
if (eccbuf) {
|
|
||||||
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
|
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
|
||||||
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
|
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
|
||||||
WriteDOC (DOC_ECC_EN, docptr, ECCConf);
|
WriteDOC (DOC_ECC_EN, docptr, ECCConf);
|
||||||
} else {
|
|
||||||
/* disable the ECC engine */
|
|
||||||
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
|
|
||||||
WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the data via the internal pipeline through CDSN IO register,
|
/* Read the data via the internal pipeline through CDSN IO register,
|
||||||
see Pipelined Read Operations 11.3 */
|
see Pipelined Read Operations 11.3 */
|
||||||
|
@ -465,7 +445,6 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
*retlen = len;
|
*retlen = len;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
if (eccbuf) {
|
|
||||||
/* Read the ECC data from Spare Data Area,
|
/* Read the ECC data from Spare Data Area,
|
||||||
see Reed-Solomon EDC/ECC 11.1 */
|
see Reed-Solomon EDC/ECC 11.1 */
|
||||||
dummy = ReadDOC(docptr, ReadPipeInit);
|
dummy = ReadDOC(docptr, ReadPipeInit);
|
||||||
|
@ -516,23 +495,15 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
|
|
||||||
/* disable the ECC engine */
|
/* disable the ECC engine */
|
||||||
WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
|
WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
|
static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
size_t *retlen, const u_char *buf)
|
size_t *retlen, const u_char *buf)
|
||||||
{
|
|
||||||
char eccbuf[6];
|
|
||||||
return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
|
|
||||||
size_t *retlen, const u_char *buf, u_char *eccbuf,
|
|
||||||
struct nand_oobinfo *oobsel)
|
|
||||||
{
|
{
|
||||||
int i,ret = 0;
|
int i,ret = 0;
|
||||||
|
char eccbuf[6];
|
||||||
volatile char dummy;
|
volatile char dummy;
|
||||||
struct DiskOnChip *this = mtd->priv;
|
struct DiskOnChip *this = mtd->priv;
|
||||||
void __iomem *docptr = this->virtadr;
|
void __iomem *docptr = this->virtadr;
|
||||||
|
@ -573,15 +544,9 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
DoC_Address(docptr, 3, to, 0x00, 0x00);
|
DoC_Address(docptr, 3, to, 0x00, 0x00);
|
||||||
DoC_WaitReady(docptr);
|
DoC_WaitReady(docptr);
|
||||||
|
|
||||||
if (eccbuf) {
|
|
||||||
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
|
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
|
||||||
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
|
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
|
||||||
WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
|
WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
|
||||||
} else {
|
|
||||||
/* disable the ECC engine */
|
|
||||||
WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
|
|
||||||
WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write the data via the internal pipeline through CDSN IO register,
|
/* Write the data via the internal pipeline through CDSN IO register,
|
||||||
see Pipelined Write Operations 11.2 */
|
see Pipelined Write Operations 11.2 */
|
||||||
|
@ -596,7 +561,6 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
#endif
|
#endif
|
||||||
WriteDOC(0x00, docptr, WritePipeTerm);
|
WriteDOC(0x00, docptr, WritePipeTerm);
|
||||||
|
|
||||||
if (eccbuf) {
|
|
||||||
/* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic
|
/* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic
|
||||||
see Reed-Solomon EDC/ECC 11.1 */
|
see Reed-Solomon EDC/ECC 11.1 */
|
||||||
WriteDOC(0, docptr, NOP);
|
WriteDOC(0, docptr, NOP);
|
||||||
|
@ -635,7 +599,6 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
(long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
|
(long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
|
||||||
eccbuf[4], eccbuf[5]);
|
eccbuf[4], eccbuf[5]);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
/* Commit the Page Program command and wait for ready
|
/* Commit the Page Program command and wait for ready
|
||||||
see Software Requirement 11.4 item 1.*/
|
see Software Requirement 11.4 item 1.*/
|
||||||
|
|
|
@ -41,12 +41,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char *buf);
|
size_t *retlen, u_char *buf);
|
||||||
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
size_t *retlen, const u_char *buf);
|
size_t *retlen, const u_char *buf);
|
||||||
static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
|
||||||
size_t *retlen, u_char *buf, u_char *eccbuf,
|
|
||||||
struct nand_oobinfo *oobsel);
|
|
||||||
static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
|
|
||||||
size_t *retlen, const u_char *buf, u_char *eccbuf,
|
|
||||||
struct nand_oobinfo *oobsel);
|
|
||||||
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
|
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
|
||||||
struct mtd_oob_ops *ops);
|
struct mtd_oob_ops *ops);
|
||||||
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
|
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
|
||||||
|
@ -594,19 +588,11 @@ static int doc_dumpblk(struct mtd_info *mtd, loff_t from)
|
||||||
|
|
||||||
static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
|
static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
size_t *retlen, u_char *buf)
|
size_t *retlen, u_char *buf)
|
||||||
{
|
|
||||||
/* Just a special case of doc_read_ecc */
|
|
||||||
return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
|
||||||
size_t *retlen, u_char *buf, u_char *eccbuf,
|
|
||||||
struct nand_oobinfo *oobsel)
|
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i;
|
||||||
volatile char dummy;
|
volatile char dummy;
|
||||||
loff_t fofs;
|
loff_t fofs;
|
||||||
unsigned char syndrome[6];
|
unsigned char syndrome[6], eccbuf[6];
|
||||||
struct DiskOnChip *this = mtd->priv;
|
struct DiskOnChip *this = mtd->priv;
|
||||||
void __iomem * docptr = this->virtadr;
|
void __iomem * docptr = this->virtadr;
|
||||||
struct Nand *mychip = &this->chips[from >> (this->chipshift)];
|
struct Nand *mychip = &this->chips[from >> (this->chipshift)];
|
||||||
|
@ -644,14 +630,9 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
WriteDOC(0, docptr, Mplus_FlashControl);
|
WriteDOC(0, docptr, Mplus_FlashControl);
|
||||||
DoC_WaitReady(docptr);
|
DoC_WaitReady(docptr);
|
||||||
|
|
||||||
if (eccbuf) {
|
|
||||||
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
|
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
|
||||||
WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
|
WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
|
||||||
WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
|
WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
|
||||||
} else {
|
|
||||||
/* disable the ECC engine */
|
|
||||||
WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Let the caller know we completed it */
|
/* Let the caller know we completed it */
|
||||||
*retlen = len;
|
*retlen = len;
|
||||||
|
@ -660,7 +641,6 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
ReadDOC(docptr, Mplus_ReadPipeInit);
|
ReadDOC(docptr, Mplus_ReadPipeInit);
|
||||||
ReadDOC(docptr, Mplus_ReadPipeInit);
|
ReadDOC(docptr, Mplus_ReadPipeInit);
|
||||||
|
|
||||||
if (eccbuf) {
|
|
||||||
/* Read the data via the internal pipeline through CDSN IO
|
/* Read the data via the internal pipeline through CDSN IO
|
||||||
register, see Pipelined Read Operations 11.3 */
|
register, see Pipelined Read Operations 11.3 */
|
||||||
MemReadDOC(docptr, buf, len);
|
MemReadDOC(docptr, buf, len);
|
||||||
|
@ -691,9 +671,10 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
printk("ECC Errors corrected: %x\n", nb_errors);
|
printk("ECC Errors corrected: %x\n", nb_errors);
|
||||||
#endif
|
#endif
|
||||||
if (nb_errors < 0) {
|
if (nb_errors < 0) {
|
||||||
/* We return error, but have actually done the read. Not that
|
/* We return error, but have actually done the
|
||||||
this can be told to user-space, via sys_read(), but at least
|
read. Not that this can be told to user-space, via
|
||||||
MTD-aware stuff can know about it by checking *retlen */
|
sys_read(), but at least MTD-aware stuff can know
|
||||||
|
about it by checking *retlen */
|
||||||
#ifdef ECC_DEBUG
|
#ifdef ECC_DEBUG
|
||||||
printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n",
|
printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n",
|
||||||
__FILE__, __LINE__, (int)from);
|
__FILE__, __LINE__, (int)from);
|
||||||
|
@ -715,16 +696,8 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
(long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
|
(long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
|
||||||
eccbuf[4], eccbuf[5]);
|
eccbuf[4], eccbuf[5]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* disable the ECC engine */
|
/* disable the ECC engine */
|
||||||
WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf);
|
WriteDOC(DOC_ECC_DIS, docptr , Mplus_ECCConf);
|
||||||
} else {
|
|
||||||
/* Read the data via the internal pipeline through CDSN IO
|
|
||||||
register, see Pipelined Read Operations 11.3 */
|
|
||||||
MemReadDOC(docptr, buf, len-2);
|
|
||||||
buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead);
|
|
||||||
buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable flash internally */
|
/* Disable flash internally */
|
||||||
WriteDOC(0, docptr, Mplus_FlashSelect);
|
WriteDOC(0, docptr, Mplus_FlashSelect);
|
||||||
|
@ -734,18 +707,11 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
|
||||||
|
|
||||||
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
size_t *retlen, const u_char *buf)
|
size_t *retlen, const u_char *buf)
|
||||||
{
|
|
||||||
char eccbuf[6];
|
|
||||||
return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
|
|
||||||
size_t *retlen, const u_char *buf, u_char *eccbuf,
|
|
||||||
struct nand_oobinfo *oobsel)
|
|
||||||
{
|
{
|
||||||
int i, before, ret = 0;
|
int i, before, ret = 0;
|
||||||
loff_t fto;
|
loff_t fto;
|
||||||
volatile char dummy;
|
volatile char dummy;
|
||||||
|
char eccbuf[6];
|
||||||
struct DiskOnChip *this = mtd->priv;
|
struct DiskOnChip *this = mtd->priv;
|
||||||
void __iomem * docptr = this->virtadr;
|
void __iomem * docptr = this->virtadr;
|
||||||
struct Nand *mychip = &this->chips[to >> (this->chipshift)];
|
struct Nand *mychip = &this->chips[to >> (this->chipshift)];
|
||||||
|
@ -795,7 +761,6 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
/* Disable the ECC engine */
|
/* Disable the ECC engine */
|
||||||
WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
|
WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
|
||||||
|
|
||||||
if (eccbuf) {
|
|
||||||
if (before) {
|
if (before) {
|
||||||
/* Write the block status BLOCK_USED (0x5555) */
|
/* Write the block status BLOCK_USED (0x5555) */
|
||||||
WriteDOC(0x55, docptr, Mil_CDSN_IO);
|
WriteDOC(0x55, docptr, Mil_CDSN_IO);
|
||||||
|
@ -804,11 +769,9 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
|
|
||||||
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
|
/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
|
||||||
WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);
|
WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);
|
||||||
}
|
|
||||||
|
|
||||||
MemWriteDOC(docptr, (unsigned char *) buf, len);
|
MemWriteDOC(docptr, (unsigned char *) buf, len);
|
||||||
|
|
||||||
if (eccbuf) {
|
|
||||||
/* Write ECC data to flash, the ECC info is generated by
|
/* Write ECC data to flash, the ECC info is generated by
|
||||||
the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */
|
the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */
|
||||||
DoC_Delay(docptr, 3);
|
DoC_Delay(docptr, 3);
|
||||||
|
@ -834,7 +797,6 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
|
||||||
(long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
|
(long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
|
||||||
eccbuf[4], eccbuf[5]);
|
eccbuf[4], eccbuf[5]);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
|
WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
|
||||||
WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
|
WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
|
||||||
|
|
Loading…
Reference in a new issue