diff options
-rw-r--r-- | drivers/mtd/spi/spi-nor-core.c | 200 | ||||
-rw-r--r-- | drivers/spi/Kconfig | 12 | ||||
-rw-r--r-- | include/linux/mtd/spi-nor.h | 2 |
3 files changed, 89 insertions, 125 deletions
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index f5c9868bbca..a3a62fff213 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -1134,12 +1134,10 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) offset /= 2; if (nor->flags & SNOR_F_HAS_STACKED) { - if (offset >= (mtd->size / 2)) { - offset = offset - (mtd->size / 2); + if (offset >= (mtd->size / 2)) nor->spi->flags |= SPI_XFER_U_PAGE; - } else { + else nor->spi->flags &= ~SPI_XFER_U_PAGE; - } } #ifdef CONFIG_SPI_FLASH_BAR ret = write_bar(nor, addr); @@ -1588,23 +1586,22 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len); if ((nor->flags & SNOR_F_HAS_PARALLEL) && (offset & 1)) { - /* We can hit this case when we use file system like ubifs */ + /* We can hit this case when we use file system like ubifs */ from--; len++; is_ofst_odd = true; } while (len) { - if (nor->addr_width == 3) { - if (nor->flags & SNOR_F_HAS_PARALLEL) { - bank = (u32)from / (SZ_16M << 0x01); - rem_bank_len = ((SZ_16M << 0x01) * - (bank + 1)) - from; - } else { - bank = (u32)from / SZ_16M; - rem_bank_len = (SZ_16M * (bank + 1)) - from; - } - } + bank = (u32)from / SZ_16M; + if (nor->flags & SNOR_F_HAS_PARALLEL) + bank /= 2; + + rem_bank_len = SZ_16M * (bank + 1); + if (nor->flags & SNOR_F_HAS_PARALLEL) + rem_bank_len *= 2; + rem_bank_len -= from; + offset = from; if (nor->flags & SNOR_F_HAS_STACKED) { @@ -1619,13 +1616,11 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, if (nor->flags & SNOR_F_HAS_PARALLEL) offset /= 2; - if (nor->addr_width == 3) { #ifdef CONFIG_SPI_FLASH_BAR - ret = write_bar(nor, offset); - if (ret < 0) - return log_ret(ret); + ret = write_bar(nor, offset); + if (ret < 0) + return log_ret(ret); #endif - } if (len < rem_bank_len) read_len = len; @@ -1635,10 +1630,6 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, if (read_len == 0) return -EIO; - ret = spi_nor_wait_till_ready(nor); - if (ret) - goto read_err; - ret = nor->read(nor, offset, read_len, buf); if (ret == 0) { /* We shouldn't see 0-length reads */ @@ -1977,9 +1968,9 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, return ret; *retlen += 1; /* We've written only one actual byte */ - ++buf; - --len; - ++to; + buf++; + len--; + to++; } for (i = 0; i < len; ) { @@ -1999,7 +1990,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, page_offset = do_div(aux, nor->page_size); } - offset = (to + i); + offset = to + i; if (nor->flags & SNOR_F_HAS_PARALLEL) offset /= 2; @@ -2012,21 +2003,16 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, } } - if (nor->addr_width == 3) { #ifdef CONFIG_SPI_FLASH_BAR - ret = write_bar(nor, offset); - if (ret < 0) - return ret; + ret = write_bar(nor, offset); + if (ret < 0) + return ret; #endif - } + /* the size of data remaining on the first page */ page_remain = min_t(size_t, nor->page_size - page_offset, len - i); - ret = spi_nor_wait_till_ready(nor); - if (ret) - goto write_err; - write_enable(nor); /* * On DTR capable flashes like Micron Xcella the writes cannot @@ -2086,10 +2072,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, if (ret) goto write_err; - ret = write_disable(nor); - if (ret) - goto write_err; - *retlen += written; i += written; } @@ -2130,10 +2112,6 @@ static int macronix_quad_enable(struct spi_nor *nor) if (ret) return ret; - ret = write_disable(nor); - if (ret) - return ret; - ret = read_sr(nor); if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { dev_err(nor->dev, "Macronix Quad bit not set\n"); @@ -2195,7 +2173,7 @@ static int spansion_quad_enable_volatile(struct spi_nor *nor, u32 addr_base, return -EINVAL; } - return write_disable(nor); + return 0; } #endif @@ -3069,13 +3047,6 @@ static int spi_nor_init_params(struct spi_nor *nor, const struct flash_info *info, struct spi_nor_flash_parameter *params) { -#if CONFIG_IS_ENABLED(DM_SPI) && CONFIG_IS_ENABLED(SPI_ADVANCE) - struct udevice *dev = nor->spi->dev; - u64 flash_size[SNOR_FLASH_CNT_MAX] = {0}; - u32 idx = 0, i = 0; - int rc; -#endif - /* Set legacy flash parameters as default. */ memset(params, 0, sizeof(*params)); @@ -3194,62 +3165,69 @@ static int spi_nor_init_params(struct spi_nor *nor, spi_nor_post_sfdp_fixups(nor, params); } -#if CONFIG_IS_ENABLED(DM_SPI) && CONFIG_IS_ENABLED(SPI_ADVANCE) - /* - * The flashes that are connected in stacked mode should be of same make. - * Except the flash size all other properties are identical for all the - * flashes connected in stacked mode. - * The flashes that are connected in parallel mode should be identical. - */ - while (i < SNOR_FLASH_CNT_MAX) { - rc = ofnode_read_u64_index(dev_ofnode(dev), "stacked-memories", - idx, &flash_size[i]); - if (rc == -EINVAL) { - break; - } else if (rc == -EOVERFLOW) { - idx++; - } else { - idx++; - i++; - if (!(nor->flags & SNOR_F_HAS_STACKED)) - nor->flags |= SNOR_F_HAS_STACKED; - if (!(nor->spi->flags & SPI_XFER_STACKED)) - nor->spi->flags |= SPI_XFER_STACKED; + + if (CONFIG_IS_ENABLED(SPI_STACKED_PARALLEL)) { + u64 flash_size[SNOR_FLASH_CNT_MAX] = { 0 }; + struct udevice *dev = nor->spi->dev; + u32 idx = 0, i = 0; + int rc; + + /* + * The flashes that are connected in stacked mode should be of same make. + * Except the flash size all other properties are identical for all the + * flashes connected in stacked mode. + * The flashes that are connected in parallel mode should be identical. + */ + while (i < SNOR_FLASH_CNT_MAX) { + rc = ofnode_read_u64_index(dev_ofnode(dev), "stacked-memories", + idx, &flash_size[i]); + if (rc == -EINVAL) { + break; + } else if (rc == -EOVERFLOW) { + idx++; + } else { + idx++; + i++; + if (!(nor->flags & SNOR_F_HAS_STACKED)) + nor->flags |= SNOR_F_HAS_STACKED; + if (!(nor->spi->flags & SPI_XFER_STACKED)) + nor->spi->flags |= SPI_XFER_STACKED; + } } - } - i = 0; - idx = 0; - while (i < SNOR_FLASH_CNT_MAX) { - rc = ofnode_read_u64_index(dev_ofnode(dev), "parallel-memories", - idx, &flash_size[i]); - if (rc == -EINVAL) { - break; - } else if (rc == -EOVERFLOW) { - idx++; - } else { - idx++; - i++; - if (!(nor->flags & SNOR_F_HAS_PARALLEL)) - nor->flags |= SNOR_F_HAS_PARALLEL; + i = 0; + idx = 0; + while (i < SNOR_FLASH_CNT_MAX) { + rc = ofnode_read_u64_index(dev_ofnode(dev), "parallel-memories", + idx, &flash_size[i]); + if (rc == -EINVAL) { + break; + } else if (rc == -EOVERFLOW) { + idx++; + } else { + idx++; + i++; + if (!(nor->flags & SNOR_F_HAS_PARALLEL)) + nor->flags |= SNOR_F_HAS_PARALLEL; + } } - } - if (nor->flags & (SNOR_F_HAS_STACKED | SNOR_F_HAS_PARALLEL)) { - params->size = 0; - for (idx = 0; idx < SNOR_FLASH_CNT_MAX; idx++) - params->size += flash_size[idx]; - } - /* - * In parallel-memories the erase operation is - * performed on both the flashes simultaneously - * so, double the erasesize. - */ - if (nor->flags & SNOR_F_HAS_PARALLEL) { - nor->mtd.erasesize <<= 1; - params->page_size <<= 1; + if (nor->flags & (SNOR_F_HAS_STACKED | SNOR_F_HAS_PARALLEL)) { + params->size = 0; + for (idx = 0; idx < SNOR_FLASH_CNT_MAX; idx++) + params->size += flash_size[idx]; + } + /* + * In parallel-memories the erase operation is + * performed on both the flashes simultaneously + * so, double the erasesize. + */ + if (nor->flags & SNOR_F_HAS_PARALLEL) { + nor->mtd.erasesize <<= 1; + params->page_size <<= 1; + } } -#endif + spi_nor_late_init_fixups(nor, params); return 0; @@ -3599,19 +3577,6 @@ static int spi_nor_select_erase(struct spi_nor *nor, mtd->erasesize = info->sector_size; } - if ((JEDEC_MFR(info) == SNOR_MFR_SST) && info->flags & SECT_4K) { - nor->erase_opcode = SPINOR_OP_BE_4K; - /* - * In parallel-memories the erase operation is - * performed on both the flashes simultaneously - * so, double the erasesize. - */ - if (nor->flags & SNOR_F_HAS_PARALLEL) - mtd->erasesize = 4096 * 2; - else - mtd->erasesize = 4096; - } - return 0; } @@ -4606,7 +4571,6 @@ int spi_nor_scan(struct spi_nor *nor) #else /* Configure the BAR - discover bank cmds and read current bank */ nor->addr_width = 3; - set_4byte(nor, info, 0); ret = read_bar(nor, info); if (ret < 0) return ret; diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index fa817ec4883..fd5cb3694f6 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -20,12 +20,6 @@ menuconfig SPI if SPI -config SPI_ADVANCE - bool "Enable the advance feature" - help - Enable the SPI advance feature support. By default this is disabled. - If you intend to use the advance feature support you should enable. - config DM_SPI bool "Enable Driver Model for SPI drivers" depends on DM @@ -615,6 +609,12 @@ config ZYNQMP_GQSPI This option is used to enable ZynqMP QSPI controller driver which is used to communicate with qspi flash devices. +config SPI_STACKED_PARALLEL + bool "Enable support for stacked or parallel memories" + help + Enable support for stacked/or parallel memories. This functionality + may appear on Xilinx hardware. By default this is disabled. + endif # if DM_SPI config FSL_ESPI diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 655a6d197ea..b8b207f7b5c 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -308,7 +308,7 @@ enum spi_nor_option_flags { SNOR_F_BROKEN_RESET = BIT(6), SNOR_F_SOFT_RESET = BIT(7), SNOR_F_IO_MODE_EN_VOLATILE = BIT(8), -#if defined(CONFIG_SPI_ADVANCE) +#if defined(CONFIG_SPI_STACKED_PARALLEL) SNOR_F_HAS_STACKED = BIT(9), SNOR_F_HAS_PARALLEL = BIT(10), #else |