|
@@ -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;
|
|
|
+ }
|
|
|
|
|
|
- /* 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");
|
|
|
+ host->pagesize_2k = (mtd->writesize == 2048) ? 1 : 0;
|
|
|
+
|
|
|
+ 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;
|
|
|
}
|