|
@@ -37,12 +37,6 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
|
|
|
size_t *retlen, u_char *buf);
|
|
|
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|
|
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,
|
|
|
struct mtd_oob_ops *ops);
|
|
|
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,
|
|
|
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;
|
|
|
volatile char dummy;
|
|
|
- unsigned char syndrome[6];
|
|
|
+ unsigned char syndrome[6], eccbuf[6];
|
|
|
struct DiskOnChip *this = mtd->priv;
|
|
|
void __iomem *docptr = this->virtadr;
|
|
|
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_WaitReady(docptr);
|
|
|
|
|
|
- if (eccbuf) {
|
|
|
- /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
|
|
|
- WriteDOC (DOC_ECC_RESET, 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);
|
|
|
- }
|
|
|
+ /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
|
|
|
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
|
|
|
+ WriteDOC (DOC_ECC_EN, docptr, ECCConf);
|
|
|
|
|
|
/* Read the data via the internal pipeline through CDSN IO register,
|
|
|
see Pipelined Read Operations 11.3 */
|
|
@@ -465,74 +445,65 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
|
|
|
*retlen = len;
|
|
|
ret = 0;
|
|
|
|
|
|
- if (eccbuf) {
|
|
|
- /* Read the ECC data from Spare Data Area,
|
|
|
- see Reed-Solomon EDC/ECC 11.1 */
|
|
|
- dummy = ReadDOC(docptr, ReadPipeInit);
|
|
|
+ /* Read the ECC data from Spare Data Area,
|
|
|
+ see Reed-Solomon EDC/ECC 11.1 */
|
|
|
+ dummy = ReadDOC(docptr, ReadPipeInit);
|
|
|
#ifndef USE_MEMCPY
|
|
|
- for (i = 0; i < 5; i++) {
|
|
|
- /* N.B. you have to increase the source address in this way or the
|
|
|
- ECC logic will not work properly */
|
|
|
- eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
|
|
|
- }
|
|
|
+ for (i = 0; i < 5; i++) {
|
|
|
+ /* N.B. you have to increase the source address in this way or the
|
|
|
+ ECC logic will not work properly */
|
|
|
+ eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i);
|
|
|
+ }
|
|
|
#else
|
|
|
- memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5);
|
|
|
+ memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5);
|
|
|
#endif
|
|
|
- eccbuf[5] = ReadDOC(docptr, LastDataRead);
|
|
|
+ eccbuf[5] = ReadDOC(docptr, LastDataRead);
|
|
|
|
|
|
- /* Flush the pipeline */
|
|
|
- dummy = ReadDOC(docptr, ECCConf);
|
|
|
- dummy = ReadDOC(docptr, ECCConf);
|
|
|
+ /* Flush the pipeline */
|
|
|
+ dummy = ReadDOC(docptr, ECCConf);
|
|
|
+ dummy = ReadDOC(docptr, ECCConf);
|
|
|
|
|
|
- /* Check the ECC Status */
|
|
|
- if (ReadDOC(docptr, ECCConf) & 0x80) {
|
|
|
- int nb_errors;
|
|
|
- /* There was an ECC error */
|
|
|
+ /* Check the ECC Status */
|
|
|
+ if (ReadDOC(docptr, ECCConf) & 0x80) {
|
|
|
+ int nb_errors;
|
|
|
+ /* There was an ECC error */
|
|
|
#ifdef ECC_DEBUG
|
|
|
- printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
|
|
|
+ printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
|
|
|
#endif
|
|
|
- /* Read the ECC syndrom through the DiskOnChip ECC logic.
|
|
|
- These syndrome will be all ZERO when there is no error */
|
|
|
- for (i = 0; i < 6; i++) {
|
|
|
- syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i);
|
|
|
- }
|
|
|
- nb_errors = doc_decode_ecc(buf, syndrome);
|
|
|
+ /* Read the ECC syndrom through the DiskOnChip ECC logic.
|
|
|
+ These syndrome will be all ZERO when there is no error */
|
|
|
+ for (i = 0; i < 6; i++) {
|
|
|
+ syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i);
|
|
|
+ }
|
|
|
+ nb_errors = doc_decode_ecc(buf, syndrome);
|
|
|
#ifdef ECC_DEBUG
|
|
|
- printk("ECC Errors corrected: %x\n", nb_errors);
|
|
|
+ printk("ECC Errors corrected: %x\n", nb_errors);
|
|
|
#endif
|
|
|
- if (nb_errors < 0) {
|
|
|
- /* We return error, but have actually done the read. Not that
|
|
|
- this can be told to user-space, via sys_read(), but at least
|
|
|
- MTD-aware stuff can know about it by checking *retlen */
|
|
|
- ret = -EIO;
|
|
|
- }
|
|
|
+ if (nb_errors < 0) {
|
|
|
+ /* We return error, but have actually done the read. Not that
|
|
|
+ this can be told to user-space, via sys_read(), but at least
|
|
|
+ MTD-aware stuff can know about it by checking *retlen */
|
|
|
+ ret = -EIO;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
#ifdef PSYCHO_DEBUG
|
|
|
- printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
|
|
|
- (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
|
|
|
- eccbuf[4], eccbuf[5]);
|
|
|
+ printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
|
|
|
+ (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
|
|
|
+ eccbuf[4], eccbuf[5]);
|
|
|
#endif
|
|
|
|
|
|
- /* disable the ECC engine */
|
|
|
- WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
|
|
|
- }
|
|
|
+ /* disable the ECC engine */
|
|
|
+ WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
|
|
|
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;
|
|
|
+ char eccbuf[6];
|
|
|
volatile char dummy;
|
|
|
struct DiskOnChip *this = mtd->priv;
|
|
|
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_WaitReady(docptr);
|
|
|
|
|
|
- if (eccbuf) {
|
|
|
- /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
|
|
|
- WriteDOC (DOC_ECC_RESET, 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);
|
|
|
- }
|
|
|
+ /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
|
|
|
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
|
|
|
+ WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
|
|
|
|
|
|
/* Write the data via the internal pipeline through CDSN IO register,
|
|
|
see Pipelined Write Operations 11.2 */
|
|
@@ -596,46 +561,44 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
|
|
|
#endif
|
|
|
WriteDOC(0x00, docptr, WritePipeTerm);
|
|
|
|
|
|
- if (eccbuf) {
|
|
|
- /* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic
|
|
|
- see Reed-Solomon EDC/ECC 11.1 */
|
|
|
- WriteDOC(0, docptr, NOP);
|
|
|
- WriteDOC(0, docptr, NOP);
|
|
|
- WriteDOC(0, docptr, NOP);
|
|
|
+ /* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic
|
|
|
+ see Reed-Solomon EDC/ECC 11.1 */
|
|
|
+ WriteDOC(0, docptr, NOP);
|
|
|
+ WriteDOC(0, docptr, NOP);
|
|
|
+ WriteDOC(0, docptr, NOP);
|
|
|
|
|
|
- /* Read the ECC data through the DiskOnChip ECC logic */
|
|
|
- for (i = 0; i < 6; i++) {
|
|
|
- eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i);
|
|
|
- }
|
|
|
+ /* Read the ECC data through the DiskOnChip ECC logic */
|
|
|
+ for (i = 0; i < 6; i++) {
|
|
|
+ eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i);
|
|
|
+ }
|
|
|
|
|
|
- /* ignore the ECC engine */
|
|
|
- WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
|
|
|
+ /* ignore the ECC engine */
|
|
|
+ WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
|
|
|
|
|
|
#ifndef USE_MEMCPY
|
|
|
- /* Write the ECC data to flash */
|
|
|
- for (i = 0; i < 6; i++) {
|
|
|
- /* N.B. you have to increase the source address in this way or the
|
|
|
- ECC logic will not work properly */
|
|
|
- WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i);
|
|
|
- }
|
|
|
+ /* Write the ECC data to flash */
|
|
|
+ for (i = 0; i < 6; i++) {
|
|
|
+ /* N.B. you have to increase the source address in this way or the
|
|
|
+ ECC logic will not work properly */
|
|
|
+ WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i);
|
|
|
+ }
|
|
|
#else
|
|
|
- memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6);
|
|
|
+ memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6);
|
|
|
#endif
|
|
|
|
|
|
- /* write the block status BLOCK_USED (0x5555) at the end of ECC data
|
|
|
- FIXME: this is only a hack for programming the IPL area for LinuxBIOS
|
|
|
- and should be replace with proper codes in user space utilities */
|
|
|
- WriteDOC(0x55, docptr, Mil_CDSN_IO);
|
|
|
- WriteDOC(0x55, docptr, Mil_CDSN_IO + 1);
|
|
|
+ /* write the block status BLOCK_USED (0x5555) at the end of ECC data
|
|
|
+ FIXME: this is only a hack for programming the IPL area for LinuxBIOS
|
|
|
+ and should be replace with proper codes in user space utilities */
|
|
|
+ WriteDOC(0x55, docptr, Mil_CDSN_IO);
|
|
|
+ WriteDOC(0x55, docptr, Mil_CDSN_IO + 1);
|
|
|
|
|
|
- WriteDOC(0x00, docptr, WritePipeTerm);
|
|
|
+ WriteDOC(0x00, docptr, WritePipeTerm);
|
|
|
|
|
|
#ifdef PSYCHO_DEBUG
|
|
|
- printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
|
|
|
- (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
|
|
|
- eccbuf[4], eccbuf[5]);
|
|
|
+ printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
|
|
|
+ (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
|
|
|
+ eccbuf[4], eccbuf[5]);
|
|
|
#endif
|
|
|
- }
|
|
|
|
|
|
/* Commit the Page Program command and wait for ready
|
|
|
see Software Requirement 11.4 item 1.*/
|