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