root/drivers/pci/controller/pcie-cadence-host.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cdns_pci_map_bus
  2. cdns_pcie_host_init_root_port
  3. cdns_pcie_host_init_address_translation
  4. cdns_pcie_host_init
  5. cdns_pcie_host_probe
  6. cdns_pcie_shutdown

   1 // SPDX-License-Identifier: GPL-2.0
   2 // Copyright (c) 2017 Cadence
   3 // Cadence PCIe host controller driver.
   4 // Author: Cyrille Pitchen <cyrille.pitchen@free-electrons.com>
   5 
   6 #include <linux/kernel.h>
   7 #include <linux/of_address.h>
   8 #include <linux/of_pci.h>
   9 #include <linux/platform_device.h>
  10 #include <linux/pm_runtime.h>
  11 
  12 #include "pcie-cadence.h"
  13 
  14 /**
  15  * struct cdns_pcie_rc - private data for this PCIe Root Complex driver
  16  * @pcie: Cadence PCIe controller
  17  * @dev: pointer to PCIe device
  18  * @cfg_res: start/end offsets in the physical system memory to map PCI
  19  *           configuration space accesses
  20  * @bus_range: first/last buses behind the PCIe host controller
  21  * @cfg_base: IO mapped window to access the PCI configuration space of a
  22  *            single function at a time
  23  * @max_regions: maximum number of regions supported by the hardware
  24  * @no_bar_nbits: Number of bits to keep for inbound (PCIe -> CPU) address
  25  *                translation (nbits sets into the "no BAR match" register)
  26  * @vendor_id: PCI vendor ID
  27  * @device_id: PCI device ID
  28  */
  29 struct cdns_pcie_rc {
  30         struct cdns_pcie        pcie;
  31         struct device           *dev;
  32         struct resource         *cfg_res;
  33         struct resource         *bus_range;
  34         void __iomem            *cfg_base;
  35         u32                     max_regions;
  36         u32                     no_bar_nbits;
  37         u16                     vendor_id;
  38         u16                     device_id;
  39 };
  40 
  41 static void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
  42                                       int where)
  43 {
  44         struct pci_host_bridge *bridge = pci_find_host_bridge(bus);
  45         struct cdns_pcie_rc *rc = pci_host_bridge_priv(bridge);
  46         struct cdns_pcie *pcie = &rc->pcie;
  47         unsigned int busn = bus->number;
  48         u32 addr0, desc0;
  49 
  50         if (busn == rc->bus_range->start) {
  51                 /*
  52                  * Only the root port (devfn == 0) is connected to this bus.
  53                  * All other PCI devices are behind some bridge hence on another
  54                  * bus.
  55                  */
  56                 if (devfn)
  57                         return NULL;
  58 
  59                 return pcie->reg_base + (where & 0xfff);
  60         }
  61         /* Check that the link is up */
  62         if (!(cdns_pcie_readl(pcie, CDNS_PCIE_LM_BASE) & 0x1))
  63                 return NULL;
  64         /* Clear AXI link-down status */
  65         cdns_pcie_writel(pcie, CDNS_PCIE_AT_LINKDOWN, 0x0);
  66 
  67         /* Update Output registers for AXI region 0. */
  68         addr0 = CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS(12) |
  69                 CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) |
  70                 CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(busn);
  71         cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR0(0), addr0);
  72 
  73         /* Configuration Type 0 or Type 1 access. */
  74         desc0 = CDNS_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID |
  75                 CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(0);
  76         /*
  77          * The bus number was already set once for all in desc1 by
  78          * cdns_pcie_host_init_address_translation().
  79          */
  80         if (busn == rc->bus_range->start + 1)
  81                 desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE0;
  82         else
  83                 desc0 |= CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE1;
  84         cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC0(0), desc0);
  85 
  86         return rc->cfg_base + (where & 0xfff);
  87 }
  88 
  89 static struct pci_ops cdns_pcie_host_ops = {
  90         .map_bus        = cdns_pci_map_bus,
  91         .read           = pci_generic_config_read,
  92         .write          = pci_generic_config_write,
  93 };
  94 
  95 static const struct of_device_id cdns_pcie_host_of_match[] = {
  96         { .compatible = "cdns,cdns-pcie-host" },
  97 
  98         { },
  99 };
 100 
 101 static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc)
 102 {
 103         struct cdns_pcie *pcie = &rc->pcie;
 104         u32 value, ctrl;
 105 
 106         /*
 107          * Set the root complex BAR configuration register:
 108          * - disable both BAR0 and BAR1.
 109          * - enable Prefetchable Memory Base and Limit registers in type 1
 110          *   config space (64 bits).
 111          * - enable IO Base and Limit registers in type 1 config
 112          *   space (32 bits).
 113          */
 114         ctrl = CDNS_PCIE_LM_BAR_CFG_CTRL_DISABLED;
 115         value = CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL(ctrl) |
 116                 CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL(ctrl) |
 117                 CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_ENABLE |
 118                 CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_64BITS |
 119                 CDNS_PCIE_LM_RC_BAR_CFG_IO_ENABLE |
 120                 CDNS_PCIE_LM_RC_BAR_CFG_IO_32BITS;
 121         cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
 122 
 123         /* Set root port configuration space */
 124         if (rc->vendor_id != 0xffff)
 125                 cdns_pcie_rp_writew(pcie, PCI_VENDOR_ID, rc->vendor_id);
 126         if (rc->device_id != 0xffff)
 127                 cdns_pcie_rp_writew(pcie, PCI_DEVICE_ID, rc->device_id);
 128 
 129         cdns_pcie_rp_writeb(pcie, PCI_CLASS_REVISION, 0);
 130         cdns_pcie_rp_writeb(pcie, PCI_CLASS_PROG, 0);
 131         cdns_pcie_rp_writew(pcie, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_PCI);
 132 
 133         return 0;
 134 }
 135 
 136 static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
 137 {
 138         struct cdns_pcie *pcie = &rc->pcie;
 139         struct resource *cfg_res = rc->cfg_res;
 140         struct resource *mem_res = pcie->mem_res;
 141         struct resource *bus_range = rc->bus_range;
 142         struct device *dev = rc->dev;
 143         struct device_node *np = dev->of_node;
 144         struct of_pci_range_parser parser;
 145         struct of_pci_range range;
 146         u32 addr0, addr1, desc1;
 147         u64 cpu_addr;
 148         int r, err;
 149 
 150         /*
 151          * Reserve region 0 for PCI configure space accesses:
 152          * OB_REGION_PCI_ADDR0 and OB_REGION_DESC0 are updated dynamically by
 153          * cdns_pci_map_bus(), other region registers are set here once for all.
 154          */
 155         addr1 = 0; /* Should be programmed to zero. */
 156         desc1 = CDNS_PCIE_AT_OB_REGION_DESC1_BUS(bus_range->start);
 157         cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_PCI_ADDR1(0), addr1);
 158         cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_DESC1(0), desc1);
 159 
 160         cpu_addr = cfg_res->start - mem_res->start;
 161         addr0 = CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(12) |
 162                 (lower_32_bits(cpu_addr) & GENMASK(31, 8));
 163         addr1 = upper_32_bits(cpu_addr);
 164         cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(0), addr0);
 165         cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(0), addr1);
 166 
 167         err = of_pci_range_parser_init(&parser, np);
 168         if (err)
 169                 return err;
 170 
 171         r = 1;
 172         for_each_of_pci_range(&parser, &range) {
 173                 bool is_io;
 174 
 175                 if (r >= rc->max_regions)
 176                         break;
 177 
 178                 if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM)
 179                         is_io = false;
 180                 else if ((range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_IO)
 181                         is_io = true;
 182                 else
 183                         continue;
 184 
 185                 cdns_pcie_set_outbound_region(pcie, 0, r, is_io,
 186                                               range.cpu_addr,
 187                                               range.pci_addr,
 188                                               range.size);
 189                 r++;
 190         }
 191 
 192         /*
 193          * Set Root Port no BAR match Inbound Translation registers:
 194          * needed for MSI and DMA.
 195          * Root Port BAR0 and BAR1 are disabled, hence no need to set their
 196          * inbound translation registers.
 197          */
 198         addr0 = CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS(rc->no_bar_nbits);
 199         addr1 = 0;
 200         cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR0(RP_NO_BAR), addr0);
 201         cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR1(RP_NO_BAR), addr1);
 202 
 203         return 0;
 204 }
 205 
 206 static int cdns_pcie_host_init(struct device *dev,
 207                                struct list_head *resources,
 208                                struct cdns_pcie_rc *rc)
 209 {
 210         struct resource *bus_range = NULL;
 211         int err;
 212 
 213         /* Parse our PCI ranges and request their resources */
 214         err = pci_parse_request_of_pci_ranges(dev, resources, &bus_range);
 215         if (err)
 216                 return err;
 217 
 218         rc->bus_range = bus_range;
 219         rc->pcie.bus = bus_range->start;
 220 
 221         err = cdns_pcie_host_init_root_port(rc);
 222         if (err)
 223                 goto err_out;
 224 
 225         err = cdns_pcie_host_init_address_translation(rc);
 226         if (err)
 227                 goto err_out;
 228 
 229         return 0;
 230 
 231  err_out:
 232         pci_free_resource_list(resources);
 233         return err;
 234 }
 235 
 236 static int cdns_pcie_host_probe(struct platform_device *pdev)
 237 {
 238         struct device *dev = &pdev->dev;
 239         struct device_node *np = dev->of_node;
 240         struct pci_host_bridge *bridge;
 241         struct list_head resources;
 242         struct cdns_pcie_rc *rc;
 243         struct cdns_pcie *pcie;
 244         struct resource *res;
 245         int ret;
 246         int phy_count;
 247 
 248         bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc));
 249         if (!bridge)
 250                 return -ENOMEM;
 251 
 252         rc = pci_host_bridge_priv(bridge);
 253         rc->dev = dev;
 254 
 255         pcie = &rc->pcie;
 256         pcie->is_rc = true;
 257 
 258         rc->max_regions = 32;
 259         of_property_read_u32(np, "cdns,max-outbound-regions", &rc->max_regions);
 260 
 261         rc->no_bar_nbits = 32;
 262         of_property_read_u32(np, "cdns,no-bar-match-nbits", &rc->no_bar_nbits);
 263 
 264         rc->vendor_id = 0xffff;
 265         of_property_read_u16(np, "vendor-id", &rc->vendor_id);
 266 
 267         rc->device_id = 0xffff;
 268         of_property_read_u16(np, "device-id", &rc->device_id);
 269 
 270         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "reg");
 271         pcie->reg_base = devm_ioremap_resource(dev, res);
 272         if (IS_ERR(pcie->reg_base)) {
 273                 dev_err(dev, "missing \"reg\"\n");
 274                 return PTR_ERR(pcie->reg_base);
 275         }
 276 
 277         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
 278         rc->cfg_base = devm_pci_remap_cfg_resource(dev, res);
 279         if (IS_ERR(rc->cfg_base)) {
 280                 dev_err(dev, "missing \"cfg\"\n");
 281                 return PTR_ERR(rc->cfg_base);
 282         }
 283         rc->cfg_res = res;
 284 
 285         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem");
 286         if (!res) {
 287                 dev_err(dev, "missing \"mem\"\n");
 288                 return -EINVAL;
 289         }
 290         pcie->mem_res = res;
 291 
 292         ret = cdns_pcie_init_phy(dev, pcie);
 293         if (ret) {
 294                 dev_err(dev, "failed to init phy\n");
 295                 return ret;
 296         }
 297         platform_set_drvdata(pdev, pcie);
 298 
 299         pm_runtime_enable(dev);
 300         ret = pm_runtime_get_sync(dev);
 301         if (ret < 0) {
 302                 dev_err(dev, "pm_runtime_get_sync() failed\n");
 303                 goto err_get_sync;
 304         }
 305 
 306         ret = cdns_pcie_host_init(dev, &resources, rc);
 307         if (ret)
 308                 goto err_init;
 309 
 310         list_splice_init(&resources, &bridge->windows);
 311         bridge->dev.parent = dev;
 312         bridge->busnr = pcie->bus;
 313         bridge->ops = &cdns_pcie_host_ops;
 314         bridge->map_irq = of_irq_parse_and_map_pci;
 315         bridge->swizzle_irq = pci_common_swizzle;
 316 
 317         ret = pci_host_probe(bridge);
 318         if (ret < 0)
 319                 goto err_host_probe;
 320 
 321         return 0;
 322 
 323  err_host_probe:
 324         pci_free_resource_list(&resources);
 325 
 326  err_init:
 327         pm_runtime_put_sync(dev);
 328 
 329  err_get_sync:
 330         pm_runtime_disable(dev);
 331         cdns_pcie_disable_phy(pcie);
 332         phy_count = pcie->phy_count;
 333         while (phy_count--)
 334                 device_link_del(pcie->link[phy_count]);
 335 
 336         return ret;
 337 }
 338 
 339 static void cdns_pcie_shutdown(struct platform_device *pdev)
 340 {
 341         struct device *dev = &pdev->dev;
 342         struct cdns_pcie *pcie = dev_get_drvdata(dev);
 343         int ret;
 344 
 345         ret = pm_runtime_put_sync(dev);
 346         if (ret < 0)
 347                 dev_dbg(dev, "pm_runtime_put_sync failed\n");
 348 
 349         pm_runtime_disable(dev);
 350         cdns_pcie_disable_phy(pcie);
 351 }
 352 
 353 static struct platform_driver cdns_pcie_host_driver = {
 354         .driver = {
 355                 .name = "cdns-pcie-host",
 356                 .of_match_table = cdns_pcie_host_of_match,
 357                 .pm     = &cdns_pcie_pm_ops,
 358         },
 359         .probe = cdns_pcie_host_probe,
 360         .shutdown = cdns_pcie_shutdown,
 361 };
 362 builtin_platform_driver(cdns_pcie_host_driver);

/* [<][>][^][v][top][bottom][index][help] */