uboot/drivers/pci/pci.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   3 * Andreas Heppel <aheppel@sysgo.de>
   4 *
   5 * (C) Copyright 2002, 2003
   6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   7 *
   8 * See file CREDITS for list of people who contributed to this
   9 * project.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 of
  14 * the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24 * MA 02111-1307 USA
  25 */
  26
  27/*
  28 * PCI routines
  29 */
  30
  31#include <common.h>
  32
  33#include <command.h>
  34#include <asm/processor.h>
  35#include <asm/io.h>
  36#include <pci.h>
  37
  38#define PCI_HOSE_OP(rw, size, type)                                     \
  39int pci_hose_##rw##_config_##size(struct pci_controller *hose,          \
  40                                  pci_dev_t dev,                        \
  41                                  int offset, type value)               \
  42{                                                                       \
  43        return hose->rw##_##size(hose, dev, offset, value);             \
  44}
  45
  46PCI_HOSE_OP(read, byte, u8 *)
  47PCI_HOSE_OP(read, word, u16 *)
  48PCI_HOSE_OP(read, dword, u32 *)
  49PCI_HOSE_OP(write, byte, u8)
  50PCI_HOSE_OP(write, word, u16)
  51PCI_HOSE_OP(write, dword, u32)
  52
  53#ifndef CONFIG_IXP425
  54#define PCI_OP(rw, size, type, error_code)                              \
  55int pci_##rw##_config_##size(pci_dev_t dev, int offset, type value)     \
  56{                                                                       \
  57        struct pci_controller *hose = pci_bus_to_hose(PCI_BUS(dev));    \
  58                                                                        \
  59        if (!hose)                                                      \
  60        {                                                               \
  61                error_code;                                             \
  62                return -1;                                              \
  63        }                                                               \
  64                                                                        \
  65        return pci_hose_##rw##_config_##size(hose, dev, offset, value); \
  66}
  67
  68PCI_OP(read, byte, u8 *, *value = 0xff)
  69PCI_OP(read, word, u16 *, *value = 0xffff)
  70PCI_OP(read, dword, u32 *, *value = 0xffffffff)
  71PCI_OP(write, byte, u8, )
  72PCI_OP(write, word, u16, )
  73PCI_OP(write, dword, u32, )
  74#endif  /* CONFIG_IXP425 */
  75
  76#define PCI_READ_VIA_DWORD_OP(size, type, off_mask)                     \
  77int pci_hose_read_config_##size##_via_dword(struct pci_controller *hose,\
  78                                        pci_dev_t dev,                  \
  79                                        int offset, type val)           \
  80{                                                                       \
  81        u32 val32;                                                      \
  82                                                                        \
  83        if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0) { \
  84                *val = -1;                                              \
  85                return -1;                                              \
  86        }                                                               \
  87                                                                        \
  88        *val = (val32 >> ((offset & (int)off_mask) * 8));               \
  89                                                                        \
  90        return 0;                                                       \
  91}
  92
  93#define PCI_WRITE_VIA_DWORD_OP(size, type, off_mask, val_mask)          \
  94int pci_hose_write_config_##size##_via_dword(struct pci_controller *hose,\
  95                                             pci_dev_t dev,             \
  96                                             int offset, type val)      \
  97{                                                                       \
  98        u32 val32, mask, ldata, shift;                                  \
  99                                                                        \
 100        if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0)\
 101                return -1;                                              \
 102                                                                        \
 103        shift = ((offset & (int)off_mask) * 8);                         \
 104        ldata = (((unsigned long)val) & val_mask) << shift;             \
 105        mask = val_mask << shift;                                       \
 106        val32 = (val32 & ~mask) | ldata;                                \
 107                                                                        \
 108        if (pci_hose_write_config_dword(hose, dev, offset & 0xfc, val32) < 0)\
 109                return -1;                                              \
 110                                                                        \
 111        return 0;                                                       \
 112}
 113
 114PCI_READ_VIA_DWORD_OP(byte, u8 *, 0x03)
 115PCI_READ_VIA_DWORD_OP(word, u16 *, 0x02)
 116PCI_WRITE_VIA_DWORD_OP(byte, u8, 0x03, 0x000000ff)
 117PCI_WRITE_VIA_DWORD_OP(word, u16, 0x02, 0x0000ffff)
 118
 119/*
 120 *
 121 */
 122
 123static struct pci_controller* hose_head = NULL;
 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 = hose_head; hose; hose = hose->next)
 142                if (bus >= hose->first_busno && bus <= hose->last_busno)
 143                        return hose;
 144
 145        printf("pci_bus_to_hose() failed\n");
 146        return NULL;
 147}
 148
 149#ifndef CONFIG_IXP425
 150pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
 151{
 152        struct pci_controller * hose;
 153        u16 vendor, device;
 154        u8 header_type;
 155        pci_dev_t bdf;
 156        int i, bus, found_multi = 0;
 157
 158        for (hose = hose_head; hose; hose = hose->next)
 159        {
 160#ifdef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE
 161                for (bus = hose->last_busno; bus >= hose->first_busno; bus--)
 162#else
 163                for (bus = hose->first_busno; bus <= hose->last_busno; bus++)
 164#endif
 165                        for (bdf = PCI_BDF(bus,0,0);
 166#if defined(CONFIG_ELPPC) || defined(CONFIG_PPMC7XX)
 167                             bdf < PCI_BDF(bus,PCI_MAX_PCI_DEVICES-1,PCI_MAX_PCI_FUNCTIONS-1);
 168#else
 169                             bdf < PCI_BDF(bus+1,0,0);
 170#endif
 171                             bdf += PCI_BDF(0,0,1))
 172                        {
 173                                if (!PCI_FUNC(bdf)) {
 174                                        pci_read_config_byte(bdf,
 175                                                             PCI_HEADER_TYPE,
 176                                                             &header_type);
 177
 178                                        found_multi = header_type & 0x80;
 179                                } else {
 180                                        if (!found_multi)
 181                                                continue;
 182                                }
 183
 184                                pci_read_config_word(bdf,
 185                                                     PCI_VENDOR_ID,
 186                                                     &vendor);
 187                                pci_read_config_word(bdf,
 188                                                     PCI_DEVICE_ID,
 189                                                     &device);
 190
 191                                for (i=0; ids[i].vendor != 0; i++)
 192                                        if (vendor == ids[i].vendor &&
 193                                            device == ids[i].device)
 194                                        {
 195                                                if (index <= 0)
 196                                                        return bdf;
 197
 198                                                index--;
 199                                        }
 200                        }
 201        }
 202
 203        return (-1);
 204}
 205#endif  /* CONFIG_IXP425 */
 206
 207pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
 208{
 209        static struct pci_device_id ids[2] = {{}, {0, 0}};
 210
 211        ids[0].vendor = vendor;
 212        ids[0].device = device;
 213
 214        return pci_find_devices(ids, index);
 215}
 216
 217/*
 218 *
 219 */
 220
 221pci_addr_t pci_hose_phys_to_bus (struct pci_controller *hose,
 222                                    phys_addr_t phys_addr,
 223                                    unsigned long flags)
 224{
 225        struct pci_region *res;
 226        pci_addr_t bus_addr;
 227        int i;
 228
 229        if (!hose) {
 230                printf ("pci_hose_phys_to_bus: %s\n", "invalid hose");
 231                goto Done;
 232        }
 233
 234        for (i = 0; i < hose->region_count; i++) {
 235                res = &hose->regions[i];
 236
 237                if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
 238                        continue;
 239
 240                bus_addr = phys_addr - res->phys_start + res->bus_start;
 241
 242                if (bus_addr >= res->bus_start &&
 243                        bus_addr < res->bus_start + res->size) {
 244                        return bus_addr;
 245                }
 246        }
 247
 248        printf ("pci_hose_phys_to_bus: %s\n", "invalid physical address");
 249
 250Done:
 251        return 0;
 252}
 253
 254phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose,
 255                                 pci_addr_t bus_addr,
 256                                 unsigned long flags)
 257{
 258        struct pci_region *res;
 259        int i;
 260
 261        if (!hose) {
 262                printf ("pci_hose_bus_to_phys: %s\n", "invalid hose");
 263                goto Done;
 264        }
 265
 266        for (i = 0; i < hose->region_count; i++) {
 267                res = &hose->regions[i];
 268
 269                if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
 270                        continue;
 271
 272                if (bus_addr >= res->bus_start &&
 273                        bus_addr < res->bus_start + res->size) {
 274                        return bus_addr - res->bus_start + res->phys_start;
 275                }
 276        }
 277
 278        printf ("pci_hose_bus_to_phys: %s\n", "invalid physical address");
 279
 280Done:
 281        return 0;
 282}
 283
 284/*
 285 *
 286 */
 287
 288int pci_hose_config_device(struct pci_controller *hose,
 289                           pci_dev_t dev,
 290                           unsigned long io,
 291                           pci_addr_t mem,
 292                           unsigned long command)
 293{
 294        unsigned int bar_response, old_command;
 295        pci_addr_t bar_value;
 296        pci_size_t bar_size;
 297        unsigned char pin;
 298        int bar, found_mem64;
 299
 300        debug ("PCI Config: I/O=0x%lx, Memory=0x%llx, Command=0x%lx\n",
 301                io, (u64)mem, command);
 302
 303        pci_hose_write_config_dword (hose, dev, PCI_COMMAND, 0);
 304
 305        for (bar = PCI_BASE_ADDRESS_0; bar < PCI_BASE_ADDRESS_5; bar += 4) {
 306                pci_hose_write_config_dword (hose, dev, bar, 0xffffffff);
 307                pci_hose_read_config_dword (hose, dev, bar, &bar_response);
 308
 309                if (!bar_response)
 310                        continue;
 311
 312                found_mem64 = 0;
 313
 314                /* Check the BAR type and set our address mask */
 315                if (bar_response & PCI_BASE_ADDRESS_SPACE) {
 316                        bar_size = ~(bar_response & PCI_BASE_ADDRESS_IO_MASK) + 1;
 317                        /* round up region base address to a multiple of size */
 318                        io = ((io - 1) | (bar_size - 1)) + 1;
 319                        bar_value = io;
 320                        /* compute new region base address */
 321                        io = io + bar_size;
 322                } else {
 323                        if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
 324                                PCI_BASE_ADDRESS_MEM_TYPE_64) {
 325                                u32 bar_response_upper;
 326                                u64 bar64;
 327                                pci_hose_write_config_dword(hose, dev, bar+4, 0xffffffff);
 328                                pci_hose_read_config_dword(hose, dev, bar+4, &bar_response_upper);
 329
 330                                bar64 = ((u64)bar_response_upper << 32) | bar_response;
 331
 332                                bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1;
 333                                found_mem64 = 1;
 334                        } else {
 335                                bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1);
 336                        }
 337
 338                        /* round up region base address to multiple of size */
 339                        mem = ((mem - 1) | (bar_size - 1)) + 1;
 340                        bar_value = mem;
 341                        /* compute new region base address */
 342                        mem = mem + bar_size;
 343                }
 344
 345                /* Write it out and update our limit */
 346                pci_hose_write_config_dword (hose, dev, bar, (u32)bar_value);
 347
 348                if (found_mem64) {
 349                        bar += 4;
 350#ifdef CONFIG_SYS_PCI_64BIT
 351                        pci_hose_write_config_dword(hose, dev, bar, (u32)(bar_value>>32));
 352#else
 353                        pci_hose_write_config_dword (hose, dev, bar, 0x00000000);
 354#endif
 355                }
 356        }
 357
 358        /* Configure Cache Line Size Register */
 359        pci_hose_write_config_byte (hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
 360
 361        /* Configure Latency Timer */
 362        pci_hose_write_config_byte (hose, dev, PCI_LATENCY_TIMER, 0x80);
 363
 364        /* Disable interrupt line, if device says it wants to use interrupts */
 365        pci_hose_read_config_byte (hose, dev, PCI_INTERRUPT_PIN, &pin);
 366        if (pin != 0) {
 367                pci_hose_write_config_byte (hose, dev, PCI_INTERRUPT_LINE, 0xff);
 368        }
 369
 370        pci_hose_read_config_dword (hose, dev, PCI_COMMAND, &old_command);
 371        pci_hose_write_config_dword (hose, dev, PCI_COMMAND,
 372                                     (old_command & 0xffff0000) | command);
 373
 374        return 0;
 375}
 376
 377/*
 378 *
 379 */
 380
 381struct pci_config_table *pci_find_config(struct pci_controller *hose,
 382                                         unsigned short class,
 383                                         unsigned int vendor,
 384                                         unsigned int device,
 385                                         unsigned int bus,
 386                                         unsigned int dev,
 387                                         unsigned int func)
 388{
 389        struct pci_config_table *table;
 390
 391        for (table = hose->config_table; table && table->vendor; table++) {
 392                if ((table->vendor == PCI_ANY_ID || table->vendor == vendor) &&
 393                    (table->device == PCI_ANY_ID || table->device == device) &&
 394                    (table->class  == PCI_ANY_ID || table->class  == class)  &&
 395                    (table->bus    == PCI_ANY_ID || table->bus    == bus)    &&
 396                    (table->dev    == PCI_ANY_ID || table->dev    == dev)    &&
 397                    (table->func   == PCI_ANY_ID || table->func   == func)) {
 398                        return table;
 399                }
 400        }
 401
 402        return NULL;
 403}
 404
 405void pci_cfgfunc_config_device(struct pci_controller *hose,
 406                               pci_dev_t dev,
 407                               struct pci_config_table *entry)
 408{
 409        pci_hose_config_device(hose, dev, entry->priv[0], entry->priv[1], entry->priv[2]);
 410}
 411
 412void pci_cfgfunc_do_nothing(struct pci_controller *hose,
 413                            pci_dev_t dev, struct pci_config_table *entry)
 414{
 415}
 416
 417/*
 418 *
 419 */
 420
 421/* HJF: Changed this to return int. I think this is required
 422 * to get the correct result when scanning bridges
 423 */
 424extern int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev);
 425extern void pciauto_config_init(struct pci_controller *hose);
 426
 427int __pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
 428{
 429        /*
 430         * Check if pci device should be skipped in configuration
 431         */
 432        if (dev == PCI_BDF(hose->first_busno, 0, 0)) {
 433#if defined(CONFIG_PCI_CONFIG_HOST_BRIDGE) /* don't skip host bridge */
 434                /*
 435                 * Only skip configuration if "pciconfighost" is not set
 436                 */
 437                if (getenv("pciconfighost") == NULL)
 438                        return 1;
 439#else
 440                return 1;
 441#endif
 442        }
 443
 444        return 0;
 445}
 446int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
 447        __attribute__((weak, alias("__pci_skip_dev")));
 448
 449#ifdef CONFIG_PCI_SCAN_SHOW
 450int __pci_print_dev(struct pci_controller *hose, pci_dev_t dev)
 451{
 452        if (dev == PCI_BDF(hose->first_busno, 0, 0))
 453                return 0;
 454
 455        return 1;
 456}
 457int pci_print_dev(struct pci_controller *hose, pci_dev_t dev)
 458        __attribute__((weak, alias("__pci_print_dev")));
 459#endif /* CONFIG_PCI_SCAN_SHOW */
 460
 461int pci_hose_scan_bus(struct pci_controller *hose, int bus)
 462{
 463        unsigned int sub_bus, found_multi=0;
 464        unsigned short vendor, device, class;
 465        unsigned char header_type;
 466        struct pci_config_table *cfg;
 467        pci_dev_t dev;
 468
 469        sub_bus = bus;
 470
 471        for (dev =  PCI_BDF(bus,0,0);
 472             dev <  PCI_BDF(bus,PCI_MAX_PCI_DEVICES-1,PCI_MAX_PCI_FUNCTIONS-1);
 473             dev += PCI_BDF(0,0,1)) {
 474
 475                if (pci_skip_dev(hose, dev))
 476                        continue;
 477
 478                if (PCI_FUNC(dev) && !found_multi)
 479                        continue;
 480
 481                pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type);
 482
 483                pci_hose_read_config_word(hose, dev, PCI_VENDOR_ID, &vendor);
 484
 485                if (vendor != 0xffff && vendor != 0x0000) {
 486
 487                        if (!PCI_FUNC(dev))
 488                                found_multi = header_type & 0x80;
 489
 490                        debug ("PCI Scan: Found Bus %d, Device %d, Function %d\n",
 491                                PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev) );
 492
 493                        pci_hose_read_config_word(hose, dev, PCI_DEVICE_ID, &device);
 494                        pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);
 495
 496                        cfg = pci_find_config(hose, class, vendor, device,
 497                                              PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev));
 498                        if (cfg) {
 499                                cfg->config_device(hose, dev, cfg);
 500                                sub_bus = max(sub_bus, hose->current_busno);
 501#ifdef CONFIG_PCI_PNP
 502                        } else {
 503                                int n = pciauto_config_device(hose, dev);
 504
 505                                sub_bus = max(sub_bus, n);
 506#endif
 507                        }
 508                        if (hose->fixup_irq)
 509                                hose->fixup_irq(hose, dev);
 510
 511#ifdef CONFIG_PCI_SCAN_SHOW
 512                        if (pci_print_dev(hose, dev)) {
 513                                unsigned char int_line;
 514
 515                                pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_LINE,
 516                                                          &int_line);
 517                                printf("        %02x  %02x  %04x  %04x  %04x  %02x\n",
 518                                       PCI_BUS(dev), PCI_DEV(dev), vendor, device, class,
 519                                       int_line);
 520                        }
 521#endif
 522                }
 523        }
 524
 525        return sub_bus;
 526}
 527
 528int pci_hose_scan(struct pci_controller *hose)
 529{
 530        /* Start scan at current_busno.
 531         * PCIe will start scan at first_busno+1.
 532         */
 533        /* For legacy support, ensure current>=first */
 534        if (hose->first_busno > hose->current_busno)
 535                hose->current_busno = hose->first_busno;
 536#ifdef CONFIG_PCI_PNP
 537        pciauto_config_init(hose);
 538#endif
 539        return pci_hose_scan_bus(hose, hose->current_busno);
 540}
 541
 542void pci_init(void)
 543{
 544#if defined(CONFIG_PCI_BOOTDELAY)
 545        char *s;
 546        int i;
 547
 548        /* wait "pcidelay" ms (if defined)... */
 549        s = getenv ("pcidelay");
 550        if (s) {
 551                int val = simple_strtoul (s, NULL, 10);
 552                for (i=0; i<val; i++)
 553                        udelay (1000);
 554        }
 555#endif /* CONFIG_PCI_BOOTDELAY */
 556
 557        /* now call board specific pci_init()... */
 558        pci_init_board();
 559}
 560