18
18
* controllers.
19
19
* @defgroup spi_interface SPI
20
20
* @since 1.0
21
- * @version 1.0 .0
21
+ * @version 1.1 .0
22
22
* @ingroup io_interfaces
23
23
* @{
24
24
*/
@@ -242,19 +242,38 @@ extern "C" {
242
242
*
243
243
*/
244
244
struct spi_cs_control {
245
- /**
246
- * GPIO devicetree specification of CS GPIO.
247
- * The device pointer can be set to NULL to fully inhibit CS control if
248
- * necessary. The GPIO flags GPIO_ACTIVE_LOW/GPIO_ACTIVE_HIGH should be
249
- * equivalent to SPI_CS_ACTIVE_HIGH/SPI_CS_ACTIVE_LOW options in struct
250
- * spi_config.
251
- */
252
- struct gpio_dt_spec gpio ;
253
- /**
254
- * Delay in microseconds to wait before starting the
255
- * transmission and before releasing the CS line.
256
- */
257
- uint32_t delay ;
245
+ union {
246
+ struct {
247
+ /**
248
+ * GPIO devicetree specification of CS GPIO.
249
+ * The device pointer can be set to NULL to fully inhibit CS control if
250
+ * necessary. The GPIO flags GPIO_ACTIVE_LOW/GPIO_ACTIVE_HIGH should be
251
+ * equivalent to SPI_CS_ACTIVE_HIGH/SPI_CS_ACTIVE_LOW options in struct
252
+ * spi_config.
253
+ */
254
+ struct gpio_dt_spec gpio ;
255
+ /**
256
+ * Delay in microseconds to wait before starting the
257
+ * transmission and before releasing the CS line.
258
+ */
259
+ uint32_t delay ;
260
+ };
261
+ struct {
262
+ /**
263
+ * CS enable lead time, i.e. how long should the CS be asserted
264
+ * before the first clock. Specified in nanoseconds.
265
+ */
266
+ uint32_t setup_ns ;
267
+ /**
268
+ * CS enable lag time, i.e. how long should the CS be asserted
269
+ * after the last clock, before the CS de-asserts.
270
+ * Specified in nanoseconds.
271
+ */
272
+ uint32_t hold_ns ;
273
+ };
274
+ };
275
+ /* To keep track of which form of this struct is valid */
276
+ bool cs_is_gpio ;
258
277
};
259
278
260
279
/**
@@ -310,6 +329,26 @@ struct spi_cs_control {
310
329
#define SPI_CS_GPIOS_DT_SPEC_INST_GET (inst ) \
311
330
SPI_CS_GPIOS_DT_SPEC_GET(DT_DRV_INST(inst))
312
331
332
+ /** @cond INTERNAL_HIDDEN */
333
+ #define SPI_CS_CONTROL_MAX_DELAY (node_id ) \
334
+ MAX(DT_PROP_OR(node_id, spi_cs_setup_delay_ns, 0), \
335
+ DT_PROP_OR(node_id, spi_cs_hold_delay_ns, 0))
336
+
337
+
338
+ #define SPI_CS_CONTROL_INIT_GPIO (node_id , ...) \
339
+ .gpio = SPI_CS_GPIOS_DT_SPEC_GET(node_id), \
340
+ .delay = COND_CODE_1(IS_EMPTY(__VA_ARGS__), \
341
+ (DIV_ROUND_UP(SPI_CS_CONTROL_MAX_DELAY(node_id), 1000)), \
342
+ (__VA_ARGS__))
343
+
344
+ #define SPI_CS_CONTROL_INIT_NATIVE (node_id ) \
345
+ .setup_ns = DT_PROP_OR(node_id, spi_cs_setup_delay_ns, 0), \
346
+ .hold_ns = DT_PROP_OR(node_id, spi_cs_hold_delay_ns, 0),
347
+
348
+ #define SPI_DEPRECATE_DELAY_WARN \
349
+ __WARN("Delay parameter in SPI DT macros is deprecated, use DT prop instead")
350
+ /** @endcond */
351
+
313
352
/**
314
353
* @brief Initialize and get a pointer to a @p spi_cs_control from a
315
354
* devicetree node identifier
@@ -332,27 +371,34 @@ struct spi_cs_control {
332
371
*
333
372
* @code{.c}
334
373
* struct spi_cs_control ctrl =
335
- * SPI_CS_CONTROL_INIT(DT_NODELABEL(spidev), 2 );
374
+ * SPI_CS_CONTROL_INIT(DT_NODELABEL(spidev));
336
375
* @endcode
337
376
*
338
- * This example is equivalent to:
377
+ * This example is roughly equivalent to:
339
378
*
340
379
* @code{.c}
341
380
* struct spi_cs_control ctrl = {
342
381
* .gpio = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(spidev)),
343
- * .delay = 2,
382
+ * .delay = DT_PROP(node_id, cs_delay_ns) / 1000,
383
+ * .cs_is_gpio = true,
344
384
* };
345
385
* @endcode
346
386
*
387
+ * For non-gpio CS, the idea is similar but the lead and lag fields of the cs struct
388
+ * will be populated instead.
389
+ *
347
390
* @param node_id Devicetree node identifier for a device on a SPI bus
348
- * @param delay_ The @p delay field to set in the @p spi_cs_control
391
+ *
349
392
* @return a pointer to the @p spi_cs_control structure
350
393
*/
351
- #define SPI_CS_CONTROL_INIT (node_id , delay_ ) \
352
- { \
353
- .gpio = SPI_CS_GPIOS_DT_SPEC_GET(node_id), \
354
- .delay = (delay_), \
355
- }
394
+ #define SPI_CS_CONTROL_INIT (node_id , ...) \
395
+ { \
396
+ COND_CODE_0(IS_EMPTY(__VA_ARGS__), (SPI_DEPRECATE_DELAY_WARN), ()) \
397
+ .cs_is_gpio = DT_SPI_DEV_HAS_CS_GPIOS(node_id), \
398
+ COND_CODE_1(DT_SPI_DEV_HAS_CS_GPIOS(node_id), \
399
+ (SPI_CS_CONTROL_INIT_GPIO(node_id, __VA_ARGS__)), \
400
+ (SPI_CS_CONTROL_INIT_NATIVE(node_id))) \
401
+ }
356
402
357
403
/**
358
404
* @brief Get a pointer to a @p spi_cs_control from a devicetree node
@@ -364,11 +410,11 @@ struct spi_cs_control {
364
410
* this macro.
365
411
*
366
412
* @param inst Devicetree node instance number
367
- * @param delay_ The @p delay field to set in the @p spi_cs_control
413
+ *
368
414
* @return a pointer to the @p spi_cs_control structure
369
415
*/
370
- #define SPI_CS_CONTROL_INIT_INST (inst , delay_ ) \
371
- SPI_CS_CONTROL_INIT(DT_DRV_INST(inst), delay_ )
416
+ #define SPI_CS_CONTROL_INIT_INST (inst ) \
417
+ SPI_CS_CONTROL_INIT(DT_DRV_INST(inst))
372
418
373
419
/** @} */
374
420
@@ -432,10 +478,8 @@ struct spi_config {
432
478
* @param node_id Devicetree node identifier for the SPI device whose
433
479
* struct spi_config to create an initializer for
434
480
* @param operation_ the desired @p operation field in the struct spi_config
435
- * @param delay_ the desired @p delay field in the struct spi_config's
436
- * spi_cs_control, if there is one
437
481
*/
438
- #define SPI_CONFIG_DT (node_id , operation_ , delay_ ) \
482
+ #define SPI_CONFIG_DT (node_id , operation_ , ...) \
439
483
{ \
440
484
.frequency = DT_PROP(node_id, spi_max_frequency), \
441
485
.operation = (operation_) | \
@@ -445,22 +489,20 @@ struct spi_config {
445
489
COND_CODE_1(DT_PROP(node_id, spi_cpha), SPI_MODE_CPHA, (0)) | \
446
490
COND_CODE_1(DT_PROP(node_id, spi_hold_cs), SPI_HOLD_ON_CS, (0)), \
447
491
.slave = DT_REG_ADDR(node_id), \
448
- .cs = SPI_CS_CONTROL_INIT(node_id, delay_), \
492
+ .cs = SPI_CS_CONTROL_INIT(node_id, __VA_ARGS__), \
449
493
}
450
494
451
495
/**
452
496
* @brief Structure initializer for spi_config from devicetree instance
453
497
*
454
498
* This is equivalent to
455
- * <tt>SPI_CONFIG_DT(DT_DRV_INST(inst), operation_, delay_ )</tt>.
499
+ * <tt>SPI_CONFIG_DT(DT_DRV_INST(inst), operation_)</tt>.
456
500
*
457
501
* @param inst Devicetree instance number
458
502
* @param operation_ the desired @p operation field in the struct spi_config
459
- * @param delay_ the desired @p delay field in the struct spi_config's
460
- * spi_cs_control, if there is one
461
503
*/
462
- #define SPI_CONFIG_DT_INST (inst , operation_ , delay_ ) \
463
- SPI_CONFIG_DT(DT_DRV_INST(inst), operation_, delay_ )
504
+ #define SPI_CONFIG_DT_INST (inst , operation_ , ...) \
505
+ SPI_CONFIG_DT(DT_DRV_INST(inst), operation_, __VA_ARGS__ )
464
506
465
507
/**
466
508
* @brief Complete SPI DT information
@@ -486,28 +528,24 @@ struct spi_dt_spec {
486
528
* @param node_id Devicetree node identifier for the SPI device whose
487
529
* struct spi_dt_spec to create an initializer for
488
530
* @param operation_ the desired @p operation field in the struct spi_config
489
- * @param delay_ the desired @p delay field in the struct spi_config's
490
- * spi_cs_control, if there is one
491
531
*/
492
- #define SPI_DT_SPEC_GET (node_id , operation_ , delay_ ) \
493
- { \
494
- .bus = DEVICE_DT_GET(DT_BUS(node_id)), \
495
- .config = SPI_CONFIG_DT(node_id, operation_, delay_) \
532
+ #define SPI_DT_SPEC_GET (node_id , operation_ , ... ) \
533
+ { \
534
+ .bus = DEVICE_DT_GET(DT_BUS(node_id)), \
535
+ .config = SPI_CONFIG_DT(node_id, operation_, __VA_ARGS__), \
496
536
}
497
537
498
538
/**
499
539
* @brief Structure initializer for spi_dt_spec from devicetree instance
500
540
*
501
541
* This is equivalent to
502
- * <tt>SPI_DT_SPEC_GET(DT_DRV_INST(inst), operation_, delay_ )</tt>.
542
+ * <tt>SPI_DT_SPEC_GET(DT_DRV_INST(inst), operation_)</tt>.
503
543
*
504
544
* @param inst Devicetree instance number
505
545
* @param operation_ the desired @p operation field in the struct spi_config
506
- * @param delay_ the desired @p delay field in the struct spi_config's
507
- * spi_cs_control, if there is one
508
546
*/
509
- #define SPI_DT_SPEC_INST_GET (inst , operation_ , delay_ ) \
510
- SPI_DT_SPEC_GET(DT_DRV_INST(inst), operation_, delay_ )
547
+ #define SPI_DT_SPEC_INST_GET (inst , operation_ , ... ) \
548
+ SPI_DT_SPEC_GET(DT_DRV_INST(inst), operation_, __VA_ARGS__ )
511
549
512
550
/**
513
551
* @brief Value that will never compare true with any valid overrun character
@@ -863,7 +901,7 @@ __subsystem struct spi_driver_api {
863
901
*/
864
902
static inline bool spi_cs_is_gpio (const struct spi_config * config )
865
903
{
866
- return config -> cs .gpio . port != NULL ;
904
+ return config -> cs .cs_is_gpio ;
867
905
}
868
906
869
907
/**
@@ -1291,11 +1329,10 @@ extern const struct rtio_iodev_api spi_iodev_api;
1291
1329
* @param name Symbolic name to use for defining the iodev
1292
1330
* @param node_id Devicetree node identifier
1293
1331
* @param operation_ SPI operational mode
1294
- * @param delay_ Chip select delay in microseconds
1295
1332
*/
1296
- #define SPI_DT_IODEV_DEFINE (name , node_id , operation_ , delay_ ) \
1333
+ #define SPI_DT_IODEV_DEFINE (name , node_id , operation_ ) \
1297
1334
const struct spi_dt_spec _spi_dt_spec_##name = \
1298
- SPI_DT_SPEC_GET(node_id, operation_, delay_); \
1335
+ SPI_DT_SPEC_GET(node_id, operation_); \
1299
1336
RTIO_IODEV_DEFINE(name, &spi_iodev_api, (void *)&_spi_dt_spec_##name)
1300
1337
1301
1338
/**
0 commit comments