1 /**
2  * @file
3  * @brief SPI Devicetree macro public API header file.
4  */
5 
6 /*
7  * Copyright (c) 2020 Nordic Semiconductor
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #ifndef ZEPHYR_INCLUDE_DEVICETREE_SPI_H_
13 #define ZEPHYR_INCLUDE_DEVICETREE_SPI_H_
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /**
20  * @defgroup devicetree-spi Devicetree SPI API
21  * @ingroup devicetree
22  * @{
23  */
24 
25 /**
26  * @brief Does a SPI controller node have chip select GPIOs configured?
27  *
28  * SPI bus controllers use the "cs-gpios" property for configuring
29  * chip select GPIOs. Its value is a phandle-array which specifies the
30  * chip select lines.
31  *
32  * Example devicetree fragment:
33  *
34  *     spi1: spi@... {
35  *             compatible = "vnd,spi";
36  *             cs-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>,
37  *                        <&gpio2 20 GPIO_ACTIVE_LOW>;
38  *     };
39  *
40  *     spi2: spi@... {
41  *             compatible = "vnd,spi";
42  *     };
43  *
44  * Example usage:
45  *
46  *     DT_SPI_HAS_CS_GPIOS(DT_NODELABEL(spi1)) // 1
47  *     DT_SPI_HAS_CS_GPIOS(DT_NODELABEL(spi2)) // 0
48  *
49  * @param spi a SPI bus controller node identifier
50  * @return 1 if "spi" has a cs-gpios property, 0 otherwise
51  */
52 #define DT_SPI_HAS_CS_GPIOS(spi) DT_NODE_HAS_PROP(spi, cs_gpios)
53 
54 /**
55  * @brief Number of chip select GPIOs in a SPI controller's cs-gpios property
56  *
57  * Example devicetree fragment:
58  *
59  *     spi1: spi@... {
60  *             compatible = "vnd,spi";
61  *             cs-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>,
62  *                        <&gpio2 20 GPIO_ACTIVE_LOW>;
63  *     };
64  *
65  *     spi2: spi@... {
66  *             compatible = "vnd,spi";
67  *     };
68  *
69  * Example usage:
70  *
71  *     DT_SPI_NUM_CS_GPIOS(DT_NODELABEL(spi1)) // 2
72  *     DT_SPI_NUM_CS_GPIOS(DT_NODELABEL(spi2)) // 0
73  *
74  * @param spi a SPI bus controller node identifier
75  * @return Logical length of spi's cs-gpios property, or 0 if "spi" doesn't
76  *         have a cs-gpios property
77  */
78 #define DT_SPI_NUM_CS_GPIOS(spi) \
79 	COND_CODE_1(DT_SPI_HAS_CS_GPIOS(spi), \
80 		    (DT_PROP_LEN(spi, cs_gpios)), (0))
81 
82 /**
83  * @brief Does a SPI device have a chip select line configured?
84  * Example devicetree fragment:
85  *
86  *     spi1: spi@... {
87  *             compatible = "vnd,spi";
88  *             cs-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>,
89  *                        <&gpio2 20 GPIO_ACTIVE_LOW>;
90  *
91  *             a: spi-dev-a@0 {
92  *                     reg = <0>;
93  *             };
94  *
95  *             b: spi-dev-b@1 {
96  *                     reg = <1>;
97  *             };
98  *     };
99  *
100  *     spi2: spi@... {
101  *             compatible = "vnd,spi";
102  *             c: spi-dev-c@0 {
103  *                     reg = <0>;
104  *             };
105  *     };
106  *
107  * Example usage:
108  *
109  *     DT_SPI_DEV_HAS_CS_GPIOS(DT_NODELABEL(a)) // 1
110  *     DT_SPI_DEV_HAS_CS_GPIOS(DT_NODELABEL(b)) // 1
111  *     DT_SPI_DEV_HAS_CS_GPIOS(DT_NODELABEL(c)) // 0
112  *
113  * @param spi_dev a SPI device node identifier
114  * @return 1 if spi_dev's bus node DT_BUS(spi_dev) has a chip select
115  *         pin at index DT_REG_ADDR(spi_dev), 0 otherwise
116  */
117 #define DT_SPI_DEV_HAS_CS_GPIOS(spi_dev) DT_SPI_HAS_CS_GPIOS(DT_BUS(spi_dev))
118 
119 /**
120  * @brief Get a SPI device's chip select GPIO controller's node identifier
121  *
122  * Example devicetree fragment:
123  *
124  *     gpio1: gpio@... { ... };
125  *
126  *     gpio2: gpio@... { ... };
127  *
128  *     spi@... {
129  *             compatible = "vnd,spi";
130  *             cs-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>,
131  *                        <&gpio2 20 GPIO_ACTIVE_LOW>;
132  *
133  *             a: spi-dev-a@0 {
134  *                     reg = <0>;
135  *             };
136  *
137  *             b: spi-dev-b@1 {
138  *                     reg = <1>;
139  *             };
140  *     };
141  *
142  * Example usage:
143  *
144  *     DT_SPI_DEV_CS_GPIOS_CTLR(DT_NODELABEL(a)) // DT_NODELABEL(gpio1)
145  *     DT_SPI_DEV_CS_GPIOS_CTLR(DT_NODELABEL(b)) // DT_NODELABEL(gpio2)
146  *
147  * @param spi_dev a SPI device node identifier
148  * @return node identifier for spi_dev's chip select GPIO controller
149  */
150 #define DT_SPI_DEV_CS_GPIOS_CTLR(spi_dev) \
151 	DT_GPIO_CTLR_BY_IDX(DT_BUS(spi_dev), cs_gpios, DT_REG_ADDR_RAW(spi_dev))
152 
153 /**
154  * @brief Get a SPI device's chip select GPIO pin number
155  *
156  * It's an error if the GPIO specifier for spi_dev's entry in its
157  * bus node's cs-gpios property has no pin cell.
158  *
159  * Example devicetree fragment:
160  *
161  *     spi1: spi@... {
162  *             compatible = "vnd,spi";
163  *             cs-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>,
164  *                        <&gpio2 20 GPIO_ACTIVE_LOW>;
165  *
166  *             a: spi-dev-a@0 {
167  *                     reg = <0>;
168  *             };
169  *
170  *             b: spi-dev-b@1 {
171  *                     reg = <1>;
172  *             };
173  *     };
174  *
175  * Example usage:
176  *
177  *     DT_SPI_DEV_CS_GPIOS_PIN(DT_NODELABEL(a)) // 10
178  *     DT_SPI_DEV_CS_GPIOS_PIN(DT_NODELABEL(b)) // 20
179  *
180  * @param spi_dev a SPI device node identifier
181  * @return pin number of spi_dev's chip select GPIO
182  */
183 #define DT_SPI_DEV_CS_GPIOS_PIN(spi_dev) \
184 	DT_GPIO_PIN_BY_IDX(DT_BUS(spi_dev), cs_gpios, DT_REG_ADDR_RAW(spi_dev))
185 
186 /**
187  * @brief Get a SPI device's chip select GPIO flags
188  *
189  * Example devicetree fragment:
190  *
191  *     spi1: spi@... {
192  *             compatible = "vnd,spi";
193  *             cs-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
194  *
195  *             a: spi-dev-a@0 {
196  *                     reg = <0>;
197  *             };
198  *     };
199  *
200  * Example usage:
201  *
202  *     DT_SPI_DEV_CS_GPIOS_FLAGS(DT_NODELABEL(a)) // GPIO_ACTIVE_LOW
203  *
204  * If the GPIO specifier for spi_dev's entry in its bus node's
205  * cs-gpios property has no flags cell, this expands to zero.
206  *
207  * @param spi_dev a SPI device node identifier
208  * @return flags value of spi_dev's chip select GPIO specifier, or
209  *         zero if there is none
210  */
211 #define DT_SPI_DEV_CS_GPIOS_FLAGS(spi_dev) \
212 	DT_GPIO_FLAGS_BY_IDX(DT_BUS(spi_dev), cs_gpios, DT_REG_ADDR_RAW(spi_dev))
213 
214 /**
215  * @brief Equivalent to DT_SPI_DEV_HAS_CS_GPIOS(DT_DRV_INST(inst)).
216  * @param inst DT_DRV_COMPAT instance number
217  * @return 1 if the instance's bus has a CS pin at index
218  *         DT_INST_REG_ADDR(inst), 0 otherwise
219  * @see DT_SPI_DEV_HAS_CS_GPIOS()
220  */
221 #define DT_INST_SPI_DEV_HAS_CS_GPIOS(inst) \
222 	DT_SPI_DEV_HAS_CS_GPIOS(DT_DRV_INST(inst))
223 
224 /**
225  * @brief Get GPIO controller node identifier for a SPI device instance
226  * This is equivalent to DT_SPI_DEV_CS_GPIOS_CTLR(DT_DRV_INST(inst)).
227  * @param inst DT_DRV_COMPAT instance number
228  * @return node identifier for instance's chip select GPIO controller
229  * @see DT_SPI_DEV_CS_GPIOS_CTLR()
230  */
231 #define DT_INST_SPI_DEV_CS_GPIOS_CTLR(inst) \
232 	DT_SPI_DEV_CS_GPIOS_CTLR(DT_DRV_INST(inst))
233 
234 /**
235  * @brief Equivalent to DT_SPI_DEV_CS_GPIOS_PIN(DT_DRV_INST(inst)).
236  * @param inst DT_DRV_COMPAT instance number
237  * @return pin number of the instance's chip select GPIO
238  * @see DT_SPI_DEV_CS_GPIOS_PIN()
239  */
240 #define DT_INST_SPI_DEV_CS_GPIOS_PIN(inst) \
241 	DT_SPI_DEV_CS_GPIOS_PIN(DT_DRV_INST(inst))
242 
243 /**
244  * @brief DT_SPI_DEV_CS_GPIOS_FLAGS(DT_DRV_INST(inst)).
245  * @param inst DT_DRV_COMPAT instance number
246  * @return flags value of the instance's chip select GPIO specifier,
247  *         or zero if there is none
248  * @see DT_SPI_DEV_CS_GPIOS_FLAGS()
249  */
250 #define DT_INST_SPI_DEV_CS_GPIOS_FLAGS(inst) \
251 	DT_SPI_DEV_CS_GPIOS_FLAGS(DT_DRV_INST(inst))
252 
253 /**
254  * @}
255  */
256 
257 #ifdef __cplusplus
258 }
259 #endif
260 
261 #endif  /* ZEPHYR_INCLUDE_DEVICETREE_SPI_H_ */
262