From: lee.jones@linaro.org (Lee Jones)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v6 32/36] mtd: st_spi_fsm: Supply the S25FLxxx chip specific configuration call-back
Date: Thu, 20 Mar 2014 09:21:04 +0000 [thread overview]
Message-ID: <1395307268-12721-33-git-send-email-lee.jones@linaro.org> (raw)
In-Reply-To: <1395307268-12721-1-git-send-email-lee.jones@linaro.org>
This patch allows us to prepare some of the message sequences which will
be required to talk to the S25FLxxx family of Serial Flash devices. It
also allows us to do some required extra operations after any busy wait
failures.
Acked-by Angus Clark <angus.clark@st.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
drivers/mtd/devices/st_spi_fsm.c | 266 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 260 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c
index 89d5e0b..9db5641 100644
--- a/drivers/mtd/devices/st_spi_fsm.c
+++ b/drivers/mtd/devices/st_spi_fsm.c
@@ -238,6 +238,16 @@
#define FLASH_CMD_READ4_1_1_4 0x6c
#define FLASH_CMD_READ4_1_4_4 0xec
+/* S25FLxxxS commands */
+#define S25FL_CMD_WRITE4_1_1_4 0x34
+#define S25FL_CMD_SE4 0xdc
+#define S25FL_CMD_CLSR 0x30
+#define S25FL_CMD_DYBWR 0xe1
+#define S25FL_CMD_DYBRD 0xe0
+#define S25FL_CMD_WRITE4 0x12 /* Note, opcode clashes with
+ * 'FLASH_CMD_WRITE_1_4_4'
+ * as found on N25Qxxx devices! */
+
/* Status register */
#define FLASH_STATUS_BUSY 0x01
#define FLASH_STATUS_WEL 0x02
@@ -246,6 +256,9 @@
#define FLASH_STATUS_BP2 0x10
#define FLASH_STATUS_SRWP0 0x80
#define FLASH_STATUS_TIMEOUT 0xff
+/* S25FL Error Flags */
+#define S25FL_STATUS_E_ERR 0x20
+#define S25FL_STATUS_P_ERR 0x40
#define FLASH_PAGESIZE 256 /* In Bytes */
#define FLASH_PAGESIZE_32 (FLASH_PAGESIZE / 4) /* In uint32_t */
@@ -327,6 +340,7 @@ struct flash_info {
static int stfsm_n25q_config(struct stfsm *fsm);
static int stfsm_mx25_config(struct stfsm *fsm);
+static int stfsm_s25fl_config(struct stfsm *fsm);
static struct flash_info flash_types[] = {
/*
@@ -388,9 +402,9 @@ static struct flash_info flash_types[] = {
FLASH_FLAG_WRITE_1_1_4 | \
FLASH_FLAG_READ_FAST)
{ "s25fl129p0", 0x012018, 0x4d00, 256 * 1024, 64, S25FLXXXP_FLAG, 80,
- NULL },
+ stfsm_s25fl_config },
{ "s25fl129p1", 0x012018, 0x4d01, 64 * 1024, 256, S25FLXXXP_FLAG, 80,
- NULL },
+ stfsm_s25fl_config },
/*
* Spansion S25FLxxxS
@@ -405,13 +419,13 @@ static struct flash_info flash_types[] = {
FLASH_FLAG_RESET | \
FLASH_FLAG_DYB_LOCKING)
{ "s25fl128s0", 0x012018, 0x0300, 256 * 1024, 64, S25FLXXXS_FLAG, 80,
- NULL },
+ stfsm_s25fl_config },
{ "s25fl128s1", 0x012018, 0x0301, 64 * 1024, 256, S25FLXXXS_FLAG, 80,
- NULL },
+ stfsm_s25fl_config },
{ "s25fl256s0", 0x010219, 0x4d00, 256 * 1024, 128,
- S25FLXXXS_FLAG | FLASH_FLAG_32BIT_ADDR, 80, NULL },
+ S25FLXXXS_FLAG | FLASH_FLAG_32BIT_ADDR, 80, stfsm_s25fl_config },
{ "s25fl256s1", 0x010219, 0x4d01, 64 * 1024, 512,
- S25FLXXXS_FLAG | FLASH_FLAG_32BIT_ADDR, 80, NULL },
+ S25FLXXXS_FLAG | FLASH_FLAG_32BIT_ADDR, 80, stfsm_s25fl_config },
/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
#define W25X_FLAG (FLASH_FLAG_READ_WRITE | \
@@ -536,6 +550,33 @@ static int stfsm_mx25_en_32bit_addr_seq(struct stfsm_seq *seq)
return 0;
}
+/*
+ * [S25FLxxx] Configuration
+ */
+#define STFSM_S25FL_CONFIG_QE (0x1 << 1)
+
+/*
+ * S25FLxxxS devices provide three ways of supporting 32-bit addressing: Bank
+ * Register, Extended Address Modes, and a 32-bit address command set. The
+ * 32-bit address command set is used here, since it avoids any problems with
+ * entering a state that is incompatible with the SPIBoot Controller.
+ */
+static struct seq_rw_config stfsm_s25fl_read4_configs[] = {
+ {FLASH_FLAG_READ_1_4_4, FLASH_CMD_READ4_1_4_4, 0, 4, 4, 0x00, 2, 4},
+ {FLASH_FLAG_READ_1_1_4, FLASH_CMD_READ4_1_1_4, 0, 1, 4, 0x00, 0, 8},
+ {FLASH_FLAG_READ_1_2_2, FLASH_CMD_READ4_1_2_2, 0, 2, 2, 0x00, 4, 0},
+ {FLASH_FLAG_READ_1_1_2, FLASH_CMD_READ4_1_1_2, 0, 1, 2, 0x00, 0, 8},
+ {FLASH_FLAG_READ_FAST, FLASH_CMD_READ4_FAST, 0, 1, 1, 0x00, 0, 8},
+ {FLASH_FLAG_READ_WRITE, FLASH_CMD_READ4, 0, 1, 1, 0x00, 0, 0},
+ {0x00, 0, 0, 0, 0, 0x00, 0, 0},
+};
+
+static struct seq_rw_config stfsm_s25fl_write4_configs[] = {
+ {FLASH_FLAG_WRITE_1_1_4, S25FL_CMD_WRITE4_1_1_4, 1, 1, 4, 0x00, 0, 0},
+ {FLASH_FLAG_READ_WRITE, S25FL_CMD_WRITE4, 1, 1, 1, 0x00, 0, 0},
+ {0x00, 0, 0, 0, 0, 0x00, 0, 0},
+};
+
static struct stfsm_seq stfsm_seq_read; /* Dynamically populated */
static struct stfsm_seq stfsm_seq_write; /* Dynamically populated */
static struct stfsm_seq stfsm_seq_en_32bit_addr;/* Dynamically populated */
@@ -1193,6 +1234,215 @@ static int stfsm_n25q_config(struct stfsm *fsm)
return 0;
}
+static void stfsm_s25fl_prepare_erasesec_seq_32(struct stfsm_seq *seq)
+{
+ seq->seq_opc[1] = (SEQ_OPC_PADS_1 |
+ SEQ_OPC_CYCLES(8) |
+ SEQ_OPC_OPCODE(S25FL_CMD_SE4));
+
+ seq->addr_cfg = (ADR_CFG_CYCLES_ADD1(16) |
+ ADR_CFG_PADS_1_ADD1 |
+ ADR_CFG_CYCLES_ADD2(16) |
+ ADR_CFG_PADS_1_ADD2 |
+ ADR_CFG_CSDEASSERT_ADD2);
+}
+
+static void stfsm_s25fl_read_dyb(struct stfsm *fsm, uint32_t offs, uint8_t *dby)
+{
+ uint32_t tmp;
+ struct stfsm_seq seq = {
+ .data_size = TRANSFER_SIZE(4),
+ .seq_opc[0] = (SEQ_OPC_PADS_1 |
+ SEQ_OPC_CYCLES(8) |
+ SEQ_OPC_OPCODE(S25FL_CMD_DYBRD)),
+ .addr_cfg = (ADR_CFG_CYCLES_ADD1(16) |
+ ADR_CFG_PADS_1_ADD1 |
+ ADR_CFG_CYCLES_ADD2(16) |
+ ADR_CFG_PADS_1_ADD2),
+ .addr1 = (offs >> 16) & 0xffff,
+ .addr2 = offs & 0xffff,
+ .seq = {
+ STFSM_INST_CMD1,
+ STFSM_INST_ADD1,
+ STFSM_INST_ADD2,
+ STFSM_INST_DATA_READ,
+ STFSM_INST_STOP,
+ },
+ .seq_cfg = (SEQ_CFG_PADS_1 |
+ SEQ_CFG_READNOTWRITE |
+ SEQ_CFG_CSDEASSERT |
+ SEQ_CFG_STARTSEQ),
+ };
+
+ stfsm_load_seq(fsm, &seq);
+
+ stfsm_read_fifo(fsm, &tmp, 4);
+
+ *dby = (uint8_t)(tmp >> 24);
+
+ stfsm_wait_seq(fsm);
+}
+
+static void stfsm_s25fl_write_dyb(struct stfsm *fsm, uint32_t offs, uint8_t dby)
+{
+ struct stfsm_seq seq = {
+ .seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) |
+ SEQ_OPC_OPCODE(FLASH_CMD_WREN) |
+ SEQ_OPC_CSDEASSERT),
+ .seq_opc[1] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) |
+ SEQ_OPC_OPCODE(S25FL_CMD_DYBWR)),
+ .addr_cfg = (ADR_CFG_CYCLES_ADD1(16) |
+ ADR_CFG_PADS_1_ADD1 |
+ ADR_CFG_CYCLES_ADD2(16) |
+ ADR_CFG_PADS_1_ADD2),
+ .status = (uint32_t)dby | STA_PADS_1 | STA_CSDEASSERT,
+ .addr1 = (offs >> 16) & 0xffff,
+ .addr2 = offs & 0xffff,
+ .seq = {
+ STFSM_INST_CMD1,
+ STFSM_INST_CMD2,
+ STFSM_INST_ADD1,
+ STFSM_INST_ADD2,
+ STFSM_INST_STA_WR1,
+ STFSM_INST_STOP,
+ },
+ .seq_cfg = (SEQ_CFG_PADS_1 |
+ SEQ_CFG_READNOTWRITE |
+ SEQ_CFG_CSDEASSERT |
+ SEQ_CFG_STARTSEQ),
+ };
+
+ stfsm_load_seq(fsm, &seq);
+ stfsm_wait_seq(fsm);
+
+ stfsm_wait_busy(fsm);
+}
+
+static int stfsm_s25fl_clear_status_reg(struct stfsm *fsm)
+{
+ struct stfsm_seq seq = {
+ .seq_opc[0] = (SEQ_OPC_PADS_1 |
+ SEQ_OPC_CYCLES(8) |
+ SEQ_OPC_OPCODE(S25FL_CMD_CLSR) |
+ SEQ_OPC_CSDEASSERT),
+ .seq_opc[1] = (SEQ_OPC_PADS_1 |
+ SEQ_OPC_CYCLES(8) |
+ SEQ_OPC_OPCODE(FLASH_CMD_WRDI) |
+ SEQ_OPC_CSDEASSERT),
+ .seq = {
+ STFSM_INST_CMD1,
+ STFSM_INST_CMD2,
+ STFSM_INST_WAIT,
+ STFSM_INST_STOP,
+ },
+ .seq_cfg = (SEQ_CFG_PADS_1 |
+ SEQ_CFG_ERASE |
+ SEQ_CFG_READNOTWRITE |
+ SEQ_CFG_CSDEASSERT |
+ SEQ_CFG_STARTSEQ),
+ };
+
+ stfsm_load_seq(fsm, &seq);
+
+ stfsm_wait_seq(fsm);
+
+ return 0;
+}
+
+static int stfsm_s25fl_config(struct stfsm *fsm)
+{
+ struct flash_info *info = fsm->info;
+ uint32_t flags = info->flags;
+ uint32_t data_pads;
+ uint32_t offs;
+ uint16_t sta_wr;
+ uint8_t sr1, cr1, dyb;
+ int ret;
+
+ if (flags & FLASH_FLAG_32BIT_ADDR) {
+ /*
+ * Prepare Read/Write/Erase sequences according to S25FLxxx
+ * 32-bit address command set
+ */
+ ret = stfsm_search_prepare_rw_seq(fsm, &stfsm_seq_read,
+ stfsm_s25fl_read4_configs);
+ if (ret)
+ return ret;
+
+ ret = stfsm_search_prepare_rw_seq(fsm, &stfsm_seq_write,
+ stfsm_s25fl_write4_configs);
+ if (ret)
+ return ret;
+
+ stfsm_s25fl_prepare_erasesec_seq_32(&stfsm_seq_erase_sector);
+
+ } else {
+ /* Use default configurations for 24-bit addressing */
+ ret = stfsm_prepare_rwe_seqs_default(fsm);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * For devices that support 'DYB' sector locking, check lock status and
+ * unlock sectors if necessary (some variants power-on with sectors
+ * locked by default)
+ */
+ if (flags & FLASH_FLAG_DYB_LOCKING) {
+ offs = 0;
+ for (offs = 0; offs < info->sector_size * info->n_sectors;) {
+ stfsm_s25fl_read_dyb(fsm, offs, &dyb);
+ if (dyb == 0x00)
+ stfsm_s25fl_write_dyb(fsm, offs, 0xff);
+
+ /* Handle bottom/top 4KiB parameter sectors */
+ if ((offs < info->sector_size * 2) ||
+ (offs >= (info->sector_size - info->n_sectors * 4)))
+ offs += 0x1000;
+ else
+ offs += 0x10000;
+ }
+ }
+
+ /* Check status of 'QE' bit */
+ data_pads = ((stfsm_seq_read.seq_cfg >> 16) & 0x3) + 1;
+ stfsm_read_status(fsm, FLASH_CMD_RDSR2, &cr1);
+ if (data_pads == 4) {
+ if (!(cr1 & STFSM_S25FL_CONFIG_QE)) {
+ /* Set 'QE' */
+ cr1 |= STFSM_S25FL_CONFIG_QE;
+
+ stfsm_read_status(fsm, FLASH_CMD_RDSR, &sr1);
+ sta_wr = ((uint16_t)cr1 << 8) | sr1;
+
+ stfsm_write_status(fsm, sta_wr, 2);
+
+ stfsm_wait_busy(fsm);
+ }
+ } else {
+ if ((cr1 & STFSM_S25FL_CONFIG_QE)) {
+ /* Clear 'QE' */
+ cr1 &= ~STFSM_S25FL_CONFIG_QE;
+
+ stfsm_read_status(fsm, FLASH_CMD_RDSR, &sr1);
+ sta_wr = ((uint16_t)cr1 << 8) | sr1;
+
+ stfsm_write_status(fsm, sta_wr, 2);
+
+ stfsm_wait_busy(fsm);
+ }
+
+ }
+
+ /*
+ * S25FLxxx devices support Program and Error error flags.
+ * Configure driver to check flags and clear if necessary.
+ */
+ fsm->configuration |= CFG_S25FL_CHECK_ERROR_FLAGS;
+
+ return 0;
+}
+
static int stfsm_read(struct stfsm *fsm, uint8_t *buf, uint32_t size,
uint32_t offset)
{
@@ -1335,6 +1585,8 @@ static int stfsm_write(struct stfsm *fsm, const uint8_t *const buf,
/* Wait for completion */
ret = stfsm_wait_busy(fsm);
+ if (ret && fsm->configuration & CFG_S25FL_CHECK_ERROR_FLAGS)
+ stfsm_s25fl_clear_status_reg(fsm);
/* Exit 32-bit address mode, if required */
if (fsm->configuration & CFG_WRITE_TOGGLE_32BIT_ADDR) {
@@ -1398,6 +1650,8 @@ static int stfsm_erase_sector(struct stfsm *fsm, const uint32_t offset)
/* Wait for completion */
ret = stfsm_wait_busy(fsm);
+ if (ret && fsm->configuration & CFG_S25FL_CHECK_ERROR_FLAGS)
+ stfsm_s25fl_clear_status_reg(fsm);
/* Exit 32-bit address mode, if required */
if (fsm->configuration & CFG_ERASESEC_TOGGLE_32BIT_ADDR)
--
1.8.3.2
next prev parent reply other threads:[~2014-03-20 9:21 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-20 9:20 [PATCH v6 00/36] mtd: st_spi_fsm: Add new driver Lee Jones
2014-03-20 9:20 ` [PATCH v6 01/36] mtd: st_spi_fsm: Allocate resources and register with MTD framework Lee Jones
2014-04-07 8:12 ` Paul Bolle
2014-04-07 9:11 ` Lee Jones
2014-04-07 9:41 ` Paul Bolle
2014-04-07 11:08 ` Lee Jones
2014-03-20 9:20 ` [PATCH v6 02/36] mtd: st_spi_fsm: Supply all register address and bit logic defines Lee Jones
2014-03-20 9:20 ` [PATCH v6 03/36] mtd: st_spi_fsm: Initialise and configure the FSM for normal working conditions Lee Jones
2014-03-20 9:20 ` [PATCH v6 04/36] mtd: st_spi_fsm: Supply framework for device requests Lee Jones
2014-03-20 9:20 ` [PATCH v6 05/36] mtd: st_spi_fsm: Supply a method to read from the FSM's FIFO Lee Jones
2014-03-20 9:20 ` [PATCH v6 06/36] mtd: st_spi_fsm: Add support for JEDEC ID extraction Lee Jones
2014-03-20 9:20 ` [PATCH v6 07/36] mtd: devices: Provide header for shared OPCODEs and SFDP commands Lee Jones
2014-03-20 9:20 ` [PATCH v6 08/36] mtd: st_spi_fsm: Provide device look-up table Lee Jones
2014-03-20 9:20 ` [PATCH v6 09/36] mtd: st_spi_fsm: Dynamically setup flash device based on JEDEC ID Lee Jones
2014-03-20 9:20 ` [PATCH v6 10/36] mtd: st_spi_fsm: Search for preferred FSM message sequence configurations Lee Jones
2014-03-20 9:20 ` [PATCH v6 11/36] mtd: st_spi_fsm: Use device size to determine address width Lee Jones
2014-03-20 9:20 ` [PATCH v6 12/36] mtd: st_spi_fsm: Prepare the read/write FSM message sequence(s) Lee Jones
2014-03-20 9:20 ` [PATCH v6 13/36] mtd: st_spi_fsm: Add device-tree binding documentation Lee Jones
2014-03-20 9:20 ` [PATCH v6 14/36] mtd: st_spi_fsm: Fetch boot-device from mode pins Lee Jones
2014-03-20 9:20 ` [PATCH v6 15/36] mtd: st_spi_fsm: Provide the erase one sector sequence Lee Jones
2014-03-20 9:20 ` [PATCH v6 16/36] mtd: st_spi_fsm: Provide the sequence for enabling 32bit addressing mode Lee Jones
2014-03-20 9:20 ` [PATCH v6 17/36] mtd: st_spi_fsm: Prepare read/write sequences according to configuration Lee Jones
2014-03-20 9:20 ` [PATCH v6 18/36] mtd: st_spi_fsm: Add a check to if the chip can handle an SoC reset Lee Jones
2014-03-20 9:20 ` [PATCH v6 19/36] mtd: st_spi_fsm: Provide a method to put the chip into 32bit addressing mode Lee Jones
2014-03-20 9:20 ` [PATCH v6 20/36] mtd: st_spi_fsm: Update the flash Volatile Configuration Register Lee Jones
2014-03-20 9:20 ` [PATCH v6 21/36] mtd: st_spi_fsm: Provide the default read/write configurations Lee Jones
2014-03-20 9:20 ` [PATCH v6 22/36] mtd: st_spi_fsm: Supply the N25Qxxx specific read configurations Lee Jones
2014-03-20 9:20 ` [PATCH v6 23/36] mtd: st_spi_fsm: Supply the N25Qxxx chip specific configuration call-back Lee Jones
2014-03-20 9:20 ` [PATCH v6 24/36] mtd: st_spi_fsm: Prepare default sequences for read/write/erase Lee Jones
2014-03-20 9:20 ` [PATCH v6 25/36] mtd: st_spi_fsm: Add the ability to read from a Serial Flash device Lee Jones
2014-03-20 9:20 ` [PATCH v6 26/36] mtd: st_spi_fsm: Write to Flash via the FSM FIFO Lee Jones
2014-03-20 9:20 ` [PATCH v6 27/36] mtd: st_spi_fsm: Supply a busy wait for post-write status Lee Jones
2014-03-20 9:21 ` [PATCH v6 28/36] mtd: st_spi_fsm: Erase partly or as a whole a Serial Flash device Lee Jones
2014-03-20 9:21 ` [PATCH v6 29/36] mtd: st_spi_fsm: Add the ability to read the FSM's status Lee Jones
2014-03-20 9:21 ` [PATCH v6 30/36] mtd: st_spi_fsm: Add the ability to write to FSM's status register Lee Jones
2014-03-20 9:21 ` [PATCH v6 31/36] mtd: st_spi_fsm: Supply the MX25xxx chip specific configuration call-back Lee Jones
2014-03-20 9:21 ` Lee Jones [this message]
2014-03-20 9:21 ` [PATCH v6 33/36] mtd: st_spi_fsm: Supply the W25Qxxx " Lee Jones
2014-03-20 9:21 ` [PATCH v6 34/36] mtd: st_spi_fsm: Move runtime configurable msg sequences into device's struct Lee Jones
2014-03-20 9:21 ` [PATCH v6 35/36] mtd: st_spi_fsm: Convert ST SPI FSM (NOR) Flash driver to new DT partitions Lee Jones
2014-03-20 9:21 ` [PATCH v6 36/36] ARM: STi: Add support for the FSM Serial Flash Controller Lee Jones
2014-03-20 11:27 ` Brian Norris
2014-03-20 15:51 ` Lee Jones
2014-03-20 9:48 ` [PATCH v6 00/36] mtd: st_spi_fsm: Add new driver Brian Norris
2014-03-20 11:19 ` Brian Norris
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=1395307268-12721-33-git-send-email-lee.jones@linaro.org \
--to=lee.jones@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
/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;
as well as URLs for NNTP newsgroup(s).