1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 /**
7  * @file Common soc.h include for Nordic nRF5 SoCs.
8  */
9 
10 #ifndef _ZEPHYR_SOC_ARM_NORDIC_NRF_SOC_NRF_COMMON_H_
11 #define _ZEPHYR_SOC_ARM_NORDIC_NRF_SOC_NRF_COMMON_H_
12 
13 #ifndef _ASMLANGUAGE
14 #include <nrfx.h>
15 #include <zephyr/devicetree.h>
16 #include <zephyr/toolchain.h>
17 
18 /**
19  * @brief Get a PSEL value out of a foo-gpios or foo-pin devicetree property
20  *
21  * Many Nordic bindings have 'foo-pin' properties to specify a pin
22  * configuration as a PSEL value directly instead of using a 'foo-gpios'
23  * <&gpioX Y flags> style controller phandle + GPIO specifier.
24  *
25  * It would be better to use 'foo-gpios' properties instead. This type
26  * of property is more in line with the recommended DT encoding for GPIOs.
27  *
28  * To allow for a smooth migration from 'foo-pin' to 'foo-gpios', this
29  * helper macro can be used to get a PSEL value out of the devicetree
30  * using whichever one of 'foo-gpios' or 'foo-pin' is in the DTS.
31  *
32  * Note that you can also use:
33  *
34  *   - NRF_DT_PSEL_CHECK_*() to check the property configuration at build time
35  *   - NRF_DT_GPIOS_TO_PSEL() if you only have a 'foo-gpios'
36  *
37  * @param node_id node identifier
38  * @param psel_prop lowercase-and-underscores old-style 'foo-pin' property
39  * @param gpios_prop new-style 'foo-gpios' property
40  * @param default_val the value returned if neither is set
41  * @return PSEL register value taken from psel_prop or gpios_prop, whichever
42  *         is present in the DTS. If gpios_prop is present, it is converted
43  *         to a PSEL register value first.
44  */
45 #define NRF_DT_PSEL(node_id, psel_prop, gpios_prop, default_val)	\
46 	COND_CODE_1(DT_NODE_HAS_PROP(node_id, psel_prop),		\
47 		    (DT_PROP(node_id, psel_prop)),			\
48 		    (COND_CODE_1(					\
49 			    DT_NODE_HAS_PROP(node_id, gpios_prop),	\
50 			    (NRF_DT_GPIOS_TO_PSEL(node_id,		\
51 						  gpios_prop)),		\
52 			    (default_val))))
53 
54 /**
55  * Error out the build if the devicetree node with identifier
56  * 'node_id' has both a legacy psel-style property and a gpios
57  * property.
58  *
59  * Otherwise, do nothing.
60  *
61  * @param node_id node identifier
62  * @param psel_prop lowercase-and-underscores PSEL style property
63  * @param psel_prop_name human-readable string name of psel_prop
64  * @param gpios_prop lowercase-and-underscores foo-gpios style property
65  * @param gpio_prop_name human-readable string name of gpios_prop
66  */
67 #define NRF_DT_PSEL_CHECK_NOT_BOTH(node_id, psel_prop, psel_prop_name,	\
68 				   gpios_prop, gpios_prop_name)		\
69 	BUILD_ASSERT(							\
70 		!(DT_NODE_HAS_PROP(node_id, psel_prop) &&		\
71 		  DT_NODE_HAS_PROP(node_id, gpios_prop)),		\
72 		"Devicetree node " DT_NODE_PATH(node_id)		\
73 		" has both of the " psel_prop_name			\
74 		" and " gpios_prop_name					\
75 		" properties set; you must remove one. "		\
76 		"Note: you can use /delete-property/ to delete properties.")
77 
78 /**
79  * Like NRF_DT_PSEL_CHECK_NOT_BOTH, but instead checks that exactly one
80  * of the properties is set.
81  */
82 #define NRF_DT_PSEL_CHECK_EXACTLY_ONE(node_id,				\
83 				      psel_prop, psel_prop_name,	\
84 				      gpios_prop, gpios_prop_name)	\
85 	BUILD_ASSERT(							\
86 		(DT_NODE_HAS_PROP(node_id, psel_prop) ^			\
87 		 DT_NODE_HAS_PROP(node_id, gpios_prop)),		\
88 		"Devicetree node " DT_NODE_PATH(node_id)		\
89 		" must have exactly one of the " psel_prop_name		\
90 		" and " gpios_prop_name					\
91 		" properties set. "					\
92 		"Note: you can use /delete-property/ to delete properties.")
93 
94 /**
95  * @brief Convert a devicetree GPIO phandle+specifier to PSEL value
96  *
97  * Various peripherals in nRF SoCs have pin select registers, which
98  * usually have PSEL in their names. The low bits of these registers
99  * generally look like this in the register map description:
100  *
101  *     Bit number     5 4 3 2 1 0
102  *     ID             B A A A A A
103  *
104  *     ID  Field  Value    Description
105  *     A   PIN    [0..31]  Pin number
106  *     B   PORT   [0..1]   Port number
107  *
108  * Examples:
109  *
110  * - pin P0.4 has "PSEL value" 4 (B=0 and A=4)
111  * - pin P1.5 has "PSEL value" 37 (B=1 and A=5)
112  *
113  * This macro converts a devicetree GPIO phandle array value
114  * "<&gpioX pin ...>" to a "PSEL value".
115  *
116  * Note: in Nordic SoC devicetrees, "gpio0" means P0, and "gpio1"
117  * means P1. This is encoded in the "port" property of each GPIO node.
118  *
119  * Examples:
120  *
121  *     foo: my-node {
122  *             tx-gpios = <&gpio0 4 ...>;
123  *             rx-gpios = <&gpio0 5 ...>, <&gpio1 5 ...>;
124  *     };
125  *
126  *     NRF_DT_GPIOS_TO_PSEL_BY_IDX(DT_NODELABEL(foo), tx_gpios, 0) // 0 + 4 = 4
127  *     NRF_DT_GPIOS_TO_PSEL_BY_IDX(DT_NODELABEL(foo), rx_gpios, 1) // 32 + 5 = 37
128  */
129 #define NRF_DT_GPIOS_TO_PSEL_BY_IDX(node_id, prop, idx)			\
130 	((DT_PROP_BY_PHANDLE_IDX(node_id, prop, idx, port) << 5) |	\
131 	 (DT_GPIO_PIN_BY_IDX(node_id, prop, idx) & 0x1F))
132 
133 
134 /**
135  * @brief Equivalent to NRF_DT_GPIOS_TO_PSEL_BY_IDX(node_id, prop, 0)
136  */
137 #define NRF_DT_GPIOS_TO_PSEL(node_id, prop)			\
138 	NRF_DT_GPIOS_TO_PSEL_BY_IDX(node_id, prop, 0)
139 
140 /**
141  * If the node has the property, expands to
142  * NRF_DT_GPIOS_TO_PSEL(node_id, prop). The default_value argument is
143  * not expanded in this case.
144  *
145  * Otherwise, expands to default_value.
146  */
147 #define NRF_DT_GPIOS_TO_PSEL_OR(node_id, prop, default_value)	\
148 	COND_CODE_1(DT_NODE_HAS_PROP(node_id, prop),		\
149 		    (NRF_DT_GPIOS_TO_PSEL(node_id, prop)),	\
150 		    (default_value))
151 
152 /**
153  * @brief Convert a devicetree GPIO phandle+specifier to GPIOTE instance number.
154  *
155  * Some of nRF SoCs may have more instances of GPIOTE.
156  * To handle this, we use the "gpiote-instance" property of the GPIO node.
157  *
158  * This macro converts a devicetree GPIO phandle array value
159  * "<&gpioX pin ...>" to a GPIOTE instance number.
160  *
161  * Examples:
162  *
163  *     &gpiote0 {
164  *             instance = <0>;
165  *     };
166  *
167  *     &gpiote20 {
168  *             instance = <20>;
169  *     };
170  *
171  *     &gpio0 {
172  *             gpiote-instance = <&gpiote0>;
173  *     }
174  *
175  *     &gpio1 {
176  *             gpiote-instance = <&gpiote20>;
177  *     }
178  *
179  *     foo: my-node {
180  *             tx-gpios = <&gpio0 4 ...>;
181  *             rx-gpios = <&gpio0 5 ...>, <&gpio1 5 ...>;
182  *     };
183  *
184  *     NRF_DT_GPIOTE_INST_BY_IDX(DT_NODELABEL(foo), tx_gpios, 0) // = 0
185  *     NRF_DT_GPIOTE_INST_BY_IDX(DT_NODELABEL(foo), rx_gpios, 1) // = 20
186  */
187 #define NRF_DT_GPIOTE_INST_BY_IDX(node_id, prop, idx)			\
188 	DT_PROP(DT_PHANDLE(DT_GPIO_CTLR_BY_IDX(node_id, prop, idx),	\
189 			   gpiote_instance),				\
190 		instance)
191 
192 /**
193  * @brief Equivalent to NRF_DT_GPIOTE_INST_BY_IDX(node_id, prop, 0)
194  */
195 #define NRF_DT_GPIOTE_INST(node_id, prop)				\
196 	NRF_DT_GPIOTE_INST_BY_IDX(node_id, prop, 0)
197 
198 /**
199  * Error out the build if 'prop' is set on node 'node_id' and
200  * DT_GPIO_CTLR(node_id, prop) is not an SoC GPIO controller,
201  * i.e. a node with compatible "nordic,nrf-gpio".
202  *
203  * Otherwise, do nothing.
204  *
205  * @param node_id node identifier
206  * @param prop lowercase-and-underscores PSEL style property
207  * @param prop_name human-readable string name for 'prop'
208  */
209 #define NRF_DT_CHECK_GPIO_CTLR_IS_SOC(node_id, prop, prop_name)		\
210 	COND_CODE_1(DT_NODE_HAS_PROP(node_id, prop),			\
211 		   (BUILD_ASSERT(DT_NODE_HAS_COMPAT(			\
212 					 DT_GPIO_CTLR(node_id, prop),	\
213 					 nordic_nrf_gpio),		\
214 				 "Devicetree node "			\
215 				 DT_NODE_PATH(node_id)			\
216 				 " property " prop_name			\
217 				 " must refer to a GPIO controller "	\
218 				 "with compatible nordic,nrf-gpio; "	\
219 				 "got "					\
220 				 DT_NODE_PATH(DT_GPIO_CTLR(node_id,	\
221 							   prop))	\
222 				 ", which does not have this "		\
223 				 "compatible")),			\
224 		    (BUILD_ASSERT(1,					\
225 				  "NRF_DT_CHECK_GPIO_CTLR_IS_SOC: OK")))
226 /* Note: allow a trailing ";" either way */
227 
228 /**
229  * Error out the build if CONFIG_PM_DEVICE=y and pinctrl-1 state (sleep) is not
230  * defined.
231  *
232  * @param node_id node identifier
233  */
234 #define NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(node_id)			       \
235 	BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE) ||			       \
236 		     DT_PINCTRL_HAS_NAME(node_id, sleep),		       \
237 		     DT_NODE_PATH(node_id) " defined without sleep state")
238 
239 #endif /* !_ASMLANGUAGE */
240 
241 #endif
242