|
9 | 9 | */
|
10 | 10 |
|
11 | 11 | #include <linux/delay.h>
|
| 12 | +#include <linux/gpio.h> |
12 | 13 | #include <linux/interrupt.h>
|
13 | 14 | #include <linux/irq.h>
|
14 | 15 | #include <linux/irqdomain.h>
|
|
18 | 19 | #include <linux/platform_device.h>
|
19 | 20 | #include <linux/msi.h>
|
20 | 21 | #include <linux/of_address.h>
|
| 22 | +#include <linux/of_gpio.h> |
21 | 23 | #include <linux/of_pci.h>
|
22 | 24 |
|
23 | 25 | #include "../pci.h"
|
@@ -204,6 +206,7 @@ struct advk_pcie {
|
204 | 206 | int root_bus_nr;
|
205 | 207 | int link_gen;
|
206 | 208 | struct pci_bridge_emul bridge;
|
| 209 | + struct gpio_desc *reset_gpio; |
207 | 210 | };
|
208 | 211 |
|
209 | 212 | 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)
|
330 | 333 | dev_err(dev, "link never came up\n");
|
331 | 334 | }
|
332 | 335 |
|
| 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 | + |
333 | 355 | static void advk_pcie_setup_hw(struct advk_pcie *pcie)
|
334 | 356 | {
|
335 | 357 | u32 reg;
|
336 | 358 |
|
| 359 | + advk_pcie_issue_perst(pcie); |
| 360 | + |
337 | 361 | /* Set to Direct mode */
|
338 | 362 | reg = advk_readl(pcie, CTRL_CONFIG_REG);
|
339 | 363 | reg &= ~(CTRL_MODE_MASK << CTRL_MODE_SHIFT);
|
@@ -406,7 +430,8 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
|
406 | 430 |
|
407 | 431 | /*
|
408 | 432 | * 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 |
410 | 435 | * fundamental reset. As required by PCI Express spec a delay for at
|
411 | 436 | * least 100ms after such a reset before link training is needed.
|
412 | 437 | */
|
@@ -1046,6 +1071,22 @@ static int advk_pcie_probe(struct platform_device *pdev)
|
1046 | 1071 | }
|
1047 | 1072 | pcie->root_bus_nr = bus->start;
|
1048 | 1073 |
|
| 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 | + |
1049 | 1090 | ret = of_pci_get_max_link_speed(dev->of_node);
|
1050 | 1091 | if (ret <= 0 || ret > 3)
|
1051 | 1092 | pcie->link_gen = 3;
|
|
0 commit comments