uboot/drivers/pci/pcie_intel_fpga.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Intel FPGA PCIe host controller driver
   4 *
   5 * Copyright (C) 2013-2018 Intel Corporation. All rights reserved
   6 *
   7 */
   8
   9#include <common.h>
  10#include <dm.h>
  11#include <pci.h>
  12#include <asm/io.h>
  13#include <dm/device_compat.h>
  14#include <linux/bitops.h>
  15#include <linux/delay.h>
  16
  17#define RP_TX_REG0                      0x2000
  18#define RP_TX_CNTRL                     0x2004
  19#define RP_TX_SOP                       BIT(0)
  20#define RP_TX_EOP                       BIT(1)
  21#define RP_RXCPL_STATUS                 0x200C
  22#define RP_RXCPL_SOP                    BIT(0)
  23#define RP_RXCPL_EOP                    BIT(1)
  24#define RP_RXCPL_REG                    0x2008
  25#define P2A_INT_STATUS                  0x3060
  26#define P2A_INT_STS_ALL                 0xf
  27#define P2A_INT_ENABLE                  0x3070
  28#define RP_CAP_OFFSET                   0x70
  29
  30/* TLP configuration type 0 and 1 */
  31#define TLP_FMTTYPE_CFGRD0              0x04    /* Configuration Read Type 0 */
  32#define TLP_FMTTYPE_CFGWR0              0x44    /* Configuration Write Type 0 */
  33#define TLP_FMTTYPE_CFGRD1              0x05    /* Configuration Read Type 1 */
  34#define TLP_FMTTYPE_CFGWR1              0x45    /* Configuration Write Type 1 */
  35#define TLP_PAYLOAD_SIZE                0x01
  36#define TLP_READ_TAG                    0x1d
  37#define TLP_WRITE_TAG                   0x10
  38#define RP_DEVFN                        0
  39
  40#define RP_CFG_ADDR(pcie, reg)                                          \
  41                ((pcie->hip_base) + (reg) + (1 << 20))
  42#define RP_SECONDARY(pcie)                                              \
  43        readb(RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS))
  44#define TLP_REQ_ID(bus, devfn)          (((bus) << 8) | (devfn))
  45
  46#define TLP_CFGRD_DW0(pcie, bus)                                        \
  47        ((((bus > RP_SECONDARY(pcie)) ? TLP_FMTTYPE_CFGRD1              \
  48                                      : TLP_FMTTYPE_CFGRD0) << 24) |    \
  49                                        TLP_PAYLOAD_SIZE)
  50
  51#define TLP_CFGWR_DW0(pcie, bus)                                        \
  52        ((((bus > RP_SECONDARY(pcie)) ? TLP_FMTTYPE_CFGWR1              \
  53                                      : TLP_FMTTYPE_CFGWR0) << 24) |    \
  54                                        TLP_PAYLOAD_SIZE)
  55
  56#define TLP_CFG_DW1(pcie, tag, be)                                      \
  57        (((TLP_REQ_ID(pcie->first_busno,  RP_DEVFN)) << 16) | (tag << 8) | (be))
  58#define TLP_CFG_DW2(bus, dev, fn, offset)                               \
  59        (((bus) << 24) | ((dev) << 19) | ((fn) << 16) | (offset))
  60
  61#define TLP_COMP_STATUS(s)              (((s) >> 13) & 7)
  62#define TLP_BYTE_COUNT(s)               (((s) >> 0) & 0xfff)
  63#define TLP_HDR_SIZE                    3
  64#define TLP_LOOP                        20000
  65#define DWORD_MASK                      3
  66
  67#define IS_ROOT_PORT(pcie, bdf)                         \
  68                ((PCI_BUS(bdf) == pcie->first_busno) ? true : false)
  69
  70#define PCI_EXP_LNKSTA          18      /* Link Status */
  71#define PCI_EXP_LNKSTA_DLLLA    0x2000  /* Data Link Layer Link Active */
  72
  73/**
  74 * struct intel_fpga_pcie - Intel FPGA PCIe controller state
  75 * @bus: Pointer to the PCI bus
  76 * @cra_base: The base address of CRA register space
  77 * @hip_base: The base address of Rootport configuration space
  78 * @first_busno: This driver supports multiple PCIe controllers.
  79 *               first_busno stores the bus number of the PCIe root-port
  80 *               number which may vary depending on the PCIe setup.
  81 */
  82struct intel_fpga_pcie {
  83        struct udevice *bus;
  84        void __iomem *cra_base;
  85        void __iomem *hip_base;
  86        int first_busno;
  87};
  88
  89/**
  90 * Intel FPGA PCIe port uses BAR0 of RC's configuration space as the
  91 * translation from PCI bus to native BUS. Entire DDR region is mapped
  92 * into PCIe space using these registers, so it can be reached by DMA from
  93 * EP devices.
  94 * The BAR0 of bridge should be hidden during enumeration to avoid the
  95 * sizing and resource allocation by PCIe core.
  96 */
  97static bool intel_fpga_pcie_hide_rc_bar(struct intel_fpga_pcie *pcie,
  98                                        pci_dev_t bdf, int offset)
  99{
 100        if (IS_ROOT_PORT(pcie, bdf) && PCI_DEV(bdf) == 0 &&
 101            PCI_FUNC(bdf) == 0 && offset == PCI_BASE_ADDRESS_0)
 102                return true;
 103
 104        return false;
 105}
 106
 107static inline void cra_writel(struct intel_fpga_pcie *pcie, const u32 value,
 108                              const u32 reg)
 109{
 110        writel(value, pcie->cra_base + reg);
 111}
 112
 113static inline u32 cra_readl(struct intel_fpga_pcie *pcie, const u32 reg)
 114{
 115        return readl(pcie->cra_base + reg);
 116}
 117
 118static bool intel_fpga_pcie_link_up(struct intel_fpga_pcie *pcie)
 119{
 120        return !!(readw(RP_CFG_ADDR(pcie, RP_CAP_OFFSET + PCI_EXP_LNKSTA))
 121                        & PCI_EXP_LNKSTA_DLLLA);
 122}
 123
 124static bool intel_fpga_pcie_addr_valid(struct intel_fpga_pcie *pcie,
 125                                       pci_dev_t bdf)
 126{
 127        /* If there is no link, then there is no device */
 128        if (!IS_ROOT_PORT(pcie, bdf) && !intel_fpga_pcie_link_up(pcie))
 129                return false;
 130
 131        /* access only one slot on each root port */
 132        if (IS_ROOT_PORT(pcie, bdf) && PCI_DEV(bdf) > 0)
 133                return false;
 134
 135        if ((PCI_BUS(bdf) == pcie->first_busno + 1) && PCI_DEV(bdf) > 0)
 136                return false;
 137
 138        return true;
 139}
 140
 141static void tlp_write_tx(struct intel_fpga_pcie *pcie, u32 reg0, u32 ctrl)
 142{
 143        cra_writel(pcie, reg0, RP_TX_REG0);
 144        cra_writel(pcie, ctrl, RP_TX_CNTRL);
 145}
 146
 147static int tlp_read_packet(struct intel_fpga_pcie *pcie, u32 *value)
 148{
 149        int i;
 150        u32 ctrl;
 151        u32 comp_status;
 152        u32 dw[4];
 153        u32 count = 0;
 154
 155        for (i = 0; i < TLP_LOOP; i++) {
 156                ctrl = cra_readl(pcie, RP_RXCPL_STATUS);
 157                if (!(ctrl & RP_RXCPL_SOP))
 158                        continue;
 159
 160                /* read first DW */
 161                dw[count++] = cra_readl(pcie, RP_RXCPL_REG);
 162
 163                /* Poll for EOP */
 164                for (i = 0; i < TLP_LOOP; i++) {
 165                        ctrl = cra_readl(pcie, RP_RXCPL_STATUS);
 166                        dw[count++] = cra_readl(pcie, RP_RXCPL_REG);
 167                        if (ctrl & RP_RXCPL_EOP) {
 168                                comp_status = TLP_COMP_STATUS(dw[1]);
 169                                if (comp_status) {
 170                                        *value = pci_get_ff(PCI_SIZE_32);
 171                                        return 0;
 172                                }
 173
 174                                if (value &&
 175                                    TLP_BYTE_COUNT(dw[1]) == sizeof(u32) &&
 176                                    count >= 3)
 177                                        *value = dw[3];
 178
 179                                return 0;
 180                        }
 181                }
 182
 183                udelay(5);
 184        }
 185
 186        dev_err(pcie->dev, "read TLP packet timed out\n");
 187        return -ENODEV;
 188}
 189
 190static void tlp_write_packet(struct intel_fpga_pcie *pcie, u32 *headers,
 191                             u32 data)
 192{
 193        tlp_write_tx(pcie, headers[0], RP_TX_SOP);
 194
 195        tlp_write_tx(pcie, headers[1], 0);
 196
 197        tlp_write_tx(pcie, headers[2], 0);
 198
 199        tlp_write_tx(pcie, data, RP_TX_EOP);
 200}
 201
 202static int tlp_cfg_dword_read(struct intel_fpga_pcie *pcie, pci_dev_t bdf,
 203                              int offset, u8 byte_en, u32 *value)
 204{
 205        u32 headers[TLP_HDR_SIZE];
 206        u8 busno = PCI_BUS(bdf);
 207
 208        headers[0] = TLP_CFGRD_DW0(pcie, busno);
 209        headers[1] = TLP_CFG_DW1(pcie, TLP_READ_TAG, byte_en);
 210        headers[2] = TLP_CFG_DW2(busno, PCI_DEV(bdf), PCI_FUNC(bdf), offset);
 211
 212        tlp_write_packet(pcie, headers, 0);
 213
 214        return tlp_read_packet(pcie, value);
 215}
 216
 217static int tlp_cfg_dword_write(struct intel_fpga_pcie *pcie, pci_dev_t bdf,
 218                               int offset, u8 byte_en, u32 value)
 219{
 220        u32 headers[TLP_HDR_SIZE];
 221        u8 busno = PCI_BUS(bdf);
 222
 223        headers[0] = TLP_CFGWR_DW0(pcie, busno);
 224        headers[1] = TLP_CFG_DW1(pcie, TLP_WRITE_TAG, byte_en);
 225        headers[2] = TLP_CFG_DW2(busno, PCI_DEV(bdf), PCI_FUNC(bdf), offset);
 226
 227        tlp_write_packet(pcie, headers, value);
 228
 229        return tlp_read_packet(pcie, NULL);
 230}
 231
 232int intel_fpga_rp_conf_addr(const struct udevice *bus, pci_dev_t bdf,
 233                            uint offset, void **paddress)
 234{
 235        struct intel_fpga_pcie *pcie = dev_get_priv(bus);
 236
 237        *paddress = RP_CFG_ADDR(pcie, offset);
 238
 239        return 0;
 240}
 241
 242static int intel_fpga_pcie_rp_rd_conf(struct udevice *bus, pci_dev_t bdf,
 243                                      uint offset, ulong *valuep,
 244                                      enum pci_size_t size)
 245{
 246        return pci_generic_mmap_read_config(bus, intel_fpga_rp_conf_addr,
 247                                            bdf, offset, valuep, size);
 248}
 249
 250static int intel_fpga_pcie_rp_wr_conf(struct udevice *bus, pci_dev_t bdf,
 251                                      uint offset, ulong value,
 252                                      enum pci_size_t size)
 253{
 254        int ret;
 255        struct intel_fpga_pcie *pcie = dev_get_priv(bus);
 256
 257        ret = pci_generic_mmap_write_config(bus, intel_fpga_rp_conf_addr,
 258                                            bdf, offset, value, size);
 259        if (!ret) {
 260                /* Monitor changes to PCI_PRIMARY_BUS register on root port
 261                 * and update local copy of root bus number accordingly.
 262                 */
 263                if (offset == PCI_PRIMARY_BUS)
 264                        pcie->first_busno = (u8)(value);
 265        }
 266
 267        return ret;
 268}
 269
 270static u8 pcie_get_byte_en(uint offset, enum pci_size_t size)
 271{
 272        switch (size) {
 273        case PCI_SIZE_8:
 274                return 1 << (offset & 3);
 275        case PCI_SIZE_16:
 276                return 3 << (offset & 3);
 277        default:
 278                return 0xf;
 279        }
 280}
 281
 282static int _pcie_intel_fpga_read_config(struct intel_fpga_pcie *pcie,
 283                                        pci_dev_t bdf, uint offset,
 284                                        ulong *valuep, enum pci_size_t size)
 285{
 286        int ret;
 287        u32 data;
 288        u8 byte_en;
 289
 290        /* Uses memory mapped method to read rootport config registers */
 291        if (IS_ROOT_PORT(pcie, bdf))
 292                return intel_fpga_pcie_rp_rd_conf(pcie->bus, bdf,
 293                                       offset, valuep, size);
 294
 295        byte_en = pcie_get_byte_en(offset, size);
 296        ret = tlp_cfg_dword_read(pcie, bdf, offset & ~DWORD_MASK,
 297                                 byte_en, &data);
 298        if (ret)
 299                return ret;
 300
 301        dev_dbg(pcie->dev, "(addr,size,val)=(0x%04x, %d, 0x%08x)\n",
 302                offset, size, data);
 303        *valuep = pci_conv_32_to_size(data, offset, size);
 304
 305        return 0;
 306}
 307
 308static int _pcie_intel_fpga_write_config(struct intel_fpga_pcie *pcie,
 309                                         pci_dev_t bdf, uint offset,
 310                                         ulong value, enum pci_size_t size)
 311{
 312        u32 data;
 313        u8 byte_en;
 314
 315        dev_dbg(pcie->dev, "PCIE CFG write: (b.d.f)=(%02d.%02d.%02d)\n",
 316                PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
 317        dev_dbg(pcie->dev, "(addr,size,val)=(0x%04x, %d, 0x%08lx)\n",
 318                offset, size, value);
 319
 320        /* Uses memory mapped method to read rootport config registers */
 321        if (IS_ROOT_PORT(pcie, bdf))
 322                return intel_fpga_pcie_rp_wr_conf(pcie->bus, bdf, offset,
 323                                                  value, size);
 324
 325        byte_en = pcie_get_byte_en(offset, size);
 326        data = pci_conv_size_to_32(0, value, offset, size);
 327
 328        return tlp_cfg_dword_write(pcie, bdf, offset & ~DWORD_MASK,
 329                                   byte_en, data);
 330}
 331
 332static int pcie_intel_fpga_read_config(const struct udevice *bus, pci_dev_t bdf,
 333                                       uint offset, ulong *valuep,
 334                                       enum pci_size_t size)
 335{
 336        struct intel_fpga_pcie *pcie = dev_get_priv(bus);
 337
 338        dev_dbg(pcie->dev, "PCIE CFG read:  (b.d.f)=(%02d.%02d.%02d)\n",
 339                PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
 340
 341        if (intel_fpga_pcie_hide_rc_bar(pcie, bdf, offset)) {
 342                *valuep = (u32)pci_get_ff(size);
 343                return 0;
 344        }
 345
 346        if (!intel_fpga_pcie_addr_valid(pcie, bdf)) {
 347                *valuep = (u32)pci_get_ff(size);
 348                return 0;
 349        }
 350
 351        return _pcie_intel_fpga_read_config(pcie, bdf, offset, valuep, size);
 352}
 353
 354static int pcie_intel_fpga_write_config(struct udevice *bus, pci_dev_t bdf,
 355                                        uint offset, ulong value,
 356                                        enum pci_size_t size)
 357{
 358        struct intel_fpga_pcie *pcie = dev_get_priv(bus);
 359
 360        if (intel_fpga_pcie_hide_rc_bar(pcie, bdf, offset))
 361                return 0;
 362
 363        if (!intel_fpga_pcie_addr_valid(pcie, bdf))
 364                return 0;
 365
 366        return _pcie_intel_fpga_write_config(pcie, bdf, offset, value,
 367                                          size);
 368}
 369
 370static int pcie_intel_fpga_probe(struct udevice *dev)
 371{
 372        struct intel_fpga_pcie *pcie = dev_get_priv(dev);
 373
 374        pcie->bus = pci_get_controller(dev);
 375        pcie->first_busno = dev->seq;
 376
 377        /* clear all interrupts */
 378        cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS);
 379        /* disable all interrupts */
 380        cra_writel(pcie, 0, P2A_INT_ENABLE);
 381
 382        return 0;
 383}
 384
 385static int pcie_intel_fpga_ofdata_to_platdata(struct udevice *dev)
 386{
 387        struct intel_fpga_pcie *pcie = dev_get_priv(dev);
 388        struct fdt_resource reg_res;
 389        int node = dev_of_offset(dev);
 390        int ret;
 391
 392        DECLARE_GLOBAL_DATA_PTR;
 393
 394        ret = fdt_get_named_resource(gd->fdt_blob, node, "reg", "reg-names",
 395                                     "Cra", &reg_res);
 396        if (ret) {
 397                dev_err(dev, "resource \"Cra\" not found\n");
 398                return ret;
 399        }
 400
 401        pcie->cra_base = map_physmem(reg_res.start,
 402                                     fdt_resource_size(&reg_res),
 403                                     MAP_NOCACHE);
 404
 405        ret = fdt_get_named_resource(gd->fdt_blob, node, "reg", "reg-names",
 406                                     "Hip", &reg_res);
 407        if (ret) {
 408                dev_err(dev, "resource \"Hip\" not found\n");
 409                return ret;
 410        }
 411
 412        pcie->hip_base = map_physmem(reg_res.start,
 413                                     fdt_resource_size(&reg_res),
 414                                     MAP_NOCACHE);
 415
 416        return 0;
 417}
 418
 419static const struct dm_pci_ops pcie_intel_fpga_ops = {
 420        .read_config    = pcie_intel_fpga_read_config,
 421        .write_config   = pcie_intel_fpga_write_config,
 422};
 423
 424static const struct udevice_id pcie_intel_fpga_ids[] = {
 425        { .compatible = "altr,pcie-root-port-2.0" },
 426        {},
 427};
 428
 429U_BOOT_DRIVER(pcie_intel_fpga) = {
 430        .name                   = "pcie_intel_fpga",
 431        .id                     = UCLASS_PCI,
 432        .of_match               = pcie_intel_fpga_ids,
 433        .ops                    = &pcie_intel_fpga_ops,
 434        .ofdata_to_platdata     = pcie_intel_fpga_ofdata_to_platdata,
 435        .probe                  = pcie_intel_fpga_probe,
 436        .priv_auto_alloc_size   = sizeof(struct intel_fpga_pcie),
 437};
 438