Skip to content

Commit 43fc679

Browse files
elkabloLorenzo Pieralisi
authored andcommitted
PCI: aardvark: Improve link training
Currently the aardvark driver trains link in PCIe gen2 mode. This may cause some buggy gen1 cards (such as Compex WLE900VX) to be unstable or even not detected. Moreover when ASPM code tries to retrain link second time, these cards may stop responding and link goes down. If gen1 is used this does not happen. Unconditionally forcing gen1 is not a good solution since it may have performance impact on gen2 cards. To overcome this, read 'max-link-speed' property (as defined in PCI device tree bindings) and use this as max gen mode. Then iteratively try link training at this mode or lower until successful. After successful link training choose final controller gen based on Negotiated Link Speed from Link Status register, which should match card speed. Link: https://lore.kernel.org/r/[email protected] Tested-by: Tomasz Maciej Nowak <[email protected]> Signed-off-by: Pali Rohár <[email protected]> Signed-off-by: Marek Behún <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]> Reviewed-by: Rob Herring <[email protected]> Acked-by: Thomas Petazzoni <[email protected]>
1 parent 2dd9072 commit 43fc679

File tree

1 file changed

+89
-25
lines changed

1 file changed

+89
-25
lines changed

drivers/pci/controller/pci-aardvark.c

Lines changed: 89 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#define PCIE_CORE_LINK_CTRL_STAT_REG 0xd0
4141
#define PCIE_CORE_LINK_L0S_ENTRY BIT(0)
4242
#define PCIE_CORE_LINK_TRAINING BIT(5)
43+
#define PCIE_CORE_LINK_SPEED_SHIFT 16
4344
#define PCIE_CORE_LINK_WIDTH_SHIFT 20
4445
#define PCIE_CORE_ERR_CAPCTL_REG 0x118
4546
#define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX BIT(5)
@@ -201,6 +202,7 @@ struct advk_pcie {
201202
struct mutex msi_used_lock;
202203
u16 msi_msg;
203204
int root_bus_nr;
205+
int link_gen;
204206
struct pci_bridge_emul bridge;
205207
};
206208

@@ -225,20 +227,16 @@ static int advk_pcie_link_up(struct advk_pcie *pcie)
225227

226228
static int advk_pcie_wait_for_link(struct advk_pcie *pcie)
227229
{
228-
struct device *dev = &pcie->pdev->dev;
229230
int retries;
230231

231232
/* check if the link is up or not */
232233
for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
233-
if (advk_pcie_link_up(pcie)) {
234-
dev_info(dev, "link up\n");
234+
if (advk_pcie_link_up(pcie))
235235
return 0;
236-
}
237236

238237
usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
239238
}
240239

241-
dev_err(dev, "link never came up\n");
242240
return -ETIMEDOUT;
243241
}
244242

@@ -253,6 +251,85 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie)
253251
}
254252
}
255253

254+
static int advk_pcie_train_at_gen(struct advk_pcie *pcie, int gen)
255+
{
256+
int ret, neg_gen;
257+
u32 reg;
258+
259+
/* Setup link speed */
260+
reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
261+
reg &= ~PCIE_GEN_SEL_MSK;
262+
if (gen == 3)
263+
reg |= SPEED_GEN_3;
264+
else if (gen == 2)
265+
reg |= SPEED_GEN_2;
266+
else
267+
reg |= SPEED_GEN_1;
268+
advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
269+
270+
/*
271+
* Enable link training. This is not needed in every call to this
272+
* function, just once suffices, but it does not break anything either.
273+
*/
274+
reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
275+
reg |= LINK_TRAINING_EN;
276+
advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
277+
278+
/*
279+
* Start link training immediately after enabling it.
280+
* This solves problems for some buggy cards.
281+
*/
282+
reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
283+
reg |= PCIE_CORE_LINK_TRAINING;
284+
advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG);
285+
286+
ret = advk_pcie_wait_for_link(pcie);
287+
if (ret)
288+
return ret;
289+
290+
reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
291+
neg_gen = (reg >> PCIE_CORE_LINK_SPEED_SHIFT) & 0xf;
292+
293+
return neg_gen;
294+
}
295+
296+
static void advk_pcie_train_link(struct advk_pcie *pcie)
297+
{
298+
struct device *dev = &pcie->pdev->dev;
299+
int neg_gen = -1, gen;
300+
301+
/*
302+
* Try link training at link gen specified by device tree property
303+
* 'max-link-speed'. If this fails, iteratively train at lower gen.
304+
*/
305+
for (gen = pcie->link_gen; gen > 0; --gen) {
306+
neg_gen = advk_pcie_train_at_gen(pcie, gen);
307+
if (neg_gen > 0)
308+
break;
309+
}
310+
311+
if (neg_gen < 0)
312+
goto err;
313+
314+
/*
315+
* After successful training if negotiated gen is lower than requested,
316+
* train again on negotiated gen. This solves some stability issues for
317+
* some buggy gen1 cards.
318+
*/
319+
if (neg_gen < gen) {
320+
gen = neg_gen;
321+
neg_gen = advk_pcie_train_at_gen(pcie, gen);
322+
}
323+
324+
if (neg_gen == gen) {
325+
dev_info(dev, "link up at gen %i\n", gen);
326+
return;
327+
}
328+
329+
err:
330+
dev_err(dev, "link never came up\n");
331+
}
332+
256333
static void advk_pcie_setup_hw(struct advk_pcie *pcie)
257334
{
258335
u32 reg;
@@ -288,12 +365,6 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
288365
PCIE_CORE_CTRL2_TD_ENABLE;
289366
advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG);
290367

291-
/* Set GEN2 */
292-
reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
293-
reg &= ~PCIE_GEN_SEL_MSK;
294-
reg |= SPEED_GEN_2;
295-
advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
296-
297368
/* Set lane X1 */
298369
reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
299370
reg &= ~LANE_CNT_MSK;
@@ -341,20 +412,7 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
341412
*/
342413
msleep(PCI_PM_D3COLD_WAIT);
343414

344-
/* Enable link training */
345-
reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
346-
reg |= LINK_TRAINING_EN;
347-
advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
348-
349-
/*
350-
* Start link training immediately after enabling it.
351-
* This solves problems for some buggy cards.
352-
*/
353-
reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
354-
reg |= PCIE_CORE_LINK_TRAINING;
355-
advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG);
356-
357-
advk_pcie_wait_for_link(pcie);
415+
advk_pcie_train_link(pcie);
358416

359417
reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
360418
reg |= PCIE_CORE_CMD_MEM_ACCESS_EN |
@@ -988,6 +1046,12 @@ static int advk_pcie_probe(struct platform_device *pdev)
9881046
}
9891047
pcie->root_bus_nr = bus->start;
9901048

1049+
ret = of_pci_get_max_link_speed(dev->of_node);
1050+
if (ret <= 0 || ret > 3)
1051+
pcie->link_gen = 3;
1052+
else
1053+
pcie->link_gen = ret;
1054+
9911055
advk_pcie_setup_hw(pcie);
9921056

9931057
advk_sw_pci_bridge_init(pcie);

0 commit comments

Comments
 (0)