diff --git a/include/drivers/spi.h b/include/drivers/spi.h
index 4d0539f7063..8044b535900 100644
--- a/include/drivers/spi.h
+++ b/include/drivers/spi.h
@@ -142,6 +142,79 @@ struct spi_cs_control {
gpio_dt_flags_t gpio_dt_flags;
};
+#ifndef __cplusplus
+/**
+ * @brief Initialize and get a pointer to a @p spi_cs_control from a
+ * devicetree node identifier
+ *
+ * This helper is useful for initializing a device on a SPI bus. It
+ * initializes a struct spi_cs_control and returns a pointer to it.
+ * Here, @p node_id is a node identifier for a SPI device, not a SPI
+ * controller.
+ *
+ * Example devicetree fragment:
+ *
+ * spi@... {
+ * cs-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
+ * spidev: spi-device@0 { ... };
+ * };
+ *
+ * Assume that @p gpio0 follows the standard convention for specifying
+ * GPIOs, i.e. it has the following in its binding:
+ *
+ * gpio-cells:
+ * - pin
+ * - flags
+ *
+ * Example usage:
+ *
+ * struct spi_cs_control *ctrl =
+ * SPI_CS_CONTROL_PTR_DT(DT_NODELABEL(spidev), 2);
+ *
+ * This example is equivalent to:
+ *
+ * struct spi_cs_control *ctrl =
+ * &(struct spi_cs_control) {
+ * .gpio_dev = DEVICE_DT_GET(DT_NODELABEL(gpio0)),
+ * .delay = 2,
+ * .gpio_pin = 1,
+ * .gpio_dt_flags = GPIO_ACTIVE_LOW
+ * };
+ *
+ * This macro is not available in C++.
+ *
+ * @param node_id Devicetree node identifier for a device on a SPI bus
+ * @param delay_ The @p delay field to set in the @p spi_cs_control
+ * @return a pointer to the @p spi_cs_control structure
+ */
+#define SPI_CS_CONTROL_PTR_DT(node_id, delay_) \
+ (&(struct spi_cs_control) { \
+ .gpio_dev = DEVICE_DT_GET( \
+ DT_SPI_DEV_CS_GPIOS_CTLR(node_id)), \
+ .delay = (delay_), \
+ .gpio_pin = DT_SPI_DEV_CS_GPIOS_PIN(node_id), \
+ .gpio_dt_flags = DT_SPI_DEV_CS_GPIOS_FLAGS(node_id), \
+ })
+
+/**
+ * @brief Get a pointer to a @p spi_cs_control from a devicetree node
+ *
+ * This is equivalent to
+ * SPI_CS_CONTROL_PTR_DT(DT_DRV_INST(inst), delay).
+ *
+ * Therefore, @p DT_DRV_COMPAT must already be defined before using
+ * this macro.
+ *
+ * This macro is not available in C++.
+ *
+ * @param inst Devicetree node instance number
+ * @param delay_ The @p delay field to set in the @p spi_cs_control
+ * @return a pointer to the @p spi_cs_control structure
+ */
+#define SPI_CS_CONTROL_PTR_DT_INST(inst, delay_) \
+ SPI_CS_CONTROL_PTR_DT(DT_DRV_INST(inst), delay_)
+#endif
+
/**
* @brief SPI controller configuration structure
*
@@ -176,6 +249,54 @@ struct spi_config {
const struct spi_cs_control *cs;
};
+#ifndef __cplusplus
+/**
+ * @brief Structure initializer for spi_config from devicetree
+ *
+ * This helper macro expands to a static initializer for a struct
+ * spi_config by reading the relevant @p frequency, @p slave, and
+ * @p cs data from the devicetree.
+ *
+ * Important: the @p cs field is initialized using
+ * SPI_CS_CONTROL_PTR_DT(). The @p gpio_dev value pointed to by this
+ * structure must be checked using device_is_ready() before use.
+ *
+ * This macro is not available in C++.
+ *
+ * @param node_id Devicetree node identifier for the SPI device whose
+ * struct spi_config to create an initializer for
+ * @param operation_ the desired @p operation field in the struct spi_config
+ * @param delay_ the desired @p delay field in the struct spi_config's
+ * spi_cs_control, if there is one
+ */
+#define SPI_CONFIG_DT(node_id, operation_, delay_) \
+ { \
+ .frequency = DT_PROP(node_id, spi_max_frequency), \
+ .operation = (operation_), \
+ .slave = DT_REG_ADDR(node_id), \
+ .cs = COND_CODE_1( \
+ DT_SPI_DEV_HAS_CS_GPIOS(node_id), \
+ (SPI_CS_CONTROL_PTR_DT(node_id, delay_)), \
+ (NULL)), \
+ }
+
+/**
+ * @brief Structure initializer for spi_config from devicetree instance
+ *
+ * This is equivalent to
+ * SPI_CONFIG_DT(DT_DRV_INST(inst), operation_, delay_).
+ *
+ * This macro is not available in C++.
+ *
+ * @param inst Devicetree instance number
+ * @param operation_ the desired @p operation field in the struct spi_config
+ * @param delay_ the desired @p delay field in the struct spi_config's
+ * spi_cs_control, if there is one
+ */
+#define SPI_CONFIG_DT_INST(inst, operation_, delay_) \
+ SPI_CONFIG_DT(DT_DRV_INST(inst), operation_, delay_)
+#endif
+
/**
* @brief SPI buffer structure
*