[U-Boot] [PATCH v3] Freescale NFC NAND driver

Scott Wood scottwood at freescale.com
Thu Nov 6 00:06:48 CET 2008


On Tue, Nov 04, 2008 at 07:02:41PM -0700, John Rigby wrote:
> +#define MIN(x, y)		((x < y) ? x : y)

Please use the min() macro defined in include/common.h.

> +static struct fsl_nfc_private {
> +	struct mtd_info mtd;
> +	char spare_only;
> +	char status_req;
> +	u16 col_addr;
> +	int writesize;
> +	int sparesize;
> +	int width;
> +	int chipsel;
> +} *priv;

Is it plausable that there will ever be a chip with more than one of
these controllers?

> +/*
> + * OOB placement block for use with hardware ecc generation
> + */
> +static struct nand_ecclayout nand_hw_eccoob_512 = {
> +	.eccbytes = 9,
> +	.eccpos = {
> +		7, 8, 9, 10, 11, 12, 13, 14, 15,
> +	},
> +	.oobfree = {
> +		{0, 5} /* byte 5 is factory bad block marker */
> +	},
> +};

Is byte 6 free?

> +static struct nand_ecclayout nand_hw_eccoob_4k_218_spare = {
> +	.eccbytes = 64,	/* actually 144 but only room for 64 */
> +	.eccpos = {
> +		/* 18 bytes of ecc for each 512 bytes of data */
> +		7, 8, 9, 10, 11, 12, 13, 14, 15,
> +		    16, 17, 18, 19, 20, 21, 22, 23, 24,
> +		33, 34, 35, 36, 37, 38, 39, 40, 41,
> +		    42, 43, 44, 45, 46, 47, 48, 49, 50,
> +		59, 60, 61, 62, 63, 64, 65, 66, 67,
> +		    68, 69, 70, 71, 72, 73, 74, 75, 76,
> +		85, 86, 87, 88, 89, 90, 91, 92, 93,
> +		    94, /* 95, 96, 97, 98, 99, 100, 101, 102,
> +		111, 112, 113, 114, 115, 116, 117, 118, 119,
> +		    120, 121, 122, 123, 124, 125, 126, 127, 128,
> +		137, 138, 139, 140, 141, 142, 143, 144, 145,
> +		    146, 147, 148, 149, 150, 151, 152, 153, 154,
> +		163, 164, 165, 166, 167, 168, 169, 170, 171,
> +		    172, 173, 174, 175, 176, 177, 178, 179, 180,
> +		189, 190, 191, 192, 193, 194, 195, 196, 197,
> +		    198, 199, 200, 201, 202, 203, 204, 205, 206, */
> +	},
> +	.oobfree = {
> +		{2, 5}, /* bytes 0 and 1 are factory bad block markers */
> +		{25, 8},
> +		{51, 8},
> +		{77, 8},
> +		{103, 8},
> +		{129, 8},
> +		{155, 8},
> +		{181, 8},
> +	},
> +};

Need to change NAND_MAX_OOBSIZE.

> +/*!
> + * This function polls the NFC to wait for the basic operation to complete by
> + * checking the INT bit of config2 register.
> + *
> + * @max_retries	number of retry attempts (separated by 1 us)
> + */
> +static void wait_op_done(int max_retries)
> +{
> +

No blank line here.

> +	}
> +	if (max_retries <= 0)

Blank line between the last two.

> +static void fsl_nfc_enable_hwecc(struct mtd_info *mtd, int mode)
> +{
> +	NFC_WRITEW(NFC_CONFIG1, (NFC_READW(NFC_CONFIG1) | NFC_ECC_EN));
> +	return;
> +}

Unnecessary "return" keyword.

> +/*!
> + * This function writes data of length \b len from buffer \b buf to the NAND
> + * internal RAM buffer's MAIN area 0.
> + *
> + * @mtd		MTD structure for the NAND Flash
> + * @buf		data to be written to NAND Flash
> + * @len		number of bytes to be written
> + */
> +static void fsl_nfc_write_buf(struct mtd_info *mtd,
> +					const u_char *buf, int len)
> +{
> +	if (priv->col_addr >= mtd->writesize || priv->spare_only) {
> +		copy_to_spare(mtd, (char *)buf, len);
> +		return;
> +	} else {
> +		priv->col_addr += len;
> +		memcpy_toio(MAIN_AREA(0), (void *)buf, len);
> +	}
> +}

What if both main and spare areas are written at once?

Also, rewrite

if (...) {
	foo;
	return;
} else {
	bar;
}

as:

if (...) {
	foo;
	return;
}

bar;

or

if (...)
	foo;
else
	bar;


> +#ifndef CONFIG_FSL_NFC_BOARD_CS_FUNC
> +static void fsl_nfc_select_chip(u8 cs)
> +{
> +	u32 val = NFC_READW(NFC_BUF_ADDR);
> +
> +	val &= ~0x60;
> +	val |= cs << 5;
> +	NFC_WRITEW(NFC_BUF_ADDR, val);
> +}
> +#define CONFIG_FSL_NFC_BOARD_CS_FUNC fsl_nfc_select_chip
> +#endif
> +
> +
> +/*!
> + * This function is used by upper layer for select and deselect of the NAND
> + * chip
> + *
> + * @mtd		MTD structure for the NAND Flash
> + * @chip	val indicating select or deselect
> + */
> +static void fsl_nfc_select_chip(struct mtd_info *mtd, int chip)

This looks like a compilation error if CONFIG_FSL_NFC_BOARD_CS_FUNC is
not defined.

> +/*
> + * Function to read a page from nand device.
> + */
> +static void read_full_page(struct mtd_info *mtd, int page_addr)
> +{
> +	send_cmd(NAND_CMD_READ0);
> +
> +	fsl_nfc_do_addr_cycle(mtd, 0, page_addr);
> +
> +	if (IS_LARGE_PAGE_NAND) {
> +		send_cmd(NAND_CMD_READSTART);
> +		send_read_page(0);
> +	} else {
> +		send_read_page(0);
> +	}
> +}

Factor out the send_read_page(0);

> +	case NAND_CMD_READOOB:
> +		priv->col_addr = column;
> +		priv->spare_only = 1;
> +		command = NAND_CMD_READ0;	/* only READ0 is valid */
> +		break;

What about small-page flash that takes an actual READOOB command?

> +static int fsl_nfc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
> +				int page, int sndcmd)
> +{
> +	if (sndcmd) {
> +		read_full_page(mtd, page);
> +		sndcmd = 0;
> +	}
> +
> +	copy_from_spare(mtd, chip->oob_poi, mtd->oobsize);
> +	return sndcmd;
> +}
> +
> +static int fsl_nfc_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
> +					int page)
> +{
> +	int status = 0;
> +	int read_oob_col = 0;
> +
> +	send_cmd(NAND_CMD_READ0);
> +	send_cmd(NAND_CMD_SEQIN);
> +	fsl_nfc_do_addr_cycle(mtd, read_oob_col, page);
> +
> +	/* copy the oob data */
> +	copy_to_spare(mtd, chip->oob_poi, mtd->oobsize);
> +
> +	send_prog_page(0);
> +
> +	send_cmd(NAND_CMD_PAGEPROG);
> +
> +	status = fsl_nfc_wait(mtd, chip);
> +	if (status & NAND_STATUS_FAIL)
> +		return -1;
> +	return 0;
> +}

Again, I'm fairly sure you don't need these if the other functions are
defined properly.

> +/*
> + * These are identical to the generic versions except
> + * for the offsets.
> + */
> +static struct nand_bbt_descr bbt_main_descr = {
> +	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
> +	    | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
> +	.offs = 0,
> +	.len = 4,
> +	.veroffs = 4,
> +	.maxblocks = 4,
> +	.pattern = bbt_pattern
> +};
> +
> +static struct nand_bbt_descr bbt_mirror_descr = {
> +	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
> +	    | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
> +	.offs = 0,
> +	.len = 4,
> +	.veroffs = 4,
> +	.maxblocks = 4,
> +	.pattern = mirror_pattern
> +};

This will overlap the bad block marker on large-page flash.

-Scott


More information about the U-Boot mailing list