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 <devicetree.h>
16 #include <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 = <&gpio1 5 ...>;
124  *     };
125  *
126  *     NRF_DT_GPIOS_TO_PSEL(DT_NODELABEL(foo), tx_gpios) // 0 + 4 = 4
127  *     NRF_DT_GPIOS_TO_PSEL(DT_NODELABEL(foo), rx_gpios) // 32 + 5 = 37
128  */
129 #define NRF_DT_GPIOS_TO_PSEL(node_id, prop)				\
130 	(DT_GPIO_PIN(node_id, prop) +					\
131 	 (DT_PROP_BY_PHANDLE(node_id, prop, port) << 5))
132 
133 /**
134  * If the node has the property, expands to
135  * NRF_DT_GPIOS_TO_PSEL(node_id, prop). The default_value argument is
136  * not expanded in this case.
137  *
138  * Otherwise, expands to default_value.
139  */
140 #define NRF_DT_GPIOS_TO_PSEL_OR(node_id, prop, default_value)	\
141 	COND_CODE_1(DT_NODE_HAS_PROP(node_id, prop),		\
142 		    (NRF_DT_GPIOS_TO_PSEL(node_id, prop)),	\
143 		    (default_value))
144 
145 /**
146  * Error out the build if 'prop' is set on node 'node_id' and
147  * DT_GPIO_CTLR(node_id, prop) is not an SoC GPIO controller,
148  * i.e. a node with compatible "nordic,nrf-gpio".
149  *
150  * Otherwise, do nothing.
151  *
152  * @param node_id node identifier
153  * @param prop lowercase-and-underscores PSEL style property
154  * @param prop_name human-readable string name for 'prop'
155  */
156 #define NRF_DT_CHECK_GPIO_CTLR_IS_SOC(node_id, prop, prop_name)		\
157 	COND_CODE_1(DT_NODE_HAS_PROP(node_id, prop),			\
158 		   (BUILD_ASSERT(DT_NODE_HAS_COMPAT(			\
159 					 DT_GPIO_CTLR(node_id, prop),	\
160 					 nordic_nrf_gpio),		\
161 				 "Devicetree node "			\
162 				 DT_NODE_PATH(node_id)			\
163 				 " property " prop_name			\
164 				 " must refer to a GPIO controller "	\
165 				 "with compatible nordic,nrf-gpio; "	\
166 				 "got "					\
167 				 DT_NODE_PATH(DT_GPIO_CTLR(node_id,	\
168 							   prop))	\
169 				 ", which does not have this "		\
170 				 "compatible")),			\
171 		    (BUILD_ASSERT(1,					\
172 				  "NRF_DT_CHECK_GPIO_CTLR_IS_SOC: OK")))
173 /* Note: allow a trailing ";" either way */
174 
175 #endif /* !_ASMLANGUAGE */
176 
177 #endif
178