diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-29 11:11:56 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-29 11:11:56 -0800 |
commit | 0fc7e74663447682c904fe375bb680b004ddaa14 (patch) | |
tree | 95f89c4a207995e57354c4f44bf7d83b5536370c /drivers/mtd/nand/gpmi-nand | |
parent | aa5e75bc7a7c4ecbdee7bc85d1a306041b926e24 (diff) | |
parent | 571cb17b23eccc22f18c4fc0a0fc34cf0abca7ef (diff) |
Merge tag 'mtd/for-4.16' of git://git.infradead.org/linux-mtd
Pull MTD updates from Boris Brezillon:
"MTD core changes:
- Rework core functions to avoid duplicating generic checks in
NAND/OneNAND sub-layers
- Update the MAINTAINERS entry to reflect the fact that MTD
maintainers now use a single git tree
MTD driver changes:
- CFI: use macros instead of inline functions to limit stack usage
and make KASAN happy
NAND core changes:
- Fix NAND_CMD_NONE handling in nand_command[_lp]() hooks
- Introduce the ->exec_op() infrastructure
- Rework NAND buffers handling
- Fix ECC requirements for K9F4G08U0D
- Fix nand_do_read_oob() to return the number of bitflips
- Mark K9F1G08U0E as not supporting subpage writes
NAND driver changes:
- MTK: Rework the driver to support new IP versions
- OMAP OneNAND: Full rework to use new APIs (libgpio, dmaengine) and
fix DT support
- Marvell: Add a new driver to replace the pxa3xx one
SPI NOR core changes:
- Add support to new ISSI and Cypress/Spansion memory parts.
- Fix support of Micron memories by checking error bits in the FSR.
- Fix update of block-protection bits by reading back the SR.
- Restore the internal state of the SPI flash memory when removing
the device.
SPI NOR driver changes:
- Maintenance for Freescale, Intel and Metiatek drivers.
- Add support of the direct access mode for the Cadence QSPI
controller"
* tag 'mtd/for-4.16' of git://git.infradead.org/linux-mtd: (93 commits)
mtd: nand: sunxi: Fix ECC strength choice
mtd: nand: gpmi: Fix subpage reads
mtd: nand: Fix build issues due to an anonymous union
mtd: nand: marvell: Fix missing memory allocation modifier
mtd: nand: marvell: remove redundant variable 'oob_len'
mtd: nand: marvell: fix spelling mistake: "suceed"-> "succeed"
mtd: onenand: omap2: Remove redundant dev_err call in omap2_onenand_probe()
mtd: Remove duplicate checks on mtd_oob_ops parameter
mtd: Fallback to ->_read/write_oob() when ->_read/write() is missing
mtd: mtdpart: Make ECC stat handling consistent
mtd: onenand: omap2: print resource using %pR format string
mtd: mtk-nor: modify functions' name more generally
mtd: onenand: samsung: remove incorrect __iomem annotation
MAINTAINERS: Add entry for Marvell NAND controller driver
ARM: OMAP2+: Remove gpmc-onenand
mtd: onenand: omap2: Configure driver from DT
mtd: onenand: omap2: Decouple DMA enabling from INT pin availability
mtd: onenand: omap2: Do not make delay for GPIO OMAP3 specific
mtd: onenand: omap2: Convert to use dmaengine for memcpy
mtd: onenand: omap2: Unify OMAP2 and OMAP3 DMA implementation
...
Diffstat (limited to 'drivers/mtd/nand/gpmi-nand')
-rw-r--r-- | drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 111 | ||||
-rw-r--r-- | drivers/mtd/nand/gpmi-nand/gpmi-nand.h | 46 |
2 files changed, 69 insertions, 88 deletions
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index d4d824ef64e9..61fdd733492f 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -1029,11 +1029,13 @@ static void block_mark_swapping(struct gpmi_nand_data *this, p[1] = (p[1] & mask) | (from_oob >> (8 - bit)); } -static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int oob_required, int page) +static int gpmi_ecc_read_page_data(struct nand_chip *chip, + uint8_t *buf, int oob_required, + int page) { struct gpmi_nand_data *this = nand_get_controller_data(chip); struct bch_geometry *nfc_geo = &this->bch_geometry; + struct mtd_info *mtd = nand_to_mtd(chip); void *payload_virt; dma_addr_t payload_phys; void *auxiliary_virt; @@ -1094,8 +1096,8 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, eccbytes = DIV_ROUND_UP(offset + eccbits, 8); offset /= 8; eccbytes -= offset; - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, offset, -1); - chip->read_buf(mtd, eccbuf, eccbytes); + nand_change_read_column_op(chip, offset, eccbuf, + eccbytes, false); /* * ECC data are not byte aligned and we may have @@ -1176,6 +1178,14 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, return max_bitflips; } +static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, + uint8_t *buf, int oob_required, int page) +{ + nand_read_page_op(chip, page, 0, NULL, 0); + + return gpmi_ecc_read_page_data(chip, buf, oob_required, page); +} + /* Fake a virtual small page for the subpage read */ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t offs, uint32_t len, uint8_t *buf, int page) @@ -1220,12 +1230,12 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, meta = geo->metadata_size; if (first) { col = meta + (size + ecc_parity_size) * first; - chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1); - meta = 0; buf = buf + first * size; } + nand_read_page_op(chip, page, col, NULL, 0); + /* Save the old environment */ r1_old = r1_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT0); r2_old = r2_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT1); @@ -1254,7 +1264,7 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, /* Read the subpage now */ this->swap_block_mark = false; - max_bitflips = gpmi_ecc_read_page(mtd, chip, buf, 0, page); + max_bitflips = gpmi_ecc_read_page_data(chip, buf, 0, page); /* Restore */ writel(r1_old, bch_regs + HW_BCH_FLASH0LAYOUT0); @@ -1277,6 +1287,9 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, int ret; dev_dbg(this->dev, "ecc write page.\n"); + + nand_prog_page_begin_op(chip, page, 0, NULL, 0); + if (this->swap_block_mark) { /* * If control arrives here, we're doing block mark swapping. @@ -1338,7 +1351,10 @@ exit_auxiliary: payload_virt, payload_phys); } - return 0; + if (ret) + return ret; + + return nand_prog_page_end_op(chip); } /* @@ -1411,7 +1427,7 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, memset(chip->oob_poi, ~0, mtd->oobsize); /* Read out the conventional OOB. */ - chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); + nand_read_page_op(chip, page, mtd->writesize, NULL, 0); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); /* @@ -1421,7 +1437,7 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, */ if (GPMI_IS_MX23(this)) { /* Read the block mark into the first byte of the OOB buffer. */ - chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); + nand_read_page_op(chip, page, 0, NULL, 0); chip->oob_poi[0] = chip->read_byte(mtd); } @@ -1432,7 +1448,6 @@ static int gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) { struct mtd_oob_region of = { }; - int status = 0; /* Do we have available oob area? */ mtd_ooblayout_free(mtd, 0, &of); @@ -1442,12 +1457,8 @@ gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) if (!nand_is_slc(chip)) return -EPERM; - chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + of.offset, page); - chip->write_buf(mtd, chip->oob_poi + of.offset, of.length); - chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); - - status = chip->waitfunc(mtd, chip); - return status & NAND_STATUS_FAIL ? -EIO : 0; + return nand_prog_page_op(chip, page, mtd->writesize + of.offset, + chip->oob_poi + of.offset, of.length); } /* @@ -1477,8 +1488,8 @@ static int gpmi_ecc_read_page_raw(struct mtd_info *mtd, uint8_t *oob = chip->oob_poi; int step; - chip->read_buf(mtd, tmp_buf, - mtd->writesize + mtd->oobsize); + nand_read_page_op(chip, page, 0, tmp_buf, + mtd->writesize + mtd->oobsize); /* * If required, swap the bad block marker and the data stored in the @@ -1487,12 +1498,8 @@ static int gpmi_ecc_read_page_raw(struct mtd_info *mtd, * See the layout description for a detailed explanation on why this * is needed. */ - if (this->swap_block_mark) { - u8 swap = tmp_buf[0]; - - tmp_buf[0] = tmp_buf[mtd->writesize]; - tmp_buf[mtd->writesize] = swap; - } + if (this->swap_block_mark) + swap(tmp_buf[0], tmp_buf[mtd->writesize]); /* * Copy the metadata section into the oob buffer (this section is @@ -1615,31 +1622,22 @@ static int gpmi_ecc_write_page_raw(struct mtd_info *mtd, * See the layout description for a detailed explanation on why this * is needed. */ - if (this->swap_block_mark) { - u8 swap = tmp_buf[0]; - - tmp_buf[0] = tmp_buf[mtd->writesize]; - tmp_buf[mtd->writesize] = swap; - } + if (this->swap_block_mark) + swap(tmp_buf[0], tmp_buf[mtd->writesize]); - chip->write_buf(mtd, tmp_buf, mtd->writesize + mtd->oobsize); - - return 0; + return nand_prog_page_op(chip, page, 0, tmp_buf, + mtd->writesize + mtd->oobsize); } static int gpmi_ecc_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, int page) { - chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); - return gpmi_ecc_read_page_raw(mtd, chip, NULL, 1, page); } static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, int page) { - chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page); - return gpmi_ecc_write_page_raw(mtd, chip, NULL, 1, page); } @@ -1649,7 +1647,7 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) struct gpmi_nand_data *this = nand_get_controller_data(chip); int ret = 0; uint8_t *block_mark; - int column, page, status, chipnr; + int column, page, chipnr; chipnr = (int)(ofs >> chip->chip_shift); chip->select_chip(mtd, chipnr); @@ -1663,13 +1661,7 @@ static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) /* Shift to get page */ page = (int)(ofs >> chip->page_shift); - chip->cmdfunc(mtd, NAND_CMD_SEQIN, column, page); - chip->write_buf(mtd, block_mark, 1); - chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); - - status = chip->waitfunc(mtd, chip); - if (status & NAND_STATUS_FAIL) - ret = -EIO; + ret = nand_prog_page_op(chip, page, column, block_mark, 1); chip->select_chip(mtd, -1); @@ -1712,7 +1704,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this) unsigned int search_area_size_in_strides; unsigned int stride; unsigned int page; - uint8_t *buffer = chip->buffers->databuf; + uint8_t *buffer = chip->data_buf; int saved_chip_number; int found_an_ncb_fingerprint = false; @@ -1737,7 +1729,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this) * Read the NCB fingerprint. The fingerprint is four bytes long * and starts in the 12th byte of the page. */ - chip->cmdfunc(mtd, NAND_CMD_READ0, 12, page); + nand_read_page_op(chip, page, 12, NULL, 0); chip->read_buf(mtd, buffer, strlen(fingerprint)); /* Look for the fingerprint. */ @@ -1771,7 +1763,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this) unsigned int block; unsigned int stride; unsigned int page; - uint8_t *buffer = chip->buffers->databuf; + uint8_t *buffer = chip->data_buf; int saved_chip_number; int status; @@ -1797,17 +1789,10 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this) dev_dbg(dev, "Erasing the search area...\n"); for (block = 0; block < search_area_size_in_blocks; block++) { - /* Compute the page address. */ - page = block * block_size_in_pages; - /* Erase this block. */ dev_dbg(dev, "\tErasing block 0x%x\n", block); - chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); - chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); - - /* Wait for the erase to finish. */ - status = chip->waitfunc(mtd, chip); - if (status & NAND_STATUS_FAIL) + status = nand_erase_op(chip, block); + if (status) dev_err(dev, "[%s] Erase failed.\n", __func__); } @@ -1823,13 +1808,9 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this) /* Write the first page of the current stride. */ dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page); - chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); - chip->ecc.write_page_raw(mtd, chip, buffer, 0, page); - chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); - /* Wait for the write to finish. */ - status = chip->waitfunc(mtd, chip); - if (status & NAND_STATUS_FAIL) + status = chip->ecc.write_page_raw(mtd, chip, buffer, 0, page); + if (status) dev_err(dev, "[%s] Write failed.\n", __func__); } @@ -1884,7 +1865,7 @@ static int mx23_boot_init(struct gpmi_nand_data *this) /* Send the command to read the conventional block mark. */ chip->select_chip(mtd, chipnr); - chip->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page); + nand_read_page_op(chip, page, mtd->writesize, NULL, 0); block_mark = chip->read_byte(mtd); chip->select_chip(mtd, -1); diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h index a45e4ce13d10..06c1f993912c 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h @@ -268,31 +268,31 @@ struct timing_threshold { }; /* Common Services */ -extern int common_nfc_set_geometry(struct gpmi_nand_data *); -extern struct dma_chan *get_dma_chan(struct gpmi_nand_data *); -extern void prepare_data_dma(struct gpmi_nand_data *, - enum dma_data_direction dr); -extern int start_dma_without_bch_irq(struct gpmi_nand_data *, - struct dma_async_tx_descriptor *); -extern int start_dma_with_bch_irq(struct gpmi_nand_data *, - struct dma_async_tx_descriptor *); +int common_nfc_set_geometry(struct gpmi_nand_data *); +struct dma_chan *get_dma_chan(struct gpmi_nand_data *); +void prepare_data_dma(struct gpmi_nand_data *, + enum dma_data_direction dr); +int start_dma_without_bch_irq(struct gpmi_nand_data *, + struct dma_async_tx_descriptor *); +int start_dma_with_bch_irq(struct gpmi_nand_data *, + struct dma_async_tx_descriptor *); /* GPMI-NAND helper function library */ -extern int gpmi_init(struct gpmi_nand_data *); -extern int gpmi_extra_init(struct gpmi_nand_data *); -extern void gpmi_clear_bch(struct gpmi_nand_data *); -extern void gpmi_dump_info(struct gpmi_nand_data *); -extern int bch_set_geometry(struct gpmi_nand_data *); -extern int gpmi_is_ready(struct gpmi_nand_data *, unsigned chip); -extern int gpmi_send_command(struct gpmi_nand_data *); -extern void gpmi_begin(struct gpmi_nand_data *); -extern void gpmi_end(struct gpmi_nand_data *); -extern int gpmi_read_data(struct gpmi_nand_data *); -extern int gpmi_send_data(struct gpmi_nand_data *); -extern int gpmi_send_page(struct gpmi_nand_data *, - dma_addr_t payload, dma_addr_t auxiliary); -extern int gpmi_read_page(struct gpmi_nand_data *, - dma_addr_t payload, dma_addr_t auxiliary); +int gpmi_init(struct gpmi_nand_data *); +int gpmi_extra_init(struct gpmi_nand_data *); +void gpmi_clear_bch(struct gpmi_nand_data *); +void gpmi_dump_info(struct gpmi_nand_data *); +int bch_set_geometry(struct gpmi_nand_data *); +int gpmi_is_ready(struct gpmi_nand_data *, unsigned chip); +int gpmi_send_command(struct gpmi_nand_data *); +void gpmi_begin(struct gpmi_nand_data *); +void gpmi_end(struct gpmi_nand_data *); +int gpmi_read_data(struct gpmi_nand_data *); +int gpmi_send_data(struct gpmi_nand_data *); +int gpmi_send_page(struct gpmi_nand_data *, + dma_addr_t payload, dma_addr_t auxiliary); +int gpmi_read_page(struct gpmi_nand_data *, + dma_addr_t payload, dma_addr_t auxiliary); void gpmi_copy_bits(u8 *dst, size_t dst_bit_off, const u8 *src, size_t src_bit_off, |