{
struct dw_pcie_ep *ep = &pci->ep;
u8 funcs = ep->epc->max_functions;
- u8 func_no;
+ u32 func0_lnkcap, lnkcap;
+ u8 func_no, offset;
dw_pcie_dbi_ro_wr_en(pci);
dw_pcie_ep_init_rebar_registers(ep, func_no);
dw_pcie_setup(pci);
+
+ /*
+ * PCIe r7.0, section 7.5.3.6 states that for multi-function
+ * endpoints, max link width and speed fields must report same
+ * values for all functions. However, dw_pcie_setup() programs
+ * these fields only for function 0. Hence, mirror these fields
+ * to all other functions as well.
+ */
+ if (funcs > 1) {
+ offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+ func0_lnkcap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP);
+ func0_lnkcap = FIELD_GET(PCI_EXP_LNKCAP_MLW |
+ PCI_EXP_LNKCAP_SLS, func0_lnkcap);
+
+ for (func_no = 1; func_no < funcs; func_no++) {
+ offset = dw_pcie_ep_find_capability(ep, func_no,
+ PCI_CAP_ID_EXP);
+ lnkcap = dw_pcie_ep_readl_dbi(ep, func_no,
+ offset + PCI_EXP_LNKCAP);
+ FIELD_MODIFY(PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS,
+ &lnkcap, func0_lnkcap);
+ dw_pcie_ep_writel_dbi(ep, func_no,
+ offset + PCI_EXP_LNKCAP, lnkcap);
+ }
+ }
+
dw_pcie_dbi_ro_wr_dis(pci);
}