@@ -1077,23 +1077,43 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
* !raw_xfer - enable ecc
* raw_xfer - transfer spare
*/
- setup_ecc_for_xfer(denali, !raw_xfer, raw_xfer);
-
+ setup_ecc_for_xfer(denali, !raw_xfer, true);
+ clear_interrupts(denali);
/* copy buffer into DMA buffer */
- memcpy(denali->buf.buf, buf, mtd->writesize);
-
if (raw_xfer) {
+ memcpy(denali->buf.buf, buf, mtd->writesize);
/* transfer the data to the spare area */
memcpy(denali->buf.buf + mtd->writesize,
chip->oob_poi,
mtd->oobsize);
+ } else {
+ uint8_t *datadest, *oobsrc;
+ const uint8_t *src;
+ uint32_t i, cpysize;
+ datadest = denali->buf.buf;
+ src = buf;
+ oobsrc = chip->oob_poi + (mtd->oobsize - mtd->oobavail);
+ for (i = 0; i < chip->ecc.steps - 1; i++,
+ src += chip->ecc.size,
+ datadest += chip->ecc.size + chip->ecc.bytes)
+ memcpy(datadest, src, chip->ecc.size);
+ cpysize = mtd->writesize -
+ (chip->ecc.size + chip->ecc.bytes) * i;
+ memcpy(datadest, src, cpysize);
+ src += cpysize;
+ datadest += cpysize;
+ for (i = 0; i < denali->bbtskipbytes; i++)
+ *datadest++ = 0xff;
+ cpysize = mtd->oobsize - mtd->oobavail -
+ denali->bbtskipbytes - chip->ecc.bytes;
+ memcpy(datadest, src, cpysize);
+ datadest += cpysize + chip->ecc.bytes;
+ memcpy(datadest, oobsrc, mtd->oobavail);
}
+ denali_enable_dma(denali, true);
pci_dma_sync_single_for_device(pci_dev, addr, size, PCI_DMA_TODEVICE);
- clear_interrupts(denali);
- denali_enable_dma(denali, true);
-
denali_setup_dma(denali, DENALI_WRITE);
/* wait for operation to complete */
@@ -1103,13 +1123,17 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
dev_err(&denali->dev->dev,
"timeout on write_page (type = %d)\n",
raw_xfer);
- denali->status =
- (irq_status & INTR_STATUS0__PROGRAM_FAIL) ?
- NAND_STATUS_FAIL : PASS;
- }
+ denali->status = NAND_STATUS_FAIL;
+ } else if (irq_status & INTR_STATUS0__PROGRAM_FAIL)
+ denali->status = NAND_STATUS_FAIL;
+ else
+ denali->status = PASS;
- denali_enable_dma(denali, false);
pci_dma_sync_single_for_cpu(pci_dev, addr, size, PCI_DMA_TODEVICE);
+
+ denali_enable_dma(denali, false);
+
+ memset(chip->oob_poi, 0xff, mtd->oobsize);
}
/* NAND core entry points */