/* * Write a page to NAND. */ static void mxs_nand_ecc_write_page(struct mtd_info *mtd, struct nand_chip *nand, const uint8_t *buf) { struct mxs_nand_info *nand_info = nand->priv; struct mxs_dma_desc *d; uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; int ret; memcpy(nand_info->data_buf, buf, mtd->writesize); memcpy(nand_info->oob_buf, nand->oob_poi, mtd->oobsize); /* Handle block mark swapping. */ mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf); /* Compile the DMA descriptor - write data. */ d = mxs_nand_get_dma_desc(nand_info); d->cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END | (6 << MXS_DMA_DESC_PIO_WORDS_OFFSET); d->cmd.address = 0; d->cmd.pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE | GPMI_CTRL0_WORD_LENGTH | (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | GPMI_CTRL0_ADDRESS_NAND_DATA; d->cmd.pio_words[1] = 0; d->cmd.pio_words[2] = GPMI_ECCCTRL_ENABLE_ECC | GPMI_ECCCTRL_ECC_CMD_ENCODE | GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE; d->cmd.pio_words[3] = mtd->writesize + mtd->oobsize; d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf; d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf; flush_buffers(mtd, nand_info); mxs_dma_desc_append(channel, d); /* Flush caches */ mxs_nand_flush_data_buf(nand_info); /* Execute the DMA chain. */ ret = mxs_dma_go(channel); if (ret) { printf("%s: DMA write error\n", __func__); goto rtn; } ret = mxs_nand_wait_for_bch_complete(); if (ret) { printf("%s: BCH write timeout\n", __func__); goto rtn; } rtn: mxs_nand_return_dma_descs(nand_info); }
/* * Write data to NAND. */ static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int length) { struct nand_chip *nand = mtd->priv; struct mxs_nand_info *nand_info = nand->priv; struct mxs_dma_desc *d; uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; int ret; if (length > NAND_MAX_PAGESIZE) { printf("MXS NAND: DMA buffer too big\n"); return; } if (!buf) { printf("MXS NAND: DMA buffer is NULL\n"); return; } memcpy(nand_info->data_buf, buf, length); /* Compile the DMA descriptor - a descriptor that writes data. */ d = mxs_nand_get_dma_desc(nand_info); d->cmd.data = MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END | (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET) | (length << MXS_DMA_DESC_BYTES_OFFSET); d->cmd.address = (dma_addr_t)nand_info->data_buf; d->cmd.pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE | GPMI_CTRL0_WORD_LENGTH | (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) | GPMI_CTRL0_ADDRESS_NAND_DATA | length; mxs_dma_desc_append(channel, d); /* Flush caches */ mxs_nand_flush_data_buf(nand_info); /* Execute the DMA chain. */ ret = mxs_dma_go(channel); if (ret) printf("MXS NAND: DMA write error\n"); mxs_nand_return_dma_descs(nand_info); }