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