Commit 009e7e61 authored by Angus Clark's avatar Angus Clark Committed by Brian Norris

mtd: st_spi_fsm: Update Macronix 32-bit addressing support

Support for the Macronix 32-bit addressing scheme was originally developed using
the MX25L25635E device.  As is often the case, it was found that the presence of
a "WAIT" instruction was required for the "EN4B/EX4B" FSM Sequence to complete.
(It is known that the SPI FSM Controller makes certain undocumented assumptions
regarding what constitutes a valid sequence.)  However, further testing
suggested that a small delay was required after issuing the "EX4B" command;
without this delay, data corruptions were observed, consistent with the device
not being ready to retrieve data.  Although the issue was not fully understood,
the workaround of adding a small delay was implemented, while awaiting
clarification from Macronix.

The same behaviour has now been found with a second Macronix device, the
MX25L25655E.  However, with this device, it seems that the delay is also
required after the 'EN4B' commands.  This discovery has prompted us to revisit
the issue.

Although still not conclusive, further tests have suggested that the issue is
down to the SPI FSM Controller, rather than the Macronix devices.  Furthermore,
an alternative workaround has emerged which is to set the WAIT time to
0x00000001, rather then 0x00000000.  (Note, the WAIT instruction is used purely
for the purpose of achieving "sequence validity", rather than actually
implementing a delay!)

The issue is now being investigated by the Design and Validation teams.  In the
meantime, we implement the alternative workaround, which reduces the effective
delay from 1us to 1ns.
Signed-off-by: default avatarAngus Clark <angus.clark@st.com>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
Signed-off-by: default avatarBrian Norris <computersforpeace@gmail.com>
parent 5fa98069
...@@ -270,7 +270,6 @@ ...@@ -270,7 +270,6 @@
*/ */
#define CFG_READ_TOGGLE_32BIT_ADDR 0x00000001 #define CFG_READ_TOGGLE_32BIT_ADDR 0x00000001
#define CFG_WRITE_TOGGLE_32BIT_ADDR 0x00000002 #define CFG_WRITE_TOGGLE_32BIT_ADDR 0x00000002
#define CFG_WRITE_EX_32BIT_ADDR_DELAY 0x00000004
#define CFG_ERASESEC_TOGGLE_32BIT_ADDR 0x00000008 #define CFG_ERASESEC_TOGGLE_32BIT_ADDR 0x00000008
#define CFG_S25FL_CHECK_ERROR_FLAGS 0x00000010 #define CFG_S25FL_CHECK_ERROR_FLAGS 0x00000010
...@@ -1152,23 +1151,17 @@ static int stfsm_mx25_config(struct stfsm *fsm) ...@@ -1152,23 +1151,17 @@ static int stfsm_mx25_config(struct stfsm *fsm)
stfsm_mx25_en_32bit_addr_seq(&fsm->stfsm_seq_en_32bit_addr); stfsm_mx25_en_32bit_addr_seq(&fsm->stfsm_seq_en_32bit_addr);
soc_reset = stfsm_can_handle_soc_reset(fsm); soc_reset = stfsm_can_handle_soc_reset(fsm);
if (soc_reset || !fsm->booted_from_spi) { if (soc_reset || !fsm->booted_from_spi)
/* If we can handle SoC resets, we enable 32-bit address /* If we can handle SoC resets, we enable 32-bit address
* mode pervasively */ * mode pervasively */
stfsm_enter_32bit_addr(fsm, 1); stfsm_enter_32bit_addr(fsm, 1);
} else { else
/* Else, enable/disable 32-bit addressing before/after /* Else, enable/disable 32-bit addressing before/after
* each operation */ * each operation */
fsm->configuration = (CFG_READ_TOGGLE_32BIT_ADDR | fsm->configuration = (CFG_READ_TOGGLE_32BIT_ADDR |
CFG_WRITE_TOGGLE_32BIT_ADDR | CFG_WRITE_TOGGLE_32BIT_ADDR |
CFG_ERASESEC_TOGGLE_32BIT_ADDR); CFG_ERASESEC_TOGGLE_32BIT_ADDR);
/* It seems a small delay is required after exiting
* 32-bit mode following a write operation. The issue
* is under investigation.
*/
fsm->configuration |= CFG_WRITE_EX_32BIT_ADDR_DELAY;
}
} }
/* For QUAD mode, set 'QE' STATUS bit */ /* For QUAD mode, set 'QE' STATUS bit */
...@@ -1631,11 +1624,8 @@ static int stfsm_write(struct stfsm *fsm, const uint8_t *buf, ...@@ -1631,11 +1624,8 @@ static int stfsm_write(struct stfsm *fsm, const uint8_t *buf,
stfsm_s25fl_clear_status_reg(fsm); stfsm_s25fl_clear_status_reg(fsm);
/* Exit 32-bit address mode, if required */ /* Exit 32-bit address mode, if required */
if (fsm->configuration & CFG_WRITE_TOGGLE_32BIT_ADDR) { if (fsm->configuration & CFG_WRITE_TOGGLE_32BIT_ADDR)
stfsm_enter_32bit_addr(fsm, 0); stfsm_enter_32bit_addr(fsm, 0);
if (fsm->configuration & CFG_WRITE_EX_32BIT_ADDR_DELAY)
udelay(1);
}
return 0; return 0;
} }
...@@ -1938,6 +1928,13 @@ static int stfsm_init(struct stfsm *fsm) ...@@ -1938,6 +1928,13 @@ static int stfsm_init(struct stfsm *fsm)
fsm->base + SPI_CONFIGDATA); fsm->base + SPI_CONFIGDATA);
writel(STFSM_DEFAULT_WR_TIME, fsm->base + SPI_STATUS_WR_TIME_REG); writel(STFSM_DEFAULT_WR_TIME, fsm->base + SPI_STATUS_WR_TIME_REG);
/*
* Set the FSM 'WAIT' delay to the minimum workable value. Note, for
* our purposes, the WAIT instruction is used purely to achieve
* "sequence validity" rather than actually implement a delay.
*/
writel(0x00000001, fsm->base + SPI_PROGRAM_ERASE_TIME);
/* Clear FIFO, just in case */ /* Clear FIFO, just in case */
stfsm_clear_fifo(fsm); stfsm_clear_fifo(fsm);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment