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

PCI: j721e: Add TI J721E PCIe driver

Add support for PCIe controller in J721E SoC. The controller uses the
Cadence PCIe core programmed by pcie-cadence*.c. The PCIe controller
will work in both host mode and device mode.
Some of the features of the controller are:
*) Supports both RC mode and EP mode
*) Supports MSI and MSI-X support
*) Supports upto GEN3 speed mode
*) Supports SR-IOV capability
*) Ability to route all transactions via SMMU (support will be added
in a later patch).

Link: https://lore.kernel.org/r/20200722110317.4744-14-kishon@ti.com
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

authored by

Kishon Vijay Abraham I and committed by
Lorenzo Pieralisi
f3e25911 45b39e92

+527 -2
+23
drivers/pci/controller/cadence/Kconfig
··· 42 42 endpoint mode. This PCIe controller may be embedded into many 43 43 different vendors SoCs. 44 44 45 + config PCI_J721E 46 + bool 47 + 48 + config PCI_J721E_HOST 49 + bool "TI J721E PCIe platform host controller" 50 + depends on OF 51 + select PCIE_CADENCE_HOST 52 + select PCI_J721E 53 + help 54 + Say Y here if you want to support the TI J721E PCIe platform 55 + controller in host mode. TI J721E PCIe controller uses Cadence PCIe 56 + core. 57 + 58 + config PCI_J721E_EP 59 + bool "TI J721E PCIe platform endpoint controller" 60 + depends on OF 61 + depends on PCI_ENDPOINT 62 + select PCIE_CADENCE_EP 63 + select PCI_J721E 64 + help 65 + Say Y here if you want to support the TI J721E PCIe platform 66 + controller in endpoint mode. TI J721E PCIe controller uses Cadence PCIe 67 + core. 45 68 endmenu
+1
drivers/pci/controller/cadence/Makefile
··· 3 3 obj-$(CONFIG_PCIE_CADENCE_HOST) += pcie-cadence-host.o 4 4 obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o 5 5 obj-$(CONFIG_PCIE_CADENCE_PLAT) += pcie-cadence-plat.o 6 + obj-$(CONFIG_PCI_J721E) += pci-j721e.o
+493
drivers/pci/controller/cadence/pci-j721e.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /** 3 + * pci-j721e - PCIe controller driver for TI's J721E SoCs 4 + * 5 + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com 6 + * Author: Kishon Vijay Abraham I <kishon@ti.com> 7 + */ 8 + 9 + #include <linux/delay.h> 10 + #include <linux/gpio/consumer.h> 11 + #include <linux/io.h> 12 + #include <linux/irqchip/chained_irq.h> 13 + #include <linux/irqdomain.h> 14 + #include <linux/mfd/syscon.h> 15 + #include <linux/of_device.h> 16 + #include <linux/of_irq.h> 17 + #include <linux/pci.h> 18 + #include <linux/pm_runtime.h> 19 + #include <linux/regmap.h> 20 + 21 + #include "../../pci.h" 22 + #include "pcie-cadence.h" 23 + 24 + #define ENABLE_REG_SYS_2 0x108 25 + #define STATUS_REG_SYS_2 0x508 26 + #define STATUS_CLR_REG_SYS_2 0x708 27 + #define LINK_DOWN BIT(1) 28 + 29 + #define J721E_PCIE_USER_CMD_STATUS 0x4 30 + #define LINK_TRAINING_ENABLE BIT(0) 31 + 32 + #define J721E_PCIE_USER_LINKSTATUS 0x14 33 + #define LINK_STATUS GENMASK(1, 0) 34 + 35 + enum link_status { 36 + NO_RECEIVERS_DETECTED, 37 + LINK_TRAINING_IN_PROGRESS, 38 + LINK_UP_DL_IN_PROGRESS, 39 + LINK_UP_DL_COMPLETED, 40 + }; 41 + 42 + #define J721E_MODE_RC BIT(7) 43 + #define LANE_COUNT_MASK BIT(8) 44 + #define LANE_COUNT(n) ((n) << 8) 45 + 46 + #define GENERATION_SEL_MASK GENMASK(1, 0) 47 + 48 + #define MAX_LANES 2 49 + 50 + struct j721e_pcie { 51 + struct device *dev; 52 + u32 mode; 53 + u32 num_lanes; 54 + struct cdns_pcie *cdns_pcie; 55 + void __iomem *user_cfg_base; 56 + void __iomem *intd_cfg_base; 57 + }; 58 + 59 + enum j721e_pcie_mode { 60 + PCI_MODE_RC, 61 + PCI_MODE_EP, 62 + }; 63 + 64 + struct j721e_pcie_data { 65 + enum j721e_pcie_mode mode; 66 + }; 67 + 68 + static inline u32 j721e_pcie_user_readl(struct j721e_pcie *pcie, u32 offset) 69 + { 70 + return readl(pcie->user_cfg_base + offset); 71 + } 72 + 73 + static inline void j721e_pcie_user_writel(struct j721e_pcie *pcie, u32 offset, 74 + u32 value) 75 + { 76 + writel(value, pcie->user_cfg_base + offset); 77 + } 78 + 79 + static inline u32 j721e_pcie_intd_readl(struct j721e_pcie *pcie, u32 offset) 80 + { 81 + return readl(pcie->intd_cfg_base + offset); 82 + } 83 + 84 + static inline void j721e_pcie_intd_writel(struct j721e_pcie *pcie, u32 offset, 85 + u32 value) 86 + { 87 + writel(value, pcie->intd_cfg_base + offset); 88 + } 89 + 90 + static irqreturn_t j721e_pcie_link_irq_handler(int irq, void *priv) 91 + { 92 + struct j721e_pcie *pcie = priv; 93 + struct device *dev = pcie->dev; 94 + u32 reg; 95 + 96 + reg = j721e_pcie_intd_readl(pcie, STATUS_REG_SYS_2); 97 + if (!(reg & LINK_DOWN)) 98 + return IRQ_NONE; 99 + 100 + dev_err(dev, "LINK DOWN!\n"); 101 + 102 + j721e_pcie_intd_writel(pcie, STATUS_CLR_REG_SYS_2, LINK_DOWN); 103 + return IRQ_HANDLED; 104 + } 105 + 106 + static void j721e_pcie_config_link_irq(struct j721e_pcie *pcie) 107 + { 108 + u32 reg; 109 + 110 + reg = j721e_pcie_intd_readl(pcie, ENABLE_REG_SYS_2); 111 + reg |= LINK_DOWN; 112 + j721e_pcie_intd_writel(pcie, ENABLE_REG_SYS_2, reg); 113 + } 114 + 115 + static int j721e_pcie_start_link(struct cdns_pcie *cdns_pcie) 116 + { 117 + struct j721e_pcie *pcie = dev_get_drvdata(cdns_pcie->dev); 118 + u32 reg; 119 + 120 + reg = j721e_pcie_user_readl(pcie, J721E_PCIE_USER_CMD_STATUS); 121 + reg |= LINK_TRAINING_ENABLE; 122 + j721e_pcie_user_writel(pcie, J721E_PCIE_USER_CMD_STATUS, reg); 123 + 124 + return 0; 125 + } 126 + 127 + static void j721e_pcie_stop_link(struct cdns_pcie *cdns_pcie) 128 + { 129 + struct j721e_pcie *pcie = dev_get_drvdata(cdns_pcie->dev); 130 + u32 reg; 131 + 132 + reg = j721e_pcie_user_readl(pcie, J721E_PCIE_USER_CMD_STATUS); 133 + reg &= ~LINK_TRAINING_ENABLE; 134 + j721e_pcie_user_writel(pcie, J721E_PCIE_USER_CMD_STATUS, reg); 135 + } 136 + 137 + static bool j721e_pcie_link_up(struct cdns_pcie *cdns_pcie) 138 + { 139 + struct j721e_pcie *pcie = dev_get_drvdata(cdns_pcie->dev); 140 + u32 reg; 141 + 142 + reg = j721e_pcie_user_readl(pcie, J721E_PCIE_USER_LINKSTATUS); 143 + reg &= LINK_STATUS; 144 + if (reg == LINK_UP_DL_COMPLETED) 145 + return true; 146 + 147 + return false; 148 + } 149 + 150 + static const struct cdns_pcie_ops j721e_pcie_ops = { 151 + .start_link = j721e_pcie_start_link, 152 + .stop_link = j721e_pcie_stop_link, 153 + .link_up = j721e_pcie_link_up, 154 + }; 155 + 156 + static int j721e_pcie_set_mode(struct j721e_pcie *pcie, struct regmap *syscon) 157 + { 158 + struct device *dev = pcie->dev; 159 + u32 mask = J721E_MODE_RC; 160 + u32 mode = pcie->mode; 161 + u32 val = 0; 162 + int ret = 0; 163 + 164 + if (mode == PCI_MODE_RC) 165 + val = J721E_MODE_RC; 166 + 167 + ret = regmap_update_bits(syscon, 0, mask, val); 168 + if (ret) 169 + dev_err(dev, "failed to set pcie mode\n"); 170 + 171 + return ret; 172 + } 173 + 174 + static int j721e_pcie_set_link_speed(struct j721e_pcie *pcie, 175 + struct regmap *syscon) 176 + { 177 + struct device *dev = pcie->dev; 178 + struct device_node *np = dev->of_node; 179 + int link_speed; 180 + u32 val = 0; 181 + int ret; 182 + 183 + link_speed = of_pci_get_max_link_speed(np); 184 + if (link_speed < 2) 185 + link_speed = 2; 186 + 187 + val = link_speed - 1; 188 + ret = regmap_update_bits(syscon, 0, GENERATION_SEL_MASK, val); 189 + if (ret) 190 + dev_err(dev, "failed to set link speed\n"); 191 + 192 + return ret; 193 + } 194 + 195 + static int j721e_pcie_set_lane_count(struct j721e_pcie *pcie, 196 + struct regmap *syscon) 197 + { 198 + struct device *dev = pcie->dev; 199 + u32 lanes = pcie->num_lanes; 200 + u32 val = 0; 201 + int ret; 202 + 203 + val = LANE_COUNT(lanes - 1); 204 + ret = regmap_update_bits(syscon, 0, LANE_COUNT_MASK, val); 205 + if (ret) 206 + dev_err(dev, "failed to set link count\n"); 207 + 208 + return ret; 209 + } 210 + 211 + static int j721e_pcie_ctrl_init(struct j721e_pcie *pcie) 212 + { 213 + struct device *dev = pcie->dev; 214 + struct device_node *node = dev->of_node; 215 + struct regmap *syscon; 216 + int ret; 217 + 218 + syscon = syscon_regmap_lookup_by_phandle(node, "ti,syscon-pcie-ctrl"); 219 + if (IS_ERR(syscon)) { 220 + dev_err(dev, "Unable to get ti,syscon-pcie-ctrl regmap\n"); 221 + return PTR_ERR(syscon); 222 + } 223 + 224 + ret = j721e_pcie_set_mode(pcie, syscon); 225 + if (ret < 0) { 226 + dev_err(dev, "Failed to set pci mode\n"); 227 + return ret; 228 + } 229 + 230 + ret = j721e_pcie_set_link_speed(pcie, syscon); 231 + if (ret < 0) { 232 + dev_err(dev, "Failed to set link speed\n"); 233 + return ret; 234 + } 235 + 236 + ret = j721e_pcie_set_lane_count(pcie, syscon); 237 + if (ret < 0) { 238 + dev_err(dev, "Failed to set num-lanes\n"); 239 + return ret; 240 + } 241 + 242 + return 0; 243 + } 244 + 245 + static int cdns_ti_pcie_config_read(struct pci_bus *bus, unsigned int devfn, 246 + int where, int size, u32 *value) 247 + { 248 + struct pci_host_bridge *bridge = pci_find_host_bridge(bus); 249 + struct cdns_pcie_rc *rc = pci_host_bridge_priv(bridge); 250 + unsigned int busn = bus->number; 251 + 252 + if (busn == rc->bus_range->start) 253 + return pci_generic_config_read32(bus, devfn, where, size, 254 + value); 255 + 256 + return pci_generic_config_read(bus, devfn, where, size, value); 257 + } 258 + 259 + static int cdns_ti_pcie_config_write(struct pci_bus *bus, unsigned int devfn, 260 + int where, int size, u32 value) 261 + { 262 + struct pci_host_bridge *bridge = pci_find_host_bridge(bus); 263 + struct cdns_pcie_rc *rc = pci_host_bridge_priv(bridge); 264 + unsigned int busn = bus->number; 265 + 266 + if (busn == rc->bus_range->start) 267 + return pci_generic_config_write32(bus, devfn, where, size, 268 + value); 269 + 270 + return pci_generic_config_write(bus, devfn, where, size, value); 271 + } 272 + 273 + static struct pci_ops cdns_ti_pcie_host_ops = { 274 + .map_bus = cdns_pci_map_bus, 275 + .read = cdns_ti_pcie_config_read, 276 + .write = cdns_ti_pcie_config_write, 277 + }; 278 + 279 + static const struct j721e_pcie_data j721e_pcie_rc_data = { 280 + .mode = PCI_MODE_RC, 281 + }; 282 + 283 + static const struct j721e_pcie_data j721e_pcie_ep_data = { 284 + .mode = PCI_MODE_EP, 285 + }; 286 + 287 + static const struct of_device_id of_j721e_pcie_match[] = { 288 + { 289 + .compatible = "ti,j721e-pcie-host", 290 + .data = &j721e_pcie_rc_data, 291 + }, 292 + { 293 + .compatible = "ti,j721e-pcie-ep", 294 + .data = &j721e_pcie_ep_data, 295 + }, 296 + {}, 297 + }; 298 + 299 + static int j721e_pcie_probe(struct platform_device *pdev) 300 + { 301 + struct device *dev = &pdev->dev; 302 + struct device_node *node = dev->of_node; 303 + struct pci_host_bridge *bridge; 304 + struct j721e_pcie_data *data; 305 + struct cdns_pcie *cdns_pcie; 306 + struct j721e_pcie *pcie; 307 + struct cdns_pcie_rc *rc; 308 + struct cdns_pcie_ep *ep; 309 + struct gpio_desc *gpiod; 310 + void __iomem *base; 311 + u32 num_lanes; 312 + u32 mode; 313 + int ret; 314 + int irq; 315 + 316 + data = (struct j721e_pcie_data *)of_device_get_match_data(dev); 317 + if (!data) 318 + return -EINVAL; 319 + 320 + mode = (u32)data->mode; 321 + 322 + pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); 323 + if (!pcie) 324 + return -ENOMEM; 325 + 326 + pcie->dev = dev; 327 + pcie->mode = mode; 328 + 329 + base = devm_platform_ioremap_resource_byname(pdev, "intd_cfg"); 330 + if (IS_ERR(base)) 331 + return PTR_ERR(base); 332 + pcie->intd_cfg_base = base; 333 + 334 + base = devm_platform_ioremap_resource_byname(pdev, "user_cfg"); 335 + if (IS_ERR(base)) 336 + return PTR_ERR(base); 337 + pcie->user_cfg_base = base; 338 + 339 + ret = of_property_read_u32(node, "num-lanes", &num_lanes); 340 + if (ret || num_lanes > MAX_LANES) 341 + num_lanes = 1; 342 + pcie->num_lanes = num_lanes; 343 + 344 + if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48))) 345 + return -EINVAL; 346 + 347 + irq = platform_get_irq_byname(pdev, "link_state"); 348 + if (irq < 0) 349 + return irq; 350 + 351 + dev_set_drvdata(dev, pcie); 352 + pm_runtime_enable(dev); 353 + ret = pm_runtime_get_sync(dev); 354 + if (ret < 0) { 355 + dev_err(dev, "pm_runtime_get_sync failed\n"); 356 + goto err_get_sync; 357 + } 358 + 359 + ret = j721e_pcie_ctrl_init(pcie); 360 + if (ret < 0) { 361 + dev_err(dev, "pm_runtime_get_sync failed\n"); 362 + goto err_get_sync; 363 + } 364 + 365 + ret = devm_request_irq(dev, irq, j721e_pcie_link_irq_handler, 0, 366 + "j721e-pcie-link-down-irq", pcie); 367 + if (ret < 0) { 368 + dev_err(dev, "failed to request link state IRQ %d\n", irq); 369 + goto err_get_sync; 370 + } 371 + 372 + j721e_pcie_config_link_irq(pcie); 373 + 374 + switch (mode) { 375 + case PCI_MODE_RC: 376 + if (!IS_ENABLED(CONFIG_PCIE_CADENCE_HOST)) { 377 + ret = -ENODEV; 378 + goto err_get_sync; 379 + } 380 + 381 + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc)); 382 + if (!bridge) { 383 + ret = -ENOMEM; 384 + goto err_get_sync; 385 + } 386 + 387 + bridge->ops = &cdns_ti_pcie_host_ops; 388 + rc = pci_host_bridge_priv(bridge); 389 + 390 + cdns_pcie = &rc->pcie; 391 + cdns_pcie->dev = dev; 392 + cdns_pcie->ops = &j721e_pcie_ops; 393 + pcie->cdns_pcie = cdns_pcie; 394 + 395 + gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 396 + if (IS_ERR(gpiod)) { 397 + ret = PTR_ERR(gpiod); 398 + if (ret != -EPROBE_DEFER) 399 + dev_err(dev, "Failed to get reset GPIO\n"); 400 + goto err_get_sync; 401 + } 402 + 403 + ret = cdns_pcie_init_phy(dev, cdns_pcie); 404 + if (ret) { 405 + dev_err(dev, "Failed to init phy\n"); 406 + goto err_get_sync; 407 + } 408 + 409 + /* 410 + * "Power Sequencing and Reset Signal Timings" table in 411 + * PCI EXPRESS CARD ELECTROMECHANICAL SPECIFICATION, REV. 3.0 412 + * indicates PERST# should be deasserted after minimum of 100us 413 + * once REFCLK is stable. The REFCLK to the connector in RC 414 + * mode is selected while enabling the PHY. So deassert PERST# 415 + * after 100 us. 416 + */ 417 + if (gpiod) { 418 + usleep_range(100, 200); 419 + gpiod_set_value_cansleep(gpiod, 1); 420 + } 421 + 422 + ret = cdns_pcie_host_setup(rc); 423 + if (ret < 0) 424 + goto err_pcie_setup; 425 + 426 + break; 427 + case PCI_MODE_EP: 428 + if (!IS_ENABLED(CONFIG_PCIE_CADENCE_EP)) { 429 + ret = -ENODEV; 430 + goto err_get_sync; 431 + } 432 + 433 + ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); 434 + if (!ep) { 435 + ret = -ENOMEM; 436 + goto err_get_sync; 437 + } 438 + 439 + cdns_pcie = &ep->pcie; 440 + cdns_pcie->dev = dev; 441 + cdns_pcie->ops = &j721e_pcie_ops; 442 + pcie->cdns_pcie = cdns_pcie; 443 + 444 + ret = cdns_pcie_init_phy(dev, cdns_pcie); 445 + if (ret) { 446 + dev_err(dev, "Failed to init phy\n"); 447 + goto err_get_sync; 448 + } 449 + 450 + ret = cdns_pcie_ep_setup(ep); 451 + if (ret < 0) 452 + goto err_pcie_setup; 453 + 454 + break; 455 + default: 456 + dev_err(dev, "INVALID device type %d\n", mode); 457 + } 458 + 459 + return 0; 460 + 461 + err_pcie_setup: 462 + cdns_pcie_disable_phy(cdns_pcie); 463 + 464 + err_get_sync: 465 + pm_runtime_put(dev); 466 + pm_runtime_disable(dev); 467 + 468 + return ret; 469 + } 470 + 471 + static int j721e_pcie_remove(struct platform_device *pdev) 472 + { 473 + struct j721e_pcie *pcie = platform_get_drvdata(pdev); 474 + struct cdns_pcie *cdns_pcie = pcie->cdns_pcie; 475 + struct device *dev = &pdev->dev; 476 + 477 + cdns_pcie_disable_phy(cdns_pcie); 478 + pm_runtime_put(dev); 479 + pm_runtime_disable(dev); 480 + 481 + return 0; 482 + } 483 + 484 + static struct platform_driver j721e_pcie_driver = { 485 + .probe = j721e_pcie_probe, 486 + .remove = j721e_pcie_remove, 487 + .driver = { 488 + .name = "j721e-pcie", 489 + .of_match_table = of_j721e_pcie_match, 490 + .suppress_bind_attrs = true, 491 + }, 492 + }; 493 + builtin_platform_driver(j721e_pcie_driver);
+2 -2
drivers/pci/controller/cadence/pcie-cadence-host.c
··· 23 23 [RP_BAR1] = 0xF, 24 24 }; 25 25 26 - static void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn, 27 - int where) 26 + void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn, 27 + int where) 28 28 { 29 29 struct pci_host_bridge *bridge = pci_find_host_bridge(bus); 30 30 struct cdns_pcie_rc *rc = pci_host_bridge_priv(bridge);
+8
drivers/pci/controller/cadence/pcie-cadence.h
··· 475 475 476 476 #ifdef CONFIG_PCIE_CADENCE_HOST 477 477 int cdns_pcie_host_setup(struct cdns_pcie_rc *rc); 478 + void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn, 479 + int where); 478 480 #else 479 481 static inline int cdns_pcie_host_setup(struct cdns_pcie_rc *rc) 480 482 { 481 483 return 0; 484 + } 485 + 486 + static inline void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn, 487 + int where) 488 + { 489 + return NULL; 482 490 } 483 491 #endif 484 492