global: Migrate CONFIG_STACKBASE to CFG
[platform/kernel/u-boot.git] / include / spi-mem.h
index e354c38..b07cf2e 100644 (file)
@@ -17,6 +17,7 @@ struct udevice;
        {                                                       \
                .buswidth = __buswidth,                         \
                .opcode = __opcode,                             \
+               .nbytes = 1,                                    \
        }
 
 #define SPI_MEM_OP_ADDR(__nbytes, __val, __buswidth)           \
@@ -69,8 +70,11 @@ enum spi_mem_data_dir {
 
 /**
  * struct spi_mem_op - describes a SPI memory operation
+ * @cmd.nbytes: number of opcode bytes (only 1 or 2 are valid). The opcode is
+ *             sent MSB-first.
  * @cmd.buswidth: number of IO lines used to transmit the command
  * @cmd.opcode: operation opcode
+ * @cmd.dtr: whether the command opcode should be sent in DTR mode or not
  * @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
@@ -78,33 +82,41 @@ enum spi_mem_data_dir {
  *           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.dir: direction of the transfer
  * @data.buf.in: input buffer
  * @data.buf.out: output buffer
  */
 struct spi_mem_op {
        struct {
+               u8 nbytes;
                u8 buswidth;
-               u8 opcode;
+               u8 dtr : 1;
+               u16 opcode;
        } cmd;
 
        struct {
                u8 nbytes;
                u8 buswidth;
+               u8 dtr : 1;
                u64 val;
        } addr;
 
        struct {
                u8 nbytes;
                u8 buswidth;
+               u8 dtr : 1;
        } dummy;
 
        struct {
                u8 buswidth;
+               u8 dtr : 1;
                enum spi_mem_data_dir dir;
                unsigned int nbytes;
                /* buf.{in,out} must be DMA-able. */
@@ -122,6 +134,48 @@ struct spi_mem_op {
                .dummy = __dummy,                               \
                .data = __data,                                 \
        }
+/**
+ * struct spi_mem_dirmap_info - Direct mapping information
+ * @op_tmpl: operation template that should be used by the direct mapping when
+ *          the memory device is accessed
+ * @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
+ * 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
+ * direction is directly encoded in the ->op_tmpl.data.dir field.
+ */
+struct spi_mem_dirmap_info {
+       struct spi_mem_op op_tmpl;
+       u64 offset;
+       u64 length;
+};
+
+/**
+ * struct spi_mem_dirmap_desc - Direct mapping descriptor
+ * @mem: the SPI memory device this direct mapping is attached to
+ * @info: information passed at direct mapping creation time
+ * @nodirmap: set to 1 if the SPI controller does not implement
+ *            ->mem_ops->dirmap_create() or when this function returned an
+ *            error. If @nodirmap is true, all spi_mem_dirmap_{read,write}()
+ *            calls will use spi_mem_exec_op() to access the memory. This is a
+ *            degraded mode that allows spi_mem drivers to use the same code
+ *            no matter whether the controller supports direct mapping or not
+ * @priv: field pointing to controller specific data
+ *
+ * Common part of a direct mapping descriptor. This object is created by
+ * spi_mem_dirmap_create() and controller implementation of ->create_dirmap()
+ * can create/attach direct mapping resources to the descriptor in the ->priv
+ * field.
+ */
+struct spi_mem_dirmap_desc {
+       struct spi_slave *slave;
+       struct spi_mem_dirmap_info info;
+       unsigned int nodirmap;
+       void *priv;
+};
 
 #ifndef __UBOOT__
 /**
@@ -171,10 +225,32 @@ static inline void *spi_mem_get_drvdata(struct spi_mem *mem)
  *                 limitations)
  * @supports_op: check if an operation is supported by the controller
  * @exec_op: execute a SPI memory operation
+ * @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
+ *                 ->dirmap_create()
+ * @dirmap_read: read data from the memory device using the direct mapping
+ *              created by ->dirmap_create(). The function can return less
+ *              data than requested (for example when the request is crossing
+ *              the currently mapped area), and the caller of
+ *              spi_mem_dirmap_read() is responsible for calling it again in
+ *              this case.
+ * @dirmap_write: write data to the memory device using the direct mapping
+ *               created by ->dirmap_create(). The function can return less
+ *               data than requested (for example when the request is crossing
+ *               the currently mapped area), and the caller of
+ *               spi_mem_dirmap_write() is responsible for calling it again in
+ *               this case.
  *
  * This interface should be implemented by SPI controllers providing an
  * high-level interface to execute SPI memory operation, which is usually the
  * case for QSPI controllers.
+ *
+ * Note on ->dirmap_{read,write}(): drivers should avoid accessing the direct
+ * mapping from the CPU because doing that can stall the CPU waiting for the
+ * SPI mem transaction to finish, and this will make real-time maintainers
+ * unhappy and might make your system less reactive. Instead, drivers should
+ * use DMA to access this direct mapping.
  */
 struct spi_controller_mem_ops {
        int (*adjust_op_size)(struct spi_slave *slave, struct spi_mem_op *op);
@@ -182,6 +258,12 @@ struct spi_controller_mem_ops {
                            const struct spi_mem_op *op);
        int (*exec_op)(struct spi_slave *slave,
                       const struct spi_mem_op *op);
+       int (*dirmap_create)(struct spi_mem_dirmap_desc *desc);
+       void (*dirmap_destroy)(struct spi_mem_dirmap_desc *desc);
+       ssize_t (*dirmap_read)(struct spi_mem_dirmap_desc *desc,
+                              u64 offs, size_t len, void *buf);
+       ssize_t (*dirmap_write)(struct spi_mem_dirmap_desc *desc,
+                               u64 offs, size_t len, const void *buf);
 };
 
 #ifndef __UBOOT__
@@ -237,12 +319,26 @@ spi_controller_dma_unmap_mem_op_data(struct spi_controller *ctlr,
 int spi_mem_adjust_op_size(struct spi_slave *slave, struct spi_mem_op *op);
 
 bool spi_mem_supports_op(struct spi_slave *slave, const struct spi_mem_op *op);
+bool spi_mem_dtr_supports_op(struct spi_slave *slave,
+                            const struct spi_mem_op *op);
+
+bool spi_mem_default_supports_op(struct spi_slave *slave,
+                                const struct spi_mem_op *op);
 
 int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op);
 
 bool spi_mem_default_supports_op(struct spi_slave *mem,
                                 const struct spi_mem_op *op);
 
+struct spi_mem_dirmap_desc *
+spi_mem_dirmap_create(struct spi_slave *mem,
+                     const struct spi_mem_dirmap_info *info);
+void spi_mem_dirmap_destroy(struct spi_mem_dirmap_desc *desc);
+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);