aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRay Jui <rjui@broadcom.com>2015-09-15 20:39:19 -0400
committerBjorn Helgaas <bhelgaas@google.com>2015-09-25 19:19:40 -0400
commitaaf22ab4e916afa68a2e1aed4e913b76cbd58276 (patch)
treea8919fe24159c70010e73b7178bb23bd92438cac
parent199ff14100095d52cd1b232cc0f3b12f348b5b07 (diff)
PCI: iproc: Improve link detection logic
Improve the link detection logic by explicitly querying the link status register to ensure link is active. Also force class to PCI_CLASS_BRIDGE_PCI (0x0604) through the host configuration space register. Signed-off-by: Ray Jui <rjui@broadcom.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Anup Patel <anup.patel@broadcom.com> Reviewed-by: Scott Branden <sbranden@broadcom.com>
-rw-r--r--drivers/pci/host/pcie-iproc.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/host/pcie-iproc.c
index 80e0541548a1..62e80855aed1 100644
--- a/drivers/pci/host/pcie-iproc.c
+++ b/drivers/pci/host/pcie-iproc.c
@@ -60,6 +60,12 @@
60#define SYS_RC_INTX_EN 0x330 60#define SYS_RC_INTX_EN 0x330
61#define SYS_RC_INTX_MASK 0xf 61#define SYS_RC_INTX_MASK 0xf
62 62
63#define PCIE_LINK_STATUS_OFFSET 0xf0c
64#define PCIE_PHYLINKUP_SHIFT 3
65#define PCIE_PHYLINKUP BIT(PCIE_PHYLINKUP_SHIFT)
66#define PCIE_DL_ACTIVE_SHIFT 2
67#define PCIE_DL_ACTIVE BIT(PCIE_DL_ACTIVE_SHIFT)
68
63static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) 69static inline struct iproc_pcie *iproc_data(struct pci_bus *bus)
64{ 70{
65 struct iproc_pcie *pcie; 71 struct iproc_pcie *pcie;
@@ -138,9 +144,15 @@ static void iproc_pcie_reset(struct iproc_pcie *pcie)
138static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) 144static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
139{ 145{
140 u8 hdr_type; 146 u8 hdr_type;
141 u32 link_ctrl; 147 u32 link_ctrl, class, val;
142 u16 pos, link_status; 148 u16 pos, link_status;
143 int link_is_active = 0; 149 bool link_is_active = false;
150
151 val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET);
152 if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) {
153 dev_err(pcie->dev, "PHY or data link is INACTIVE!\n");
154 return -ENODEV;
155 }
144 156
145 /* make sure we are not in EP mode */ 157 /* make sure we are not in EP mode */
146 pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type); 158 pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type);
@@ -150,14 +162,19 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
150 } 162 }
151 163
152 /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */ 164 /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */
153 pci_bus_write_config_word(bus, 0, PCI_CLASS_DEVICE, 165#define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c
154 PCI_CLASS_BRIDGE_PCI); 166#define PCI_CLASS_BRIDGE_MASK 0xffff00
167#define PCI_CLASS_BRIDGE_SHIFT 8
168 pci_bus_read_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, &class);
169 class &= ~PCI_CLASS_BRIDGE_MASK;
170 class |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT);
171 pci_bus_write_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, class);
155 172
156 /* check link status to see if link is active */ 173 /* check link status to see if link is active */
157 pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP); 174 pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP);
158 pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status); 175 pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status);
159 if (link_status & PCI_EXP_LNKSTA_NLW) 176 if (link_status & PCI_EXP_LNKSTA_NLW)
160 link_is_active = 1; 177 link_is_active = true;
161 178
162 if (!link_is_active) { 179 if (!link_is_active) {
163 /* try GEN 1 link speed */ 180 /* try GEN 1 link speed */
@@ -181,7 +198,7 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
181 pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, 198 pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA,
182 &link_status); 199 &link_status);
183 if (link_status & PCI_EXP_LNKSTA_NLW) 200 if (link_status & PCI_EXP_LNKSTA_NLW)
184 link_is_active = 1; 201 link_is_active = true;
185 } 202 }
186 } 203 }
187 204