summaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-aardvark.c
diff options
context:
space:
mode:
authorPali Rohár <pali@kernel.org>2020-08-19 15:57:07 +0200
committerStefan Roese <sr@denx.de>2020-08-31 14:45:53 +0200
commit828d32621686aec593076d16445d39b9b8d49c05 (patch)
tree8268dbb7582a30ca52526cb87c13be6379d91846 /drivers/pci/pci-aardvark.c
parent563b85bd88772c8949d10f7fa8e39a20280b1aac (diff)
downloadu-boot-828d32621686aec593076d16445d39b9b8d49c05.tar.gz
u-boot-828d32621686aec593076d16445d39b9b8d49c05.tar.xz
u-boot-828d32621686aec593076d16445d39b9b8d49c05.zip
arm64: a37xx: pci: Assert PERST# signal when unloading driver
This change ensures that PCIe card is put into reset state when U-Boot stops using it. DM_FLAG_OS_PREPARE ensures that U-Boot executes driver's remove callback prior booting Linux kernel. Linux kernel pci-aardvark driver needs to reset PCIe card via PERST# signal prior initializing it. If it does not issue reset then some PCIe cards (specially Compex WiFi cards) are not detected at all. Putting PCIe card into reset state prior booting Linux kernel would ensure that card would be properly reset at time when Linux kernel starts initializing pci-aardvark driver. Signed-off-by: Pali Rohár <pali@kernel.org> Reviewed-by: Konstantin Porotchkin <kostap@marvell.com> Tested-by: Andre Heider <a.heider@gmail.com>
Diffstat (limited to 'drivers/pci/pci-aardvark.c')
-rw-r--r--drivers/pci/pci-aardvark.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/drivers/pci/pci-aardvark.c b/drivers/pci/pci-aardvark.c
index 5b3f23c184..8996be5309 100644
--- a/drivers/pci/pci-aardvark.c
+++ b/drivers/pci/pci-aardvark.c
@@ -148,6 +148,9 @@ struct pcie_advk {
void *base;
int first_busno;
struct udevice *dev;
+#if CONFIG_IS_ENABLED(DM_GPIO)
+ struct gpio_desc reset_gpio;
+#endif
};
static inline void advk_writel(struct pcie_advk *pcie, uint val, uint reg)
@@ -614,9 +617,7 @@ static int pcie_advk_probe(struct udevice *dev)
struct pcie_advk *pcie = dev_get_priv(dev);
#if CONFIG_IS_ENABLED(DM_GPIO)
- struct gpio_desc reset_gpio;
-
- gpio_request_by_name(dev, "reset-gpios", 0, &reset_gpio,
+ gpio_request_by_name(dev, "reset-gpios", 0, &pcie->reset_gpio,
GPIOD_IS_OUT);
/*
* Issue reset to add-in card through the dedicated GPIO.
@@ -631,11 +632,11 @@ static int pcie_advk_probe(struct udevice *dev)
* possible before PCIe PHY initialization. Moreover, the PCIe
* clock should be gated as well.
*/
- if (dm_gpio_is_valid(&reset_gpio)) {
+ if (dm_gpio_is_valid(&pcie->reset_gpio)) {
dev_dbg(pcie->dev, "Toggle PCIE Reset GPIO ...\n");
- dm_gpio_set_value(&reset_gpio, 1);
+ dm_gpio_set_value(&pcie->reset_gpio, 1);
mdelay(200);
- dm_gpio_set_value(&reset_gpio, 0);
+ dm_gpio_set_value(&pcie->reset_gpio, 0);
}
#else
dev_dbg(pcie->dev, "PCIE Reset on GPIO support is missing\n");
@@ -647,6 +648,18 @@ static int pcie_advk_probe(struct udevice *dev)
return pcie_advk_setup_hw(pcie);
}
+static int pcie_advk_remove(struct udevice *dev)
+{
+#if CONFIG_IS_ENABLED(DM_GPIO)
+ struct pcie_advk *pcie = dev_get_priv(dev);
+
+ if (dm_gpio_is_valid(&pcie->reset_gpio))
+ dm_gpio_set_value(&pcie->reset_gpio, 1);
+#endif /* DM_GPIO */
+
+ return 0;
+}
+
/**
* pcie_advk_ofdata_to_platdata() - Translate from DT to device state
*
@@ -687,5 +700,7 @@ U_BOOT_DRIVER(pcie_advk) = {
.ops = &pcie_advk_ops,
.ofdata_to_platdata = pcie_advk_ofdata_to_platdata,
.probe = pcie_advk_probe,
+ .remove = pcie_advk_remove,
+ .flags = DM_FLAG_OS_PREPARE,
.priv_auto_alloc_size = sizeof(struct pcie_advk),
};