linux/drivers/pci/controller/dwc/pcie-al.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * PCIe host controller driver for Amazon's Annapurna Labs IP (used in chips
   4 * such as Graviton and Alpine)
   5 *
   6 * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   7 *
   8 * Author: Jonathan Chocron <jonnyc@amazon.com>
   9 */
  10
  11#include <linux/pci.h>
  12#include <linux/pci-ecam.h>
  13#include <linux/pci-acpi.h>
  14#include "../../pci.h"
  15
  16#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
  17
  18struct al_pcie_acpi  {
  19        void __iomem *dbi_base;
  20};
  21
  22static void __iomem *al_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
  23                                     int where)
  24{
  25        struct pci_config_window *cfg = bus->sysdata;
  26        struct al_pcie_acpi *pcie = cfg->priv;
  27        void __iomem *dbi_base = pcie->dbi_base;
  28
  29        if (bus->number == cfg->busr.start) {
  30                /*
  31                 * The DW PCIe core doesn't filter out transactions to other
  32                 * devices/functions on the root bus num, so we do this here.
  33                 */
  34                if (PCI_SLOT(devfn) > 0)
  35                        return NULL;
  36                else
  37                        return dbi_base + where;
  38        }
  39
  40        return pci_ecam_map_bus(bus, devfn, where);
  41}
  42
  43static int al_pcie_init(struct pci_config_window *cfg)
  44{
  45        struct device *dev = cfg->parent;
  46        struct acpi_device *adev = to_acpi_device(dev);
  47        struct acpi_pci_root *root = acpi_driver_data(adev);
  48        struct al_pcie_acpi *al_pcie;
  49        struct resource *res;
  50        int ret;
  51
  52        al_pcie = devm_kzalloc(dev, sizeof(*al_pcie), GFP_KERNEL);
  53        if (!al_pcie)
  54                return -ENOMEM;
  55
  56        res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
  57        if (!res)
  58                return -ENOMEM;
  59
  60        ret = acpi_get_rc_resources(dev, "AMZN0001", root->segment, res);
  61        if (ret) {
  62                dev_err(dev, "can't get rc dbi base address for SEG %d\n",
  63                        root->segment);
  64                return ret;
  65        }
  66
  67        dev_dbg(dev, "Root port dbi res: %pR\n", res);
  68
  69        al_pcie->dbi_base = devm_pci_remap_cfg_resource(dev, res);
  70        if (IS_ERR(al_pcie->dbi_base))
  71                return PTR_ERR(al_pcie->dbi_base);
  72
  73        cfg->priv = al_pcie;
  74
  75        return 0;
  76}
  77
  78const struct pci_ecam_ops al_pcie_ops = {
  79        .init         =  al_pcie_init,
  80        .pci_ops      = {
  81                .map_bus    = al_pcie_map_bus,
  82                .read       = pci_generic_config_read,
  83                .write      = pci_generic_config_write,
  84        }
  85};
  86
  87#endif /* defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) */
  88
  89#ifdef CONFIG_PCIE_AL
  90
  91#include <linux/of_pci.h>
  92#include "pcie-designware.h"
  93
  94#define AL_PCIE_REV_ID_2        2
  95#define AL_PCIE_REV_ID_3        3
  96#define AL_PCIE_REV_ID_4        4
  97
  98#define AXI_BASE_OFFSET         0x0
  99
 100#define DEVICE_ID_OFFSET        0x16c
 101
 102#define DEVICE_REV_ID                   0x0
 103#define DEVICE_REV_ID_DEV_ID_MASK       GENMASK(31, 16)
 104
 105#define DEVICE_REV_ID_DEV_ID_X4         0
 106#define DEVICE_REV_ID_DEV_ID_X8         2
 107#define DEVICE_REV_ID_DEV_ID_X16        4
 108
 109#define OB_CTRL_REV1_2_OFFSET   0x0040
 110#define OB_CTRL_REV3_5_OFFSET   0x0030
 111
 112#define CFG_TARGET_BUS                  0x0
 113#define CFG_TARGET_BUS_MASK_MASK        GENMASK(7, 0)
 114#define CFG_TARGET_BUS_BUSNUM_MASK      GENMASK(15, 8)
 115
 116#define CFG_CONTROL                     0x4
 117#define CFG_CONTROL_SUBBUS_MASK         GENMASK(15, 8)
 118#define CFG_CONTROL_SEC_BUS_MASK        GENMASK(23, 16)
 119
 120struct al_pcie_reg_offsets {
 121        unsigned int ob_ctrl;
 122};
 123
 124struct al_pcie_target_bus_cfg {
 125        u8 reg_val;
 126        u8 reg_mask;
 127        u8 ecam_mask;
 128};
 129
 130struct al_pcie {
 131        struct dw_pcie *pci;
 132        void __iomem *controller_base; /* base of PCIe unit (not DW core) */
 133        struct device *dev;
 134        resource_size_t ecam_size;
 135        unsigned int controller_rev_id;
 136        struct al_pcie_reg_offsets reg_offsets;
 137        struct al_pcie_target_bus_cfg target_bus_cfg;
 138};
 139
 140#define to_al_pcie(x)           dev_get_drvdata((x)->dev)
 141
 142static inline u32 al_pcie_controller_readl(struct al_pcie *pcie, u32 offset)
 143{
 144        return readl_relaxed(pcie->controller_base + offset);
 145}
 146
 147static inline void al_pcie_controller_writel(struct al_pcie *pcie, u32 offset,
 148                                             u32 val)
 149{
 150        writel_relaxed(val, pcie->controller_base + offset);
 151}
 152
 153static int al_pcie_rev_id_get(struct al_pcie *pcie, unsigned int *rev_id)
 154{
 155        u32 dev_rev_id_val;
 156        u32 dev_id_val;
 157
 158        dev_rev_id_val = al_pcie_controller_readl(pcie, AXI_BASE_OFFSET +
 159                                                  DEVICE_ID_OFFSET +
 160                                                  DEVICE_REV_ID);
 161        dev_id_val = FIELD_GET(DEVICE_REV_ID_DEV_ID_MASK, dev_rev_id_val);
 162
 163        switch (dev_id_val) {
 164        case DEVICE_REV_ID_DEV_ID_X4:
 165                *rev_id = AL_PCIE_REV_ID_2;
 166                break;
 167        case DEVICE_REV_ID_DEV_ID_X8:
 168                *rev_id = AL_PCIE_REV_ID_3;
 169                break;
 170        case DEVICE_REV_ID_DEV_ID_X16:
 171                *rev_id = AL_PCIE_REV_ID_4;
 172                break;
 173        default:
 174                dev_err(pcie->dev, "Unsupported dev_id_val (0x%x)\n",
 175                        dev_id_val);
 176                return -EINVAL;
 177        }
 178
 179        dev_dbg(pcie->dev, "dev_id_val: 0x%x\n", dev_id_val);
 180
 181        return 0;
 182}
 183
 184static int al_pcie_reg_offsets_set(struct al_pcie *pcie)
 185{
 186        switch (pcie->controller_rev_id) {
 187        case AL_PCIE_REV_ID_2:
 188                pcie->reg_offsets.ob_ctrl = OB_CTRL_REV1_2_OFFSET;
 189                break;
 190        case AL_PCIE_REV_ID_3:
 191        case AL_PCIE_REV_ID_4:
 192                pcie->reg_offsets.ob_ctrl = OB_CTRL_REV3_5_OFFSET;
 193                break;
 194        default:
 195                dev_err(pcie->dev, "Unsupported controller rev_id: 0x%x\n",
 196                        pcie->controller_rev_id);
 197                return -EINVAL;
 198        }
 199
 200        return 0;
 201}
 202
 203static inline void al_pcie_target_bus_set(struct al_pcie *pcie,
 204                                          u8 target_bus,
 205                                          u8 mask_target_bus)
 206{
 207        u32 reg;
 208
 209        reg = FIELD_PREP(CFG_TARGET_BUS_MASK_MASK, mask_target_bus) |
 210              FIELD_PREP(CFG_TARGET_BUS_BUSNUM_MASK, target_bus);
 211
 212        al_pcie_controller_writel(pcie, AXI_BASE_OFFSET +
 213                                  pcie->reg_offsets.ob_ctrl + CFG_TARGET_BUS,
 214                                  reg);
 215}
 216
 217static void __iomem *al_pcie_conf_addr_map_bus(struct pci_bus *bus,
 218                                               unsigned int devfn, int where)
 219{
 220        struct pcie_port *pp = bus->sysdata;
 221        struct al_pcie *pcie = to_al_pcie(to_dw_pcie_from_pp(pp));
 222        unsigned int busnr = bus->number;
 223        struct al_pcie_target_bus_cfg *target_bus_cfg = &pcie->target_bus_cfg;
 224        unsigned int busnr_ecam = busnr & target_bus_cfg->ecam_mask;
 225        unsigned int busnr_reg = busnr & target_bus_cfg->reg_mask;
 226
 227        if (busnr_reg != target_bus_cfg->reg_val) {
 228                dev_dbg(pcie->pci->dev, "Changing target bus busnum val from 0x%x to 0x%x\n",
 229                        target_bus_cfg->reg_val, busnr_reg);
 230                target_bus_cfg->reg_val = busnr_reg;
 231                al_pcie_target_bus_set(pcie,
 232                                       target_bus_cfg->reg_val,
 233                                       target_bus_cfg->reg_mask);
 234        }
 235
 236        return pp->va_cfg0_base + PCIE_ECAM_OFFSET(busnr_ecam, devfn, where);
 237}
 238
 239static struct pci_ops al_child_pci_ops = {
 240        .map_bus = al_pcie_conf_addr_map_bus,
 241        .read = pci_generic_config_read,
 242        .write = pci_generic_config_write,
 243};
 244
 245static void al_pcie_config_prepare(struct al_pcie *pcie)
 246{
 247        struct al_pcie_target_bus_cfg *target_bus_cfg;
 248        struct pcie_port *pp = &pcie->pci->pp;
 249        unsigned int ecam_bus_mask;
 250        u32 cfg_control_offset;
 251        u8 subordinate_bus;
 252        u8 secondary_bus;
 253        u32 cfg_control;
 254        u32 reg;
 255        struct resource *bus = resource_list_first_type(&pp->bridge->windows, IORESOURCE_BUS)->res;
 256
 257        target_bus_cfg = &pcie->target_bus_cfg;
 258
 259        ecam_bus_mask = (pcie->ecam_size >> PCIE_ECAM_BUS_SHIFT) - 1;
 260        if (ecam_bus_mask > 255) {
 261                dev_warn(pcie->dev, "ECAM window size is larger than 256MB. Cutting off at 256\n");
 262                ecam_bus_mask = 255;
 263        }
 264
 265        /* This portion is taken from the transaction address */
 266        target_bus_cfg->ecam_mask = ecam_bus_mask;
 267        /* This portion is taken from the cfg_target_bus reg */
 268        target_bus_cfg->reg_mask = ~target_bus_cfg->ecam_mask;
 269        target_bus_cfg->reg_val = bus->start & target_bus_cfg->reg_mask;
 270
 271        al_pcie_target_bus_set(pcie, target_bus_cfg->reg_val,
 272                               target_bus_cfg->reg_mask);
 273
 274        secondary_bus = bus->start + 1;
 275        subordinate_bus = bus->end;
 276
 277        /* Set the valid values of secondary and subordinate buses */
 278        cfg_control_offset = AXI_BASE_OFFSET + pcie->reg_offsets.ob_ctrl +
 279                             CFG_CONTROL;
 280
 281        cfg_control = al_pcie_controller_readl(pcie, cfg_control_offset);
 282
 283        reg = cfg_control &
 284              ~(CFG_CONTROL_SEC_BUS_MASK | CFG_CONTROL_SUBBUS_MASK);
 285
 286        reg |= FIELD_PREP(CFG_CONTROL_SUBBUS_MASK, subordinate_bus) |
 287               FIELD_PREP(CFG_CONTROL_SEC_BUS_MASK, secondary_bus);
 288
 289        al_pcie_controller_writel(pcie, cfg_control_offset, reg);
 290}
 291
 292static int al_pcie_host_init(struct pcie_port *pp)
 293{
 294        struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 295        struct al_pcie *pcie = to_al_pcie(pci);
 296        int rc;
 297
 298        pp->bridge->child_ops = &al_child_pci_ops;
 299
 300        rc = al_pcie_rev_id_get(pcie, &pcie->controller_rev_id);
 301        if (rc)
 302                return rc;
 303
 304        rc = al_pcie_reg_offsets_set(pcie);
 305        if (rc)
 306                return rc;
 307
 308        al_pcie_config_prepare(pcie);
 309
 310        return 0;
 311}
 312
 313static const struct dw_pcie_host_ops al_pcie_host_ops = {
 314        .host_init = al_pcie_host_init,
 315};
 316
 317static const struct dw_pcie_ops dw_pcie_ops = {
 318};
 319
 320static int al_pcie_probe(struct platform_device *pdev)
 321{
 322        struct device *dev = &pdev->dev;
 323        struct resource *controller_res;
 324        struct resource *ecam_res;
 325        struct al_pcie *al_pcie;
 326        struct dw_pcie *pci;
 327
 328        al_pcie = devm_kzalloc(dev, sizeof(*al_pcie), GFP_KERNEL);
 329        if (!al_pcie)
 330                return -ENOMEM;
 331
 332        pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
 333        if (!pci)
 334                return -ENOMEM;
 335
 336        pci->dev = dev;
 337        pci->ops = &dw_pcie_ops;
 338        pci->pp.ops = &al_pcie_host_ops;
 339
 340        al_pcie->pci = pci;
 341        al_pcie->dev = dev;
 342
 343        ecam_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
 344        if (!ecam_res) {
 345                dev_err(dev, "couldn't find 'config' reg in DT\n");
 346                return -ENOENT;
 347        }
 348        al_pcie->ecam_size = resource_size(ecam_res);
 349
 350        controller_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 351                                                      "controller");
 352        al_pcie->controller_base = devm_ioremap_resource(dev, controller_res);
 353        if (IS_ERR(al_pcie->controller_base)) {
 354                dev_err(dev, "couldn't remap controller base %pR\n",
 355                        controller_res);
 356                return PTR_ERR(al_pcie->controller_base);
 357        }
 358
 359        dev_dbg(dev, "From DT: controller_base: %pR\n", controller_res);
 360
 361        platform_set_drvdata(pdev, al_pcie);
 362
 363        return dw_pcie_host_init(&pci->pp);
 364}
 365
 366static const struct of_device_id al_pcie_of_match[] = {
 367        { .compatible = "amazon,al-alpine-v2-pcie",
 368        },
 369        { .compatible = "amazon,al-alpine-v3-pcie",
 370        },
 371        {},
 372};
 373
 374static struct platform_driver al_pcie_driver = {
 375        .driver = {
 376                .name   = "al-pcie",
 377                .of_match_table = al_pcie_of_match,
 378                .suppress_bind_attrs = true,
 379        },
 380        .probe = al_pcie_probe,
 381};
 382builtin_platform_driver(al_pcie_driver);
 383
 384#endif /* CONFIG_PCIE_AL*/
 385