]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/mtd/nand/mxs_nand.c
Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
[karo-tx-uboot.git] / drivers / mtd / nand / mxs_nand.c
index 4b1297a2fdc140bf46b9ece19c5f611b5578b98b..866cabd2765764ff29dbd84b9e2f9e58f6855ec0 100644 (file)
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#include <common.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/types.h>
-#include <common.h>
 #include <malloc.h>
 #include <asm/errno.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/imx-regs.h>
+#include <asm/imx-common/regs-bch.h>
+#include <asm/imx-common/regs-gpmi.h>
 #include <asm/arch/sys_proto.h>
-#include <asm/arch/dma.h>
+#include <asm/imx-common/dma.h>
 
 #define        MXS_NAND_DMA_DESCRIPTOR_COUNT           4
 
 #define        MXS_NAND_CHUNK_DATA_CHUNK_SIZE          512
+#if defined(CONFIG_MX6)
+#define        MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT    2
+#else
+#define        MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT    0
+#endif
 #define        MXS_NAND_METADATA_SIZE                  10
 
 #define        MXS_NAND_COMMAND_BUFFER_SIZE            32
@@ -233,11 +240,11 @@ static uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
  */
 static int mxs_nand_wait_for_bch_complete(void)
 {
-       struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+       struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
        int timeout = MXS_NAND_BCH_TIMEOUT;
        int ret;
 
-       ret = mx28_wait_mask_set(&bch_regs->hw_bch_ctrl_reg,
+       ret = mxs_wait_mask_set(&bch_regs->hw_bch_ctrl_reg,
                BCH_CTRL_COMPLETE_IRQ, timeout);
 
        writel(BCH_CTRL_COMPLETE_IRQ, &bch_regs->hw_bch_ctrl_clr);
@@ -338,8 +345,8 @@ static int mxs_nand_device_ready(struct mtd_info *mtd)
 {
        struct nand_chip *chip = mtd->priv;
        struct mxs_nand_info *nand_info = chip->priv;
-       struct mx28_gpmi_regs *gpmi_regs =
-               (struct mx28_gpmi_regs *)MXS_GPMI_BASE;
+       struct mxs_gpmi_regs *gpmi_regs =
+               (struct mxs_gpmi_regs *)MXS_GPMI_BASE;
        uint32_t tmp;
 
        tmp = readl(&gpmi_regs->hw_gpmi_stat);
@@ -546,7 +553,8 @@ static uint8_t mxs_nand_read_byte(struct mtd_info *mtd)
  * Read a page from NAND.
  */
 static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
-                                       uint8_t *buf, int page)
+                                       uint8_t *buf, int oob_required,
+                                       int page)
 {
        struct mxs_nand_info *nand_info = nand->priv;
        struct mxs_dma_desc *d;
@@ -691,8 +699,9 @@ rtn:
 /*
  * Write a page to NAND.
  */
-static void mxs_nand_ecc_write_page(struct mtd_info *mtd,
-                               struct nand_chip *nand, const uint8_t *buf)
+static int mxs_nand_ecc_write_page(struct mtd_info *mtd,
+                               struct nand_chip *nand, const uint8_t *buf,
+                               int oob_required)
 {
        struct mxs_nand_info *nand_info = nand->priv;
        struct mxs_dma_desc *d;
@@ -748,6 +757,7 @@ static void mxs_nand_ecc_write_page(struct mtd_info *mtd,
 
 rtn:
        mxs_nand_return_dma_descs(nand_info);
+       return 0;
 }
 
 /*
@@ -763,7 +773,7 @@ static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from,
        struct mxs_nand_info *nand_info = chip->priv;
        int ret;
 
-       if (ops->mode == MTD_OOB_RAW)
+       if (ops->mode == MTD_OPS_RAW)
                nand_info->raw_oob_mode = 1;
        else
                nand_info->raw_oob_mode = 0;
@@ -788,7 +798,7 @@ static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to,
        struct mxs_nand_info *nand_info = chip->priv;
        int ret;
 
-       if (ops->mode == MTD_OOB_RAW)
+       if (ops->mode == MTD_OPS_RAW)
                nand_info->raw_oob_mode = 1;
        else
                nand_info->raw_oob_mode = 0;
@@ -866,7 +876,7 @@ static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs)
  * what to do.
  */
 static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
-                               int page, int cmd)
+                               int page)
 {
        struct mxs_nand_info *nand_info = nand->priv;
 
@@ -968,11 +978,11 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd)
 {
        struct nand_chip *nand = mtd->priv;
        struct mxs_nand_info *nand_info = nand->priv;
-       struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE;
+       struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
        uint32_t tmp;
 
        /* Configure BCH and set NFC geometry */
-       mx28_reset_block(&bch_regs->hw_bch_ctrl_reg);
+       mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
 
        /* Configure layout 0 */
        tmp = (mxs_nand_ecc_chunk_cnt(mtd->writesize) - 1)
@@ -980,14 +990,16 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd)
        tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
        tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
                << BCH_FLASHLAYOUT0_ECC0_OFFSET;
-       tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+       tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE
+               >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
        writel(tmp, &bch_regs->hw_bch_flash0layout0);
 
        tmp = (mtd->writesize + mtd->oobsize)
                << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
        tmp |= (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1)
                << BCH_FLASHLAYOUT1_ECCN_OFFSET;
-       tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
+       tmp |= MXS_NAND_CHUNK_DATA_CHUNK_SIZE
+               >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
        writel(tmp, &bch_regs->hw_bch_flash0layout1);
 
        /* Set *all* chip selects to use layout 0 */
@@ -997,19 +1009,19 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd)
        writel(BCH_CTRL_COMPLETE_IRQ_EN, &bch_regs->hw_bch_ctrl_set);
 
        /* Hook some operations at the MTD level. */
-       if (mtd->read_oob != mxs_nand_hook_read_oob) {
-               nand_info->hooked_read_oob = mtd->read_oob;
-               mtd->read_oob = mxs_nand_hook_read_oob;
+       if (mtd->_read_oob != mxs_nand_hook_read_oob) {
+               nand_info->hooked_read_oob = mtd->_read_oob;
+               mtd->_read_oob = mxs_nand_hook_read_oob;
        }
 
-       if (mtd->write_oob != mxs_nand_hook_write_oob) {
-               nand_info->hooked_write_oob = mtd->write_oob;
-               mtd->write_oob = mxs_nand_hook_write_oob;
+       if (mtd->_write_oob != mxs_nand_hook_write_oob) {
+               nand_info->hooked_write_oob = mtd->_write_oob;
+               mtd->_write_oob = mxs_nand_hook_write_oob;
        }
 
-       if (mtd->block_markbad != mxs_nand_hook_block_markbad) {
-               nand_info->hooked_block_markbad = mtd->block_markbad;
-               mtd->block_markbad = mxs_nand_hook_block_markbad;
+       if (mtd->_block_markbad != mxs_nand_hook_block_markbad) {
+               nand_info->hooked_block_markbad = mtd->_block_markbad;
+               mtd->_block_markbad = mxs_nand_hook_block_markbad;
        }
 
        /* We use the reference implementation for bad block management. */
@@ -1056,9 +1068,11 @@ int mxs_nand_alloc_buffers(struct mxs_nand_info *nand_info)
  */
 int mxs_nand_init(struct mxs_nand_info *info)
 {
-       struct mx28_gpmi_regs *gpmi_regs =
-               (struct mx28_gpmi_regs *)MXS_GPMI_BASE;
-       int i = 0;
+       struct mxs_gpmi_regs *gpmi_regs =
+               (struct mxs_gpmi_regs *)MXS_GPMI_BASE;
+       struct mxs_bch_regs *bch_regs =
+               (struct mxs_bch_regs *)MXS_BCH_BASE;
+       int i = 0, j;
 
        info->desc = malloc(sizeof(struct mxs_dma_desc *) *
                                MXS_NAND_DMA_DESCRIPTOR_COUNT);
@@ -1073,10 +1087,15 @@ int mxs_nand_init(struct mxs_nand_info *info)
        }
 
        /* Init the DMA controller. */
-       mxs_dma_init();
+       for (j = MXS_DMA_CHANNEL_AHB_APBH_GPMI0;
+               j <= MXS_DMA_CHANNEL_AHB_APBH_GPMI7; j++) {
+               if (mxs_dma_init_channel(j))
+                       goto err3;
+       }
 
        /* Reset the GPMI block. */
-       mx28_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
+       mxs_reset_block(&gpmi_regs->hw_gpmi_ctrl0_reg);
+       mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);
 
        /*
         * Choose NAND mode, set IRQ polarity, disable write protection and
@@ -1089,6 +1108,9 @@ int mxs_nand_init(struct mxs_nand_info *info)
 
        return 0;
 
+err3:
+       for (--j; j >= 0; j--)
+               mxs_dma_release(j);
 err2:
        free(info->desc);
 err1:
@@ -1153,6 +1175,7 @@ int board_nand_init(struct nand_chip *nand)
        nand->ecc.mode          = NAND_ECC_HW;
        nand->ecc.bytes         = 9;
        nand->ecc.size          = 512;
+       nand->ecc.strength      = 8;
 
        return 0;