uboot/drivers/pci/pci_common.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2014 Google, Inc
   3 *
   4 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   5 * Andreas Heppel <aheppel@sysgo.de>
   6 *
   7 * (C) Copyright 2002, 2003
   8 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   9 *
  10 * SPDX-License-Identifier:     GPL-2.0+
  11 */
  12
  13#include <common.h>
  14#include <dm.h>
  15#include <errno.h>
  16#include <pci.h>
  17#include <asm/io.h>
  18
  19const char *pci_class_str(u8 class)
  20{
  21        switch (class) {
  22        case PCI_CLASS_NOT_DEFINED:
  23                return "Build before PCI Rev2.0";
  24                break;
  25        case PCI_BASE_CLASS_STORAGE:
  26                return "Mass storage controller";
  27                break;
  28        case PCI_BASE_CLASS_NETWORK:
  29                return "Network controller";
  30                break;
  31        case PCI_BASE_CLASS_DISPLAY:
  32                return "Display controller";
  33                break;
  34        case PCI_BASE_CLASS_MULTIMEDIA:
  35                return "Multimedia device";
  36                break;
  37        case PCI_BASE_CLASS_MEMORY:
  38                return "Memory controller";
  39                break;
  40        case PCI_BASE_CLASS_BRIDGE:
  41                return "Bridge device";
  42                break;
  43        case PCI_BASE_CLASS_COMMUNICATION:
  44                return "Simple comm. controller";
  45                break;
  46        case PCI_BASE_CLASS_SYSTEM:
  47                return "Base system peripheral";
  48                break;
  49        case PCI_BASE_CLASS_INPUT:
  50                return "Input device";
  51                break;
  52        case PCI_BASE_CLASS_DOCKING:
  53                return "Docking station";
  54                break;
  55        case PCI_BASE_CLASS_PROCESSOR:
  56                return "Processor";
  57                break;
  58        case PCI_BASE_CLASS_SERIAL:
  59                return "Serial bus controller";
  60                break;
  61        case PCI_BASE_CLASS_INTELLIGENT:
  62                return "Intelligent controller";
  63                break;
  64        case PCI_BASE_CLASS_SATELLITE:
  65                return "Satellite controller";
  66                break;
  67        case PCI_BASE_CLASS_CRYPT:
  68                return "Cryptographic device";
  69                break;
  70        case PCI_BASE_CLASS_SIGNAL_PROCESSING:
  71                return "DSP";
  72                break;
  73        case PCI_CLASS_OTHERS:
  74                return "Does not fit any class";
  75                break;
  76        default:
  77        return  "???";
  78                break;
  79        };
  80}
  81
  82__weak int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
  83{
  84        /*
  85         * Check if pci device should be skipped in configuration
  86         */
  87        if (dev == PCI_BDF(hose->first_busno, 0, 0)) {
  88#if defined(CONFIG_PCI_CONFIG_HOST_BRIDGE) /* don't skip host bridge */
  89                /*
  90                 * Only skip configuration if "pciconfighost" is not set
  91                 */
  92                if (getenv("pciconfighost") == NULL)
  93                        return 1;
  94#else
  95                return 1;
  96#endif
  97        }
  98
  99        return 0;
 100}
 101
 102#if !defined(CONFIG_DM_PCI) || defined(CONFIG_DM_PCI_COMPAT)
 103/* Get a virtual address associated with a BAR region */
 104void *pci_map_bar(pci_dev_t pdev, int bar, int flags)
 105{
 106        pci_addr_t pci_bus_addr;
 107        u32 bar_response;
 108
 109        /* read BAR address */
 110        pci_read_config_dword(pdev, bar, &bar_response);
 111        pci_bus_addr = (pci_addr_t)(bar_response & ~0xf);
 112
 113        /*
 114         * Pass "0" as the length argument to pci_bus_to_virt.  The arg
 115         * isn't actualy used on any platform because u-boot assumes a static
 116         * linear mapping.  In the future, this could read the BAR size
 117         * and pass that as the size if needed.
 118         */
 119        return pci_bus_to_virt(pdev, pci_bus_addr, flags, 0, MAP_NOCACHE);
 120}
 121
 122void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
 123                     u32 addr_and_ctrl)
 124{
 125        int bar;
 126
 127        bar = PCI_BASE_ADDRESS_0 + barnum * 4;
 128        pci_hose_write_config_dword(hose, dev, bar, addr_and_ctrl);
 129}
 130
 131u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum)
 132{
 133        u32 addr;
 134        int bar;
 135
 136        bar = PCI_BASE_ADDRESS_0 + barnum * 4;
 137        pci_hose_read_config_dword(hose, dev, bar, &addr);
 138        if (addr & PCI_BASE_ADDRESS_SPACE_IO)
 139                return addr & PCI_BASE_ADDRESS_IO_MASK;
 140        else
 141                return addr & PCI_BASE_ADDRESS_MEM_MASK;
 142}
 143
 144int __pci_hose_bus_to_phys(struct pci_controller *hose,
 145                           pci_addr_t bus_addr,
 146                           unsigned long flags,
 147                           unsigned long skip_mask,
 148                           phys_addr_t *pa)
 149{
 150        struct pci_region *res;
 151        int i;
 152
 153        for (i = 0; i < hose->region_count; i++) {
 154                res = &hose->regions[i];
 155
 156                if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
 157                        continue;
 158
 159                if (res->flags & skip_mask)
 160                        continue;
 161
 162                if (bus_addr >= res->bus_start &&
 163                    (bus_addr - res->bus_start) < res->size) {
 164                        *pa = (bus_addr - res->bus_start + res->phys_start);
 165                        return 0;
 166                }
 167        }
 168
 169        return 1;
 170}
 171
 172phys_addr_t pci_hose_bus_to_phys(struct pci_controller *hose,
 173                                 pci_addr_t bus_addr,
 174                                 unsigned long flags)
 175{
 176        phys_addr_t phys_addr = 0;
 177        int ret;
 178
 179        if (!hose) {
 180                puts("pci_hose_bus_to_phys: invalid hose\n");
 181                return phys_addr;
 182        }
 183
 184#ifdef CONFIG_DM_PCI
 185        /* The root controller has the region information */
 186        hose = pci_bus_to_hose(0);
 187#endif
 188
 189        /*
 190         * if PCI_REGION_MEM is set we do a two pass search with preference
 191         * on matches that don't have PCI_REGION_SYS_MEMORY set
 192         */
 193        if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
 194                ret = __pci_hose_bus_to_phys(hose, bus_addr,
 195                                flags, PCI_REGION_SYS_MEMORY, &phys_addr);
 196                if (!ret)
 197                        return phys_addr;
 198        }
 199
 200        ret = __pci_hose_bus_to_phys(hose, bus_addr, flags, 0, &phys_addr);
 201
 202        if (ret)
 203                puts("pci_hose_bus_to_phys: invalid physical address\n");
 204
 205        return phys_addr;
 206}
 207
 208int __pci_hose_phys_to_bus(struct pci_controller *hose,
 209                           phys_addr_t phys_addr,
 210                           unsigned long flags,
 211                           unsigned long skip_mask,
 212                           pci_addr_t *ba)
 213{
 214        struct pci_region *res;
 215        pci_addr_t bus_addr;
 216        int i;
 217
 218        for (i = 0; i < hose->region_count; i++) {
 219                res = &hose->regions[i];
 220
 221                if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
 222                        continue;
 223
 224                if (res->flags & skip_mask)
 225                        continue;
 226
 227                bus_addr = phys_addr - res->phys_start + res->bus_start;
 228
 229                if (bus_addr >= res->bus_start &&
 230                    (bus_addr - res->bus_start) < res->size) {
 231                        *ba = bus_addr;
 232                        return 0;
 233                }
 234        }
 235
 236        return 1;
 237}
 238
 239pci_addr_t pci_hose_phys_to_bus(struct pci_controller *hose,
 240                                phys_addr_t phys_addr,
 241                                unsigned long flags)
 242{
 243        pci_addr_t bus_addr = 0;
 244        int ret;
 245
 246        if (!hose) {
 247                puts("pci_hose_phys_to_bus: invalid hose\n");
 248                return bus_addr;
 249        }
 250
 251#ifdef CONFIG_DM_PCI
 252        /* The root controller has the region information */
 253        hose = pci_bus_to_hose(0);
 254#endif
 255
 256        /*
 257         * if PCI_REGION_MEM is set we do a two pass search with preference
 258         * on matches that don't have PCI_REGION_SYS_MEMORY set
 259         */
 260        if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
 261                ret = __pci_hose_phys_to_bus(hose, phys_addr,
 262                                flags, PCI_REGION_SYS_MEMORY, &bus_addr);
 263                if (!ret)
 264                        return bus_addr;
 265        }
 266
 267        ret = __pci_hose_phys_to_bus(hose, phys_addr, flags, 0, &bus_addr);
 268
 269        if (ret)
 270                puts("pci_hose_phys_to_bus: invalid physical address\n");
 271
 272        return bus_addr;
 273}
 274
 275pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
 276{
 277        struct pci_device_id ids[2] = { {}, {0, 0} };
 278
 279        ids[0].vendor = vendor;
 280        ids[0].device = device;
 281
 282        return pci_find_devices(ids, index);
 283}
 284
 285pci_dev_t pci_hose_find_devices(struct pci_controller *hose, int busnum,
 286                                struct pci_device_id *ids, int *indexp)
 287{
 288        int found_multi = 0;
 289        u16 vendor, device;
 290        u8 header_type;
 291        pci_dev_t bdf;
 292        int i;
 293
 294        for (bdf = PCI_BDF(busnum, 0, 0);
 295             bdf < PCI_BDF(busnum + 1, 0, 0);
 296             bdf += PCI_BDF(0, 0, 1)) {
 297                if (pci_skip_dev(hose, bdf))
 298                        continue;
 299
 300                if (!PCI_FUNC(bdf)) {
 301                        pci_read_config_byte(bdf, PCI_HEADER_TYPE,
 302                                             &header_type);
 303                        found_multi = header_type & 0x80;
 304                } else {
 305                        if (!found_multi)
 306                                continue;
 307                }
 308
 309                pci_read_config_word(bdf, PCI_VENDOR_ID, &vendor);
 310                pci_read_config_word(bdf, PCI_DEVICE_ID, &device);
 311
 312                for (i = 0; ids[i].vendor != 0; i++) {
 313                        if (vendor == ids[i].vendor &&
 314                            device == ids[i].device) {
 315                                if ((*indexp) <= 0)
 316                                        return bdf;
 317
 318                                (*indexp)--;
 319                        }
 320                }
 321        }
 322
 323        return -1;
 324}
 325
 326pci_dev_t pci_find_class(uint find_class, int index)
 327{
 328        int bus;
 329        int devnum;
 330        pci_dev_t bdf;
 331        uint32_t class;
 332
 333        for (bus = 0; bus <= pci_last_busno(); bus++) {
 334                for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES - 1; devnum++) {
 335                        pci_read_config_dword(PCI_BDF(bus, devnum, 0),
 336                                              PCI_CLASS_REVISION, &class);
 337                        if (class >> 16 == 0xffff)
 338                                continue;
 339
 340                        for (bdf = PCI_BDF(bus, devnum, 0);
 341                                        bdf <= PCI_BDF(bus, devnum,
 342                                                PCI_MAX_PCI_FUNCTIONS - 1);
 343                                        bdf += PCI_BDF(0, 0, 1)) {
 344                                pci_read_config_dword(bdf, PCI_CLASS_REVISION,
 345                                                      &class);
 346                                class >>= 8;
 347
 348                                if (class != find_class)
 349                                        continue;
 350                                /*
 351                                 * Decrement the index. We want to return the
 352                                 * correct device, so index is 0 for the first
 353                                 * matching device, 1 for the second, etc.
 354                                 */
 355                                if (index) {
 356                                        index--;
 357                                        continue;
 358                                }
 359                                /* Return index'th controller. */
 360                                return bdf;
 361                        }
 362                }
 363        }
 364
 365        return -ENODEV;
 366}
 367#endif /* !CONFIG_DM_PCI || CONFIG_DM_PCI_COMPAT */
 368