This also fix 8-wire support a bit.

Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevets...@iopsys.eu>
---
 drivers/spi/spi-mem.c | 13 +++---
 include/spi-mem.h     | 92 ++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 90 insertions(+), 15 deletions(-)

diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index 3579b7d7db5..6f06650384c 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -120,18 +120,21 @@ static int spi_check_buswidth_req(struct spi_slave 
*slave, u8 buswidth, bool tx)
                return 0;
 
        case 2:
-               if ((tx && (mode & (SPI_TX_DUAL | SPI_TX_QUAD))) ||
-                   (!tx && (mode & (SPI_RX_DUAL | SPI_RX_QUAD))))
+               if ((tx &&
+                    (mode & (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL))) ||
+                   (!tx &&
+                    (mode & (SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL))))
                        return 0;
 
                break;
 
        case 4:
-               if ((tx && (mode & SPI_TX_QUAD)) ||
-                   (!tx && (mode & SPI_RX_QUAD)))
+               if ((tx && (mode & (SPI_TX_QUAD | SPI_TX_OCTAL))) ||
+                   (!tx && (mode & (SPI_RX_QUAD | SPI_RX_OCTAL))))
                        return 0;
 
                break;
+
        case 8:
                if ((tx && (mode & SPI_TX_OCTAL)) ||
                    (!tx && (mode & SPI_RX_OCTAL)))
@@ -300,7 +303,7 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct 
spi_mem_op *op)
                 * read path) and expect the core to use the regular SPI
                 * interface in other cases.
                 */
-               if (!ret || ret != -ENOTSUPP) {
+               if (!ret || (ret != -ENOTSUPP && ret != -EOPNOTSUPP)) {
                        spi_release_bus(slave);
                        return ret;
                }
diff --git a/include/spi-mem.h b/include/spi-mem.h
index 2eb05a2e5bc..e68e2b50e85 100644
--- a/include/spi-mem.h
+++ b/include/spi-mem.h
@@ -17,16 +17,32 @@ struct udevice;
 
 #define SPI_MEM_OP_CMD(__opcode, __buswidth)                   \
        {                                                       \
+               .nbytes = 1,                                    \
                .buswidth = __buswidth,                         \
                .opcode = __opcode,                             \
+       }
+
+#define SPI_MEM_DTR_OP_CMD(__opcode, __buswidth)               \
+       {                                                       \
                .nbytes = 1,                                    \
+               .opcode = __opcode,                             \
+               .buswidth = __buswidth,                         \
+               .dtr = true,                                    \
        }
 
 #define SPI_MEM_OP_ADDR(__nbytes, __val, __buswidth)           \
+       {                                                       \
+               .nbytes = __nbytes,                             \
+               .buswidth = __buswidth,                         \
+               .val = __val,                                   \
+       }
+
+#define SPI_MEM_DTR_OP_ADDR(__nbytes, __val, __buswidth)       \
        {                                                       \
                .nbytes = __nbytes,                             \
                .val = __val,                                   \
                .buswidth = __buswidth,                         \
+               .dtr = true,                                    \
        }
 
 #define SPI_MEM_OP_NO_ADDR     { }
@@ -37,22 +53,47 @@ struct udevice;
                .buswidth = __buswidth,                         \
        }
 
+#define SPI_MEM_DTR_OP_DUMMY(__nbytes, __buswidth)             \
+       {                                                       \
+               .nbytes = __nbytes,                             \
+               .buswidth = __buswidth,                         \
+               .dtr = true,                                    \
+       }
+
 #define SPI_MEM_OP_NO_DUMMY    { }
 
 #define SPI_MEM_OP_DATA_IN(__nbytes, __buf, __buswidth)                \
+       {                                                       \
+               .buswidth = __buswidth,                         \
+               .dir = SPI_MEM_DATA_IN,                         \
+               .nbytes = __nbytes,                             \
+               .buf.in = __buf,                                \
+       }
+
+#define SPI_MEM_DTR_OP_DATA_IN(__nbytes, __buf, __buswidth)    \
        {                                                       \
                .dir = SPI_MEM_DATA_IN,                         \
                .nbytes = __nbytes,                             \
                .buf.in = __buf,                                \
                .buswidth = __buswidth,                         \
+               .dtr = true,                                    \
        }
 
 #define SPI_MEM_OP_DATA_OUT(__nbytes, __buf, __buswidth)       \
+       {                                                       \
+               .buswidth = __buswidth,                         \
+               .dir = SPI_MEM_DATA_OUT,                        \
+               .nbytes = __nbytes,                             \
+               .buf.out = __buf,                               \
+       }
+
+#define SPI_MEM_DTR_OP_DATA_OUT(__nbytes, __buf, __buswidth)   \
        {                                                       \
                .dir = SPI_MEM_DATA_OUT,                        \
                .nbytes = __nbytes,                             \
                .buf.out = __buf,                               \
                .buswidth = __buswidth,                         \
+               .dtr = true,                                    \
        }
 
 #define SPI_MEM_OP_NO_DATA     { }
@@ -62,7 +103,7 @@ struct udevice;
  *                        transfer from the controller perspective
  * @SPI_MEM_NO_DATA: no data transferred
  * @SPI_MEM_DATA_IN: data coming from the SPI memory
- * @SPI_MEM_DATA_OUT: data sent the SPI memory
+ * @SPI_MEM_DATA_OUT: data sent to the SPI memory
  */
 enum spi_mem_data_dir {
        SPI_MEM_NO_DATA,
@@ -70,6 +111,9 @@ enum spi_mem_data_dir {
        SPI_MEM_DATA_OUT,
 };
 
+#define SPI_MEM_OP_MAX_FREQ(__freq)                            \
+       .max_freq = __freq
+
 /**
  * struct spi_mem_op - describes a SPI memory operation
  * @cmd.nbytes: number of opcode bytes (only 1 or 2 are valid). The opcode is
@@ -80,26 +124,35 @@ enum spi_mem_data_dir {
  * @addr.nbytes: number of address bytes to send. Can be zero if the operation
  *              does not need to send an address
  * @addr.buswidth: number of IO lines used to transmit the address cycles
+ * @addr.dtr: whether the address should be sent in DTR mode or not
  * @addr.val: address value. This value is always sent MSB first on the bus.
  *           Note that only @addr.nbytes are taken into account in this
  *           address value, so users should make sure the value fits in the
  *           assigned number of bytes.
- * @addr.dtr: whether the address should be sent in DTR mode or not
  * @dummy.nbytes: number of dummy bytes to send after an opcode or address. Can
  *               be zero if the operation does not require dummy bytes
  * @dummy.buswidth: number of IO lanes used to transmit the dummy bytes
  * @dummy.dtr: whether the dummy bytes should be sent in DTR mode or not
  * @data.buswidth: number of IO lanes used to send/receive the data
  * @data.dtr: whether the data should be sent in DTR mode or not
+ * @data.ecc: whether error correction is required or not
+ * @data.swap16: whether the byte order of 16-bit words is swapped when read
+ *              or written in Octal DTR mode compared to STR mode.
  * @data.dir: direction of the transfer
- * @data.buf.in: input buffer
- * @data.buf.out: output buffer
+ * @data.nbytes: number of data bytes to send/receive. Can be zero if the
+ *              operation does not involve transferring data
+ * @data.buf.in: input buffer (must be DMA-able)
+ * @data.buf.out: output buffer (must be DMA-able)
+ * @max_freq: frequency limitation wrt this operation. 0 means there is no
+ *           specific constraint and the highest achievable frequency can be
+ *           attempted.
  */
 struct spi_mem_op {
        struct {
                u8 nbytes;
                u8 buswidth;
                u8 dtr : 1;
+               u8 __pad : 7;
                u16 opcode;
        } cmd;
 
@@ -107,6 +160,7 @@ struct spi_mem_op {
                u8 nbytes;
                u8 buswidth;
                u8 dtr : 1;
+               u8 __pad : 7;
                u64 val;
        } addr;
 
@@ -114,28 +168,35 @@ struct spi_mem_op {
                u8 nbytes;
                u8 buswidth;
                u8 dtr : 1;
+               u8 __pad : 7;
        } dummy;
 
        struct {
                u8 buswidth;
                u8 dtr : 1;
+               u8 ecc : 1;
+               u8 swap16 : 1;
+               u8 __pad : 5;
                enum spi_mem_data_dir dir;
                unsigned int nbytes;
-               /* buf.{in,out} must be DMA-able. */
                union {
                        void *in;
                        const void *out;
                } buf;
        } data;
+
+       unsigned int max_freq;
 };
 
-#define SPI_MEM_OP(__cmd, __addr, __dummy, __data)             \
+#define SPI_MEM_OP(__cmd, __addr, __dummy, __data, ...)                \
        {                                                       \
                .cmd = __cmd,                                   \
                .addr = __addr,                                 \
                .dummy = __dummy,                               \
                .data = __data,                                 \
+               __VA_ARGS__                                     \
        }
+
 /**
  * struct spi_mem_dirmap_info - Direct mapping information
  * @op_tmpl: operation template that should be used by the direct mapping when
@@ -143,7 +204,7 @@ struct spi_mem_op {
  * @offset: absolute offset this direct mapping is pointing to
  * @length: length in byte of this direct mapping
  *
- * This information is used by the controller specific implementation to know
+ * These information are used by the controller specific implementation to know
  * the portion of memory that is directly mapped and the spi_mem_op that should
  * be used to access the device.
  * A direct mapping is only valid for one direction (read or write) and this
@@ -223,10 +284,12 @@ static inline void *spi_mem_get_drvdata(struct spi_mem 
*mem)
 /**
  * struct spi_controller_mem_ops - SPI memory operations
  * @adjust_op_size: shrink the data xfer of an operation to match controller's
- *                 limitations (can be alignment of max RX/TX size
+ *                 limitations (can be alignment or max RX/TX size
  *                 limitations)
  * @supports_op: check if an operation is supported by the controller
  * @exec_op: execute a SPI memory operation
+ *           not all driver provides supports_op(), so it can return 
-EOPNOTSUPP
+ *           if the op is not supported by the driver/controller
  * @dirmap_create: create a direct mapping descriptor that can later be used to
  *                access the memory device. This method is optional
  * @dirmap_destroy: destroy a memory descriptor previous created by
@@ -300,13 +363,16 @@ int spi_controller_dma_map_mem_op_data(struct 
spi_controller *ctlr,
 void spi_controller_dma_unmap_mem_op_data(struct spi_controller *ctlr,
                                          const struct spi_mem_op *op,
                                          struct sg_table *sg);
+
+bool spi_mem_default_supports_op(struct spi_mem *mem,
+                                const struct spi_mem_op *op);
 #else
 static inline int
 spi_controller_dma_map_mem_op_data(struct spi_controller *ctlr,
                                   const struct spi_mem_op *op,
                                   struct sg_table *sg)
 {
-       return -ENOSYS;
+       return -ENOTSUPP;
 }
 
 static inline void
@@ -315,6 +381,13 @@ spi_controller_dma_unmap_mem_op_data(struct spi_controller 
*ctlr,
                                     struct sg_table *sg)
 {
 }
+
+static inline
+bool spi_mem_default_supports_op(struct spi_mem *mem,
+                                const struct spi_mem_op *op)
+{
+       return false;
+}
 #endif /* CONFIG_SPI_MEM */
 #endif /* __UBOOT__ */
 
@@ -337,7 +410,6 @@ ssize_t spi_mem_dirmap_read(struct spi_mem_dirmap_desc 
*desc,
                            u64 offs, size_t len, void *buf);
 ssize_t spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
                             u64 offs, size_t len, const void *buf);
-
 #ifndef __UBOOT__
 int spi_mem_driver_register_with_owner(struct spi_mem_driver *drv,
                                       struct module *owner);
-- 
2.47.2

Reply via email to