diff options
-rw-r--r-- | drivers/pci/host/pcie-iproc.c | 29 |
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 | |||
63 | static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) | 69 | static 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) | |||
138 | static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) | 144 | static 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 | ||