@@ -75,17 +75,30 @@ struct spi_context {
7575 }, \
7676 ._ctx_name.num_cs_gpios = DT_PROP_LEN_OR(_node_id, cs_gpios, 0),
7777
78+ /*
79+ * Checks if a spi config is the same as the one stored in the spi_context
80+ * The intention of this function is to be used to check if a driver can skip
81+ * some reconfiguration for a transfer in a fast code path.
82+ */
7883static inline bool spi_context_configured (struct spi_context * ctx ,
7984 const struct spi_config * config )
8085{
8186 return !!(ctx -> config == config );
8287}
8388
89+ /* Returns true if the spi configuration stored for this context
90+ * specifies a slave mode configuration, returns false otherwise
91+ */
8492static inline bool spi_context_is_slave (struct spi_context * ctx )
8593{
8694 return (ctx -> config -> operation & SPI_OP_MODE_SLAVE );
8795}
8896
97+ /*
98+ * The purpose of the context lock is to synchronize the usage of the driver/hardware.
99+ * The driver should call this function to claim or wait for ownership of the spi resource.
100+ * Usually the appropriate time to call this is at the start of the transceive API implementation.
101+ */
89102static inline void spi_context_lock (struct spi_context * ctx ,
90103 bool asynchronous ,
91104 spi_callback_t callback ,
@@ -108,6 +121,13 @@ static inline void spi_context_lock(struct spi_context *ctx,
108121#endif /* CONFIG_SPI_ASYNC */
109122}
110123
124+ /*
125+ * This function must be called by a driver which has called spi_context_lock in order
126+ * to release the ownership of the spi resource.
127+ * Usually the appropriate time to call this would be at the end of a transfer that was
128+ * initiated by a transceive API call, except in the case that the SPI_LOCK_ON bit was set
129+ * in the configuration.
130+ */
111131static inline void spi_context_release (struct spi_context * ctx , int status )
112132{
113133#ifdef CONFIG_SPI_SLAVE
@@ -132,6 +152,13 @@ static inline void spi_context_release(struct spi_context *ctx, int status)
132152static inline size_t spi_context_total_tx_len (struct spi_context * ctx );
133153static inline size_t spi_context_total_rx_len (struct spi_context * ctx );
134154
155+ /* This function essentially is a way for a driver to seamlessly implement both the
156+ * synchronous transceive API and the asynchronous transceive_async API in the same way.
157+ *
158+ * The exact way this function is used may depend on driver implementation, but
159+ * essentially this will block waiting for a signal from spi_context_complete,
160+ * unless the transfer is asynchronous, in which case it does nothing in master mode.
161+ */
135162static inline int spi_context_wait_for_completion (struct spi_context * ctx )
136163{
137164 int status = 0 ;
@@ -180,6 +207,12 @@ static inline int spi_context_wait_for_completion(struct spi_context *ctx)
180207 return status ;
181208}
182209
210+ /* For synchronous transfers, this will signal to a thread waiting
211+ * on spi_context_wait for completion.
212+ *
213+ * For asynchronous tranfers, this will call the async callback function
214+ * with the user data.
215+ */
183216static inline void spi_context_complete (struct spi_context * ctx ,
184217 const struct device * dev ,
185218 int status )
@@ -212,6 +245,14 @@ static inline void spi_context_complete(struct spi_context *ctx,
212245#endif /* CONFIG_SPI_ASYNC */
213246}
214247
248+ /*
249+ * This function initializes all the chip select GPIOs associated with a spi controller.
250+ * The context first must be initialized using the SPI_CONTEXT_CS_GPIOS_INITIALIZE macro.
251+ * This function should be called during the device init sequence so that
252+ * all the CS lines are configured properly before the first transfer begins.
253+ * Note: If a controller has native CS control in SPI hardware, they should also be initialized
254+ * during device init by the driver with hardware-specific code.
255+ */
215256static inline int spi_context_cs_configure_all (struct spi_context * ctx )
216257{
217258 int ret ;
@@ -233,6 +274,7 @@ static inline int spi_context_cs_configure_all(struct spi_context *ctx)
233274 return 0 ;
234275}
235276
277+ /* Helper function to control the GPIO CS, not meant to be used directly by drivers */
236278static inline void _spi_context_cs_control (struct spi_context * ctx ,
237279 bool on , bool force_off )
238280{
@@ -252,11 +294,22 @@ static inline void _spi_context_cs_control(struct spi_context *ctx,
252294 }
253295}
254296
297+ /* This function should be called by drivers to control the chip select line in master mode
298+ * in the case of the CS being a GPIO. The de facto usage of the zephyr SPI API expects that the
299+ * chip select be asserted throughout the entire transfer specified by a transceive call,
300+ * ie all buffers in a spi_buf_set should be finished before deasserting CS. And usually
301+ * the deassertion is at the end of the transfer, except in the case that the
302+ * SPI_HOLD_ON_CS bit was set in the configuration.
303+ */
255304static inline void spi_context_cs_control (struct spi_context * ctx , bool on )
256305{
257306 _spi_context_cs_control (ctx , on , false);
258307}
259308
309+ /* Forcefully releases the spi context and removes the owner, allowing taking the lock
310+ * with spi_context_lock without the previous owner releasing the lock.
311+ * This is usually used to aid in implementation of the spi_release driver API.
312+ */
260313static inline void spi_context_unlock_unconditionally (struct spi_context * ctx )
261314{
262315 /* Forcing CS to go to inactive status */
@@ -268,6 +321,11 @@ static inline void spi_context_unlock_unconditionally(struct spi_context *ctx)
268321 }
269322}
270323
324+ /*
325+ * Helper function for incrementing buffer pointer.
326+ * Generally not needed to be used directly by drivers.
327+ * Use spi_context_update_(tx/rx) instead.
328+ */
271329static inline void * spi_context_get_next_buf (const struct spi_buf * * current ,
272330 size_t * count ,
273331 size_t * buf_len ,
@@ -287,6 +345,17 @@ static inline void *spi_context_get_next_buf(const struct spi_buf **current,
287345 return NULL ;
288346}
289347
348+ /*
349+ * The spi context private api works with the driver by providing code to
350+ * keep track of how much of the transfer has been completed. The driver
351+ * calls functions to report when some tx or rx has finished, and the driver
352+ * then can use the spi context to keep track of how much is left to do.
353+ */
354+
355+ /*
356+ * This function must be called at the start of a transfer by the driver
357+ * to initialize the spi context fields for tracking the progress.
358+ */
290359static inline
291360void spi_context_buffers_setup (struct spi_context * ctx ,
292361 const struct spi_buf_set * tx_bufs ,
@@ -322,8 +391,10 @@ void spi_context_buffers_setup(struct spi_context *ctx,
322391}
323392
324393/*
325- * Note: dfs is the number of bytes needed to store a data frame,
326- * while len is the number of data frames sent.
394+ * Should be called to update the tracking of TX being completed.
395+ *
396+ * Parameter "dfs" is the number of bytes needed to store a data frame.
397+ * Parameter "len" is the number of data frames of TX that were sent.
327398 */
328399static ALWAYS_INLINE
329400void spi_context_update_tx (struct spi_context * ctx , uint8_t dfs , uint32_t len )
@@ -353,21 +424,29 @@ void spi_context_update_tx(struct spi_context *ctx, uint8_t dfs, uint32_t len)
353424 LOG_DBG ("tx buf/len %p/%zu" , (void * )ctx -> tx_buf , ctx -> tx_len );
354425}
355426
427+ /* Returns true if there is still TX buffers left in the spi_buf_set
428+ * even if they are "null" (nop) buffers.
429+ */
356430static ALWAYS_INLINE
357431bool spi_context_tx_on (struct spi_context * ctx )
358432{
359433 return !!(ctx -> tx_len );
360434}
361435
436+ /* Similar to spi_context_tx_on, but only returns true if the current buffer is
437+ * not a null/NOP placeholder.
438+ */
362439static ALWAYS_INLINE
363440bool spi_context_tx_buf_on (struct spi_context * ctx )
364441{
365442 return !!(ctx -> tx_buf && ctx -> tx_len );
366443}
367444
368445/*
369- * Note: dfs is the number of bytes needed to store a data frame,
370- * while len is the number of data frames received.
446+ * Should be called to update the tracking of RX being completed.
447+ *
448+ * @param dfs is the number of bytes needed to store a data frame.
449+ * @param len is the number of data frames of RX that were received.
371450 */
372451static ALWAYS_INLINE
373452void spi_context_update_rx (struct spi_context * ctx , uint8_t dfs , uint32_t len )
@@ -404,12 +483,18 @@ void spi_context_update_rx(struct spi_context *ctx, uint8_t dfs, uint32_t len)
404483 LOG_DBG ("rx buf/len %p/%zu" , (void * )ctx -> rx_buf , ctx -> rx_len );
405484}
406485
486+ /* Returns true if there is still RX buffers left in the spi_buf_set
487+ * even if they are "null" (nop) buffers.
488+ */
407489static ALWAYS_INLINE
408490bool spi_context_rx_on (struct spi_context * ctx )
409491{
410492 return !!(ctx -> rx_len );
411493}
412494
495+ /* Similar to spi_context_rx_on, but only returns true if the current buffer is
496+ * not a null/NOP placeholder.
497+ */
413498static ALWAYS_INLINE
414499bool spi_context_rx_buf_on (struct spi_context * ctx )
415500{
@@ -420,6 +505,10 @@ bool spi_context_rx_buf_on(struct spi_context *ctx)
420505 * Returns the maximum length of a transfer for which all currently active
421506 * directions have a continuous buffer, i.e. the maximum SPI transfer that
422507 * can be done with DMA that handles only non-scattered buffers.
508+ *
509+ * In other words, returns the length of the smaller of the current RX or current TX buffer.
510+ * Except if either RX or TX buf length is 0, returns the length of the other.
511+ * And if both are 0 then will return 0 and should indicate transfer completion.
423512 */
424513static inline size_t spi_context_max_continuous_chunk (struct spi_context * ctx )
425514{
@@ -432,11 +521,13 @@ static inline size_t spi_context_max_continuous_chunk(struct spi_context *ctx)
432521 return MIN (ctx -> tx_len , ctx -> rx_len );
433522}
434523
524+ /* Returns the length of the longer of the current RX or current TX buffer. */
435525static inline size_t spi_context_longest_current_buf (struct spi_context * ctx )
436526{
437527 return ctx -> tx_len > ctx -> rx_len ? ctx -> tx_len : ctx -> rx_len ;
438528}
439529
530+ /* Helper function, not intended to be used by drivers directly */
440531static size_t spi_context_count_tx_buf_lens (struct spi_context * ctx , size_t start_index )
441532{
442533 size_t n ;
@@ -449,6 +540,7 @@ static size_t spi_context_count_tx_buf_lens(struct spi_context *ctx, size_t star
449540 return total_len ;
450541}
451542
543+ /* Helper function, not intended to be used by drivers directly */
452544static size_t spi_context_count_rx_buf_lens (struct spi_context * ctx , size_t start_index )
453545{
454546 size_t n ;
@@ -462,21 +554,33 @@ static size_t spi_context_count_rx_buf_lens(struct spi_context *ctx, size_t star
462554}
463555
464556
557+ /* Returns the length of the sum of the remaining TX buffers in the buf set, including
558+ * the current buffer in the total.
559+ */
465560static inline size_t spi_context_total_tx_len (struct spi_context * ctx )
466561{
467562 return spi_context_count_tx_buf_lens (ctx , 0 );
468563}
469564
565+ /* Returns the length of the sum of the remaining RX buffers in the buf set, including
566+ * the current buffer in the total.
567+ */
470568static inline size_t spi_context_total_rx_len (struct spi_context * ctx )
471569{
472570 return spi_context_count_rx_buf_lens (ctx , 0 );
473571}
474572
573+ /* Similar to spi_context_total_tx_len, except does not count words that have been finished
574+ * in the current buffer, ie only including what is remaining in the current buffer in the sum.
575+ */
475576static inline size_t spi_context_tx_len_left (struct spi_context * ctx )
476577{
477578 return ctx -> tx_len + spi_context_count_tx_buf_lens (ctx , 1 );
478579}
479580
581+ /* Similar to spi_context_total_rx_len, except does not count words that have been finished
582+ * in the current buffer, ie only including what is remaining in the current buffer in the sum.
583+ */
480584static inline size_t spi_context_rx_len_left (struct spi_context * ctx )
481585{
482586 return ctx -> rx_len + spi_context_count_rx_buf_lens (ctx , 1 );
0 commit comments