uboot/drivers/pci/pci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   4 * Andreas Heppel <aheppel@sysgo.de>
   5 *
   6 * (C) Copyright 2002, 2003
   7 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   8 */
   9
  10/*
  11 * Old PCI routines
  12 *
  13 * Do not change this file. Instead, convert your board to use CONFIG_DM_PCI
  14 * and change pci-uclass.c.
  15 */
  16
  17#include <common.h>
  18#include <init.h>
  19#include <log.h>
  20#include <asm/global_data.h>
  21#include <linux/delay.h>
  22
  23#include <command.h>
  24#include <env.h>
  25#include <errno.h>
  26#include <asm/processor.h>
  27#include <asm/io.h>
  28#include <pci.h>
  29
  30DECLARE_GLOBAL_DATA_PTR;
  31
  32#define PCI_HOSE_OP(rw, size, type)                                     \
  33int pci_hose_##rw##_config_##size(struct pci_controller *hose,          \
  34                                  pci_dev_t dev,                        \
  35                                  int offset, type value)               \
  36{                                                                       \
  37        return hose->rw##_##size(hose, dev, offset, value);             \
  38}
  39
  40PCI_HOSE_OP(read, byte, u8 *)
  41PCI_HOSE_OP(read, word, u16 *)
  42PCI_HOSE_OP(read, dword, u32 *)
  43PCI_HOSE_OP(write, byte, u8)
  44PCI_HOSE_OP(write, word, u16)
  45PCI_HOSE_OP(write, dword, u32)
  46
  47#define PCI_OP(rw, size, type, error_code)                              \
  48int pci_##rw##_config_##size(pci_dev_t dev, int offset, type value)     \
  49{                                                                       \
  50        struct pci_controller *hose = pci_bus_to_hose(PCI_BUS(dev));    \
  51                                                                        \
  52        if (!hose)                                                      \
  53        {                                                               \
  54                error_code;                                             \
  55                return -1;                                              \
  56        }                                                               \
  57                                                                        \
  58        return pci_hose_##rw##_config_##size(hose, dev, offset, value); \
  59}
  60
  61PCI_OP(read, byte, u8 *, *value = 0xff)
  62PCI_OP(read, word, u16 *, *value = 0xffff)
  63PCI_OP(read, dword, u32 *, *value = 0xffffffff)
  64PCI_OP(write, byte, u8, )
  65PCI_OP(write, word, u16, )
  66PCI_OP(write, dword, u32, )
  67
  68#define PCI_READ_VIA_DWORD_OP(size, type, off_mask)                     \
  69int pci_hose_read_config_##size##_via_dword(struct pci_controller *hose,\
  70                                        pci_dev_t dev,                  \
  71                                        int offset, type val)           \
  72{                                                                       \
  73        u32 val32;                                                      \
  74                                                                        \
  75        if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0) { \
  76                *val = -1;                                              \
  77                return -1;                                              \
  78        }                                                               \
  79                                                                        \
  80        *val = (val32 >> ((offset & (int)off_mask) * 8));               \
  81                                                                        \
  82        return 0;                                                       \
  83}
  84
  85#define PCI_WRITE_VIA_DWORD_OP(size, type, off_mask, val_mask)          \
  86int pci_hose_write_config_##size##_via_dword(struct pci_controller *hose,\
  87                                             pci_dev_t dev,             \
  88                                             int offset, type val)      \
  89{                                                                       \
  90        u32 val32, mask, ldata, shift;                                  \
  91                                                                        \
  92        if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0)\
  93                return -1;                                              \
  94                                                                        \
  95        shift = ((offset & (int)off_mask) * 8);                         \
  96        ldata = (((unsigned long)val) & val_mask) << shift;             \
  97        mask = val_mask << shift;                                       \
  98        val32 = (val32 & ~mask) | ldata;                                \
  99                                                                        \
 100        if (pci_hose_write_config_dword(hose, dev, offset & 0xfc, val32) < 0)\
 101                return -1;                                              \
 102                                                                        \
 103        return 0;                                                       \
 104}
 105
 106PCI_READ_VIA_DWORD_OP(byte, u8 *, 0x03)
 107PCI_READ_VIA_DWORD_OP(word, u16 *, 0x02)
 108PCI_WRITE_VIA_DWORD_OP(byte, u8, 0x03, 0x000000ff)
 109PCI_WRITE_VIA_DWORD_OP(word, u16, 0x02, 0x0000ffff)
 110
 111/*
 112 *
 113 */
 114
 115static struct pci_controller* hose_head;
 116
 117struct pci_controller *pci_get_hose_head(void)
 118{
 119        if (gd->hose)
 120                return gd->hose;
 121
 122        return hose_head;
 123}
 124
 125void pci_register_hose(struct pci_controller* hose)
 126{
 127        struct pci_controller **phose = &hose_head;
 128
 129        while(*phose)
 130                phose = &(*phose)->next;
 131
 132        hose->next = NULL;
 133
 134        *phose = hose;
 135}
 136
 137struct pci_controller *pci_bus_to_hose(int bus)
 138{
 139        struct pci_controller *hose;
 140
 141        for (hose = pci_get_hose_head(); hose; hose = hose->next) {
 142                if (bus >= hose->first_busno && bus <= hose->last_busno)
 143                        return hose;
 144        }
 145
 146        printf("pci_bus_to_hose() failed\n");
 147        return NULL;
 148}
 149
 150struct pci_controller *find_hose_by_cfg_addr(void *cfg_addr)
 151{
 152        struct pci_controller *hose;
 153
 154        for (hose = pci_get_hose_head(); hose; hose = hose->next) {
 155                if (hose->cfg_addr == cfg_addr)
 156                        return hose;
 157        }
 158
 159        return NULL;
 160}
 161
 162int pci_last_busno(void)
 163{
 164        struct pci_controller *hose = pci_get_hose_head();
 165
 166        if (!hose)
 167                return -1;
 168
 169        while (hose->next)
 170                hose = hose->next;
 171
 172        return hose->last_busno;
 173}
 174
 175pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
 176{
 177        struct pci_controller * hose;
 178        pci_dev_t bdf;
 179        int bus;
 180
 181        for (hose = pci_get_hose_head(); hose; hose = hose->next) {
 182                for (bus = hose->first_busno; bus <= hose->last_busno; bus++) {
 183                        bdf = pci_hose_find_devices(hose, bus, ids, &index);
 184                        if (bdf != -1)
 185                                return bdf;
 186                }
 187        }
 188
 189        return -1;
 190}
 191
 192static int pci_hose_config_device(struct pci_controller *hose, pci_dev_t dev,
 193                                  ulong io, pci_addr_t mem, ulong command)
 194{
 195        u32 bar_response;
 196        unsigned int old_command;
 197        pci_addr_t bar_value;
 198        pci_size_t bar_size;
 199        unsigned char pin;
 200        int bar, found_mem64;
 201
 202        debug("PCI Config: I/O=0x%lx, Memory=0x%llx, Command=0x%lx\n", io,
 203                (u64)mem, command);
 204
 205        pci_hose_write_config_dword(hose, dev, PCI_COMMAND, 0);
 206
 207        for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar += 4) {
 208                pci_hose_write_config_dword(hose, dev, bar, 0xffffffff);
 209                pci_hose_read_config_dword(hose, dev, bar, &bar_response);
 210
 211                if (!bar_response)
 212                        continue;
 213
 214                found_mem64 = 0;
 215
 216                /* Check the BAR type and set our address mask */
 217                if (bar_response & PCI_BASE_ADDRESS_SPACE) {
 218                        bar_size = ~(bar_response & PCI_BASE_ADDRESS_IO_MASK) + 1;
 219                        /* round up region base address to a multiple of size */
 220                        io = ((io - 1) | (bar_size - 1)) + 1;
 221                        bar_value = io;
 222                        /* compute new region base address */
 223                        io = io + bar_size;
 224                } else {
 225                        if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
 226                                PCI_BASE_ADDRESS_MEM_TYPE_64) {
 227                                u32 bar_response_upper;
 228                                u64 bar64;
 229                                pci_hose_write_config_dword(hose, dev, bar + 4,
 230                                        0xffffffff);
 231                                pci_hose_read_config_dword(hose, dev, bar + 4,
 232                                        &bar_response_upper);
 233
 234                                bar64 = ((u64)bar_response_upper << 32) | bar_response;
 235
 236                                bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1;
 237                                found_mem64 = 1;
 238                        } else {
 239                                bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1);
 240                        }
 241
 242                        /* round up region base address to multiple of size */
 243                        mem = ((mem - 1) | (bar_size - 1)) + 1;
 244                        bar_value = mem;
 245                        /* compute new region base address */
 246                        mem = mem + bar_size;
 247                }
 248
 249                /* Write it out and update our limit */
 250                pci_hose_write_config_dword (hose, dev, bar, (u32)bar_value);
 251
 252                if (found_mem64) {
 253                        bar += 4;
 254#ifdef CONFIG_SYS_PCI_64BIT
 255                        pci_hose_write_config_dword(hose, dev, bar,
 256                                (u32)(bar_value >> 32));
 257#else
 258                        pci_hose_write_config_dword(hose, dev, bar, 0x00000000);
 259#endif
 260                }
 261        }
 262
 263        /* Configure Cache Line Size Register */
 264        pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
 265
 266        /* Configure Latency Timer */
 267        pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
 268
 269        /* Disable interrupt line, if device says it wants to use interrupts */
 270        pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin);
 271        if (pin != 0) {
 272                pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE,
 273                                           PCI_INTERRUPT_LINE_DISABLE);
 274        }
 275
 276        pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &old_command);
 277        pci_hose_write_config_dword(hose, dev, PCI_COMMAND,
 278                                     (old_command & 0xffff0000) | command);
 279
 280        return 0;
 281}
 282
 283/*
 284 *
 285 */
 286
 287struct pci_config_table *pci_find_config(struct pci_controller *hose,
 288                                         unsigned short class,
 289                                         unsigned int vendor,
 290                                         unsigned int device,
 291                                         unsigned int bus,
 292                                         unsigned int dev,
 293                                         unsigned int func)
 294{
 295        struct pci_config_table *table;
 296
 297        for (table = hose->config_table; table && table->vendor; table++) {
 298                if ((table->vendor == PCI_ANY_ID || table->vendor == vendor) &&
 299                    (table->device == PCI_ANY_ID || table->device == device) &&
 300                    (table->class  == PCI_ANY_ID || table->class  == class)  &&
 301                    (table->bus    == PCI_ANY_ID || table->bus    == bus)    &&
 302                    (table->dev    == PCI_ANY_ID || table->dev    == dev)    &&
 303                    (table->func   == PCI_ANY_ID || table->func   == func)) {
 304                        return table;
 305                }
 306        }
 307
 308        return NULL;
 309}
 310
 311void pci_cfgfunc_config_device(struct pci_controller *hose,
 312                               pci_dev_t dev,
 313                               struct pci_config_table *entry)
 314{
 315        pci_hose_config_device(hose, dev, entry->priv[0], entry->priv[1],
 316                entry->priv[2]);
 317}
 318
 319void pci_cfgfunc_do_nothing(struct pci_controller *hose,
 320                            pci_dev_t dev, struct pci_config_table *entry)
 321{
 322}
 323
 324/*
 325 * HJF: Changed this to return int. I think this is required
 326 * to get the correct result when scanning bridges
 327 */
 328extern int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev);
 329
 330#ifdef CONFIG_PCI_SCAN_SHOW
 331__weak int pci_print_dev(struct pci_controller *hose, pci_dev_t dev)
 332{
 333        if (dev == PCI_BDF(hose->first_busno, 0, 0))
 334                return 0;
 335
 336        return 1;
 337}
 338#endif /* CONFIG_PCI_SCAN_SHOW */
 339
 340int pci_hose_scan_bus(struct pci_controller *hose, int bus)
 341{
 342        unsigned int sub_bus, found_multi = 0;
 343        unsigned short vendor, device, class;
 344        unsigned char header_type;
 345#ifndef CONFIG_PCI_PNP
 346        struct pci_config_table *cfg;
 347#endif
 348        pci_dev_t dev;
 349#ifdef CONFIG_PCI_SCAN_SHOW
 350        static int indent = 0;
 351#endif
 352
 353        sub_bus = bus;
 354
 355        for (dev =  PCI_BDF(bus,0,0);
 356             dev <  PCI_BDF(bus, PCI_MAX_PCI_DEVICES - 1,
 357                                PCI_MAX_PCI_FUNCTIONS - 1);
 358             dev += PCI_BDF(0, 0, 1)) {
 359
 360                if (pci_skip_dev(hose, dev))
 361                        continue;
 362
 363                if (PCI_FUNC(dev) && !found_multi)
 364                        continue;
 365
 366                pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type);
 367
 368                pci_hose_read_config_word(hose, dev, PCI_VENDOR_ID, &vendor);
 369
 370                if (vendor == 0xffff || vendor == 0x0000)
 371                        continue;
 372
 373                if (!PCI_FUNC(dev))
 374                        found_multi = header_type & 0x80;
 375
 376                debug("PCI Scan: Found Bus %d, Device %d, Function %d\n",
 377                        PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev));
 378
 379                pci_hose_read_config_word(hose, dev, PCI_DEVICE_ID, &device);
 380                pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);
 381
 382#ifdef CONFIG_PCI_FIXUP_DEV
 383                board_pci_fixup_dev(hose, dev, vendor, device, class);
 384#endif
 385
 386#ifdef CONFIG_PCI_SCAN_SHOW
 387                indent++;
 388
 389                /* Print leading space, including bus indentation */
 390                printf("%*c", indent + 1, ' ');
 391
 392                if (pci_print_dev(hose, dev)) {
 393                        printf("%02x:%02x.%-*x - %04x:%04x - %s\n",
 394                               PCI_BUS(dev), PCI_DEV(dev), 6 - indent, PCI_FUNC(dev),
 395                               vendor, device, pci_class_str(class >> 8));
 396                }
 397#endif
 398
 399#ifdef CONFIG_PCI_PNP
 400                sub_bus = max((unsigned int)pciauto_config_device(hose, dev),
 401                              sub_bus);
 402#else
 403                cfg = pci_find_config(hose, class, vendor, device,
 404                                      PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev));
 405                if (cfg) {
 406                        cfg->config_device(hose, dev, cfg);
 407                        sub_bus = max(sub_bus,
 408                                      (unsigned int)hose->current_busno);
 409                }
 410#endif
 411
 412#ifdef CONFIG_PCI_SCAN_SHOW
 413                indent--;
 414#endif
 415
 416                if (hose->fixup_irq)
 417                        hose->fixup_irq(hose, dev);
 418        }
 419
 420        return sub_bus;
 421}
 422
 423int pci_hose_scan(struct pci_controller *hose)
 424{
 425#if defined(CONFIG_PCI_BOOTDELAY)
 426        char *s;
 427        int i;
 428
 429        if (!gd->pcidelay_done) {
 430                /* wait "pcidelay" ms (if defined)... */
 431                s = env_get("pcidelay");
 432                if (s) {
 433                        int val = simple_strtoul(s, NULL, 10);
 434                        for (i = 0; i < val; i++)
 435                                udelay(1000);
 436                }
 437                gd->pcidelay_done = 1;
 438        }
 439#endif /* CONFIG_PCI_BOOTDELAY */
 440
 441#ifdef CONFIG_PCI_SCAN_SHOW
 442        puts("PCI:\n");
 443#endif
 444
 445        /*
 446         * Start scan at current_busno.
 447         * PCIe will start scan at first_busno+1.
 448         */
 449        /* For legacy support, ensure current >= first */
 450        if (hose->first_busno > hose->current_busno)
 451                hose->current_busno = hose->first_busno;
 452#ifdef CONFIG_PCI_PNP
 453        pciauto_config_init(hose);
 454#endif
 455        return pci_hose_scan_bus(hose, hose->current_busno);
 456}
 457
 458int pci_init(void)
 459{
 460        hose_head = NULL;
 461
 462        /* allow env to disable pci init/enum */
 463        if (env_get("pcidisable") != NULL)
 464                return 0;
 465
 466        /* now call board specific pci_init()... */
 467        pci_init_board();
 468
 469        return 0;
 470}
 471
 472/* Returns the address of the requested capability structure within the
 473 * device's PCI configuration space or 0 in case the device does not
 474 * support it.
 475 * */
 476int pci_hose_find_capability(struct pci_controller *hose, pci_dev_t dev,
 477                             int cap)
 478{
 479        int pos;
 480        u8 hdr_type;
 481
 482        pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &hdr_type);
 483
 484        pos = pci_hose_find_cap_start(hose, dev, hdr_type & 0x7F);
 485
 486        if (pos)
 487                pos = pci_find_cap(hose, dev, pos, cap);
 488
 489        return pos;
 490}
 491
 492/* Find the header pointer to the Capabilities*/
 493int pci_hose_find_cap_start(struct pci_controller *hose, pci_dev_t dev,
 494                            u8 hdr_type)
 495{
 496        u16 status;
 497
 498        pci_hose_read_config_word(hose, dev, PCI_STATUS, &status);
 499
 500        if (!(status & PCI_STATUS_CAP_LIST))
 501                return 0;
 502
 503        switch (hdr_type) {
 504        case PCI_HEADER_TYPE_NORMAL:
 505        case PCI_HEADER_TYPE_BRIDGE:
 506                return PCI_CAPABILITY_LIST;
 507        case PCI_HEADER_TYPE_CARDBUS:
 508                return PCI_CB_CAPABILITY_LIST;
 509        default:
 510                return 0;
 511        }
 512}
 513
 514int pci_find_cap(struct pci_controller *hose, pci_dev_t dev, int pos, int cap)
 515{
 516        int ttl = PCI_FIND_CAP_TTL;
 517        u8 id;
 518        u8 next_pos;
 519
 520        while (ttl--) {
 521                pci_hose_read_config_byte(hose, dev, pos, &next_pos);
 522                if (next_pos < CAP_START_POS)
 523                        break;
 524                next_pos &= ~3;
 525                pos = (int) next_pos;
 526                pci_hose_read_config_byte(hose, dev,
 527                                          pos + PCI_CAP_LIST_ID, &id);
 528                if (id == 0xff)
 529                        break;
 530                if (id == cap)
 531                        return pos;
 532                pos += PCI_CAP_LIST_NEXT;
 533        }
 534        return 0;
 535}
 536
 537/**
 538 * pci_find_next_ext_capability - Find an extended capability
 539 *
 540 * Returns the address of the next matching extended capability structure
 541 * within the device's PCI configuration space or 0 if the device does
 542 * not support it.  Some capabilities can occur several times, e.g., the
 543 * vendor-specific capability, and this provides a way to find them all.
 544 */
 545int pci_find_next_ext_capability(struct pci_controller *hose, pci_dev_t dev,
 546                                 int start, int cap)
 547{
 548        u32 header;
 549        int ttl, pos = PCI_CFG_SPACE_SIZE;
 550
 551        /* minimum 8 bytes per capability */
 552        ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
 553
 554        if (start)
 555                pos = start;
 556
 557        pci_hose_read_config_dword(hose, dev, pos, &header);
 558        if (header == 0xffffffff || header == 0)
 559                return 0;
 560
 561        while (ttl-- > 0) {
 562                if (PCI_EXT_CAP_ID(header) == cap && pos != start)
 563                        return pos;
 564
 565                pos = PCI_EXT_CAP_NEXT(header);
 566                if (pos < PCI_CFG_SPACE_SIZE)
 567                        break;
 568
 569                pci_hose_read_config_dword(hose, dev, pos, &header);
 570                if (header == 0xffffffff || header == 0)
 571                        break;
 572        }
 573
 574        return 0;
 575}
 576
 577/**
 578 * pci_hose_find_ext_capability - Find an extended capability
 579 *
 580 * Returns the address of the requested extended capability structure
 581 * within the device's PCI configuration space or 0 if the device does
 582 * not support it.
 583 */
 584int pci_hose_find_ext_capability(struct pci_controller *hose, pci_dev_t dev,
 585                                 int cap)
 586{
 587        return pci_find_next_ext_capability(hose, dev, 0, cap);
 588}
 589