Skip to content

Commit 0b843be

Browse files
decsnykartben
authored andcommitted
drivers: spi_context: Add comments for context
Personally I found this file hard to understand at first, but since now it is clear to me, I decided to put these comments with my understanding to help anyone else who needs to use these. Signed-off-by: Declan Snyder <[email protected]>
1 parent cccd961 commit 0b843be

File tree

1 file changed

+108
-4
lines changed

1 file changed

+108
-4
lines changed

drivers/spi/spi_context.h

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
*/
7883
static 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+
*/
8492
static 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+
*/
89102
static 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+
*/
111131
static 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)
132152
static inline size_t spi_context_total_tx_len(struct spi_context *ctx);
133153
static 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+
*/
135162
static 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+
*/
183216
static 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+
*/
215256
static 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 */
236278
static 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+
*/
255304
static 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+
*/
260313
static 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+
*/
271329
static 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+
*/
290359
static inline
291360
void 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
*/
328399
static ALWAYS_INLINE
329400
void 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+
*/
356430
static ALWAYS_INLINE
357431
bool 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+
*/
362439
static ALWAYS_INLINE
363440
bool 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
*/
372451
static ALWAYS_INLINE
373452
void 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+
*/
407489
static ALWAYS_INLINE
408490
bool 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+
*/
413498
static ALWAYS_INLINE
414499
bool 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
*/
424513
static 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. */
435525
static 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 */
440531
static 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 */
452544
static 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+
*/
465560
static 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+
*/
470568
static 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+
*/
475576
static 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+
*/
480584
static 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

Comments
 (0)