|
33 | 33 | #define PCIE_CORE_CMD_STATUS_REG 0x4
|
34 | 34 | #define PCIE_CORE_DEV_REV_REG 0x8
|
35 | 35 | #define PCIE_CORE_PCIEXP_CAP 0xc0
|
| 36 | +#define PCIE_CORE_PCIERR_CAP 0x100 |
36 | 37 | #define PCIE_CORE_ERR_CAPCTL_REG 0x118
|
37 | 38 | #define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX BIT(5)
|
38 | 39 | #define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN BIT(6)
|
@@ -944,11 +945,89 @@ advk_pci_bridge_emul_pcie_conf_write(struct pci_bridge_emul *bridge,
|
944 | 945 | }
|
945 | 946 | }
|
946 | 947 |
|
| 948 | +static pci_bridge_emul_read_status_t |
| 949 | +advk_pci_bridge_emul_ext_conf_read(struct pci_bridge_emul *bridge, |
| 950 | + int reg, u32 *value) |
| 951 | +{ |
| 952 | + struct advk_pcie *pcie = bridge->data; |
| 953 | + |
| 954 | + switch (reg) { |
| 955 | + case 0: |
| 956 | + *value = advk_readl(pcie, PCIE_CORE_PCIERR_CAP + reg); |
| 957 | + |
| 958 | + /* |
| 959 | + * PCI_EXT_CAP_NEXT bits are set to offset 0x150, but Armada |
| 960 | + * 3700 Functional Specification does not document registers |
| 961 | + * at those addresses. |
| 962 | + * |
| 963 | + * Thus we clear PCI_EXT_CAP_NEXT bits to make Advanced Error |
| 964 | + * Reporting Capability header the last Extended Capability. |
| 965 | + * If we obtain documentation for those registers in the |
| 966 | + * future, this can be changed. |
| 967 | + */ |
| 968 | + *value &= 0x000fffff; |
| 969 | + return PCI_BRIDGE_EMUL_HANDLED; |
| 970 | + |
| 971 | + case PCI_ERR_UNCOR_STATUS: |
| 972 | + case PCI_ERR_UNCOR_MASK: |
| 973 | + case PCI_ERR_UNCOR_SEVER: |
| 974 | + case PCI_ERR_COR_STATUS: |
| 975 | + case PCI_ERR_COR_MASK: |
| 976 | + case PCI_ERR_CAP: |
| 977 | + case PCI_ERR_HEADER_LOG + 0: |
| 978 | + case PCI_ERR_HEADER_LOG + 4: |
| 979 | + case PCI_ERR_HEADER_LOG + 8: |
| 980 | + case PCI_ERR_HEADER_LOG + 12: |
| 981 | + case PCI_ERR_ROOT_COMMAND: |
| 982 | + case PCI_ERR_ROOT_STATUS: |
| 983 | + case PCI_ERR_ROOT_ERR_SRC: |
| 984 | + *value = advk_readl(pcie, PCIE_CORE_PCIERR_CAP + reg); |
| 985 | + return PCI_BRIDGE_EMUL_HANDLED; |
| 986 | + |
| 987 | + default: |
| 988 | + return PCI_BRIDGE_EMUL_NOT_HANDLED; |
| 989 | + } |
| 990 | +} |
| 991 | + |
| 992 | +static void |
| 993 | +advk_pci_bridge_emul_ext_conf_write(struct pci_bridge_emul *bridge, |
| 994 | + int reg, u32 old, u32 new, u32 mask) |
| 995 | +{ |
| 996 | + struct advk_pcie *pcie = bridge->data; |
| 997 | + |
| 998 | + switch (reg) { |
| 999 | + /* These are W1C registers, so clear other bits */ |
| 1000 | + case PCI_ERR_UNCOR_STATUS: |
| 1001 | + case PCI_ERR_COR_STATUS: |
| 1002 | + case PCI_ERR_ROOT_STATUS: |
| 1003 | + new &= mask; |
| 1004 | + fallthrough; |
| 1005 | + |
| 1006 | + case PCI_ERR_UNCOR_MASK: |
| 1007 | + case PCI_ERR_UNCOR_SEVER: |
| 1008 | + case PCI_ERR_COR_MASK: |
| 1009 | + case PCI_ERR_CAP: |
| 1010 | + case PCI_ERR_HEADER_LOG + 0: |
| 1011 | + case PCI_ERR_HEADER_LOG + 4: |
| 1012 | + case PCI_ERR_HEADER_LOG + 8: |
| 1013 | + case PCI_ERR_HEADER_LOG + 12: |
| 1014 | + case PCI_ERR_ROOT_COMMAND: |
| 1015 | + case PCI_ERR_ROOT_ERR_SRC: |
| 1016 | + advk_writel(pcie, new, PCIE_CORE_PCIERR_CAP + reg); |
| 1017 | + break; |
| 1018 | + |
| 1019 | + default: |
| 1020 | + break; |
| 1021 | + } |
| 1022 | +} |
| 1023 | + |
947 | 1024 | static const struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = {
|
948 | 1025 | .read_base = advk_pci_bridge_emul_base_conf_read,
|
949 | 1026 | .write_base = advk_pci_bridge_emul_base_conf_write,
|
950 | 1027 | .read_pcie = advk_pci_bridge_emul_pcie_conf_read,
|
951 | 1028 | .write_pcie = advk_pci_bridge_emul_pcie_conf_write,
|
| 1029 | + .read_ext = advk_pci_bridge_emul_ext_conf_read, |
| 1030 | + .write_ext = advk_pci_bridge_emul_ext_conf_write, |
952 | 1031 | };
|
953 | 1032 |
|
954 | 1033 | /*
|
|
0 commit comments