From 6008e7ee24e1593eeff7cc26c1dda5a2366559f8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mart=C3=AD=20Bol=C3=ADvar?= <marti.bolivar@nordicsemi.no>
Date: Wed, 4 Nov 2020 15:23:48 -0800
Subject: [PATCH] devicetree: spi: add CS GPIO controller accessors
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Add two new macros for getting the chip select GPIO controller from a
SPI device:

- DT_SPI_DEV_CS_GPIOS_CTLR()
- DT_INST_SPI_DEV_CS_GPIOS_CTLR()

Now that we can get struct device pointers at build time directly from
a devicetree node identifier, it's useful to be able to get a
node_id for a CS GPIO controller from the SPI device, because that's
necessary for setting up the gpio_dev in a struct spi_cs_control.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
---
 include/devicetree/spi.h            | 44 +++++++++++++++++++++++++++++
 tests/lib/devicetree/api/src/main.c |  8 ++++++
 2 files changed, 52 insertions(+)

diff --git a/include/devicetree/spi.h b/include/devicetree/spi.h
index d97b6c3c396a..bbdc5f31ab9c 100644
--- ncs/zephyr/include/devicetree/spi.h
+++ ncs/zephyr/include/devicetree/spi.h
@@ -116,6 +116,40 @@ extern "C" {
  */
 #define DT_SPI_DEV_HAS_CS_GPIOS(spi_dev) DT_SPI_HAS_CS_GPIOS(DT_BUS(spi_dev))
 
+/**
+ * @brief Get a SPI device's chip select GPIO controller's node identifier
+ *
+ * Example devicetree fragment:
+ *
+ *     gpio1: gpio@... { ... };
+ *
+ *     gpio2: gpio@... { ... };
+ *
+ *     spi@... {
+ *             compatible = "vnd,spi";
+ *             cs-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>,
+ *                        <&gpio2 20 GPIO_ACTIVE_LOW>;
+ *
+ *             a: spi-dev-a@0 {
+ *                     reg = <0>;
+ *             };
+ *
+ *             b: spi-dev-b@1 {
+ *                     reg = <1>;
+ *             };
+ *     };
+ *
+ * Example usage:
+ *
+ *     DT_SPI_DEV_CS_GPIOS_CTLR(DT_NODELABEL(a)) // DT_NODELABEL(gpio1)
+ *     DT_SPI_DEV_CS_GPIOS_CTLR(DT_NODELABEL(b)) // DT_NODELABEL(gpio2)
+ *
+ * @param spi_dev a SPI device node identifier
+ * @return node identifier for spi_dev's chip select GPIO controller
+ */
+#define DT_SPI_DEV_CS_GPIOS_CTLR(spi_dev) \
+	DT_PHANDLE_BY_IDX(DT_BUS(spi_dev), cs_gpios, DT_REG_ADDR(spi_dev))
+
 /**
  * @brief Get a SPI device's chip select GPIO controller's label property
  *
@@ -225,6 +259,16 @@ extern "C" {
 #define DT_INST_SPI_DEV_HAS_CS_GPIOS(inst) \
 	DT_SPI_DEV_HAS_CS_GPIOS(DT_DRV_INST(inst))
 
+/**
+ * @brief Get GPIO controller node identifier for a SPI device instance
+ * This is equivalent to DT_SPI_DEV_CS_GPIOS_CTLR(DT_DRV_INST(inst)).
+ * @param inst DT_DRV_COMPAT instance number
+ * @return node identifier for instance's chip select GPIO controller
+ * @see DT_SPI_DEV_CS_GPIOS_CTLR()
+ */
+#define DT_INST_SPI_DEV_CS_GPIOS_CTLR(inst) \
+	DT_SPI_DEV_CS_GPIOS_CTLR(DT_DRV_INST(inst))
+
 /**
  * @brief Get GPIO controller name for a SPI device instance
  * This is equivalent to DT_SPI_DEV_CS_GPIOS_LABEL(DT_DRV_INST(inst)).
diff --git a/tests/lib/devicetree/api/src/main.c b/tests/lib/devicetree/api/src/main.c
index cb13c5977c2d..5b051b4ad176 100644
--- ncs/zephyr/tests/lib/devicetree/api/src/main.c
+++ ncs/zephyr/tests/lib/devicetree/api/src/main.c
@@ -298,6 +298,11 @@ static void test_bus(void)
 	 */
 	zassert_equal(DT_INST_SPI_DEV_HAS_CS_GPIOS(0), 1, "");
 
+#define CTLR_NODE DT_INST_SPI_DEV_CS_GPIOS_CTLR(0)
+	zassert_true(DT_SAME_NODE(CTLR_NODE, DT_NODELABEL(test_gpio_1)) ||
+		     DT_SAME_NODE(CTLR_NODE, DT_NODELABEL(test_gpio_2)), "");
+#undef CTLR_NODE
+
 	zassert_true(!strncmp(gpio, DT_INST_SPI_DEV_CS_GPIOS_LABEL(0),
 			      strlen(gpio)), "");
 
@@ -1267,6 +1272,9 @@ static void test_cs_gpios(void)
 	zassert_equal(DT_SPI_HAS_CS_GPIOS(TEST_SPI), 1, "");
 	zassert_equal(DT_SPI_NUM_CS_GPIOS(TEST_SPI), 3, "");
 
+	zassert_equal(DT_DEP_ORD(DT_SPI_DEV_CS_GPIOS_CTLR(TEST_SPI_DEV_0)),
+		      DT_DEP_ORD(DT_NODELABEL(test_gpio_1)),
+		     "dev 0 cs gpio controller");
 	zassert_true(!strcmp(DT_SPI_DEV_CS_GPIOS_LABEL(TEST_SPI_DEV_0),
 			     "TEST_GPIO_1"), "");
 	zassert_equal(DT_SPI_DEV_CS_GPIOS_PIN(TEST_SPI_DEV_0), 0x10, "");
