uboot/drivers/pci/pci_auto_old.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * PCI autoconfiguration library (legacy version, do not change)
   4 *
   5 * Author: Matt Porter <mporter@mvista.com>
   6 *
   7 * Copyright 2000 MontaVista Software Inc.
   8 */
   9
  10#include <common.h>
  11#include <errno.h>
  12#include <pci.h>
  13
  14/*
  15 * Do not change this file. Instead, convert your board to use CONFIG_DM_PCI
  16 * and change pci_auto.c.
  17 */
  18
  19/* the user can define CONFIG_SYS_PCI_CACHE_LINE_SIZE to avoid problems */
  20#ifndef CONFIG_SYS_PCI_CACHE_LINE_SIZE
  21#define CONFIG_SYS_PCI_CACHE_LINE_SIZE  8
  22#endif
  23
  24/*
  25 *
  26 */
  27
  28void pciauto_setup_device(struct pci_controller *hose,
  29                          pci_dev_t dev, int bars_num,
  30                          struct pci_region *mem,
  31                          struct pci_region *prefetch,
  32                          struct pci_region *io)
  33{
  34        u32 bar_response;
  35        pci_size_t bar_size;
  36        u16 cmdstat = 0;
  37        int bar, bar_nr = 0;
  38#ifndef CONFIG_PCI_ENUM_ONLY
  39        u8 header_type;
  40        int rom_addr;
  41        pci_addr_t bar_value;
  42        struct pci_region *bar_res;
  43        int found_mem64 = 0;
  44#endif
  45        u16 class;
  46
  47        pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
  48        cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | PCI_COMMAND_MASTER;
  49
  50        for (bar = PCI_BASE_ADDRESS_0;
  51                bar < PCI_BASE_ADDRESS_0 + (bars_num * 4); bar += 4) {
  52                /* Tickle the BAR and get the response */
  53#ifndef CONFIG_PCI_ENUM_ONLY
  54                pci_hose_write_config_dword(hose, dev, bar, 0xffffffff);
  55#endif
  56                pci_hose_read_config_dword(hose, dev, bar, &bar_response);
  57
  58                /* If BAR is not implemented go to the next BAR */
  59                if (!bar_response)
  60                        continue;
  61
  62#ifndef CONFIG_PCI_ENUM_ONLY
  63                found_mem64 = 0;
  64#endif
  65
  66                /* Check the BAR type and set our address mask */
  67                if (bar_response & PCI_BASE_ADDRESS_SPACE) {
  68                        bar_size = ((~(bar_response & PCI_BASE_ADDRESS_IO_MASK))
  69                                   & 0xffff) + 1;
  70#ifndef CONFIG_PCI_ENUM_ONLY
  71                        bar_res = io;
  72#endif
  73
  74                        debug("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ",
  75                              bar_nr, (unsigned long long)bar_size);
  76                } else {
  77                        if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
  78                             PCI_BASE_ADDRESS_MEM_TYPE_64) {
  79                                u32 bar_response_upper;
  80                                u64 bar64;
  81
  82#ifndef CONFIG_PCI_ENUM_ONLY
  83                                pci_hose_write_config_dword(hose, dev, bar + 4,
  84                                        0xffffffff);
  85#endif
  86                                pci_hose_read_config_dword(hose, dev, bar + 4,
  87                                        &bar_response_upper);
  88
  89                                bar64 = ((u64)bar_response_upper << 32) | bar_response;
  90
  91                                bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1;
  92#ifndef CONFIG_PCI_ENUM_ONLY
  93                                found_mem64 = 1;
  94#endif
  95                        } else {
  96                                bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1);
  97                        }
  98#ifndef CONFIG_PCI_ENUM_ONLY
  99                        if (prefetch && (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH))
 100                                bar_res = prefetch;
 101                        else
 102                                bar_res = mem;
 103
 104                        debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ",
 105                              bar_nr, bar_res == prefetch ? "Prf" : "Mem",
 106                              (unsigned long long)bar_size);
 107#endif
 108                }
 109
 110#ifndef CONFIG_PCI_ENUM_ONLY
 111                if (pciauto_region_allocate(bar_res, bar_size,
 112                                            &bar_value, found_mem64) == 0) {
 113                        /* Write it out and update our limit */
 114                        pci_hose_write_config_dword(hose, dev, bar, (u32)bar_value);
 115
 116                        if (found_mem64) {
 117                                bar += 4;
 118#ifdef CONFIG_SYS_PCI_64BIT
 119                                pci_hose_write_config_dword(hose, dev, bar, (u32)(bar_value>>32));
 120#else
 121                                /*
 122                                 * If we are a 64-bit decoder then increment to the
 123                                 * upper 32 bits of the bar and force it to locate
 124                                 * in the lower 4GB of memory.
 125                                 */
 126                                pci_hose_write_config_dword(hose, dev, bar, 0x00000000);
 127#endif
 128                        }
 129
 130                }
 131#endif
 132                cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ?
 133                        PCI_COMMAND_IO : PCI_COMMAND_MEMORY;
 134
 135                debug("\n");
 136
 137                bar_nr++;
 138        }
 139
 140#ifndef CONFIG_PCI_ENUM_ONLY
 141        /* Configure the expansion ROM address */
 142        pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type);
 143        header_type &= 0x7f;
 144        if (header_type != PCI_HEADER_TYPE_CARDBUS) {
 145                rom_addr = (header_type == PCI_HEADER_TYPE_NORMAL) ?
 146                           PCI_ROM_ADDRESS : PCI_ROM_ADDRESS1;
 147                pci_hose_write_config_dword(hose, dev, rom_addr, 0xfffffffe);
 148                pci_hose_read_config_dword(hose, dev, rom_addr, &bar_response);
 149                if (bar_response) {
 150                        bar_size = -(bar_response & ~1);
 151                        debug("PCI Autoconfig: ROM, size=%#x, ",
 152                              (unsigned int)bar_size);
 153                        if (pciauto_region_allocate(mem, bar_size,
 154                                                    &bar_value, false) == 0) {
 155                                pci_hose_write_config_dword(hose, dev, rom_addr,
 156                                                            bar_value);
 157                        }
 158                        cmdstat |= PCI_COMMAND_MEMORY;
 159                        debug("\n");
 160                }
 161        }
 162#endif
 163
 164        /* PCI_COMMAND_IO must be set for VGA device */
 165        pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);
 166        if (class == PCI_CLASS_DISPLAY_VGA)
 167                cmdstat |= PCI_COMMAND_IO;
 168
 169        pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat);
 170        pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE,
 171                CONFIG_SYS_PCI_CACHE_LINE_SIZE);
 172        pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
 173}
 174
 175void pciauto_prescan_setup_bridge(struct pci_controller *hose,
 176                                         pci_dev_t dev, int sub_bus)
 177{
 178        struct pci_region *pci_mem;
 179        struct pci_region *pci_prefetch;
 180        struct pci_region *pci_io;
 181        u16 cmdstat, prefechable_64;
 182
 183        pci_mem = hose->pci_mem;
 184        pci_prefetch = hose->pci_prefetch;
 185        pci_io = hose->pci_io;
 186
 187        pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
 188        pci_hose_read_config_word(hose, dev, PCI_PREF_MEMORY_BASE,
 189                                &prefechable_64);
 190        prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK;
 191
 192        /* Configure bus number registers */
 193        pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS,
 194                                   PCI_BUS(dev) - hose->first_busno);
 195        pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS,
 196                                   sub_bus - hose->first_busno);
 197        pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, 0xff);
 198
 199        if (pci_mem) {
 200                /* Round memory allocator to 1MB boundary */
 201                pciauto_region_align(pci_mem, 0x100000);
 202
 203                /* Set up memory and I/O filter limits, assume 32-bit I/O space */
 204                pci_hose_write_config_word(hose, dev, PCI_MEMORY_BASE,
 205                                        (pci_mem->bus_lower & 0xfff00000) >> 16);
 206
 207                cmdstat |= PCI_COMMAND_MEMORY;
 208        }
 209
 210        if (pci_prefetch) {
 211                /* Round memory allocator to 1MB boundary */
 212                pciauto_region_align(pci_prefetch, 0x100000);
 213
 214                /* Set up memory and I/O filter limits, assume 32-bit I/O space */
 215                pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE,
 216                                        (pci_prefetch->bus_lower & 0xfff00000) >> 16);
 217                if (prefechable_64 == PCI_PREF_RANGE_TYPE_64)
 218#ifdef CONFIG_SYS_PCI_64BIT
 219                        pci_hose_write_config_dword(hose, dev,
 220                                        PCI_PREF_BASE_UPPER32,
 221                                        pci_prefetch->bus_lower >> 32);
 222#else
 223                        pci_hose_write_config_dword(hose, dev,
 224                                        PCI_PREF_BASE_UPPER32,
 225                                        0x0);
 226#endif
 227
 228                cmdstat |= PCI_COMMAND_MEMORY;
 229        } else {
 230                /* We don't support prefetchable memory for now, so disable */
 231                pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000);
 232                pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x0);
 233                if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) {
 234                        pci_hose_write_config_word(hose, dev, PCI_PREF_BASE_UPPER32, 0x0);
 235                        pci_hose_write_config_word(hose, dev, PCI_PREF_LIMIT_UPPER32, 0x0);
 236                }
 237        }
 238
 239        if (pci_io) {
 240                /* Round I/O allocator to 4KB boundary */
 241                pciauto_region_align(pci_io, 0x1000);
 242
 243                pci_hose_write_config_byte(hose, dev, PCI_IO_BASE,
 244                                        (pci_io->bus_lower & 0x0000f000) >> 8);
 245                pci_hose_write_config_word(hose, dev, PCI_IO_BASE_UPPER16,
 246                                        (pci_io->bus_lower & 0xffff0000) >> 16);
 247
 248                cmdstat |= PCI_COMMAND_IO;
 249        }
 250
 251        /* Enable memory and I/O accesses, enable bus master */
 252        pci_hose_write_config_word(hose, dev, PCI_COMMAND,
 253                                        cmdstat | PCI_COMMAND_MASTER);
 254}
 255
 256void pciauto_postscan_setup_bridge(struct pci_controller *hose,
 257                                          pci_dev_t dev, int sub_bus)
 258{
 259        struct pci_region *pci_mem;
 260        struct pci_region *pci_prefetch;
 261        struct pci_region *pci_io;
 262
 263        pci_mem = hose->pci_mem;
 264        pci_prefetch = hose->pci_prefetch;
 265        pci_io = hose->pci_io;
 266
 267        /* Configure bus number registers */
 268        pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS,
 269                                   sub_bus - hose->first_busno);
 270
 271        if (pci_mem) {
 272                /* Round memory allocator to 1MB boundary */
 273                pciauto_region_align(pci_mem, 0x100000);
 274
 275                pci_hose_write_config_word(hose, dev, PCI_MEMORY_LIMIT,
 276                                (pci_mem->bus_lower - 1) >> 16);
 277        }
 278
 279        if (pci_prefetch) {
 280                u16 prefechable_64;
 281
 282                pci_hose_read_config_word(hose, dev,
 283                                        PCI_PREF_MEMORY_LIMIT,
 284                                        &prefechable_64);
 285                prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK;
 286
 287                /* Round memory allocator to 1MB boundary */
 288                pciauto_region_align(pci_prefetch, 0x100000);
 289
 290                pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT,
 291                                (pci_prefetch->bus_lower - 1) >> 16);
 292                if (prefechable_64 == PCI_PREF_RANGE_TYPE_64)
 293#ifdef CONFIG_SYS_PCI_64BIT
 294                        pci_hose_write_config_dword(hose, dev,
 295                                        PCI_PREF_LIMIT_UPPER32,
 296                                        (pci_prefetch->bus_lower - 1) >> 32);
 297#else
 298                        pci_hose_write_config_dword(hose, dev,
 299                                        PCI_PREF_LIMIT_UPPER32,
 300                                        0x0);
 301#endif
 302        }
 303
 304        if (pci_io) {
 305                /* Round I/O allocator to 4KB boundary */
 306                pciauto_region_align(pci_io, 0x1000);
 307
 308                pci_hose_write_config_byte(hose, dev, PCI_IO_LIMIT,
 309                                ((pci_io->bus_lower - 1) & 0x0000f000) >> 8);
 310                pci_hose_write_config_word(hose, dev, PCI_IO_LIMIT_UPPER16,
 311                                ((pci_io->bus_lower - 1) & 0xffff0000) >> 16);
 312        }
 313}
 314
 315
 316/*
 317 * HJF: Changed this to return int. I think this is required
 318 * to get the correct result when scanning bridges
 319 */
 320int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev)
 321{
 322        struct pci_region *pci_mem;
 323        struct pci_region *pci_prefetch;
 324        struct pci_region *pci_io;
 325        unsigned int sub_bus = PCI_BUS(dev);
 326        unsigned short class;
 327        int n;
 328
 329        pci_mem = hose->pci_mem;
 330        pci_prefetch = hose->pci_prefetch;
 331        pci_io = hose->pci_io;
 332
 333        pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);
 334
 335        switch (class) {
 336        case PCI_CLASS_BRIDGE_PCI:
 337                debug("PCI Autoconfig: Found P2P bridge, device %d\n",
 338                      PCI_DEV(dev));
 339
 340                pciauto_setup_device(hose, dev, 2, pci_mem,
 341                                     pci_prefetch, pci_io);
 342
 343                /* Passing in current_busno allows for sibling P2P bridges */
 344                hose->current_busno++;
 345                pciauto_prescan_setup_bridge(hose, dev, hose->current_busno);
 346                /*
 347                 * need to figure out if this is a subordinate bridge on the bus
 348                 * to be able to properly set the pri/sec/sub bridge registers.
 349                 */
 350                n = pci_hose_scan_bus(hose, hose->current_busno);
 351
 352                /* figure out the deepest we've gone for this leg */
 353                sub_bus = max((unsigned int)n, sub_bus);
 354                pciauto_postscan_setup_bridge(hose, dev, sub_bus);
 355
 356                sub_bus = hose->current_busno;
 357                break;
 358
 359        case PCI_CLASS_BRIDGE_CARDBUS:
 360                /*
 361                 * just do a minimal setup of the bridge,
 362                 * let the OS take care of the rest
 363                 */
 364                pciauto_setup_device(hose, dev, 0, pci_mem,
 365                                     pci_prefetch, pci_io);
 366
 367                debug("PCI Autoconfig: Found P2CardBus bridge, device %d\n",
 368                      PCI_DEV(dev));
 369
 370                hose->current_busno++;
 371                break;
 372
 373#if defined(CONFIG_PCIAUTO_SKIP_HOST_BRIDGE)
 374        case PCI_CLASS_BRIDGE_OTHER:
 375                debug("PCI Autoconfig: Skipping bridge device %d\n",
 376                      PCI_DEV(dev));
 377                break;
 378#endif
 379#if defined(CONFIG_ARCH_MPC834X) && !defined(CONFIG_TARGET_VME8349) && \
 380                !defined(CONFIG_TARGET_CADDY2)
 381        case PCI_CLASS_BRIDGE_OTHER:
 382                /*
 383                 * The host/PCI bridge 1 seems broken in 8349 - it presents
 384                 * itself as 'PCI_CLASS_BRIDGE_OTHER' and appears as an _agent_
 385                 * device claiming resources io/mem/irq.. we only allow for
 386                 * the PIMMR window to be allocated (BAR0 - 1MB size)
 387                 */
 388                debug("PCI Autoconfig: Broken bridge found, only minimal config\n");
 389                pciauto_setup_device(hose, dev, 0, hose->pci_mem,
 390                        hose->pci_prefetch, hose->pci_io);
 391                break;
 392#endif
 393
 394        case PCI_CLASS_PROCESSOR_POWERPC: /* an agent or end-point */
 395                debug("PCI AutoConfig: Found PowerPC device\n");
 396
 397        default:
 398                pciauto_setup_device(hose, dev, 6, pci_mem,
 399                                     pci_prefetch, pci_io);
 400                break;
 401        }
 402
 403        return sub_bus;
 404}
 405