@@ -75,17 +75,30 @@ struct spi_context {
75
75
}, \
76
76
._ctx_name.num_cs_gpios = DT_PROP_LEN_OR(_node_id, cs_gpios, 0),
77
77
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
+ */
78
83
static inline bool spi_context_configured (struct spi_context * ctx ,
79
84
const struct spi_config * config )
80
85
{
81
86
return !!(ctx -> config == config );
82
87
}
83
88
89
+ /* Returns true if the spi configuration stored for this context
90
+ * specifies a slave mode configuration, returns false otherwise
91
+ */
84
92
static inline bool spi_context_is_slave (struct spi_context * ctx )
85
93
{
86
94
return (ctx -> config -> operation & SPI_OP_MODE_SLAVE );
87
95
}
88
96
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
+ */
89
102
static inline void spi_context_lock (struct spi_context * ctx ,
90
103
bool asynchronous ,
91
104
spi_callback_t callback ,
@@ -108,6 +121,13 @@ static inline void spi_context_lock(struct spi_context *ctx,
108
121
#endif /* CONFIG_SPI_ASYNC */
109
122
}
110
123
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
+ */
111
131
static inline void spi_context_release (struct spi_context * ctx , int status )
112
132
{
113
133
#ifdef CONFIG_SPI_SLAVE
@@ -132,6 +152,13 @@ static inline void spi_context_release(struct spi_context *ctx, int status)
132
152
static inline size_t spi_context_total_tx_len (struct spi_context * ctx );
133
153
static inline size_t spi_context_total_rx_len (struct spi_context * ctx );
134
154
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
+ */
135
162
static inline int spi_context_wait_for_completion (struct spi_context * ctx )
136
163
{
137
164
int status = 0 ;
@@ -180,6 +207,12 @@ static inline int spi_context_wait_for_completion(struct spi_context *ctx)
180
207
return status ;
181
208
}
182
209
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
+ */
183
216
static inline void spi_context_complete (struct spi_context * ctx ,
184
217
const struct device * dev ,
185
218
int status )
@@ -212,6 +245,14 @@ static inline void spi_context_complete(struct spi_context *ctx,
212
245
#endif /* CONFIG_SPI_ASYNC */
213
246
}
214
247
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
+ */
215
256
static inline int spi_context_cs_configure_all (struct spi_context * ctx )
216
257
{
217
258
int ret ;
@@ -233,6 +274,7 @@ static inline int spi_context_cs_configure_all(struct spi_context *ctx)
233
274
return 0 ;
234
275
}
235
276
277
+ /* Helper function to control the GPIO CS, not meant to be used directly by drivers */
236
278
static inline void _spi_context_cs_control (struct spi_context * ctx ,
237
279
bool on , bool force_off )
238
280
{
@@ -252,11 +294,22 @@ static inline void _spi_context_cs_control(struct spi_context *ctx,
252
294
}
253
295
}
254
296
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
+ */
255
304
static inline void spi_context_cs_control (struct spi_context * ctx , bool on )
256
305
{
257
306
_spi_context_cs_control (ctx , on , false);
258
307
}
259
308
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
+ */
260
313
static inline void spi_context_unlock_unconditionally (struct spi_context * ctx )
261
314
{
262
315
/* Forcing CS to go to inactive status */
@@ -268,6 +321,11 @@ static inline void spi_context_unlock_unconditionally(struct spi_context *ctx)
268
321
}
269
322
}
270
323
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
+ */
271
329
static inline void * spi_context_get_next_buf (const struct spi_buf * * current ,
272
330
size_t * count ,
273
331
size_t * buf_len ,
@@ -287,6 +345,17 @@ static inline void *spi_context_get_next_buf(const struct spi_buf **current,
287
345
return NULL ;
288
346
}
289
347
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
+ */
290
359
static inline
291
360
void spi_context_buffers_setup (struct spi_context * ctx ,
292
361
const struct spi_buf_set * tx_bufs ,
@@ -322,8 +391,10 @@ void spi_context_buffers_setup(struct spi_context *ctx,
322
391
}
323
392
324
393
/*
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.
327
398
*/
328
399
static ALWAYS_INLINE
329
400
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)
353
424
LOG_DBG ("tx buf/len %p/%zu" , (void * )ctx -> tx_buf , ctx -> tx_len );
354
425
}
355
426
427
+ /* Returns true if there is still TX buffers left in the spi_buf_set
428
+ * even if they are "null" (nop) buffers.
429
+ */
356
430
static ALWAYS_INLINE
357
431
bool spi_context_tx_on (struct spi_context * ctx )
358
432
{
359
433
return !!(ctx -> tx_len );
360
434
}
361
435
436
+ /* Similar to spi_context_tx_on, but only returns true if the current buffer is
437
+ * not a null/NOP placeholder.
438
+ */
362
439
static ALWAYS_INLINE
363
440
bool spi_context_tx_buf_on (struct spi_context * ctx )
364
441
{
365
442
return !!(ctx -> tx_buf && ctx -> tx_len );
366
443
}
367
444
368
445
/*
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.
371
450
*/
372
451
static ALWAYS_INLINE
373
452
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)
404
483
LOG_DBG ("rx buf/len %p/%zu" , (void * )ctx -> rx_buf , ctx -> rx_len );
405
484
}
406
485
486
+ /* Returns true if there is still RX buffers left in the spi_buf_set
487
+ * even if they are "null" (nop) buffers.
488
+ */
407
489
static ALWAYS_INLINE
408
490
bool spi_context_rx_on (struct spi_context * ctx )
409
491
{
410
492
return !!(ctx -> rx_len );
411
493
}
412
494
495
+ /* Similar to spi_context_rx_on, but only returns true if the current buffer is
496
+ * not a null/NOP placeholder.
497
+ */
413
498
static ALWAYS_INLINE
414
499
bool spi_context_rx_buf_on (struct spi_context * ctx )
415
500
{
@@ -420,6 +505,10 @@ bool spi_context_rx_buf_on(struct spi_context *ctx)
420
505
* Returns the maximum length of a transfer for which all currently active
421
506
* directions have a continuous buffer, i.e. the maximum SPI transfer that
422
507
* 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.
423
512
*/
424
513
static inline size_t spi_context_max_continuous_chunk (struct spi_context * ctx )
425
514
{
@@ -432,11 +521,13 @@ static inline size_t spi_context_max_continuous_chunk(struct spi_context *ctx)
432
521
return MIN (ctx -> tx_len , ctx -> rx_len );
433
522
}
434
523
524
+ /* Returns the length of the longer of the current RX or current TX buffer. */
435
525
static inline size_t spi_context_longest_current_buf (struct spi_context * ctx )
436
526
{
437
527
return ctx -> tx_len > ctx -> rx_len ? ctx -> tx_len : ctx -> rx_len ;
438
528
}
439
529
530
+ /* Helper function, not intended to be used by drivers directly */
440
531
static size_t spi_context_count_tx_buf_lens (struct spi_context * ctx , size_t start_index )
441
532
{
442
533
size_t n ;
@@ -449,6 +540,7 @@ static size_t spi_context_count_tx_buf_lens(struct spi_context *ctx, size_t star
449
540
return total_len ;
450
541
}
451
542
543
+ /* Helper function, not intended to be used by drivers directly */
452
544
static size_t spi_context_count_rx_buf_lens (struct spi_context * ctx , size_t start_index )
453
545
{
454
546
size_t n ;
@@ -462,21 +554,33 @@ static size_t spi_context_count_rx_buf_lens(struct spi_context *ctx, size_t star
462
554
}
463
555
464
556
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
+ */
465
560
static inline size_t spi_context_total_tx_len (struct spi_context * ctx )
466
561
{
467
562
return spi_context_count_tx_buf_lens (ctx , 0 );
468
563
}
469
564
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
+ */
470
568
static inline size_t spi_context_total_rx_len (struct spi_context * ctx )
471
569
{
472
570
return spi_context_count_rx_buf_lens (ctx , 0 );
473
571
}
474
572
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
+ */
475
576
static inline size_t spi_context_tx_len_left (struct spi_context * ctx )
476
577
{
477
578
return ctx -> tx_len + spi_context_count_tx_buf_lens (ctx , 1 );
478
579
}
479
580
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
+ */
480
584
static inline size_t spi_context_rx_len_left (struct spi_context * ctx )
481
585
{
482
586
return ctx -> rx_len + spi_context_count_rx_buf_lens (ctx , 1 );
0 commit comments