From: Bin Meng <bmeng.cn@gmail.com>
To: Mika Westerberg <mika.westerberg@linux.intel.com>,
Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>,
Marek Vasut <marek.vasut@gmail.com>,
Boris Brezillon <boris.brezillon@free-electrons.com>,
Brian Norris <computersforpeace@gmail.com>,
Richard Weinberger <richard@nod.at>,
David Woodhouse <dwmw2@infradead.org>,
linux-mtd <linux-mtd@lists.infradead.org>,
linux-kernel <linux-kernel@vger.kernel.org>
Cc: Stefan Roese <sr@denx.de>
Subject: [PATCH v2 10/10] spi-nor: intel-spi: Fall back to use SW sequencer to erase
Date: Mon, 11 Sep 2017 02:42:00 -0700 [thread overview]
Message-ID: <1505122921-5534-11-git-send-email-bmeng.cn@gmail.com> (raw)
In-Reply-To: <1505122921-5534-1-git-send-email-bmeng.cn@gmail.com>
According to the datasheet, the HW sequencer has a predefined list
of opcodes, with only the erase opcode being programmable in LVSCC
and UVSCC registers. If these registers don't contain a valid erase
opcode (eg: BIOS does not program it), erase cannot be done using
the HW sequencer, even though the erase operation does not report
any error, the flash remains not erased.
If such register setting is detected, let's fall back to use the SW
sequencer to erase instead.
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
Changes in v2:
- Fix typo of 'operatoin'
drivers/mtd/spi-nor/intel-spi.c | 50 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 49 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c
index 5e7a389..ef034d8 100644
--- a/drivers/mtd/spi-nor/intel-spi.c
+++ b/drivers/mtd/spi-nor/intel-spi.c
@@ -111,6 +111,13 @@
#define BXT_FREG_NUM 12
#define BXT_PR_NUM 6
+#define LVSCC 0xc4
+#define UVSCC 0xc8
+#define ERASE_OPCODE_SHIFT 8
+#define ERASE_OPCODE_MASK (0xff << ERASE_OPCODE_SHIFT)
+#define ERASE_64K_OPCODE_SHIFT 16
+#define ERASE_64K_OPCODE_MASK (0xff << ERASE_OPCODE_SHIFT)
+
#define INTEL_SPI_TIMEOUT 5000 /* ms */
#define INTEL_SPI_FIFO_SZ 64
@@ -127,6 +134,7 @@
* @writeable: Is the chip writeable
* @locked: Is SPI setting locked
* @swseq_reg: Use SW sequencer in register reads/writes
+ * @swseq_erase: Use SW sequencer in erase operation
* @erase_64k: 64k erase supported
* @opcodes: Opcodes which are supported. This are programmed by BIOS
* before it locks down the controller.
@@ -144,6 +152,7 @@ struct intel_spi {
bool writeable;
bool locked;
bool swseq_reg;
+ bool swseq_erase;
bool erase_64k;
u8 opcodes[8];
u8 preopcodes[2];
@@ -191,6 +200,9 @@ static void intel_spi_dump_regs(struct intel_spi *ispi)
if (ispi->info->type == INTEL_SPI_BYT)
dev_dbg(ispi->dev, "BCR=0x%08x\n", readl(ispi->base + BYT_BCR));
+ dev_dbg(ispi->dev, "LVSCC=0x%08x\n", readl(ispi->base + LVSCC));
+ dev_dbg(ispi->dev, "UVSCC=0x%08x\n", readl(ispi->base + UVSCC));
+
dev_dbg(ispi->dev, "Protected regions:\n");
for (i = 0; i < ispi->pr_num; i++) {
u32 base, limit;
@@ -225,6 +237,8 @@ static void intel_spi_dump_regs(struct intel_spi *ispi)
dev_dbg(ispi->dev, "Using %cW sequencer for register access\n",
ispi->swseq_reg ? 'S' : 'H');
+ dev_dbg(ispi->dev, "Using %cW sequencer for erase operation\n",
+ ispi->swseq_erase ? 'S' : 'H');
}
/* Reads max INTEL_SPI_FIFO_SZ bytes from the device fifo */
@@ -288,7 +302,7 @@ static int intel_spi_wait_sw_busy(struct intel_spi *ispi)
static int intel_spi_init(struct intel_spi *ispi)
{
- u32 opmenu0, opmenu1, val;
+ u32 opmenu0, opmenu1, lvscc, uvscc, val;
int i;
switch (ispi->info->type) {
@@ -339,6 +353,24 @@ static int intel_spi_init(struct intel_spi *ispi)
writel(val, ispi->base + HSFSTS_CTL);
/*
+ * Determine whether erase operation should use HW or SW sequencer.
+ *
+ * The HW sequencer has a predefined list of opcodes, with only the
+ * erase opcode being programmable in LVSCC and UVSCC registers.
+ * If these registers don't contain a valid erase opcode, erase
+ * cannot be done using HW sequencer.
+ */
+ lvscc = readl(ispi->base + LVSCC);
+ uvscc = readl(ispi->base + UVSCC);
+ if (!(lvscc & ERASE_OPCODE_MASK) || !(uvscc & ERASE_OPCODE_MASK))
+ ispi->swseq_erase = true;
+ /* SPI controller on Intel BXT supports 64K erase opcode */
+ if (ispi->info->type == INTEL_SPI_BXT && !ispi->swseq_erase)
+ if (!(lvscc & ERASE_64K_OPCODE_MASK) ||
+ !(uvscc & ERASE_64K_OPCODE_MASK))
+ ispi->erase_64k = false;
+
+ /*
* Some controllers can only do basic operations using hardware
* sequencer. All other operations are supposed to be carried out
* using software sequencer.
@@ -665,6 +697,22 @@ static int intel_spi_erase(struct spi_nor *nor, loff_t offs)
erase_size = SZ_4K;
}
+ if (ispi->swseq_erase) {
+ while (len > 0) {
+ writel(offs, ispi->base + FADDR);
+
+ ret = intel_spi_sw_cycle(ispi, nor->erase_opcode,
+ 0, OPTYPE_WRITE_WITH_ADDR);
+ if (ret)
+ return ret;
+
+ offs += erase_size;
+ len -= erase_size;
+ }
+
+ return 0;
+ }
+
while (len > 0) {
writel(offs, ispi->base + FADDR);
--
2.9.2
next prev parent reply other threads:[~2017-09-11 9:38 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-11 9:41 [PATCH v2 00/10] spi-nor: intel-spi: Various fixes and enhancements Bin Meng
2017-09-11 9:41 ` [PATCH v2 01/10] spi-nor: intel-spi: Fix number of protected range registers for BYT/LPT Bin Meng
2017-09-11 9:41 ` [PATCH v2 02/10] spi-nor: intel-spi: Remove useless 'buf' parameter in the HW/SW cycle Bin Meng
2017-09-11 9:41 ` [PATCH v2 03/10] spi-nor: intel-spi: Fix broken software sequencing codes Bin Meng
2017-09-11 9:41 ` [PATCH v2 04/10] spi-nor: intel-spi: Check transfer length in the HW/SW cycle Bin Meng
2017-09-11 9:41 ` [PATCH v2 05/10] spi-nor: intel-spi: Use SW sequencer for BYT/LPT Bin Meng
2017-09-11 9:41 ` [PATCH v2 06/10] spi-nor: intel-spi: Remove 'Atomic Cycle Sequence' in intel_spi_write() Bin Meng
2017-09-11 9:41 ` [PATCH v2 07/10] spi-nor: intel-spi: Don't assume OPMENU0/1 to be programmed by BIOS Bin Meng
2017-09-11 9:41 ` [PATCH v2 08/10] spi-nor: intel-spi: Remove the unnecessary HSFSTS register RW Bin Meng
2017-09-11 9:41 ` [PATCH v2 09/10] spi-nor: intel-spi: Rename swseq to swseq_reg in 'struct intel_spi' Bin Meng
2017-09-11 9:42 ` Bin Meng [this message]
2017-09-11 17:44 ` [PATCH v2 00/10] spi-nor: intel-spi: Various fixes and enhancements Joakim Tjernlund
2017-09-13 2:11 ` Bin Meng
2017-09-13 9:47 ` mika.westerberg
2017-10-11 8:06 ` Cyrille Pitchen
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=1505122921-5534-11-git-send-email-bmeng.cn@gmail.com \
--to=bmeng.cn@gmail.com \
--cc=boris.brezillon@free-electrons.com \
--cc=computersforpeace@gmail.com \
--cc=cyrille.pitchen@wedev4u.fr \
--cc=dwmw2@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=marek.vasut@gmail.com \
--cc=mika.westerberg@linux.intel.com \
--cc=richard@nod.at \
--cc=sr@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