Commit 76dc2bfc authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mtd/fixes-for-5.10-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux

Pull mtd fixes from Miquel Raynal:
 "Because of a recent change in the core, NAND controller drivers
  initializing the ECC engine too early in the probe path are broken.

  Drivers should wait for the NAND device to be discovered and its
  memory layout known before doing any ECC related initialization, so
  instead of reverting the faulty change which is actually moving in the
  right direction, let's fix the drivers directly: socrates, sharpsl,
  r852, plat_nand, pasemi, tmio, txx9ndfmc, orion, mpc5121, lpc32xx_slc,
  lpc32xx_mlc, fsmc, diskonchip, davinci, cs553x, au1550, ams-delta,
  xway and gpio"

* tag 'mtd/fixes-for-5.10-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux:
  mtd: rawnand: socrates: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: sharpsl: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: r852: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: plat_nand: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: pasemi: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: tmio: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: txx9ndfmc: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: orion: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: mpc5121: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: lpc32xx_slc: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: lpc32xx_mlc: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: fsmc: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: diskonchip: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: davinci: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: cs553x: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: au1550: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: ams-delta: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: xway: Move the ECC initialization to ->attach_chip()
  mtd: rawnand: gpio: Move the ECC initialization to ->attach_chip()
parents 87c301ca b36bf0a0
......@@ -215,8 +215,17 @@ static int gpio_nand_setup_interface(struct nand_chip *this, int csline,
return 0;
}
static int gpio_nand_attach_chip(struct nand_chip *chip)
{
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
return 0;
}
static const struct nand_controller_ops gpio_nand_ops = {
.exec_op = gpio_nand_exec_op,
.attach_chip = gpio_nand_attach_chip,
.setup_interface = gpio_nand_setup_interface,
};
......@@ -260,9 +269,6 @@ static int gpio_nand_probe(struct platform_device *pdev)
return err;
}
this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
this->ecc.algo = NAND_ECC_ALGO_HAMMING;
platform_set_drvdata(pdev, priv);
/* Set chip enabled but write protected */
......
......@@ -236,8 +236,17 @@ static int au1550nd_exec_op(struct nand_chip *this,
return ret;
}
static int au1550nd_attach_chip(struct nand_chip *chip)
{
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
return 0;
}
static const struct nand_controller_ops au1550nd_ops = {
.exec_op = au1550nd_exec_op,
.attach_chip = au1550nd_attach_chip,
};
static int au1550nd_probe(struct platform_device *pdev)
......@@ -294,8 +303,6 @@ static int au1550nd_probe(struct platform_device *pdev)
nand_controller_init(&ctx->controller);
ctx->controller.ops = &au1550nd_ops;
this->controller = &ctx->controller;
this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
this->ecc.algo = NAND_ECC_ALGO_HAMMING;
if (pd->devwidth)
this->options |= NAND_BUSWIDTH_16;
......
......@@ -243,8 +243,24 @@ static int cs_calculate_ecc(struct nand_chip *this, const u_char *dat,
static struct cs553x_nand_controller *controllers[4];
static int cs553x_attach_chip(struct nand_chip *chip)
{
if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
return 0;
chip->ecc.size = 256;
chip->ecc.bytes = 3;
chip->ecc.hwctl = cs_enable_hwecc;
chip->ecc.calculate = cs_calculate_ecc;
chip->ecc.correct = nand_correct_data;
chip->ecc.strength = 1;
return 0;
}
static const struct nand_controller_ops cs553x_nand_controller_ops = {
.exec_op = cs553x_exec_op,
.attach_chip = cs553x_attach_chip,
};
static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
......@@ -286,14 +302,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
goto out_mtd;
}
this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
this->ecc.size = 256;
this->ecc.bytes = 3;
this->ecc.hwctl = cs_enable_hwecc;
this->ecc.calculate = cs_calculate_ecc;
this->ecc.correct = nand_correct_data;
this->ecc.strength = 1;
/* Enable the following for a flash based bad block table */
this->bbt_options = NAND_BBT_USE_FLASH;
......
......@@ -585,6 +585,10 @@ static int davinci_nand_attach_chip(struct nand_chip *chip)
if (IS_ERR(pdata))
return PTR_ERR(pdata);
/* Use board-specific ECC config */
info->chip.ecc.engine_type = pdata->engine_type;
info->chip.ecc.placement = pdata->ecc_placement;
switch (info->chip.ecc.engine_type) {
case NAND_ECC_ENGINE_TYPE_NONE:
pdata->ecc_bits = 0;
......@@ -850,10 +854,6 @@ static int nand_davinci_probe(struct platform_device *pdev)
info->mask_ale = pdata->mask_ale ? : MASK_ALE;
info->mask_cle = pdata->mask_cle ? : MASK_CLE;
/* Use board-specific ECC config */
info->chip.ecc.engine_type = pdata->engine_type;
info->chip.ecc.placement = pdata->ecc_placement;
spin_lock_irq(&davinci_nand_lock);
/* put CSxNAND into NAND mode */
......
......@@ -1269,12 +1269,31 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
return 1;
}
static int doc200x_attach_chip(struct nand_chip *chip)
{
if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
return 0;
chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED;
chip->ecc.size = 512;
chip->ecc.bytes = 6;
chip->ecc.strength = 2;
chip->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
chip->ecc.hwctl = doc200x_enable_hwecc;
chip->ecc.calculate = doc200x_calculate_ecc;
chip->ecc.correct = doc200x_correct_data;
return 0;
}
static const struct nand_controller_ops doc200x_ops = {
.exec_op = doc200x_exec_op,
.attach_chip = doc200x_attach_chip,
};
static const struct nand_controller_ops doc2001plus_ops = {
.exec_op = doc2001plus_exec_op,
.attach_chip = doc200x_attach_chip,
};
static int __init doc_probe(unsigned long physadr)
......@@ -1452,16 +1471,6 @@ static int __init doc_probe(unsigned long physadr)
nand->controller = &doc->base;
nand_set_controller_data(nand, doc);
nand->ecc.hwctl = doc200x_enable_hwecc;
nand->ecc.calculate = doc200x_calculate_ecc;
nand->ecc.correct = doc200x_correct_data;
nand->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
nand->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED;
nand->ecc.size = 512;
nand->ecc.bytes = 6;
nand->ecc.strength = 2;
nand->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
nand->bbt_options = NAND_BBT_USE_FLASH;
/* Skip the automatic BBT scan so we can run it manually */
nand->options |= NAND_SKIP_BBTSCAN | NAND_NO_BBM_QUIRK;
......
......@@ -880,6 +880,20 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand)
struct mtd_info *mtd = nand_to_mtd(nand);
struct fsmc_nand_data *host = nand_to_fsmc(nand);
if (nand->ecc.engine_type == NAND_ECC_ENGINE_TYPE_INVALID)
nand->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
if (!nand->ecc.size)
nand->ecc.size = 512;
if (AMBA_REV_BITS(host->pid) >= 8) {
nand->ecc.read_page = fsmc_read_page_hwecc;
nand->ecc.calculate = fsmc_read_hwecc_ecc4;
nand->ecc.correct = fsmc_bch8_correct_data;
nand->ecc.bytes = 13;
nand->ecc.strength = 8;
}
if (AMBA_REV_BITS(host->pid) >= 8) {
switch (mtd->oobsize) {
case 16:
......@@ -905,6 +919,7 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand)
dev_info(host->dev, "Using 1-bit HW ECC scheme\n");
nand->ecc.calculate = fsmc_read_hwecc_ecc1;
nand->ecc.correct = nand_correct_data;
nand->ecc.hwctl = fsmc_enable_hwecc;
nand->ecc.bytes = 3;
nand->ecc.strength = 1;
nand->ecc.options |= NAND_ECC_SOFT_HAMMING_SM_ORDER;
......@@ -1055,13 +1070,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
mtd->dev.parent = &pdev->dev;
/*
* Setup default ECC mode. nand_dt_init() called from nand_scan_ident()
* can overwrite this value if the DT provides a different value.
*/
nand->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
nand->ecc.hwctl = fsmc_enable_hwecc;
nand->ecc.size = 512;
nand->badblockbits = 7;
if (host->mode == USE_DMA_ACCESS) {
......@@ -1084,14 +1092,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
nand->options |= NAND_KEEP_TIMINGS;
}
if (AMBA_REV_BITS(host->pid) >= 8) {
nand->ecc.read_page = fsmc_read_page_hwecc;
nand->ecc.calculate = fsmc_read_hwecc_ecc4;
nand->ecc.correct = fsmc_bch8_correct_data;
nand->ecc.bytes = 13;
nand->ecc.strength = 8;
}
nand_controller_init(&host->base);
host->base.ops = &fsmc_nand_controller_ops;
nand->controller = &host->base;
......
......@@ -161,8 +161,17 @@ static int gpio_nand_exec_op(struct nand_chip *chip,
return ret;
}
static int gpio_nand_attach_chip(struct nand_chip *chip)
{
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
return 0;
}
static const struct nand_controller_ops gpio_nand_ops = {
.exec_op = gpio_nand_exec_op,
.attach_chip = gpio_nand_attach_chip,
};
#ifdef CONFIG_OF
......@@ -342,8 +351,6 @@ static int gpio_nand_probe(struct platform_device *pdev)
gpiomtd->base.ops = &gpio_nand_ops;
nand_set_flash_node(chip, pdev->dev.of_node);
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
chip->options = gpiomtd->plat.options;
chip->controller = &gpiomtd->base;
......
......@@ -648,6 +648,9 @@ static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
struct device *dev = &host->pdev->dev;
if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
return 0;
host->dma_buf = devm_kzalloc(dev, mtd->writesize, GFP_KERNEL);
if (!host->dma_buf)
return -ENOMEM;
......@@ -656,8 +659,17 @@ static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
if (!host->dummy_buf)
return -ENOMEM;
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
chip->ecc.size = 512;
chip->ecc.hwctl = lpc32xx_ecc_enable;
chip->ecc.read_page_raw = lpc32xx_read_page;
chip->ecc.read_page = lpc32xx_read_page;
chip->ecc.write_page_raw = lpc32xx_write_page_lowlevel;
chip->ecc.write_page = lpc32xx_write_page_lowlevel;
chip->ecc.write_oob = lpc32xx_write_oob;
chip->ecc.read_oob = lpc32xx_read_oob;
chip->ecc.strength = 4;
chip->ecc.bytes = 10;
mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops);
host->mlcsubpages = mtd->writesize / 512;
......@@ -741,15 +753,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, host);
/* Initialize function pointers */
nand_chip->ecc.hwctl = lpc32xx_ecc_enable;
nand_chip->ecc.read_page_raw = lpc32xx_read_page;
nand_chip->ecc.read_page = lpc32xx_read_page;
nand_chip->ecc.write_page_raw = lpc32xx_write_page_lowlevel;
nand_chip->ecc.write_page = lpc32xx_write_page_lowlevel;
nand_chip->ecc.write_oob = lpc32xx_write_oob;
nand_chip->ecc.read_oob = lpc32xx_read_oob;
nand_chip->ecc.strength = 4;
nand_chip->ecc.bytes = 10;
nand_chip->legacy.waitfunc = lpc32xx_waitfunc;
nand_chip->options = NAND_NO_SUBPAGE_WRITE;
......
......@@ -775,6 +775,9 @@ static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
struct mtd_info *mtd = nand_to_mtd(chip);
struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
return 0;
/* OOB and ECC CPU and DMA work areas */
host->ecc_buf = (uint32_t *)(host->data_buf + LPC32XX_DMA_DATA_SIZE);
......@@ -786,11 +789,22 @@ static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
if (mtd->writesize <= 512)
mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops);
chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED;
/* These sizes remain the same regardless of page size */
chip->ecc.size = 256;
chip->ecc.strength = 1;
chip->ecc.bytes = LPC32XX_SLC_DEV_ECC_BYTES;
chip->ecc.prepad = 0;
chip->ecc.postpad = 0;
chip->ecc.read_page_raw = lpc32xx_nand_read_page_raw_syndrome;
chip->ecc.read_page = lpc32xx_nand_read_page_syndrome;
chip->ecc.write_page_raw = lpc32xx_nand_write_page_raw_syndrome;
chip->ecc.write_page = lpc32xx_nand_write_page_syndrome;
chip->ecc.write_oob = lpc32xx_nand_write_oob_syndrome;
chip->ecc.read_oob = lpc32xx_nand_read_oob_syndrome;
chip->ecc.calculate = lpc32xx_nand_ecc_calculate;
chip->ecc.correct = nand_correct_data;
chip->ecc.hwctl = lpc32xx_nand_ecc_enable;
/*
* Use a custom BBT marker setup for small page FLASH that
......@@ -881,21 +895,9 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, host);
/* NAND callbacks for LPC32xx SLC hardware */
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED;
chip->legacy.read_byte = lpc32xx_nand_read_byte;
chip->legacy.read_buf = lpc32xx_nand_read_buf;
chip->legacy.write_buf = lpc32xx_nand_write_buf;
chip->ecc.read_page_raw = lpc32xx_nand_read_page_raw_syndrome;
chip->ecc.read_page = lpc32xx_nand_read_page_syndrome;
chip->ecc.write_page_raw = lpc32xx_nand_write_page_raw_syndrome;
chip->ecc.write_page = lpc32xx_nand_write_page_syndrome;
chip->ecc.write_oob = lpc32xx_nand_write_oob_syndrome;
chip->ecc.read_oob = lpc32xx_nand_read_oob_syndrome;
chip->ecc.calculate = lpc32xx_nand_ecc_calculate;
chip->ecc.correct = nand_correct_data;
chip->ecc.strength = 1;
chip->ecc.hwctl = lpc32xx_nand_ecc_enable;
/*
* Allocate a large enough buffer for a single huge page plus
......
......@@ -104,6 +104,7 @@
#define NFC_TIMEOUT (HZ / 10) /* 1/10 s */
struct mpc5121_nfc_prv {
struct nand_controller controller;
struct nand_chip chip;
int irq;
void __iomem *regs;
......@@ -602,6 +603,18 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
iounmap(prv->csreg);
}
static int mpc5121_nfc_attach_chip(struct nand_chip *chip)
{
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
return 0;
}
static const struct nand_controller_ops mpc5121_nfc_ops = {
.attach_chip = mpc5121_nfc_attach_chip,
};
static int mpc5121_nfc_probe(struct platform_device *op)
{
struct device_node *dn = op->dev.of_node;
......@@ -634,6 +647,10 @@ static int mpc5121_nfc_probe(struct platform_device *op)
chip = &prv->chip;
mtd = nand_to_mtd(chip);
nand_controller_init(&prv->controller);
prv->controller.ops = &mpc5121_nfc_ops;
chip->controller = &prv->controller;
mtd->dev.parent = dev;
nand_set_controller_data(chip, prv);
nand_set_flash_node(chip, dn);
......@@ -688,8 +705,6 @@ static int mpc5121_nfc_probe(struct platform_device *op)
chip->legacy.set_features = nand_get_set_features_notsupp;
chip->legacy.get_features = nand_get_set_features_notsupp;
chip->bbt_options = NAND_BBT_USE_FLASH;
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
/* Support external chip-select logic on ADS5121 board */
if (of_machine_is_compatible("fsl,mpc5121ads")) {
......
......@@ -22,6 +22,7 @@
#include <linux/platform_data/mtd-orion_nand.h>
struct orion_nand_info {
struct nand_controller controller;
struct nand_chip chip;
struct clk *clk;
};
......@@ -82,6 +83,18 @@ static void orion_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
buf[i++] = readb(io_base);
}
static int orion_nand_attach_chip(struct nand_chip *chip)
{
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
return 0;
}
static const struct nand_controller_ops orion_nand_ops = {
.attach_chip = orion_nand_attach_chip,
};
static int __init orion_nand_probe(struct platform_device *pdev)
{
struct orion_nand_info *info;
......@@ -101,6 +114,10 @@ static int __init orion_nand_probe(struct platform_device *pdev)
nc = &info->chip;
mtd = nand_to_mtd(nc);
nand_controller_init(&info->controller);
info->controller.ops = &orion_nand_ops;
nc->controller = &info->controller;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
io_base = devm_ioremap_resource(&pdev->dev, res);
......@@ -139,8 +156,6 @@ static int __init orion_nand_probe(struct platform_device *pdev)
nc->legacy.IO_ADDR_R = nc->legacy.IO_ADDR_W = io_base;
nc->legacy.cmd_ctrl = orion_nand_cmd_ctrl;
nc->legacy.read_buf = orion_nand_read_buf;
nc->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
nc->ecc.algo = NAND_ECC_ALGO_HAMMING;
if (board->chip_delay)
nc->legacy.chip_delay = board->chip_delay;
......
......@@ -29,6 +29,7 @@
static unsigned int lpcctl;
static struct mtd_info *pasemi_nand_mtd;
static struct nand_controller controller;
static const char driver_name[] = "pasemi-nand";
static void pasemi_read_buf(struct nand_chip *chip, u_char *buf, int len)
......@@ -73,6 +74,18 @@ static int pasemi_device_ready(struct nand_chip *chip)
return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR);
}
static int pasemi_attach_chip(struct nand_chip *chip)
{
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
return 0;
}
static const struct nand_controller_ops pasemi_ops = {
.attach_chip = pasemi_attach_chip,
};
static int pasemi_nand_probe(struct platform_device *ofdev)
{
struct device *dev = &ofdev->dev;
......@@ -100,6 +113,10 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
goto out;
}
controller.ops = &pasemi_ops;
nand_controller_init(&controller);
chip->controller = &controller;
pasemi_nand_mtd = nand_to_mtd(chip);
/* Link the private data with the MTD structure */
......@@ -132,8 +149,6 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
chip->legacy.read_buf = pasemi_read_buf;
chip->legacy.write_buf = pasemi_write_buf;
chip->legacy.chip_delay = 0;
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
/* Enable the following for a flash based bad block table */
chip->bbt_options = NAND_BBT_USE_FLASH;
......
......@@ -14,10 +14,23 @@
#include <linux/mtd/platnand.h>
struct plat_nand_data {
struct nand_controller controller;
struct nand_chip chip;
void __iomem *io_base;
};
static int plat_nand_attach_chip(struct nand_chip *chip)
{
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
return 0;
}
static const struct nand_controller_ops plat_nand_ops = {
.attach_chip = plat_nand_attach_chip,
};
/*
* Probe for the NAND device.
*/
......@@ -46,6 +59,10 @@ static int plat_nand_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
data->controller.ops = &plat_nand_ops;
nand_controller_init(&data->controller);
data->chip.controller = &data->controller;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->io_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(data->io_base))
......@@ -66,9 +83,6 @@ static int plat_nand_probe(struct platform_device *pdev)
data->chip.options |= pdata->chip.options;
data->chip.bbt_options |= pdata->chip.bbt_options;
data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
data->chip.ecc.algo = NAND_ECC_ALGO_HAMMING;
platform_set_drvdata(pdev, data);
/* Handle any platform specific setup */
......
......@@ -817,6 +817,29 @@ static irqreturn_t r852_irq(int irq, void *data)
return ret;
}
static int r852_attach_chip(struct nand_chip *chip)
{
if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
return 0;
chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED;
chip->ecc.size = R852_DMA_LEN;
chip->ecc.bytes = SM_OOB_SIZE;
chip->ecc.strength = 2;
chip->ecc.hwctl = r852_ecc_hwctl;
chip->ecc.calculate = r852_ecc_calculate;
chip->ecc.correct = r852_ecc_correct;
/* TODO: hack */
chip->ecc.read_oob = r852_read_oob;
return 0;
}
static const struct nand_controller_ops r852_ops = {
.attach_chip = r852_attach_chip,
};
static int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
{
int error;
......@@ -858,19 +881,6 @@ static int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
chip->legacy.read_buf = r852_read_buf;
chip->legacy.write_buf = r852_write_buf;
/* ecc */
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED;
chip->ecc.size = R852_DMA_LEN;
chip->ecc.bytes = SM_OOB_SIZE;
chip->ecc.strength = 2;
chip->ecc.hwctl = r852_ecc_hwctl;
chip->ecc.calculate = r852_ecc_calculate;
chip->ecc.correct = r852_ecc_correct;
/* TODO: hack */
chip->ecc.read_oob = r852_read_oob;
/* init our device structure */
dev = kzalloc(sizeof(struct r852_device), GFP_KERNEL);
......@@ -882,6 +892,10 @@ static int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
dev->pci_dev = pci_dev;
pci_set_drvdata(pci_dev, dev);
nand_controller_init(&dev->controller);
dev->controller.ops = &r852_ops;
chip->controller = &dev->controller;
dev->bounce_buffer = dma_alloc_coherent(&pci_dev->dev, R852_DMA_LEN,
&dev->phys_bounce_buffer, GFP_KERNEL);
......
......@@ -104,6 +104,7 @@
#define DMA_MEMORY 1
struct r852_device {
struct nand_controller controller;
void __iomem *mmio; /* mmio */
struct nand_chip *chip; /* nand chip backpointer */
struct pci_dev *pci_dev; /* pci backpointer */
......
......@@ -20,6 +20,7 @@
#include <linux/io.h>
struct sharpsl_nand {
struct nand_controller controller;
struct nand_chip chip;
void __iomem *io;
......@@ -96,6 +97,25 @@ static int sharpsl_nand_calculate_ecc(struct nand_chip *chip,
return readb(sharpsl->io + ECCCNTR) != 0;
}
static int sharpsl_attach_chip(struct nand_chip *chip)
{
if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
return 0;
chip->ecc.size = 256;
chip->ecc.bytes = 3;
chip->ecc.strength = 1;
chip->ecc.hwctl = sharpsl_nand_enable_hwecc;
chip->ecc.calculate = sharpsl_nand_calculate_ecc;
chip->ecc.correct = nand_correct_data;
return 0;
}
static const struct nand_controller_ops sharpsl_ops = {
.attach_chip = sharpsl_attach_chip,
};
/*
* Main initialization routine
*/
......@@ -136,6 +156,10 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
/* Get pointer to private data */
this = (struct nand_chip *)(&sharpsl->chip);
nand_controller_init(&sharpsl->controller);
sharpsl->controller.ops = &sharpsl_ops;
this->controller = &sharpsl->controller;
/* Link the private data with the MTD structure */
mtd = nand_to_mtd(this);
mtd->dev.parent = &pdev->dev;
......@@ -156,15 +180,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
this->legacy.dev_ready = sharpsl_nand_dev_ready;
/* 15 us command delay time */
this->legacy.chip_delay = 15;
/* set eccmode using hardware ECC */
this->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
this->ecc.size = 256;
this->ecc.bytes = 3;
this->ecc.strength = 1;
this->badblock_pattern = data->badblock_pattern;
this->ecc.hwctl = sharpsl_nand_enable_hwecc;
this->ecc.calculate = sharpsl_nand_calculate_ecc;
this->ecc.correct = nand_correct_data;
/* Scan to find existence of the device */
err = nand_scan(this, 1);
......
......@@ -22,6 +22,7 @@
#define FPGA_NAND_DATA_SHIFT 16
struct socrates_nand_host {
struct nand_controller controller;
struct nand_chip nand_chip;
void __iomem *io_base;
struct device *dev;
......@@ -116,6 +117,18 @@ static int socrates_nand_device_ready(struct nand_chip *nand_chip)
return 1;
}
static int socrates_attach_chip(struct nand_chip *chip)
{
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
return 0;
}
static const struct nand_controller_ops socrates_ops = {
.attach_chip = socrates_attach_chip,
};
/*
* Probe for the NAND device.
*/
......@@ -141,6 +154,10 @@ static int socrates_nand_probe(struct platform_device *ofdev)
mtd = nand_to_mtd(nand_chip);
host->dev = &ofdev->dev;
nand_controller_init(&host->controller);
host->controller.ops = &socrates_ops;
nand_chip->controller = &host->controller;
/* link the private data structures */
nand_set_controller_data(nand_chip, host);
nand_set_flash_node(nand_chip, ofdev->dev.of_node);
......@@ -153,10 +170,6 @@ static int socrates_nand_probe(struct platform_device *ofdev)
nand_chip->legacy.read_buf = socrates_nand_read_buf;
nand_chip->legacy.dev_ready = socrates_nand_device_ready;
/* enable ECC */
nand_chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
nand_chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
/* TODO: I have no idea what real delay is. */
nand_chip->legacy.chip_delay = 20; /* 20us command delay time */
......
......@@ -103,6 +103,7 @@
/*--------------------------------------------------------------------------*/
struct tmio_nand {
struct nand_controller controller;
struct nand_chip chip;
struct completion comp;
......@@ -355,6 +356,25 @@ static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio)
cell->disable(dev);
}
static int tmio_attach_chip(struct nand_chip *chip)
{
if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
return 0;
chip->ecc.size = 512;
chip->ecc.bytes = 6;
chip->ecc.strength = 2;
chip->ecc.hwctl = tmio_nand_enable_hwecc;
chip->ecc.calculate = tmio_nand_calculate_ecc;
chip->ecc.correct = tmio_nand_correct_data;
return 0;
}
static const struct nand_controller_ops tmio_ops = {
.attach_chip = tmio_attach_chip,
};
static int tmio_probe(struct platform_device *dev)
{
struct tmio_nand_data *data = dev_get_platdata(&dev->dev);
......@@ -385,6 +405,10 @@ static int tmio_probe(struct platform_device *dev)
mtd->name = "tmio-nand";
mtd->dev.parent = &dev->dev;
nand_controller_init(&tmio->controller);
tmio->controller.ops = &tmio_ops;
nand_chip->controller = &tmio->controller;
tmio->ccr = devm_ioremap(&dev->dev, ccr->start, resource_size(ccr));
if (!tmio->ccr)
return -EIO;
......@@ -409,15 +433,6 @@ static int tmio_probe(struct platform_device *dev)
nand_chip->legacy.write_buf = tmio_nand_write_buf;
nand_chip->legacy.read_buf = tmio_nand_read_buf;
/* set eccmode using hardware ECC */
nand_chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
nand_chip->ecc.size = 512;
nand_chip->ecc.bytes = 6;
nand_chip->ecc.strength = 2;
nand_chip->ecc.hwctl = tmio_nand_enable_hwecc;
nand_chip->ecc.calculate = tmio_nand_calculate_ecc;
nand_chip->ecc.correct = tmio_nand_correct_data;
if (data)
nand_chip->badblock_pattern = data->badblock_pattern;
......
......@@ -253,6 +253,11 @@ static int txx9ndfmc_attach_chip(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
return 0;
chip->ecc.strength = 1;
if (mtd->writesize >= 512) {
chip->ecc.size = 512;
chip->ecc.bytes = 6;
......@@ -261,6 +266,10 @@ static int txx9ndfmc_attach_chip(struct nand_chip *chip)
chip->ecc.bytes = 3;
}
chip->ecc.calculate = txx9ndfmc_calculate_ecc;
chip->ecc.correct = txx9ndfmc_correct_data;
chip->ecc.hwctl = txx9ndfmc_enable_hwecc;
return 0;
}
......@@ -326,11 +335,6 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
chip->legacy.write_buf = txx9ndfmc_write_buf;
chip->legacy.cmd_ctrl = txx9ndfmc_cmd_ctrl;
chip->legacy.dev_ready = txx9ndfmc_dev_ready;
chip->ecc.calculate = txx9ndfmc_calculate_ecc;
chip->ecc.correct = txx9ndfmc_correct_data;
chip->ecc.hwctl = txx9ndfmc_enable_hwecc;
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
chip->ecc.strength = 1;
chip->legacy.chip_delay = 100;
chip->controller = &drvdata->controller;
......
......@@ -62,6 +62,7 @@
#define NAND_CON_NANDM 1
struct xway_nand_data {
struct nand_controller controller;
struct nand_chip chip;
unsigned long csflags;
void __iomem *nandaddr;
......@@ -145,6 +146,18 @@ static void xway_write_buf(struct nand_chip *chip, const u_char *buf, int len)
xway_writeb(nand_to_mtd(chip), NAND_WRITE_DATA, buf[i]);
}
static int xway_attach_chip(struct nand_chip *chip)
{
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
return 0;
}
static const struct nand_controller_ops xway_nand_ops = {
.attach_chip = xway_attach_chip,
};
/*
* Probe for the NAND device.
*/
......@@ -180,8 +193,9 @@ static int xway_nand_probe(struct platform_device *pdev)
data->chip.legacy.read_byte = xway_read_byte;
data->chip.legacy.chip_delay = 30;
data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
data->chip.ecc.algo = NAND_ECC_ALGO_HAMMING;
nand_controller_init(&data->controller);
data->controller.ops = &xway_nand_ops;
data->chip.controller = &data->controller;
platform_set_drvdata(pdev, data);
nand_set_controller_data(&data->chip, data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment