
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@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@freescale.com,
Scott Wood <scottwood@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.