diff options
Diffstat (limited to 'drivers/mtd/spi-nor/spi-nor.c')
-rw-r--r-- | drivers/mtd/spi-nor/spi-nor.c | 61 |
1 files changed, 40 insertions, 21 deletions
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 038d7072aa..1773db09a1 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Based on m25p80.c, by Mike Lavender (mike@steroidmicros.com), with * influence from lart.c (Abraham Van Der Merwe) and mtd_dataflash.c * * Copyright (C) 2005, Intec Automation Inc. * Copyright (C) 2014, Freescale Semiconductor, Inc. - * - * This code is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <clock.h> @@ -22,10 +19,8 @@ #include <linux/mtd/cfi.h> #include <linux/mtd/spi-nor.h> #include <of.h> -#include <spi/flash.h> #define SPI_NOR_MAX_ID_LEN 6 -#define SPI_NOR_MAX_ADDR_WIDTH 4 /* * For everything but full-chip erase; probably could be much smaller, but kept @@ -87,6 +82,7 @@ struct flash_info { #define USE_CLSR BIT(14) /* use CLSR command */ #define SPI_NOR_OCTAL_READ BIT(15) /* Flash supports Octal Read */ #define UNLOCK_GLOBAL_BLOCK BIT(16) /* Unlock global block protection */ +#define SPI_NOR_QUAD_WRITE BIT(17) /* Flash supports Quad Write */ }; enum spi_nor_read_command_index { @@ -470,6 +466,9 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) uint32_t rem; int ret; + if (!IS_ENABLED(CONFIG_MTD_WRITE)) + return -ENOSYS; + dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr, (long long)instr->len); @@ -540,14 +539,10 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); - instr->state = MTD_ERASE_DONE; - mtd_erase_callback(instr); - return ret; erase_err: spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); - instr->state = MTD_ERASE_FAILED; return ret; } @@ -640,6 +635,9 @@ static const struct spi_device_id spi_nor_ids[] = { { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) }, + /* Cypress */ + { "cy15x104q", INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1, SPI_NOR_NO_ERASE) }, + /* EON -- en25xxx */ { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) }, { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, @@ -664,6 +662,7 @@ static const struct spi_device_id spi_nor_ids[] = { { "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) }, /* GigaDevice */ + { "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32, SECT_4K) }, { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K) }, @@ -680,7 +679,7 @@ static const struct spi_device_id spi_nor_ids[] = { { "is25lp016d", INFO(0x9d6015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25lp01g", INFO(0x9d601b, 0, 64 * 1024, 2048, - SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) }, { "is25lp080d", INFO(0x9d6014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25lp032", INFO(0x9d6016, 0, 64 * 1024, 64, @@ -697,6 +696,8 @@ static const struct spi_device_id spi_nor_ids[] = { SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25wp128", INFO(0x9d7018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "is25wp256", INFO(0x9d7019, 0, 64 * 1024, 512, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25lq128", INFO(0x9d6018, 0, 64 * 1024, 256, 0) }, /* Macronix */ @@ -727,6 +728,7 @@ static const struct spi_device_id spi_nor_ids[] = { { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, + { "mt25qu256a", INFO(0x20bb19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, @@ -865,11 +867,15 @@ static const struct spi_device_id spi_nor_ids[] = { { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, SECT_4K) }, + { "w25q512nwq", INFO(0xef6020, 0, 512 * 1024, 128, SECT_4K) }, { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, { "w25q128", INFO(0xef7018, 0, 64 * 1024, 256, SECT_4K) }, - { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) }, + { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | + SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE | SPI_NOR_4B_OPCODES) }, + { "w25q256jwm", INFO(0xef8019, 0, 64 * 1024, 512, SECT_4K | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, /* Catalyst / On Semiconductor -- non-JEDEC */ { "cat25c11", CAT25_INFO( 16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, @@ -929,6 +935,9 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, size_t actual; int ret; + if (!IS_ENABLED(CONFIG_MTD_WRITE)) + return -ENOSYS; + dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE); @@ -1001,6 +1010,9 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, size_t retval; int ret; + if (!IS_ENABLED(CONFIG_MTD_WRITE)) + return -ENOSYS; + dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE); @@ -1123,7 +1135,7 @@ static int spi_nor_init_params(struct spi_nor *nor, memset(params, 0, sizeof(*params)); /* Set SPI NOR sizes. */ - params->size = info->sector_size * info->n_sectors; + params->size = info->sector_size * (u64)info->n_sectors; params->page_size = info->page_size; /* (Fast) Read settings. */ @@ -1158,6 +1170,13 @@ static int spi_nor_init_params(struct spi_nor *nor, spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP], SPINOR_OP_PP, SNOR_PROTO_1_1_1); + if (info->flags & SPI_NOR_QUAD_WRITE) { + params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4; + spi_nor_set_pp_settings( + ¶ms->page_programs[SNOR_CMD_PP_1_1_4], + SPINOR_OP_PP_1_1_4, SNOR_PROTO_1_1_4); + } + if (info->flags & UNLOCK_GLOBAL_BLOCK) { int err; @@ -1361,9 +1380,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, struct spi_nor_flash_parameter params; const struct spi_device_id *id = NULL; struct flash_info *info; - struct device_d *dev = nor->dev; + struct device *dev = nor->dev; struct mtd_info *mtd = nor->mtd; - struct device_node *np = dev->device_node; + struct device_node *np = dev->of_node; int ret; int i; @@ -1438,20 +1457,20 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, mtd->writesize = 1; mtd->flags = MTD_CAP_NORFLASH; mtd->size = params.size; - mtd->erase = spi_nor_erase; - mtd->read = spi_nor_read; + mtd->_erase = spi_nor_erase; + mtd->_read = spi_nor_read; /* nor protection support for STmicro chips */ if (JEDEC_MFR(info) == CFI_MFR_ST) { - mtd->lock = spi_nor_lock; - mtd->unlock = spi_nor_unlock; + mtd->_lock = spi_nor_lock; + mtd->_unlock = spi_nor_unlock; } /* sst nor chips use AAI word program */ if (info->flags & SST_WRITE) - mtd->write = sst_write; + mtd->_write = sst_write; else - mtd->write = spi_nor_write; + mtd->_write = spi_nor_write; if (info->flags & USE_FSR) nor->flags |= SNOR_F_USE_FSR; |