[U-Boot-Users] [PATCH 2/2] Freescale eLBC FCM NAND driver

Jean-Christophe PLAGNIOL-VILLARD plagnioj at jcrosoft.com
Tue Mar 25 17:49:36 CET 2008


On 12:53 Mon 24 Mar     , Scott Wood wrote:
> This is a driver for the Flash Control Machine of the enhanched Local Bus
> Controller found on some Freescale chips (such as the mpc8313 and the
> mpc8379).
> 
> Signed-off-by: Scott Wood <scottwood at freescale.com>
> ---
> This patch applies to the mtd-2.6.22.1 branch of the nand tree.
> 
>  drivers/mtd/nand/Makefile        |    1 +
>  drivers/mtd/nand/fsl_elbc_nand.c |  764 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 765 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mtd/nand/fsl_elbc_nand.c
> 
> diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
> index 244fa09..470f63f 100644
> --- a/drivers/mtd/nand/Makefile
> +++ b/drivers/mtd/nand/Makefile
> @@ -32,6 +32,7 @@ COBJS-y += nand_ecc.o
>  COBJS-y += nand_bbt.o
>  COBJS-y += nand_util.o
>  
> +COBJS-y += fsl_elbc_nand.o
>  COBJS-y += fsl_upm.o
>  
>  COBJS	:= $(COBJS-y)
> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
> new file mode 100644
> index 0000000..ceb3529
> --- /dev/null
> +++ b/drivers/mtd/nand/fsl_elbc_nand.c
> @@ -0,0 +1,764 @@
> +/* Freescale Enhanced Local Bus Controller FCM NAND driver
> + *
> + * Copyright (c) 2006-2008 Freescale Semiconductor
> + *
> + * Authors: Nick Spence <nick.spence at freescale.com>,
> + *          Scott Wood <scottwood at freescale.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + */
> +
> +#include <common.h>
> +
> +#if defined(CONFIG_CMD_NAND) && defined(CONFIG_NAND_FSL_ELBC)
Please move to the Makefile
> +
> +#include <malloc.h>
> +
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/nand.h>
> +#include <linux/mtd/nand_ecc.h>
> +
> +#include <asm/io.h>
> +#include <asm/errno.h>
> +
....
> +		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
> +		ctrl->index += column;
> +
> +		fsl_elbc_do_read(chip, 0);
> +		fsl_elbc_run_command(mtd);
> +		return;
> +
> +	/* READOOB reads only the OOB because no ECC is performed. */
> +	case NAND_CMD_READOOB:
> +		vdbg("fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
> +		     " 0x%x, column: 0x%x.\n", page_addr, column);
> +
> +		out_be32(&lbc->fbcr, mtd->oobsize - column);
> +		set_addr(mtd, column, page_addr, 1);
> +
> +		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
> +
> +		fsl_elbc_do_read(chip, 1);
> +		fsl_elbc_run_command(mtd);
> +		
   ^^^^^^^^^^^^^
WhiteSpace please remove
> +		return;
> +
> +	/* READID must read all 5 possible bytes while CEB is active */
> +	case NAND_CMD_READID:
> +		vdbg("fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
> +
> +		out_be32(&lbc->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) |
> +		                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
> +		                    (FIR_OP_RBW << FIR_OP2_SHIFT));
> +		out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
> +		/* 5 bytes for manuf, device and exts */
> +		out_be32(&lbc->fbcr, 5);
> +		ctrl->read_bytes = 5;
> +		ctrl->use_mdr = 1;
> +		ctrl->mdr = 0;
> +
> +		set_addr(mtd, 0, 0, 0);
> +		fsl_elbc_run_command(mtd);
> +		return;
> +
....
> +		printf("fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
> +		        command);
> +	}
> +}
> +
> +static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip)
> +{
> +	/* The hardware does not seem to support multiple
> +	 * chips per bank.
> +	 */
please use this comment style
/*
 * ...
 * ....
 */
> +}
> +
> +/*
> + * Write buf to the FCM Controller Data Buffer
> + */
> +static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
> +{
> +	struct nand_chip *chip = mtd->priv;
> +	struct fsl_elbc_mtd *priv = chip->priv;
> +	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	unsigned int bufsize = mtd->writesize + mtd->oobsize;
> +
....
> +
> +	for (i = 0; i < len; i++)
> +		if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
> +			break;
> +
> +	ctrl->index += len;
> +	return i == len && ctrl->status == LTESR_CC ? 0 : -EIO;
please use something like that to help the reading
	return ((i==len) && (ctrl->status==LTESR_CC))? 0 : -EIO;
> +}
> +
> +/* This function is called after Program and Erase Operations to
> + * check for success or failure.
> + */
Comment same as before
> +static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
> +{
> +	struct fsl_elbc_mtd *priv = chip->priv;
> +	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	lbus83xx_t *lbc = ctrl->regs;
> +
> +	if (ctrl->status != LTESR_CC)
> +		return NAND_STATUS_FAIL;
> +
> +	/* Use READ_STATUS command, but wait for the device to be ready */
> +	ctrl->use_mdr = 0;
> +	out_be32(&lbc->fir,
> +	         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
> +	         (FIR_OP_RBW << FIR_OP1_SHIFT));
> +	out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
> +	out_be32(&lbc->fbcr, 1);
> +	set_addr(mtd, 0, 0, 0);
> +	ctrl->read_bytes = 1;
> +
> +	fsl_elbc_run_command(mtd);
> +
> +	if (ctrl->status != LTESR_CC)
> +		return NAND_STATUS_FAIL;
> +
> +	/* The chip always seems to report that it is
> +	 * write-protected, even when it is not.
> +	 */
> +	out_8(ctrl->addr, in_8(ctrl->addr) | NAND_STATUS_WP);
> +	return fsl_elbc_read_byte(mtd);
> +}
> +
> +static int fsl_elbc_read_page(struct mtd_info *mtd,
> +                              struct nand_chip *chip,
> +                              uint8_t *buf)
> +{
> +	fsl_elbc_read_buf(mtd, buf, mtd->writesize);
> +	fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
> +
> +	if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL)
> +		mtd->ecc_stats.failed++;
> +
> +	return 0;
> +}
> +
> +/* ECC will be calculated automatically, and errors will be detected in
> + * waitfunc.
> + */
Comment same as before
> +static void fsl_elbc_write_page(struct mtd_info *mtd,
> +                                struct nand_chip *chip,
> +                                const uint8_t *buf)
> +{
> +	struct fsl_elbc_mtd *priv = chip->priv;
> +	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +
> +	fsl_elbc_write_buf(mtd, buf, mtd->writesize);
> +	fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
> +
> +	ctrl->oob_poi = chip->oob_poi;
> +}
> +
> +static struct fsl_elbc_ctrl *elbc_ctrl;
> +
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->ctrl = elbc_ctrl;
> +	priv->vbase = nand->IO_ADDR_R;
> +
> +	/* Find which chip select it is connected to.  It'd be nice
> +	 * if we could pass more than one datum to the NAND driver...
> +	 */
Comment same as before
> +	for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) {
> +		br = in_be32(&elbc_ctrl->regs->bank[priv->bank].br);
> +		or = in_be32(&elbc_ctrl->regs->bank[priv->bank].or);
> +
> +		if ((br & BR_V) && (br & BR_MSEL) == BR_MS_FCM &&
> +		    (br & or & BR_BA) == (phys_addr_t)nand->IO_ADDR_R)
> +			break;
> +	}
> +
> +	if (priv->bank >= MAX_BANKS) {
> +		printf("fsl_elbc_nand: address did not match any "
> +		       "chip selects\n");
> +		return -ENODEV;
> +	}
> +
> +	elbc_ctrl->chips[priv->bank] = priv;
> +
Please check all comments.

Best Regards,
J.




More information about the U-Boot mailing list