|
16 | 16 | #include <linux/gpio/consumer.h>
|
17 | 17 | #include <linux/ioport.h>
|
18 | 18 | #include <linux/of.h>
|
| 19 | +#include <linux/pcie-dwc.h> |
19 | 20 | #include <linux/platform_device.h>
|
20 | 21 | #include <linux/sizes.h>
|
21 | 22 | #include <linux/types.h>
|
@@ -283,6 +284,45 @@ u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap)
|
283 | 284 | }
|
284 | 285 | EXPORT_SYMBOL_GPL(dw_pcie_find_ext_capability);
|
285 | 286 |
|
| 287 | +static u16 __dw_pcie_find_vsec_capability(struct dw_pcie *pci, u16 vendor_id, |
| 288 | + u16 vsec_id) |
| 289 | +{ |
| 290 | + u16 vsec = 0; |
| 291 | + u32 header; |
| 292 | + |
| 293 | + if (vendor_id != dw_pcie_readw_dbi(pci, PCI_VENDOR_ID)) |
| 294 | + return 0; |
| 295 | + |
| 296 | + while ((vsec = dw_pcie_find_next_ext_capability(pci, vsec, |
| 297 | + PCI_EXT_CAP_ID_VNDR))) { |
| 298 | + header = dw_pcie_readl_dbi(pci, vsec + PCI_VNDR_HEADER); |
| 299 | + if (PCI_VNDR_HEADER_ID(header) == vsec_id) |
| 300 | + return vsec; |
| 301 | + } |
| 302 | + |
| 303 | + return 0; |
| 304 | +} |
| 305 | + |
| 306 | +static u16 dw_pcie_find_vsec_capability(struct dw_pcie *pci, |
| 307 | + const struct dwc_pcie_vsec_id *vsec_ids) |
| 308 | +{ |
| 309 | + const struct dwc_pcie_vsec_id *vid; |
| 310 | + u16 vsec; |
| 311 | + u32 header; |
| 312 | + |
| 313 | + for (vid = vsec_ids; vid->vendor_id; vid++) { |
| 314 | + vsec = __dw_pcie_find_vsec_capability(pci, vid->vendor_id, |
| 315 | + vid->vsec_id); |
| 316 | + if (vsec) { |
| 317 | + header = dw_pcie_readl_dbi(pci, vsec + PCI_VNDR_HEADER); |
| 318 | + if (PCI_VNDR_HEADER_REV(header) == vid->vsec_rev) |
| 319 | + return vsec; |
| 320 | + } |
| 321 | + } |
| 322 | + |
| 323 | + return 0; |
| 324 | +} |
| 325 | + |
286 | 326 | int dw_pcie_read(void __iomem *addr, int size, u32 *val)
|
287 | 327 | {
|
288 | 328 | if (!IS_ALIGNED((uintptr_t)addr, size)) {
|
|
0 commit comments