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

Commit bd3fd62e authored by Vladimir Barinov's avatar Vladimir Barinov Committed by David Woodhouse
Browse files

mtd: MXC NAND support for 2KiB page size flashes



- Add support for 2KiB page size flashes
- Fix page address access for large pages
- Detect oob layout at runtime
- handle pagesize_2k variable
- Fix oob16 layout: reserve location 5 of oob area since it's used for bbt

Signed-off-by: default avatarVladimir Barinov <vova.barinov@gmail.com>
Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent f36e20c0
Loading
Loading
Loading
Loading
+51 −9
Original line number Diff line number Diff line
@@ -138,7 +138,14 @@ static struct nand_ecclayout nand_hw_eccoob_8 = {
static struct nand_ecclayout nand_hw_eccoob_16 = {
	.eccbytes = 5,
	.eccpos = {6, 7, 8, 9, 10},
	.oobfree = {{0, 6}, {12, 4}, }
	.oobfree = {{0, 5}, {11, 5}, }
};

static struct nand_ecclayout nand_hw_eccoob_64 = {
	.eccbytes = 20,
	.eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
		   38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
	.oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
};

#ifdef CONFIG_MTD_PARTITIONS
@@ -795,9 +802,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
		send_addr(host, (page_addr & 0xff), false);

		if (host->pagesize_2k) {
			send_addr(host, (page_addr >> 8) & 0xFF, false);
			if (mtd->size >= 0x40000000)
			if (mtd->size >= 0x10000000) {
				/* paddr_8 - paddr_15 */
				send_addr(host, (page_addr >> 8) & 0xff, false);
				send_addr(host, (page_addr >> 16) & 0xff, true);
			} else
				/* paddr_8 - paddr_15 */
				send_addr(host, (page_addr >> 8) & 0xff, true);
		} else {
			/* One more address cycle for higher density devices */
			if (mtd->size >= 0x4000000) {
@@ -919,7 +930,6 @@ static int __init mxcnd_probe(struct platform_device *pdev)
		this->ecc.mode = NAND_ECC_HW;
		this->ecc.size = 512;
		this->ecc.bytes = 3;
		this->ecc.layout = &nand_hw_eccoob_8;
		tmp = readw(host->regs + NFC_CONFIG1);
		tmp |= NFC_ECC_EN;
		writew(tmp, host->regs + NFC_CONFIG1);
@@ -953,12 +963,44 @@ static int __init mxcnd_probe(struct platform_device *pdev)
		this->ecc.layout = &nand_hw_eccoob_16;
	}

	host->pagesize_2k = 0;
	/* first scan to find the device and get the page size */
	if (nand_scan_ident(mtd, 1)) {
		err = -ENXIO;
		goto escan;
	}

	host->pagesize_2k = (mtd->writesize == 2048) ? 1 : 0;

	/* Scan to find existence of the device */
	if (nand_scan(mtd, 1)) {
		DEBUG(MTD_DEBUG_LEVEL0,
		      "MXC_ND: Unable to find any NAND device.\n");
	if (this->ecc.mode == NAND_ECC_HW) {
		switch (mtd->oobsize) {
		case 8:
			this->ecc.layout = &nand_hw_eccoob_8;
			break;
		case 16:
			this->ecc.layout = &nand_hw_eccoob_16;
			break;
		case 64:
			this->ecc.layout = &nand_hw_eccoob_64;
			break;
		default:
			/* page size not handled by HW ECC */
			/* switching back to soft ECC */
			this->ecc.size = 512;
			this->ecc.bytes = 3;
			this->ecc.layout = &nand_hw_eccoob_8;
			this->ecc.mode = NAND_ECC_SOFT;
			this->ecc.calculate = NULL;
			this->ecc.correct = NULL;
			this->ecc.hwctl = NULL;
			tmp = readw(host->regs + NFC_CONFIG1);
			tmp &= ~NFC_ECC_EN;
			writew(tmp, host->regs + NFC_CONFIG1);
			break;
		}
	}

	/* second phase scan */
	if (nand_scan_tail(mtd)) {
		err = -ENXIO;
		goto escan;
	}