aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/devices
diff options
context:
space:
mode:
authorAngus Clark <angus.clark@st.com>2014-03-26 12:39:16 -0400
committerBrian Norris <computersforpeace@gmail.com>2014-04-14 14:22:59 -0400
commit009e7e61b1f15b16964f1b4b6bb1e30e6b03dc3b (patch)
treed79f9cf93bcb63c3581d3d6bda3e8b5bfffd99b4 /drivers/mtd/devices
parent5fa980691bb4f61e3c2ca9ca451111be4e06caa2 (diff)
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: Angus Clark <angus.clark@st.com> Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'drivers/mtd/devices')
-rw-r--r--drivers/mtd/devices/st_spi_fsm.c23
1 files changed, 10 insertions, 13 deletions
diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c
index d7e38cc8814f..40eb830eea21 100644
--- a/drivers/mtd/devices/st_spi_fsm.c
+++ b/drivers/mtd/devices/st_spi_fsm.c
@@ -270,7 +270,6 @@
270 */ 270 */
271#define CFG_READ_TOGGLE_32BIT_ADDR 0x00000001 271#define CFG_READ_TOGGLE_32BIT_ADDR 0x00000001
272#define CFG_WRITE_TOGGLE_32BIT_ADDR 0x00000002 272#define CFG_WRITE_TOGGLE_32BIT_ADDR 0x00000002
273#define CFG_WRITE_EX_32BIT_ADDR_DELAY 0x00000004
274#define CFG_ERASESEC_TOGGLE_32BIT_ADDR 0x00000008 273#define CFG_ERASESEC_TOGGLE_32BIT_ADDR 0x00000008
275#define CFG_S25FL_CHECK_ERROR_FLAGS 0x00000010 274#define CFG_S25FL_CHECK_ERROR_FLAGS 0x00000010
276 275
@@ -1152,23 +1151,17 @@ static int stfsm_mx25_config(struct stfsm *fsm)
1152 stfsm_mx25_en_32bit_addr_seq(&fsm->stfsm_seq_en_32bit_addr); 1151 stfsm_mx25_en_32bit_addr_seq(&fsm->stfsm_seq_en_32bit_addr);
1153 1152
1154 soc_reset = stfsm_can_handle_soc_reset(fsm); 1153 soc_reset = stfsm_can_handle_soc_reset(fsm);
1155 if (soc_reset || !fsm->booted_from_spi) { 1154 if (soc_reset || !fsm->booted_from_spi)
1156 /* If we can handle SoC resets, we enable 32-bit address 1155 /* If we can handle SoC resets, we enable 32-bit address
1157 * mode pervasively */ 1156 * mode pervasively */
1158 stfsm_enter_32bit_addr(fsm, 1); 1157 stfsm_enter_32bit_addr(fsm, 1);
1159 1158
1160 } else { 1159 else
1161 /* Else, enable/disable 32-bit addressing before/after 1160 /* Else, enable/disable 32-bit addressing before/after
1162 * each operation */ 1161 * each operation */
1163 fsm->configuration = (CFG_READ_TOGGLE_32BIT_ADDR | 1162 fsm->configuration = (CFG_READ_TOGGLE_32BIT_ADDR |
1164 CFG_WRITE_TOGGLE_32BIT_ADDR | 1163 CFG_WRITE_TOGGLE_32BIT_ADDR |
1165 CFG_ERASESEC_TOGGLE_32BIT_ADDR); 1164 CFG_ERASESEC_TOGGLE_32BIT_ADDR);
1166 /* It seems a small delay is required after exiting
1167 * 32-bit mode following a write operation. The issue
1168 * is under investigation.
1169 */
1170 fsm->configuration |= CFG_WRITE_EX_32BIT_ADDR_DELAY;
1171 }
1172 } 1165 }
1173 1166
1174 /* For QUAD mode, set 'QE' STATUS bit */ 1167 /* For QUAD mode, set 'QE' STATUS bit */
@@ -1631,11 +1624,8 @@ static int stfsm_write(struct stfsm *fsm, const uint8_t *buf,
1631 stfsm_s25fl_clear_status_reg(fsm); 1624 stfsm_s25fl_clear_status_reg(fsm);
1632 1625
1633 /* Exit 32-bit address mode, if required */ 1626 /* Exit 32-bit address mode, if required */
1634 if (fsm->configuration & CFG_WRITE_TOGGLE_32BIT_ADDR) { 1627 if (fsm->configuration & CFG_WRITE_TOGGLE_32BIT_ADDR)
1635 stfsm_enter_32bit_addr(fsm, 0); 1628 stfsm_enter_32bit_addr(fsm, 0);
1636 if (fsm->configuration & CFG_WRITE_EX_32BIT_ADDR_DELAY)
1637 udelay(1);
1638 }
1639 1629
1640 return 0; 1630 return 0;
1641} 1631}
@@ -1938,6 +1928,13 @@ static int stfsm_init(struct stfsm *fsm)
1938 fsm->base + SPI_CONFIGDATA); 1928 fsm->base + SPI_CONFIGDATA);
1939 writel(STFSM_DEFAULT_WR_TIME, fsm->base + SPI_STATUS_WR_TIME_REG); 1929 writel(STFSM_DEFAULT_WR_TIME, fsm->base + SPI_STATUS_WR_TIME_REG);
1940 1930
1931 /*
1932 * Set the FSM 'WAIT' delay to the minimum workable value. Note, for
1933 * our purposes, the WAIT instruction is used purely to achieve
1934 * "sequence validity" rather than actually implement a delay.
1935 */
1936 writel(0x00000001, fsm->base + SPI_PROGRAM_ERASE_TIME);
1937
1941 /* Clear FIFO, just in case */ 1938 /* Clear FIFO, just in case */
1942 stfsm_clear_fifo(fsm); 1939 stfsm_clear_fifo(fsm);
1943 1940