1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * PCIe host controller driver for Axis ARTPEC-6 SoC 4 * 5 * Author: Niklas Cassel <niklas.cassel@axis.com> 6 * 7 * Based on work done by Phil Edworthy <phil@edworthys.org> 8 */ 9 10 #include <linux/delay.h> 11 #include <linux/kernel.h> 12 #include <linux/init.h> 13 #include <linux/of.h> 14 #include <linux/pci.h> 15 #include <linux/platform_device.h> 16 #include <linux/resource.h> 17 #include <linux/signal.h> 18 #include <linux/types.h> 19 #include <linux/interrupt.h> 20 #include <linux/mfd/syscon.h> 21 #include <linux/regmap.h> 22 23 #include "pcie-designware.h" 24 25 #define to_artpec6_pcie(x) dev_get_drvdata((x)->dev) 26 27 enum artpec_pcie_variants { 28 ARTPEC6, 29 ARTPEC7, 30 }; 31 32 struct artpec6_pcie { 33 struct dw_pcie *pci; 34 struct regmap *regmap; /* DT axis,syscon-pcie */ 35 void __iomem *phy_base; /* DT phy */ 36 enum artpec_pcie_variants variant; 37 }; 38 39 struct artpec_pcie_of_data { 40 enum artpec_pcie_variants variant; 41 enum dw_pcie_device_mode mode; 42 }; 43 44 static const struct of_device_id artpec6_pcie_of_match[]; 45 46 /* ARTPEC-6 specific registers */ 47 #define PCIECFG 0x18 48 #define PCIECFG_DBG_OEN BIT(24) 49 #define PCIECFG_CORE_RESET_REQ BIT(21) 50 #define PCIECFG_LTSSM_ENABLE BIT(20) 51 #define PCIECFG_DEVICE_TYPE_MASK GENMASK(19, 16) 52 #define PCIECFG_CLKREQ_B BIT(11) 53 #define PCIECFG_REFCLK_ENABLE BIT(10) 54 #define PCIECFG_PLL_ENABLE BIT(9) 55 #define PCIECFG_PCLK_ENABLE BIT(8) 56 #define PCIECFG_RISRCREN BIT(4) 57 #define PCIECFG_MODE_TX_DRV_EN BIT(3) 58 #define PCIECFG_CISRREN BIT(2) 59 #define PCIECFG_MACRO_ENABLE BIT(0) 60 /* ARTPEC-7 specific fields */ 61 #define PCIECFG_REFCLKSEL BIT(23) 62 #define PCIECFG_NOC_RESET BIT(3) 63 64 #define PCIESTAT 0x1c 65 /* ARTPEC-7 specific fields */ 66 #define PCIESTAT_EXTREFCLK BIT(3) 67 68 #define NOCCFG 0x40 69 #define NOCCFG_ENABLE_CLK_PCIE BIT(4) 70 #define NOCCFG_POWER_PCIE_IDLEACK BIT(3) 71 #define NOCCFG_POWER_PCIE_IDLE BIT(2) 72 #define NOCCFG_POWER_PCIE_IDLEREQ BIT(1) 73 74 #define PHY_STATUS 0x118 75 #define PHY_COSPLLLOCK BIT(0) 76 77 #define PHY_TX_ASIC_OUT 0x4040 78 #define PHY_TX_ASIC_OUT_TX_ACK BIT(0) 79 80 #define PHY_RX_ASIC_OUT 0x405c 81 #define PHY_RX_ASIC_OUT_ACK BIT(0) 82 83 static u32 artpec6_pcie_readl(struct artpec6_pcie *artpec6_pcie, u32 offset) 84 { 85 u32 val; 86 87 regmap_read(artpec6_pcie->regmap, offset, &val); 88 return val; 89 } 90 91 static void artpec6_pcie_writel(struct artpec6_pcie *artpec6_pcie, u32 offset, u32 val) 92 { 93 regmap_write(artpec6_pcie->regmap, offset, val); 94 } 95 96 static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr) 97 { 98 struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); 99 struct dw_pcie_rp *pp = &pci->pp; 100 struct dw_pcie_ep *ep = &pci->ep; 101 102 switch (artpec6_pcie->pci->mode) { 103 case DW_PCIE_RC_TYPE: 104 return cpu_addr - pp->cfg0_base; 105 case DW_PCIE_EP_TYPE: 106 return cpu_addr - ep->phys_base; 107 default: 108 dev_err(pci->dev, "UNKNOWN device type\n"); 109 } 110 return cpu_addr; 111 } 112 113 static int artpec6_pcie_establish_link(struct dw_pcie *pci) 114 { 115 struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); 116 u32 val; 117 118 val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); 119 val |= PCIECFG_LTSSM_ENABLE; 120 artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); 121 122 return 0; 123 } 124 125 static void artpec6_pcie_stop_link(struct dw_pcie *pci) 126 { 127 struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); 128 u32 val; 129 130 val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); 131 val &= ~PCIECFG_LTSSM_ENABLE; 132 artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); 133 } 134 135 static const struct dw_pcie_ops dw_pcie_ops = { 136 .cpu_addr_fixup = artpec6_pcie_cpu_addr_fixup, 137 .start_link = artpec6_pcie_establish_link, 138 .stop_link = artpec6_pcie_stop_link, 139 }; 140 141 static void artpec6_pcie_wait_for_phy_a6(struct artpec6_pcie *artpec6_pcie) 142 { 143 struct dw_pcie *pci = artpec6_pcie->pci; 144 struct device *dev = pci->dev; 145 u32 val; 146 unsigned int retries; 147 148 retries = 50; 149 do { 150 usleep_range(1000, 2000); 151 val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); 152 retries--; 153 } while (retries && 154 (val & (NOCCFG_POWER_PCIE_IDLEACK | NOCCFG_POWER_PCIE_IDLE))); 155 if (!retries) 156 dev_err(dev, "PCIe clock manager did not leave idle state\n"); 157 158 retries = 50; 159 do { 160 usleep_range(1000, 2000); 161 val = readl(artpec6_pcie->phy_base + PHY_STATUS); 162 retries--; 163 } while (retries && !(val & PHY_COSPLLLOCK)); 164 if (!retries) 165 dev_err(dev, "PHY PLL did not lock\n"); 166 } 167 168 static void artpec6_pcie_wait_for_phy_a7(struct artpec6_pcie *artpec6_pcie) 169 { 170 struct dw_pcie *pci = artpec6_pcie->pci; 171 struct device *dev = pci->dev; 172 u32 val; 173 u16 phy_status_tx, phy_status_rx; 174 unsigned int retries; 175 176 retries = 50; 177 do { 178 usleep_range(1000, 2000); 179 val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); 180 retries--; 181 } while (retries && 182 (val & (NOCCFG_POWER_PCIE_IDLEACK | NOCCFG_POWER_PCIE_IDLE))); 183 if (!retries) 184 dev_err(dev, "PCIe clock manager did not leave idle state\n"); 185 186 retries = 50; 187 do { 188 usleep_range(1000, 2000); 189 phy_status_tx = readw(artpec6_pcie->phy_base + PHY_TX_ASIC_OUT); 190 phy_status_rx = readw(artpec6_pcie->phy_base + PHY_RX_ASIC_OUT); 191 retries--; 192 } while (retries && ((phy_status_tx & PHY_TX_ASIC_OUT_TX_ACK) || 193 (phy_status_rx & PHY_RX_ASIC_OUT_ACK))); 194 if (!retries) 195 dev_err(dev, "PHY did not enter Pn state\n"); 196 } 197 198 static void artpec6_pcie_wait_for_phy(struct artpec6_pcie *artpec6_pcie) 199 { 200 switch (artpec6_pcie->variant) { 201 case ARTPEC6: 202 artpec6_pcie_wait_for_phy_a6(artpec6_pcie); 203 break; 204 case ARTPEC7: 205 artpec6_pcie_wait_for_phy_a7(artpec6_pcie); 206 break; 207 } 208 } 209 210 static void artpec6_pcie_init_phy_a6(struct artpec6_pcie *artpec6_pcie) 211 { 212 u32 val; 213 214 val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); 215 val |= PCIECFG_RISRCREN | /* Receiver term. 50 Ohm */ 216 PCIECFG_MODE_TX_DRV_EN | 217 PCIECFG_CISRREN | /* Reference clock term. 100 Ohm */ 218 PCIECFG_MACRO_ENABLE; 219 val |= PCIECFG_REFCLK_ENABLE; 220 val &= ~PCIECFG_DBG_OEN; 221 val &= ~PCIECFG_CLKREQ_B; 222 artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); 223 usleep_range(5000, 6000); 224 225 val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); 226 val |= NOCCFG_ENABLE_CLK_PCIE; 227 artpec6_pcie_writel(artpec6_pcie, NOCCFG, val); 228 usleep_range(20, 30); 229 230 val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); 231 val |= PCIECFG_PCLK_ENABLE | PCIECFG_PLL_ENABLE; 232 artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); 233 usleep_range(6000, 7000); 234 235 val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); 236 val &= ~NOCCFG_POWER_PCIE_IDLEREQ; 237 artpec6_pcie_writel(artpec6_pcie, NOCCFG, val); 238 } 239 240 static void artpec6_pcie_init_phy_a7(struct artpec6_pcie *artpec6_pcie) 241 { 242 struct dw_pcie *pci = artpec6_pcie->pci; 243 u32 val; 244 bool extrefclk; 245 246 /* Check if external reference clock is connected */ 247 val = artpec6_pcie_readl(artpec6_pcie, PCIESTAT); 248 extrefclk = !!(val & PCIESTAT_EXTREFCLK); 249 dev_dbg(pci->dev, "Using reference clock: %s\n", 250 extrefclk ? "external" : "internal"); 251 252 val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); 253 val |= PCIECFG_RISRCREN | /* Receiver term. 50 Ohm */ 254 PCIECFG_PCLK_ENABLE; 255 if (extrefclk) 256 val |= PCIECFG_REFCLKSEL; 257 else 258 val &= ~PCIECFG_REFCLKSEL; 259 artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); 260 usleep_range(10, 20); 261 262 val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); 263 val |= NOCCFG_ENABLE_CLK_PCIE; 264 artpec6_pcie_writel(artpec6_pcie, NOCCFG, val); 265 usleep_range(20, 30); 266 267 val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); 268 val &= ~NOCCFG_POWER_PCIE_IDLEREQ; 269 artpec6_pcie_writel(artpec6_pcie, NOCCFG, val); 270 } 271 272 static void artpec6_pcie_init_phy(struct artpec6_pcie *artpec6_pcie) 273 { 274 switch (artpec6_pcie->variant) { 275 case ARTPEC6: 276 artpec6_pcie_init_phy_a6(artpec6_pcie); 277 break; 278 case ARTPEC7: 279 artpec6_pcie_init_phy_a7(artpec6_pcie); 280 break; 281 } 282 } 283 284 static void artpec6_pcie_assert_core_reset(struct artpec6_pcie *artpec6_pcie) 285 { 286 u32 val; 287 288 val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); 289 switch (artpec6_pcie->variant) { 290 case ARTPEC6: 291 val |= PCIECFG_CORE_RESET_REQ; 292 break; 293 case ARTPEC7: 294 val &= ~PCIECFG_NOC_RESET; 295 break; 296 } 297 artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); 298 } 299 300 static void artpec6_pcie_deassert_core_reset(struct artpec6_pcie *artpec6_pcie) 301 { 302 u32 val; 303 304 val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); 305 switch (artpec6_pcie->variant) { 306 case ARTPEC6: 307 val &= ~PCIECFG_CORE_RESET_REQ; 308 break; 309 case ARTPEC7: 310 val |= PCIECFG_NOC_RESET; 311 break; 312 } 313 artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); 314 usleep_range(100, 200); 315 } 316 317 static int artpec6_pcie_host_init(struct dw_pcie_rp *pp) 318 { 319 struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 320 struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); 321 322 if (artpec6_pcie->variant == ARTPEC7) { 323 pci->n_fts[0] = 180; 324 pci->n_fts[1] = 180; 325 } 326 artpec6_pcie_assert_core_reset(artpec6_pcie); 327 artpec6_pcie_init_phy(artpec6_pcie); 328 artpec6_pcie_deassert_core_reset(artpec6_pcie); 329 artpec6_pcie_wait_for_phy(artpec6_pcie); 330 331 return 0; 332 } 333 334 static const struct dw_pcie_host_ops artpec6_pcie_host_ops = { 335 .init = artpec6_pcie_host_init, 336 }; 337 338 static int artpec6_pcie_ep_init(struct dw_pcie_ep *ep) 339 { 340 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 341 struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); 342 343 artpec6_pcie_assert_core_reset(artpec6_pcie); 344 artpec6_pcie_init_phy(artpec6_pcie); 345 artpec6_pcie_deassert_core_reset(artpec6_pcie); 346 artpec6_pcie_wait_for_phy(artpec6_pcie); 347 348 return 0; 349 } 350 351 static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, 352 unsigned int type, u16 interrupt_num) 353 { 354 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 355 356 switch (type) { 357 case PCI_IRQ_INTX: 358 dev_err(pci->dev, "EP cannot trigger INTx IRQs\n"); 359 return -EINVAL; 360 case PCI_IRQ_MSI: 361 return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num); 362 default: 363 dev_err(pci->dev, "UNKNOWN IRQ type\n"); 364 } 365 366 return 0; 367 } 368 369 static const struct pci_epc_features artpec6_pcie_epc_features = { 370 DWC_EPC_COMMON_FEATURES, 371 .msi_capable = true, 372 }; 373 374 static const struct pci_epc_features * 375 artpec6_pcie_get_features(struct dw_pcie_ep *ep) 376 { 377 return &artpec6_pcie_epc_features; 378 } 379 380 static const struct dw_pcie_ep_ops pcie_ep_ops = { 381 .init = artpec6_pcie_ep_init, 382 .raise_irq = artpec6_pcie_raise_irq, 383 .get_features = artpec6_pcie_get_features, 384 }; 385 386 static int artpec6_pcie_probe(struct platform_device *pdev) 387 { 388 struct device *dev = &pdev->dev; 389 struct dw_pcie *pci; 390 struct artpec6_pcie *artpec6_pcie; 391 int ret; 392 const struct artpec_pcie_of_data *data; 393 enum artpec_pcie_variants variant; 394 enum dw_pcie_device_mode mode; 395 u32 val; 396 397 data = of_device_get_match_data(dev); 398 if (!data) 399 return -EINVAL; 400 401 variant = (enum artpec_pcie_variants)data->variant; 402 mode = (enum dw_pcie_device_mode)data->mode; 403 404 artpec6_pcie = devm_kzalloc(dev, sizeof(*artpec6_pcie), GFP_KERNEL); 405 if (!artpec6_pcie) 406 return -ENOMEM; 407 408 pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); 409 if (!pci) 410 return -ENOMEM; 411 412 pci->dev = dev; 413 pci->ops = &dw_pcie_ops; 414 415 artpec6_pcie->pci = pci; 416 artpec6_pcie->variant = variant; 417 artpec6_pcie->pci->mode = mode; 418 419 artpec6_pcie->phy_base = 420 devm_platform_ioremap_resource_byname(pdev, "phy"); 421 if (IS_ERR(artpec6_pcie->phy_base)) 422 return PTR_ERR(artpec6_pcie->phy_base); 423 424 artpec6_pcie->regmap = 425 syscon_regmap_lookup_by_phandle(dev->of_node, 426 "axis,syscon-pcie"); 427 if (IS_ERR(artpec6_pcie->regmap)) 428 return PTR_ERR(artpec6_pcie->regmap); 429 430 platform_set_drvdata(pdev, artpec6_pcie); 431 432 switch (artpec6_pcie->pci->mode) { 433 case DW_PCIE_RC_TYPE: 434 if (!IS_ENABLED(CONFIG_PCIE_ARTPEC6_HOST)) 435 return -ENODEV; 436 437 pci->pp.ops = &artpec6_pcie_host_ops; 438 439 ret = dw_pcie_host_init(&pci->pp); 440 if (ret < 0) 441 return ret; 442 break; 443 case DW_PCIE_EP_TYPE: 444 if (!IS_ENABLED(CONFIG_PCIE_ARTPEC6_EP)) 445 return -ENODEV; 446 447 val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); 448 val &= ~PCIECFG_DEVICE_TYPE_MASK; 449 artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); 450 451 pci->ep.ops = &pcie_ep_ops; 452 453 ret = dw_pcie_ep_init(&pci->ep); 454 if (ret) 455 return ret; 456 457 ret = dw_pcie_ep_init_registers(&pci->ep); 458 if (ret) { 459 dev_err(dev, "Failed to initialize DWC endpoint registers\n"); 460 dw_pcie_ep_deinit(&pci->ep); 461 return ret; 462 } 463 464 pci_epc_init_notify(pci->ep.epc); 465 466 break; 467 default: 468 dev_err(dev, "INVALID device type %d\n", artpec6_pcie->pci->mode); 469 } 470 471 return 0; 472 } 473 474 static const struct artpec_pcie_of_data artpec6_pcie_rc_of_data = { 475 .variant = ARTPEC6, 476 .mode = DW_PCIE_RC_TYPE, 477 }; 478 479 static const struct artpec_pcie_of_data artpec6_pcie_ep_of_data = { 480 .variant = ARTPEC6, 481 .mode = DW_PCIE_EP_TYPE, 482 }; 483 484 static const struct artpec_pcie_of_data artpec7_pcie_rc_of_data = { 485 .variant = ARTPEC7, 486 .mode = DW_PCIE_RC_TYPE, 487 }; 488 489 static const struct artpec_pcie_of_data artpec7_pcie_ep_of_data = { 490 .variant = ARTPEC7, 491 .mode = DW_PCIE_EP_TYPE, 492 }; 493 494 static const struct of_device_id artpec6_pcie_of_match[] = { 495 { 496 .compatible = "axis,artpec6-pcie", 497 .data = &artpec6_pcie_rc_of_data, 498 }, 499 { 500 .compatible = "axis,artpec6-pcie-ep", 501 .data = &artpec6_pcie_ep_of_data, 502 }, 503 { 504 .compatible = "axis,artpec7-pcie", 505 .data = &artpec7_pcie_rc_of_data, 506 }, 507 { 508 .compatible = "axis,artpec7-pcie-ep", 509 .data = &artpec7_pcie_ep_of_data, 510 }, 511 {}, 512 }; 513 514 static struct platform_driver artpec6_pcie_driver = { 515 .probe = artpec6_pcie_probe, 516 .driver = { 517 .name = "artpec6-pcie", 518 .of_match_table = artpec6_pcie_of_match, 519 .suppress_bind_attrs = true, 520 }, 521 }; 522 builtin_platform_driver(artpec6_pcie_driver); 523