1 /*
2 * Copyright (c) 2015 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Public API for SPI drivers and applications
10 */
11
12 #ifndef ZEPHYR_INCLUDE_DRIVERS_SPI_H_
13 #define ZEPHYR_INCLUDE_DRIVERS_SPI_H_
14
15 /**
16 * @brief SPI Interface
17 * @defgroup spi_interface SPI Interface
18 * @since 1.0
19 * @version 1.0.0
20 * @ingroup io_interfaces
21 * @{
22 */
23
24 #include <zephyr/types.h>
25 #include <stddef.h>
26 #include <zephyr/device.h>
27 #include <zephyr/dt-bindings/spi/spi.h>
28 #include <zephyr/drivers/gpio.h>
29 #include <zephyr/kernel.h>
30 #include <zephyr/sys/__assert.h>
31 #include <zephyr/rtio/rtio.h>
32 #include <zephyr/stats/stats.h>
33
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37
38 /**
39 * @name SPI operational mode
40 * @{
41 */
42 #define SPI_OP_MODE_MASTER 0U /**< Master mode. */
43 #define SPI_OP_MODE_SLAVE BIT(0) /**< Slave mode. */
44 /** @cond INTERNAL_HIDDEN */
45 #define SPI_OP_MODE_MASK 0x1U
46 /** @endcond */
47 /** Get SPI operational mode. */
48 #define SPI_OP_MODE_GET(_operation_) ((_operation_) & SPI_OP_MODE_MASK)
49 /** @} */
50
51 /**
52 * @name SPI Polarity & Phase Modes
53 * @{
54 */
55
56 /**
57 * Clock Polarity: if set, clock idle state will be 1
58 * and active state will be 0. If untouched, the inverse will be true
59 * which is the default.
60 */
61 #define SPI_MODE_CPOL BIT(1)
62
63 /**
64 * Clock Phase: this dictates when is the data captured, and depends
65 * clock's polarity. When SPI_MODE_CPOL is set and this bit as well,
66 * capture will occur on low to high transition and high to low if
67 * this bit is not set (default). This is fully reversed if CPOL is
68 * not set.
69 */
70 #define SPI_MODE_CPHA BIT(2)
71
72 /**
73 * Whatever data is transmitted is looped-back to the receiving buffer of
74 * the controller. This is fully controller dependent as some may not
75 * support this, and can be used for testing purposes only.
76 */
77 #define SPI_MODE_LOOP BIT(3)
78 /** @cond INTERNAL_HIDDEN */
79 #define SPI_MODE_MASK (0xEU)
80 /** @endcond */
81 /** Get SPI polarity and phase mode bits. */
82 #define SPI_MODE_GET(_mode_) \
83 ((_mode_) & SPI_MODE_MASK)
84
85 /** @} */
86
87 /**
88 * @name SPI Transfer modes (host controller dependent)
89 * @{
90 */
91 #define SPI_TRANSFER_MSB (0U) /**< Most significant bit first. */
92 #define SPI_TRANSFER_LSB BIT(4) /**< Least significant bit first. */
93 /** @} */
94
95 /**
96 * @name SPI word size
97 * @{
98 */
99 /** @cond INTERNAL_HIDDEN */
100 #define SPI_WORD_SIZE_SHIFT (5U)
101 #define SPI_WORD_SIZE_MASK (0x3FU << SPI_WORD_SIZE_SHIFT)
102 /** @endcond */
103 /** Get SPI word size. */
104 #define SPI_WORD_SIZE_GET(_operation_) \
105 (((_operation_) & SPI_WORD_SIZE_MASK) >> SPI_WORD_SIZE_SHIFT)
106 /** Set SPI word size. */
107 #define SPI_WORD_SET(_word_size_) \
108 ((_word_size_) << SPI_WORD_SIZE_SHIFT)
109 /** @} */
110
111 /**
112 * @name Specific SPI devices control bits
113 * @{
114 */
115 /** Requests - if possible - to keep CS asserted after the transaction */
116 #define SPI_HOLD_ON_CS BIT(12)
117 /** Keep the device locked after the transaction for the current config.
118 * Use this with extreme caution (see spi_release() below) as it will
119 * prevent other callers to access the SPI device until spi_release() is
120 * properly called.
121 */
122 #define SPI_LOCK_ON BIT(13)
123
124 /** Active high logic on CS. Usually, and by default, CS logic is active
125 * low. However, some devices may require the reverse logic: active high.
126 * This bit will request the controller to use that logic. Note that not
127 * all controllers are able to handle that natively. In this case deferring
128 * the CS control to a gpio line through struct spi_cs_control would be
129 * the solution.
130 */
131 #define SPI_CS_ACTIVE_HIGH BIT(14)
132 /** @} */
133
134 /**
135 * @name SPI MISO lines
136 * @{
137 *
138 * Some controllers support dual, quad or octal MISO lines connected to slaves.
139 * Default is single, which is the case most of the time.
140 * Without @kconfig{CONFIG_SPI_EXTENDED_MODES} being enabled, single is the
141 * only supported one.
142 */
143 #define SPI_LINES_SINGLE (0U << 16) /**< Single line */
144 #define SPI_LINES_DUAL (1U << 16) /**< Dual lines */
145 #define SPI_LINES_QUAD (2U << 16) /**< Quad lines */
146 #define SPI_LINES_OCTAL (3U << 16) /**< Octal lines */
147
148 #define SPI_LINES_MASK (0x3U << 16) /**< Mask for MISO lines in spi_operation_t */
149
150 /** @} */
151
152 /**
153 * @brief SPI Chip Select control structure
154 *
155 * This can be used to control a CS line via a GPIO line, instead of
156 * using the controller inner CS logic.
157 *
158 */
159 struct spi_cs_control {
160 /**
161 * GPIO devicetree specification of CS GPIO.
162 * The device pointer can be set to NULL to fully inhibit CS control if
163 * necessary. The GPIO flags GPIO_ACTIVE_LOW/GPIO_ACTIVE_HIGH should be
164 * equivalent to SPI_CS_ACTIVE_HIGH/SPI_CS_ACTIVE_LOW options in struct
165 * spi_config.
166 */
167 struct gpio_dt_spec gpio;
168 /**
169 * Delay in microseconds to wait before starting the
170 * transmission and before releasing the CS line.
171 */
172 uint32_t delay;
173 };
174
175 /**
176 * @brief Get a <tt>struct gpio_dt_spec</tt> for a SPI device's chip select pin
177 *
178 * Example devicetree fragment:
179 *
180 * @code{.devicetree}
181 * gpio1: gpio@abcd0001 { ... };
182 *
183 * gpio2: gpio@abcd0002 { ... };
184 *
185 * spi@abcd0003 {
186 * compatible = "vnd,spi";
187 * cs-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>,
188 * <&gpio2 20 GPIO_ACTIVE_LOW>;
189 *
190 * a: spi-dev-a@0 {
191 * reg = <0>;
192 * };
193 *
194 * b: spi-dev-b@1 {
195 * reg = <1>;
196 * };
197 * };
198 * @endcode
199 *
200 * Example usage:
201 *
202 * @code{.c}
203 * SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(a)) \
204 * // { DEVICE_DT_GET(DT_NODELABEL(gpio1)), 10, GPIO_ACTIVE_LOW }
205 * SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(b)) \
206 * // { DEVICE_DT_GET(DT_NODELABEL(gpio2)), 20, GPIO_ACTIVE_LOW }
207 * @endcode
208 *
209 * @param spi_dev a SPI device node identifier
210 * @return #gpio_dt_spec struct corresponding with spi_dev's chip select
211 */
212 #define SPI_CS_GPIOS_DT_SPEC_GET(spi_dev) \
213 GPIO_DT_SPEC_GET_BY_IDX_OR(DT_BUS(spi_dev), cs_gpios, \
214 DT_REG_ADDR(spi_dev), {})
215
216 /**
217 * @brief Get a <tt>struct gpio_dt_spec</tt> for a SPI device's chip select pin
218 *
219 * This is equivalent to
220 * <tt>SPI_CS_GPIOS_DT_SPEC_GET(DT_DRV_INST(inst))</tt>.
221 *
222 * @param inst Devicetree instance number
223 * @return #gpio_dt_spec struct corresponding with spi_dev's chip select
224 */
225 #define SPI_CS_GPIOS_DT_SPEC_INST_GET(inst) \
226 SPI_CS_GPIOS_DT_SPEC_GET(DT_DRV_INST(inst))
227
228 /**
229 * @brief Initialize and get a pointer to a @p spi_cs_control from a
230 * devicetree node identifier
231 *
232 * This helper is useful for initializing a device on a SPI bus. It
233 * initializes a struct spi_cs_control and returns a pointer to it.
234 * Here, @p node_id is a node identifier for a SPI device, not a SPI
235 * controller.
236 *
237 * Example devicetree fragment:
238 *
239 * @code{.devicetree}
240 * spi@abcd0001 {
241 * cs-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
242 * spidev: spi-device@0 { ... };
243 * };
244 * @endcode
245 *
246 * Example usage:
247 *
248 * @code{.c}
249 * struct spi_cs_control ctrl =
250 * SPI_CS_CONTROL_INIT(DT_NODELABEL(spidev), 2);
251 * @endcode
252 *
253 * This example is equivalent to:
254 *
255 * @code{.c}
256 * struct spi_cs_control ctrl = {
257 * .gpio = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(spidev)),
258 * .delay = 2,
259 * };
260 * @endcode
261 *
262 * @param node_id Devicetree node identifier for a device on a SPI bus
263 * @param delay_ The @p delay field to set in the @p spi_cs_control
264 * @return a pointer to the @p spi_cs_control structure
265 */
266 #define SPI_CS_CONTROL_INIT(node_id, delay_) \
267 { \
268 .gpio = SPI_CS_GPIOS_DT_SPEC_GET(node_id), \
269 .delay = (delay_), \
270 }
271
272 /**
273 * @brief Get a pointer to a @p spi_cs_control from a devicetree node
274 *
275 * This is equivalent to
276 * <tt>SPI_CS_CONTROL_INIT(DT_DRV_INST(inst), delay)</tt>.
277 *
278 * Therefore, @p DT_DRV_COMPAT must already be defined before using
279 * this macro.
280 *
281 * @param inst Devicetree node instance number
282 * @param delay_ The @p delay field to set in the @p spi_cs_control
283 * @return a pointer to the @p spi_cs_control structure
284 */
285 #define SPI_CS_CONTROL_INIT_INST(inst, delay_) \
286 SPI_CS_CONTROL_INIT(DT_DRV_INST(inst), delay_)
287
288 /**
289 * @typedef spi_operation_t
290 * Opaque type to hold the SPI operation flags.
291 */
292 #if defined(CONFIG_SPI_EXTENDED_MODES)
293 typedef uint32_t spi_operation_t;
294 #else
295 typedef uint16_t spi_operation_t;
296 #endif
297
298 /**
299 * @brief SPI controller configuration structure
300 */
301 struct spi_config {
302 /** @brief Bus frequency in Hertz. */
303 uint32_t frequency;
304 /**
305 * @brief Operation flags.
306 *
307 * It is a bit field with the following parts:
308 *
309 * - 0: Master or slave.
310 * - 1..3: Polarity, phase and loop mode.
311 * - 4: LSB or MSB first.
312 * - 5..10: Size of a data frame in bits.
313 * - 11: Full/half duplex.
314 * - 12: Hold on the CS line if possible.
315 * - 13: Keep resource locked for the caller.
316 * - 14: Active high CS logic.
317 * - 15: Motorola or TI frame format (optional).
318 *
319 * If @kconfig{CONFIG_SPI_EXTENDED_MODES} is enabled:
320 *
321 * - 16..17: MISO lines (Single/Dual/Quad/Octal).
322 * - 18..31: Reserved for future use.
323 */
324 spi_operation_t operation;
325 /** @brief Slave number from 0 to host controller slave limit. */
326 uint16_t slave;
327 /**
328 * @brief GPIO chip-select line (optional, must be initialized to zero
329 * if not used).
330 */
331 struct spi_cs_control cs;
332 };
333
334 /**
335 * @brief Structure initializer for spi_config from devicetree
336 *
337 * This helper macro expands to a static initializer for a <tt>struct
338 * spi_config</tt> by reading the relevant @p frequency, @p slave, and
339 * @p cs data from the devicetree.
340 *
341 * @param node_id Devicetree node identifier for the SPI device whose
342 * struct spi_config to create an initializer for
343 * @param operation_ the desired @p operation field in the struct spi_config
344 * @param delay_ the desired @p delay field in the struct spi_config's
345 * spi_cs_control, if there is one
346 */
347 #define SPI_CONFIG_DT(node_id, operation_, delay_) \
348 { \
349 .frequency = DT_PROP(node_id, spi_max_frequency), \
350 .operation = (operation_) | \
351 DT_PROP(node_id, duplex) | \
352 DT_PROP(node_id, frame_format) | \
353 COND_CODE_1(DT_PROP(node_id, spi_cpol), SPI_MODE_CPOL, (0)) | \
354 COND_CODE_1(DT_PROP(node_id, spi_cpha), SPI_MODE_CPHA, (0)) | \
355 COND_CODE_1(DT_PROP(node_id, spi_hold_cs), SPI_HOLD_ON_CS, (0)), \
356 .slave = DT_REG_ADDR(node_id), \
357 .cs = SPI_CS_CONTROL_INIT(node_id, delay_), \
358 }
359
360 /**
361 * @brief Structure initializer for spi_config from devicetree instance
362 *
363 * This is equivalent to
364 * <tt>SPI_CONFIG_DT(DT_DRV_INST(inst), operation_, delay_)</tt>.
365 *
366 * @param inst Devicetree instance number
367 * @param operation_ the desired @p operation field in the struct spi_config
368 * @param delay_ the desired @p delay field in the struct spi_config's
369 * spi_cs_control, if there is one
370 */
371 #define SPI_CONFIG_DT_INST(inst, operation_, delay_) \
372 SPI_CONFIG_DT(DT_DRV_INST(inst), operation_, delay_)
373
374 /**
375 * @brief Complete SPI DT information
376 */
377 struct spi_dt_spec {
378 /** SPI bus */
379 const struct device *bus;
380 /** Slave specific configuration */
381 struct spi_config config;
382 };
383
384 /**
385 * @brief Structure initializer for spi_dt_spec from devicetree
386 *
387 * This helper macro expands to a static initializer for a <tt>struct
388 * spi_dt_spec</tt> by reading the relevant bus, frequency, slave, and cs
389 * data from the devicetree.
390 *
391 * Important: multiple fields are automatically constructed by this macro
392 * which must be checked before use. @ref spi_is_ready_dt performs the required
393 * @ref device_is_ready checks.
394 *
395 * @param node_id Devicetree node identifier for the SPI device whose
396 * struct spi_dt_spec to create an initializer for
397 * @param operation_ the desired @p operation field in the struct spi_config
398 * @param delay_ the desired @p delay field in the struct spi_config's
399 * spi_cs_control, if there is one
400 */
401 #define SPI_DT_SPEC_GET(node_id, operation_, delay_) \
402 { \
403 .bus = DEVICE_DT_GET(DT_BUS(node_id)), \
404 .config = SPI_CONFIG_DT(node_id, operation_, delay_) \
405 }
406
407 /**
408 * @brief Structure initializer for spi_dt_spec from devicetree instance
409 *
410 * This is equivalent to
411 * <tt>SPI_DT_SPEC_GET(DT_DRV_INST(inst), operation_, delay_)</tt>.
412 *
413 * @param inst Devicetree instance number
414 * @param operation_ the desired @p operation field in the struct spi_config
415 * @param delay_ the desired @p delay field in the struct spi_config's
416 * spi_cs_control, if there is one
417 */
418 #define SPI_DT_SPEC_INST_GET(inst, operation_, delay_) \
419 SPI_DT_SPEC_GET(DT_DRV_INST(inst), operation_, delay_)
420
421 /**
422 * @brief SPI buffer structure
423 */
424 struct spi_buf {
425 /** Valid pointer to a data buffer, or NULL otherwise */
426 void *buf;
427 /** Length of the buffer @a buf.
428 * If @a buf is NULL, length which as to be sent as dummy bytes (as TX
429 * buffer) or the length of bytes that should be skipped (as RX buffer).
430 */
431 size_t len;
432 };
433
434 /**
435 * @brief SPI buffer array structure
436 */
437 struct spi_buf_set {
438 /** Pointer to an array of spi_buf, or NULL */
439 const struct spi_buf *buffers;
440 /** Length of the array pointed by @a buffers */
441 size_t count;
442 };
443
444 #if defined(CONFIG_SPI_STATS)
445 STATS_SECT_START(spi)
446 STATS_SECT_ENTRY32(rx_bytes)
447 STATS_SECT_ENTRY32(tx_bytes)
448 STATS_SECT_ENTRY32(transfer_error)
449 STATS_SECT_END;
450
451 STATS_NAME_START(spi)
452 STATS_NAME(spi, rx_bytes)
453 STATS_NAME(spi, tx_bytes)
454 STATS_NAME(spi, transfer_error)
455 STATS_NAME_END(spi);
456
457 /**
458 * @brief SPI specific device state which allows for SPI device class specific additions
459 */
460 struct spi_device_state {
461 struct device_state devstate;
462 struct stats_spi stats;
463 };
464
465 /**
466 * @brief Get pointer to SPI statistics structure
467 */
468 #define Z_SPI_GET_STATS(dev_) \
469 CONTAINER_OF(dev_->state, struct spi_device_state, devstate)->stats
470
471 /**
472 * @brief Increment the rx bytes for a SPI device
473 *
474 * @param dev_ Pointer to the device structure for the driver instance.
475 */
476 #define SPI_STATS_RX_BYTES_INCN(dev_, n) \
477 STATS_INCN(Z_SPI_GET_STATS(dev_), rx_bytes, n)
478
479 /**
480 * @brief Increment the tx bytes for a SPI device
481 *
482 * @param dev_ Pointer to the device structure for the driver instance.
483 */
484 #define SPI_STATS_TX_BYTES_INCN(dev_, n) \
485 STATS_INCN(Z_SPI_GET_STATS(dev_), tx_bytes, n)
486
487 /**
488 * @brief Increment the transfer error counter for a SPI device
489 *
490 * The transfer error count is incremented when there occurred a transfer error
491 *
492 * @param dev_ Pointer to the device structure for the driver instance.
493 */
494 #define SPI_STATS_TRANSFER_ERROR_INC(dev_) \
495 STATS_INC(Z_SPI_GET_STATS(dev_), transfer_error)
496
497 /**
498 * @brief Define a statically allocated and section assigned SPI device state
499 */
500 #define Z_SPI_DEVICE_STATE_DEFINE(dev_id) \
501 static struct spi_device_state Z_DEVICE_STATE_NAME(dev_id) \
502 __attribute__((__section__(".z_devstate")));
503
504 /**
505 * @brief Define an SPI device init wrapper function
506 *
507 * This does device instance specific initialization of common data (such as stats)
508 * and calls the given init_fn
509 */
510 #define Z_SPI_INIT_FN(dev_id, init_fn) \
511 static inline int UTIL_CAT(dev_id, _init)(const struct device *dev) \
512 { \
513 struct spi_device_state *state = \
514 CONTAINER_OF(dev->state, struct spi_device_state, devstate); \
515 stats_init(&state->stats.s_hdr, STATS_SIZE_32, 3, \
516 STATS_NAME_INIT_PARMS(spi)); \
517 stats_register(dev->name, &(state->stats.s_hdr)); \
518 return init_fn(dev); \
519 }
520
521 /**
522 * @brief Like DEVICE_DT_DEFINE() with SPI specifics.
523 *
524 * @details Defines a device which implements the SPI API. May
525 * generate a custom device_state container struct and init_fn
526 * wrapper when needed depending on SPI @kconfig{CONFIG_SPI_STATS}.
527 *
528 * @param node_id The devicetree node identifier.
529 * @param init_fn Name of the init function of the driver.
530 * @param pm_device PM device resources reference (NULL if device does not use PM).
531 * @param data_ptr Pointer to the device's private data.
532 * @param cfg_ptr The address to the structure containing the configuration
533 * information for this instance of the driver.
534 * @param level The initialization level. See SYS_INIT() for details.
535 * @param prio Priority within the selected initialization level. See SYS_INIT()
536 * for details.
537 * @param api_ptr Provides an initial pointer to the API function struct used by
538 * the driver. Can be NULL.
539 */
540 #define SPI_DEVICE_DT_DEFINE(node_id, init_fn, pm_device, \
541 data_ptr, cfg_ptr, level, prio, \
542 api_ptr, ...) \
543 Z_SPI_DEVICE_STATE_DEFINE(Z_DEVICE_DT_DEV_ID(node_id)); \
544 Z_SPI_INIT_FN(Z_DEVICE_DT_DEV_ID(node_id), init_fn) \
545 Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), \
546 DEVICE_DT_NAME(node_id), \
547 &UTIL_CAT(Z_DEVICE_DT_DEV_ID(node_id), _init), \
548 pm_device, \
549 data_ptr, cfg_ptr, level, prio, \
550 api_ptr, \
551 &(Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_ID(node_id)).devstate), \
552 __VA_ARGS__)
553
spi_transceive_stats(const struct device * dev,int error,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs)554 static inline void spi_transceive_stats(const struct device *dev, int error,
555 const struct spi_buf_set *tx_bufs,
556 const struct spi_buf_set *rx_bufs)
557 {
558 uint32_t tx_bytes;
559 uint32_t rx_bytes;
560
561 if (error) {
562 SPI_STATS_TRANSFER_ERROR_INC(dev);
563 }
564
565 if (tx_bufs) {
566 tx_bytes = tx_bufs->count ? tx_bufs->buffers->len : 0;
567 SPI_STATS_TX_BYTES_INCN(dev, tx_bytes);
568 }
569
570 if (rx_bufs) {
571 rx_bytes = rx_bufs->count ? rx_bufs->buffers->len : 0;
572 SPI_STATS_RX_BYTES_INCN(dev, rx_bytes);
573 }
574 }
575
576 #else /*CONFIG_SPI_STATS*/
577
578 #define SPI_DEVICE_DT_DEFINE(node_id, init_fn, pm, \
579 data, config, level, prio, \
580 api, ...) \
581 Z_DEVICE_STATE_DEFINE(Z_DEVICE_DT_DEV_ID(node_id)); \
582 Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), \
583 DEVICE_DT_NAME(node_id), init_fn, pm, data, config, \
584 level, prio, api, \
585 &Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_ID(node_id)), \
586 __VA_ARGS__)
587
588 #define SPI_STATS_RX_BYTES_INC(dev_)
589 #define SPI_STATS_TX_BYTES_INC(dev_)
590 #define SPI_STATS_TRANSFER_ERROR_INC(dev_)
591
592 #define spi_transceive_stats(dev, error, tx_bufs, rx_bufs)
593
594 #endif /*CONFIG_SPI_STATS*/
595
596 /**
597 * @typedef spi_api_io
598 * @brief Callback API for I/O
599 * See spi_transceive() for argument descriptions
600 */
601 typedef int (*spi_api_io)(const struct device *dev,
602 const struct spi_config *config,
603 const struct spi_buf_set *tx_bufs,
604 const struct spi_buf_set *rx_bufs);
605
606 /**
607 * @brief SPI callback for asynchronous transfer requests
608 *
609 * @param dev SPI device which is notifying of transfer completion or error
610 * @param result Result code of the transfer request. 0 is success, -errno for failure.
611 * @param data Transfer requester supplied data which is passed along to the callback.
612 */
613 typedef void (*spi_callback_t)(const struct device *dev, int result, void *data);
614
615 /**
616 * @typedef spi_api_io
617 * @brief Callback API for asynchronous I/O
618 * See spi_transceive_signal() for argument descriptions
619 */
620 typedef int (*spi_api_io_async)(const struct device *dev,
621 const struct spi_config *config,
622 const struct spi_buf_set *tx_bufs,
623 const struct spi_buf_set *rx_bufs,
624 spi_callback_t cb,
625 void *userdata);
626
627 #if defined(CONFIG_SPI_RTIO) || defined(DOXYGEN)
628
629 /**
630 * @typedef spi_api_iodev_submit
631 * @brief Callback API for submitting work to a SPI device with RTIO
632 */
633 typedef void (*spi_api_iodev_submit)(const struct device *dev,
634 struct rtio_iodev_sqe *iodev_sqe);
635 #endif /* CONFIG_SPI_RTIO */
636
637 /**
638 * @typedef spi_api_release
639 * @brief Callback API for unlocking SPI device.
640 * See spi_release() for argument descriptions
641 */
642 typedef int (*spi_api_release)(const struct device *dev,
643 const struct spi_config *config);
644
645
646 /**
647 * @brief SPI driver API
648 * This is the mandatory API any SPI driver needs to expose.
649 */
650 __subsystem struct spi_driver_api {
651 spi_api_io transceive;
652 #ifdef CONFIG_SPI_ASYNC
653 spi_api_io_async transceive_async;
654 #endif /* CONFIG_SPI_ASYNC */
655 #ifdef CONFIG_SPI_RTIO
656 spi_api_iodev_submit iodev_submit;
657 #endif /* CONFIG_SPI_RTIO */
658 spi_api_release release;
659 };
660
661 /**
662 * @brief Check if SPI CS is controlled using a GPIO.
663 *
664 * @param config SPI configuration.
665 * @return true If CS is controlled using a GPIO.
666 * @return false If CS is controlled by hardware or any other means.
667 */
spi_cs_is_gpio(const struct spi_config * config)668 static inline bool spi_cs_is_gpio(const struct spi_config *config)
669 {
670 return config->cs.gpio.port != NULL;
671 }
672
673 /**
674 * @brief Check if SPI CS in @ref spi_dt_spec is controlled using a GPIO.
675 *
676 * @param spec SPI specification from devicetree.
677 * @return true If CS is controlled using a GPIO.
678 * @return false If CS is controlled by hardware or any other means.
679 */
spi_cs_is_gpio_dt(const struct spi_dt_spec * spec)680 static inline bool spi_cs_is_gpio_dt(const struct spi_dt_spec *spec)
681 {
682 return spi_cs_is_gpio(&spec->config);
683 }
684
685 /**
686 * @brief Validate that SPI bus (and CS gpio if defined) is ready.
687 *
688 * @param spec SPI specification from devicetree
689 *
690 * @retval true if the SPI bus is ready for use.
691 * @retval false if the SPI bus (or the CS gpio defined) is not ready for use.
692 */
spi_is_ready_dt(const struct spi_dt_spec * spec)693 static inline bool spi_is_ready_dt(const struct spi_dt_spec *spec)
694 {
695 /* Validate bus is ready */
696 if (!device_is_ready(spec->bus)) {
697 return false;
698 }
699 /* Validate CS gpio port is ready, if it is used */
700 if (spi_cs_is_gpio_dt(spec) &&
701 !gpio_is_ready_dt(&spec->config.cs.gpio)) {
702 return false;
703 }
704 return true;
705 }
706
707 /**
708 * @brief Read/write the specified amount of data from the SPI driver.
709 *
710 * @note This function is synchronous.
711 *
712 * @param dev Pointer to the device structure for the driver instance
713 * @param config Pointer to a valid spi_config structure instance.
714 * Pointer-comparison may be used to detect changes from
715 * previous operations.
716 * @param tx_bufs Buffer array where data to be sent originates from,
717 * or NULL if none.
718 * @param rx_bufs Buffer array where data to be read will be written to,
719 * or NULL if none.
720 *
721 * @retval frames Positive number of frames received in slave mode.
722 * @retval 0 If successful in master mode.
723 * @retval -errno Negative errno code on failure.
724 */
725 __syscall int spi_transceive(const struct device *dev,
726 const struct spi_config *config,
727 const struct spi_buf_set *tx_bufs,
728 const struct spi_buf_set *rx_bufs);
729
z_impl_spi_transceive(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs)730 static inline int z_impl_spi_transceive(const struct device *dev,
731 const struct spi_config *config,
732 const struct spi_buf_set *tx_bufs,
733 const struct spi_buf_set *rx_bufs)
734 {
735 const struct spi_driver_api *api =
736 (const struct spi_driver_api *)dev->api;
737 int ret;
738
739 ret = api->transceive(dev, config, tx_bufs, rx_bufs);
740 spi_transceive_stats(dev, ret, tx_bufs, rx_bufs);
741
742 return ret;
743 }
744
745 /**
746 * @brief Read/write data from an SPI bus specified in @p spi_dt_spec.
747 *
748 * This is equivalent to:
749 *
750 * spi_transceive(spec->bus, &spec->config, tx_bufs, rx_bufs);
751 *
752 * @param spec SPI specification from devicetree
753 * @param tx_bufs Buffer array where data to be sent originates from,
754 * or NULL if none.
755 * @param rx_bufs Buffer array where data to be read will be written to,
756 * or NULL if none.
757 *
758 * @return a value from spi_transceive().
759 */
spi_transceive_dt(const struct spi_dt_spec * spec,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs)760 static inline int spi_transceive_dt(const struct spi_dt_spec *spec,
761 const struct spi_buf_set *tx_bufs,
762 const struct spi_buf_set *rx_bufs)
763 {
764 return spi_transceive(spec->bus, &spec->config, tx_bufs, rx_bufs);
765 }
766
767 /**
768 * @brief Read the specified amount of data from the SPI driver.
769 *
770 * @note This function is synchronous.
771 *
772 * @note This function is a helper function calling spi_transceive.
773 *
774 * @param dev Pointer to the device structure for the driver instance
775 * @param config Pointer to a valid spi_config structure instance.
776 * Pointer-comparison may be used to detect changes from
777 * previous operations.
778 * @param rx_bufs Buffer array where data to be read will be written to.
779 *
780 * @retval frames Positive number of frames received in slave mode.
781 * @retval 0 If successful.
782 * @retval -errno Negative errno code on failure.
783 */
spi_read(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * rx_bufs)784 static inline int spi_read(const struct device *dev,
785 const struct spi_config *config,
786 const struct spi_buf_set *rx_bufs)
787 {
788 return spi_transceive(dev, config, NULL, rx_bufs);
789 }
790
791 /**
792 * @brief Read data from a SPI bus specified in @p spi_dt_spec.
793 *
794 * This is equivalent to:
795 *
796 * spi_read(spec->bus, &spec->config, rx_bufs);
797 *
798 * @param spec SPI specification from devicetree
799 * @param rx_bufs Buffer array where data to be read will be written to.
800 *
801 * @return a value from spi_read().
802 */
spi_read_dt(const struct spi_dt_spec * spec,const struct spi_buf_set * rx_bufs)803 static inline int spi_read_dt(const struct spi_dt_spec *spec,
804 const struct spi_buf_set *rx_bufs)
805 {
806 return spi_read(spec->bus, &spec->config, rx_bufs);
807 }
808
809 /**
810 * @brief Write the specified amount of data from the SPI driver.
811 *
812 * @note This function is synchronous.
813 *
814 * @note This function is a helper function calling spi_transceive.
815 *
816 * @param dev Pointer to the device structure for the driver instance
817 * @param config Pointer to a valid spi_config structure instance.
818 * Pointer-comparison may be used to detect changes from
819 * previous operations.
820 * @param tx_bufs Buffer array where data to be sent originates from.
821 *
822 * @retval 0 If successful.
823 * @retval -errno Negative errno code on failure.
824 */
spi_write(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * tx_bufs)825 static inline int spi_write(const struct device *dev,
826 const struct spi_config *config,
827 const struct spi_buf_set *tx_bufs)
828 {
829 return spi_transceive(dev, config, tx_bufs, NULL);
830 }
831
832 /**
833 * @brief Write data to a SPI bus specified in @p spi_dt_spec.
834 *
835 * This is equivalent to:
836 *
837 * spi_write(spec->bus, &spec->config, tx_bufs);
838 *
839 * @param spec SPI specification from devicetree
840 * @param tx_bufs Buffer array where data to be sent originates from.
841 *
842 * @return a value from spi_write().
843 */
spi_write_dt(const struct spi_dt_spec * spec,const struct spi_buf_set * tx_bufs)844 static inline int spi_write_dt(const struct spi_dt_spec *spec,
845 const struct spi_buf_set *tx_bufs)
846 {
847 return spi_write(spec->bus, &spec->config, tx_bufs);
848 }
849
850 #if defined(CONFIG_SPI_ASYNC) || defined(__DOXYGEN__)
851
852 /**
853 * @brief Read/write the specified amount of data from the SPI driver.
854 *
855 * @note This function is asynchronous.
856 *
857 * @note This function is available only if @kconfig{CONFIG_SPI_ASYNC}
858 * is selected.
859 *
860 * @param dev Pointer to the device structure for the driver instance
861 * @param config Pointer to a valid spi_config structure instance.
862 * Pointer-comparison may be used to detect changes from
863 * previous operations.
864 * @param tx_bufs Buffer array where data to be sent originates from,
865 * or NULL if none.
866 * @param rx_bufs Buffer array where data to be read will be written to,
867 * or NULL if none.
868 * @param callback Function pointer to completion callback.
869 * (Note: if NULL this function will not
870 * notify the end of the transaction, and whether it went
871 * successfully or not).
872 * @param userdata Userdata passed to callback
873 *
874 * @retval frames Positive number of frames received in slave mode.
875 * @retval 0 If successful in master mode.
876 * @retval -errno Negative errno code on failure.
877 */
spi_transceive_cb(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs,spi_callback_t callback,void * userdata)878 static inline int spi_transceive_cb(const struct device *dev,
879 const struct spi_config *config,
880 const struct spi_buf_set *tx_bufs,
881 const struct spi_buf_set *rx_bufs,
882 spi_callback_t callback,
883 void *userdata)
884 {
885 const struct spi_driver_api *api =
886 (const struct spi_driver_api *)dev->api;
887
888 return api->transceive_async(dev, config, tx_bufs, rx_bufs, callback, userdata);
889 }
890
891 #if defined(CONFIG_POLL) || defined(__DOXYGEN__)
892
893 /** @cond INTERNAL_HIDDEN */
894 void z_spi_transfer_signal_cb(const struct device *dev, int result, void *userdata);
895 /** @endcond */
896
897 /**
898 * @brief Read/write the specified amount of data from the SPI driver.
899 *
900 * @note This function is asynchronous.
901 *
902 * @note This function is available only if @kconfig{CONFIG_SPI_ASYNC}
903 * and @kconfig{CONFIG_POLL} are selected.
904 *
905 * @param dev Pointer to the device structure for the driver instance
906 * @param config Pointer to a valid spi_config structure instance.
907 * Pointer-comparison may be used to detect changes from
908 * previous operations.
909 * @param tx_bufs Buffer array where data to be sent originates from,
910 * or NULL if none.
911 * @param rx_bufs Buffer array where data to be read will be written to,
912 * or NULL if none.
913 * @param sig A pointer to a valid and ready to be signaled
914 * struct k_poll_signal. (Note: if NULL this function will not
915 * notify the end of the transaction, and whether it went
916 * successfully or not).
917 *
918 * @retval frames Positive number of frames received in slave mode.
919 * @retval 0 If successful in master mode.
920 * @retval -errno Negative errno code on failure.
921 */
spi_transceive_signal(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs,struct k_poll_signal * sig)922 static inline int spi_transceive_signal(const struct device *dev,
923 const struct spi_config *config,
924 const struct spi_buf_set *tx_bufs,
925 const struct spi_buf_set *rx_bufs,
926 struct k_poll_signal *sig)
927 {
928 const struct spi_driver_api *api =
929 (const struct spi_driver_api *)dev->api;
930 spi_callback_t cb = (sig == NULL) ? NULL : z_spi_transfer_signal_cb;
931
932 return api->transceive_async(dev, config, tx_bufs, rx_bufs, cb, sig);
933 }
934
935 /**
936 * @brief Read the specified amount of data from the SPI driver.
937 *
938 * @note This function is asynchronous.
939 *
940 * @note This function is a helper function calling spi_transceive_signal.
941 *
942 * @note This function is available only if @kconfig{CONFIG_SPI_ASYNC}
943 * and @kconfig{CONFIG_POLL} are selected.
944 *
945 * @param dev Pointer to the device structure for the driver instance
946 * @param config Pointer to a valid spi_config structure instance.
947 * Pointer-comparison may be used to detect changes from
948 * previous operations.
949 * @param rx_bufs Buffer array where data to be read will be written to.
950 * @param sig A pointer to a valid and ready to be signaled
951 * struct k_poll_signal. (Note: if NULL this function will not
952 * notify the end of the transaction, and whether it went
953 * successfully or not).
954 *
955 * @retval frames Positive number of frames received in slave mode.
956 * @retval 0 If successful
957 * @retval -errno Negative errno code on failure.
958 */
spi_read_signal(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * rx_bufs,struct k_poll_signal * sig)959 static inline int spi_read_signal(const struct device *dev,
960 const struct spi_config *config,
961 const struct spi_buf_set *rx_bufs,
962 struct k_poll_signal *sig)
963 {
964 return spi_transceive_signal(dev, config, NULL, rx_bufs, sig);
965 }
966
967 /**
968 * @brief Write the specified amount of data from the SPI driver.
969 *
970 * @note This function is asynchronous.
971 *
972 * @note This function is a helper function calling spi_transceive_signal.
973 *
974 * @note This function is available only if @kconfig{CONFIG_SPI_ASYNC}
975 * and @kconfig{CONFIG_POLL} are selected.
976 *
977 * @param dev Pointer to the device structure for the driver instance
978 * @param config Pointer to a valid spi_config structure instance.
979 * Pointer-comparison may be used to detect changes from
980 * previous operations.
981 * @param tx_bufs Buffer array where data to be sent originates from.
982 * @param sig A pointer to a valid and ready to be signaled
983 * struct k_poll_signal. (Note: if NULL this function will not
984 * notify the end of the transaction, and whether it went
985 * successfully or not).
986 *
987 * @retval 0 If successful.
988 * @retval -errno Negative errno code on failure.
989 */
spi_write_signal(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * tx_bufs,struct k_poll_signal * sig)990 static inline int spi_write_signal(const struct device *dev,
991 const struct spi_config *config,
992 const struct spi_buf_set *tx_bufs,
993 struct k_poll_signal *sig)
994 {
995 return spi_transceive_signal(dev, config, tx_bufs, NULL, sig);
996 }
997
998 #endif /* CONFIG_POLL */
999
1000 #endif /* CONFIG_SPI_ASYNC */
1001
1002
1003 #if defined(CONFIG_SPI_RTIO) || defined(__DOXYGEN__)
1004
1005 /**
1006 * @brief Submit a SPI device with a request
1007 *
1008 * @param iodev_sqe Prepared submissions queue entry connected to an iodev
1009 * defined by SPI_IODEV_DEFINE.
1010 * Must live as long as the request is in flight.
1011 */
spi_iodev_submit(struct rtio_iodev_sqe * iodev_sqe)1012 static inline void spi_iodev_submit(struct rtio_iodev_sqe *iodev_sqe)
1013 {
1014 const struct spi_dt_spec *dt_spec = iodev_sqe->sqe.iodev->data;
1015 const struct device *dev = dt_spec->bus;
1016 const struct spi_driver_api *api = (const struct spi_driver_api *)dev->api;
1017
1018 api->iodev_submit(dt_spec->bus, iodev_sqe);
1019 }
1020
1021 extern const struct rtio_iodev_api spi_iodev_api;
1022
1023 /**
1024 * @brief Define an iodev for a given dt node on the bus
1025 *
1026 * These do not need to be shared globally but doing so
1027 * will save a small amount of memory.
1028 *
1029 * @param name Symbolic name to use for defining the iodev
1030 * @param node_id Devicetree node identifier
1031 * @param operation_ SPI operational mode
1032 * @param delay_ Chip select delay in microseconds
1033 */
1034 #define SPI_DT_IODEV_DEFINE(name, node_id, operation_, delay_) \
1035 const struct spi_dt_spec _spi_dt_spec_##name = \
1036 SPI_DT_SPEC_GET(node_id, operation_, delay_); \
1037 RTIO_IODEV_DEFINE(name, &spi_iodev_api, (void *)&_spi_dt_spec_##name)
1038
1039 /**
1040 * @brief Validate that SPI bus (and CS gpio if defined) is ready.
1041 *
1042 * @param spi_iodev SPI iodev defined with SPI_DT_IODEV_DEFINE
1043 *
1044 * @retval true if the SPI bus is ready for use.
1045 * @retval false if the SPI bus (or the CS gpio defined) is not ready for use.
1046 */
spi_is_ready_iodev(const struct rtio_iodev * spi_iodev)1047 static inline bool spi_is_ready_iodev(const struct rtio_iodev *spi_iodev)
1048 {
1049 struct spi_dt_spec *spec = spi_iodev->data;
1050
1051 return spi_is_ready_dt(spec);
1052 }
1053
1054 /**
1055 * @brief Copy the tx_bufs and rx_bufs into a set of RTIO requests
1056 *
1057 * @param[in] r rtio context
1058 * @param[in] iodev iodev to transceive with
1059 * @param[in] tx_bufs transmit buffer set
1060 * @param[in] rx_bufs receive buffer set
1061 * @param[out] last_sqe last sqe submitted, NULL if not enough memory
1062 *
1063 * @retval Number of submission queue entries
1064 * @retval -ENOMEM out of memory
1065 */
spi_rtio_copy(struct rtio * r,struct rtio_iodev * iodev,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs,struct rtio_sqe ** last_sqe)1066 static inline int spi_rtio_copy(struct rtio *r,
1067 struct rtio_iodev *iodev,
1068 const struct spi_buf_set *tx_bufs,
1069 const struct spi_buf_set *rx_bufs,
1070 struct rtio_sqe **last_sqe)
1071 {
1072 int ret = 0;
1073 size_t tx_count = tx_bufs ? tx_bufs->count : 0;
1074 size_t rx_count = rx_bufs ? rx_bufs->count : 0;
1075
1076 uint32_t tx = 0, tx_len = 0;
1077 uint32_t rx = 0, rx_len = 0;
1078 uint8_t *tx_buf, *rx_buf;
1079
1080 struct rtio_sqe *sqe = NULL;
1081
1082 if (tx < tx_count) {
1083 tx_buf = tx_bufs->buffers[tx].buf;
1084 tx_len = tx_bufs->buffers[tx].len;
1085 } else {
1086 tx_buf = NULL;
1087 tx_len = rx_bufs->buffers[rx].len;
1088 }
1089
1090 if (rx < rx_count) {
1091 rx_buf = rx_bufs->buffers[rx].buf;
1092 rx_len = rx_bufs->buffers[rx].len;
1093 } else {
1094 rx_buf = NULL;
1095 rx_len = tx_bufs->buffers[tx].len;
1096 }
1097
1098
1099 while ((tx < tx_count || rx < rx_count) && (tx_len > 0 || rx_len > 0)) {
1100 sqe = rtio_sqe_acquire(r);
1101
1102 if (sqe == NULL) {
1103 ret = -ENOMEM;
1104 rtio_sqe_drop_all(r);
1105 goto out;
1106 }
1107
1108 ret++;
1109
1110 /* If tx/rx len are same, we can do a simple transceive */
1111 if (tx_len == rx_len) {
1112 if (tx_buf == NULL) {
1113 rtio_sqe_prep_read(sqe, iodev, RTIO_PRIO_NORM,
1114 rx_buf, rx_len, NULL);
1115 } else if (rx_buf == NULL) {
1116 rtio_sqe_prep_write(sqe, iodev, RTIO_PRIO_NORM,
1117 tx_buf, tx_len, NULL);
1118 } else {
1119 rtio_sqe_prep_transceive(sqe, iodev, RTIO_PRIO_NORM,
1120 tx_buf, rx_buf, rx_len, NULL);
1121 }
1122 tx++;
1123 rx++;
1124 if (rx < rx_count) {
1125 rx_buf = rx_bufs->buffers[rx].buf;
1126 rx_len = rx_bufs->buffers[rx].len;
1127 } else {
1128 rx_buf = NULL;
1129 rx_len = 0;
1130 }
1131 if (tx < tx_count) {
1132 tx_buf = tx_bufs->buffers[tx].buf;
1133 tx_len = tx_bufs->buffers[tx].len;
1134 } else {
1135 tx_buf = NULL;
1136 tx_len = 0;
1137 }
1138 } else if (tx_len == 0) {
1139 rtio_sqe_prep_read(sqe, iodev, RTIO_PRIO_NORM,
1140 (uint8_t *)rx_buf,
1141 (uint32_t)rx_len,
1142 NULL);
1143 rx++;
1144 if (rx < rx_count) {
1145 rx_buf = rx_bufs->buffers[rx].buf;
1146 rx_len = rx_bufs->buffers[rx].len;
1147 } else {
1148 rx_buf = NULL;
1149 rx_len = 0;
1150 }
1151 } else if (rx_len == 0) {
1152 rtio_sqe_prep_write(sqe, iodev, RTIO_PRIO_NORM,
1153 (uint8_t *)tx_buf,
1154 (uint32_t)tx_len,
1155 NULL);
1156 tx++;
1157 if (tx < tx_count) {
1158 tx_buf = rx_bufs->buffers[rx].buf;
1159 tx_len = rx_bufs->buffers[rx].len;
1160 } else {
1161 tx_buf = NULL;
1162 tx_len = 0;
1163 }
1164 } else if (tx_len > rx_len) {
1165 rtio_sqe_prep_transceive(sqe, iodev, RTIO_PRIO_NORM,
1166 (uint8_t *)tx_buf,
1167 (uint8_t *)rx_buf,
1168 (uint32_t)rx_len,
1169 NULL);
1170 tx_len -= rx_len;
1171 tx_buf += rx_len;
1172 rx++;
1173 if (rx < rx_count) {
1174 rx_buf = rx_bufs->buffers[rx].buf;
1175 rx_len = rx_bufs->buffers[rx].len;
1176 } else {
1177 rx_buf = NULL;
1178 rx_len = tx_len;
1179 }
1180 } else if (rx_len > tx_len) {
1181 rtio_sqe_prep_transceive(sqe, iodev, RTIO_PRIO_NORM,
1182 (uint8_t *)tx_buf,
1183 (uint8_t *)rx_buf,
1184 (uint32_t)tx_len,
1185 NULL);
1186 rx_len -= tx_len;
1187 rx_buf += tx_len;
1188 tx++;
1189 if (tx < tx_count) {
1190 tx_buf = tx_bufs->buffers[tx].buf;
1191 tx_len = tx_bufs->buffers[tx].len;
1192 } else {
1193 tx_buf = NULL;
1194 tx_len = rx_len;
1195 }
1196 } else {
1197 __ASSERT_NO_MSG("Invalid spi_rtio_copy state");
1198 }
1199
1200 sqe->flags = RTIO_SQE_TRANSACTION;
1201 }
1202
1203 if (sqe != NULL) {
1204 sqe->flags = 0;
1205 *last_sqe = sqe;
1206 }
1207
1208 out:
1209 return ret;
1210 }
1211
1212 #endif /* CONFIG_SPI_RTIO */
1213
1214 /**
1215 * @brief Release the SPI device locked on and/or the CS by the current config
1216 *
1217 * Note: This synchronous function is used to release either the lock on the
1218 * SPI device and/or the CS line that was kept if, and if only,
1219 * given config parameter was the last one to be used (in any of the
1220 * above functions) and if it has the SPI_LOCK_ON bit set and/or the
1221 * SPI_HOLD_ON_CS bit set into its operation bits field.
1222 * This can be used if the caller needs to keep its hand on the SPI
1223 * device for consecutive transactions and/or if it needs the device to
1224 * stay selected. Usually both bits will be used along each other, so the
1225 * the device is locked and stays on until another operation is necessary
1226 * or until it gets released with the present function.
1227 *
1228 * @param dev Pointer to the device structure for the driver instance
1229 * @param config Pointer to a valid spi_config structure instance.
1230 *
1231 * @retval 0 If successful.
1232 * @retval -errno Negative errno code on failure.
1233 */
1234 __syscall int spi_release(const struct device *dev,
1235 const struct spi_config *config);
1236
z_impl_spi_release(const struct device * dev,const struct spi_config * config)1237 static inline int z_impl_spi_release(const struct device *dev,
1238 const struct spi_config *config)
1239 {
1240 const struct spi_driver_api *api =
1241 (const struct spi_driver_api *)dev->api;
1242
1243 return api->release(dev, config);
1244 }
1245
1246 /**
1247 * @brief Release the SPI device specified in @p spi_dt_spec.
1248 *
1249 * This is equivalent to:
1250 *
1251 * spi_release(spec->bus, &spec->config);
1252 *
1253 * @param spec SPI specification from devicetree
1254 *
1255 * @return a value from spi_release().
1256 */
spi_release_dt(const struct spi_dt_spec * spec)1257 static inline int spi_release_dt(const struct spi_dt_spec *spec)
1258 {
1259 return spi_release(spec->bus, &spec->config);
1260 }
1261
1262 #ifdef __cplusplus
1263 }
1264 #endif
1265
1266 /**
1267 * @}
1268 */
1269
1270 #include <zephyr/syscalls/spi.h>
1271
1272 #endif /* ZEPHYR_INCLUDE_DRIVERS_SPI_H_ */
1273