]> Git Repo - linux.git/blob - include/linux/spi/spi-mem.h
mfd: cros-ec: Increase maximum mkbp event size
[linux.git] / include / linux / spi / spi-mem.h
1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * Copyright (C) 2018 Exceet Electronics GmbH
4  * Copyright (C) 2018 Bootlin
5  *
6  * Author: Boris Brezillon <[email protected]>
7  */
8
9 #ifndef __LINUX_SPI_MEM_H
10 #define __LINUX_SPI_MEM_H
11
12 #include <linux/spi/spi.h>
13
14 #define SPI_MEM_OP_CMD(__opcode, __buswidth)                    \
15         {                                                       \
16                 .buswidth = __buswidth,                         \
17                 .opcode = __opcode,                             \
18         }
19
20 #define SPI_MEM_OP_ADDR(__nbytes, __val, __buswidth)            \
21         {                                                       \
22                 .nbytes = __nbytes,                             \
23                 .val = __val,                                   \
24                 .buswidth = __buswidth,                         \
25         }
26
27 #define SPI_MEM_OP_NO_ADDR      { }
28
29 #define SPI_MEM_OP_DUMMY(__nbytes, __buswidth)                  \
30         {                                                       \
31                 .nbytes = __nbytes,                             \
32                 .buswidth = __buswidth,                         \
33         }
34
35 #define SPI_MEM_OP_NO_DUMMY     { }
36
37 #define SPI_MEM_OP_DATA_IN(__nbytes, __buf, __buswidth)         \
38         {                                                       \
39                 .dir = SPI_MEM_DATA_IN,                         \
40                 .nbytes = __nbytes,                             \
41                 .buf.in = __buf,                                \
42                 .buswidth = __buswidth,                         \
43         }
44
45 #define SPI_MEM_OP_DATA_OUT(__nbytes, __buf, __buswidth)        \
46         {                                                       \
47                 .dir = SPI_MEM_DATA_OUT,                        \
48                 .nbytes = __nbytes,                             \
49                 .buf.out = __buf,                               \
50                 .buswidth = __buswidth,                         \
51         }
52
53 #define SPI_MEM_OP_NO_DATA      { }
54
55 /**
56  * enum spi_mem_data_dir - describes the direction of a SPI memory data
57  *                         transfer from the controller perspective
58  * @SPI_MEM_DATA_IN: data coming from the SPI memory
59  * @SPI_MEM_DATA_OUT: data sent the SPI memory
60  */
61 enum spi_mem_data_dir {
62         SPI_MEM_DATA_IN,
63         SPI_MEM_DATA_OUT,
64 };
65
66 /**
67  * struct spi_mem_op - describes a SPI memory operation
68  * @cmd.buswidth: number of IO lines used to transmit the command
69  * @cmd.opcode: operation opcode
70  * @addr.nbytes: number of address bytes to send. Can be zero if the operation
71  *               does not need to send an address
72  * @addr.buswidth: number of IO lines used to transmit the address cycles
73  * @addr.val: address value. This value is always sent MSB first on the bus.
74  *            Note that only @addr.nbytes are taken into account in this
75  *            address value, so users should make sure the value fits in the
76  *            assigned number of bytes.
77  * @dummy.nbytes: number of dummy bytes to send after an opcode or address. Can
78  *                be zero if the operation does not require dummy bytes
79  * @dummy.buswidth: number of IO lanes used to transmit the dummy bytes
80  * @data.buswidth: number of IO lanes used to send/receive the data
81  * @data.dir: direction of the transfer
82  * @data.buf.in: input buffer
83  * @data.buf.out: output buffer
84  */
85 struct spi_mem_op {
86         struct {
87                 u8 buswidth;
88                 u8 opcode;
89         } cmd;
90
91         struct {
92                 u8 nbytes;
93                 u8 buswidth;
94                 u64 val;
95         } addr;
96
97         struct {
98                 u8 nbytes;
99                 u8 buswidth;
100         } dummy;
101
102         struct {
103                 u8 buswidth;
104                 enum spi_mem_data_dir dir;
105                 unsigned int nbytes;
106                 /* buf.{in,out} must be DMA-able. */
107                 union {
108                         void *in;
109                         const void *out;
110                 } buf;
111         } data;
112 };
113
114 #define SPI_MEM_OP(__cmd, __addr, __dummy, __data)              \
115         {                                                       \
116                 .cmd = __cmd,                                   \
117                 .addr = __addr,                                 \
118                 .dummy = __dummy,                               \
119                 .data = __data,                                 \
120         }
121
122 /**
123  * struct spi_mem - describes a SPI memory device
124  * @spi: the underlying SPI device
125  * @drvpriv: spi_mem_drviver private data
126  *
127  * Extra information that describe the SPI memory device and may be needed by
128  * the controller to properly handle this device should be placed here.
129  *
130  * One example would be the device size since some controller expose their SPI
131  * mem devices through a io-mapped region.
132  */
133 struct spi_mem {
134         struct spi_device *spi;
135         void *drvpriv;
136 };
137
138 /**
139  * struct spi_mem_set_drvdata() - attach driver private data to a SPI mem
140  *                                device
141  * @mem: memory device
142  * @data: data to attach to the memory device
143  */
144 static inline void spi_mem_set_drvdata(struct spi_mem *mem, void *data)
145 {
146         mem->drvpriv = data;
147 }
148
149 /**
150  * struct spi_mem_get_drvdata() - get driver private data attached to a SPI mem
151  *                                device
152  * @mem: memory device
153  *
154  * Return: the data attached to the mem device.
155  */
156 static inline void *spi_mem_get_drvdata(struct spi_mem *mem)
157 {
158         return mem->drvpriv;
159 }
160
161 /**
162  * struct spi_controller_mem_ops - SPI memory operations
163  * @adjust_op_size: shrink the data xfer of an operation to match controller's
164  *                  limitations (can be alignment of max RX/TX size
165  *                  limitations)
166  * @supports_op: check if an operation is supported by the controller
167  * @exec_op: execute a SPI memory operation
168  *
169  * This interface should be implemented by SPI controllers providing an
170  * high-level interface to execute SPI memory operation, which is usually the
171  * case for QSPI controllers.
172  */
173 struct spi_controller_mem_ops {
174         int (*adjust_op_size)(struct spi_mem *mem, struct spi_mem_op *op);
175         bool (*supports_op)(struct spi_mem *mem,
176                             const struct spi_mem_op *op);
177         int (*exec_op)(struct spi_mem *mem,
178                        const struct spi_mem_op *op);
179 };
180
181 /**
182  * struct spi_mem_driver - SPI memory driver
183  * @spidrv: inherit from a SPI driver
184  * @probe: probe a SPI memory. Usually where detection/initialization takes
185  *         place
186  * @remove: remove a SPI memory
187  * @shutdown: take appropriate action when the system is shutdown
188  *
189  * This is just a thin wrapper around a spi_driver. The core takes care of
190  * allocating the spi_mem object and forwarding the probe/remove/shutdown
191  * request to the spi_mem_driver. The reason we use this wrapper is because
192  * we might have to stuff more information into the spi_mem struct to let
193  * SPI controllers know more about the SPI memory they interact with, and
194  * having this intermediate layer allows us to do that without adding more
195  * useless fields to the spi_device object.
196  */
197 struct spi_mem_driver {
198         struct spi_driver spidrv;
199         int (*probe)(struct spi_mem *mem);
200         int (*remove)(struct spi_mem *mem);
201         void (*shutdown)(struct spi_mem *mem);
202 };
203
204 #if IS_ENABLED(CONFIG_SPI_MEM)
205 int spi_controller_dma_map_mem_op_data(struct spi_controller *ctlr,
206                                        const struct spi_mem_op *op,
207                                        struct sg_table *sg);
208
209 void spi_controller_dma_unmap_mem_op_data(struct spi_controller *ctlr,
210                                           const struct spi_mem_op *op,
211                                           struct sg_table *sg);
212 #else
213 static inline int
214 spi_controller_dma_map_mem_op_data(struct spi_controller *ctlr,
215                                    const struct spi_mem_op *op,
216                                    struct sg_table *sg)
217 {
218         return -ENOTSUPP;
219 }
220
221 static inline void
222 spi_controller_dma_unmap_mem_op_data(struct spi_controller *ctlr,
223                                      const struct spi_mem_op *op,
224                                      struct sg_table *sg)
225 {
226 }
227 #endif /* CONFIG_SPI_MEM */
228
229 int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op);
230
231 bool spi_mem_supports_op(struct spi_mem *mem,
232                          const struct spi_mem_op *op);
233
234 int spi_mem_exec_op(struct spi_mem *mem,
235                     const struct spi_mem_op *op);
236
237 int spi_mem_driver_register_with_owner(struct spi_mem_driver *drv,
238                                        struct module *owner);
239
240 void spi_mem_driver_unregister(struct spi_mem_driver *drv);
241
242 #define spi_mem_driver_register(__drv)                                  \
243         spi_mem_driver_register_with_owner(__drv, THIS_MODULE)
244
245 #define module_spi_mem_driver(__drv)                                    \
246         module_driver(__drv, spi_mem_driver_register,                   \
247                       spi_mem_driver_unregister)
248
249 #endif /* __LINUX_SPI_MEM_H */
This page took 0.048163 seconds and 4 git commands to generate.