1 /*
2 * Copyright (c) 2020 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #ifndef ZEPHYR_INCLUDE_SYS_DEVICE_MMIO_H
7 #define ZEPHYR_INCLUDE_SYS_DEVICE_MMIO_H
8
9 #include <zephyr/toolchain.h>
10 #include <zephyr/linker/sections.h>
11
12 /**
13 * @defgroup device-mmio Device memory-mapped IO management
14 * @ingroup device_model
15 *
16 * Definitions and helper macros for managing driver memory-mapped
17 * input/output (MMIO) regions appropriately in either RAM or ROM.
18 *
19 * In most cases drivers will just want to include device.h, but
20 * including this separately may be needed for arch-level driver code
21 * which uses the DEVICE_MMIO_TOPLEVEL variants and including the
22 * main device.h would introduce header dependency loops due to that
23 * header's reliance on kernel.h.
24 *
25 * @{
26 */
27
28 /* Storing MMIO addresses in RAM is a system-wide decision based on
29 * configuration. This is just used to simplify some other definitions.
30 *
31 * If we have an MMU enabled, all physical MMIO regions must be mapped into
32 * the kernel's virtual address space at runtime, this is a hard requirement.
33 *
34 * If we have PCIE enabled, this does mean that non-PCIE drivers may waste
35 * a bit of RAM, but systems with PCI express are not RAM constrained.
36 */
37 #if defined(CONFIG_MMU) || defined(CONFIG_PCIE) || defined(CONFIG_EXTERNAL_ADDRESS_TRANSLATION)
38 #define DEVICE_MMIO_IS_IN_RAM
39 #endif
40
41 #if defined(CONFIG_EXTERNAL_ADDRESS_TRANSLATION)
42 #include <zephyr/drivers/mm/system_mm.h>
43 #endif
44
45 #ifndef _ASMLANGUAGE
46 #include <stdint.h>
47 #include <stddef.h>
48 #include <zephyr/kernel/mm.h>
49 #include <zephyr/sys/sys_io.h>
50
51 #ifdef DEVICE_MMIO_IS_IN_RAM
52 /* Store the physical address and size from DTS, we'll memory
53 * map into the virtual address space at runtime. This is not applicable
54 * to PCIe devices, which must query the bus for BAR information.
55 */
56 struct z_device_mmio_rom {
57 /** MMIO physical address */
58 uintptr_t phys_addr;
59
60 /** MMIO region size */
61 size_t size;
62 };
63
64 #define Z_DEVICE_MMIO_ROM_INITIALIZER(node_id) \
65 { \
66 .phys_addr = DT_REG_ADDR(node_id), \
67 .size = DT_REG_SIZE(node_id) \
68 }
69
70 #define Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(name, node_id) \
71 { \
72 .phys_addr = DT_REG_ADDR_BY_NAME(node_id, name), \
73 .size = DT_REG_SIZE_BY_NAME(node_id, name) \
74 }
75
76 /**
77 * Set linear address for device MMIO access
78 *
79 * This function sets the `virt_addr` parameter to the correct linear
80 * address for the MMIO region.
81 *
82 * If the MMU is enabled, mappings may be created in the page tables.
83 *
84 * Normally, only a caching mode needs to be set for the 'flags' parameter.
85 * The mapped linear address will have read-write access to supervisor mode.
86 *
87 * @see k_map()
88 *
89 * @param[out] virt_addr Output linear address storage location, most
90 * users will want some DEVICE_MMIO_RAM_PTR() value
91 * @param[in] phys_addr Physical address base of the MMIO region
92 * @param[in] size Size of the MMIO region
93 * @param[in] flags Caching mode and access flags, see K_MEM_CACHE_* and
94 * K_MEM_PERM_* macros
95 */
96 __boot_func
device_map(mm_reg_t * virt_addr,uintptr_t phys_addr,size_t size,uint32_t flags)97 static inline void device_map(mm_reg_t *virt_addr, uintptr_t phys_addr,
98 size_t size, uint32_t flags)
99 {
100 #ifdef CONFIG_MMU
101 /* Pass along flags and add that we want supervisor mode
102 * read-write access.
103 */
104 k_mem_map_phys_bare((uint8_t **)virt_addr, phys_addr, size,
105 flags | K_MEM_PERM_RW);
106 #else
107 ARG_UNUSED(size);
108 ARG_UNUSED(flags);
109 #ifdef CONFIG_EXTERNAL_ADDRESS_TRANSLATION
110 sys_mm_drv_page_phys_get((void *) phys_addr, virt_addr);
111 #else
112 *virt_addr = phys_addr;
113 #endif /* CONFIG_EXTERNAL_ADDRESS_TRANSLATION */
114 #endif /* CONFIG_MMU */
115 }
116 #else
117 /* No MMU or PCIe. Just store the address from DTS and treat as a linear
118 * address
119 */
120 struct z_device_mmio_rom {
121 /** MMIO linear address */
122 mm_reg_t addr;
123 };
124
125 #define Z_DEVICE_MMIO_ROM_INITIALIZER(node_id) \
126 { \
127 .addr = (mm_reg_t)DT_REG_ADDR_U64(node_id) \
128 }
129
130 #define Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(name, node_id) \
131 { \
132 .addr = (mm_reg_t)DT_REG_ADDR_BY_NAME_U64(node_id, name) \
133 }
134
135 #endif /* DEVICE_MMIO_IS_IN_RAM */
136 #endif /* !_ASMLANGUAGE */
137 /** @} */
138
139 /**
140 * @defgroup device-mmio-single Single MMIO region macros
141 * @ingroup device-mmio
142 *
143 * For drivers which need to manage just one MMIO region, the most common
144 * case.
145 *
146 * @{
147 */
148
149 /**
150 * @def DEVICE_MMIO_RAM
151 *
152 * Declare storage for MMIO information within a device's dev_data struct.
153 *
154 * This gets accessed by the DEVICE_MMIO_MAP() and DEVICE_MMIO_GET() macros.
155 *
156 * Depending on configuration, no memory may be reserved at all.
157 * This must be the first member of the data struct.
158 *
159 * There must be a corresponding DEVICE_MMIO_ROM in config_info if the
160 * physical address is known at build time, but may be omitted if not (such
161 * as with PCIe)
162 *
163 * Example for a driver named "foo":
164 *
165 * @code{.c}
166 *
167 * struct foo_driver_data {
168 * DEVICE_MMIO_RAM;
169 * int wibble;
170 * ...
171 * }
172 *
173 * @endcode
174 *
175 * No build-time initialization of this memory is necessary; it
176 * will be set up in the init function by DEVICE_MMIO_MAP().
177 *
178 * A pointer to this memory may be obtained with DEVICE_MMIO_RAM_PTR().
179 */
180 #ifdef DEVICE_MMIO_IS_IN_RAM
181 #define DEVICE_MMIO_RAM mm_reg_t _mmio
182 #else
183 #define DEVICE_MMIO_RAM
184 #endif
185
186 #ifdef DEVICE_MMIO_IS_IN_RAM
187 /**
188 * Return a pointer to the RAM-based storage area for a device's MMIO
189 * address.
190 *
191 * This is useful for the target MMIO address location when using
192 * device_map() directly.
193 *
194 * @param device device node_id object
195 * @retval mm_reg_t pointer to storage location
196 */
197 #define DEVICE_MMIO_RAM_PTR(device) (mm_reg_t *)((device)->data)
198 #endif /* DEVICE_MMIO_IS_IN_RAM */
199
200 /**
201 * @brief Declare storage for MMIO data within a device's config struct
202 *
203 * This gets accessed by DEVICE_MMIO_MAP() and DEVICE_MMIO_GET() macros.
204 *
205 * What gets stored here varies considerably by configuration.
206 * This must be the first member of the config struct. There must be
207 * a corresponding DEVICE_MMIO_RAM in data.
208 *
209 * This storage is not used if the device is PCIe and may be omitted.
210 *
211 * This should be initialized at build time with information from DTS
212 * using DEVICE_MMIO_ROM_INIT().
213 *
214 * A pointer to this memory may be obtained with DEVICE_MMIO_ROM_PTR().
215 *
216 * Example for a driver named "foo":
217 *
218 * @code{.c}
219 *
220 * struct foo_config {
221 * DEVICE_MMIO_ROM;
222 * int baz;
223 * ...
224 * }
225 *
226 * @endcode
227 *
228 * @see DEVICE_MMIO_ROM_INIT()
229 */
230 #define DEVICE_MMIO_ROM struct z_device_mmio_rom _mmio
231
232 /**
233 * Return a pointer to the ROM-based storage area for a device's MMIO
234 * information. This macro will not work properly if the ROM storage
235 * was omitted from the config struct declaration, and should not
236 * be used in this case.
237 *
238 * @param dev device instance object
239 * @retval struct device_mmio_rom * pointer to storage location
240 */
241 #define DEVICE_MMIO_ROM_PTR(dev) \
242 ((struct z_device_mmio_rom *)((dev)->config))
243
244 /**
245 * @brief Initialize a DEVICE_MMIO_ROM member
246 *
247 * Initialize MMIO-related information within a specific instance of
248 * a device config struct, using information from DTS.
249 *
250 * Example for a driver belonging to the "foo" subsystem:
251 *
252 * @code{.c}
253 *
254 * struct foo_config my_config = {
255 * DEVICE_MMIO_ROM_INIT(DT_DRV_INST(...)),
256 * .baz = 2;
257 * ...
258 * }
259 *
260 * @endcode
261 *
262 * @see DEVICE_MMIO_ROM()
263 *
264 * @param node_id DTS node_id
265 */
266 #define DEVICE_MMIO_ROM_INIT(node_id) \
267 ._mmio = Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
268
269 /**
270 * @def DEVICE_MMIO_MAP(device, flags)
271 *
272 * @brief Map MMIO memory into the address space
273 *
274 * This is not intended for PCIe devices; these must be probed at runtime
275 * and you will want to make a device_map() call directly, using
276 * DEVICE_MMIO_RAM_PTR() as the target virtual address location.
277 *
278 * The flags argument is currently used for caching mode, which should be
279 * one of the DEVICE_CACHE_* macros. Unused bits are reserved for future
280 * expansion.
281 *
282 * @param dev Device object instance
283 * @param flags cache mode flags
284 */
285 #ifdef DEVICE_MMIO_IS_IN_RAM
286 #define DEVICE_MMIO_MAP(dev, flags) \
287 device_map(DEVICE_MMIO_RAM_PTR(dev), \
288 DEVICE_MMIO_ROM_PTR(dev)->phys_addr, \
289 DEVICE_MMIO_ROM_PTR(dev)->size, \
290 (flags))
291 #else
292 #define DEVICE_MMIO_MAP(dev, flags) do { } while (false)
293 #endif
294
295 /**
296 * @def DEVICE_MMIO_GET(dev)
297 *
298 * @brief Obtain the MMIO address for a device
299 *
300 * For most microcontrollers MMIO addresses can be fixed values known at
301 * build time, and we can store this in device->config, residing in ROM.
302 *
303 * However, some devices can only know their MMIO addresses at runtime,
304 * because they need to be memory-mapped into the address space, enumerated
305 * from PCI, or both.
306 *
307 * This macro returns the linear address of the driver's MMIO region.
308 * This is for drivers which have exactly one MMIO region.
309 * A call must have been made to device_map() in the driver init function.
310 *
311 * @param dev Device object
312 * @return mm_reg_t linear address of the MMIO region
313 */
314 #ifdef DEVICE_MMIO_IS_IN_RAM
315 #define DEVICE_MMIO_GET(dev) (*DEVICE_MMIO_RAM_PTR(dev))
316 #else
317 #define DEVICE_MMIO_GET(dev) (DEVICE_MMIO_ROM_PTR(dev)->addr)
318 #endif
319 /** @} */
320
321 /**
322 * @defgroup device-mmio-named Named MMIO region macros
323 * @ingroup device-mmio
324 *
325 * For drivers which need to manage multiple MMIO regions, which will
326 * be referenced by name.
327 *
328 * @{
329 */
330
331 /**
332 * @def DEVICE_MMIO_NAMED_RAM(name)
333 *
334 * @brief Declare storage for MMIO data within a device's dev_data struct
335 *
336 * This gets accessed by the DEVICE_MMIO_NAMED_MAP() and
337 * DEVICE_MMIO_NAMED_GET() macros.
338 *
339 * Depending on configuration, no memory may be reserved at all.
340 * Multiple named regions may be declared.
341 *
342 * There must be a corresponding DEVICE_MMIO_ROM in config if the
343 * physical address is known at build time, but may be omitted if not (such
344 * as with PCIe.
345 *
346 * Example for a driver named "foo":
347 *
348 * @code{.c}
349 *
350 * struct foo_driver_data {
351 * int blarg;
352 * DEVICE_MMIO_NAMED_RAM(corge);
353 * DEVICE_MMIO_NAMED_RAM(grault);
354 * int wibble;
355 * ...
356 * }
357 *
358 * @endcode
359 *
360 * No build-time initialization of this memory is necessary; it
361 * will be set up in the init function by DEVICE_MMIO_NAMED_MAP().
362 *
363 * @param name Member name to use to store within dev_data.
364 */
365 #ifdef DEVICE_MMIO_IS_IN_RAM
366 #define DEVICE_MMIO_NAMED_RAM(name) mm_reg_t name
367 #else
368 #define DEVICE_MMIO_NAMED_RAM(name)
369 #endif /* DEVICE_MMIO_IS_IN_RAM */
370
371 #ifdef DEVICE_MMIO_IS_IN_RAM
372 /**
373 * @brief Return a pointer to the RAM storage for a device's named MMIO address
374 *
375 * This macro requires that the macro DEV_DATA is locally defined and returns
376 * a properly typed pointer to the particular dev_data struct for this driver.
377 *
378 * @param dev device instance object
379 * @param name Member name within dev_data
380 * @retval mm_reg_t pointer to storage location
381 */
382 #define DEVICE_MMIO_NAMED_RAM_PTR(dev, name) \
383 (&(DEV_DATA(dev)->name))
384 #endif /* DEVICE_MMIO_IS_IN_RAM */
385
386 /**
387 * @brief Declare storage for MMIO data within a device's config struct.
388 *
389 * This gets accessed by DEVICE_MMIO_NAMED_MAP() and
390 * DEVICE_MMIO_NAMED_GET() macros.
391 *
392 * What gets stored here varies considerably by configuration. Multiple named
393 * regions may be declared. There must be corresponding entries in the dev_data
394 * struct.
395 *
396 * This storage is not used if the device is PCIe and may be omitted.
397 *
398 * If used, this must be initialized at build time with information from DTS
399 * using DEVICE_MMIO_NAMED_ROM_INIT()
400 *
401 * A pointer to this memory may be obtained with DEVICE_MMIO_NAMED_ROM_PTR().
402 *
403 * Example for a driver named "foo":
404 *
405 * @code{.c}
406 *
407 * struct foo_config {
408 * int bar;
409 * DEVICE_MMIO_NAMED_ROM(corge);
410 * DEVICE_MMIO_NAMED_ROM(grault);
411 * int baz;
412 * ...
413 * }
414 *
415 * @endcode
416 *
417 * @see DEVICE_MMIO_NAMED_ROM_INIT()
418 *
419 * @param name Member name to store within config
420 */
421 #define DEVICE_MMIO_NAMED_ROM(name) struct z_device_mmio_rom name
422
423 /**
424 * Return a pointer to the ROM-based storage area for a device's MMIO
425 * information.
426 *
427 * This macro requires that the macro DEV_CFG is locally defined and returns
428 * a properly typed pointer to the particular config struct for this
429 * driver.
430 *
431 * @param dev device instance object
432 * @param name Member name within config
433 * @retval struct device_mmio_rom * pointer to storage location
434 */
435 #define DEVICE_MMIO_NAMED_ROM_PTR(dev, name) (&(DEV_CFG(dev)->name))
436
437 /**
438 * @brief Initialize a named DEVICE_MMIO_NAMED_ROM member
439 *
440 * Initialize MMIO-related information within a specific instance of
441 * a device config struct, using information from DTS.
442 *
443 * Example for an instance of a driver belonging to the "foo" subsystem
444 * that will have two regions named 'corge' and 'grault':
445 *
446 * @code{.c}
447 *
448 * struct foo_config my_config = {
449 * bar = 7;
450 * DEVICE_MMIO_NAMED_ROM_INIT(corge, DT_DRV_INST(...));
451 * DEVICE_MMIO_NAMED_ROM_INIT(grault, DT_DRV_INST(...));
452 * baz = 2;
453 * ...
454 * }
455 *
456 * @endcode
457 *
458 * @see DEVICE_MMIO_NAMED_ROM()
459 *
460 * @param name Member name within config for the MMIO region
461 * @param node_id DTS node identifier
462 */
463 #define DEVICE_MMIO_NAMED_ROM_INIT(name, node_id) \
464 .name = Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
465
466 /**
467 * @brief Initialize a named DEVICE_MMIO_NAMED_ROM member using a named DT
468 * reg property.
469 *
470 * Same as @ref DEVICE_MMIO_NAMED_ROM_INIT but the size and address are taken
471 * from a named DT reg property.
472 *
473 * Example for an instance of a driver belonging to the "foo" subsystem
474 * that will have two DT-defined regions named 'chip' and 'dale':
475 *
476 * @code{.dts}
477 *
478 * foo@E5000000 {
479 * reg = <0xE5000000 0x1000>, <0xE6000000 0x1000>;
480 * reg-names = "chip", "dale";
481 * ...
482 * };
483 *
484 * @endcode
485 *
486 * @code{.c}
487 *
488 * struct foo_config my_config = {
489 * bar = 7;
490 * DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(chip, DT_DRV_INST(...));
491 * DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(dale, DT_DRV_INST(...));
492 * baz = 2;
493 * ...
494 * }
495 *
496 * @endcode
497 *
498 * @see DEVICE_MMIO_NAMED_ROM_INIT()
499 *
500 * @param name Member name within config for the MMIO region and name of the
501 * reg property in the DT
502 * @param node_id DTS node identifier
503 */
504 #define DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(name, node_id) \
505 .name = Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(name, node_id)
506
507 /**
508 * @brief Set up memory for a named MMIO region
509 *
510 * This performs the necessary PCI probing and/or MMU virtual memory mapping
511 * such that DEVICE_MMIO_GET(name) returns a suitable linear memory address
512 * for the MMIO region.
513 *
514 * If such operations are not required by the target hardware, this expands
515 * to nothing.
516 *
517 * This should be called from the driver's init function, once for each
518 * MMIO region that needs to be mapped.
519 *
520 * This macro requires that the macros DEV_DATA and DEV_CFG are locally
521 * defined and return properly typed pointers to the particular dev_data
522 * and config structs for this driver.
523 *
524 * The flags argument is currently used for caching mode, which should be
525 * one of the DEVICE_CACHE_* macros. Unused bits are reserved for future
526 * expansion.
527 *
528 * @param dev Device object
529 * @param name Member name for MMIO information, as declared with
530 * DEVICE_MMIO_NAMED_RAM/DEVICE_MMIO_NAMED_ROM
531 * @param flags One of the DEVICE_CACHE_* caching modes
532 */
533 #ifdef DEVICE_MMIO_IS_IN_RAM
534 #define DEVICE_MMIO_NAMED_MAP(dev, name, flags) \
535 device_map(DEVICE_MMIO_NAMED_RAM_PTR((dev), name), \
536 (DEVICE_MMIO_NAMED_ROM_PTR((dev), name)->phys_addr), \
537 (DEVICE_MMIO_NAMED_ROM_PTR((dev), name)->size), \
538 (flags))
539 #else
540 #define DEVICE_MMIO_NAMED_MAP(dev, name, flags) do { } while (false)
541 #endif
542
543 /**
544 * @def DEVICE_MMIO_NAMED_GET(dev, name)
545 *
546 * @brief Obtain a named MMIO address for a device
547 *
548 * This macro returns the MMIO base address for a named region from the
549 * appropriate place within the device object's linked data structures.
550 *
551 * This is for drivers which have multiple MMIO regions.
552 *
553 * This macro requires that the macros DEV_DATA and DEV_CFG are locally
554 * defined and return properly typed pointers to the particular dev_data
555 * and config structs for this driver.
556 *
557 * @see DEVICE_MMIO_GET
558 *
559 * @param dev Device object
560 * @param name Member name for MMIO information, as declared with
561 * DEVICE_MMIO_NAMED_RAM/DEVICE_MMIO_NAMED_ROM
562 * @return mm_reg_t linear address of the MMIO region
563 */
564 #ifdef DEVICE_MMIO_IS_IN_RAM
565 #define DEVICE_MMIO_NAMED_GET(dev, name) \
566 (*DEVICE_MMIO_NAMED_RAM_PTR((dev), name))
567 #else
568 #define DEVICE_MMIO_NAMED_GET(dev, name) \
569 ((DEVICE_MMIO_NAMED_ROM_PTR((dev), name))->addr)
570 #endif /* DEVICE_MMIO_IS_IN_RAM */
571
572 /** @} */
573
574 /**
575 * @defgroup device-mmio-toplevel Top-level MMIO region macros
576 * @ingroup device-mmio
577 *
578 * For drivers which do not use Zephyr's driver model and do not
579 * associate struct device with a driver instance. Top-level storage
580 * is used instead, with either global or static scope.
581 *
582 * This is often useful for interrupt controller and timer drivers.
583 *
584 * Currently PCIe devices are not well-supported with this set of macros.
585 * Either use Zephyr's driver model for these kinds of devices, or
586 * manage memory manually with calls to device_map().
587 *
588 * @{
589 */
590
591 #define Z_TOPLEVEL_ROM_NAME(name) _CONCAT(z_mmio_rom__, name)
592 #define Z_TOPLEVEL_RAM_NAME(name) _CONCAT(z_mmio_ram__, name)
593
594 /**
595 * @def DEVICE_MMIO_TOPLEVEL(name, node_id)
596 *
597 * @brief Declare top-level storage for MMIO information, global scope
598 *
599 * This is intended for drivers which do not use Zephyr's driver model
600 * of config/dev_data linked to a struct device.
601 *
602 * Instead, this is a top-level declaration for the driver's C file.
603 * The scope of this declaration is global and may be referenced by
604 * other C files, using DEVICE_MMIO_TOPLEVEL_DECLARE.
605 *
606 * @param name Base symbol name
607 * @param node_id Device-tree node identifier for this region
608 */
609 #ifdef DEVICE_MMIO_IS_IN_RAM
610 #define DEVICE_MMIO_TOPLEVEL(name, node_id) \
611 __pinned_bss \
612 mm_reg_t Z_TOPLEVEL_RAM_NAME(name); \
613 __pinned_rodata \
614 const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name) = \
615 Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
616 #else
617 #define DEVICE_MMIO_TOPLEVEL(name, node_id) \
618 __pinned_rodata \
619 const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name) = \
620 Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
621 #endif /* DEVICE_MMIO_IS_IN_RAM */
622
623 /**
624 * @def DEVICE_MMIO_TOPLEVEL_DECLARE(name)
625 *
626 * Provide an extern reference to a top-level MMIO region
627 *
628 * If a top-level MMIO region defined with DEVICE_MMIO_DEFINE needs to be
629 * referenced from other C files, this macro provides the necessary extern
630 * definitions.
631 *
632 * @see DEVICE_MMIO_TOPLEVEL
633 *
634 * @param name Name of the top-level MMIO region
635 */
636
637 #ifdef DEVICE_MMIO_IS_IN_RAM
638 #define DEVICE_MMIO_TOPLEVEL_DECLARE(name) \
639 extern mm_reg_t Z_TOPLEVEL_RAM_NAME(name); \
640 extern const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name)
641 #else
642 #define DEVICE_MMIO_TOPLEVEL_DECLARE(name) \
643 extern const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name)
644 #endif /* DEVICE_MMIO_IS_IN_RAM */
645
646 /**
647 * @def DEVICE_MMIO_TOPLEVEL_STATIC(name, node_id)
648 *
649 * @brief Declare top-level storage for MMIO information, static scope
650 *
651 * This is intended for drivers which do not use Zephyr's driver model
652 * of config/dev_data linked to a struct device.
653 *
654 * Instead, this is a top-level declaration for the driver's C file.
655 * The scope of this declaration is static.
656 *
657 * @param name Name of the top-level MMIO region
658 * @param node_id Device-tree node identifier for this region
659 */
660 #ifdef DEVICE_MMIO_IS_IN_RAM
661 #define DEVICE_MMIO_TOPLEVEL_STATIC(name, node_id) \
662 __pinned_bss \
663 static mm_reg_t Z_TOPLEVEL_RAM_NAME(name); \
664 __pinned_rodata \
665 static const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name) = \
666 Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
667 #else
668 #define DEVICE_MMIO_TOPLEVEL_STATIC(name, node_id) \
669 __pinned_rodata \
670 static const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name) = \
671 Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
672 #endif /* DEVICE_MMIO_IS_IN_RAM */
673
674 #ifdef DEVICE_MMIO_IS_IN_RAM
675 /**
676 * @brief Return a pointer to the RAM storage for a device's toplevel MMIO
677 * address.
678 *
679 * @param name Name of toplevel MMIO region
680 * @retval mm_reg_t pointer to storage location
681 */
682 #define DEVICE_MMIO_TOPLEVEL_RAM_PTR(name) &Z_TOPLEVEL_RAM_NAME(name)
683 #endif /* DEVICE_MMIO_IS_IN_RAM */
684
685 /**
686 * Return a pointer to the ROM-based storage area for a toplevel MMIO region.
687 *
688 * @param name MMIO region name
689 * @retval struct device_mmio_rom * pointer to storage location
690 */
691 #define DEVICE_MMIO_TOPLEVEL_ROM_PTR(name) &Z_TOPLEVEL_ROM_NAME(name)
692
693 /**
694 * @def DEVICE_MMIO_TOPLEVEL_MAP(name, flags)
695 *
696 * @brief Set up memory for a driver'sMMIO region
697 *
698 * This performs the necessary MMU virtual memory mapping
699 * such that DEVICE_MMIO_GET() returns a suitable linear memory address
700 * for the MMIO region.
701 *
702 * If such operations are not required by the target hardware, this expands
703 * to nothing.
704 *
705 * This should be called once from the driver's init function.
706 *
707 * The flags argument is currently used for caching mode, which should be
708 * one of the DEVICE_CACHE_* macros. Unused bits are reserved for future
709 * expansion.
710 *
711 * @param name Name of the top-level MMIO region
712 * @param flags One of the DEVICE_CACHE_* caching modes
713 */
714 #ifdef DEVICE_MMIO_IS_IN_RAM
715 #define DEVICE_MMIO_TOPLEVEL_MAP(name, flags) \
716 device_map(&Z_TOPLEVEL_RAM_NAME(name), \
717 Z_TOPLEVEL_ROM_NAME(name).phys_addr, \
718 Z_TOPLEVEL_ROM_NAME(name).size, (flags))
719 #else
720 #define DEVICE_MMIO_TOPLEVEL_MAP(name, flags) do { } while (false)
721 #endif
722
723 /**
724 * @def DEVICE_MMIO_TOPLEVEL_GET(name)
725 *
726 * @brief Obtain the MMIO address for a device declared top-level
727 *
728 * @see DEVICE_MMIO_GET
729 *
730 * @param name Name of the top-level MMIO region
731 * @return mm_reg_t linear address of the MMIO region
732 */
733 #ifdef DEVICE_MMIO_IS_IN_RAM
734 #define DEVICE_MMIO_TOPLEVEL_GET(name) \
735 ((mm_reg_t)Z_TOPLEVEL_RAM_NAME(name))
736 #else
737 #define DEVICE_MMIO_TOPLEVEL_GET(name) \
738 ((mm_reg_t)Z_TOPLEVEL_ROM_NAME(name).addr)
739 #endif
740 /** @} */
741
742 #endif /* ZEPHYR_INCLUDE_SYS_DEVICE_MMIO_H */
743