bcm53xx: backport iProc Kconfig fixes
[openwrt/openwrt.git] / target / linux / bcm53xx / patches-4.1 / 144-PCI-iproc-Improve-link-detection-logic.patch
1 From aaf22ab4e916afa68a2e1aed4e913b76cbd58276 Mon Sep 17 00:00:00 2001
2 From: Ray Jui <rjui@broadcom.com>
3 Date: Tue, 15 Sep 2015 17:39:19 -0700
4 Subject: [PATCH 144/147] PCI: iproc: Improve link detection logic
5
6 Improve the link detection logic by explicitly querying the link status
7 register to ensure link is active.
8
9 Also force class to PCI_CLASS_BRIDGE_PCI (0x0604) through the host
10 configuration space register.
11
12 Signed-off-by: Ray Jui <rjui@broadcom.com>
13 Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
14 Reviewed-by: Anup Patel <anup.patel@broadcom.com>
15 Reviewed-by: Scott Branden <sbranden@broadcom.com>
16 ---
17 drivers/pci/host/pcie-iproc.c | 29 +++++++++++++++++++++++------
18 1 file changed, 23 insertions(+), 6 deletions(-)
19
20 --- a/drivers/pci/host/pcie-iproc.c
21 +++ b/drivers/pci/host/pcie-iproc.c
22 @@ -60,6 +60,12 @@
23 #define SYS_RC_INTX_EN 0x330
24 #define SYS_RC_INTX_MASK 0xf
25
26 +#define PCIE_LINK_STATUS_OFFSET 0xf0c
27 +#define PCIE_PHYLINKUP_SHIFT 3
28 +#define PCIE_PHYLINKUP BIT(PCIE_PHYLINKUP_SHIFT)
29 +#define PCIE_DL_ACTIVE_SHIFT 2
30 +#define PCIE_DL_ACTIVE BIT(PCIE_DL_ACTIVE_SHIFT)
31 +
32 static inline struct iproc_pcie *iproc_data(struct pci_bus *bus)
33 {
34 struct iproc_pcie *pcie;
35 @@ -138,9 +144,15 @@ static void iproc_pcie_reset(struct ipro
36 static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
37 {
38 u8 hdr_type;
39 - u32 link_ctrl;
40 + u32 link_ctrl, class, val;
41 u16 pos, link_status;
42 - int link_is_active = 0;
43 + bool link_is_active = false;
44 +
45 + val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET);
46 + if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) {
47 + dev_err(pcie->dev, "PHY or data link is INACTIVE!\n");
48 + return -ENODEV;
49 + }
50
51 /* make sure we are not in EP mode */
52 pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type);
53 @@ -150,14 +162,19 @@ static int iproc_pcie_check_link(struct
54 }
55
56 /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */
57 - pci_bus_write_config_word(bus, 0, PCI_CLASS_DEVICE,
58 - PCI_CLASS_BRIDGE_PCI);
59 +#define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c
60 +#define PCI_CLASS_BRIDGE_MASK 0xffff00
61 +#define PCI_CLASS_BRIDGE_SHIFT 8
62 + pci_bus_read_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, &class);
63 + class &= ~PCI_CLASS_BRIDGE_MASK;
64 + class |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT);
65 + pci_bus_write_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, class);
66
67 /* check link status to see if link is active */
68 pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP);
69 pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status);
70 if (link_status & PCI_EXP_LNKSTA_NLW)
71 - link_is_active = 1;
72 + link_is_active = true;
73
74 if (!link_is_active) {
75 /* try GEN 1 link speed */
76 @@ -181,7 +198,7 @@ static int iproc_pcie_check_link(struct
77 pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA,
78 &link_status);
79 if (link_status & PCI_EXP_LNKSTA_NLW)
80 - link_is_active = 1;
81 + link_is_active = true;
82 }
83 }
84