diff options
Diffstat (limited to 'drivers/mtd/nand/raw/fsl_ifc_nand.c')
| -rw-r--r-- | drivers/mtd/nand/raw/fsl_ifc_nand.c | 83 |
1 files changed, 39 insertions, 44 deletions
diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c index e65d274399f9..7be95d0be248 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c @@ -1,26 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Freescale Integrated Flash Controller NAND driver * * Copyright 2011-2012 Freescale Semiconductor, Inc * * Author: Dipen Dudhat <Dipen.Dudhat@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 <linux/module.h> +#include <linux/platform_device.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/of_address.h> @@ -28,13 +16,12 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/rawnand.h> #include <linux/mtd/partitions.h> -#include <linux/mtd/nand_ecc.h> #include <linux/fsl_ifc.h> #include <linux/iopoll.h> #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ -#define IFC_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait +#define IFC_TIMEOUT_MSECS 1000 /* Maximum timeout to wait for IFC NAND Machine */ struct fsl_ifc_ctrl; @@ -322,7 +309,7 @@ static void fsl_ifc_cmdfunc(struct nand_chip *chip, unsigned int command, ifc_nand_ctrl->read_bytes = mtd->writesize + mtd->oobsize; ifc_nand_ctrl->index += column; - if (chip->ecc.mode == NAND_ECC_HW) + if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) ifc_nand_ctrl->eccread = 1; fsl_ifc_do_read(chip, 0, mtd); @@ -720,11 +707,35 @@ static int fsl_ifc_attach_chip(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); struct fsl_ifc_mtd *priv = nand_get_controller_data(chip); + struct fsl_ifc_ctrl *ctrl = priv->ctrl; + struct fsl_ifc_global __iomem *ifc_global = ctrl->gregs; + u32 csor; + + csor = ifc_in32(&ifc_global->csor_cs[priv->bank].csor); + + /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */ + if (csor & CSOR_NAND_ECC_DEC_EN) { + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; + mtd_set_ooblayout(mtd, &fsl_ifc_ooblayout_ops); + + /* Hardware generates ECC per 512 Bytes */ + chip->ecc.size = 512; + if ((csor & CSOR_NAND_ECC_MODE_MASK) == CSOR_NAND_ECC_MODE_4) { + chip->ecc.bytes = 8; + chip->ecc.strength = 4; + } else { + chip->ecc.bytes = 16; + chip->ecc.strength = 8; + } + } else { + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; + } dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__, - chip->numchips); + nanddev_ntargets(&chip->base)); dev_dbg(priv->dev, "%s: nand->chipsize = %lld\n", __func__, - chip->chipsize); + nanddev_target_size(&chip->base)); dev_dbg(priv->dev, "%s: nand->pagemask = %8x\n", __func__, chip->pagemask); dev_dbg(priv->dev, "%s: nand->legacy.chip_delay = %d\n", __func__, @@ -737,8 +748,8 @@ static int fsl_ifc_attach_chip(struct nand_chip *chip) chip->page_shift); dev_dbg(priv->dev, "%s: nand->phys_erase_shift = %d\n", __func__, chip->phys_erase_shift); - dev_dbg(priv->dev, "%s: nand->ecc.mode = %d\n", __func__, - chip->ecc.mode); + dev_dbg(priv->dev, "%s: nand->ecc.engine_type = %d\n", __func__, + chip->ecc.engine_type); dev_dbg(priv->dev, "%s: nand->ecc.steps = %d\n", __func__, chip->ecc.steps); dev_dbg(priv->dev, "%s: nand->ecc.bytes = %d\n", __func__, @@ -923,25 +934,6 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) return -ENODEV; } - /* Must also set CSOR_NAND_ECC_ENC_EN if DEC_EN set */ - if (csor & CSOR_NAND_ECC_DEC_EN) { - chip->ecc.mode = NAND_ECC_HW; - mtd_set_ooblayout(mtd, &fsl_ifc_ooblayout_ops); - - /* Hardware generates ECC per 512 Bytes */ - chip->ecc.size = 512; - if ((csor & CSOR_NAND_ECC_MODE_MASK) == CSOR_NAND_ECC_MODE_4) { - chip->ecc.bytes = 8; - chip->ecc.strength = 4; - } else { - chip->ecc.bytes = 16; - chip->ecc.strength = 8; - } - } else { - chip->ecc.mode = NAND_ECC_SOFT; - chip->ecc.algo = NAND_ECC_HAMMING; - } - ret = fsl_ifc_sram_init(priv); if (ret) return ret; @@ -1103,11 +1095,16 @@ err: return ret; } -static int fsl_ifc_nand_remove(struct platform_device *dev) +static void fsl_ifc_nand_remove(struct platform_device *dev) { struct fsl_ifc_mtd *priv = dev_get_drvdata(&dev->dev); + struct nand_chip *chip = &priv->chip; + int ret; + + ret = mtd_device_unregister(nand_to_mtd(chip)); + WARN_ON(ret); + nand_cleanup(chip); - nand_release(&priv->chip); fsl_ifc_chip_remove(priv); mutex_lock(&fsl_ifc_nand_mutex); @@ -1117,8 +1114,6 @@ static int fsl_ifc_nand_remove(struct platform_device *dev) kfree(ifc_nand_ctrl); } mutex_unlock(&fsl_ifc_nand_mutex); - - return 0; } static const struct of_device_id fsl_ifc_nand_match[] = { |
