[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