Angel Pons | 5f249e6 | 2020-04-04 18:51:01 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Angel Pons | 5f249e6 | 2020-04-04 18:51:01 +0200 | [diff] [blame] | 2 | |
Patrick Rudolph | b94ecc4 | 2019-02-22 12:05:16 +0100 | [diff] [blame] | 3 | /* |
Patrick Rudolph | b94ecc4 | 2019-02-22 12:05:16 +0100 | [diff] [blame] | 4 | * Derived from Cavium's BSD-3 Clause OCTEONTX-SDK-6.2.0. |
| 5 | */ |
| 6 | |
Kyösti Mälkki | 9c0e14e | 2019-01-23 16:46:35 +0200 | [diff] [blame] | 7 | #define __SIMPLE_DEVICE__ |
| 8 | |
Patrick Rudolph | b94ecc4 | 2019-02-22 12:05:16 +0100 | [diff] [blame] | 9 | #include <device/pci_ops.h> |
Patrick Rudolph | b94ecc4 | 2019-02-22 12:05:16 +0100 | [diff] [blame] | 10 | #include <device/pci.h> |
| 11 | #include <soc/addressmap.h> |
| 12 | #include <soc/ecam.h> |
Patrick Rudolph | b94ecc4 | 2019-02-22 12:05:16 +0100 | [diff] [blame] | 13 | |
| 14 | /** |
| 15 | * Get PCI BAR address from cavium specific extended capability. |
| 16 | * Use regular BAR if not found in extended capability space. |
| 17 | * |
Kyösti Mälkki | 9c0e14e | 2019-01-23 16:46:35 +0200 | [diff] [blame] | 18 | * @return The physical address of the BAR, zero on error |
Patrick Rudolph | b94ecc4 | 2019-02-22 12:05:16 +0100 | [diff] [blame] | 19 | */ |
Patrick Rudolph | b94ecc4 | 2019-02-22 12:05:16 +0100 | [diff] [blame] | 20 | uint64_t ecam0_get_bar_val(pci_devfn_t dev, u8 bar) |
Patrick Rudolph | b94ecc4 | 2019-02-22 12:05:16 +0100 | [diff] [blame] | 21 | { |
Kyösti Mälkki | 9c0e14e | 2019-01-23 16:46:35 +0200 | [diff] [blame] | 22 | size_t cap_offset = pci_s_find_capability(dev, 0x14); |
Patrick Rudolph | b94ecc4 | 2019-02-22 12:05:16 +0100 | [diff] [blame] | 23 | uint64_t h, l, ret = 0; |
| 24 | if (cap_offset) { |
| 25 | /* Found EA */ |
| 26 | u8 es, bei; |
| 27 | u8 ne = pci_read_config8(dev, cap_offset + 2) & 0x3f; |
| 28 | |
| 29 | cap_offset += 4; |
| 30 | while (ne) { |
| 31 | uint32_t dw0 = pci_read_config32(dev, cap_offset); |
| 32 | |
| 33 | es = dw0 & 7; |
| 34 | bei = (dw0 >> 4) & 0xf; |
| 35 | if (bei == bar) { |
| 36 | h = 0; |
| 37 | l = pci_read_config32(dev, cap_offset + 4); |
| 38 | if (l & 2) |
| 39 | h = pci_read_config32(dev, |
| 40 | cap_offset + 12); |
| 41 | ret = (h << 32) | (l & ~0xfull); |
| 42 | break; |
| 43 | } |
| 44 | cap_offset += (es + 1) * 4; |
| 45 | ne--; |
| 46 | } |
| 47 | } else { |
| 48 | h = 0; |
| 49 | l = pci_read_config32(dev, bar * 4 + PCI_BASE_ADDRESS_0); |
| 50 | if (l & 4) |
| 51 | h = pci_read_config32(dev, bar * 4 + PCI_BASE_ADDRESS_0 |
| 52 | + 4); |
| 53 | ret = (h << 32) | (l & ~0xfull); |
| 54 | } |
| 55 | return ret; |
| 56 | } |