diff options
Diffstat (limited to 'drivers/mtd/nand/raw')
-rw-r--r-- | drivers/mtd/nand/raw/cafe_nand.c | 7 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/diskonchip.c | 67 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/marvell_nand.c | 20 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/nand_base.c | 5 |
4 files changed, 54 insertions, 45 deletions
diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index d8c8c9d1e640..d721f489b38b 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -394,12 +394,13 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, for (i=0; i<8; i+=2) { uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN01 + (i*2)); - syn[i] = cafe->rs->index_of[tmp & 0xfff]; - syn[i+1] = cafe->rs->index_of[(tmp >> 16) & 0xfff]; + + syn[i] = cafe->rs->codec->index_of[tmp & 0xfff]; + syn[i+1] = cafe->rs->codec->index_of[(tmp >> 16) & 0xfff]; } n = decode_rs16(cafe->rs, NULL, NULL, 1367, syn, 0, pos, 0, - pat); + pat); for (i = 0; i < n; i++) { int p = pos[i]; diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c index 86a258de0b75..2b7b2b982b77 100644 --- a/drivers/mtd/nand/raw/diskonchip.c +++ b/drivers/mtd/nand/raw/diskonchip.c @@ -66,6 +66,7 @@ struct doc_priv { int curchip; int mh0_page; int mh1_page; + struct rs_control *rs_decoder; struct mtd_info *nextdoc; /* Handle the last stage of initialization (BBT scan, partitioning) */ @@ -123,9 +124,6 @@ MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe /* Number of symbols */ #define NN 1023 -/* the Reed Solomon control structure */ -static struct rs_control *rs_decoder; - /* * The HW decoder in the DoC ASIC's provides us a error syndrome, * which we must convert to a standard syndrome usable by the generic @@ -140,6 +138,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) int i, j, nerr, errpos[8]; uint8_t parity; uint16_t ds[4], s[5], tmp, errval[8], syn[4]; + struct rs_codec *cd = rs->codec; memset(syn, 0, sizeof(syn)); /* Convert the ecc bytes into words */ @@ -160,15 +159,15 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) for (j = 1; j < NROOTS; j++) { if (ds[j] == 0) continue; - tmp = rs->index_of[ds[j]]; + tmp = cd->index_of[ds[j]]; for (i = 0; i < NROOTS; i++) - s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; + s[i] ^= cd->alpha_to[rs_modnn(cd, tmp + (FCR + i) * j)]; } /* Calc syn[i] = s[i] / alpha^(v + i) */ for (i = 0; i < NROOTS; i++) { if (s[i]) - syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); + syn[i] = rs_modnn(cd, cd->index_of[s[i]] + (NN - FCR - i)); } /* Call the decoder library */ nerr = decode_rs16(rs, NULL, NULL, 1019, syn, 0, errpos, 0, errval); @@ -930,7 +929,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, calc_ecc[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i); } - ret = doc_ecc_decode(rs_decoder, dat, calc_ecc); + ret = doc_ecc_decode(doc->rs_decoder, dat, calc_ecc); if (ret > 0) pr_err("doc200x_correct_data corrected %d errors\n", ret); @@ -1421,10 +1420,10 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd) static int __init doc_probe(unsigned long physadr) { + struct nand_chip *nand = NULL; + struct doc_priv *doc = NULL; unsigned char ChipID; struct mtd_info *mtd; - struct nand_chip *nand; - struct doc_priv *doc; void __iomem *virtadr; unsigned char save_control; unsigned char tmp, tmpb, tmpc; @@ -1561,8 +1560,25 @@ static int __init doc_probe(unsigned long physadr) goto fail; } + + /* + * Allocate a RS codec instance + * + * Symbolsize is 10 (bits) + * Primitve polynomial is x^10+x^3+1 + * First consecutive root is 510 + * Primitve element to generate roots = 1 + * Generator polinomial degree = 4 + */ + doc = (struct doc_priv *) (nand + 1); + doc->rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS); + if (!doc->rs_decoder) { + pr_err("DiskOnChip: Could not create a RS codec\n"); + ret = -ENOMEM; + goto fail; + } + mtd = nand_to_mtd(nand); - doc = (struct doc_priv *) (nand + 1); nand->bbt_td = (struct nand_bbt_descr *) (doc + 1); nand->bbt_md = nand->bbt_td + 1; @@ -1612,7 +1628,6 @@ static int __init doc_probe(unsigned long physadr) haven't yet added it. This is handled without incident by mtd_device_unregister, as far as I can tell. */ nand_release(mtd); - kfree(nand); goto fail; } @@ -1625,6 +1640,9 @@ static int __init doc_probe(unsigned long physadr) actually a DiskOnChip. */ WriteDOC(save_control, virtadr, DOCControl); fail: + if (doc) + free_rs(doc->rs_decoder); + kfree(nand); iounmap(virtadr); error_ioremap: @@ -1647,6 +1665,7 @@ static void release_nanddoc(void) nand_release(mtd); iounmap(doc->virtadr); release_mem_region(doc->physadr, DOC_IOREMAP_LEN); + free_rs(doc->rs_decoder); kfree(nand); } } @@ -1655,27 +1674,12 @@ static int __init init_nanddoc(void) { int i, ret = 0; - /* We could create the decoder on demand, if memory is a concern. - * This way we have it handy, if an error happens - * - * Symbolsize is 10 (bits) - * Primitve polynomial is x^10+x^3+1 - * first consecutive root is 510 - * primitve element to generate roots = 1 - * generator polinomial degree = 4 - */ - rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS); - if (!rs_decoder) { - pr_err("DiskOnChip: Could not create a RS decoder\n"); - return -ENOMEM; - } - if (doc_config_location) { pr_info("Using configured DiskOnChip probe address 0x%lx\n", doc_config_location); ret = doc_probe(doc_config_location); if (ret < 0) - goto outerr; + return ret; } else { for (i = 0; (doc_locations[i] != 0xffffffff); i++) { doc_probe(doc_locations[i]); @@ -1686,11 +1690,7 @@ static int __init init_nanddoc(void) if (!doclist) { pr_info("No valid DiskOnChip devices found\n"); ret = -ENODEV; - goto outerr; } - return 0; - outerr: - free_rs(rs_decoder); return ret; } @@ -1698,11 +1698,6 @@ static void __exit cleanup_nanddoc(void) { /* Cleanup the nand/DoC resources */ release_nanddoc(); - - /* Free the reed solomon resources */ - if (rs_decoder) { - free_rs(rs_decoder); - } } module_init(init_nanddoc); diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 1d779a35ac8e..ebb1d141b900 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -1074,7 +1074,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip, return ret; ret = marvell_nfc_wait_op(chip, - chip->data_interface.timings.sdr.tPROG_max); + PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max)); return ret; } @@ -1194,11 +1194,13 @@ static void marvell_nfc_hw_ecc_bch_read_chunk(struct nand_chip *chip, int chunk, NDCB0_CMD2(NAND_CMD_READSTART); /* - * Trigger the naked read operation only on the last chunk. - * Otherwise, use monolithic read. + * Trigger the monolithic read on the first chunk, then naked read on + * intermediate chunks and finally a last naked read on the last chunk. */ - if (lt->nchunks == 1 || (chunk < lt->nchunks - 1)) + if (chunk == 0) nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_MONOLITHIC_RW); + else if (chunk < lt->nchunks - 1) + nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_NAKED_RW); else nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_LAST_NAKED_RW); @@ -1408,6 +1410,7 @@ marvell_nfc_hw_ecc_bch_write_chunk(struct nand_chip *chip, int chunk, struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip); struct marvell_nfc *nfc = to_marvell_nfc(chip->controller); const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout; + u32 xtype; int ret; struct marvell_nfc_op nfc_op = { .ndcb[0] = NDCB0_CMD_TYPE(TYPE_WRITE) | NDCB0_LEN_OVRD, @@ -1423,7 +1426,12 @@ marvell_nfc_hw_ecc_bch_write_chunk(struct nand_chip *chip, int chunk, * last naked write. */ if (chunk == 0) { - nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_WRITE_DISPATCH) | + if (lt->nchunks == 1) + xtype = XTYPE_MONOLITHIC_RW; + else + xtype = XTYPE_WRITE_DISPATCH; + + nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(xtype) | NDCB0_ADDR_CYC(marvell_nand->addr_cyc) | NDCB0_CMD1(NAND_CMD_SEQIN); nfc_op.ndcb[1] |= NDCB1_ADDRS_PAGE(page); @@ -1494,7 +1502,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct mtd_info *mtd, } ret = marvell_nfc_wait_op(chip, - chip->data_interface.timings.sdr.tPROG_max); + PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max)); marvell_nfc_disable_hw_ecc(chip); diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 72f3a89da513..f28c3a555861 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -706,12 +706,17 @@ static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo) */ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms) { + const struct nand_sdr_timings *timings; u8 status = 0; int ret; if (!chip->exec_op) return -ENOTSUPP; + /* Wait tWB before polling the STATUS reg. */ + timings = nand_get_sdr_timings(&chip->data_interface); + ndelay(PSEC_TO_NSEC(timings->tWB_max)); + ret = nand_status_op(chip, NULL); if (ret) return ret; |