xref: /aosp_15_r20/external/coreboot/src/include/device/pci_ops.h (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #ifndef PCI_OPS_H
4 #define PCI_OPS_H
5 
6 #include <stdint.h>
7 #include <device/device.h>
8 #include <device/pci_type.h>
9 #include <arch/pci_ops.h> /* IWYU pragma: export */
10 
11 void __noreturn pcidev_die(void);
12 
pcidev_bdf(const struct device * dev)13 static __always_inline pci_devfn_t pcidev_bdf(const struct device *dev)
14 {
15 	return (dev->path.pci.devfn << 12) | (dev->upstream->secondary << 20) |
16 		(dev->upstream->segment_group << 28);
17 }
18 
pcidev_assert(const struct device * dev)19 static __always_inline pci_devfn_t pcidev_assert(const struct device *dev)
20 {
21 	if (!dev)
22 		pcidev_die();
23 	return pcidev_bdf(dev);
24 }
25 
26 #if defined(__SIMPLE_DEVICE__)
27 #define ENV_PCI_SIMPLE_DEVICE 1
28 #else
29 #define ENV_PCI_SIMPLE_DEVICE 0
30 #endif
31 
32 #if ENV_PCI_SIMPLE_DEVICE
33 
34 /* Avoid name collisions as different stages have different signature
35  * for these functions. The _s_ stands for simple, fundamental IO or
36  * MMIO variant.
37  */
38 #define pci_read_config8 pci_s_read_config8
39 #define pci_read_config16 pci_s_read_config16
40 #define pci_read_config32 pci_s_read_config32
41 #define pci_write_config8 pci_s_write_config8
42 #define pci_write_config16 pci_s_write_config16
43 #define pci_write_config32 pci_s_write_config32
44 #else
45 
46 static __always_inline
pci_read_config8(const struct device * dev,u16 reg)47 u8 pci_read_config8(const struct device *dev, u16 reg)
48 {
49 	return pci_s_read_config8(PCI_BDF(dev), reg);
50 }
51 
52 static __always_inline
pci_read_config16(const struct device * dev,u16 reg)53 u16 pci_read_config16(const struct device *dev, u16 reg)
54 {
55 	return pci_s_read_config16(PCI_BDF(dev), reg);
56 }
57 
58 static __always_inline
pci_read_config32(const struct device * dev,u16 reg)59 u32 pci_read_config32(const struct device *dev, u16 reg)
60 {
61 	return pci_s_read_config32(PCI_BDF(dev), reg);
62 }
63 
64 static __always_inline
pci_write_config8(const struct device * dev,u16 reg,u8 val)65 void pci_write_config8(const struct device *dev, u16 reg, u8 val)
66 {
67 	pci_s_write_config8(PCI_BDF(dev), reg, val);
68 }
69 
70 static __always_inline
pci_write_config16(const struct device * dev,u16 reg,u16 val)71 void pci_write_config16(const struct device *dev, u16 reg, u16 val)
72 {
73 	pci_s_write_config16(PCI_BDF(dev), reg, val);
74 }
75 
76 static __always_inline
pci_write_config32(const struct device * dev,u16 reg,u32 val)77 void pci_write_config32(const struct device *dev, u16 reg, u32 val)
78 {
79 	pci_s_write_config32(PCI_BDF(dev), reg, val);
80 }
81 
82 #endif
83 
84 #if ENV_PCI_SIMPLE_DEVICE
85 static __always_inline
pci_update_config8(pci_devfn_t dev,u16 reg,u8 mask,u8 or)86 void pci_update_config8(pci_devfn_t dev, u16 reg, u8 mask, u8 or)
87 #else
88 static __always_inline
89 void pci_update_config8(const struct device *dev, u16 reg, u8 mask, u8 or)
90 #endif
91 {
92 	u8 reg8;
93 
94 	reg8 = pci_read_config8(dev, reg);
95 	reg8 &= mask;
96 	reg8 |= or;
97 	pci_write_config8(dev, reg, reg8);
98 }
99 
100 #if ENV_PCI_SIMPLE_DEVICE
101 static __always_inline
pci_update_config16(pci_devfn_t dev,u16 reg,u16 mask,u16 or)102 void pci_update_config16(pci_devfn_t dev, u16 reg, u16 mask, u16 or)
103 #else
104 static __always_inline
105 void pci_update_config16(const struct device *dev, u16 reg, u16 mask, u16 or)
106 #endif
107 {
108 	u16 reg16;
109 
110 	reg16 = pci_read_config16(dev, reg);
111 	reg16 &= mask;
112 	reg16 |= or;
113 	pci_write_config16(dev, reg, reg16);
114 }
115 
116 #if ENV_PCI_SIMPLE_DEVICE
117 static __always_inline
pci_update_config32(pci_devfn_t dev,u16 reg,u32 mask,u32 or)118 void pci_update_config32(pci_devfn_t dev, u16 reg, u32 mask, u32 or)
119 #else
120 static __always_inline
121 void pci_update_config32(const struct device *dev, u16 reg, u32 mask, u32 or)
122 #endif
123 {
124 	u32 reg32;
125 
126 	reg32 = pci_read_config32(dev, reg);
127 	reg32 &= mask;
128 	reg32 |= or;
129 	pci_write_config32(dev, reg, reg32);
130 }
131 
132 #if ENV_PCI_SIMPLE_DEVICE
133 static __always_inline
pci_and_config8(pci_devfn_t dev,u16 reg,u8 andmask)134 void pci_and_config8(pci_devfn_t dev, u16 reg, u8 andmask)
135 #else
136 static __always_inline
137 void pci_and_config8(const struct device *dev, u16 reg, u8 andmask)
138 #endif
139 {
140 	pci_update_config8(dev, reg, andmask, 0);
141 }
142 
143 #if ENV_PCI_SIMPLE_DEVICE
144 static __always_inline
pci_and_config16(pci_devfn_t dev,u16 reg,u16 andmask)145 void pci_and_config16(pci_devfn_t dev, u16 reg, u16 andmask)
146 #else
147 static __always_inline
148 void pci_and_config16(const struct device *dev, u16 reg, u16 andmask)
149 #endif
150 {
151 	pci_update_config16(dev, reg, andmask, 0);
152 }
153 
154 #if ENV_PCI_SIMPLE_DEVICE
155 static __always_inline
pci_and_config32(pci_devfn_t dev,u16 reg,u32 andmask)156 void pci_and_config32(pci_devfn_t dev, u16 reg, u32 andmask)
157 #else
158 static __always_inline
159 void pci_and_config32(const struct device *dev, u16 reg, u32 andmask)
160 #endif
161 {
162 	pci_update_config32(dev, reg, andmask, 0);
163 }
164 
165 #if ENV_PCI_SIMPLE_DEVICE
166 static __always_inline
pci_or_config8(pci_devfn_t dev,u16 reg,u8 ormask)167 void pci_or_config8(pci_devfn_t dev, u16 reg, u8 ormask)
168 #else
169 static __always_inline
170 void pci_or_config8(const struct device *dev, u16 reg, u8 ormask)
171 #endif
172 {
173 	pci_update_config8(dev, reg, 0xff, ormask);
174 }
175 
176 #if ENV_PCI_SIMPLE_DEVICE
177 static __always_inline
pci_or_config16(pci_devfn_t dev,u16 reg,u16 ormask)178 void pci_or_config16(pci_devfn_t dev, u16 reg, u16 ormask)
179 #else
180 static __always_inline
181 void pci_or_config16(const struct device *dev, u16 reg, u16 ormask)
182 #endif
183 {
184 	pci_update_config16(dev, reg, 0xffff, ormask);
185 }
186 
187 #if ENV_PCI_SIMPLE_DEVICE
188 static __always_inline
pci_or_config32(pci_devfn_t dev,u16 reg,u32 ormask)189 void pci_or_config32(pci_devfn_t dev, u16 reg, u32 ormask)
190 #else
191 static __always_inline
192 void pci_or_config32(const struct device *dev, u16 reg, u32 ormask)
193 #endif
194 {
195 	pci_update_config32(dev, reg, 0xffffffff, ormask);
196 }
197 
198 u16 pci_s_find_next_capability(pci_devfn_t dev, u16 cap, u16 last);
199 u16 pci_s_find_capability(pci_devfn_t dev, u16 cap);
200 
201 static __always_inline
pci_find_next_capability(const struct device * dev,u16 cap,u16 last)202 u16 pci_find_next_capability(const struct device *dev, u16 cap, u16 last)
203 {
204 	return pci_s_find_next_capability(PCI_BDF(dev), cap, last);
205 }
206 
207 static __always_inline
pci_find_capability(const struct device * dev,u16 cap)208 u16 pci_find_capability(const struct device *dev, u16 cap)
209 {
210 	return pci_s_find_capability(PCI_BDF(dev), cap);
211 }
212 
213 /*
214  * Determine if the given PCI device is the source of wake from sleep by checking PME_STATUS and
215  * PME_ENABLE bits in PM control and status register.
216  *
217  * Returns true if PCI device is wake source, false otherwise.
218  */
219 bool pci_dev_is_wake_source(pci_devfn_t dev);
220 
221 #endif /* PCI_OPS_H */
222