summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/spi-nor/spi-nor.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/spi-nor/spi-nor.c')
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c61
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(&params->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(
+ &params->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;