Skip to content

Commit 5169a98

Browse files
paliLorenzo Pieralisi
authored andcommitted
PCI: aardvark: Issue PERST via GPIO
Add support for issuing PERST via GPIO specified in 'reset-gpios' property (as described in PCI device tree bindings). Some buggy cards (e.g. Compex WLE900VX or WLE1216) are not detected after reboot when PERST is not issued during driver initialization. If bootloader already enabled link training then issuing PERST has no effect for some buggy cards (e.g. Compex WLE900VX) and these cards are not detected. We therefore clear the LINK_TRAINING_EN register before. It was observed that Compex WLE900VX card needs to be in PERST reset for at least 10ms if bootloader enabled link training. Tested on Turris MOX. 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: Lorenzo Pieralisi <[email protected]> Acked-by: Thomas Petazzoni <[email protected]>
1 parent 43fc679 commit 5169a98

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

drivers/pci/controller/pci-aardvark.c

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
#include <linux/delay.h>
12+
#include <linux/gpio.h>
1213
#include <linux/interrupt.h>
1314
#include <linux/irq.h>
1415
#include <linux/irqdomain.h>
@@ -18,6 +19,7 @@
1819
#include <linux/platform_device.h>
1920
#include <linux/msi.h>
2021
#include <linux/of_address.h>
22+
#include <linux/of_gpio.h>
2123
#include <linux/of_pci.h>
2224

2325
#include "../pci.h"
@@ -204,6 +206,7 @@ struct advk_pcie {
204206
int root_bus_nr;
205207
int link_gen;
206208
struct pci_bridge_emul bridge;
209+
struct gpio_desc *reset_gpio;
207210
};
208211

209212
static inline void advk_writel(struct advk_pcie *pcie, u32 val, u64 reg)
@@ -330,10 +333,31 @@ static void advk_pcie_train_link(struct advk_pcie *pcie)
330333
dev_err(dev, "link never came up\n");
331334
}
332335

336+
static void advk_pcie_issue_perst(struct advk_pcie *pcie)
337+
{
338+
u32 reg;
339+
340+
if (!pcie->reset_gpio)
341+
return;
342+
343+
/* PERST does not work for some cards when link training is enabled */
344+
reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
345+
reg &= ~LINK_TRAINING_EN;
346+
advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
347+
348+
/* 10ms delay is needed for some cards */
349+
dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n");
350+
gpiod_set_value_cansleep(pcie->reset_gpio, 1);
351+
usleep_range(10000, 11000);
352+
gpiod_set_value_cansleep(pcie->reset_gpio, 0);
353+
}
354+
333355
static void advk_pcie_setup_hw(struct advk_pcie *pcie)
334356
{
335357
u32 reg;
336358

359+
advk_pcie_issue_perst(pcie);
360+
337361
/* Set to Direct mode */
338362
reg = advk_readl(pcie, CTRL_CONFIG_REG);
339363
reg &= ~(CTRL_MODE_MASK << CTRL_MODE_SHIFT);
@@ -406,7 +430,8 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
406430

407431
/*
408432
* PERST# signal could have been asserted by pinctrl subsystem before
409-
* probe() callback has been called, making the endpoint going into
433+
* probe() callback has been called or issued explicitly by reset gpio
434+
* function advk_pcie_issue_perst(), making the endpoint going into
410435
* fundamental reset. As required by PCI Express spec a delay for at
411436
* least 100ms after such a reset before link training is needed.
412437
*/
@@ -1046,6 +1071,22 @@ static int advk_pcie_probe(struct platform_device *pdev)
10461071
}
10471072
pcie->root_bus_nr = bus->start;
10481073

1074+
pcie->reset_gpio = devm_gpiod_get_from_of_node(dev, dev->of_node,
1075+
"reset-gpios", 0,
1076+
GPIOD_OUT_LOW,
1077+
"pcie1-reset");
1078+
ret = PTR_ERR_OR_ZERO(pcie->reset_gpio);
1079+
if (ret) {
1080+
if (ret == -ENOENT) {
1081+
pcie->reset_gpio = NULL;
1082+
} else {
1083+
if (ret != -EPROBE_DEFER)
1084+
dev_err(dev, "Failed to get reset-gpio: %i\n",
1085+
ret);
1086+
return ret;
1087+
}
1088+
}
1089+
10491090
ret = of_pci_get_max_link_speed(dev->of_node);
10501091
if (ret <= 0 || ret > 3)
10511092
pcie->link_gen = 3;

0 commit comments

Comments
 (0)