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 * @ingroup io_interfaces
19 * @{
20 */
21
22 #include <zephyr/types.h>
23 #include <stddef.h>
24 #include <device.h>
25 #include <drivers/gpio.h>
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30
31 /**
32 * @brief SPI operational mode
33 */
34 #define SPI_OP_MODE_MASTER 0
35 #define SPI_OP_MODE_SLAVE BIT(0)
36 #define SPI_OP_MODE_MASK 0x1
37 #define SPI_OP_MODE_GET(_operation_) ((_operation_) & SPI_OP_MODE_MASK)
38
39 /**
40 * @brief SPI Polarity & Phase Modes
41 */
42
43 /**
44 * Clock Polarity: if set, clock idle state will be 1
45 * and active state will be 0. If untouched, the inverse will be true
46 * which is the default.
47 */
48 #define SPI_MODE_CPOL BIT(1)
49
50 /**
51 * Clock Phase: this dictates when is the data captured, and depends
52 * clock's polarity. When SPI_MODE_CPOL is set and this bit as well,
53 * capture will occur on low to high transition and high to low if
54 * this bit is not set (default). This is fully reversed if CPOL is
55 * not set.
56 */
57 #define SPI_MODE_CPHA BIT(2)
58
59 /**
60 * Whatever data is transmitted is looped-back to the receiving buffer of
61 * the controller. This is fully controller dependent as some may not
62 * support this, and can be used for testing purposes only.
63 */
64 #define SPI_MODE_LOOP BIT(3)
65
66 #define SPI_MODE_MASK (0xE)
67 #define SPI_MODE_GET(_mode_) \
68 ((_mode_) & SPI_MODE_MASK)
69
70 /**
71 * @brief SPI Transfer modes (host controller dependent)
72 */
73 #define SPI_TRANSFER_MSB (0)
74 #define SPI_TRANSFER_LSB BIT(4)
75
76 /**
77 * @brief SPI word size
78 */
79 #define SPI_WORD_SIZE_SHIFT (5)
80 #define SPI_WORD_SIZE_MASK (0x3F << SPI_WORD_SIZE_SHIFT)
81 #define SPI_WORD_SIZE_GET(_operation_) \
82 (((_operation_) & SPI_WORD_SIZE_MASK) >> SPI_WORD_SIZE_SHIFT)
83
84 #define SPI_WORD_SET(_word_size_) \
85 ((_word_size_) << SPI_WORD_SIZE_SHIFT)
86
87 /**
88 * @brief SPI MISO lines
89 *
90 * Some controllers support dual, quad or octal MISO lines connected to slaves.
91 * Default is single, which is the case most of the time.
92 */
93 #define SPI_LINES_SINGLE (0 << 11)
94 #define SPI_LINES_DUAL (1 << 11)
95 #define SPI_LINES_QUAD (2 << 11)
96 #define SPI_LINES_OCTAL (3 << 11)
97
98 #define SPI_LINES_MASK (0x3 << 11)
99
100 /**
101 * @brief Specific SPI devices control bits
102 */
103 /* Requests - if possible - to keep CS asserted after the transaction */
104 #define SPI_HOLD_ON_CS BIT(13)
105 /* Keep the device locked after the transaction for the current config.
106 * Use this with extreme caution (see spi_release() below) as it will
107 * prevent other callers to access the SPI device until spi_release() is
108 * properly called.
109 */
110 #define SPI_LOCK_ON BIT(14)
111
112 /* Active high logic on CS - Usually, and by default, CS logic is active
113 * low. However, some devices may require the reverse logic: active high.
114 * This bit will request the controller to use that logic. Note that not
115 * all controllers are able to handle that natively. In this case deferring
116 * the CS control to a gpio line through struct spi_cs_control would be
117 * the solution.
118 */
119 #define SPI_CS_ACTIVE_HIGH BIT(15)
120
121 /**
122 * @brief SPI Chip Select control structure
123 *
124 * This can be used to control a CS line via a GPIO line, instead of
125 * using the controller inner CS logic.
126 *
127 * @param gpio_dev is a valid pointer to an actual GPIO device. A NULL pointer
128 * can be provided to full inhibit CS control if necessary.
129 * @param gpio_pin is a number representing the gpio PIN that will be used
130 * to act as a CS line
131 * @param delay is a delay in microseconds to wait before starting the
132 * transmission and before releasing the CS line
133 * @param gpio_dt_flags is the devicetree flags corresponding to how the CS
134 * line should be driven. GPIO_ACTIVE_LOW/GPIO_ACTIVE_HIGH should be
135 * equivalent to SPI_CS_ACTIVE_HIGH/SPI_CS_ACTIVE_LOW options in struct
136 * spi_config.
137 */
138 struct spi_cs_control {
139 const struct device *gpio_dev;
140 uint32_t delay;
141 gpio_pin_t gpio_pin;
142 gpio_dt_flags_t gpio_dt_flags;
143 };
144
145 #ifndef __cplusplus
146 /**
147 * @brief Initialize and get a pointer to a @p spi_cs_control from a
148 * devicetree node identifier
149 *
150 * This helper is useful for initializing a device on a SPI bus. It
151 * initializes a struct spi_cs_control and returns a pointer to it.
152 * Here, @p node_id is a node identifier for a SPI device, not a SPI
153 * controller.
154 *
155 * Example devicetree fragment:
156 *
157 * spi@... {
158 * cs-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
159 * spidev: spi-device@0 { ... };
160 * };
161 *
162 * Assume that @p gpio0 follows the standard convention for specifying
163 * GPIOs, i.e. it has the following in its binding:
164 *
165 * gpio-cells:
166 * - pin
167 * - flags
168 *
169 * Example usage:
170 *
171 * struct spi_cs_control *ctrl =
172 * SPI_CS_CONTROL_PTR_DT(DT_NODELABEL(spidev), 2);
173 *
174 * This example is equivalent to:
175 *
176 * struct spi_cs_control *ctrl =
177 * &(struct spi_cs_control) {
178 * .gpio_dev = DEVICE_DT_GET(DT_NODELABEL(gpio0)),
179 * .delay = 2,
180 * .gpio_pin = 1,
181 * .gpio_dt_flags = GPIO_ACTIVE_LOW
182 * };
183 *
184 * This macro is not available in C++.
185 *
186 * @param node_id Devicetree node identifier for a device on a SPI bus
187 * @param delay_ The @p delay field to set in the @p spi_cs_control
188 * @return a pointer to the @p spi_cs_control structure
189 */
190 #define SPI_CS_CONTROL_PTR_DT(node_id, delay_) \
191 (&(struct spi_cs_control) { \
192 .gpio_dev = DEVICE_DT_GET( \
193 DT_SPI_DEV_CS_GPIOS_CTLR(node_id)), \
194 .delay = (delay_), \
195 .gpio_pin = DT_SPI_DEV_CS_GPIOS_PIN(node_id), \
196 .gpio_dt_flags = DT_SPI_DEV_CS_GPIOS_FLAGS(node_id), \
197 })
198
199 /**
200 * @brief Get a pointer to a @p spi_cs_control from a devicetree node
201 *
202 * This is equivalent to
203 * <tt>SPI_CS_CONTROL_PTR_DT(DT_DRV_INST(inst), delay)</tt>.
204 *
205 * Therefore, @p DT_DRV_COMPAT must already be defined before using
206 * this macro.
207 *
208 * This macro is not available in C++.
209 *
210 * @param inst Devicetree node instance number
211 * @param delay_ The @p delay field to set in the @p spi_cs_control
212 * @return a pointer to the @p spi_cs_control structure
213 */
214 #define SPI_CS_CONTROL_PTR_DT_INST(inst, delay_) \
215 SPI_CS_CONTROL_PTR_DT(DT_DRV_INST(inst), delay_)
216 #endif
217
218 /**
219 * @brief SPI controller configuration structure
220 *
221 * @param frequency is the bus frequency in Hertz
222 * @param operation is a bit field with the following parts:
223 *
224 * operational mode [ 0 ] - master or slave.
225 * mode [ 1 : 3 ] - Polarity, phase and loop mode.
226 * transfer [ 4 ] - LSB or MSB first.
227 * word_size [ 5 : 10 ] - Size of a data frame in bits.
228 * lines [ 11 : 12 ] - MISO lines: Single/Dual/Quad/Octal.
229 * cs_hold [ 13 ] - Hold on the CS line if possible.
230 * lock_on [ 14 ] - Keep resource locked for the caller.
231 * cs_active_high [ 15 ] - Active high CS logic.
232 * @param slave is the slave number from 0 to host controller slave limit.
233 * @param cs is a valid pointer on a struct spi_cs_control is CS line is
234 * emulated through a gpio line, or NULL otherwise.
235 *
236 * @note Only cs_hold and lock_on can be changed between consecutive
237 * transceive call. Rest of the attributes are not meant to be tweaked.
238 *
239 * @warning Most drivers use pointer comparison to determine whether a
240 * passed configuration is different from one used in a previous
241 * transaction. Changes to fields in the structure may not be
242 * detected.
243 */
244 struct spi_config {
245 uint32_t frequency;
246 uint16_t operation;
247 uint16_t slave;
248
249 const struct spi_cs_control *cs;
250 };
251
252 #ifndef __cplusplus
253 /**
254 * @brief Structure initializer for spi_config from devicetree
255 *
256 * This helper macro expands to a static initializer for a <tt>struct
257 * spi_config</tt> by reading the relevant @p frequency, @p slave, and
258 * @p cs data from the devicetree.
259 *
260 * Important: the @p cs field is initialized using
261 * SPI_CS_CONTROL_PTR_DT(). The @p gpio_dev value pointed to by this
262 * structure must be checked using device_is_ready() before use.
263 *
264 * This macro is not available in C++.
265 *
266 * @param node_id Devicetree node identifier for the SPI device whose
267 * struct spi_config to create an initializer for
268 * @param operation_ the desired @p operation field in the struct spi_config
269 * @param delay_ the desired @p delay field in the struct spi_config's
270 * spi_cs_control, if there is one
271 */
272 #define SPI_CONFIG_DT(node_id, operation_, delay_) \
273 { \
274 .frequency = DT_PROP(node_id, spi_max_frequency), \
275 .operation = (operation_), \
276 .slave = DT_REG_ADDR(node_id), \
277 .cs = COND_CODE_1( \
278 DT_SPI_DEV_HAS_CS_GPIOS(node_id), \
279 (SPI_CS_CONTROL_PTR_DT(node_id, delay_)), \
280 (NULL)), \
281 }
282
283 /**
284 * @brief Structure initializer for spi_config from devicetree instance
285 *
286 * This is equivalent to
287 * <tt>SPI_CONFIG_DT(DT_DRV_INST(inst), operation_, delay_)</tt>.
288 *
289 * This macro is not available in C++.
290 *
291 * @param inst Devicetree instance number
292 * @param operation_ the desired @p operation field in the struct spi_config
293 * @param delay_ the desired @p delay field in the struct spi_config's
294 * spi_cs_control, if there is one
295 */
296 #define SPI_CONFIG_DT_INST(inst, operation_, delay_) \
297 SPI_CONFIG_DT(DT_DRV_INST(inst), operation_, delay_)
298 #endif
299
300 /**
301 * @brief Complete SPI DT information
302 *
303 * @param bus is the SPI bus
304 * @param config is the slave specific configuration
305 */
306 struct spi_dt_spec {
307 const struct device *bus;
308 struct spi_config config;
309 };
310
311 #ifndef __cplusplus
312 /**
313 * @brief Structure initializer for spi_dt_spec from devicetree
314 *
315 * This helper macro expands to a static initializer for a <tt>struct
316 * spi_dt_spec</tt> by reading the relevant bus, frequency, slave, and cs
317 * data from the devicetree.
318 *
319 * Important: multiple fields are automatically constructed by this macro
320 * which must be checked before use. @ref spi_is_ready performs the required
321 * @ref device_is_ready checks.
322 *
323 * This macro is not available in C++.
324 *
325 * @param node_id Devicetree node identifier for the SPI device whose
326 * struct spi_dt_spec to create an initializer for
327 * @param operation_ the desired @p operation field in the struct spi_config
328 * @param delay_ the desired @p delay field in the struct spi_config's
329 * spi_cs_control, if there is one
330 */
331 #define SPI_DT_SPEC_GET(node_id, operation_, delay_) \
332 { \
333 .bus = DEVICE_DT_GET(DT_BUS(node_id)), \
334 .config = SPI_CONFIG_DT(node_id, operation_, delay_) \
335 }
336
337 /**
338 * @brief Structure initializer for spi_dt_spec from devicetree instance
339 *
340 * This is equivalent to
341 * <tt>SPI_DT_SPEC_GET(DT_DRV_INST(inst), operation_, delay_)</tt>.
342 *
343 * This macro is not available in C++.
344 *
345 * @param inst Devicetree instance number
346 * @param operation_ the desired @p operation field in the struct spi_config
347 * @param delay_ the desired @p delay field in the struct spi_config's
348 * spi_cs_control, if there is one
349 */
350 #define SPI_DT_SPEC_INST_GET(inst, operation_, delay_) \
351 SPI_DT_SPEC_GET(DT_DRV_INST(inst), operation_, delay_)
352 #endif
353
354 /**
355 * @brief SPI buffer structure
356 *
357 * @param buf is a valid pointer on a data buffer, or NULL otherwise.
358 * @param len is the length of the buffer or, if buf is NULL, will be the
359 * length which as to be sent as dummy bytes (as TX buffer) or
360 * the length of bytes that should be skipped (as RX buffer).
361 */
362 struct spi_buf {
363 void *buf;
364 size_t len;
365 };
366
367 /**
368 * @brief SPI buffer array structure
369 *
370 * @param buffers is a valid pointer on an array of spi_buf, or NULL.
371 * @param count is the length of the array pointed by buffers.
372 */
373 struct spi_buf_set {
374 const struct spi_buf *buffers;
375 size_t count;
376 };
377
378 /**
379 * @typedef spi_api_io
380 * @brief Callback API for I/O
381 * See spi_transceive() for argument descriptions
382 */
383 typedef int (*spi_api_io)(const struct device *dev,
384 const struct spi_config *config,
385 const struct spi_buf_set *tx_bufs,
386 const struct spi_buf_set *rx_bufs);
387
388 /**
389 * @typedef spi_api_io
390 * @brief Callback API for asynchronous I/O
391 * See spi_transceive_async() for argument descriptions
392 */
393 typedef int (*spi_api_io_async)(const struct device *dev,
394 const struct spi_config *config,
395 const struct spi_buf_set *tx_bufs,
396 const struct spi_buf_set *rx_bufs,
397 struct k_poll_signal *async);
398
399 /**
400 * @typedef spi_api_release
401 * @brief Callback API for unlocking SPI device.
402 * See spi_release() for argument descriptions
403 */
404 typedef int (*spi_api_release)(const struct device *dev,
405 const struct spi_config *config);
406
407
408 /**
409 * @brief SPI driver API
410 * This is the mandatory API any SPI driver needs to expose.
411 */
412 __subsystem struct spi_driver_api {
413 spi_api_io transceive;
414 #ifdef CONFIG_SPI_ASYNC
415 spi_api_io_async transceive_async;
416 #endif /* CONFIG_SPI_ASYNC */
417 spi_api_release release;
418 };
419
420 /**
421 * @brief Validate that SPI bus is ready.
422 *
423 * @param spec SPI specification from devicetree
424 *
425 * @retval true if the SPI bus is ready for use.
426 * @retval false if the SPI bus is not ready for use.
427 */
spi_is_ready(const struct spi_dt_spec * spec)428 static inline bool spi_is_ready(const struct spi_dt_spec *spec)
429 {
430 /* Validate bus is ready */
431 if (!device_is_ready(spec->bus)) {
432 return false;
433 }
434 /* Validate CS gpio port is ready, if it is used */
435 if (spec->config.cs &&
436 !device_is_ready(spec->config.cs->gpio_dev)) {
437 return false;
438 }
439 return true;
440 }
441
442 /**
443 * @brief Read/write the specified amount of data from the SPI driver.
444 *
445 * @note This function is synchronous.
446 *
447 * @param dev Pointer to the device structure for the driver instance
448 * @param config Pointer to a valid spi_config structure instance.
449 * Pointer-comparison may be used to detect changes from
450 * previous operations.
451 * @param tx_bufs Buffer array where data to be sent originates from,
452 * or NULL if none.
453 * @param rx_bufs Buffer array where data to be read will be written to,
454 * or NULL if none.
455 *
456 * @retval frames Positive number of frames received in slave mode.
457 * @retval 0 If successful in master mode.
458 * @retval -errno Negative errno code on failure.
459 */
460 __syscall int spi_transceive(const struct device *dev,
461 const struct spi_config *config,
462 const struct spi_buf_set *tx_bufs,
463 const struct spi_buf_set *rx_bufs);
464
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)465 static inline int z_impl_spi_transceive(const struct device *dev,
466 const struct spi_config *config,
467 const struct spi_buf_set *tx_bufs,
468 const struct spi_buf_set *rx_bufs)
469 {
470 const struct spi_driver_api *api =
471 (const struct spi_driver_api *)dev->api;
472
473 return api->transceive(dev, config, tx_bufs, rx_bufs);
474 }
475
476 /**
477 * @brief Read/write data from an SPI bus specified in @p spi_dt_spec.
478 *
479 * This is equivalent to:
480 *
481 * spi_transceive(spec->bus, &spec->config, tx_bufs, rx_bufs);
482 *
483 * @param spec SPI specification from devicetree
484 * @param tx_bufs Buffer array where data to be sent originates from,
485 * or NULL if none.
486 * @param rx_bufs Buffer array where data to be read will be written to,
487 * or NULL if none.
488 *
489 * @return a value from spi_transceive().
490 */
spi_transceive_dt(const struct spi_dt_spec * spec,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs)491 static inline int spi_transceive_dt(const struct spi_dt_spec *spec,
492 const struct spi_buf_set *tx_bufs,
493 const struct spi_buf_set *rx_bufs)
494 {
495 return spi_transceive(spec->bus, &spec->config, tx_bufs, rx_bufs);
496 }
497
498 /**
499 * @brief Read the specified amount of data from the SPI driver.
500 *
501 * @note This function is synchronous.
502 *
503 * @note This function is an helper function calling spi_transceive.
504 *
505 * @param dev Pointer to the device structure for the driver instance
506 * @param config Pointer to a valid spi_config structure instance.
507 * Pointer-comparison may be used to detect changes from
508 * previous operations.
509 * @param rx_bufs Buffer array where data to be read will be written to.
510 *
511 * @retval 0 If successful.
512 * @retval -errno Negative errno code on failure.
513 */
spi_read(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * rx_bufs)514 static inline int spi_read(const struct device *dev,
515 const struct spi_config *config,
516 const struct spi_buf_set *rx_bufs)
517 {
518 return spi_transceive(dev, config, NULL, rx_bufs);
519 }
520
521 /**
522 * @brief Read data from a SPI bus specified in @p spi_dt_spec.
523 *
524 * This is equivalent to:
525 *
526 * spi_read(spec->bus, &spec->config, rx_bufs);
527 *
528 * @param spec SPI specification from devicetree
529 * @param rx_bufs Buffer array where data to be read will be written to.
530 *
531 * @return a value from spi_read().
532 */
spi_read_dt(const struct spi_dt_spec * spec,const struct spi_buf_set * rx_bufs)533 static inline int spi_read_dt(const struct spi_dt_spec *spec,
534 const struct spi_buf_set *rx_bufs)
535 {
536 return spi_read(spec->bus, &spec->config, rx_bufs);
537 }
538
539 /**
540 * @brief Write the specified amount of data from the SPI driver.
541 *
542 * @note This function is synchronous.
543 *
544 * @note This function is an helper function calling spi_transceive.
545 *
546 * @param dev Pointer to the device structure for the driver instance
547 * @param config Pointer to a valid spi_config structure instance.
548 * Pointer-comparison may be used to detect changes from
549 * previous operations.
550 * @param tx_bufs Buffer array where data to be sent originates from.
551 *
552 * @retval 0 If successful.
553 * @retval -errno Negative errno code on failure.
554 */
spi_write(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * tx_bufs)555 static inline int spi_write(const struct device *dev,
556 const struct spi_config *config,
557 const struct spi_buf_set *tx_bufs)
558 {
559 return spi_transceive(dev, config, tx_bufs, NULL);
560 }
561
562 /**
563 * @brief Write data to a SPI bus specified in @p spi_dt_spec.
564 *
565 * This is equivalent to:
566 *
567 * spi_write(spec->bus, &spec->config, tx_bufs);
568 *
569 * @param spec SPI specification from devicetree
570 * @param tx_bufs Buffer array where data to be sent originates from.
571 *
572 * @return a value from spi_write().
573 */
spi_write_dt(const struct spi_dt_spec * spec,const struct spi_buf_set * tx_bufs)574 static inline int spi_write_dt(const struct spi_dt_spec *spec,
575 const struct spi_buf_set *tx_bufs)
576 {
577 return spi_write(spec->bus, &spec->config, tx_bufs);
578 }
579
580 /* Doxygen defines this so documentation is generated. */
581 #ifdef CONFIG_SPI_ASYNC
582
583 /**
584 * @brief Read/write the specified amount of data from the SPI driver.
585 *
586 * @note This function is asynchronous.
587 *
588 * @note This function is available only if @kconfig{CONFIG_SPI_ASYNC}
589 * is selected.
590 *
591 * @param dev Pointer to the device structure for the driver instance
592 * @param config Pointer to a valid spi_config structure instance.
593 * Pointer-comparison may be used to detect changes from
594 * previous operations.
595 * @param tx_bufs Buffer array where data to be sent originates from,
596 * or NULL if none.
597 * @param rx_bufs Buffer array where data to be read will be written to,
598 * or NULL if none.
599 * @param async A pointer to a valid and ready to be signaled
600 * struct k_poll_signal. (Note: if NULL this function will not
601 * notify the end of the transaction, and whether it went
602 * successfully or not).
603 *
604 * @retval frames Positive number of frames received in slave mode.
605 * @retval 0 If successful in master mode.
606 * @retval -errno Negative errno code on failure.
607 */
spi_transceive_async(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 * async)608 static inline int spi_transceive_async(const struct device *dev,
609 const struct spi_config *config,
610 const struct spi_buf_set *tx_bufs,
611 const struct spi_buf_set *rx_bufs,
612 struct k_poll_signal *async)
613 {
614 const struct spi_driver_api *api =
615 (const struct spi_driver_api *)dev->api;
616
617 return api->transceive_async(dev, config, tx_bufs, rx_bufs, async);
618 }
619
620 /**
621 * @brief Read the specified amount of data from the SPI driver.
622 *
623 * @note This function is asynchronous.
624 *
625 * @note This function is an helper function calling spi_transceive_async.
626 *
627 * @note This function is available only if @kconfig{CONFIG_SPI_ASYNC}
628 * is selected.
629 *
630 * @param dev Pointer to the device structure for the driver instance
631 * @param config Pointer to a valid spi_config structure instance.
632 * Pointer-comparison may be used to detect changes from
633 * previous operations.
634 * @param rx_bufs Buffer array where data to be read will be written to.
635 * @param async A pointer to a valid and ready to be signaled
636 * struct k_poll_signal. (Note: if NULL this function will not
637 * notify the end of the transaction, and whether it went
638 * successfully or not).
639 *
640 * @retval 0 If successful
641 * @retval -errno Negative errno code on failure.
642 */
spi_read_async(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * rx_bufs,struct k_poll_signal * async)643 static inline int spi_read_async(const struct device *dev,
644 const struct spi_config *config,
645 const struct spi_buf_set *rx_bufs,
646 struct k_poll_signal *async)
647 {
648 return spi_transceive_async(dev, config, NULL, rx_bufs, async);
649 }
650
651 /**
652 * @brief Write the specified amount of data from the SPI driver.
653 *
654 * @note This function is asynchronous.
655 *
656 * @note This function is an helper function calling spi_transceive_async.
657 *
658 * @note This function is available only if @kconfig{CONFIG_SPI_ASYNC}
659 * is selected.
660 *
661 * @param dev Pointer to the device structure for the driver instance
662 * @param config Pointer to a valid spi_config structure instance.
663 * Pointer-comparison may be used to detect changes from
664 * previous operations.
665 * @param tx_bufs Buffer array where data to be sent originates from.
666 * @param async A pointer to a valid and ready to be signaled
667 * struct k_poll_signal. (Note: if NULL this function will not
668 * notify the end of the transaction, and whether it went
669 * successfully or not).
670 *
671 * @retval 0 If successful.
672 * @retval -errno Negative errno code on failure.
673 */
spi_write_async(const struct device * dev,const struct spi_config * config,const struct spi_buf_set * tx_bufs,struct k_poll_signal * async)674 static inline int spi_write_async(const struct device *dev,
675 const struct spi_config *config,
676 const struct spi_buf_set *tx_bufs,
677 struct k_poll_signal *async)
678 {
679 return spi_transceive_async(dev, config, tx_bufs, NULL, async);
680 }
681 #endif /* CONFIG_SPI_ASYNC */
682
683 /**
684 * @brief Release the SPI device locked on by the current config
685 *
686 * Note: This synchronous function is used to release the lock on the SPI
687 * device that was kept if, and if only, given config parameter was
688 * the last one to be used (in any of the above functions) and if
689 * it has the SPI_LOCK_ON bit set into its operation bits field.
690 * This can be used if the caller needs to keep its hand on the SPI
691 * device for consecutive transactions.
692 *
693 * @param dev Pointer to the device structure for the driver instance
694 * @param config Pointer to a valid spi_config structure instance.
695 * Pointer-comparison may be used to detect changes from
696 * previous operations.
697 *
698 * @retval 0 If successful.
699 * @retval -errno Negative errno code on failure.
700 */
701 __syscall int spi_release(const struct device *dev,
702 const struct spi_config *config);
703
z_impl_spi_release(const struct device * dev,const struct spi_config * config)704 static inline int z_impl_spi_release(const struct device *dev,
705 const struct spi_config *config)
706 {
707 const struct spi_driver_api *api =
708 (const struct spi_driver_api *)dev->api;
709
710 return api->release(dev, config);
711 }
712
713 /**
714 * @brief Release the SPI device specified in @p spi_dt_spec.
715 *
716 * This is equivalent to:
717 *
718 * spi_release(spec->bus, &spec->config);
719 *
720 * @param spec SPI specification from devicetree
721 *
722 * @return a value from spi_release().
723 */
spi_release_dt(const struct spi_dt_spec * spec)724 static inline int spi_release_dt(const struct spi_dt_spec *spec)
725 {
726 return spi_release(spec->bus, &spec->config);
727 }
728
729 #ifdef __cplusplus
730 }
731 #endif
732
733 /**
734 * @}
735 */
736
737 #include <syscalls/spi.h>
738
739 #endif /* ZEPHYR_INCLUDE_DRIVERS_SPI_H_ */
740