public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Ilya Yanok <yanok@emcraft.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3
Date: Fri, 17 Jul 2009 14:48:38 +0400	[thread overview]
Message-ID: <4A605706.9020909@emcraft.com> (raw)
In-Reply-To: <20090622234349.GE4756@b07421-ec1.am.freescale.net>

Hi Scott,

please review the updated patch (will be posted as a follow-up).

Scott Wood wrote:
> Please look at drivers/mtd/nand/mpc5121_nfc.c, which AFAICT is very
> similar hardware, and see if anything can be factored out into common
> code, and try to keep the rest looking the same except where the hardware
> actually differs.
>   

Hmm... For now we just can't spend enough effort for this...

>> +static struct nand_ecclayout nand_hw_eccoob_16 = {
>> +	.eccbytes = 5,
>> +	.eccpos = {6, 7, 8, 9, 10},
>> +	.oobfree = {{0, 6}, {12, 4}, }
>> +};
>>     
>
> This implies the bad block marker is one byte at offset 11 (it's all
> that's left), but I don't see any override of the bad block pattern.
>   

This is surely a bug. Fixed.

>> +static void *mxc_nand_memcpy32(void *dest, void *source, size_t size)
>> +{
>> +	uint32_t *s = source, *d = dest;
>> +
>> +	size >>= 2;
>> +	while (size--)
>> +		*d++ = *s++;
>> +	return dest;
>> +}
>>     
>
> This should probably be using I/O accessors (possibly raw) -- and should
> take uint32_t *, not void *.
>   

Fixed.

>> +/*
>> + * This function requests the NANDFC to perform a read of the
>> + * NAND device status and returns the current status.
>> + */
>> +static uint16_t get_dev_status(struct mxc_nand_host *host)
>> +{
>> +	void __iomem *main_buf = host->regs->main_area1;
>> +	uint32_t store;
>> +	uint16_t ret, tmp;
>> +	/* Issue status request to NAND device */
>> +
>> +	/* store the main area1 first word, later do recovery */
>> +	store = readl(main_buf);
>> +	/*
>> +	 * NANDFC buffer 1 is used for device status to prevent
>> +	 * corruption of read/write buffer on status requests.
>> +	 */
>> +	writew(1, &host->regs->nfc_buf_addr);
>>     
>
> But it looks like buffer 1 is used for data with large page flash.
>   

Well, we save first word of the buffer and then recover it.

> Other drivers don't seem to have any problem with status reads clobbering
> the buffer...
>
>   
>> +/* This functions is used by upper layer to checks if device is ready */
>> +static int mxc_nand_dev_ready(struct mtd_info *mtd)
>>     
>
> "This functions is"?  I'd say this comment is pretty redundant with respect
> to the function name anyway...
>   

Fixed.

>> +static u_char mxc_nand_read_byte(struct mtd_info *mtd)
>> +{
>> +	struct nand_chip *nand_chip = mtd->priv;
>> +	struct mxc_nand_host *host = nand_chip->priv;
>> +	uint8_t ret = 0;
>> +	uint16_t col, rd_word;
>> +	uint16_t __iomem *main_buf =
>> +		(uint16_t __iomem *)host->regs->main_area0;
>> +	uint16_t __iomem *spare_buf =
>> +		(uint16_t __iomem *)host->regs->spare_area0;
>>     
>
> According to Magnus Lilja, "the nand flash controller can only handle 32
> bit read/write operations, any other size will cause an abort (or
> something like that)".  But now we're accessing it as 16-bit?
>   

16-bit accesses work quite well. Problem was with 8-bit accesses.

>> +static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
>> +{
>> +	struct nand_chip *nand_chip = mtd->priv;
>> +	struct mxc_nand_host *host = nand_chip->priv;
>> +	uint16_t col, rd_word, ret;
>> +	uint16_t __iomem *p;
>> +
>> +	MTDDEBUG(MTD_DEBUG_LEVEL3,
>> +	      "mxc_nand_read_word(col = %d)\n", host->col_addr);
>> +
>> +	col = host->col_addr;
>> +	/* Adjust saved column address */
>> +	if (col < mtd->writesize && host->spare_only)
>> +		col += mtd->writesize;
>> +
>> +	if (col < mtd->writesize) {
>> +		p = (uint16_t __iomem *)(host->regs->main_area0 + (col >> 1));
>> +	} else {
>> +		p = (uint16_t __iomem *)(host->regs->spare_area0 +
>> +				((col - mtd->writesize) >> 1));
>> +	}
>> +
>> +	if (col & 1) {
>> +		rd_word = readw(p);
>> +		ret = (rd_word >> 8) & 0xff;
>> +		rd_word = readw(&p[1]);
>> +		ret |= (rd_word << 8) & 0xff00;
>> +
>>     
>
> col should never be odd if you're reading words.
>   

It can be odd if previously we've read a byte.

>> +/*
>> + * Write data of length len to buffer buf. The data to be
>> + * written on NAND Flash is first copied to RAMbuffer. After the Data Input
>> + * Operation by the NFC, the data is written to NAND Flash
>> + */
>> +static void mxc_nand_write_buf(struct mtd_info *mtd,
>> +				const u_char *buf, int len)
>> +{
>> +	struct nand_chip *nand_chip = mtd->priv;
>> +	struct mxc_nand_host *host = nand_chip->priv;
>> +	int n, col, i = 0;
>> +
>> +	MTDDEBUG(MTD_DEBUG_LEVEL3,
>> +	      "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
>> +	      len);
>> +
>> +	col = host->col_addr;
>> +
>> +	/* Adjust saved column address */
>> +	if (col < mtd->writesize && host->spare_only)
>> +		col += mtd->writesize;
>> +
>> +	n = mtd->writesize + mtd->oobsize - col;
>> +	n = min(len, n);
>> +
>> +	MTDDEBUG(MTD_DEBUG_LEVEL3,
>> +	      "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
>> +
>> +	while (n) {
>>     
>
> Safer to do while (n > 0), especially when the code is this complex.
>   

Fixed.

>> +		void __iomem *p;
>> +
>> +		if (col < mtd->writesize) {
>> +			p = host->regs->main_area0 + (col & ~3);
>> +		} else {
>> +			p = host->regs->spare_area0 -
>> +						mtd->writesize + (col & ~3);
>> +		}
>> +
>> +		MTDDEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
>> +		      __LINE__, p);
>> +
>> +		if (((col | (int)&buf[i]) & 3) || n < 16) {
>>     
>
> Do not cast pointers to "int".  Use "uintptr_t" or "unsigned long" if you
> must.
>
> Why < 16 and not < 4?
>   

Fixed.

>> +			uint32_t data = 0;
>> +
>> +			if (col & 3 || n < 4)
>> +				data = readl(p);
>>     
>
> If that condition doesn't hold, the data we use is zero?
>   

If that condition doesn't hold we are going to rewrite a whole 32-bit
word so there is no need to read it's old content. But I've changed that
piece of code as you suggested anyway.

>> +
>> +			switch (col & 3) {
>> +			case 0:
>> +				if (n) {
>> +					data = (data & 0xffffff00) |
>> +					    (buf[i++] << 0);
>> +					n--;
>> +					col++;
>> +				}
>> +			case 1:
>> +				if (n) {
>> +					data = (data & 0xffff00ff) |
>> +					    (buf[i++] << 8);
>> +					n--;
>> +					col++;
>> +				}
>> +			case 2:
>> +				if (n) {
>> +					data = (data & 0xff00ffff) |
>> +					    (buf[i++] << 16);
>> +					n--;
>> +					col++;
>> +				}
>> +			case 3:
>> +				if (n) {
>> +					data = (data & 0x00ffffff) |
>> +					    (buf[i++] << 24);
>> +					n--;
>> +					col++;
>> +				}
>> +			}
>> +			writel(data, p);
>>     
>
> Might I suggest this?
>
> union {
> 	uint32_t word;
> 	uint8_t bytes[4];
> } nfc_word;
>
> nfc_word.word = readl(p);
> nfc_word.bytes[col & 3] = buf[i++];
> n--;
> col++;
>
> writel(nfc_word.word, p);
>
> As a side benefit, you lose the endian dependency.
>   

Thanks! I've used your code.

>> +			mxc_nand_memcpy32(p, (void *)&buf[i], m);
>>     
>
> Unnecessary cast.
>   

Fixed.

>> +	/* Update saved column address */
>> +	host->col_addr = col;
>> +
>> +}
>>     
>
> No blank lines before the brace at the end of a block.
>   

Fixed.

>> +
>> +/*
>> + * Used by the upper layer to verify the data in NAND Flash
>> + * with the data in the buf.
>> + */
>> +static int mxc_nand_verify_buf(struct mtd_info *mtd,
>> +				const u_char *buf, int len)
>> +{
>> +	return -EFAULT;
>> +}
>>     
>
> Umm...
>   

I've added verify_buf function.

>> +	case NAND_CMD_SEQIN:
>> +		if (column >= mtd->writesize) {
>> +			/*
>> +			 * FIXME: before send SEQIN command for write OOB,
>> +			 * We must read one page out.
>> +			 * For K9F1GXX has no READ1 command to set current HW
>> +			 * pointer to spare area, we must write the whole page
>> +			 * including OOB together.
>> +			 */
>> +			if (host->pagesize_2k) {
>> +				/* call ourself to read a page */
>> +				mxc_nand_command(mtd, NAND_CMD_READ0, 0,
>> +						page_addr);
>> +			}
>>     
>
> Should this be #ifdef HWECC?  And update the comment to indicate the
> actual problem, which is the unusual hardware ECC implementation.  I
> don't see what the lack of a "READ1" command has to do with it.
>   

I've updated the comment.

> And is this actually a FIXME if it's already being done?
>
>   
>> +#ifdef CONFIG_MXC_NAND_HWECC
>> +	this->ecc.calculate = mxc_nand_calculate_ecc;
>> +	this->ecc.hwctl = mxc_nand_enable_hwecc;
>> +	this->ecc.correct = mxc_nand_correct_data;
>> +	this->ecc.mode = NAND_ECC_HW;
>> +	this->ecc.size = 512;
>> +	this->ecc.bytes = 3;
>> +	this->ecc.layout = &nand_hw_eccoob_8;
>> +	tmp = readw(&host->regs->nfc_config1);
>> +	tmp |= NFC_ECC_EN;
>> +	writew(tmp, &host->regs->nfc_config1);
>> +#else
>> +	this->ecc.size = 512;
>> +	this->ecc.bytes = 3;
>> +	this->ecc.layout = &nand_hw_eccoob_8;
>> +	this->ecc.mode = NAND_ECC_SOFT;
>> +	tmp = readw(&host->regs->nfc_config1);
>> +	tmp &= ~NFC_ECC_EN;
>> +	writew(tmp, &host->regs->nfc_config1);
>> +#endif
>>     
>
> Soft ECC only supports 256-byte ECC blocks (anything you set here to the
> contrary will just be overwritten), and you'll need a layout that
> accommodates that with enough ECC bytes.
>
> Alternatively, you can implement 512-byte soft ECC if you don't want to
> waste those 3 extra OOB bytes. :-)
>
>   
>> +	host->pagesize_2k = 0;
>>     
>
> So large page is currently unsupported?
>   

Linux driver was fixed recently and now it claims to support 2K page
size... I've added all needed fixes but I can understand how this driver
should detect the pagesize... Linux driver calls nand_scan_ident()
itself for this... Do you think I can calls nand_scan_ident() from my
board_nand_init() function?

Regards, Ilya.

  parent reply	other threads:[~2009-07-17 10:48 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-06-08  0:12 [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Ilya Yanok
2009-06-08  0:12 ` [U-Boot] [PATCH 1/7] mx27: basic cpu support Ilya Yanok
2009-06-20 13:13   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-08  0:12 ` [U-Boot] [PATCH 2/7] serial_mx31: allow it to work with mx27 too and rename to serial_mxc Ilya Yanok
2009-06-20 13:18   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-08  0:12 ` [U-Boot] [PATCH 3/7] fec_imx27: driver for FEC ethernet controller on i.MX27 Ilya Yanok
2009-07-17 10:57   ` [U-Boot] [PATCH] fec_mxc: " Ilya Yanok
2009-07-17 14:05     ` Ben Warren
2009-07-21 15:32       ` Ilya Yanok
2009-07-22 22:23         ` Jean-Christophe PLAGNIOL-VILLARD
2009-07-22 23:03           ` Ben Warren
2009-07-23  6:28         ` Ben Warren
2009-06-08  0:12 ` [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3 Ilya Yanok
2009-06-20 13:22   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-22 23:43   ` Scott Wood
2009-06-23 20:03     ` Magnus Lilja
2009-07-03 19:03       ` Paul Thomas
2009-07-03 19:11         ` Paul Thomas
2009-07-17 10:48     ` Ilya Yanok [this message]
2009-07-17 10:53       ` [U-Boot] [PATCH] " Ilya Yanok
2009-07-22 21:33         ` Jean-Christophe PLAGNIOL-VILLARD
2009-07-28 22:37         ` Scott Wood
2009-08-03  1:45           ` Ilya Yanok
2009-08-04 23:32             ` Scott Wood
2009-08-10 22:32               ` Ilya Yanok
2009-08-11 22:53                 ` Scott Wood
2009-08-03  2:01           ` Ilya Yanok
2009-08-03 16:58             ` Scott Wood
2009-07-17 16:00       ` [U-Boot] [PATCH 4/7] " Scott Wood
2009-06-08  0:12 ` [U-Boot] [PATCH 5/7] mxc-mmc: sdhc host driver for MX2 and MX3 proccessor Ilya Yanok
2009-06-21 11:04   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-23 23:02   ` alfred steele
2009-08-07 20:13   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-08  0:12 ` [U-Boot] [PATCH 6/7] arm: add support for CONFIG_GENERIC_MMC Ilya Yanok
2009-06-20 13:20   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-08  0:12 ` [U-Boot] [PATCH 7/7] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
2009-06-21 11:21   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-23 16:55     ` Detlev Zundel
2009-07-07 19:24     ` Wolfgang Denk
2009-07-17 11:00     ` [U-Boot] [PATCH] " Ilya Yanok
2009-07-22 21:37       ` Jean-Christophe PLAGNIOL-VILLARD
2009-07-22 22:17         ` Ilya Yanok
2009-07-23 21:37           ` Jean-Christophe PLAGNIOL-VILLARD
2009-08-03  1:46             ` Ilya Yanok
2009-08-03  5:32               ` Jean-Christophe PLAGNIOL-VILLARD
2009-08-03  8:19                 ` Wolfgang Denk
2009-08-03 12:17                   ` Jean-Christophe PLAGNIOL-VILLARD
2009-08-03 14:35                     ` Wolfgang Denk
2009-08-05 10:09                       ` javier Martin
2009-08-05 12:30                         ` javier Martin
2009-08-05 12:45                           ` Wolfgang Denk
2009-08-05 14:17                             ` javier Martin
2009-08-05 14:21                               ` Wolfgang Denk
2009-08-05 15:01                                 ` javier Martin
2009-08-06 20:10                           ` Wolfgang Denk
2009-08-07  7:18                             ` javier Martin
2009-08-07  9:13                               ` Wolfgang Denk
2009-08-06 19:29                         ` [U-Boot] [PATCH] ARM EABI: add new helper functions resp. function names Wolfgang Denk
2009-08-08  6:50                           ` Dirk Behme
2009-08-08  7:16                             ` Wolfgang Denk
2009-08-08  7:39                               ` Dirk Behme
2009-08-09 21:28                           ` Wolfgang Denk
2009-08-10 22:32                 ` [U-Boot] [PATCH] imx27lite: add support for imx27lite board from LogicPD Ilya Yanok
2009-08-11 18:47                   ` Fabio Estevam
2009-08-11 19:12                     ` Ilya Yanok
2009-08-14  7:03                   ` Jean-Christophe PLAGNIOL-VILLARD
2009-08-26 20:14                     ` Wolfgang Denk
2009-08-26 20:43                       ` Scott Wood
2009-09-01 20:10                   ` Jean-Christophe PLAGNIOL-VILLARD
2009-06-28  9:52 ` [U-Boot] [PATCH 0/7][v3] Support for LogicPD i.MX27-LITEKIT development board Jean-Christophe PLAGNIOL-VILLARD
  -- strict thread matches above, loose matches on Subject: below --
2009-05-19 23:55 [U-Boot] [PATCH 00/10][v2] " Ilya Yanok
2009-05-19 23:55 ` [U-Boot] [PATCH 4/7] mxc_nand: add nand driver for MX2/MX3 Ilya Yanok
2009-05-28 23:06   ` Wolfgang Denk
2009-05-29  6:22     ` Magnus Lilja
2009-05-29  8:40       ` Wolfgang Denk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A605706.9020909@emcraft.com \
    --to=yanok@emcraft.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox