1/* 2 * pcie-dra7xx - PCIe controller driver for TI DRA7xx SoCs 3 * 4 * Copyright (C) 2013-2014 Texas Instruments Incorporated - http://www.ti.com 5 * 6 * Authors: Kishon Vijay Abraham I <kishon@ti.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13#include <linux/delay.h> 14#include <linux/err.h> 15#include <linux/interrupt.h> 16#include <linux/irq.h> 17#include <linux/irqdomain.h> 18#include <linux/kernel.h> 19#include <linux/module.h> 20#include <linux/of_gpio.h> 21#include <linux/pci.h> 22#include <linux/phy/phy.h> 23#include <linux/platform_device.h> 24#include <linux/pm_runtime.h> 25#include <linux/resource.h> 26#include <linux/types.h> 27 28#include "pcie-designware.h" 29 30/* PCIe controller wrapper DRA7XX configuration registers */ 31 32#define PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN 0x0024 33#define PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN 0x0028 34#define ERR_SYS BIT(0) 35#define ERR_FATAL BIT(1) 36#define ERR_NONFATAL BIT(2) 37#define ERR_COR BIT(3) 38#define ERR_AXI BIT(4) 39#define ERR_ECRC BIT(5) 40#define PME_TURN_OFF BIT(8) 41#define PME_TO_ACK BIT(9) 42#define PM_PME BIT(10) 43#define LINK_REQ_RST BIT(11) 44#define LINK_UP_EVT BIT(12) 45#define CFG_BME_EVT BIT(13) 46#define CFG_MSE_EVT BIT(14) 47#define INTERRUPTS (ERR_SYS | ERR_FATAL | ERR_NONFATAL | ERR_COR | ERR_AXI | \ 48 ERR_ECRC | PME_TURN_OFF | PME_TO_ACK | PM_PME | \ 49 LINK_REQ_RST | LINK_UP_EVT | CFG_BME_EVT | CFG_MSE_EVT) 50 51#define PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI 0x0034 52#define PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI 0x0038 53#define INTA BIT(0) 54#define INTB BIT(1) 55#define INTC BIT(2) 56#define INTD BIT(3) 57#define MSI BIT(4) 58#define LEG_EP_INTERRUPTS (INTA | INTB | INTC | INTD) 59 60#define PCIECTRL_DRA7XX_CONF_DEVICE_CMD 0x0104 61#define LTSSM_EN 0x1 62 63#define PCIECTRL_DRA7XX_CONF_PHY_CS 0x010C 64#define LINK_UP BIT(16) 65#define DRA7XX_CPU_TO_BUS_ADDR 0x0FFFFFFF 66 67struct dra7xx_pcie { 68 void __iomem *base; 69 struct phy **phy; 70 int phy_count; 71 struct device *dev; 72 struct pcie_port pp; 73}; 74 75#define to_dra7xx_pcie(x) container_of((x), struct dra7xx_pcie, pp) 76 77static inline u32 dra7xx_pcie_readl(struct dra7xx_pcie *pcie, u32 offset) 78{ 79 return readl(pcie->base + offset); 80} 81 82static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset, 83 u32 value) 84{ 85 writel(value, pcie->base + offset); 86} 87 88static inline u32 dra7xx_pcie_readl_rc(struct pcie_port *pp, u32 offset) 89{ 90 return readl(pp->dbi_base + offset); 91} 92 93static inline void dra7xx_pcie_writel_rc(struct pcie_port *pp, u32 offset, 94 u32 value) 95{ 96 writel(value, pp->dbi_base + offset); 97} 98 99static int dra7xx_pcie_link_up(struct pcie_port *pp) 100{ 101 struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp); 102 u32 reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_PHY_CS); 103 104 return !!(reg & LINK_UP); 105} 106 107static int dra7xx_pcie_establish_link(struct pcie_port *pp) 108{ 109 struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp); 110 u32 reg; 111 unsigned int retries; 112 113 if (dw_pcie_link_up(pp)) { 114 dev_err(pp->dev, "link is already up\n"); 115 return 0; 116 } 117 118 reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD); 119 reg |= LTSSM_EN; 120 dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg); 121 122 for (retries = 0; retries < 1000; retries++) { 123 if (dw_pcie_link_up(pp)) 124 return 0; 125 usleep_range(10, 20); 126 } 127 128 dev_err(pp->dev, "link is not up\n"); 129 return -EINVAL; 130} 131 132static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp) 133{ 134 struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp); 135 136 dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN, 137 ~INTERRUPTS); 138 dra7xx_pcie_writel(dra7xx, 139 PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN, INTERRUPTS); 140 dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI, 141 ~LEG_EP_INTERRUPTS & ~MSI); 142 143 if (IS_ENABLED(CONFIG_PCI_MSI)) 144 dra7xx_pcie_writel(dra7xx, 145 PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI, MSI); 146 else 147 dra7xx_pcie_writel(dra7xx, 148 PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI, 149 LEG_EP_INTERRUPTS); 150} 151 152static void dra7xx_pcie_host_init(struct pcie_port *pp) 153{ 154 dw_pcie_setup_rc(pp); 155 156 pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR; 157 pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR; 158 pp->cfg0_base &= DRA7XX_CPU_TO_BUS_ADDR; 159 pp->cfg1_base &= DRA7XX_CPU_TO_BUS_ADDR; 160 161 dra7xx_pcie_establish_link(pp); 162 if (IS_ENABLED(CONFIG_PCI_MSI)) 163 dw_pcie_msi_init(pp); 164 dra7xx_pcie_enable_interrupts(pp); 165} 166 167static struct pcie_host_ops dra7xx_pcie_host_ops = { 168 .link_up = dra7xx_pcie_link_up, 169 .host_init = dra7xx_pcie_host_init, 170}; 171 172static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq, 173 irq_hw_number_t hwirq) 174{ 175 irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq); 176 irq_set_chip_data(irq, domain->host_data); 177 178 return 0; 179} 180 181static const struct irq_domain_ops intx_domain_ops = { 182 .map = dra7xx_pcie_intx_map, 183}; 184 185static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp) 186{ 187 struct device *dev = pp->dev; 188 struct device_node *node = dev->of_node; 189 struct device_node *pcie_intc_node = of_get_next_child(node, NULL); 190 191 if (!pcie_intc_node) { 192 dev_err(dev, "No PCIe Intc node found\n"); 193 return PTR_ERR(pcie_intc_node); 194 } 195 196 pp->irq_domain = irq_domain_add_linear(pcie_intc_node, 4, 197 &intx_domain_ops, pp); 198 if (!pp->irq_domain) { 199 dev_err(dev, "Failed to get a INTx IRQ domain\n"); 200 return PTR_ERR(pp->irq_domain); 201 } 202 203 return 0; 204} 205 206static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg) 207{ 208 struct pcie_port *pp = arg; 209 struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp); 210 u32 reg; 211 212 reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI); 213 214 switch (reg) { 215 case MSI: 216 dw_handle_msi_irq(pp); 217 break; 218 case INTA: 219 case INTB: 220 case INTC: 221 case INTD: 222 generic_handle_irq(irq_find_mapping(pp->irq_domain, ffs(reg))); 223 break; 224 } 225 226 dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI, reg); 227 228 return IRQ_HANDLED; 229} 230 231 232static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg) 233{ 234 struct dra7xx_pcie *dra7xx = arg; 235 u32 reg; 236 237 reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN); 238 239 if (reg & ERR_SYS) 240 dev_dbg(dra7xx->dev, "System Error\n"); 241 242 if (reg & ERR_FATAL) 243 dev_dbg(dra7xx->dev, "Fatal Error\n"); 244 245 if (reg & ERR_NONFATAL) 246 dev_dbg(dra7xx->dev, "Non Fatal Error\n"); 247 248 if (reg & ERR_COR) 249 dev_dbg(dra7xx->dev, "Correctable Error\n"); 250 251 if (reg & ERR_AXI) 252 dev_dbg(dra7xx->dev, "AXI tag lookup fatal Error\n"); 253 254 if (reg & ERR_ECRC) 255 dev_dbg(dra7xx->dev, "ECRC Error\n"); 256 257 if (reg & PME_TURN_OFF) 258 dev_dbg(dra7xx->dev, 259 "Power Management Event Turn-Off message received\n"); 260 261 if (reg & PME_TO_ACK) 262 dev_dbg(dra7xx->dev, 263 "Power Management Turn-Off Ack message received\n"); 264 265 if (reg & PM_PME) 266 dev_dbg(dra7xx->dev, 267 "PM Power Management Event message received\n"); 268 269 if (reg & LINK_REQ_RST) 270 dev_dbg(dra7xx->dev, "Link Request Reset\n"); 271 272 if (reg & LINK_UP_EVT) 273 dev_dbg(dra7xx->dev, "Link-up state change\n"); 274 275 if (reg & CFG_BME_EVT) 276 dev_dbg(dra7xx->dev, "CFG 'Bus Master Enable' change\n"); 277 278 if (reg & CFG_MSE_EVT) 279 dev_dbg(dra7xx->dev, "CFG 'Memory Space Enable' change\n"); 280 281 dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN, reg); 282 283 return IRQ_HANDLED; 284} 285 286static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, 287 struct platform_device *pdev) 288{ 289 int ret; 290 struct pcie_port *pp; 291 struct resource *res; 292 struct device *dev = &pdev->dev; 293 294 pp = &dra7xx->pp; 295 pp->dev = dev; 296 pp->ops = &dra7xx_pcie_host_ops; 297 298 pp->irq = platform_get_irq(pdev, 1); 299 if (pp->irq < 0) { 300 dev_err(dev, "missing IRQ resource\n"); 301 return -EINVAL; 302 } 303 304 ret = devm_request_irq(&pdev->dev, pp->irq, 305 dra7xx_pcie_msi_irq_handler, 306 IRQF_SHARED | IRQF_NO_THREAD, 307 "dra7-pcie-msi", pp); 308 if (ret) { 309 dev_err(&pdev->dev, "failed to request irq\n"); 310 return ret; 311 } 312 313 if (!IS_ENABLED(CONFIG_PCI_MSI)) { 314 ret = dra7xx_pcie_init_irq_domain(pp); 315 if (ret < 0) 316 return ret; 317 } 318 319 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbics"); 320 pp->dbi_base = devm_ioremap(dev, res->start, resource_size(res)); 321 if (!pp->dbi_base) 322 return -ENOMEM; 323 324 ret = dw_pcie_host_init(pp); 325 if (ret) { 326 dev_err(dra7xx->dev, "failed to initialize host\n"); 327 return ret; 328 } 329 330 return 0; 331} 332 333static int __init dra7xx_pcie_probe(struct platform_device *pdev) 334{ 335 u32 reg; 336 int ret; 337 int irq; 338 int i; 339 int phy_count; 340 struct phy **phy; 341 void __iomem *base; 342 struct resource *res; 343 struct dra7xx_pcie *dra7xx; 344 struct device *dev = &pdev->dev; 345 struct device_node *np = dev->of_node; 346 char name[10]; 347 int gpio_sel; 348 enum of_gpio_flags flags; 349 unsigned long gpio_flags; 350 351 dra7xx = devm_kzalloc(dev, sizeof(*dra7xx), GFP_KERNEL); 352 if (!dra7xx) 353 return -ENOMEM; 354 355 irq = platform_get_irq(pdev, 0); 356 if (irq < 0) { 357 dev_err(dev, "missing IRQ resource\n"); 358 return -EINVAL; 359 } 360 361 ret = devm_request_irq(dev, irq, dra7xx_pcie_irq_handler, 362 IRQF_SHARED, "dra7xx-pcie-main", dra7xx); 363 if (ret) { 364 dev_err(dev, "failed to request irq\n"); 365 return ret; 366 } 367 368 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ti_conf"); 369 base = devm_ioremap_nocache(dev, res->start, resource_size(res)); 370 if (!base) 371 return -ENOMEM; 372 373 phy_count = of_property_count_strings(np, "phy-names"); 374 if (phy_count < 0) { 375 dev_err(dev, "unable to find the strings\n"); 376 return phy_count; 377 } 378 379 phy = devm_kzalloc(dev, sizeof(*phy) * phy_count, GFP_KERNEL); 380 if (!phy) 381 return -ENOMEM; 382 383 for (i = 0; i < phy_count; i++) { 384 snprintf(name, sizeof(name), "pcie-phy%d", i); 385 phy[i] = devm_phy_get(dev, name); 386 if (IS_ERR(phy[i])) 387 return PTR_ERR(phy[i]); 388 389 ret = phy_init(phy[i]); 390 if (ret < 0) 391 goto err_phy; 392 393 ret = phy_power_on(phy[i]); 394 if (ret < 0) { 395 phy_exit(phy[i]); 396 goto err_phy; 397 } 398 } 399 400 dra7xx->base = base; 401 dra7xx->phy = phy; 402 dra7xx->dev = dev; 403 dra7xx->phy_count = phy_count; 404 405 pm_runtime_enable(dev); 406 ret = pm_runtime_get_sync(dev); 407 if (ret < 0) { 408 dev_err(dev, "pm_runtime_get_sync failed\n"); 409 goto err_get_sync; 410 } 411 412 gpio_sel = of_get_gpio_flags(dev->of_node, 0, &flags); 413 if (gpio_is_valid(gpio_sel)) { 414 gpio_flags = (flags & OF_GPIO_ACTIVE_LOW) ? 415 GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; 416 ret = devm_gpio_request_one(dev, gpio_sel, gpio_flags, 417 "pcie_reset"); 418 if (ret) { 419 dev_err(&pdev->dev, "gpio%d request failed, ret %d\n", 420 gpio_sel, ret); 421 goto err_gpio; 422 } 423 } else if (gpio_sel == -EPROBE_DEFER) { 424 ret = -EPROBE_DEFER; 425 goto err_gpio; 426 } 427 428 reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD); 429 reg &= ~LTSSM_EN; 430 dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg); 431 432 platform_set_drvdata(pdev, dra7xx); 433 434 ret = dra7xx_add_pcie_port(dra7xx, pdev); 435 if (ret < 0) 436 goto err_gpio; 437 438 return 0; 439 440err_gpio: 441 pm_runtime_put(dev); 442 443err_get_sync: 444 pm_runtime_disable(dev); 445 446err_phy: 447 while (--i >= 0) { 448 phy_power_off(phy[i]); 449 phy_exit(phy[i]); 450 } 451 452 return ret; 453} 454 455static int __exit dra7xx_pcie_remove(struct platform_device *pdev) 456{ 457 struct dra7xx_pcie *dra7xx = platform_get_drvdata(pdev); 458 struct pcie_port *pp = &dra7xx->pp; 459 struct device *dev = &pdev->dev; 460 int count = dra7xx->phy_count; 461 462 if (pp->irq_domain) 463 irq_domain_remove(pp->irq_domain); 464 pm_runtime_put(dev); 465 pm_runtime_disable(dev); 466 while (count--) { 467 phy_power_off(dra7xx->phy[count]); 468 phy_exit(dra7xx->phy[count]); 469 } 470 471 return 0; 472} 473 474#ifdef CONFIG_PM_SLEEP 475static int dra7xx_pcie_suspend(struct device *dev) 476{ 477 struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev); 478 struct pcie_port *pp = &dra7xx->pp; 479 u32 val; 480 481 /* clear MSE */ 482 val = dra7xx_pcie_readl_rc(pp, PCI_COMMAND); 483 val &= ~PCI_COMMAND_MEMORY; 484 dra7xx_pcie_writel_rc(pp, PCI_COMMAND, val); 485 486 return 0; 487} 488 489static int dra7xx_pcie_resume(struct device *dev) 490{ 491 struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev); 492 struct pcie_port *pp = &dra7xx->pp; 493 u32 val; 494 495 /* set MSE */ 496 val = dra7xx_pcie_readl_rc(pp, PCI_COMMAND); 497 val |= PCI_COMMAND_MEMORY; 498 dra7xx_pcie_writel_rc(pp, PCI_COMMAND, val); 499 500 return 0; 501} 502 503static int dra7xx_pcie_suspend_noirq(struct device *dev) 504{ 505 struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev); 506 int count = dra7xx->phy_count; 507 508 while (count--) { 509 phy_power_off(dra7xx->phy[count]); 510 phy_exit(dra7xx->phy[count]); 511 } 512 513 return 0; 514} 515 516static int dra7xx_pcie_resume_noirq(struct device *dev) 517{ 518 struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev); 519 int phy_count = dra7xx->phy_count; 520 int ret; 521 int i; 522 523 for (i = 0; i < phy_count; i++) { 524 ret = phy_init(dra7xx->phy[i]); 525 if (ret < 0) 526 goto err_phy; 527 528 ret = phy_power_on(dra7xx->phy[i]); 529 if (ret < 0) { 530 phy_exit(dra7xx->phy[i]); 531 goto err_phy; 532 } 533 } 534 535 return 0; 536 537err_phy: 538 while (--i >= 0) { 539 phy_power_off(dra7xx->phy[i]); 540 phy_exit(dra7xx->phy[i]); 541 } 542 543 return ret; 544} 545#endif 546 547static const struct dev_pm_ops dra7xx_pcie_pm_ops = { 548 SET_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend, dra7xx_pcie_resume) 549 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend_noirq, 550 dra7xx_pcie_resume_noirq) 551}; 552 553static const struct of_device_id of_dra7xx_pcie_match[] = { 554 { .compatible = "ti,dra7-pcie", }, 555 {}, 556}; 557MODULE_DEVICE_TABLE(of, of_dra7xx_pcie_match); 558 559static struct platform_driver dra7xx_pcie_driver = { 560 .remove = __exit_p(dra7xx_pcie_remove), 561 .driver = { 562 .name = "dra7-pcie", 563 .of_match_table = of_dra7xx_pcie_match, 564 .pm = &dra7xx_pcie_pm_ops, 565 }, 566}; 567 568module_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe); 569 570MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); 571MODULE_DESCRIPTION("TI PCIe controller driver"); 572MODULE_LICENSE("GPL v2"); 573