coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
pci_mmio_cfg.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #ifndef _PCI_MMIO_CFG_H
4 #define _PCI_MMIO_CFG_H
5 
6 #include <stdint.h>
7 #include <device/mmio.h>
8 #include <device/pci_type.h>
9 
10 /* Using a unique datatype for MMIO writes makes the pointers to _not_
11  * qualify for pointer aliasing with any other objects in memory.
12  *
13  * MMIO offset is a value originally derived from 'struct device *'
14  * in ramstage. For the compiler to not discard this MMIO offset value
15  * from CPU registers after any MMIO writes, -fstrict-aliasing has to
16  * be also set for the build.
17  *
18  * Bottom 12 bits (4 KiB) are reserved to address the registers of a
19  * single PCI function. Declare the bank as a union to avoid some casting
20  * in the functions below.
21  */
22 union pci_bank {
23  uint8_t reg8[4096];
24  uint16_t reg16[4096 / sizeof(uint16_t)];
25  uint32_t reg32[4096 / sizeof(uint32_t)];
26 };
27 
28 #if CONFIG(ECAM_MMCONF_SUPPORT)
29 
30 #if CONFIG_ECAM_MMCONF_BASE_ADDRESS == 0
31 #error "CONFIG_ECAM_MMCONF_BASE_ADDRESS undefined!"
32 #endif
33 
34 #if CONFIG_ECAM_MMCONF_BUS_NUMBER * MiB != CONFIG_ECAM_MMCONF_LENGTH
35 #error "CONFIG_ECAM_MMCONF_LENGTH does not correspond with CONFIG_ECAM_MMCONF_BUS_NUMBER!"
36 #endif
37 
38 /* By not assigning this to CONFIG_ECAM_MMCONF_BASE_ADDRESS here we
39  prevent some sub-optimal constant folding. */
40 extern u8 *const pci_mmconf;
41 
42 static __always_inline
43 volatile union pci_bank *pci_map_bus(pci_devfn_t dev)
44 {
45  return (void *)&pci_mmconf[PCI_DEVFN_OFFSET(dev)];
46 }
47 
48 #else
49 
50 /* For platforms not supporting ECAM, they need to define pci_map_bus function
51  * in their platform-specific code */
52 volatile union pci_bank *pci_map_bus(pci_devfn_t dev);
53 
54 #endif
55 
56 /*
57  * Avoid name collisions as different stages have different signature
58  * for these functions. The _s_ stands for simple, fundamental IO or
59  * MMIO variant.
60  */
61 
62 static __always_inline
64 {
65  return pci_map_bus(dev)->reg8[reg];
66 }
67 
68 static __always_inline
70 {
71  return pci_map_bus(dev)->reg16[reg / sizeof(uint16_t)];
72 }
73 
74 static __always_inline
76 {
77  return pci_map_bus(dev)->reg32[reg / sizeof(uint32_t)];
78 }
79 
80 static __always_inline
82 {
83  pci_map_bus(dev)->reg8[reg] = value;
84 }
85 
86 static __always_inline
88 {
89  pci_map_bus(dev)->reg16[reg / sizeof(uint16_t)] = value;
90 }
91 
92 static __always_inline
94 {
95  pci_map_bus(dev)->reg32[reg / sizeof(uint32_t)] = value;
96 }
97 
98 /*
99  * The functions pci_mmio_config*_addr provide a way to determine the MMIO address of a PCI
100  * config register. The address returned is dependent of both the MMCONF base address and the
101  * assigned PCI bus number of the requested device, which both can change during the boot
102  * process. Thus, the pointer returned here must not be cached!
103  */
104 static __always_inline
106 {
107  return (uint8_t *)&pci_map_bus(dev)->reg8[reg];
108 }
109 
110 static __always_inline
112 {
113  return (uint16_t *)&pci_map_bus(dev)->reg16[reg / sizeof(uint16_t)];
114 }
115 
116 static __always_inline
118 {
119  return (uint32_t *)&pci_map_bus(dev)->reg32[reg / sizeof(uint32_t)];
120 }
121 
122 #endif /* _PCI_MMIO_CFG_H */
pte_t value
Definition: mmu.c:91
#define __always_inline
Definition: compiler.h:35
static __always_inline uint32_t pci_s_read_config32(pci_devfn_t dev, uint16_t reg)
Definition: pci_mmio_cfg.h:75
volatile union pci_bank * pci_map_bus(pci_devfn_t dev)
Definition: pcie.c:115
static __always_inline uint16_t pci_s_read_config16(pci_devfn_t dev, uint16_t reg)
Definition: pci_mmio_cfg.h:69
static __always_inline uint8_t pci_s_read_config8(pci_devfn_t dev, uint16_t reg)
Definition: pci_mmio_cfg.h:63
static __always_inline void pci_s_write_config8(pci_devfn_t dev, uint16_t reg, uint8_t value)
Definition: pci_mmio_cfg.h:81
static __always_inline uint8_t * pci_mmio_config8_addr(pci_devfn_t dev, uint16_t reg)
Definition: pci_mmio_cfg.h:105
static __always_inline void pci_s_write_config16(pci_devfn_t dev, uint16_t reg, uint16_t value)
Definition: pci_mmio_cfg.h:87
static __always_inline uint32_t * pci_mmio_config32_addr(pci_devfn_t dev, uint16_t reg)
Definition: pci_mmio_cfg.h:117
static __always_inline uint16_t * pci_mmio_config16_addr(pci_devfn_t dev, uint16_t reg)
Definition: pci_mmio_cfg.h:111
static __always_inline void pci_s_write_config32(pci_devfn_t dev, uint16_t reg, uint32_t value)
Definition: pci_mmio_cfg.h:93
u8 *const pci_mmconf
Definition: pci_ops.c:10
u32 pci_devfn_t
Definition: pci_type.h:8
#define PCI_DEVFN_OFFSET(x)
Definition: pci_type.h:12
unsigned short uint16_t
Definition: stdint.h:11
unsigned int uint32_t
Definition: stdint.h:14
uint8_t u8
Definition: stdint.h:45
unsigned char uint8_t
Definition: stdint.h:8
uint8_t reg8[4096]
Definition: pci_mmio_cfg.h:23
uint16_t reg16[4096/sizeof(uint16_t)]
Definition: pci_mmio_cfg.h:24
uint32_t reg32[4096/sizeof(uint32_t)]
Definition: pci_mmio_cfg.h:25