Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3dfe41a4 authored by Josh Wu's avatar Josh Wu Committed by David Woodhouse
Browse files

mtd: at91: extract hw ecc initialization to one function



This patch moves hw ecc initialization code to one function.

Signed-off-by: default avatarHong Xu <hong.xu@atmel.com>
Signed-off-by: default avatarJosh Wu <josh.wu@atmel.com>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 95c1b0ce
Loading
Loading
Loading
Loading
+66 −61
Original line number Diff line number Diff line
@@ -527,6 +527,66 @@ static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
}
#endif

static int __init atmel_hw_nand_init_params(struct platform_device *pdev,
					 struct atmel_nand_host *host)
{
	struct mtd_info *mtd = &host->mtd;
	struct nand_chip *nand_chip = &host->nand_chip;
	struct resource		*regs;

	regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (!regs) {
		dev_err(host->dev,
			"Can't get I/O resource regs, use software ECC\n");
		nand_chip->ecc.mode = NAND_ECC_SOFT;
		return 0;
	}

	host->ecc = ioremap(regs->start, resource_size(regs));
	if (host->ecc == NULL) {
		dev_err(host->dev, "ioremap failed\n");
		return -EIO;
	}

	/* ECC is calculated for the whole page (1 step) */
	nand_chip->ecc.size = mtd->writesize;

	/* set ECC page size and oob layout */
	switch (mtd->writesize) {
	case 512:
		nand_chip->ecc.layout = &atmel_oobinfo_small;
		ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
		break;
	case 1024:
		nand_chip->ecc.layout = &atmel_oobinfo_large;
		ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
		break;
	case 2048:
		nand_chip->ecc.layout = &atmel_oobinfo_large;
		ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
		break;
	case 4096:
		nand_chip->ecc.layout = &atmel_oobinfo_large;
		ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
		break;
	default:
		/* page size not handled by HW ECC */
		/* switching back to soft ECC */
		nand_chip->ecc.mode = NAND_ECC_SOFT;
		return 0;
	}

	/* set up for HW ECC */
	nand_chip->ecc.calculate = atmel_nand_calculate;
	nand_chip->ecc.correct = atmel_nand_correct;
	nand_chip->ecc.hwctl = atmel_nand_hwctl;
	nand_chip->ecc.read_page = atmel_nand_read_page;
	nand_chip->ecc.bytes = 4;
	nand_chip->ecc.strength = 1;

	return 0;
}

/*
 * Probe for the NAND device.
 */
@@ -535,7 +595,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
	struct atmel_nand_host *host;
	struct mtd_info *mtd;
	struct nand_chip *nand_chip;
	struct resource *regs;
	struct resource *mem;
	struct mtd_part_parser_data ppdata = {};
	int res;
@@ -587,29 +646,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
		nand_chip->dev_ready = atmel_nand_device_ready;

	nand_chip->ecc.mode = host->board.ecc_mode;

	regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (!regs && nand_chip->ecc.mode == NAND_ECC_HW) {
		printk(KERN_ERR "atmel_nand: can't get I/O resource "
				"regs\nFalling back on software ECC\n");
		nand_chip->ecc.mode = NAND_ECC_SOFT;
	}

	if (nand_chip->ecc.mode == NAND_ECC_HW) {
		host->ecc = ioremap(regs->start, resource_size(regs));
		if (host->ecc == NULL) {
			printk(KERN_ERR "atmel_nand: ioremap failed\n");
			res = -EIO;
			goto err_ecc_ioremap;
		}
		nand_chip->ecc.calculate = atmel_nand_calculate;
		nand_chip->ecc.correct = atmel_nand_correct;
		nand_chip->ecc.hwctl = atmel_nand_hwctl;
		nand_chip->ecc.read_page = atmel_nand_read_page;
		nand_chip->ecc.bytes = 4;
		nand_chip->ecc.strength = 1;
	}

	nand_chip->chip_delay = 20;		/* 20us command delay time */

	if (host->board.bus_width_16)	/* 16-bit bus width */
@@ -661,40 +697,9 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
	}

	if (nand_chip->ecc.mode == NAND_ECC_HW) {
		/* ECC is calculated for the whole page (1 step) */
		nand_chip->ecc.size = mtd->writesize;

		/* set ECC page size and oob layout */
		switch (mtd->writesize) {
		case 512:
			nand_chip->ecc.layout = &atmel_oobinfo_small;
			ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
			break;
		case 1024:
			nand_chip->ecc.layout = &atmel_oobinfo_large;
			ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
			break;
		case 2048:
			nand_chip->ecc.layout = &atmel_oobinfo_large;
			ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
			break;
		case 4096:
			nand_chip->ecc.layout = &atmel_oobinfo_large;
			ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
			break;
		default:
			/* page size not handled by HW ECC */
			/* switching back to soft ECC */
			nand_chip->ecc.mode = NAND_ECC_SOFT;
			nand_chip->ecc.calculate = NULL;
			nand_chip->ecc.correct = NULL;
			nand_chip->ecc.hwctl = NULL;
			nand_chip->ecc.read_page = NULL;
			nand_chip->ecc.postpad = 0;
			nand_chip->ecc.prepad = 0;
			nand_chip->ecc.bytes = 0;
			break;
		}
		res = atmel_hw_nand_init_params(pdev, host);
		if (res != 0)
			goto err_hw_ecc;
	}

	/* second phase scan */
@@ -711,15 +716,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
		return res;

err_scan_tail:
	if (host->ecc)
		iounmap(host->ecc);
err_hw_ecc:
err_scan_ident:
err_no_card:
	atmel_nand_disable(host);
	platform_set_drvdata(pdev, NULL);
	if (host->dma_chan)
		dma_release_channel(host->dma_chan);
	if (host->ecc)
		iounmap(host->ecc);
err_ecc_ioremap:
	iounmap(host->io_base);
err_nand_ioremap:
	kfree(host);