Zephyr API Documentation 4.4.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
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#ifndef ZEPHYR_INCLUDE_SYS_DEVICE_MMIO_H
7#define ZEPHYR_INCLUDE_SYS_DEVICE_MMIO_H
8
9#include <zephyr/toolchain.h>
11
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)
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 */
56struct z_device_mmio_rom {
58 uintptr_t phys_addr;
59
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
96__boot_func
97static 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 if (IS_ENABLED(CONFIG_KERNEL_DIRECT_MAP)) {
106 }
107 k_mem_map_phys_bare((uint8_t **)virt_addr, phys_addr, size,
109#else
110 ARG_UNUSED(size);
111 ARG_UNUSED(flags);
112#ifdef CONFIG_EXTERNAL_ADDRESS_TRANSLATION
113 sys_mm_drv_page_phys_get((void *) phys_addr, virt_addr);
114#else
115 *virt_addr = phys_addr;
116#endif /* CONFIG_EXTERNAL_ADDRESS_TRANSLATION */
117#endif /* CONFIG_MMU */
118}
119
128__boot_func
129static inline void device_unmap(mm_reg_t virt_addr, size_t size)
130{
131#ifdef CONFIG_MMU
132 k_mem_unmap_phys_bare((uint8_t *)virt_addr, size);
133#else
134 ARG_UNUSED(virt_addr);
135 ARG_UNUSED(size);
136#endif /* CONFIG_MMU */
137}
138#else
139/* No MMU or PCIe. Just store the address from DTS and treat as a linear
140 * address
141 */
142struct z_device_mmio_rom {
144 mm_reg_t addr;
145};
146
147#define Z_DEVICE_MMIO_ROM_INITIALIZER(node_id) \
148 { \
149 .addr = (mm_reg_t)DT_REG_ADDR_U64(node_id) \
150 }
151
152#define Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(name, node_id) \
153 { \
154 .addr = (mm_reg_t)DT_REG_ADDR_BY_NAME_U64(node_id, name) \
155 }
156
157__boot_func
158static inline void device_map(mm_reg_t *virt_addr, uintptr_t phys_addr,
159 size_t size, uint32_t flags)
160{
161 ARG_UNUSED(size);
162 ARG_UNUSED(flags);
163 *virt_addr = phys_addr;
164}
165
166__boot_func
167static inline void device_unmap(mm_reg_t virt_addr, size_t size)
168{
169 ARG_UNUSED(virt_addr);
170 ARG_UNUSED(size);
171}
172
173#endif /* DEVICE_MMIO_IS_IN_RAM */
174#endif /* !_ASMLANGUAGE */
176
186
218#ifdef DEVICE_MMIO_IS_IN_RAM
219#define DEVICE_MMIO_RAM mm_reg_t _mmio
220#else
221#define DEVICE_MMIO_RAM
222#endif
223
224#ifdef DEVICE_MMIO_IS_IN_RAM
235#define DEVICE_MMIO_RAM_PTR(device) (mm_reg_t *)((device)->data)
236#endif /* DEVICE_MMIO_IS_IN_RAM */
237
268#define DEVICE_MMIO_ROM struct z_device_mmio_rom _mmio
269
279#define DEVICE_MMIO_ROM_PTR(dev) \
280 ((struct z_device_mmio_rom *)((dev)->config))
281
304#define DEVICE_MMIO_ROM_INIT(node_id) \
305 ._mmio = Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
306
323#ifdef DEVICE_MMIO_IS_IN_RAM
324#define DEVICE_MMIO_MAP(dev, flags) \
325 device_map(DEVICE_MMIO_RAM_PTR(dev), \
326 DEVICE_MMIO_ROM_PTR(dev)->phys_addr, \
327 DEVICE_MMIO_ROM_PTR(dev)->size, \
328 (flags))
329#else
330#define DEVICE_MMIO_MAP(dev, flags) do { } while (false)
331#endif
332
352#ifdef DEVICE_MMIO_IS_IN_RAM
353#define DEVICE_MMIO_GET(dev) (*DEVICE_MMIO_RAM_PTR(dev))
354#else
355#define DEVICE_MMIO_GET(dev) (DEVICE_MMIO_ROM_PTR(dev)->addr)
356#endif
358
368
403#ifdef DEVICE_MMIO_IS_IN_RAM
404#define DEVICE_MMIO_NAMED_RAM(name) mm_reg_t name
405#else
406#define DEVICE_MMIO_NAMED_RAM(name)
407#endif /* DEVICE_MMIO_IS_IN_RAM */
408
409#ifdef DEVICE_MMIO_IS_IN_RAM
420#define DEVICE_MMIO_NAMED_RAM_PTR(dev, name) \
421 (&(DEV_DATA(dev)->name))
422#endif /* DEVICE_MMIO_IS_IN_RAM */
423
459#define DEVICE_MMIO_NAMED_ROM(name) struct z_device_mmio_rom name
460
473#define DEVICE_MMIO_NAMED_ROM_PTR(dev, name) (&(DEV_CFG(dev)->name))
474
501#define DEVICE_MMIO_NAMED_ROM_INIT(name, node_id) \
502 .name = Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
503
542#define DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(name, node_id) \
543 .name = Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(name, node_id)
544
571#ifdef DEVICE_MMIO_IS_IN_RAM
572#define DEVICE_MMIO_NAMED_MAP(dev, name, flags) \
573 device_map(DEVICE_MMIO_NAMED_RAM_PTR((dev), name), \
574 (DEVICE_MMIO_NAMED_ROM_PTR((dev), name)->phys_addr), \
575 (DEVICE_MMIO_NAMED_ROM_PTR((dev), name)->size), \
576 (flags))
577#else
578#define DEVICE_MMIO_NAMED_MAP(dev, name, flags) do { } while (false)
579#endif
580
602#ifdef DEVICE_MMIO_IS_IN_RAM
603#define DEVICE_MMIO_NAMED_GET(dev, name) \
604 (*DEVICE_MMIO_NAMED_RAM_PTR((dev), name))
605#else
606#define DEVICE_MMIO_NAMED_GET(dev, name) \
607 ((DEVICE_MMIO_NAMED_ROM_PTR((dev), name))->addr)
608#endif /* DEVICE_MMIO_IS_IN_RAM */
609
611
628
629 #define Z_TOPLEVEL_ROM_NAME(name) _CONCAT(z_mmio_rom__, name)
630 #define Z_TOPLEVEL_RAM_NAME(name) _CONCAT(z_mmio_ram__, name)
631
647#ifdef DEVICE_MMIO_IS_IN_RAM
648#define DEVICE_MMIO_TOPLEVEL(name, node_id) \
649 __pinned_bss \
650 mm_reg_t Z_TOPLEVEL_RAM_NAME(name); \
651 __pinned_rodata \
652 const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name) = \
653 Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
654#else
655#define DEVICE_MMIO_TOPLEVEL(name, node_id) \
656 __pinned_rodata \
657 const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name) = \
658 Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
659#endif /* DEVICE_MMIO_IS_IN_RAM */
660
674
675#ifdef DEVICE_MMIO_IS_IN_RAM
676#define DEVICE_MMIO_TOPLEVEL_DECLARE(name) \
677 extern mm_reg_t Z_TOPLEVEL_RAM_NAME(name); \
678 extern const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name)
679#else
680#define DEVICE_MMIO_TOPLEVEL_DECLARE(name) \
681 extern const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name)
682#endif /* DEVICE_MMIO_IS_IN_RAM */
683
698#ifdef DEVICE_MMIO_IS_IN_RAM
699#define DEVICE_MMIO_TOPLEVEL_STATIC(name, node_id) \
700 __pinned_bss \
701 static mm_reg_t Z_TOPLEVEL_RAM_NAME(name); \
702 __pinned_rodata \
703 static const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name) = \
704 Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
705#else
706#define DEVICE_MMIO_TOPLEVEL_STATIC(name, node_id) \
707 __pinned_rodata \
708 static const struct z_device_mmio_rom Z_TOPLEVEL_ROM_NAME(name) = \
709 Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
710#endif /* DEVICE_MMIO_IS_IN_RAM */
711
712#ifdef DEVICE_MMIO_IS_IN_RAM
720#define DEVICE_MMIO_TOPLEVEL_RAM_PTR(name) &Z_TOPLEVEL_RAM_NAME(name)
721#endif /* DEVICE_MMIO_IS_IN_RAM */
722
729#define DEVICE_MMIO_TOPLEVEL_ROM_PTR(name) &Z_TOPLEVEL_ROM_NAME(name)
730
752#ifdef DEVICE_MMIO_IS_IN_RAM
753#define DEVICE_MMIO_TOPLEVEL_MAP(name, flags) \
754 device_map(&Z_TOPLEVEL_RAM_NAME(name), \
755 Z_TOPLEVEL_ROM_NAME(name).phys_addr, \
756 Z_TOPLEVEL_ROM_NAME(name).size, (flags))
757#else
758#define DEVICE_MMIO_TOPLEVEL_MAP(name, flags) do { } while (false)
759#endif
760
771#ifdef DEVICE_MMIO_IS_IN_RAM
772#define DEVICE_MMIO_TOPLEVEL_GET(name) \
773 ((mm_reg_t)Z_TOPLEVEL_RAM_NAME(name))
774#else
775#define DEVICE_MMIO_TOPLEVEL_GET(name) \
776 ((mm_reg_t)Z_TOPLEVEL_ROM_NAME(name).addr)
777#endif
779
780#endif /* ZEPHYR_INCLUDE_SYS_DEVICE_MMIO_H */
static __boot_func void device_unmap(mm_reg_t virt_addr, size_t size)
Un-set linear address for device MMIO access.
Definition device_mmio.h:129
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:97
#define K_MEM_DIRECT_MAP
Region will be mapped to 1:1 virtual and physical address.
Definition mm.h:80
#define K_MEM_PERM_RW
Region will have read/write access (and not read-only).
Definition mm.h:63
void k_mem_map_phys_bare(uint8_t **virt_ptr, uintptr_t phys, size_t size, uint32_t flags)
Map a physical memory region into the kernel's virtual address space.
void k_mem_unmap_phys_bare(uint8_t *virt, size_t size)
Unmap a virtual memory region from kernel's virtual address space.
int sys_mm_drv_page_phys_get(void *virt, uintptr_t *phys)
Get the mapped physical memory address from virtual address.
#define IS_ENABLED(config_macro)
Check for macro definition in compiler-visible expressions.
Definition util_macro.h:154
flags
Definition parser.h:97
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.