Zephyr API Documentation  3.7.0
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
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 k_mem_map_phys_bare((uint8_t **)virt_addr, phys_addr, size,
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 */
120struct z_device_mmio_rom {
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 */
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
197#define DEVICE_MMIO_RAM_PTR(device) (mm_reg_t *)((device)->data)
198#endif /* DEVICE_MMIO_IS_IN_RAM */
199
230#define DEVICE_MMIO_ROM struct z_device_mmio_rom _mmio
231
241#define DEVICE_MMIO_ROM_PTR(dev) \
242 ((struct z_device_mmio_rom *)((dev)->config))
243
266#define DEVICE_MMIO_ROM_INIT(node_id) \
267 ._mmio = Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
268
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
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
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
382#define DEVICE_MMIO_NAMED_RAM_PTR(dev, name) \
383 (&(DEV_DATA(dev)->name))
384#endif /* DEVICE_MMIO_IS_IN_RAM */
385
421#define DEVICE_MMIO_NAMED_ROM(name) struct z_device_mmio_rom name
422
435#define DEVICE_MMIO_NAMED_ROM_PTR(dev, name) (&(DEV_CFG(dev)->name))
436
463#define DEVICE_MMIO_NAMED_ROM_INIT(name, node_id) \
464 .name = Z_DEVICE_MMIO_ROM_INITIALIZER(node_id)
465
504#define DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(name, node_id) \
505 .name = Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(name, node_id)
506
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
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
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
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
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
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
682#define DEVICE_MMIO_TOPLEVEL_RAM_PTR(name) &Z_TOPLEVEL_RAM_NAME(name)
683#endif /* DEVICE_MMIO_IS_IN_RAM */
684
691#define DEVICE_MMIO_TOPLEVEL_ROM_PTR(name) &Z_TOPLEVEL_ROM_NAME(name)
692
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
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
742#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:97
#define K_MEM_PERM_RW
Region will have read/write access (and not read-only)
Definition: mm.h:61
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.
int sys_mm_drv_page_phys_get(void *virt, uintptr_t *phys)
Get the mapped physical memory address from virtual address.
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.