From: Vignesh R <vigneshr@ti.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v3 12/20] mtd: spi: spi-nor-core: Add back U-Boot specific features
Date: Tue, 29 Jan 2019 11:19:59 +0530 [thread overview]
Message-ID: <20190129055007.17376-13-vigneshr@ti.com> (raw)
In-Reply-To: <20190129055007.17376-1-vigneshr@ti.com>
For legacy reasons, we will have to keep around U-Boot specific
SPI_FLASH_BAR and SPI_TX_BYTE. Add them back to the new framework
Signed-off-by: Vignesh R <vigneshr@ti.com>
---
drivers/mtd/spi/spi-nor-core.c | 162 ++++++++++++++++++++++++++++++++-
include/linux/mtd/spi-nor.h | 9 ++
2 files changed, 168 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 97ec8e8e7a19..c3f6929db506 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -291,6 +291,7 @@ static struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
return mtd->priv;
}
+#ifndef CONFIG_SPI_FLASH_BAR
static u8 spi_nor_convert_opcode(u8 opcode, const u8 table[][2], size_t size)
{
size_t i;
@@ -365,6 +366,7 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor,
nor->program_opcode = spi_nor_convert_3to4_program(nor->program_opcode);
nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);
}
+#endif /* !CONFIG_SPI_FLASH_BAR */
/* Enable/disable 4-byte addressing mode. */
static int set_4byte(struct spi_nor *nor, const struct flash_info *info,
@@ -499,6 +501,79 @@ static int spi_nor_wait_till_ready(struct spi_nor *nor)
DEFAULT_READY_WAIT_JIFFIES);
}
+#ifdef CONFIG_SPI_FLASH_BAR
+/*
+ * This "clean_bar" is necessary in a situation when one was accessing
+ * spi flash memory > 16 MiB by using Bank Address Register's BA24 bit.
+ *
+ * After it the BA24 bit shall be cleared to allow access to correct
+ * memory region after SW reset (by calling "reset" command).
+ *
+ * Otherwise, the BA24 bit may be left set and then after reset, the
+ * ROM would read/write/erase SPL from 16 MiB * bank_sel address.
+ */
+static int clean_bar(struct spi_nor *nor)
+{
+ u8 cmd, bank_sel = 0;
+
+ if (nor->bank_curr == 0)
+ return 0;
+ cmd = nor->bank_write_cmd;
+ nor->bank_curr = 0;
+ write_enable(nor);
+
+ return nor->write_reg(nor, cmd, &bank_sel, 1);
+}
+
+static int write_bar(struct spi_nor *nor, u32 offset)
+{
+ u8 cmd, bank_sel;
+ int ret;
+
+ bank_sel = offset / SZ_16M;
+ if (bank_sel == nor->bank_curr)
+ goto bar_end;
+
+ cmd = nor->bank_write_cmd;
+ write_enable(nor);
+ ret = nor->write_reg(nor, cmd, &bank_sel, 1);
+ if (ret < 0) {
+ debug("SF: fail to write bank register\n");
+ return ret;
+ }
+
+bar_end:
+ nor->bank_curr = bank_sel;
+ return nor->bank_curr;
+}
+
+static int read_bar(struct spi_nor *nor, const struct flash_info *info)
+{
+ u8 curr_bank = 0;
+ int ret;
+
+ switch (JEDEC_MFR(info)) {
+ case SNOR_MFR_SPANSION:
+ nor->bank_read_cmd = SPINOR_OP_BRRD;
+ nor->bank_write_cmd = SPINOR_OP_BRWR;
+ break;
+ default:
+ nor->bank_read_cmd = SPINOR_OP_RDEAR;
+ nor->bank_write_cmd = SPINOR_OP_WREAR;
+ }
+
+ ret = nor->read_reg(nor, nor->bank_read_cmd,
+ &curr_bank, 1);
+ if (ret) {
+ debug("SF: fail to read bank addr register\n");
+ return ret;
+ }
+ nor->bank_curr = curr_bank;
+
+ return 0;
+}
+#endif
+
/*
* Initiate the erasure of a single sector
*/
@@ -543,6 +618,11 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
len = instr->len;
while (len) {
+#ifdef CONFIG_SPI_FLASH_BAR
+ ret = write_bar(nor, addr);
+ if (ret < 0)
+ return ret;
+#endif
write_enable(nor);
ret = spi_nor_erase_sector(nor, addr);
@@ -557,9 +637,12 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
goto erase_err;
}
+erase_err:
+#ifdef CONFIG_SPI_FLASH_BAR
+ ret = clean_bar(nor);
+#endif
write_disable(nor);
-erase_err:
return ret;
}
@@ -1144,8 +1227,23 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
while (len) {
loff_t addr = from;
+ size_t read_len = len;
- ret = nor->read(nor, addr, len, buf);
+#ifdef CONFIG_SPI_FLASH_BAR
+ u32 remain_len;
+
+ ret = write_bar(nor, addr);
+ if (ret < 0)
+ return log_ret(ret);
+ remain_len = (SZ_16M * (nor->bank_curr + 1)) - addr;
+
+ if (len < remain_len)
+ read_len = len;
+ else
+ read_len = remain_len;
+#endif
+
+ ret = nor->read(nor, addr, read_len, buf);
if (ret == 0) {
/* We shouldn't see 0-length reads */
ret = -EIO;
@@ -1162,18 +1260,49 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
ret = 0;
read_err:
+#ifdef CONFIG_SPI_FLASH_BAR
+ ret = clean_bar(nor);
+#endif
return ret;
}
#ifdef CONFIG_SPI_FLASH_SST
+static int sst_write_byteprogram(struct spi_nor *nor, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ size_t actual;
+ int ret = 0;
+
+ for (actual = 0; actual < len; actual++) {
+ nor->program_opcode = SPINOR_OP_BP;
+
+ write_enable(nor);
+ /* write one byte. */
+ ret = nor->write(nor, to, 1, buf + actual);
+ if (ret < 0)
+ goto sst_write_err;
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ goto sst_write_err;
+ to++;
+ }
+
+sst_write_err:
+ write_disable(nor);
+ return ret;
+}
+
static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ struct spi_slave *spi = nor->spi;
size_t actual;
int ret;
dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
+ if (spi->mode & SPI_TX_BYTE)
+ return sst_write_byteprogram(nor, to, len, retlen, buf);
write_enable(nor);
@@ -1271,6 +1400,11 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
page_remain = min_t(size_t,
nor->page_size - page_offset, len - i);
+#ifdef CONFIG_SPI_FLASH_BAR
+ ret = write_bar(nor, addr);
+ if (ret < 0)
+ return ret;
+#endif
write_enable(nor);
ret = nor->write(nor, addr, page_remain, buf + i);
if (ret < 0)
@@ -1289,6 +1423,9 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
}
write_err:
+#ifdef CONFIG_SPI_FLASH_BAR
+ ret = clean_bar(nor);
+#endif
return ret;
}
@@ -2532,12 +2669,20 @@ int spi_nor_scan(struct spi_nor *nor)
/* already configured from SFDP */
} else if (info->addr_width) {
nor->addr_width = info->addr_width;
- } else if (mtd->size > 0x1000000) {
+ } else if (mtd->size > SZ_16M) {
+#ifndef CONFIG_SPI_FLASH_BAR
/* enable 4-byte addressing if the device exceeds 16MiB */
nor->addr_width = 4;
if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||
info->flags & SPI_NOR_4B_OPCODES)
spi_nor_set_4byte_opcodes(nor, info);
+#else
+ /* Configure the BAR - discover bank cmds and read current bank */
+ nor->addr_width = 3;
+ ret = read_bar(nor, info);
+ if (ret < 0)
+ return ret;
+#endif
} else {
nor->addr_width = 3;
}
@@ -2571,6 +2716,17 @@ int spi_nor_scan(struct spi_nor *nor)
}
EXPORT_SYMBOL_GPL(spi_nor_scan);
+/* U-Boot specific functions, need to extend MTD to support these */
+int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor)
+{
+ int sr = read_sr(nor);
+
+ if (sr < 0)
+ return sr;
+
+ return (sr >> 2) & 7;
+}
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Huang Shijie <shijie8@gmail.com>");
MODULE_AUTHOR("Mike Lavender");
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 507458a76076..88e80af57941 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -105,6 +105,7 @@
/* Used for Spansion flashes only. */
#define SPINOR_OP_BRWR 0x17 /* Bank register write */
+#define SPINOR_OP_BRRD 0x16 /* Bank register read */
#define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */
/* Used for Micron flashes only. */
@@ -256,6 +257,9 @@ struct flash_info;
* @read_opcode: the read opcode
* @read_dummy: the dummy needed by the read operation
* @program_opcode: the program opcode
+ * @bank_read_cmd: Bank read cmd
+ * @bank_write_cmd: Bank write cmd
+ * @bank_curr: Current flash bank
* @sst_write_second: used by the SST write operation
* @flags: flag options for the current SPI-NOR (SNOR_F_*)
* @read_proto: the SPI protocol for read operations
@@ -291,6 +295,11 @@ struct spi_nor {
u8 read_opcode;
u8 read_dummy;
u8 program_opcode;
+#ifdef CONFIG_SPI_FLASH_BAR
+ u8 bank_read_cmd;
+ u8 bank_write_cmd;
+ u8 bank_curr;
+#endif
enum spi_nor_protocol read_proto;
enum spi_nor_protocol write_proto;
enum spi_nor_protocol reg_proto;
--
2.20.1
next prev parent reply other threads:[~2019-01-29 5:49 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-29 5:49 [U-Boot] [PATCH v3 00/20] SF: Migrate to Linux SPI NOR framework Vignesh R
2019-01-29 5:49 ` [U-Boot] [PATCH v3 01/20] configs: Move CONFIG_SPI_FLASH into defconfigs Vignesh R
2019-01-29 5:49 ` [U-Boot] [PATCH v3 02/20] bitops: Fix GENMASK definition for Sandbox Vignesh R
2019-01-31 0:41 ` Simon Glass
2019-01-31 13:34 ` Vignesh R
2019-01-29 5:49 ` [U-Boot] [PATCH v3 03/20] spi: spi-mem: Allow use of spi_mem_exec_op for all SPI modes Vignesh R
2019-01-29 5:49 ` [U-Boot] [PATCH v3 04/20] spi: spi-mem: Extend spi_mem_adjust_op_size() to honor max xfer size Vignesh R
2019-01-29 5:49 ` [U-Boot] [PATCH v3 05/20] spi: spi-mem: Claim SPI bus before spi mem access Vignesh R
2019-01-29 5:49 ` [U-Boot] [PATCH v3 06/20] spi: Add non DM version of SPI_MEM Vignesh R
2019-01-29 5:49 ` [U-Boot] [PATCH v3 07/20] sh: bitops: add hweight*() macros Vignesh R
2019-01-29 5:49 ` [U-Boot] [PATCH v3 08/20] mtd: spi: Port SPI NOR framework from Linux Vignesh R
2019-01-29 5:49 ` [U-Boot] [PATCH v3 09/20] mtd: spi: spi-nor-core: Add SPI MEM support Vignesh R
2019-01-29 5:49 ` [U-Boot] [PATCH v3 10/20] mtd: spi: spi-nor-core: Add 4 Byte addressing support Vignesh R
2019-01-29 5:49 ` [U-Boot] [PATCH v3 11/20] mtd: spi: spi-nor-core: Add SFDP support Vignesh R
2019-01-29 5:49 ` Vignesh R [this message]
2019-01-29 5:50 ` [U-Boot] [PATCH v3 13/20] mtd: spi: sf_probe: Add "jedec, spi-nor" compatible string Vignesh R
2019-01-29 5:50 ` [U-Boot] [PATCH v3 14/20] mtd: spi: Switch to new SPI NOR framework Vignesh R
2019-01-31 12:23 ` Jagan Teki
2019-01-31 12:39 ` Vignesh R
2019-01-31 12:39 ` Jagan Teki
2019-01-31 12:55 ` Vignesh R
2019-01-31 12:57 ` Jagan Teki
2019-01-29 5:50 ` [U-Boot] [PATCH v3 15/20] mtd: spi: Remove unused files Vignesh R
2019-01-29 5:50 ` [U-Boot] [PATCH v3 16/20] mtd: spi: Add lightweight SPI flash stack for SPL Vignesh R
2019-01-31 12:06 ` Jagan Teki
2019-01-31 17:51 ` Vignesh R
2019-02-01 15:48 ` Jagan Teki
2019-02-01 17:04 ` Vignesh R
2019-02-02 13:12 ` Jagan Teki
2019-01-29 5:50 ` [U-Boot] [PATCH v3 17/20] spl: Kconfig: Enable SPI_FLASH_TINY by default " Vignesh R
2019-01-29 5:50 ` [U-Boot] [PATCH v3 18/20] configs: Remove SF_DUAL_FLASH Vignesh R
2019-01-29 5:50 ` [U-Boot] [PATCH v3 19/20] configs: Don't use SPI_FLASH_BAR as default Vignesh R
2019-01-31 13:18 ` Jagan Teki
2019-01-31 13:33 ` Vignesh R
2019-01-31 13:36 ` Jagan Teki
2019-01-31 13:47 ` Vignesh R
2019-01-31 13:50 ` Jagan Teki
2019-01-31 17:35 ` Vignesh R
2019-02-01 15:54 ` Jagan Teki
2019-02-01 17:08 ` Vignesh R
2019-02-02 13:10 ` Jagan Teki
2019-01-29 5:50 ` [U-Boot] [PATCH v3 20/20] MAINTAINERS: Add an entry for SPI NOR Vignesh R
2019-01-29 8:15 ` [U-Boot] [PATCH v3 00/20] SF: Migrate to Linux SPI NOR framework Simon Goldschmidt
2019-01-29 11:56 ` Vignesh R
2019-01-29 11:58 ` Simon Goldschmidt
2019-01-29 12:25 ` Tom Rini
2019-01-31 14:40 ` Jagan Teki
2019-01-31 14:42 ` Tom Rini
2019-01-31 14:45 ` Jagan Teki
2019-02-01 8:27 ` Vignesh R
2019-02-04 19:03 ` Jagan Teki
2019-01-31 14:48 ` Simon Goldschmidt
2019-01-31 14:51 ` Jagan Teki
2019-01-31 14:54 ` Tom Rini
2019-01-31 14:58 ` Simon Goldschmidt
2019-01-31 15:02 ` Tom Rini
2019-01-31 15:08 ` Simon Goldschmidt
2019-01-31 15:00 ` Jagan Teki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190129055007.17376-13-vigneshr@ti.com \
--to=vigneshr@ti.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox