diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2020-11-10 15:07:38 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2020-11-10 15:07:38 +0100 |
commit | 7b1d8b4b3561c043a79d5933a7c1eb9266dc328d (patch) | |
tree | 9c398aa20e22763a239d11eecf6fb4c1d06d4c97 /drivers/mtd/nand/nand_mxs.c | |
parent | 0b0eada569b198aa3882cfec5874bc35a8a0fa14 (diff) | |
parent | 4db0f1c3dbe6173fdf91cbeb83e250719332c6a3 (diff) | |
download | barebox-7b1d8b4b3561c043a79d5933a7c1eb9266dc328d.tar.gz barebox-7b1d8b4b3561c043a79d5933a7c1eb9266dc328d.tar.xz |
Merge branch 'for-next/mtd-nand'
Diffstat (limited to 'drivers/mtd/nand/nand_mxs.c')
-rw-r--r-- | drivers/mtd/nand/nand_mxs.c | 172 |
1 files changed, 85 insertions, 87 deletions
diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c index e2b6e21620..9f7ab14426 100644 --- a/drivers/mtd/nand/nand_mxs.c +++ b/drivers/mtd/nand/nand_mxs.c @@ -20,6 +20,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> +#include <linux/mtd/rawnand.h> #include <linux/mtd/nand_mxs.h> #include <linux/types.h> #include <linux/clk.h> @@ -235,8 +236,6 @@ struct mxs_nand_info { int bb_mark_bit_offset; }; -static struct nand_ecclayout fake_ecc_layout; - static inline int mxs_nand_is_imx6(struct mxs_nand_info *info) { return info->type == GPMI_IMX6; @@ -330,16 +329,14 @@ static uint32_t mxs_nand_get_mark_offset(struct mtd_info *mtd) return block_mark_bit_offset; } -static int mxs_nand_calc_geo(struct mtd_info *mtd) +static int mxs_nand_calc_geo(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct mxs_nand_info *nand_info = chip->priv; int ecc_chunk_count = mxs_nand_ecc_chunk_cnt(mtd->writesize); int gf_len = 13; /* length of Galois Field for non-DDR nand */ int max_ecc_strength; - nand_of_parse_node(mtd, mtd->parent->device_node); - max_ecc_strength = ((mtd->oobsize - MXS_NAND_METADATA_SIZE) * 8) / (gf_len * ecc_chunk_count); /* We need the minor even number. */ @@ -420,9 +417,8 @@ static int mxs_nand_wait_for_bch_complete(struct mxs_nand_info *nand_info) * ignore the chip enable bit and concentrate only on sending bytes to the NAND * Flash. */ -static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl) +static void mxs_nand_cmd_ctrl(struct nand_chip *chip, int data, unsigned int ctrl) { - struct nand_chip *chip = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = chip->priv; struct mxs_dma_desc *d; uint32_t channel = nand_info->dma_channel_base + nand_info->cur_chip; @@ -496,9 +492,8 @@ static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl) /* * Test if the NAND flash is ready. */ -static int mxs_nand_device_ready(struct mtd_info *mtd) +static int mxs_nand_device_ready(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = chip->priv; void __iomem *gpmi_regs = nand_info->io_base; uint32_t tmp; @@ -522,9 +517,8 @@ static int mxs_nand_device_ready(struct mtd_info *mtd) /* * Select the NAND chip. */ -static void mxs_nand_select_chip(struct mtd_info *mtd, int chipnum) +static void mxs_nand_select_chip(struct nand_chip *chip, int chipnum) { - struct nand_chip *chip = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = chip->priv; nand_info->cur_chip = chipnum; @@ -537,10 +531,9 @@ static void mxs_nand_select_chip(struct mtd_info *mtd, int chipnum) * swapping the block mark, or swapping it *back* -- but it doesn't matter * because the the operation is the same. */ -static void mxs_nand_swap_block_mark(struct mtd_info *mtd, +static void mxs_nand_swap_block_mark(struct nand_chip *chip, uint8_t *data_buf, uint8_t *oob_buf) { - struct nand_chip *chip = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = chip->priv; uint32_t bit_offset; @@ -579,9 +572,8 @@ static void mxs_nand_swap_block_mark(struct mtd_info *mtd, /* * Read data from NAND. */ -static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length) +static void mxs_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int length) { - struct nand_chip *chip = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = chip->priv; struct mxs_dma_desc *d; uint32_t channel = nand_info->dma_channel_base + nand_info->cur_chip; @@ -656,10 +648,9 @@ rtn: /* * Write data to NAND. */ -static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, +static void mxs_nand_write_buf(struct nand_chip *chip, const uint8_t *buf, int length) { - struct nand_chip *chip = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = chip->priv; struct mxs_dma_desc *d; uint32_t channel = nand_info->dma_channel_base + nand_info->cur_chip; @@ -707,16 +698,15 @@ static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, /* * Read a single byte from NAND. */ -static uint8_t mxs_nand_read_byte(struct mtd_info *mtd) +static uint8_t mxs_nand_read_byte(struct nand_chip *chip) { uint8_t buf; - mxs_nand_read_buf(mtd, &buf, 1); + mxs_nand_read_buf(chip, &buf, 1); return buf; } -static void mxs_nand_config_bch(struct mtd_info *mtd, int readlen) +static void mxs_nand_config_bch(struct nand_chip *chip, int readlen) { - struct nand_chip *chip = mtd_to_nand(mtd); struct mxs_nand_info *nand_info = chip->priv; int chunk_size; void __iomem *bch_regs = nand_info->bch_base; @@ -744,10 +734,11 @@ static void mxs_nand_config_bch(struct mtd_info *mtd, int readlen) /* * Read a page from NAND. */ -static int __mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, +static int __mxs_nand_ecc_read_page(struct nand_chip *chip, uint8_t *buf, int oob_required, int page, int readlen) { + struct mtd_info *mtd = nand_to_mtd(chip); struct mxs_nand_info *nand_info = chip->priv; struct mxs_dma_desc *d; uint32_t channel = nand_info->dma_channel_base + nand_info->cur_chip; @@ -756,13 +747,15 @@ static int __mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip unsigned int max_bitflips = 0; int i, ret, readtotal, nchunks; + nand_read_page_op(chip, page, 0, NULL, 0); + readlen = roundup(readlen, MXS_NAND_CHUNK_DATA_CHUNK_SIZE); nchunks = mxs_nand_ecc_chunk_cnt(readlen); readtotal = MXS_NAND_METADATA_SIZE; readtotal += MXS_NAND_CHUNK_DATA_CHUNK_SIZE * nchunks; readtotal += DIV_ROUND_UP(13 * chip->ecc.strength * nchunks, 8); - mxs_nand_config_bch(mtd, readtotal); + mxs_nand_config_bch(chip, readtotal); /* Compile the DMA descriptor - wait for ready. */ d = mxs_nand_get_dma_desc(nand_info); @@ -850,7 +843,7 @@ static int __mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip } /* Read DMA completed, now do the mark swapping. */ - mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf); + mxs_nand_swap_block_mark(chip, nand_info->data_buf, nand_info->oob_buf); memcpy(buf, nand_info->data_buf, readlen); @@ -931,19 +924,21 @@ static int __mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip rtn: mxs_nand_return_dma_descs(nand_info); - mxs_nand_config_bch(mtd, mtd->writesize + mtd->oobsize); + mxs_nand_config_bch(chip, mtd->writesize + mtd->oobsize); return ret ? ret : max_bitflips; } -static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, +static int mxs_nand_ecc_read_page(struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - return __mxs_nand_ecc_read_page(mtd, chip, buf, oob_required, page, + struct mtd_info *mtd = nand_to_mtd(chip); + + return __mxs_nand_ecc_read_page(chip, buf, oob_required, page, mtd->writesize); } -static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, +static int gpmi_ecc_read_subpage(struct nand_chip *chip, uint32_t offs, uint32_t len, uint8_t *buf, int page) { /* @@ -956,26 +951,28 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, offs = 0; } - return __mxs_nand_ecc_read_page(mtd, chip, buf, 0, page, len); + return __mxs_nand_ecc_read_page(chip, buf, 0, page, len); } /* * Write a page to NAND. */ -static int mxs_nand_ecc_write_page(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf, - int oob_required) +static int mxs_nand_ecc_write_page(struct nand_chip *chip, const uint8_t *buf, + int oob_required, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct mxs_nand_info *nand_info = chip->priv; struct mxs_dma_desc *d; uint32_t channel = nand_info->dma_channel_base + nand_info->cur_chip; int ret = 0; + nand_prog_page_begin_op(chip, page, 0, NULL, 0); + memcpy(nand_info->data_buf, buf, mtd->writesize); memcpy(nand_info->oob_buf, chip->oob_poi, mtd->oobsize); /* Handle block mark swapping. */ - mxs_nand_swap_block_mark(mtd, nand_info->data_buf, nand_info->oob_buf); + mxs_nand_swap_block_mark(chip, nand_info->data_buf, nand_info->oob_buf); /* Compile the DMA descriptor - write data. */ d = mxs_nand_get_dma_desc(nand_info); @@ -1018,7 +1015,10 @@ static int mxs_nand_ecc_write_page(struct mtd_info *mtd, rtn: mxs_nand_return_dma_descs(nand_info); - return ret; + if (ret) + return ret; + + return nand_prog_page_end_op(chip); } /* @@ -1136,9 +1136,9 @@ static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs) * raw_oob_mode field so that, when control finally arrives here, we'll know * what to do. */ -static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int mxs_nand_ecc_read_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct mxs_nand_info *nand_info = chip->priv; int column; @@ -1152,8 +1152,8 @@ static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, * If control arrives here, we're doing a "raw" read. Send the * command to read the conventional OOB and read it. */ - chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); - chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + chip->legacy.cmdfunc(chip, NAND_CMD_READ0, mtd->writesize, page); + chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize); } else { /* * If control arrives here, we're not doing a "raw" read. Fill @@ -1162,8 +1162,8 @@ static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, memset(chip->oob_poi, 0xff, mtd->oobsize); column = nand_info->version == GPMI_VERSION_TYPE_MX23 ? 0 : mtd->writesize; - chip->cmdfunc(mtd, NAND_CMD_READ0, column, page); - mxs_nand_read_buf(mtd, chip->oob_poi, 1); + chip->legacy.cmdfunc(chip, NAND_CMD_READ0, column, page); + mxs_nand_read_buf(chip, chip->oob_poi, 1); } return 0; @@ -1173,9 +1173,9 @@ static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, /* * Write OOB data to NAND. */ -static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, - int page) +static int mxs_nand_ecc_write_oob(struct nand_chip *chip, int page) { + struct mtd_info *mtd = nand_to_mtd(chip); struct mxs_nand_info *nand_info = chip->priv; int column; uint8_t block_mark = 0; @@ -1196,12 +1196,12 @@ static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, column = nand_info->version == GPMI_VERSION_TYPE_MX23 ? 0 : mtd->writesize; /* Write the block mark. */ - chip->cmdfunc(mtd, NAND_CMD_SEQIN, column, page); - chip->write_buf(mtd, &block_mark, 1); - chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + chip->legacy.cmdfunc(chip, NAND_CMD_SEQIN, column, page); + chip->legacy.write_buf(chip, &block_mark, 1); + chip->legacy.cmdfunc(chip, NAND_CMD_PAGEPROG, -1, -1); /* Check if it worked. */ - if (chip->waitfunc(mtd, chip) & NAND_STATUS_FAIL) + if (chip->legacy.waitfunc(chip) & NAND_STATUS_FAIL) return -EIO; return 0; @@ -1220,7 +1220,7 @@ static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, * Thus, this function is only called when we want *all* blocks to look good, * so it *always* return success. */ -static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) +static int mxs_nand_block_bad(struct nand_chip *chip , loff_t ofs) { return 0; } @@ -1239,9 +1239,9 @@ static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) * call to nand_scan(). Anything other than zero will cause this driver to * tear everything down and declare failure. */ -static int mxs_nand_scan_bbt(struct mtd_info *mtd) +static int mxs_nand_scan_bbt(struct nand_chip *chip) { - struct nand_chip *chip = mtd_to_nand(mtd); + struct mtd_info *mtd = nand_to_mtd(chip); struct mxs_nand_info *nand_info = chip->priv; void __iomem *bch_regs = nand_info->bch_base; int ret; @@ -1252,7 +1252,7 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd) if (ret) return ret; - mxs_nand_config_bch(mtd, mtd->writesize + mtd->oobsize); + mxs_nand_config_bch(chip, mtd->writesize + mtd->oobsize); /* Set *all* chip selects to use layout 0 */ writel(0, bch_regs + BCH_LAYOUTSELECT); @@ -1261,23 +1261,23 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd) writel(BCH_CTRL_COMPLETE_IRQ_EN, bch_regs + BCH_CTRL + STMP_OFFSET_REG_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. */ - return nand_default_bbt(mtd); + return nand_create_bbt(chip); } /* @@ -1478,11 +1478,11 @@ static int mxs_nand_compute_hardware_timing(struct mxs_nand_info *info, * If there are multiple chips, we need to relax the timings to allow * for signal distortion due to higher capacitance. */ - if (chip->numchips > 2) { + if (nanddev_ntargets(&chip->base) > 2) { target.data_setup_in_ns += 10; target.data_hold_in_ns += 10; target.address_setup_in_ns += 10; - } else if (chip->numchips > 1) { + } else if (nanddev_ntargets(&chip->base) > 1) { target.data_setup_in_ns += 5; target.data_hold_in_ns += 5; target.address_setup_in_ns += 5; @@ -2029,14 +2029,13 @@ static void mxs_nand_compute_edo_timing(struct mxs_nand_info *info, static int mxs_nand_enable_edo_mode(struct mxs_nand_info *info) { struct nand_chip *chip = &info->nand_chip; - struct mtd_info *mtd = &chip->mtd; uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {}; int ret, mode; if (!mxs_nand_is_imx6(info)) return -ENODEV; - if (!chip->onfi_version) + if (!chip->parameters.onfi) return -ENOENT; mode = onfi_get_async_timing_mode(chip); @@ -2049,27 +2048,26 @@ static int mxs_nand_enable_edo_mode(struct mxs_nand_info *info) else return -EINVAL; - chip->select_chip(mtd, 0); + chip->legacy.select_chip(chip, 0); - if (le16_to_cpu(chip->onfi_params.opt_cmd) - & ONFI_OPT_CMD_SET_GET_FEATURES) { + if (nand_supports_set_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE)) { /* [1] send SET FEATURE commond to NAND */ feature[0] = mode; - ret = chip->onfi_set_features(mtd, chip, + ret = chip->legacy.set_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE, feature); if (ret) goto err_out; /* [2] send GET FEATURE command to double-check the timing mode */ - ret = chip->onfi_get_features(mtd, chip, + ret = chip->legacy.get_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE, feature); if (ret || feature[0] != mode) goto err_out; } - chip->select_chip(mtd, -1); + chip->legacy.select_chip(chip, -1); /* [3] set the main IO clock, 100MHz for mode 5, 80MHz for mode 4. */ clk_disable(info->clk); @@ -2081,7 +2079,7 @@ static int mxs_nand_enable_edo_mode(struct mxs_nand_info *info) return mode; err_out: - chip->select_chip(mtd, -1); + chip->legacy.select_chip(chip, -1); return -EINVAL; } @@ -2193,37 +2191,35 @@ static int mxs_nand_probe(struct device_d *dev) /* structures must be linked */ chip = &nand_info->nand_chip; - mtd = &nand_info->nand_chip.mtd; - mtd->parent = dev; + mtd = nand_to_mtd(chip); + mtd->dev.parent = dev; chip->priv = nand_info; - chip->cmd_ctrl = mxs_nand_cmd_ctrl; + chip->legacy.cmd_ctrl = mxs_nand_cmd_ctrl; - chip->dev_ready = mxs_nand_device_ready; - chip->select_chip = mxs_nand_select_chip; - chip->block_bad = mxs_nand_block_bad; - chip->scan_bbt = mxs_nand_scan_bbt; + chip->legacy.dev_ready = mxs_nand_device_ready; + chip->legacy.select_chip = mxs_nand_select_chip; + chip->legacy.block_bad = mxs_nand_block_bad; - chip->read_byte = mxs_nand_read_byte; + chip->legacy.read_byte = mxs_nand_read_byte; - chip->read_buf = mxs_nand_read_buf; - chip->write_buf = mxs_nand_write_buf; + chip->legacy.read_buf = mxs_nand_read_buf; + chip->legacy.write_buf = mxs_nand_write_buf; chip->ecc.read_page = mxs_nand_ecc_read_page; chip->ecc.write_page = mxs_nand_ecc_write_page; chip->ecc.read_oob = mxs_nand_ecc_read_oob; chip->ecc.write_oob = mxs_nand_ecc_write_oob; - chip->ecc.layout = &fake_ecc_layout; chip->ecc.mode = NAND_ECC_HW; /* first scan to find the device and get the page size */ - err = nand_scan_ident(mtd, 4, NULL); + err = nand_scan_ident(chip, 4, NULL); if (err) goto err2; - err = mxs_nand_calc_geo(mtd); + err = mxs_nand_calc_geo(chip); if (err) goto err2; @@ -2232,15 +2228,17 @@ static int mxs_nand_probe(struct device_d *dev) chip->options |= NAND_SUBPAGE_READ; } - chip->options |= NAND_NO_SUBPAGE_WRITE; + chip->options |= NAND_NO_SUBPAGE_WRITE | NAND_SKIP_BBTSCAN; mxs_nand_setup_timing(nand_info); /* second phase scan */ - err = nand_scan_tail(mtd); + err = nand_scan_tail(chip); if (err) goto err2; + mxs_nand_scan_bbt(chip); + err = add_mtd_nand_device(mtd, "nand"); if (err) goto err2; |