Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f8a8940 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

[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: default avatarThomas Gleixner <tglx@linutronix.de>
parent a39727f2
Loading
Loading
Loading
Loading
+73 −106
Original line number Diff line number Diff line
@@ -55,10 +55,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,
@@ -614,18 +610,11 @@ EXPORT_SYMBOL_GPL(DoC2k_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)
{
	struct DiskOnChip *this = mtd->priv;
	void __iomem *docptr = this->virtadr;
	struct Nand *mychip;
	unsigned char syndrome[6];
	unsigned char syndrome[6], eccbuf[6];
	volatile char dummy;
	int i, len256 = 0, ret=0;
	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,
			    CDSN_CTRL_ECC_IO);

		if (eccbuf) {
		/* Prime the ECC engine */
		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);
		}

		/* treat crossing 256-byte sector for 2M x 8bits devices */
		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 */
		*retlen += len;

		if (eccbuf) {
		/* Read the ECC data through the DiskOnChip ECC logic */
		/* Note: this will work even with 2M x 8bit devices as   */
		/*       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
			printk(KERN_ERR "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 */
			/* 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);
@@ -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);
#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 */
				/* 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;
			}
		}
@@ -749,7 +734,6 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,

		/* disable the ECC engine */
		WriteDOC(DOC_ECC_DIS, docptr , ECCConf);
		}

		/* according to 11.4.1, we need to wait for the busy line
	         * 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,
		     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;
	int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */
	void __iomem *docptr = this->virtadr;
	unsigned char eccbuf[6];
	volatile char dummy;
	int len256 = 0;
	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_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO);

		if (eccbuf) {
		/* Prime the ECC engine */
		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);
		}

		/* treat crossing 256-byte sector for 2M x 8bits devices */
		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);

		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)) {
			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],
			 eccbuf[4], eccbuf[5]);
#endif
		}

		DoC_Command(this, NAND_CMD_PAGEPROG, 0);

		DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP);
+71 −108
Original line number Diff line number Diff line
@@ -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);
	}

	/* Read the data via the internal pipeline through CDSN IO register,
	   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;
        ret = 0;

	if (eccbuf) {
	/* Read the ECC data from Spare Data Area,
	   see Reed-Solomon EDC/ECC 11.1 */
	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 */
	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);
	}

	/* Write the data via the internal pipeline through CDSN IO register,
	   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
	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);
@@ -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],
	       eccbuf[4], eccbuf[5]);
#endif
	}

	/* Commit the Page Program command and wait for ready
	   see Software Requirement 11.4 item 1.*/
+63 −101
Original line number Diff line number Diff line
@@ -41,12 +41,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,
@@ -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,
		    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;
	volatile char dummy;
	loff_t fofs;
	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)];
@@ -644,14 +630,9 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
	WriteDOC(0, docptr, Mplus_FlashControl);
	DoC_WaitReady(docptr);

	if (eccbuf) {
	/* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
	WriteDOC(DOC_ECC_RESET, 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 */
	*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);

	if (eccbuf) {
	/* Read the data via the internal pipeline through CDSN IO
	   register, see Pipelined Read Operations 11.3 */
	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);
#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 */
			/* 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 */
#ifdef ECC_DEBUG
			printk("%s(%d): Millennium Plus ECC error (from=0x%x:\n",
				__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],
	       eccbuf[4], eccbuf[5]);
#endif

	/* disable the ECC engine */
	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 */
	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,
		     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;
	loff_t fto;
	volatile char dummy;
	char eccbuf[6];
	struct DiskOnChip *this = mtd->priv;
	void __iomem * docptr = this->virtadr;
	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 */
	WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);

	if (eccbuf) {
	if (before) {
		/* Write the block status BLOCK_USED (0x5555) */
		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 .*/
	WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, Mplus_ECCConf);
	}

	MemWriteDOC(docptr, (unsigned char *) buf, len);

	if (eccbuf) {
	/* Write ECC data to flash, the ECC info is generated by
	   the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */
	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],
	       eccbuf[4], eccbuf[5]);
#endif
	}

	WriteDOC(0x00, docptr, Mplus_WritePipeTerm);
	WriteDOC(0x00, docptr, Mplus_WritePipeTerm);