Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: altera: Add Stratix 10 PCIe support

Add PCIe Root Port support for Stratix 10 device.

Main differences compared to the PCIe Root Port IP on Cyclone V
and Arria 10 devices:

- HIP interface to access Root Port configuration register
- TLP programming flow:
- One REG0 register
- Don't need to check alignment

Signed-off-by: Ley Foon Tan <ley.foon.tan@intel.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

authored by

Ley Foon Tan and committed by
Lorenzo Pieralisi
49fdbd7c bfeffd15

+246 -24
+246 -24
drivers/pci/controller/pcie-altera.c
··· 11 11 #include <linux/irqchip/chained_irq.h> 12 12 #include <linux/init.h> 13 13 #include <linux/of_address.h> 14 + #include <linux/of_device.h> 14 15 #include <linux/of_irq.h> 15 16 #include <linux/of_pci.h> 16 17 #include <linux/pci.h> ··· 38 37 #define RP_LTSSM_MASK 0x1f 39 38 #define LTSSM_L0 0xf 40 39 41 - #define PCIE_CAP_OFFSET 0x80 40 + #define S10_RP_TX_CNTRL 0x2004 41 + #define S10_RP_RXCPL_REG 0x2008 42 + #define S10_RP_RXCPL_STATUS 0x200C 43 + #define S10_RP_CFG_ADDR(pcie, reg) \ 44 + (((pcie)->hip_base) + (reg) + (1 << 20)) 45 + 42 46 /* TLP configuration type 0 and 1 */ 43 47 #define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */ 44 48 #define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */ ··· 55 49 #define RP_DEVFN 0 56 50 #define TLP_REQ_ID(bus, devfn) (((bus) << 8) | (devfn)) 57 51 #define TLP_CFGRD_DW0(pcie, bus) \ 58 - ((((bus == pcie->root_bus_nr) ? TLP_FMTTYPE_CFGRD0 \ 59 - : TLP_FMTTYPE_CFGRD1) << 24) | \ 60 - TLP_PAYLOAD_SIZE) 52 + ((((bus == pcie->root_bus_nr) ? pcie->pcie_data->cfgrd0 \ 53 + : pcie->pcie_data->cfgrd1) << 24) | \ 54 + TLP_PAYLOAD_SIZE) 61 55 #define TLP_CFGWR_DW0(pcie, bus) \ 62 - ((((bus == pcie->root_bus_nr) ? TLP_FMTTYPE_CFGWR0 \ 63 - : TLP_FMTTYPE_CFGWR1) << 24) | \ 64 - TLP_PAYLOAD_SIZE) 56 + ((((bus == pcie->root_bus_nr) ? pcie->pcie_data->cfgwr0 \ 57 + : pcie->pcie_data->cfgwr1) << 24) | \ 58 + TLP_PAYLOAD_SIZE) 65 59 #define TLP_CFG_DW1(pcie, tag, be) \ 66 - (((TLP_REQ_ID(pcie->root_bus_nr, RP_DEVFN)) << 16) | (tag << 8) | (be)) 60 + (((TLP_REQ_ID(pcie->root_bus_nr, RP_DEVFN)) << 16) | (tag << 8) | (be)) 67 61 #define TLP_CFG_DW2(bus, devfn, offset) \ 68 62 (((bus) << 24) | ((devfn) << 16) | (offset)) 69 63 #define TLP_COMP_STATUS(s) (((s) >> 13) & 7) 64 + #define TLP_BYTE_COUNT(s) (((s) >> 0) & 0xfff) 70 65 #define TLP_HDR_SIZE 3 71 66 #define TLP_LOOP 500 72 67 ··· 76 69 77 70 #define DWORD_MASK 3 78 71 72 + #define S10_TLP_FMTTYPE_CFGRD0 0x05 73 + #define S10_TLP_FMTTYPE_CFGRD1 0x04 74 + #define S10_TLP_FMTTYPE_CFGWR0 0x45 75 + #define S10_TLP_FMTTYPE_CFGWR1 0x44 76 + 77 + enum altera_pcie_version { 78 + ALTERA_PCIE_V1 = 0, 79 + ALTERA_PCIE_V2, 80 + }; 81 + 79 82 struct altera_pcie { 80 83 struct platform_device *pdev; 81 - void __iomem *cra_base; /* DT Cra */ 84 + void __iomem *cra_base; 85 + void __iomem *hip_base; 82 86 int irq; 83 87 u8 root_bus_nr; 84 88 struct irq_domain *irq_domain; 85 89 struct resource bus_range; 86 90 struct list_head resources; 91 + const struct altera_pcie_data *pcie_data; 92 + }; 93 + 94 + struct altera_pcie_ops { 95 + int (*tlp_read_pkt)(struct altera_pcie *pcie, u32 *value); 96 + void (*tlp_write_pkt)(struct altera_pcie *pcie, u32 *headers, 97 + u32 data, bool align); 98 + bool (*get_link_status)(struct altera_pcie *pcie); 99 + int (*rp_read_cfg)(struct altera_pcie *pcie, int where, 100 + int size, u32 *value); 101 + int (*rp_write_cfg)(struct altera_pcie *pcie, u8 busno, 102 + int where, int size, u32 value); 103 + }; 104 + 105 + struct altera_pcie_data { 106 + const struct altera_pcie_ops *ops; 107 + enum altera_pcie_version version; 108 + u32 cap_offset; /* PCIe capability structure register offset */ 109 + u32 cfgrd0; 110 + u32 cfgrd1; 111 + u32 cfgwr0; 112 + u32 cfgwr1; 87 113 }; 88 114 89 115 struct tlp_rp_regpair_t { ··· 139 99 static bool altera_pcie_link_up(struct altera_pcie *pcie) 140 100 { 141 101 return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); 102 + } 103 + 104 + static bool s10_altera_pcie_link_up(struct altera_pcie *pcie) 105 + { 106 + void __iomem *addr = S10_RP_CFG_ADDR(pcie, 107 + pcie->pcie_data->cap_offset + 108 + PCI_EXP_LNKSTA); 109 + 110 + return !!(readw(addr) & PCI_EXP_LNKSTA_DLLLA); 142 111 } 143 112 144 113 /* ··· 177 128 cra_writel(pcie, tlp_rp_regdata->ctrl, RP_TX_CNTRL); 178 129 } 179 130 131 + static void s10_tlp_write_tx(struct altera_pcie *pcie, u32 reg0, u32 ctrl) 132 + { 133 + cra_writel(pcie, reg0, RP_TX_REG0); 134 + cra_writel(pcie, ctrl, S10_RP_TX_CNTRL); 135 + } 136 + 180 137 static bool altera_pcie_valid_device(struct altera_pcie *pcie, 181 138 struct pci_bus *bus, int dev) 182 139 { 183 140 /* If there is no link, then there is no device */ 184 141 if (bus->number != pcie->root_bus_nr) { 185 - if (!altera_pcie_link_up(pcie)) 142 + if (!pcie->pcie_data->ops->get_link_status(pcie)) 186 143 return false; 187 144 } 188 145 ··· 238 183 return PCIBIOS_DEVICE_NOT_FOUND; 239 184 } 240 185 186 + static int s10_tlp_read_packet(struct altera_pcie *pcie, u32 *value) 187 + { 188 + u32 ctrl; 189 + u32 comp_status; 190 + u32 dw[4]; 191 + u32 count; 192 + struct device *dev = &pcie->pdev->dev; 193 + 194 + for (count = 0; count < TLP_LOOP; count++) { 195 + ctrl = cra_readl(pcie, S10_RP_RXCPL_STATUS); 196 + if (ctrl & RP_RXCPL_SOP) { 197 + /* Read first DW */ 198 + dw[0] = cra_readl(pcie, S10_RP_RXCPL_REG); 199 + break; 200 + } 201 + 202 + udelay(5); 203 + } 204 + 205 + /* SOP detection failed, return error */ 206 + if (count == TLP_LOOP) 207 + return PCIBIOS_DEVICE_NOT_FOUND; 208 + 209 + count = 1; 210 + 211 + /* Poll for EOP */ 212 + while (count < ARRAY_SIZE(dw)) { 213 + ctrl = cra_readl(pcie, S10_RP_RXCPL_STATUS); 214 + dw[count++] = cra_readl(pcie, S10_RP_RXCPL_REG); 215 + if (ctrl & RP_RXCPL_EOP) { 216 + comp_status = TLP_COMP_STATUS(dw[1]); 217 + if (comp_status) 218 + return PCIBIOS_DEVICE_NOT_FOUND; 219 + 220 + if (value && TLP_BYTE_COUNT(dw[1]) == sizeof(u32) && 221 + count == 4) 222 + *value = dw[3]; 223 + 224 + return PCIBIOS_SUCCESSFUL; 225 + } 226 + } 227 + 228 + dev_warn(dev, "Malformed TLP packet\n"); 229 + 230 + return PCIBIOS_DEVICE_NOT_FOUND; 231 + } 232 + 241 233 static void tlp_write_packet(struct altera_pcie *pcie, u32 *headers, 242 234 u32 data, bool align) 243 235 { ··· 312 210 tlp_write_tx(pcie, &tlp_rp_regdata); 313 211 } 314 212 213 + static void s10_tlp_write_packet(struct altera_pcie *pcie, u32 *headers, 214 + u32 data, bool dummy) 215 + { 216 + s10_tlp_write_tx(pcie, headers[0], RP_TX_SOP); 217 + s10_tlp_write_tx(pcie, headers[1], 0); 218 + s10_tlp_write_tx(pcie, headers[2], 0); 219 + s10_tlp_write_tx(pcie, data, RP_TX_EOP); 220 + } 221 + 315 222 static int tlp_cfg_dword_read(struct altera_pcie *pcie, u8 bus, u32 devfn, 316 223 int where, u8 byte_en, u32 *value) 317 224 { ··· 330 219 headers[1] = TLP_CFG_DW1(pcie, TLP_READ_TAG, byte_en); 331 220 headers[2] = TLP_CFG_DW2(bus, devfn, where); 332 221 333 - tlp_write_packet(pcie, headers, 0, false); 222 + pcie->pcie_data->ops->tlp_write_pkt(pcie, headers, 0, false); 334 223 335 - return tlp_read_packet(pcie, value); 224 + return pcie->pcie_data->ops->tlp_read_pkt(pcie, value); 336 225 } 337 226 338 227 static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, ··· 347 236 348 237 /* check alignment to Qword */ 349 238 if ((where & 0x7) == 0) 350 - tlp_write_packet(pcie, headers, value, true); 239 + pcie->pcie_data->ops->tlp_write_pkt(pcie, headers, 240 + value, true); 351 241 else 352 - tlp_write_packet(pcie, headers, value, false); 242 + pcie->pcie_data->ops->tlp_write_pkt(pcie, headers, 243 + value, false); 353 244 354 - ret = tlp_read_packet(pcie, NULL); 245 + ret = pcie->pcie_data->ops->tlp_read_pkt(pcie, NULL); 355 246 if (ret != PCIBIOS_SUCCESSFUL) 356 247 return ret; 357 248 ··· 367 254 return PCIBIOS_SUCCESSFUL; 368 255 } 369 256 257 + static int s10_rp_read_cfg(struct altera_pcie *pcie, int where, 258 + int size, u32 *value) 259 + { 260 + void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); 261 + 262 + switch (size) { 263 + case 1: 264 + *value = readb(addr); 265 + break; 266 + case 2: 267 + *value = readw(addr); 268 + break; 269 + default: 270 + *value = readl(addr); 271 + break; 272 + } 273 + 274 + return PCIBIOS_SUCCESSFUL; 275 + } 276 + 277 + static int s10_rp_write_cfg(struct altera_pcie *pcie, u8 busno, 278 + int where, int size, u32 value) 279 + { 280 + void __iomem *addr = S10_RP_CFG_ADDR(pcie, where); 281 + 282 + switch (size) { 283 + case 1: 284 + writeb(value, addr); 285 + break; 286 + case 2: 287 + writew(value, addr); 288 + break; 289 + default: 290 + writel(value, addr); 291 + break; 292 + } 293 + 294 + /* 295 + * Monitor changes to PCI_PRIMARY_BUS register on root port 296 + * and update local copy of root bus number accordingly. 297 + */ 298 + if (busno == pcie->root_bus_nr && where == PCI_PRIMARY_BUS) 299 + pcie->root_bus_nr = value & 0xff; 300 + 301 + return PCIBIOS_SUCCESSFUL; 302 + } 303 + 370 304 static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, 371 305 unsigned int devfn, int where, int size, 372 306 u32 *value) ··· 421 261 int ret; 422 262 u32 data; 423 263 u8 byte_en; 264 + 265 + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_read_cfg) 266 + return pcie->pcie_data->ops->rp_read_cfg(pcie, where, 267 + size, value); 424 268 425 269 switch (size) { 426 270 case 1: ··· 465 301 u32 data32; 466 302 u32 shift = 8 * (where & 3); 467 303 u8 byte_en; 304 + 305 + if (busno == pcie->root_bus_nr && pcie->pcie_data->ops->rp_write_cfg) 306 + return pcie->pcie_data->ops->rp_write_cfg(pcie, busno, 307 + where, size, value); 468 308 469 309 switch (size) { 470 310 case 1: ··· 533 365 int ret; 534 366 535 367 ret = _altera_pcie_cfg_read(pcie, busno, devfn, 536 - PCIE_CAP_OFFSET + offset, sizeof(*value), 368 + pcie->pcie_data->cap_offset + offset, 369 + sizeof(*value), 537 370 &data); 538 371 *value = data; 539 372 return ret; ··· 544 375 unsigned int devfn, int offset, u16 value) 545 376 { 546 377 return _altera_pcie_cfg_write(pcie, busno, devfn, 547 - PCIE_CAP_OFFSET + offset, sizeof(value), 378 + pcie->pcie_data->cap_offset + offset, 379 + sizeof(value), 548 380 value); 549 381 } 550 382 ··· 573 403 /* Wait for link is up */ 574 404 start_jiffies = jiffies; 575 405 for (;;) { 576 - if (altera_pcie_link_up(pcie)) 406 + if (pcie->pcie_data->ops->get_link_status(pcie)) 577 407 break; 578 408 579 409 if (time_after(jiffies, start_jiffies + LINK_UP_TIMEOUT)) { ··· 588 418 { 589 419 u16 linkcap, linkstat, linkctl; 590 420 591 - if (!altera_pcie_link_up(pcie)) 421 + if (!pcie->pcie_data->ops->get_link_status(pcie)) 592 422 return; 593 423 594 424 /* ··· 710 540 struct device *dev = &pcie->pdev->dev; 711 541 struct platform_device *pdev = pcie->pdev; 712 542 struct resource *cra; 543 + struct resource *hip; 713 544 714 545 cra = platform_get_resource_byname(pdev, IORESOURCE_MEM, "Cra"); 715 546 pcie->cra_base = devm_ioremap_resource(dev, cra); 716 547 if (IS_ERR(pcie->cra_base)) 717 548 return PTR_ERR(pcie->cra_base); 549 + 550 + if (pcie->pcie_data->version == ALTERA_PCIE_V2) { 551 + hip = platform_get_resource_byname(pdev, IORESOURCE_MEM, "Hip"); 552 + pcie->hip_base = devm_ioremap_resource(&pdev->dev, hip); 553 + if (IS_ERR(pcie->hip_base)) 554 + return PTR_ERR(pcie->hip_base); 555 + } 718 556 719 557 /* setup IRQ */ 720 558 pcie->irq = platform_get_irq(pdev, 0); ··· 740 562 altera_pcie_retrain(pcie); 741 563 } 742 564 565 + static const struct altera_pcie_ops altera_pcie_ops_1_0 = { 566 + .tlp_read_pkt = tlp_read_packet, 567 + .tlp_write_pkt = tlp_write_packet, 568 + .get_link_status = altera_pcie_link_up, 569 + }; 570 + 571 + static const struct altera_pcie_ops altera_pcie_ops_2_0 = { 572 + .tlp_read_pkt = s10_tlp_read_packet, 573 + .tlp_write_pkt = s10_tlp_write_packet, 574 + .get_link_status = s10_altera_pcie_link_up, 575 + .rp_read_cfg = s10_rp_read_cfg, 576 + .rp_write_cfg = s10_rp_write_cfg, 577 + }; 578 + 579 + static const struct altera_pcie_data altera_pcie_1_0_data = { 580 + .ops = &altera_pcie_ops_1_0, 581 + .cap_offset = 0x80, 582 + .version = ALTERA_PCIE_V1, 583 + .cfgrd0 = TLP_FMTTYPE_CFGRD0, 584 + .cfgrd1 = TLP_FMTTYPE_CFGRD1, 585 + .cfgwr0 = TLP_FMTTYPE_CFGWR0, 586 + .cfgwr1 = TLP_FMTTYPE_CFGWR1, 587 + }; 588 + 589 + static const struct altera_pcie_data altera_pcie_2_0_data = { 590 + .ops = &altera_pcie_ops_2_0, 591 + .version = ALTERA_PCIE_V2, 592 + .cap_offset = 0x70, 593 + .cfgrd0 = S10_TLP_FMTTYPE_CFGRD0, 594 + .cfgrd1 = S10_TLP_FMTTYPE_CFGRD1, 595 + .cfgwr0 = S10_TLP_FMTTYPE_CFGWR0, 596 + .cfgwr1 = S10_TLP_FMTTYPE_CFGWR1, 597 + }; 598 + 599 + static const struct of_device_id altera_pcie_of_match[] = { 600 + {.compatible = "altr,pcie-root-port-1.0", 601 + .data = &altera_pcie_1_0_data }, 602 + {.compatible = "altr,pcie-root-port-2.0", 603 + .data = &altera_pcie_2_0_data }, 604 + {}, 605 + }; 606 + 743 607 static int altera_pcie_probe(struct platform_device *pdev) 744 608 { 745 609 struct device *dev = &pdev->dev; ··· 790 570 struct pci_bus *child; 791 571 struct pci_host_bridge *bridge; 792 572 int ret; 573 + const struct of_device_id *match; 793 574 794 575 bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie)); 795 576 if (!bridge) ··· 798 577 799 578 pcie = pci_host_bridge_priv(bridge); 800 579 pcie->pdev = pdev; 580 + 581 + match = of_match_device(altera_pcie_of_match, &pdev->dev); 582 + if (!match) 583 + return -ENODEV; 584 + 585 + pcie->pcie_data = match->data; 801 586 802 587 ret = altera_pcie_parse_dt(pcie); 803 588 if (ret) { ··· 854 627 pci_bus_add_devices(bus); 855 628 return ret; 856 629 } 857 - 858 - static const struct of_device_id altera_pcie_of_match[] = { 859 - { .compatible = "altr,pcie-root-port-1.0", }, 860 - {}, 861 - }; 862 630 863 631 static struct platform_driver altera_pcie_driver = { 864 632 .probe = altera_pcie_probe,