diff options
author | Ley Foon Tan <lftan@altera.com> | 2016-08-25 21:47:25 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2016-09-12 17:49:13 -0400 |
commit | ce4f1c7ad490aa7129bde5632d6e53943f8a866c (patch) | |
tree | 983786b7b3a1a332c0d20497f5cb23ff07ba10f0 | |
parent | 31fc0ad47e2e0b8417616aa0f1ddcc67edf1e109 (diff) |
PCI: altera: Move retrain from fixup to altera_pcie_host_init()
Previously we used a PCI early fixup to initiate a link retrain on Altera
devices. But Altera PCIe IP can be configured as either a Root Port or an
Endpoint, and they might have same vendor ID, so the fixup would be run for
both.
We only want to initiate a link retrain for Altera Root Port devices, not
for Endpoints, so move the link retrain functionality from the fixup to
altera_pcie_host_init().
[bhelgaas: changelog]
Signed-off-by: Ley Foon Tan <lftan@altera.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r-- | drivers/pci/host/pcie-altera.c | 151 |
1 files changed, 91 insertions, 60 deletions
diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c index 34e6258992c1..4ca50a28af82 100644 --- a/drivers/pci/host/pcie-altera.c +++ b/drivers/pci/host/pcie-altera.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #define RP_LTSSM_MASK 0x1f | 43 | #define RP_LTSSM_MASK 0x1f |
44 | #define LTSSM_L0 0xf | 44 | #define LTSSM_L0 0xf |
45 | 45 | ||
46 | #define PCIE_CAP_OFFSET 0x80 | ||
46 | /* TLP configuration type 0 and 1 */ | 47 | /* TLP configuration type 0 and 1 */ |
47 | #define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */ | 48 | #define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */ |
48 | #define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */ | 49 | #define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */ |
@@ -100,66 +101,6 @@ static bool altera_pcie_link_is_up(struct altera_pcie *pcie) | |||
100 | return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); | 101 | return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); |
101 | } | 102 | } |
102 | 103 | ||
103 | static void altera_wait_link_retrain(struct pci_dev *dev) | ||
104 | { | ||
105 | u16 reg16; | ||
106 | unsigned long start_jiffies; | ||
107 | struct altera_pcie *pcie = dev->bus->sysdata; | ||
108 | |||
109 | /* Wait for link training end. */ | ||
110 | start_jiffies = jiffies; | ||
111 | for (;;) { | ||
112 | pcie_capability_read_word(dev, PCI_EXP_LNKSTA, ®16); | ||
113 | if (!(reg16 & PCI_EXP_LNKSTA_LT)) | ||
114 | break; | ||
115 | |||
116 | if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) { | ||
117 | dev_err(&pcie->pdev->dev, "link retrain timeout\n"); | ||
118 | break; | ||
119 | } | ||
120 | udelay(100); | ||
121 | } | ||
122 | |||
123 | /* Wait for link is up */ | ||
124 | start_jiffies = jiffies; | ||
125 | for (;;) { | ||
126 | if (altera_pcie_link_is_up(pcie)) | ||
127 | break; | ||
128 | |||
129 | if (time_after(jiffies, start_jiffies + LINK_UP_TIMEOUT)) { | ||
130 | dev_err(&pcie->pdev->dev, "link up timeout\n"); | ||
131 | break; | ||
132 | } | ||
133 | udelay(100); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | static void altera_pcie_retrain(struct pci_dev *dev) | ||
138 | { | ||
139 | u16 linkcap, linkstat; | ||
140 | struct altera_pcie *pcie = dev->bus->sysdata; | ||
141 | |||
142 | if (!altera_pcie_link_is_up(pcie)) | ||
143 | return; | ||
144 | |||
145 | /* | ||
146 | * Set the retrain bit if the PCIe rootport support > 2.5GB/s, but | ||
147 | * current speed is 2.5 GB/s. | ||
148 | */ | ||
149 | pcie_capability_read_word(dev, PCI_EXP_LNKCAP, &linkcap); | ||
150 | |||
151 | if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB) | ||
152 | return; | ||
153 | |||
154 | pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &linkstat); | ||
155 | if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) { | ||
156 | pcie_capability_set_word(dev, PCI_EXP_LNKCTL, | ||
157 | PCI_EXP_LNKCTL_RL); | ||
158 | altera_wait_link_retrain(dev); | ||
159 | } | ||
160 | } | ||
161 | DECLARE_PCI_FIXUP_EARLY(0x1172, PCI_ANY_ID, altera_pcie_retrain); | ||
162 | |||
163 | /* | 104 | /* |
164 | * Altera PCIe port uses BAR0 of RC's configuration space as the translation | 105 | * Altera PCIe port uses BAR0 of RC's configuration space as the translation |
165 | * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space | 106 | * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space |
@@ -434,6 +375,90 @@ static struct pci_ops altera_pcie_ops = { | |||
434 | .write = altera_pcie_cfg_write, | 375 | .write = altera_pcie_cfg_write, |
435 | }; | 376 | }; |
436 | 377 | ||
378 | static int altera_read_cap_word(struct altera_pcie *pcie, u8 busno, | ||
379 | unsigned int devfn, int offset, u16 *value) | ||
380 | { | ||
381 | u32 data; | ||
382 | int ret; | ||
383 | |||
384 | ret = _altera_pcie_cfg_read(pcie, busno, devfn, | ||
385 | PCIE_CAP_OFFSET + offset, sizeof(*value), | ||
386 | &data); | ||
387 | *value = data; | ||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | static int altera_write_cap_word(struct altera_pcie *pcie, u8 busno, | ||
392 | unsigned int devfn, int offset, u16 value) | ||
393 | { | ||
394 | return _altera_pcie_cfg_write(pcie, busno, devfn, | ||
395 | PCIE_CAP_OFFSET + offset, sizeof(value), | ||
396 | value); | ||
397 | } | ||
398 | |||
399 | static void altera_wait_link_retrain(struct altera_pcie *pcie) | ||
400 | { | ||
401 | u16 reg16; | ||
402 | unsigned long start_jiffies; | ||
403 | |||
404 | /* Wait for link training end. */ | ||
405 | start_jiffies = jiffies; | ||
406 | for (;;) { | ||
407 | altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, | ||
408 | PCI_EXP_LNKSTA, ®16); | ||
409 | if (!(reg16 & PCI_EXP_LNKSTA_LT)) | ||
410 | break; | ||
411 | |||
412 | if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) { | ||
413 | dev_err(&pcie->pdev->dev, "link retrain timeout\n"); | ||
414 | break; | ||
415 | } | ||
416 | udelay(100); | ||
417 | } | ||
418 | |||
419 | /* Wait for link is up */ | ||
420 | start_jiffies = jiffies; | ||
421 | for (;;) { | ||
422 | if (altera_pcie_link_is_up(pcie)) | ||
423 | break; | ||
424 | |||
425 | if (time_after(jiffies, start_jiffies + LINK_UP_TIMEOUT)) { | ||
426 | dev_err(&pcie->pdev->dev, "link up timeout\n"); | ||
427 | break; | ||
428 | } | ||
429 | udelay(100); | ||
430 | } | ||
431 | } | ||
432 | |||
433 | static void altera_pcie_retrain(struct altera_pcie *pcie) | ||
434 | { | ||
435 | u16 linkcap, linkstat, linkctl; | ||
436 | |||
437 | if (!altera_pcie_link_is_up(pcie)) | ||
438 | return; | ||
439 | |||
440 | /* | ||
441 | * Set the retrain bit if the PCIe rootport support > 2.5GB/s, but | ||
442 | * current speed is 2.5 GB/s. | ||
443 | */ | ||
444 | altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, PCI_EXP_LNKCAP, | ||
445 | &linkcap); | ||
446 | if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB) | ||
447 | return; | ||
448 | |||
449 | altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, PCI_EXP_LNKSTA, | ||
450 | &linkstat); | ||
451 | if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) { | ||
452 | altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, | ||
453 | PCI_EXP_LNKCTL, &linkctl); | ||
454 | linkctl |= PCI_EXP_LNKCTL_RL; | ||
455 | altera_write_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, | ||
456 | PCI_EXP_LNKCTL, linkctl); | ||
457 | |||
458 | altera_wait_link_retrain(pcie); | ||
459 | } | ||
460 | } | ||
461 | |||
437 | static int altera_pcie_intx_map(struct irq_domain *domain, unsigned int irq, | 462 | static int altera_pcie_intx_map(struct irq_domain *domain, unsigned int irq, |
438 | irq_hw_number_t hwirq) | 463 | irq_hw_number_t hwirq) |
439 | { | 464 | { |
@@ -555,6 +580,11 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) | |||
555 | return 0; | 580 | return 0; |
556 | } | 581 | } |
557 | 582 | ||
583 | static void altera_pcie_host_init(struct altera_pcie *pcie) | ||
584 | { | ||
585 | altera_pcie_retrain(pcie); | ||
586 | } | ||
587 | |||
558 | static int altera_pcie_probe(struct platform_device *pdev) | 588 | static int altera_pcie_probe(struct platform_device *pdev) |
559 | { | 589 | { |
560 | struct altera_pcie *pcie; | 590 | struct altera_pcie *pcie; |
@@ -592,6 +622,7 @@ static int altera_pcie_probe(struct platform_device *pdev) | |||
592 | cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); | 622 | cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); |
593 | /* enable all interrupts */ | 623 | /* enable all interrupts */ |
594 | cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); | 624 | cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); |
625 | altera_pcie_host_init(pcie); | ||
595 | 626 | ||
596 | bus = pci_scan_root_bus(&pdev->dev, pcie->root_bus_nr, &altera_pcie_ops, | 627 | bus = pci_scan_root_bus(&pdev->dev, pcie->root_bus_nr, &altera_pcie_ops, |
597 | pcie, &pcie->resources); | 628 | pcie, &pcie->resources); |