|
@@ -663,6 +663,23 @@ static struct stfsm_seq stfsm_seq_write_status = {
|
|
SEQ_CFG_STARTSEQ),
|
|
SEQ_CFG_STARTSEQ),
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+/* Dummy sequence to read one byte of data from flash into the FIFO */
|
|
|
|
+static const struct stfsm_seq stfsm_seq_load_fifo_byte = {
|
|
|
|
+ .data_size = TRANSFER_SIZE(1),
|
|
|
|
+ .seq_opc[0] = (SEQ_OPC_PADS_1 |
|
|
|
|
+ SEQ_OPC_CYCLES(8) |
|
|
|
|
+ SEQ_OPC_OPCODE(SPINOR_OP_RDID)),
|
|
|
|
+ .seq = {
|
|
|
|
+ STFSM_INST_CMD1,
|
|
|
|
+ STFSM_INST_DATA_READ,
|
|
|
|
+ STFSM_INST_STOP,
|
|
|
|
+ },
|
|
|
|
+ .seq_cfg = (SEQ_CFG_PADS_1 |
|
|
|
|
+ SEQ_CFG_READNOTWRITE |
|
|
|
|
+ SEQ_CFG_CSDEASSERT |
|
|
|
|
+ SEQ_CFG_STARTSEQ),
|
|
|
|
+};
|
|
|
|
+
|
|
static int stfsm_n25q_en_32bit_addr_seq(struct stfsm_seq *seq)
|
|
static int stfsm_n25q_en_32bit_addr_seq(struct stfsm_seq *seq)
|
|
{
|
|
{
|
|
seq->seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) |
|
|
seq->seq_opc[0] = (SEQ_OPC_PADS_1 | SEQ_OPC_CYCLES(8) |
|
|
@@ -695,22 +712,6 @@ static inline uint32_t stfsm_fifo_available(struct stfsm *fsm)
|
|
return (readl(fsm->base + SPI_FAST_SEQ_STA) >> 5) & 0x7f;
|
|
return (readl(fsm->base + SPI_FAST_SEQ_STA) >> 5) & 0x7f;
|
|
}
|
|
}
|
|
|
|
|
|
-static void stfsm_clear_fifo(struct stfsm *fsm)
|
|
|
|
-{
|
|
|
|
- uint32_t avail;
|
|
|
|
-
|
|
|
|
- for (;;) {
|
|
|
|
- avail = stfsm_fifo_available(fsm);
|
|
|
|
- if (!avail)
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- while (avail) {
|
|
|
|
- readl(fsm->base + SPI_FAST_SEQ_DATA_REG);
|
|
|
|
- avail--;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static inline void stfsm_load_seq(struct stfsm *fsm,
|
|
static inline void stfsm_load_seq(struct stfsm *fsm,
|
|
const struct stfsm_seq *seq)
|
|
const struct stfsm_seq *seq)
|
|
{
|
|
{
|
|
@@ -772,6 +773,68 @@ static void stfsm_read_fifo(struct stfsm *fsm, uint32_t *buf, uint32_t size)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Clear the data FIFO
|
|
|
|
+ *
|
|
|
|
+ * Typically, this is only required during driver initialisation, where no
|
|
|
|
+ * assumptions can be made regarding the state of the FIFO.
|
|
|
|
+ *
|
|
|
|
+ * The process of clearing the FIFO is complicated by fact that while it is
|
|
|
|
+ * possible for the FIFO to contain an arbitrary number of bytes [1], the
|
|
|
|
+ * SPI_FAST_SEQ_STA register only reports the number of complete 32-bit words
|
|
|
|
+ * present. Furthermore, data can only be drained from the FIFO by reading
|
|
|
|
+ * complete 32-bit words.
|
|
|
|
+ *
|
|
|
|
+ * With this in mind, a two stage process is used to the clear the FIFO:
|
|
|
|
+ *
|
|
|
|
+ * 1. Read any complete 32-bit words from the FIFO, as reported by the
|
|
|
|
+ * SPI_FAST_SEQ_STA register.
|
|
|
|
+ *
|
|
|
|
+ * 2. Mop up any remaining bytes. At this point, it is not known if there
|
|
|
|
+ * are 0, 1, 2, or 3 bytes in the FIFO. To handle all cases, a dummy FSM
|
|
|
|
+ * sequence is used to load one byte at a time, until a complete 32-bit
|
|
|
|
+ * word is formed; at most, 4 bytes will need to be loaded.
|
|
|
|
+ *
|
|
|
|
+ * [1] It is theoretically possible for the FIFO to contain an arbitrary number
|
|
|
|
+ * of bits. However, since there are no known use-cases that leave
|
|
|
|
+ * incomplete bytes in the FIFO, only words and bytes are considered here.
|
|
|
|
+ */
|
|
|
|
+static void stfsm_clear_fifo(struct stfsm *fsm)
|
|
|
|
+{
|
|
|
|
+ const struct stfsm_seq *seq = &stfsm_seq_load_fifo_byte;
|
|
|
|
+ uint32_t words, i;
|
|
|
|
+
|
|
|
|
+ /* 1. Clear any 32-bit words */
|
|
|
|
+ words = stfsm_fifo_available(fsm);
|
|
|
|
+ if (words) {
|
|
|
|
+ for (i = 0; i < words; i++)
|
|
|
|
+ readl(fsm->base + SPI_FAST_SEQ_DATA_REG);
|
|
|
|
+ dev_dbg(fsm->dev, "cleared %d words from FIFO\n", words);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * 2. Clear any remaining bytes
|
|
|
|
+ * - Load the FIFO, one byte at a time, until a complete 32-bit word
|
|
|
|
+ * is available.
|
|
|
|
+ */
|
|
|
|
+ for (i = 0, words = 0; i < 4 && !words; i++) {
|
|
|
|
+ stfsm_load_seq(fsm, seq);
|
|
|
|
+ stfsm_wait_seq(fsm);
|
|
|
|
+ words = stfsm_fifo_available(fsm);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* - A single word must be available now */
|
|
|
|
+ if (words != 1) {
|
|
|
|
+ dev_err(fsm->dev, "failed to clear bytes from the data FIFO\n");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* - Read the 32-bit word */
|
|
|
|
+ readl(fsm->base + SPI_FAST_SEQ_DATA_REG);
|
|
|
|
+
|
|
|
|
+ dev_dbg(fsm->dev, "cleared %d byte(s) from the data FIFO\n", 4 - i);
|
|
|
|
+}
|
|
|
|
+
|
|
static int stfsm_write_fifo(struct stfsm *fsm, const uint32_t *buf,
|
|
static int stfsm_write_fifo(struct stfsm *fsm, const uint32_t *buf,
|
|
uint32_t size)
|
|
uint32_t size)
|
|
{
|
|
{
|