Zephyr API Documentation  3.5.0
A Scalable Open Source RTOS
3.5.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
device_mmio.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Definitions and helper macros for managing driver memory-mapped
7 * input/output (MMIO) regions appropriately in either RAM or ROM.
8 *
9 * In most cases drivers will just want to include device.h, but
10 * including this separately may be needed for arch-level driver code
11 * which uses the DEVICE_MMIO_TOPLEVEL variants and including the
12 * main device.h would introduce header dependency loops due to that
13 * header's reliance on kernel.h.
14 */
15#ifndef ZEPHYR_INCLUDE_SYS_DEVICE_MMIO_H
16#define ZEPHYR_INCLUDE_SYS_DEVICE_MMIO_H
17
18#include <zephyr/toolchain.h>
20
27/* Storing MMIO addresses in RAM is a system-wide decision based on
28 * configuration. This is just used to simplify some other definitions.
29 *
30 * If we have an MMU enabled, all physical MMIO regions must be mapped into
31 * the kernel's virtual address space at runtime, this is a hard requirement.
32 *
33 * If we have PCIE enabled, this does mean that non-PCIE drivers may waste
34 * a bit of RAM, but systems with PCI express are not RAM constrained.
35 */
36#if defined(CONFIG_MMU) || defined(CONFIG_PCIE) || defined(CONFIG_EXTERNAL_ADDRESS_TRANSLATION)
37#define DEVICE_MMIO_IS_IN_RAM
38#endif
39
40#if defined(CONFIG_EXTERNAL_ADDRESS_TRANSLATION)
42#endif
43
44#ifndef _ASMLANGUAGE
45#include <stdint.h>
46#include <stddef.h>
48#include <zephyr/sys/sys_io.h>
49
50#ifdef DEVICE_MMIO_IS_IN_RAM
51/* Store the physical address and size from DTS, we'll memory
52 * map into the virtual address space at runtime. This is not applicable
53 * to PCIe devices, which must query the bus for BAR information.
54 */
55struct z_device_mmio_rom {
57 uintptr_t phys_addr;
58
60 size_t size;
61};
62
63#define Z_DEVICE_MMIO_ROM_INITIALIZER(node_id) \
64 { \
65 .phys_addr = DT_REG_ADDR(node_id), \
66 .size = DT_REG_SIZE(node_id) \
67 }
68
69#define Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(name, node_id) \
70 { \
71 .phys_addr = DT_REG_ADDR_BY_NAME(node_id, name), \
72 .size = DT_REG_SIZE_BY_NAME(node_id, name) \
73 }
74
95__boot_func
96static inline void device_map(mm_reg_t *virt_addr, uintptr_t phys_addr,
97 size_t size, uint32_t flags)
98{
99#ifdef CONFIG_MMU
100 /* Pass along flags and add that we want supervisor mode
101 * read-write access.
102 */
103 z_phys_map((uint8_t **)virt_addr, phys_addr, size,
105#else
106 ARG_UNUSED(size);
107 ARG_UNUSED(flags);
108#ifdef CONFIG_EXTERNAL_ADDRESS_TRANSLATION
109 sys_mm_drv_page_phys_get((void *) phys_addr, virt_addr);
110#else
111 *virt_addr = phys_addr;
112#endif /* CONFIG_EXTERNAL_ADDRESS_TRANSLATION */
113#endif /* CONFIG_MMU */
114}
115#else
116/* No MMU or PCIe. Just store the address from DTS and treat as a linear
117 * address
118 */
119struct z_device_mmio_rom {
121 mm_reg_t addr;
122};
123
124#define Z_DEVICE_MMIO_ROM_INITIALIZER(node_id) \
125 { \
126 .addr = (mm_reg_t)DT_REG_ADDR_U64(node_id) \
127 }
128
129#define Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(name, node_id) \
130 { \
131 .addr = (mm_reg_t)DT_REG_ADDR_BY_NAME_U64(node_id, name) \
132 }
133
134#endif /* DEVICE_MMIO_IS_IN_RAM */
135#endif /* !_ASMLANGUAGE */
175#ifdef DEVICE_MMIO_IS_IN_RAM
176#define DEVICE_MMIO_RAM mm_reg_t _mmio
177#else
178#define DEVICE_MMIO_RAM
179#endif
180
181#ifdef DEVICE_MMIO_IS_IN_RAM
192#define DEVICE_MMIO_RAM_PTR(device) (mm_reg_t *)((device)->data)
193#endif /* DEVICE_MMIO_IS_IN_RAM */
194
221#define DEVICE_MMIO_ROM struct z_device_mmio_rom _mmio
222
232#define DEVICE_MMIO_ROM_PTR(dev) \
233 ((struct z_device_mmio_rom *)((dev)->config))
234
253#define DEVICE_MMIO_ROM_INIT(node_id) \
254 ._mmio = Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
255
272#ifdef DEVICE_MMIO_IS_IN_RAM
273#define DEVICE_MMIO_MAP(dev, flags) \
274 device_map(DEVICE_MMIO_RAM_PTR(dev), \
275 DEVICE_MMIO_ROM_PTR(dev)->phys_addr, \
276 DEVICE_MMIO_ROM_PTR(dev)->size, \
277 (flags))
278#else
279#define DEVICE_MMIO_MAP(dev, flags) do { } while (false)
280#endif
281
301#ifdef DEVICE_MMIO_IS_IN_RAM
302#define DEVICE_MMIO_GET(dev) (*DEVICE_MMIO_RAM_PTR(dev))
303#else
304#define DEVICE_MMIO_GET(dev) (DEVICE_MMIO_ROM_PTR(dev)->addr)
305#endif
348#ifdef DEVICE_MMIO_IS_IN_RAM
349#define DEVICE_MMIO_NAMED_RAM(name) mm_reg_t name
350#else
351#define DEVICE_MMIO_NAMED_RAM(name)
352#endif /* DEVICE_MMIO_IS_IN_RAM */
353
354#ifdef DEVICE_MMIO_IS_IN_RAM
365#define DEVICE_MMIO_NAMED_RAM_PTR(dev, name) \
366 (&(DEV_DATA(dev)->name))
367#endif /* DEVICE_MMIO_IS_IN_RAM */
368
400#define DEVICE_MMIO_NAMED_ROM(name) struct z_device_mmio_rom name
401
414#define DEVICE_MMIO_NAMED_ROM_PTR(dev, name) (&(DEV_CFG(dev)->name))
415
438#define DEVICE_MMIO_NAMED_ROM_INIT(name, node_id) \
439 .name = Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
440
479#define DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(name, node_id) \
480 .name = Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(name, node_id)
481
508#ifdef DEVICE_MMIO_IS_IN_RAM
509#define DEVICE_MMIO_NAMED_MAP(dev, name, flags) \
510 device_map(DEVICE_MMIO_NAMED_RAM_PTR((dev), name), \
511 (DEVICE_MMIO_NAMED_ROM_PTR((dev), name)->phys_addr), \
512 (DEVICE_MMIO_NAMED_ROM_PTR((dev), name)->size), \
513 (flags))
514#else
515#define DEVICE_MMIO_NAMED_MAP(dev, name, flags) do { } while (false)
516#endif
517
539#ifdef DEVICE_MMIO_IS_IN_RAM
540#define DEVICE_MMIO_NAMED_GET(dev, name) \
541 (*DEVICE_MMIO_NAMED_RAM_PTR((dev), name))
542#else
543#define DEVICE_MMIO_NAMED_GET(dev, name) \
544 ((DEVICE_MMIO_NAMED_ROM_PTR((dev), name))->addr)
545#endif /* DEVICE_MMIO_IS_IN_RAM */
546
566 #define Z_TOPLEVEL_ROM_NAME(name) _CONCAT(z_mmio_rom__, name)
567 #define Z_TOPLEVEL_RAM_NAME(name) _CONCAT(z_mmio_ram__, name)
568
584#ifdef DEVICE_MMIO_IS_IN_RAM
585#define DEVICE_MMIO_TOPLEVEL(name, node_id) \
586 __pinned_bss \
587 mm_reg_t Z_TOPLEVEL_RAM_NAME(name); \
588 __pinned_rodata \
589 const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name) = \
590 Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
591#else
592#define DEVICE_MMIO_TOPLEVEL(name, node_id) \
593 __pinned_rodata \
594 const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name) = \
595 Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
596#endif /* DEVICE_MMIO_IS_IN_RAM */
597
612#ifdef DEVICE_MMIO_IS_IN_RAM
613#define DEVICE_MMIO_TOPLEVEL_DECLARE(name) \
614 extern mm_reg_t Z_TOPLEVEL_RAM_NAME(name); \
615 extern const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name)
616#else
617#define DEVICE_MMIO_TOPLEVEL_DECLARE(name) \
618 extern const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name)
619#endif /* DEVICE_MMIO_IS_IN_RAM */
620
635#ifdef DEVICE_MMIO_IS_IN_RAM
636#define DEVICE_MMIO_TOPLEVEL_STATIC(name, node_id) \
637 __pinned_bss \
638 static mm_reg_t Z_TOPLEVEL_RAM_NAME(name); \
639 __pinned_rodata \
640 static const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name) = \
641 Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
642#else
643#define DEVICE_MMIO_TOPLEVEL_STATIC(name, node_id) \
644 __pinned_rodata \
645 static const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name) = \
646 Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
647#endif /* DEVICE_MMIO_IS_IN_RAM */
648
649#ifdef DEVICE_MMIO_IS_IN_RAM
657#define DEVICE_MMIO_TOPLEVEL_RAM_PTR(name) &Z_TOPLEVEL_RAM_NAME(name)
658#endif /* DEVICE_MMIO_IS_IN_RAM */
659
666#define DEVICE_MMIO_TOPLEVEL_ROM_PTR(name) &Z_TOPLEVEL_ROM_NAME(name)
667
689#ifdef DEVICE_MMIO_IS_IN_RAM
690#define DEVICE_MMIO_TOPLEVEL_MAP(name, flags) \
691 device_map(&Z_TOPLEVEL_RAM_NAME(name), \
692 Z_TOPLEVEL_ROM_NAME(name).phys_addr, \
693 Z_TOPLEVEL_ROM_NAME(name).size, flags)
694#else
695#define DEVICE_MMIO_TOPLEVEL_MAP(name, flags) do { } while (false)
696#endif
697
708#ifdef DEVICE_MMIO_IS_IN_RAM
709#define DEVICE_MMIO_TOPLEVEL_GET(name) \
710 ((mm_reg_t)Z_TOPLEVEL_RAM_NAME(name))
711#else
712#define DEVICE_MMIO_TOPLEVEL_GET(name) \
713 ((mm_reg_t)Z_TOPLEVEL_ROM_NAME(name).addr)
714#endif
717#endif /* ZEPHYR_INCLUDE_SYS_DEVICE_MMIO_H */
static __boot_func void device_map(mm_reg_t *virt_addr, uintptr_t phys_addr, size_t size, uint32_t flags)
Set linear address for device MMIO access.
Definition: device_mmio.h:96
int sys_mm_drv_page_phys_get(void *virt, uintptr_t *phys)
Get the mapped physical memory address from virtual address.
#define K_MEM_PERM_RW
Region will have read/write access (and not read-only)
Definition: mem_manage.h:50
flags
Definition: parser.h:96
Definitions of various linker Sections.
__UINT32_TYPE__ uint32_t
Definition: stdint.h:90
__UINT8_TYPE__ uint8_t
Definition: stdint.h:88
__UINTPTR_TYPE__ uintptr_t
Definition: stdint.h:105
uintptr_t mm_reg_t
Definition: sys_io.h:20
Memory Management Driver APIs.
Macros to abstract toolchain specific capabilities.