1 /* 2 * Copyright (c) 2020, Linaro Ltd. 3 * Copyright (c) 2021-2024, Gerson Fernando Budke <nandojve@gmail.com> 4 * 5 * SPDX-License-Identifier: Apache-2.0 6 */ 7 8 /** @file 9 * @brief Atmel SAM0 MCU family devicetree helper macros 10 */ 11 12 #ifndef _ATMEL_SAM0_DT_H_ 13 #define _ATMEL_SAM0_DT_H_ 14 15 /* clang-format off */ 16 17 #define ATMEL_SAM0_DT_INST_CELL_REG_ADDR_OFFSET(n, cell) \ 18 (volatile uint32_t *) \ 19 (DT_REG_ADDR(DT_INST_PHANDLE_BY_NAME(n, clocks, cell)) + \ 20 DT_INST_CLOCKS_CELL_BY_NAME(n, cell, offset)) 21 22 #define ATMEL_SAM0_DT_INST_CELL_PERIPH_MASK(n, name, cell) \ 23 BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, name, cell)) 24 25 /* Helper macro to get register address that control peripheral clock 26 * enable bit. 27 */ 28 #define ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n) \ 29 COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(mclk)), \ 30 (ATMEL_SAM0_DT_INST_CELL_REG_ADDR_OFFSET(n, mclk)), \ 31 (ATMEL_SAM0_DT_INST_CELL_REG_ADDR_OFFSET(n, pm))) 32 33 /* Helper macro to get peripheral clock bit mask. 34 */ 35 #define ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, cell) \ 36 COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(mclk)), \ 37 (ATMEL_SAM0_DT_INST_CELL_PERIPH_MASK(n, mclk, cell)), \ 38 (ATMEL_SAM0_DT_INST_CELL_PERIPH_MASK(n, pm, cell))) 39 40 /* Helper macros for use with ATMEL SAM0 DMAC controller 41 * return 0xff as default value if there is no 'dmas' property 42 */ 43 #define ATMEL_SAM0_DT_INST_DMA_CELL(n, name, cell) \ 44 COND_CODE_1(DT_INST_NODE_HAS_PROP(n, dmas), \ 45 (DT_INST_DMAS_CELL_BY_NAME(n, name, cell)), \ 46 (0xff)) 47 #define ATMEL_SAM0_DT_INST_DMA_TRIGSRC(n, name) \ 48 ATMEL_SAM0_DT_INST_DMA_CELL(n, name, trigsrc) 49 #define ATMEL_SAM0_DT_INST_DMA_CHANNEL(n, name) \ 50 ATMEL_SAM0_DT_INST_DMA_CELL(n, name, channel) 51 #define ATMEL_SAM0_DT_INST_DMA_CTLR(n, name) \ 52 COND_CODE_1(DT_INST_NODE_HAS_PROP(n, dmas), \ 53 (DT_INST_DMAS_CTLR_BY_NAME(n, name)), \ 54 (DT_INVALID_NODE)) 55 56 57 /* Use to check if a sercom 'n' is enabled for a given 'compat' */ 58 #define ATMEL_SAM0_DT_SERCOM_CHECK(n, compat) \ 59 DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(sercom##n), compat, okay) 60 61 /* Use to check if TCC 'n' is enabled for a given 'compat' */ 62 #define ATMEL_SAM0_DT_TCC_CHECK(n, compat) \ 63 DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(tcc##n), compat, okay) 64 65 /* Common macro for use to set HCLK_FREQ_HZ */ 66 #define ATMEL_SAM0_DT_CPU_CLK_FREQ_HZ \ 67 DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) 68 69 /** 70 * @brief Test if a node has a atmel,assigned-clocks phandle-array property at 71 * a given index. 72 * 73 * This expands to 1 if the given index is valid atmel,assigned-clocks property 74 * phandle-array index. Otherwise, it expands to 0. 75 * 76 * Example devicetree fragment: 77 * 78 * n1: node-1 { 79 * atmel,assigned-clocks = <...>, <...>; 80 * }; 81 * 82 * n2: node-2 { 83 * atmel,assigned-clocks = <...>; 84 * }; 85 * 86 * Example usage: 87 * 88 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_HAS_IDX(DT_NODELABEL(n1), 0) // 1 89 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_HAS_IDX(DT_NODELABEL(n1), 1) // 1 90 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_HAS_IDX(DT_NODELABEL(n1), 2) // 0 91 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_HAS_IDX(DT_NODELABEL(n2), 1) // 0 92 * 93 * @param node_id node identifier; may or may not have any atmel,assigned-clocks 94 * property 95 * @param idx index of a atmel,assigned-clocks property phandle-array whose 96 * existence to check 97 * @return 1 if the index exists, 0 otherwise 98 */ 99 #define ATMEL_SAM0_DT_ASSIGNED_CLOCKS_HAS_IDX(node_id, idx) \ 100 DT_PROP_HAS_IDX(node_id, atmel_assigned_clocks, idx) 101 102 /** 103 * @brief Test if a node has a clock-names array property holds a given name 104 * 105 * This expands to 1 if the name is available as atmel,assigned-clocks-name array 106 * property cell. Otherwise, it expands to 0. 107 * 108 * Example devicetree fragment: 109 * 110 * n1: node-1 { 111 * atmel,assigned-clocks = <...>, <...>; 112 * atmel,assigned-clock-names = "alpha", "beta"; 113 * }; 114 * 115 * n2: node-2 { 116 * atmel,assigned-clocks = <...>; 117 * atmel,assigned-clock-names = "alpha"; 118 * }; 119 * 120 * Example usage: 121 * 122 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_HAS_NAME(DT_NODELABEL(n1), alpha) // 1 123 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_HAS_NAME(DT_NODELABEL(n1), beta) // 1 124 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_HAS_NAME(DT_NODELABEL(n2), beta) // 0 125 * 126 * @param node_id node identifier; may or may not have any clock-names property. 127 * @param name lowercase-and-underscores clock-names cell value name to check 128 * @return 1 if the atmel,assigned-clock name exists, 0 otherwise 129 */ 130 #define ATMEL_SAM0_DT_ASSIGNED_CLOCKS_HAS_NAME(node_id, name) \ 131 DT_PROP_HAS_NAME(node_id, atmel_assigned_clocks, name) 132 133 /** 134 * @brief Get the number of elements in a atmel,assigned-clocks property 135 * 136 * Example devicetree fragment: 137 * 138 * n1: node-1 { 139 * atmel,assigned-clocks = <&foo>, <&bar>; 140 * }; 141 * 142 * n2: node-2 { 143 * atmel,assigned-clocks = <&foo>; 144 * }; 145 * 146 * Example usage: 147 * 148 * ATMEL_SAM0_DT_NUM_ASSIGNED_CLOCKS(DT_NODELABEL(n1)) // 2 149 * ATMEL_SAM0_DT_NUM_ASSIGNED_CLOCKS(DT_NODELABEL(n2)) // 1 150 * 151 * @param node_id node identifier with a atmel,assigned-clocks property 152 * @return number of elements in the property 153 */ 154 #define ATMEL_SAM0_DT_NUM_ASSIGNED_CLOCKS(node_id) \ 155 DT_PROP_LEN(node_id, atmel_assigned_clocks) 156 157 158 /** 159 * @brief Get the node identifier for the controller phandle from a 160 * "atmel,assigned-clocks" phandle-array property at an index 161 * 162 * Example devicetree fragment: 163 * 164 * clk1: clock-controller@... { ... }; 165 * 166 * clk2: clock-controller@... { ... }; 167 * 168 * n: node { 169 * atmel,assigned-clocks = <&clk1 10 20>, <&clk2 30 40>; 170 * }; 171 * 172 * Example usage: 173 * 174 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(DT_NODELABEL(n), 0)) // DT_NODELABEL(clk1) 175 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(DT_NODELABEL(n), 1)) // DT_NODELABEL(clk2) 176 * 177 * @param node_id node identifier 178 * @param idx logical index into "atmel,assigned-clocks" 179 * @return the node identifier for the clock controller referenced at index "idx" 180 * @see DT_PHANDLE_BY_IDX() 181 */ 182 #define ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(node_id, idx) \ 183 DT_PHANDLE_BY_IDX(node_id, atmel_assigned_clocks, idx) 184 185 /** 186 * @brief Equivalent to ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(node_id, 0) 187 * @param node_id node identifier 188 * @return a node identifier for the atmel,assigned-clocks controller at index 0 189 * in "atmel,assigned-clocks" 190 * @see ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR_BY_IDX() 191 */ 192 #define ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR(node_id) \ 193 ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(node_id, 0) 194 195 /** 196 * @brief Get the node identifier for the controller phandle from a 197 * atmel,assigned-clocks phandle-array property by name 198 * 199 * Example devicetree fragment: 200 * 201 * clk1: clock-controller@... { ... }; 202 * 203 * clk2: clock-controller@... { ... }; 204 * 205 * n: node { 206 * atmel,assigned-clocks = <&clk1 10 20>, <&clk2 30 40>; 207 * atmel,assigned-clock-names = "alpha", "beta"; 208 * }; 209 * 210 * Example usage: 211 * 212 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR_BY_NAME(DT_NODELABEL(n), beta) // DT_NODELABEL(clk2) 213 * 214 * @param node_id node identifier 215 * @param name lowercase-and-underscores name of a atmel,assigned-clocks element 216 * as defined by the node's clock-names property 217 * @return the node identifier for the clock controller referenced by name 218 * @see DT_PHANDLE_BY_NAME() 219 */ 220 #define ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR_BY_NAME(node_id, name) \ 221 DT_PHANDLE_BY_NAME(node_id, atmel_assigned_clocks, name) 222 223 /** 224 * @brief Get a atmel,assigned-clock specifier's cell value at an index 225 * 226 * Example devicetree fragment: 227 * 228 * clk1: clock-controller@... { 229 * compatible = "vnd,clock"; 230 * #atmel,assigned-clock-cells = < 2 >; 231 * }; 232 * 233 * n: node { 234 * atmel,assigned-clocks = < &clk1 10 20 >, < &clk1 30 40 >; 235 * }; 236 * 237 * Bindings fragment for the vnd,clock compatible: 238 * 239 * atmel,assigned-clock-cells: 240 * - bus 241 * - bits 242 * 243 * Example usage: 244 * 245 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL_BY_IDX(DT_NODELABEL(n), 0, bus) // 10 246 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL_BY_IDX(DT_NODELABEL(n), 1, bits) // 40 247 * 248 * @param node_id node identifier for a node with a atmel,assigned-clocks property 249 * @param idx logical index into atmel,assigned-clocks property 250 * @param cell lowercase-and-underscores cell name 251 * @return the cell value at index "idx" 252 * @see DT_PHA_BY_IDX() 253 */ 254 #define ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL_BY_IDX(node_id, idx, cell) \ 255 DT_PHA_BY_IDX(node_id, atmel_assigned_clocks, idx, cell) 256 257 /** 258 * @brief Get a atmel,assigned-clock specifier's cell value by name 259 * 260 * Example devicetree fragment: 261 * 262 * clk1: clock-controller@... { 263 * compatible = "vnd,clock"; 264 * #atmel,assigned-clock-cells = < 2 >; 265 * }; 266 * 267 * n: node { 268 * atmel,assigned-clocks = < &clk1 10 20 >, < &clk1 30 40 >; 269 * clock-names = "alpha", "beta"; 270 * }; 271 * 272 * Bindings fragment for the vnd,clock compatible: 273 * 274 * atmel,assigned-clock-cells: 275 * - bus 276 * - bits 277 * 278 * Example usage: 279 * 280 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL_BY_NAME(DT_NODELABEL(n), alpha, bus) // 10 281 * ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL_BY_NAME(DT_NODELABEL(n), beta, bits) // 40 282 * 283 * @param node_id node identifier for a node with a atmel,assigned-clocks property 284 * @param name lowercase-and-underscores name of a atmel,assigned-clocks element 285 * as defined by the node's clock-names property 286 * @param cell lowercase-and-underscores cell name 287 * @return the cell value in the specifier at the named element 288 * @see DT_PHA_BY_NAME() 289 */ 290 #define ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL_BY_NAME(node_id, name, cell) \ 291 DT_PHA_BY_NAME(node_id, atmel_assigned_clocks, name, cell) 292 293 /** 294 * @brief Equivalent to ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL_BY_IDX(node_id, 0, cell) 295 * @param node_id node identifier for a node with a atmel,assigned-clocks property 296 * @param cell lowercase-and-underscores cell name 297 * @return the cell value at index 0 298 * @see ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL_BY_IDX() 299 */ 300 #define ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL(node_id, cell) \ 301 ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL_BY_IDX(node_id, 0, cell) 302 303 /** 304 * @brief Equivalent to ATMEL_SAM0_DT_ASSIGNED_CLOCKS_HAS_IDX(DT_DRV_INST(inst), idx) 305 * @param inst DT_DRV_COMPAT instance number; may or may not have any 306 * atmel,assigned-clocks property 307 * @param idx index of a atmel,assigned-clocks property phandle-array whose existence 308 * to check 309 * @return 1 if the index exists, 0 otherwise 310 */ 311 #define ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_HAS_IDX(inst, idx) \ 312 DT_ASSIGNED_CLOCKS_HAS_IDX(DT_DRV_INST(inst), idx) 313 314 /** 315 * @brief Equivalent to DT_CLOCK_HAS_NAME(DT_DRV_INST(inst), name) 316 * @param inst DT_DRV_COMPAT instance number; may or may not have any 317 * atmel,clock-names property. 318 * @param name lowercase-and-underscores clock-names cell value name to check 319 * @return 1 if the atmel,assigned-clock name exists, 0 otherwise 320 */ 321 #define ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_HAS_NAME(inst, name) \ 322 ATMEL_SAM0_DT_ASSIGNED_CLOCKS_HAS_NAME(DT_DRV_INST(inst), name) 323 324 /** 325 * @brief Equivalent to ATMEL_SAM0_DT_NUM_ASSIGNED_CLOCKS(DT_DRV_INST(inst)) 326 * @param inst instance number 327 * @return number of elements in the atmel,assigned-clocks property 328 */ 329 #define ATMEL_SAM0_DT_INST_NUM_ASSIGNED_CLOCKS(inst) \ 330 ATMEL_SAM0_DT_NUM_ASSIGNED_CLOCKS(DT_DRV_INST(inst)) 331 332 /** 333 * @brief Get the node identifier for the controller phandle from a 334 * "atmel,assigned-clocks" phandle-array property at an index 335 * 336 * @param inst instance number 337 * @param idx logical index into "atmel,assigned-clocks" 338 * @return the node identifier for the clock controller referenced at 339 * index "idx" 340 * @see ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR_BY_IDX() 341 */ 342 #define ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_CTLR_BY_IDX(inst, idx) \ 343 ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(DT_DRV_INST(inst), idx) 344 345 /** 346 * @brief Equivalent to ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_CTLR_BY_IDX(inst, 0) 347 * @param inst instance number 348 * @return a node identifier for the atmel,assigned-clocks controller at index 0 349 * in "atmel,assigned-clocks" 350 * @see ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR() 351 */ 352 #define ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_CTLR(inst) \ 353 ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_CTLR_BY_IDX(inst, 0) 354 355 /** 356 * @brief Get the node identifier for the controller phandle from a 357 * atmel,assigned-clocks phandle-array property by name 358 * 359 * @param inst instance number 360 * @param name lowercase-and-underscores name of a atmel,assigned-clocks element 361 * as defined by the node's atmel,assigned-clock-names property 362 * @return the node identifier for the clock controller referenced by 363 * the named element 364 * @see ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR_BY_NAME() 365 */ 366 #define ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_CTLR_BY_NAME(inst, name) \ 367 ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CTLR_BY_NAME(DT_DRV_INST(inst), name) 368 369 /** 370 * @brief Get a DT_DRV_COMPAT instance's atmel,assigned-clock specifier's cell 371 * value at an index 372 * @param inst DT_DRV_COMPAT instance number 373 * @param idx logical index into atmel,assigned-clocks property 374 * @param cell lowercase-and-underscores cell name 375 * @return the cell value at index "idx" 376 * @see ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL_BY_IDX() 377 */ 378 #define ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_CELL_BY_IDX(inst, idx, cell) \ 379 ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL_BY_IDX(DT_DRV_INST(inst), idx, cell) 380 381 /** 382 * @brief Get a DT_DRV_COMPAT instance's atmel,assigned-clock specifier's cell 383 * value by name 384 * @param inst DT_DRV_COMPAT instance number 385 * @param name lowercase-and-underscores name of a atmel,assigned-clocks element 386 * as defined by the node's atmel,assigned-clock-names property 387 * @param cell lowercase-and-underscores cell name 388 * @return the cell value in the specifier at the named element 389 * @see ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL_BY_NAME() 390 */ 391 #define ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(inst, name, cell) \ 392 ATMEL_SAM0_DT_ASSIGNED_CLOCKS_CELL_BY_NAME(DT_DRV_INST(inst), name, cell) 393 394 /** 395 * @brief Equivalent to ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_CELL_BY_IDX(inst, 0, cell) 396 * @param inst DT_DRV_COMPAT instance number 397 * @param cell lowercase-and-underscores cell name 398 * @return the value of the cell inside the specifier at index 0 399 */ 400 #define ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_CELL(inst, cell) \ 401 ATMEL_SAM0_DT_INST_ASSIGNED_CLOCKS_CELL_BY_IDX(inst, 0, cell) 402 403 /* clang-format on */ 404 405 #endif /* _ATMEL_SAM0_SOC_DT_H_ */ 406