diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2019-08-15 10:58:11 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-08-15 10:58:11 +0200 |
commit | a6aab0ebab471e91beb4e14c2d305b326ac18928 (patch) | |
tree | 44411e6dbed5e1c1f9999ae9827d678a5a88cdcb /drivers/mtd | |
parent | a0b3119905e16d7610f950d0fd04a8689979be2e (diff) | |
parent | 6b309a2f91dca742a05a53922ff70970f28b428d (diff) | |
download | barebox-a6aab0ebab471e91beb4e14c2d305b326ac18928.tar.gz barebox-a6aab0ebab471e91beb4e14c2d305b326ac18928.tar.xz |
Merge branch 'for-next/mtd-gpmi-nand'
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 27 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_mxs.c | 273 |
2 files changed, 182 insertions, 118 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5474d0db3c..9c0c01694a 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -43,6 +43,7 @@ #include <io.h> #include <malloc.h> #include <module.h> +#include <of_mtd.h> /* Define default oob placement schemes for large and small page devices */ static struct nand_ecclayout nand_oob_8 = { @@ -3507,6 +3508,32 @@ ident_done: } /** + * nand_of_parse_node - parse generic NAND properties + * @mtd: MTD device structure + * @np: Device node to read information from + * + * This parses device tree properties generic to NAND controllers and fills in + * the various fields in struct nand_chip. + */ +void nand_of_parse_node(struct mtd_info *mtd, struct device_node *np) +{ + struct nand_chip *chip = mtd->priv; + int ecc_strength, ecc_size; + + if (!IS_ENABLED(CONFIG_OFDEVICE)) + return; + + ecc_strength = of_get_nand_ecc_strength(np); + ecc_size = of_get_nand_ecc_step_size(np); + + if (ecc_strength >= 0) + chip->ecc.strength = ecc_strength; + + if (ecc_size >= 0) + chip->ecc.size = ecc_size; +} + +/** * nand_scan_ident - [NAND Interface] Scan for the NAND device * @mtd: MTD device structure * @maxchips: number of chips to scan for diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c index c3b07aa3f6..b016c5bff0 100644 --- a/drivers/mtd/nand/nand_mxs.c +++ b/drivers/mtd/nand/nand_mxs.c @@ -232,9 +232,11 @@ struct mxs_nand_info { #define GPMI_TIMING_INIT_OK (1 << 1) unsigned flags; struct nand_timing timing; + + int bb_mark_bit_offset; }; -struct nand_ecclayout fake_ecc_layout; +static struct nand_ecclayout fake_ecc_layout; static inline int mxs_nand_is_imx6(struct mxs_nand_info *info) { @@ -275,33 +277,14 @@ static uint32_t mxs_nand_ecc_chunk_cnt(uint32_t page_data_size) return page_data_size / MXS_NAND_CHUNK_DATA_CHUNK_SIZE; } -static uint32_t mxs_nand_ecc_size_in_bits(uint32_t ecc_strength) -{ - return ecc_strength * 13; -} - static uint32_t mxs_nand_aux_status_offset(void) { return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3; } -uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size, - uint32_t page_oob_size) -{ - int ecc_chunk_count = mxs_nand_ecc_chunk_cnt(page_data_size); - int ecc_strength = 0; - int gf_len = 13; /* length of Galois Field for non-DDR nand */ - - ecc_strength = ((page_oob_size - MXS_NAND_METADATA_SIZE) * 8) - / (gf_len * ecc_chunk_count); - - /* We need the minor even number. */ - return rounddown(ecc_strength, 2); -} - -static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size, - uint32_t ecc_strength) +static uint32_t mxs_nand_get_mark_offset(struct mtd_info *mtd) { + struct nand_chip *chip = mtd->priv; uint32_t chunk_data_size_in_bits; uint32_t chunk_ecc_size_in_bits; uint32_t chunk_total_size_in_bits; @@ -310,13 +293,13 @@ static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size, uint32_t block_mark_bit_offset; chunk_data_size_in_bits = MXS_NAND_CHUNK_DATA_CHUNK_SIZE * 8; - chunk_ecc_size_in_bits = mxs_nand_ecc_size_in_bits(ecc_strength); + chunk_ecc_size_in_bits = chip->ecc.strength * 13; chunk_total_size_in_bits = chunk_data_size_in_bits + chunk_ecc_size_in_bits; /* Compute the bit offset of the block mark within the physical page. */ - block_mark_bit_offset = page_data_size * 8; + block_mark_bit_offset = mtd->writesize * 8; /* Subtract the metadata bits. */ block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8; @@ -348,18 +331,62 @@ static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size, return block_mark_bit_offset; } -uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd) +static int mxs_nand_calc_geo(struct mtd_info *mtd) { - uint32_t ecc_strength; - ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize); - return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) >> 3; + struct nand_chip *chip = mtd->priv; + 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. */ + max_ecc_strength = rounddown(max_ecc_strength, 2); + + if (chip->ecc.strength) { + if (chip->ecc.strength > max_ecc_strength) { + dev_err(nand_info->dev, "invalid ecc strength %d (maximum %d)\n", + chip->ecc.strength, max_ecc_strength); + return -EINVAL; + } + } else { + chip->ecc.strength = max_ecc_strength; + } + + if (chip->ecc.size && chip->ecc.size != MXS_NAND_CHUNK_DATA_CHUNK_SIZE) { + dev_err(nand_info->dev, "invalid ecc size %d, this driver only supports %d\n", + chip->ecc.size, MXS_NAND_CHUNK_DATA_CHUNK_SIZE); + return -EINVAL; + } + + chip->ecc.bytes = DIV_ROUND_UP(13 * chip->ecc.strength, 8); + chip->ecc.size = MXS_NAND_CHUNK_DATA_CHUNK_SIZE; + + nand_info->bb_mark_bit_offset = mxs_nand_get_mark_offset(mtd); + + return 0; } -uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd) +static struct mtd_info *mxs_nand_mtd; + +int mxs_nand_get_geo(int *ecc_strength, int *bb_mark_bit_offset) { - uint32_t ecc_strength; - ecc_strength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize); - return mxs_nand_get_mark_offset(mtd->writesize, ecc_strength) & 0x7; + struct nand_chip *chip; + struct mxs_nand_info *nand_info; + + if (!mxs_nand_mtd) + return -ENODEV; + + chip = mxs_nand_mtd->priv; + nand_info = chip->priv; + + *ecc_strength = chip->ecc.strength; + *bb_mark_bit_offset = nand_info->bb_mark_bit_offset; + + return 0; } /* @@ -396,8 +423,8 @@ static int mxs_nand_wait_for_bch_complete(struct mxs_nand_info *nand_info) */ static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl) { - struct nand_chip *nand = mtd->priv; - struct mxs_nand_info *nand_info = nand->priv; + struct nand_chip *chip = mtd->priv; + 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; @@ -496,12 +523,12 @@ 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 chip) +static void mxs_nand_select_chip(struct mtd_info *mtd, int chipnum) { - struct nand_chip *nand = mtd->priv; - struct mxs_nand_info *nand_info = nand->priv; + struct nand_chip *chip = mtd->priv; + struct mxs_nand_info *nand_info = chip->priv; - nand_info->cur_chip = chip; + nand_info->cur_chip = chipnum; } /* @@ -527,8 +554,8 @@ static void mxs_nand_swap_block_mark(struct mtd_info *mtd, if (nand_info->version == GPMI_VERSION_TYPE_MX23) return; - bit_offset = mxs_nand_mark_bit_offset(mtd); - buf_offset = mxs_nand_mark_byte_offset(mtd); + bit_offset = nand_info->bb_mark_bit_offset & 0x7; + buf_offset = nand_info->bb_mark_bit_offset >> 3; /* * Get the byte from the data area that overlays the block mark. Since @@ -555,8 +582,8 @@ static void mxs_nand_swap_block_mark(struct mtd_info *mtd, */ static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length) { - struct nand_chip *nand = mtd->priv; - struct mxs_nand_info *nand_info = nand->priv; + struct nand_chip *chip = mtd->priv; + 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; @@ -633,8 +660,8 @@ rtn: 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 nand_chip *chip = mtd->priv; + 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; @@ -690,8 +717,8 @@ static uint8_t mxs_nand_read_byte(struct mtd_info *mtd) static void mxs_nand_config_bch(struct mtd_info *mtd, int readlen) { - struct nand_chip *nand = mtd->priv; - struct mxs_nand_info *nand_info = nand->priv; + struct nand_chip *chip = mtd->priv; + struct mxs_nand_info *nand_info = chip->priv; int chunk_size; void __iomem *bch_regs = nand_info->bch_base; @@ -703,13 +730,13 @@ static void mxs_nand_config_bch(struct mtd_info *mtd, int readlen) writel((mxs_nand_ecc_chunk_cnt(readlen) - 1) << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET | MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET | - (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1) + (chip->ecc.strength >> 1) << IMX6_BCH_FLASHLAYOUT0_ECC0_OFFSET | chunk_size, bch_regs + BCH_FLASH0LAYOUT0); writel(readlen << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET | - (mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1) + (chip->ecc.strength >> 1) << IMX6_BCH_FLASHLAYOUT1_ECCN_OFFSET | chunk_size, bch_regs + BCH_FLASH0LAYOUT1); @@ -718,25 +745,23 @@ 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 *nand, +static int __mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page, int readlen) { - struct mxs_nand_info *nand_info = nand->priv; + 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; uint32_t corrected = 0, failed = 0; uint8_t *status; unsigned int max_bitflips = 0; - int i, ret, readtotal, nchunks, eccstrength; - - eccstrength = mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize); + int i, ret, readtotal, nchunks; 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 * eccstrength * nchunks, 8); + readtotal += DIV_ROUND_UP(13 * chip->ecc.strength * nchunks, 8); mxs_nand_config_bch(mtd, readtotal); @@ -899,9 +924,9 @@ static int __mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand * necessary, it has already been done, so we can rely on the first * byte of the auxiliary buffer to contain the block mark. */ - memset(nand->oob_poi, 0xff, mtd->oobsize); + memset(chip->oob_poi, 0xff, mtd->oobsize); - nand->oob_poi[0] = nand_info->oob_buf[0]; + chip->oob_poi[0] = nand_info->oob_buf[0]; ret = 0; rtn: @@ -912,10 +937,10 @@ rtn: return ret ? ret : max_bitflips; } -static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand, +static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - return __mxs_nand_ecc_read_page(mtd, nand, buf, oob_required, page, + return __mxs_nand_ecc_read_page(mtd, chip, buf, oob_required, page, mtd->writesize); } @@ -939,16 +964,16 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, * Write a page to NAND. */ static int mxs_nand_ecc_write_page(struct mtd_info *mtd, - struct nand_chip *nand, const uint8_t *buf, + struct nand_chip *chip, const uint8_t *buf, int oob_required) { - struct mxs_nand_info *nand_info = nand->priv; + 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; memcpy(nand_info->data_buf, buf, mtd->writesize); - memcpy(nand_info->oob_buf, nand->oob_poi, mtd->oobsize); + 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); @@ -1112,10 +1137,10 @@ 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 *nand, +static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) { - struct mxs_nand_info *nand_info = nand->priv; + struct mxs_nand_info *nand_info = chip->priv; int column; /* @@ -1128,18 +1153,18 @@ static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand, * If control arrives here, we're doing a "raw" read. Send the * command to read the conventional OOB and read it. */ - nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); - nand->read_buf(mtd, nand->oob_poi, mtd->oobsize); + chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); } else { /* * If control arrives here, we're not doing a "raw" read. Fill * the OOB buffer with set bits and correct the block mark. */ - memset(nand->oob_poi, 0xff, mtd->oobsize); + memset(chip->oob_poi, 0xff, mtd->oobsize); column = nand_info->version == GPMI_VERSION_TYPE_MX23 ? 0 : mtd->writesize; - nand->cmdfunc(mtd, NAND_CMD_READ0, column, page); - mxs_nand_read_buf(mtd, nand->oob_poi, 1); + chip->cmdfunc(mtd, NAND_CMD_READ0, column, page); + mxs_nand_read_buf(mtd, chip->oob_poi, 1); } return 0; @@ -1149,10 +1174,10 @@ static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand, /* * Write OOB data to NAND. */ -static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand, +static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) { - struct mxs_nand_info *nand_info = nand->priv; + struct mxs_nand_info *nand_info = chip->priv; int column; uint8_t block_mark = 0; @@ -1172,12 +1197,12 @@ static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand, column = nand_info->version == GPMI_VERSION_TYPE_MX23 ? 0 : mtd->writesize; /* Write the block mark. */ - nand->cmdfunc(mtd, NAND_CMD_SEQIN, column, page); - nand->write_buf(mtd, &block_mark, 1); - nand->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + chip->cmdfunc(mtd, NAND_CMD_SEQIN, column, page); + chip->write_buf(mtd, &block_mark, 1); + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); /* Check if it worked. */ - if (nand->waitfunc(mtd, nand) & NAND_STATUS_FAIL) + if (chip->waitfunc(mtd, chip) & NAND_STATUS_FAIL) return -EIO; return 0; @@ -1217,8 +1242,8 @@ static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) */ 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 nand_chip *chip = mtd->priv; + struct mxs_nand_info *nand_info = chip->priv; void __iomem *bch_regs = nand_info->bch_base; int ret; @@ -1346,13 +1371,13 @@ err1: static void mxs_nand_probe_dt(struct device_d *dev, struct mxs_nand_info *nand_info) { - struct nand_chip *nand = &nand_info->nand_chip; + struct nand_chip *chip = &nand_info->nand_chip; if (!IS_ENABLED(CONFIG_OFTREE)) return; if (of_get_nand_on_flash_bbt(dev->device_node)) - nand->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; + chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; } /** @@ -1433,7 +1458,7 @@ static int mxs_nand_compute_hardware_timing(struct mxs_nand_info *info, struct gpmi_nfc_hardware_timing *hw) { struct timing_threshold *nfc = &timing_default_threshold; - struct nand_chip *nand = &info->nand_chip; + struct nand_chip *chip = &info->nand_chip; struct nand_timing target = info->timing; unsigned long clock_frequency_in_hz; unsigned int clock_period_in_ns; @@ -1454,11 +1479,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 (nand->numchips > 2) { + if (chip->numchips > 2) { target.data_setup_in_ns += 10; target.data_hold_in_ns += 10; target.address_setup_in_ns += 10; - } else if (nand->numchips > 1) { + } else if (chip->numchips > 1) { target.data_setup_in_ns += 5; target.data_hold_in_ns += 5; target.address_setup_in_ns += 5; @@ -2004,7 +2029,7 @@ 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 *nand = &info->nand_chip; + struct nand_chip *chip = &info->nand_chip; struct mtd_info *mtd = &info->mtd; uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {}; int ret, mode; @@ -2012,10 +2037,10 @@ static int mxs_nand_enable_edo_mode(struct mxs_nand_info *info) if (!mxs_nand_is_imx6(info)) return -ENODEV; - if (!nand->onfi_version) + if (!chip->onfi_version) return -ENOENT; - mode = onfi_get_async_timing_mode(nand); + mode = onfi_get_async_timing_mode(chip); /* We only support the timing mode 4 and mode 5. */ if (mode & ONFI_TIMING_MODE_5) @@ -2025,27 +2050,27 @@ static int mxs_nand_enable_edo_mode(struct mxs_nand_info *info) else return -EINVAL; - nand->select_chip(mtd, 0); + chip->select_chip(mtd, 0); - if (le16_to_cpu(nand->onfi_params.opt_cmd) + if (le16_to_cpu(chip->onfi_params.opt_cmd) & ONFI_OPT_CMD_SET_GET_FEATURES) { /* [1] send SET FEATURE commond to NAND */ feature[0] = mode; - ret = nand->onfi_set_features(mtd, nand, + ret = chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_TIMING_MODE, feature); if (ret) goto err_out; /* [2] send GET FEATURE command to double-check the timing mode */ - ret = nand->onfi_get_features(mtd, nand, + ret = chip->onfi_get_features(mtd, chip, ONFI_FEATURE_ADDR_TIMING_MODE, feature); if (ret || feature[0] != mode) goto err_out; } - nand->select_chip(mtd, -1); + chip->select_chip(mtd, -1); /* [3] set the main IO clock, 100MHz for mode 5, 80MHz for mode 4. */ clk_disable(info->clk); @@ -2057,7 +2082,7 @@ static int mxs_nand_enable_edo_mode(struct mxs_nand_info *info) return mode; err_out: - nand->select_chip(mtd, -1); + chip->select_chip(mtd, -1); return -EINVAL; } @@ -2112,11 +2137,15 @@ static int mxs_nand_probe(struct device_d *dev) { struct resource *iores; struct mxs_nand_info *nand_info; - struct nand_chip *nand; + struct nand_chip *chip; struct mtd_info *mtd; enum gpmi_type type; int err; + /* We expect only one */ + if (mxs_nand_mtd) + return -EBUSY; + err = dev_get_drvdata(dev, (const void **)&type); if (err) type = GPMI_MXS; @@ -2165,50 +2194,49 @@ static int mxs_nand_probe(struct device_d *dev) if (err) goto err2; - memset(&fake_ecc_layout, 0, sizeof(fake_ecc_layout)); - /* structures must be linked */ - nand = &nand_info->nand_chip; + chip = &nand_info->nand_chip; mtd = &nand_info->mtd; - mtd->priv = nand; + mtd->priv = chip; mtd->parent = dev; - nand->priv = nand_info; + chip->priv = nand_info; - nand->cmd_ctrl = mxs_nand_cmd_ctrl; + chip->cmd_ctrl = mxs_nand_cmd_ctrl; - nand->dev_ready = mxs_nand_device_ready; - nand->select_chip = mxs_nand_select_chip; - nand->block_bad = mxs_nand_block_bad; - nand->scan_bbt = mxs_nand_scan_bbt; + 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; - nand->read_byte = mxs_nand_read_byte; + chip->read_byte = mxs_nand_read_byte; - nand->read_buf = mxs_nand_read_buf; - nand->write_buf = mxs_nand_write_buf; + chip->read_buf = mxs_nand_read_buf; + chip->write_buf = mxs_nand_write_buf; - nand->ecc.read_page = mxs_nand_ecc_read_page; - nand->ecc.write_page = mxs_nand_ecc_write_page; - nand->ecc.read_oob = mxs_nand_ecc_read_oob; - nand->ecc.write_oob = mxs_nand_ecc_write_oob; + 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; - nand->ecc.layout = &fake_ecc_layout; - nand->ecc.mode = NAND_ECC_HW; - nand->ecc.bytes = 9; - nand->ecc.size = 512; - nand->ecc.strength = 8; + 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); if (err) goto err2; - if ((13 * mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) % 8) == 0) { - nand->ecc.read_subpage = gpmi_ecc_read_subpage; - nand->options |= NAND_SUBPAGE_READ; + err = mxs_nand_calc_geo(mtd); + if (err) + goto err2; + + if ((13 * chip->ecc.strength % 8) == 0) { + chip->ecc.read_subpage = gpmi_ecc_read_subpage; + chip->options |= NAND_SUBPAGE_READ; } - nand->options |= NAND_NO_SUBPAGE_WRITE; + chip->options |= NAND_NO_SUBPAGE_WRITE; mxs_nand_setup_timing(nand_info); @@ -2217,12 +2245,21 @@ static int mxs_nand_probe(struct device_d *dev) if (err) goto err2; - return add_mtd_nand_device(mtd, "nand"); + err = add_mtd_nand_device(mtd, "nand"); + if (err) + goto err2; + + mxs_nand_mtd = mtd; + + return 0; err2: free(nand_info->data_buf); free(nand_info->cmd_buf); err1: free(nand_info); + + mxs_nand_mtd = NULL; + return err; } |