diff options
author | Miquel Raynal <miquel.raynal@bootlin.com> | 2020-01-27 17:49:15 +0100 |
---|---|---|
committer | Miquel Raynal <miquel.raynal@bootlin.com> | 2020-01-27 17:49:15 +0100 |
commit | 4575243c5c173f8adbc08a5c6ea2269742ea2b47 (patch) | |
tree | d084fde0a55f38f1924e45f9629dad7747759df7 /drivers/mtd | |
parent | Merge tag 'spi-nor/for-5.6' into mtd/next (diff) | |
parent | mtd: onenand: Rename omap2 driver to avoid a build warning (diff) | |
download | linux-4575243c5c173f8adbc08a5c6ea2269742ea2b47.tar.xz linux-4575243c5c173f8adbc08a5c6ea2269742ea2b47.zip |
Merge tag 'nand/for-5.6' into mtd/next
Raw NAND
* Macronix: Use match_string() helper
* Atmel: switch to using devm_fwnode_gpiod_get()
* Denali: rework the SKIP_BYTES feature and add reset controlling
* Brcmnand: set appropriate DMA mask
* Various cleanup.
Onenand drivers
* Rename Samsung and Omap2 drivers to avoid possible build warnings
* Enable compile testing
* Various build issues
* Kconfig cleanup
SPI-NAND
* Support for Toshiba TC58CVG2S0HRAIJ
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/onenand/Kconfig | 14 | ||||
-rw-r--r-- | drivers/mtd/nand/onenand/Makefile | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/onenand/onenand_base.c | 96 | ||||
-rw-r--r-- | drivers/mtd/nand/onenand/onenand_omap2.c (renamed from drivers/mtd/nand/onenand/omap2.c) | 14 | ||||
-rw-r--r-- | drivers/mtd/nand/onenand/onenand_samsung.c (renamed from drivers/mtd/nand/onenand/samsung_mtd.c) | 17 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/atmel/nand-controller.c | 20 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/brcmnand/brcmnand.c | 10 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/cadence-nand-controller.c | 13 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/denali.c | 14 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/denali_dt.c | 56 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/mpc5121_nfc.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/nand_macronix.c | 11 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/stm32_fmc2_nand.c | 38 | ||||
-rw-r--r-- | drivers/mtd/nand/spi/toshiba.c | 10 | ||||
-rw-r--r-- | drivers/mtd/parsers/sharpslpart.c | 4 | ||||
-rw-r--r-- | drivers/mtd/sm_ftl.c | 3 | ||||
-rw-r--r-- | drivers/mtd/spi-nor/spi-nor.c | 1 |
17 files changed, 212 insertions, 115 deletions
diff --git a/drivers/mtd/nand/onenand/Kconfig b/drivers/mtd/nand/onenand/Kconfig index ae0b8fe5b990..572b8fe69abb 100644 --- a/drivers/mtd/nand/onenand/Kconfig +++ b/drivers/mtd/nand/onenand/Kconfig @@ -25,7 +25,7 @@ config MTD_ONENAND_GENERIC config MTD_ONENAND_OMAP2 tristate "OneNAND on OMAP2/OMAP3 support" - depends on ARCH_OMAP2 || ARCH_OMAP3 + depends on ARCH_OMAP2 || ARCH_OMAP3 || (COMPILE_TEST && ARM) depends on OF || COMPILE_TEST help Support for a OneNAND flash device connected to an OMAP2/OMAP3 SoC @@ -33,12 +33,12 @@ config MTD_ONENAND_OMAP2 Enable dmaengine and gpiolib for better performance. config MTD_ONENAND_SAMSUNG - tristate "OneNAND on Samsung SOC controller support" - depends on ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS4 - help - Support for a OneNAND flash device connected to an Samsung SOC. - S3C64XX uses command mapping method. - S5PC110/S5PC210 use generic OneNAND method. + tristate "OneNAND on Samsung SOC controller support" + depends on ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS4 || COMPILE_TEST + help + Support for a OneNAND flash device connected to an Samsung SOC. + S3C64XX uses command mapping method. + S5PC110/S5PC210 use generic OneNAND method. config MTD_ONENAND_OTP bool "OneNAND OTP Support" diff --git a/drivers/mtd/nand/onenand/Makefile b/drivers/mtd/nand/onenand/Makefile index a27b635eb23a..a0761c7e0288 100644 --- a/drivers/mtd/nand/onenand/Makefile +++ b/drivers/mtd/nand/onenand/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o # Board specific. obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o -obj-$(CONFIG_MTD_ONENAND_OMAP2) += omap2.o -obj-$(CONFIG_MTD_ONENAND_SAMSUNG) += samsung_mtd.o +obj-$(CONFIG_MTD_ONENAND_OMAP2) += onenand_omap2.o +obj-$(CONFIG_MTD_ONENAND_SAMSUNG) += onenand_samsung.o onenand-objs = onenand_base.o onenand_bbt.o diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c index 77bd32a683e1..d5326d19b136 100644 --- a/drivers/mtd/nand/onenand/onenand_base.c +++ b/drivers/mtd/nand/onenand/onenand_base.c @@ -1248,44 +1248,44 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, stats = mtd->ecc_stats; - /* Read-while-load method */ + /* Read-while-load method */ - /* Do first load to bufferRAM */ - if (read < len) { - if (!onenand_check_bufferram(mtd, from)) { + /* Do first load to bufferRAM */ + if (read < len) { + if (!onenand_check_bufferram(mtd, from)) { this->command(mtd, ONENAND_CMD_READ, from, writesize); - ret = this->wait(mtd, FL_READING); - onenand_update_bufferram(mtd, from, !ret); + ret = this->wait(mtd, FL_READING); + onenand_update_bufferram(mtd, from, !ret); if (mtd_is_eccerr(ret)) ret = 0; - } - } + } + } thislen = min_t(int, writesize, len - read); column = from & (writesize - 1); if (column + thislen > writesize) thislen = writesize - column; - while (!ret) { - /* If there is more to load then start next load */ - from += thislen; - if (read + thislen < len) { + while (!ret) { + /* If there is more to load then start next load */ + from += thislen; + if (read + thislen < len) { this->command(mtd, ONENAND_CMD_READ, from, writesize); - /* - * Chip boundary handling in DDP - * Now we issued chip 1 read and pointed chip 1 + /* + * Chip boundary handling in DDP + * Now we issued chip 1 read and pointed chip 1 * bufferram so we have to point chip 0 bufferram. - */ - if (ONENAND_IS_DDP(this) && - unlikely(from == (this->chipsize >> 1))) { - this->write_word(ONENAND_DDP_CHIP0, this->base + ONENAND_REG_START_ADDRESS2); - boundary = 1; - } else - boundary = 0; - ONENAND_SET_PREV_BUFFERRAM(this); - } - /* While load is going, read from last bufferRAM */ - this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); + */ + if (ONENAND_IS_DDP(this) && + unlikely(from == (this->chipsize >> 1))) { + this->write_word(ONENAND_DDP_CHIP0, this->base + ONENAND_REG_START_ADDRESS2); + boundary = 1; + } else + boundary = 0; + ONENAND_SET_PREV_BUFFERRAM(this); + } + /* While load is going, read from last bufferRAM */ + this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); /* Read oob area if needed */ if (oobbuf) { @@ -1301,24 +1301,24 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from, oobcolumn = 0; } - /* See if we are done */ - read += thislen; - if (read == len) - break; - /* Set up for next read from bufferRAM */ - if (unlikely(boundary)) - this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2); - ONENAND_SET_NEXT_BUFFERRAM(this); - buf += thislen; + /* See if we are done */ + read += thislen; + if (read == len) + break; + /* Set up for next read from bufferRAM */ + if (unlikely(boundary)) + this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2); + ONENAND_SET_NEXT_BUFFERRAM(this); + buf += thislen; thislen = min_t(int, writesize, len - read); - column = 0; - cond_resched(); - /* Now wait for load */ - ret = this->wait(mtd, FL_READING); - onenand_update_bufferram(mtd, from, !ret); + column = 0; + cond_resched(); + /* Now wait for load */ + ret = this->wait(mtd, FL_READING); + onenand_update_bufferram(mtd, from, !ret); if (mtd_is_eccerr(ret)) ret = 0; - } + } /* * Return success, if no ECC failures, else -EBADMSG @@ -2853,7 +2853,7 @@ static int onenand_otp_write_oob_nolock(struct mtd_info *mtd, loff_t to, /* Exit OTP access mode */ this->command(mtd, ONENAND_CMD_RESET, 0, 0); - this->wait(mtd, FL_RESETING); + this->wait(mtd, FL_RESETTING); status = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); status &= 0x60; @@ -2924,7 +2924,7 @@ static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len, /* Exit OTP access mode */ this->command(mtd, ONENAND_CMD_RESET, 0, 0); - this->wait(mtd, FL_RESETING); + this->wait(mtd, FL_RESETTING); return ret; } @@ -2968,7 +2968,7 @@ static int do_otp_write(struct mtd_info *mtd, loff_t to, size_t len, /* Exit OTP access mode */ this->command(mtd, ONENAND_CMD_RESET, 0, 0); - this->wait(mtd, FL_RESETING); + this->wait(mtd, FL_RESETTING); return ret; } @@ -3008,7 +3008,7 @@ static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len, /* Exit OTP access mode */ this->command(mtd, ONENAND_CMD_RESET, 0, 0); - this->wait(mtd, FL_RESETING); + this->wait(mtd, FL_RESETTING); } else { ops.mode = MTD_OPS_PLACE_OOB; ops.ooblen = len; @@ -3413,7 +3413,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd) this->boundary[die] = bdry & FLEXONENAND_PI_MASK; this->command(mtd, ONENAND_CMD_RESET, 0, 0); - this->wait(mtd, FL_RESETING); + this->wait(mtd, FL_RESETTING); printk(KERN_INFO "Die %d boundary: %d%s\n", die, this->boundary[die], locked ? "(Locked)" : "(Unlocked)"); @@ -3635,7 +3635,7 @@ static int flexonenand_set_boundary(struct mtd_info *mtd, int die, ret = this->wait(mtd, FL_WRITING); out: this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_REG_COMMAND); - this->wait(mtd, FL_RESETING); + this->wait(mtd, FL_RESETTING); if (!ret) /* Recalculate device size on boundary change*/ flexonenand_get_size(mtd); @@ -3671,7 +3671,7 @@ static int onenand_chip_probe(struct mtd_info *mtd) /* Reset OneNAND to read default register values */ this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM); /* Wait reset */ - this->wait(mtd, FL_RESETING); + this->wait(mtd, FL_RESETTING); /* Restore system configuration 1 */ this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1); diff --git a/drivers/mtd/nand/onenand/omap2.c b/drivers/mtd/nand/onenand/onenand_omap2.c index edf94ee54ec7..aa9368bf7a0c 100644 --- a/drivers/mtd/nand/onenand/omap2.c +++ b/drivers/mtd/nand/onenand/onenand_omap2.c @@ -148,13 +148,13 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state) unsigned long timeout; u32 syscfg; - if (state == FL_RESETING || state == FL_PREPARING_ERASE || + if (state == FL_RESETTING || state == FL_PREPARING_ERASE || state == FL_VERIFYING_ERASE) { int i = 21; unsigned int intr_flags = ONENAND_INT_MASTER; switch (state) { - case FL_RESETING: + case FL_RESETTING: intr_flags |= ONENAND_INT_RESET; break; case FL_PREPARING_ERASE: @@ -328,7 +328,8 @@ static inline int omap2_onenand_dma_transfer(struct omap2_onenand *c, struct dma_async_tx_descriptor *tx; dma_cookie_t cookie; - tx = dmaengine_prep_dma_memcpy(c->dma_chan, dst, src, count, 0); + tx = dmaengine_prep_dma_memcpy(c->dma_chan, dst, src, count, + DMA_CTRL_ACK | DMA_PREP_INTERRUPT); if (!tx) { dev_err(&c->pdev->dev, "Failed to prepare DMA memcpy\n"); return -EIO; @@ -375,7 +376,7 @@ static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area, * context fallback to PIO mode. */ if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 || - count < 384 || in_interrupt() || oops_in_progress ) + count < 384 || in_interrupt() || oops_in_progress) goto out_copy; xtra = count & 3; @@ -422,7 +423,7 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area, * context fallback to PIO mode. */ if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 || - count < 384 || in_interrupt() || oops_in_progress ) + count < 384 || in_interrupt() || oops_in_progress) goto out_copy; dma_src = dma_map_single(dev, buf, count, DMA_TO_DEVICE); @@ -528,7 +529,8 @@ static int omap2_onenand_probe(struct platform_device *pdev) c->gpmc_cs, c->phys_base, c->onenand.base, c->dma_chan ? "DMA" : "PIO"); - if ((r = onenand_scan(&c->mtd, 1)) < 0) + r = onenand_scan(&c->mtd, 1); + if (r < 0) goto err_release_dma; freq = omap2_onenand_get_freq(c->onenand.version_id); diff --git a/drivers/mtd/nand/onenand/samsung_mtd.c b/drivers/mtd/nand/onenand/onenand_samsung.c index 55e5536a5850..87b28e397d67 100644 --- a/drivers/mtd/nand/onenand/samsung_mtd.c +++ b/drivers/mtd/nand/onenand/onenand_samsung.c @@ -248,7 +248,7 @@ static unsigned short s3c_onenand_readw(void __iomem *addr) } /* BootRAM access control */ - if ((unsigned int) addr < ONENAND_DATARAM && onenand->bootram_command) { + if ((unsigned long)addr < ONENAND_DATARAM && onenand->bootram_command) { if (word_addr == 0) return s3c_read_reg(MANUFACT_ID_OFFSET); if (word_addr == 1) @@ -289,7 +289,7 @@ static void s3c_onenand_writew(unsigned short value, void __iomem *addr) } /* BootRAM access control */ - if ((unsigned int)addr < ONENAND_DATARAM) { + if ((unsigned long)addr < ONENAND_DATARAM) { if (value == ONENAND_CMD_READID) { onenand->bootram_command = 1; return; @@ -658,7 +658,7 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, dma_dst = dma_map_single(dev, buf, count, DMA_FROM_DEVICE); } if (dma_mapping_error(dev, dma_dst)) { - dev_err(dev, "Couldn't map a %d byte buffer for DMA\n", count); + dev_err(dev, "Couldn't map a %zu byte buffer for DMA\n", count); goto normal; } err = s5pc110_dma_ops(dma_dst, dma_src, @@ -675,12 +675,12 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, normal: if (count != mtd->writesize) { /* Copy the bufferram to memory to prevent unaligned access */ - memcpy(this->page_buf, p, mtd->writesize); - p = this->page_buf + offset; + memcpy_fromio(this->page_buf, p, mtd->writesize); + memcpy(buffer, this->page_buf + offset, count); + } else { + memcpy_fromio(buffer, p, count); } - memcpy(buffer, p, count); - return 0; } @@ -728,13 +728,12 @@ static void s3c_onenand_check_lock_status(struct mtd_info *mtd) struct onenand_chip *this = mtd->priv; struct device *dev = &onenand->pdev->dev; unsigned int block, end; - int tmp; end = this->chipsize >> this->erase_shift; for (block = 0; block < end; block++) { unsigned int mem_addr = onenand->mem_addr(block, 0, 0); - tmp = s3c_read_cmd(CMD_MAP_01(onenand, mem_addr)); + s3c_read_cmd(CMD_MAP_01(onenand, mem_addr)); if (s3c_read_reg(INT_ERR_STAT_OFFSET) & LOCKED_BLK) { dev_err(dev, "block %d is write-protected!\n", block); diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 8d6be90a6fe8..3ba17a98df4d 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -1578,9 +1578,8 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc, nand->numcs = numcs; - gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev, "det", 0, - &np->fwnode, GPIOD_IN, - "nand-det"); + gpio = devm_fwnode_gpiod_get(nc->dev, of_fwnode_handle(np), + "det", GPIOD_IN, "nand-det"); if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) { dev_err(nc->dev, "Failed to get detect gpio (err = %ld)\n", @@ -1624,9 +1623,10 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc, nand->cs[i].rb.type = ATMEL_NAND_NATIVE_RB; nand->cs[i].rb.id = val; } else { - gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev, - "rb", i, &np->fwnode, - GPIOD_IN, "nand-rb"); + gpio = devm_fwnode_gpiod_get_index(nc->dev, + of_fwnode_handle(np), + "rb", i, GPIOD_IN, + "nand-rb"); if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) { dev_err(nc->dev, "Failed to get R/B gpio (err = %ld)\n", @@ -1640,10 +1640,10 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc, } } - gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev, "cs", - i, &np->fwnode, - GPIOD_OUT_HIGH, - "nand-cs"); + gpio = devm_fwnode_gpiod_get_index(nc->dev, + of_fwnode_handle(np), + "cs", i, GPIOD_OUT_HIGH, + "nand-cs"); if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) { dev_err(nc->dev, "Failed to get CS gpio (err = %ld)\n", diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 1a66b1cd51c0..44518dada75b 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -2635,6 +2635,16 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) /* initialize the dma version */ brcmnand_flash_dma_revision_init(ctrl); + ret = -EIO; + if (ctrl->nand_version >= 0x0700) + ret = dma_set_mask_and_coherent(&pdev->dev, + DMA_BIT_MASK(40)); + if (ret) + ret = dma_set_mask_and_coherent(&pdev->dev, + DMA_BIT_MASK(32)); + if (ret) + goto err; + /* linked-list and stop on error */ flash_dma_writel(ctrl, FLASH_DMA_MODE, FLASH_DMA_MODE_MASK); flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0); diff --git a/drivers/mtd/nand/raw/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c index 3a36285a8d8a..f6c7102a1e32 100644 --- a/drivers/mtd/nand/raw/cadence-nand-controller.c +++ b/drivers/mtd/nand/raw/cadence-nand-controller.c @@ -914,8 +914,8 @@ static void cadence_nand_get_caps(struct cdns_nand_ctrl *cdns_ctrl) /* Prepare CDMA descriptor. */ static void cadence_nand_cdma_desc_prepare(struct cdns_nand_ctrl *cdns_ctrl, - char nf_mem, u32 flash_ptr, char *mem_ptr, - char *ctrl_data_ptr, u16 ctype) + char nf_mem, u32 flash_ptr, dma_addr_t mem_ptr, + dma_addr_t ctrl_data_ptr, u16 ctype) { struct cadence_nand_cdma_desc *cdma_desc = cdns_ctrl->cdma_desc; @@ -931,13 +931,13 @@ cadence_nand_cdma_desc_prepare(struct cdns_nand_ctrl *cdns_ctrl, cdma_desc->command_flags |= CDMA_CF_DMA_MASTER; cdma_desc->command_flags |= CDMA_CF_INT; - cdma_desc->memory_pointer = (uintptr_t)mem_ptr; + cdma_desc->memory_pointer = mem_ptr; cdma_desc->status = 0; cdma_desc->sync_flag_pointer = 0; cdma_desc->sync_arguments = 0; cdma_desc->command_type = ctype; - cdma_desc->ctrl_data_ptr = (uintptr_t)ctrl_data_ptr; + cdma_desc->ctrl_data_ptr = ctrl_data_ptr; } static u8 cadence_nand_check_desc_error(struct cdns_nand_ctrl *cdns_ctrl, @@ -1280,8 +1280,7 @@ cadence_nand_cdma_transfer(struct cdns_nand_ctrl *cdns_ctrl, u8 chip_nr, } cadence_nand_cdma_desc_prepare(cdns_ctrl, chip_nr, page, - (void *)dma_buf, (void *)dma_ctrl_dat, - ctype); + dma_buf, dma_ctrl_dat, ctype); status = cadence_nand_cdma_send_and_wait(cdns_ctrl, thread_nr); @@ -1360,7 +1359,7 @@ static int cadence_nand_erase(struct nand_chip *chip, u32 page) cadence_nand_cdma_desc_prepare(cdns_ctrl, cdns_chip->cs[chip->cur_cs], - page, NULL, NULL, + page, 0, 0, CDMA_CT_ERASE); status = cadence_nand_cdma_send_and_wait(cdns_ctrl, thread_nr); if (status) { diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index 3102ddbd8abd..fafd0a0aa8e2 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -21,7 +21,6 @@ #include "denali.h" #define DENALI_NAND_NAME "denali-nand" -#define DENALI_DEFAULT_OOB_SKIP_BYTES 8 /* for Indexed Addressing */ #define DENALI_INDEXED_CTRL 0x00 @@ -1302,15 +1301,16 @@ int denali_init(struct denali_controller *denali) /* * Set how many bytes should be skipped before writing data in OOB. - * If a non-zero value has already been set (by firmware or something), - * just use it. Otherwise, set the driver's default. + * If a platform requests a non-zero value, set it to the register. + * Otherwise, read the value out, expecting it has already been set up + * by firmware. */ - denali->oob_skip_bytes = ioread32(denali->reg + SPARE_AREA_SKIP_BYTES); - if (!denali->oob_skip_bytes) { - denali->oob_skip_bytes = DENALI_DEFAULT_OOB_SKIP_BYTES; + if (denali->oob_skip_bytes) iowrite32(denali->oob_skip_bytes, denali->reg + SPARE_AREA_SKIP_BYTES); - } + else + denali->oob_skip_bytes = ioread32(denali->reg + + SPARE_AREA_SKIP_BYTES); iowrite32(0, denali->reg + TRANSFER_SPARE_REG); iowrite32(GENMASK(denali->nbanks - 1, 0), denali->reg + RB_PIN_ENABLED); diff --git a/drivers/mtd/nand/raw/denali_dt.c b/drivers/mtd/nand/raw/denali_dt.c index 8b779a899dcf..f08740ae282b 100644 --- a/drivers/mtd/nand/raw/denali_dt.c +++ b/drivers/mtd/nand/raw/denali_dt.c @@ -6,6 +6,7 @@ */ #include <linux/clk.h> +#include <linux/delay.h> #include <linux/err.h> #include <linux/io.h> #include <linux/ioport.h> @@ -14,6 +15,7 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> +#include <linux/reset.h> #include "denali.h" @@ -22,11 +24,14 @@ struct denali_dt { struct clk *clk; /* core clock */ struct clk *clk_x; /* bus interface clock */ struct clk *clk_ecc; /* ECC circuit clock */ + struct reset_control *rst; /* core reset */ + struct reset_control *rst_reg; /* register reset */ }; struct denali_dt_data { unsigned int revision; unsigned int caps; + unsigned int oob_skip_bytes; const struct nand_ecc_caps *ecc_caps; }; @@ -34,6 +39,7 @@ NAND_ECC_CAPS_SINGLE(denali_socfpga_ecc_caps, denali_calc_ecc_bytes, 512, 8, 15); static const struct denali_dt_data denali_socfpga_data = { .caps = DENALI_CAP_HW_ECC_FIXUP, + .oob_skip_bytes = 2, .ecc_caps = &denali_socfpga_ecc_caps, }; @@ -42,6 +48,7 @@ NAND_ECC_CAPS_SINGLE(denali_uniphier_v5a_ecc_caps, denali_calc_ecc_bytes, static const struct denali_dt_data denali_uniphier_v5a_data = { .caps = DENALI_CAP_HW_ECC_FIXUP | DENALI_CAP_DMA_64BIT, + .oob_skip_bytes = 8, .ecc_caps = &denali_uniphier_v5a_ecc_caps, }; @@ -51,6 +58,7 @@ static const struct denali_dt_data denali_uniphier_v5b_data = { .revision = 0x0501, .caps = DENALI_CAP_HW_ECC_FIXUP | DENALI_CAP_DMA_64BIT, + .oob_skip_bytes = 8, .ecc_caps = &denali_uniphier_v5b_ecc_caps, }; @@ -118,11 +126,13 @@ static int denali_dt_probe(struct platform_device *pdev) denali = &dt->controller; data = of_device_get_match_data(dev); - if (data) { - denali->revision = data->revision; - denali->caps = data->caps; - denali->ecc_caps = data->ecc_caps; - } + if (WARN_ON(!data)) + return -EINVAL; + + denali->revision = data->revision; + denali->caps = data->caps; + denali->oob_skip_bytes = data->oob_skip_bytes; + denali->ecc_caps = data->ecc_caps; denali->dev = dev; denali->irq = platform_get_irq(pdev, 0); @@ -151,6 +161,14 @@ static int denali_dt_probe(struct platform_device *pdev) if (IS_ERR(dt->clk_ecc)) return PTR_ERR(dt->clk_ecc); + dt->rst = devm_reset_control_get_optional_shared(dev, "nand"); + if (IS_ERR(dt->rst)) + return PTR_ERR(dt->rst); + + dt->rst_reg = devm_reset_control_get_optional_shared(dev, "reg"); + if (IS_ERR(dt->rst_reg)) + return PTR_ERR(dt->rst_reg); + ret = clk_prepare_enable(dt->clk); if (ret) return ret; @@ -166,10 +184,30 @@ static int denali_dt_probe(struct platform_device *pdev) denali->clk_rate = clk_get_rate(dt->clk); denali->clk_x_rate = clk_get_rate(dt->clk_x); - ret = denali_init(denali); + /* + * Deassert the register reset, and the core reset in this order. + * Deasserting the core reset while the register reset is asserted + * will cause unpredictable behavior in the controller. + */ + ret = reset_control_deassert(dt->rst_reg); if (ret) goto out_disable_clk_ecc; + ret = reset_control_deassert(dt->rst); + if (ret) + goto out_assert_rst_reg; + + /* + * When the reset is deasserted, the initialization sequence is kicked + * (bootstrap process). The driver must wait until it finished. + * Otherwise, it will result in unpredictable behavior. + */ + usleep_range(200, 1000); + + ret = denali_init(denali); + if (ret) + goto out_assert_rst; + for_each_child_of_node(dev->of_node, np) { ret = denali_dt_chip_init(denali, np); if (ret) { @@ -184,6 +222,10 @@ static int denali_dt_probe(struct platform_device *pdev) out_remove_denali: denali_remove(denali); +out_assert_rst: + reset_control_assert(dt->rst); +out_assert_rst_reg: + reset_control_assert(dt->rst_reg); out_disable_clk_ecc: clk_disable_unprepare(dt->clk_ecc); out_disable_clk_x: @@ -199,6 +241,8 @@ static int denali_dt_remove(struct platform_device *pdev) struct denali_dt *dt = platform_get_drvdata(pdev); denali_remove(&dt->controller); + reset_control_assert(dt->rst); + reset_control_assert(dt->rst_reg); clk_disable_unprepare(dt->clk_ecc); clk_disable_unprepare(dt->clk_x); clk_disable_unprepare(dt->clk); diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c index 8b90def6686f..a2fcb739e5f8 100644 --- a/drivers/mtd/nand/raw/mpc5121_nfc.c +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c @@ -438,7 +438,7 @@ static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset, buffer += blksize; offset += blksize; size -= blksize; - }; + } } /* Copy data from/to NFC main and spare buffers */ diff --git a/drivers/mtd/nand/raw/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c index 58511aeb0c9a..3ff7ce00cbdb 100644 --- a/drivers/mtd/nand/raw/nand_macronix.c +++ b/drivers/mtd/nand/raw/nand_macronix.c @@ -59,7 +59,7 @@ static void macronix_nand_onfi_init(struct nand_chip *chip) */ static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip) { - unsigned int i; + int i; static const char * const broken_get_timings[] = { "MX30LF1G18AC", "MX30LF1G28AC", @@ -80,12 +80,9 @@ static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip) if (!chip->parameters.supports_set_get_features) return; - for (i = 0; i < ARRAY_SIZE(broken_get_timings); i++) { - if (!strcmp(broken_get_timings[i], chip->parameters.model)) - break; - } - - if (i == ARRAY_SIZE(broken_get_timings)) + i = match_string(broken_get_timings, ARRAY_SIZE(broken_get_timings), + chip->parameters.model); + if (i < 0) return; bitmap_clear(chip->parameters.get_feature_list, diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c index 9e63800f768a..3ba73f18841f 100644 --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -37,6 +37,7 @@ /* Max ECC buffer length */ #define FMC2_MAX_ECC_BUF_LEN (FMC2_BCHDSRS_LEN * FMC2_MAX_SG) +#define FMC2_TIMEOUT_US 1000 #define FMC2_TIMEOUT_MS 1000 /* Timings */ @@ -53,6 +54,8 @@ #define FMC2_PMEM 0x88 #define FMC2_PATT 0x8c #define FMC2_HECCR 0x94 +#define FMC2_ISR 0x184 +#define FMC2_ICR 0x188 #define FMC2_CSQCR 0x200 #define FMC2_CSQCFGR1 0x204 #define FMC2_CSQCFGR2 0x208 @@ -118,6 +121,12 @@ #define FMC2_PATT_ATTHIZ(x) (((x) & 0xff) << 24) #define FMC2_PATT_DEFAULT 0x0a0a0a0a +/* Register: FMC2_ISR */ +#define FMC2_ISR_IHLF BIT(1) + +/* Register: FMC2_ICR */ +#define FMC2_ICR_CIHLF BIT(1) + /* Register: FMC2_CSQCR */ #define FMC2_CSQCR_CSQSTART BIT(0) @@ -1322,6 +1331,31 @@ static void stm32_fmc2_write_data(struct nand_chip *chip, const void *buf, stm32_fmc2_set_buswidth_16(fmc2, true); } +static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + const struct nand_sdr_timings *timings; + u32 isr, sr; + + /* Check if there is no pending requests to the NAND flash */ + if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr, + sr & FMC2_SR_NWRF, 1, + FMC2_TIMEOUT_US)) + dev_warn(fmc2->dev, "Waitrdy timeout\n"); + + /* Wait tWB before R/B# signal is low */ + timings = nand_get_sdr_timings(&chip->data_interface); + ndelay(PSEC_TO_NSEC(timings->tWB_max)); + + /* R/B# signal is low, clear high level flag */ + writel_relaxed(FMC2_ICR_CIHLF, fmc2->io_base + FMC2_ICR); + + /* Wait R/B# signal is high */ + return readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_ISR, + isr, isr & FMC2_ISR_IHLF, + 5, 1000 * timeout_ms); +} + static int stm32_fmc2_exec_op(struct nand_chip *chip, const struct nand_operation *op, bool check_only) @@ -1366,8 +1400,8 @@ static int stm32_fmc2_exec_op(struct nand_chip *chip, break; case NAND_OP_WAITRDY_INSTR: - ret = nand_soft_waitrdy(chip, - instr->ctx.waitrdy.timeout_ms); + ret = stm32_fmc2_waitrdy(chip, + instr->ctx.waitrdy.timeout_ms); break; } } diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c index 1cb3760ff779..0db5ee4e82af 100644 --- a/drivers/mtd/nand/spi/toshiba.c +++ b/drivers/mtd/nand/spi/toshiba.c @@ -124,6 +124,16 @@ static const struct spinand_info toshiba_spinand_table[] = { 0, SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, tc58cxgxsx_ecc_get_status)), + /* 3.3V 4Gb */ + SPINAND_INFO("TC58CVG2S0", 0xED, + NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, + tc58cxgxsx_ecc_get_status)), /* 1.8V 1Gb */ SPINAND_INFO("TC58CYG0S3", 0xB2, NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), diff --git a/drivers/mtd/parsers/sharpslpart.c b/drivers/mtd/parsers/sharpslpart.c index e5ea6127ab5a..671a61845bd5 100644 --- a/drivers/mtd/parsers/sharpslpart.c +++ b/drivers/mtd/parsers/sharpslpart.c @@ -165,10 +165,10 @@ static int sharpsl_nand_get_logical_num(u8 *oob) static int sharpsl_nand_init_ftl(struct mtd_info *mtd, struct sharpsl_ftl *ftl) { - unsigned int block_num, log_num, phymax; + unsigned int block_num, phymax; + int i, ret, log_num; loff_t block_adr; u8 *oob; - int i, ret; oob = kzalloc(mtd->oobsize, GFP_KERNEL); if (!oob) diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c index 4744bf94ad9a..b9f272408c4d 100644 --- a/drivers/mtd/sm_ftl.c +++ b/drivers/mtd/sm_ftl.c @@ -247,7 +247,8 @@ static int sm_read_sector(struct sm_ftl *ftl, /* FTL can contain -1 entries that are by default filled with bits */ if (block == -1) { - memset(buffer, 0xFF, SM_SECTOR_SIZE); + if (buffer) + memset(buffer, 0xFF, SM_SECTOR_SIZE); return 0; } diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 928a660e3b1d..94422e880b70 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -4647,6 +4647,7 @@ static void sst_set_default_init(struct spi_nor *nor) static void st_micron_set_default_init(struct spi_nor *nor) { nor->flags |= SNOR_F_HAS_LOCK; + nor->flags &= ~SNOR_F_HAS_16BIT_SR; nor->params.quad_enable = NULL; nor->params.set_4byte = st_micron_set_4byte; } |