linux/drivers/pci/controller/pcie-cadence-host.c
<<
>>
Prefs
   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 */
  29struct 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
  41static 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
  89static 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
  95static const struct of_device_id cdns_pcie_host_of_match[] = {
  96        { .compatible = "cdns,cdns-pcie-host" },
  97
  98        { },
  99};
 100
 101static 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
 136static 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
 206static 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
 236static 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
 339static 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
 353static 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};
 362builtin_platform_driver(cdns_pcie_host_driver);
 363