diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-10 13:15:17 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-10 13:15:17 -0700 |
commit | 6f51ab9440d131ae424cce27e3170746219f5142 (patch) | |
tree | e198f70fb53214ca67db8ffb76cafc29852c05df /drivers/mtd/nand/raw/nand_onfi.c | |
parent | 6f630784cc0d92fb58ea326e2bc01aa056279ecb (diff) | |
parent | 5788ccf3c84f5587418a80128a3653aa35abf00b (diff) |
Merge tag 'mtd/for-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux
Pull MTD updates from Richard Weinberger:
"MTD core changes:
- partition parser: Support MTD names containing one or more colons.
- mtdblock: clear cache_state to avoid writing to bad blocks
repeatedly.
Raw NAND core changes:
- Stop using nand_release(), patched all drivers.
- Give more information about the ECC weakness when not matching the
chip's requirement.
- MAINTAINERS updates.
- Support emulated SLC mode on MLC NANDs.
- Support "constrained" controllers, adapt the core and ONFI/JEDEC
table parsing and Micron's code.
- Take check_only into account.
- Add an invalid ECC mode to discriminate with valid ones.
- Return an enum from of_get_nand_ecc_algo().
- Drop OOB_FIRST placement scheme.
- Introduce nand_extract_bits().
- Ensure a consistent bitflips numbering.
- BCH lib:
- Allow easy bit swapping.
- Rework a little bit the exported function names.
- Fix nand_gpio_waitrdy().
- Propage CS selection to sub operations.
- Add a NAND_NO_BBM_QUIRK flag.
- Give the possibility to verify a read operation is supported.
- Add a helper to check supported operations.
- Avoid indirect access to ->data_buf().
- Rename the use_bufpoi variables.
- Fix comments about the use of bufpoi.
- Rename a NAND chip option.
- Reorder the nand_chip->options flags.
- Translate obscure bitfields into readable macros.
- Timings:
- Fix default values.
- Add mode information to the timings structure.
Raw NAND controller driver changes:
- Fixed many error paths.
- Arasan
- New driver
- Au1550nd:
- Various cleanups
- Migration to ->exec_op()
- brcmnand:
- Misc cleanup.
- Support v2.1-v2.2 controllers.
- Remove unused including <linux/version.h>.
- Correctly verify erased pages.
- Fix Hamming OOB layout.
- Cadence
- Make cadence_nand_attach_chip static.
- Cafe:
- Set the NAND_NO_BBM_QUIRK flag
- cmx270:
- Remove this controller driver.
- cs553x:
- Misc cleanup
- Migration to ->exec_op()
- Davinci:
- Misc cleanup.
- Migration to ->exec_op()
- Denali:
- Add more delays before latching incoming data
- Diskonchip:
- Misc cleanup
- Migration to ->exec_op()
- Fsmc:
- Change to non-atomic bit operations.
- GPMI:
- Use nand_extract_bits()
- Fix runtime PM imbalance.
- Ingenic:
- Migration to exec_op()
- Fix the RB gpio active-high property on qi, lb60
- Make qi_lb60_ooblayout_ops static.
- Marvell:
- Misc cleanup and small fixes
- Nandsim:
- Fix the error paths, driver wide.
- Omap_elm:
- Fix runtime PM imbalance.
- STM32_FMC2:
- Misc cleanups (error cases, comments, timeout valus, cosmetic
changes).
SPI NOR core changes:
- Add, update support and fix few flashes.
- Prepare BFPT parsing for JESD216 rev D.
- Kernel doc fixes.
CFI changes:
- Support the absence of protection registers for Intel CFI flashes.
- Replace zero-length array with flexible-arrays"
* tag 'mtd/for-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (208 commits)
mtd: clear cache_state to avoid writing to bad blocks repeatedly
mtd: parser: cmdline: Support MTD names containing one or more colons
mtd: physmap_of_gemini: remove defined but not used symbol 'syscon_match'
mtd: rawnand: Add an invalid ECC mode to discriminate with valid ones
mtd: rawnand: Return an enum from of_get_nand_ecc_algo()
mtd: rawnand: Drop OOB_FIRST placement scheme
mtd: rawnand: Avoid a typedef
mtd: Fix typo in mtd_ooblayout_set_databytes() description
mtd: rawnand: Stop using nand_release()
mtd: rawnand: nandsim: Reorganize ns_cleanup_module()
mtd: rawnand: nandsim: Rename a label in ns_init_module()
mtd: rawnand: nandsim: Manage lists on error in ns_init_module()
mtd: rawnand: nandsim: Fix the label pointing on nand_cleanup()
mtd: rawnand: nandsim: Free erase_block_wear on error
mtd: rawnand: nandsim: Use an additional label when freeing the nandsim object
mtd: rawnand: nandsim: Stop using nand_release()
mtd: rawnand: nandsim: Free the partition names in ns_free()
mtd: rawnand: nandsim: Free the allocated device on error in ns_init()
mtd: rawnand: nandsim: Free partition names on error in ns_init()
mtd: rawnand: nandsim: Fix the two ns_alloc_device() error paths
...
Diffstat (limited to 'drivers/mtd/nand/raw/nand_onfi.c')
-rw-r--r-- | drivers/mtd/nand/raw/nand_onfi.c | 71 |
1 files changed, 42 insertions, 29 deletions
diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c index 0b879bd0a68c..be3456627288 100644 --- a/drivers/mtd/nand/raw/nand_onfi.c +++ b/drivers/mtd/nand/raw/nand_onfi.c @@ -16,6 +16,8 @@ #include "internals.h" +#define ONFI_PARAM_PAGES 3 + u16 onfi_crc16(u16 crc, u8 const *p, size_t len) { int i; @@ -45,12 +47,10 @@ static int nand_flash_detect_ext_param_page(struct nand_chip *chip, if (!ep) return -ENOMEM; - /* Send our own NAND_CMD_PARAM. */ - ret = nand_read_param_page_op(chip, 0, NULL, 0); - if (ret) - goto ext_out; - - /* Use the Change Read Column command to skip the ONFI param pages. */ + /* + * Use the Change Read Column command to skip the ONFI param pages and + * ensure we read at the right location. + */ ret = nand_change_read_column_op(chip, sizeof(*p) * p->num_of_param_pages, ep, len, true); @@ -141,11 +141,13 @@ int nand_onfi_detect(struct nand_chip *chip) { struct mtd_info *mtd = nand_to_mtd(chip); struct nand_memory_organization *memorg; - struct nand_onfi_params *p; + struct nand_onfi_params *p = NULL, *pbuf; struct onfi_params *onfi; + bool use_datain = false; int onfi_version = 0; char id[4]; int i, ret, val; + u16 crc; memorg = nanddev_get_memorg(&chip->base); @@ -155,43 +157,54 @@ int nand_onfi_detect(struct nand_chip *chip) return 0; /* ONFI chip: allocate a buffer to hold its parameter page */ - p = kzalloc((sizeof(*p) * 3), GFP_KERNEL); - if (!p) + pbuf = kzalloc((sizeof(*pbuf) * ONFI_PARAM_PAGES), GFP_KERNEL); + if (!pbuf) return -ENOMEM; - ret = nand_read_param_page_op(chip, 0, NULL, 0); - if (ret) { - ret = 0; - goto free_onfi_param_page; - } - - for (i = 0; i < 3; i++) { - ret = nand_read_data_op(chip, &p[i], sizeof(*p), true); + if (!nand_has_exec_op(chip) || + !nand_read_data_op(chip, &pbuf[0], sizeof(*pbuf), true, true)) + use_datain = true; + + for (i = 0; i < ONFI_PARAM_PAGES; i++) { + if (!i) + ret = nand_read_param_page_op(chip, 0, &pbuf[i], + sizeof(*pbuf)); + else if (use_datain) + ret = nand_read_data_op(chip, &pbuf[i], sizeof(*pbuf), + true, false); + else + ret = nand_change_read_column_op(chip, sizeof(*pbuf) * i, + &pbuf[i], sizeof(*pbuf), + true); if (ret) { ret = 0; goto free_onfi_param_page; } - if (onfi_crc16(ONFI_CRC_BASE, (u8 *)&p[i], 254) == - le16_to_cpu(p->crc)) { - if (i) - memcpy(p, &p[i], sizeof(*p)); + crc = onfi_crc16(ONFI_CRC_BASE, (u8 *)&pbuf[i], 254); + if (crc == le16_to_cpu(pbuf[i].crc)) { + p = &pbuf[i]; break; } } - if (i == 3) { - const void *srcbufs[3] = {p, p + 1, p + 2}; + if (i == ONFI_PARAM_PAGES) { + const void *srcbufs[ONFI_PARAM_PAGES]; + unsigned int j; + + for (j = 0; j < ONFI_PARAM_PAGES; j++) + srcbufs[j] = pbuf + j; pr_warn("Could not find a valid ONFI parameter page, trying bit-wise majority to recover it\n"); - nand_bit_wise_majority(srcbufs, ARRAY_SIZE(srcbufs), p, - sizeof(*p)); + nand_bit_wise_majority(srcbufs, ONFI_PARAM_PAGES, pbuf, + sizeof(*pbuf)); - if (onfi_crc16(ONFI_CRC_BASE, (u8 *)p, 254) != - le16_to_cpu(p->crc)) { + crc = onfi_crc16(ONFI_CRC_BASE, (u8 *)pbuf, 254); + if (crc != le16_to_cpu(pbuf->crc)) { pr_err("ONFI parameter recovery failed, aborting\n"); goto free_onfi_param_page; } + p = pbuf; } if (chip->manufacturer.desc && chip->manufacturer.desc->ops && @@ -299,14 +312,14 @@ int nand_onfi_detect(struct nand_chip *chip) chip->parameters.onfi = onfi; /* Identification done, free the full ONFI parameter page and exit */ - kfree(p); + kfree(pbuf); return 1; free_model: kfree(chip->parameters.model); free_onfi_param_page: - kfree(p); + kfree(pbuf); return ret; } |