X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fmtd%2Fnand%2Fmxs_nand.c;h=378f8c513aac6381a6e5cc931c384270ec71b047;hb=1a4596601fd395f3afb8f82f3f840c5e00bdd57a;hp=4b1297a2fdc140bf46b9ece19c5f611b5578b98b;hpb=a939ea3ab459d5fb3d1eaaec289c6ca85f2f74c1;p=u-boot diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index 4b1297a2fd..378f8c513a 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -10,36 +10,31 @@ * Copyright (C) 2010 Freescale Semiconductor, Inc. * Copyright (C) 2008 Embedded Alley Solutions, Inc. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * SPDX-License-Identifier: GPL-2.0+ */ +#include #include #include #include -#include #include #include #include #include #include +#include +#include #include -#include +#include #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 +228,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 +333,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 +541,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 +687,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 +745,7 @@ static void mxs_nand_ecc_write_page(struct mtd_info *mtd, rtn: mxs_nand_return_dma_descs(nand_info); + return 0; } /* @@ -763,7 +761,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 +786,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 +864,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 +966,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 +978,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 +997,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 +1056,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 +1075,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 +1096,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 +1163,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;