linux/arch/xtensa/lib/pci-auto.c
<<
>>
Prefs
   1/*
   2 * arch/xtensa/lib/pci-auto.c
   3 *
   4 * PCI autoconfiguration library
   5 *
   6 * Copyright (C) 2001 - 2005 Tensilica Inc.
   7 *
   8 * Chris Zankel <zankel@tensilica.com, cez@zankel.net>
   9 *
  10 * Based on work from Matt Porter <mporter@mvista.com>
  11 *
  12 * This program is free software; you can redistribute  it and/or modify it
  13 * under  the terms of  the GNU General  Public License as published by the
  14 * Free Software Foundation;  either version 2 of the  License, or (at your
  15 * option) any later version.
  16 */
  17
  18#include <linux/kernel.h>
  19#include <linux/init.h>
  20#include <linux/pci.h>
  21
  22#include <asm/pci-bridge.h>
  23
  24
  25/*
  26 *
  27 * Setting up a PCI
  28 *
  29 * pci_ctrl->first_busno = <first bus number (0)>
  30 * pci_ctrl->last_busno = <last bus number (0xff)>
  31 * pci_ctrl->ops = <PCI config operations>
  32 * pci_ctrl->map_irq = <function to return the interrupt number for a device>
  33 *
  34 * pci_ctrl->io_space.start = <IO space start address (PCI view)>
  35 * pci_ctrl->io_space.end = <IO space end address (PCI view)>
  36 * pci_ctrl->io_space.base = <IO space offset: address 0 from CPU space>
  37 * pci_ctrl->mem_space.start = <MEM space start address (PCI view)>
  38 * pci_ctrl->mem_space.end = <MEM space end address (PCI view)>
  39 * pci_ctrl->mem_space.base = <MEM space offset: address 0 from CPU space>
  40 *
  41 * pcibios_init_resource(&pci_ctrl->io_resource, <IO space start>,
  42 *                       <IO space end>, IORESOURCE_IO, "PCI host bridge");
  43 * pcibios_init_resource(&pci_ctrl->mem_resources[0], <MEM space start>,
  44 *                       <MEM space end>, IORESOURCE_MEM, "PCI host bridge");
  45 *
  46 * pci_ctrl->last_busno = pciauto_bus_scan(pci_ctrl,pci_ctrl->first_busno);
  47 *
  48 * int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus)
  49 *
  50 */
  51
  52
  53/* define DEBUG to print some debugging messages. */
  54
  55#undef DEBUG
  56
  57#ifdef DEBUG
  58# define DBG(x...) printk(x)
  59#else
  60# define DBG(x...)
  61#endif
  62
  63static int pciauto_upper_iospc;
  64static int pciauto_upper_memspc;
  65
  66static struct pci_dev pciauto_dev;
  67static struct pci_bus pciauto_bus;
  68
  69/*
  70 * Helper functions
  71 */
  72
  73/* Initialize the bars of a PCI device.  */
  74
  75static void __init
  76pciauto_setup_bars(struct pci_dev *dev, int bar_limit)
  77{
  78        int bar_size;
  79        int bar, bar_nr;
  80        int *upper_limit;
  81        int found_mem64 = 0;
  82
  83        for (bar = PCI_BASE_ADDRESS_0, bar_nr = 0;
  84             bar <= bar_limit;
  85             bar+=4, bar_nr++)
  86        {
  87                /* Tickle the BAR and get the size */
  88                pci_write_config_dword(dev, bar, 0xffffffff);
  89                pci_read_config_dword(dev, bar, &bar_size);
  90
  91                /* If BAR is not implemented go to the next BAR */
  92                if (!bar_size)
  93                        continue;
  94
  95                /* Check the BAR type and set our address mask */
  96                if (bar_size & PCI_BASE_ADDRESS_SPACE_IO)
  97                {
  98                        bar_size &= PCI_BASE_ADDRESS_IO_MASK;
  99                        upper_limit = &pciauto_upper_iospc;
 100                        DBG("PCI Autoconfig: BAR %d, I/O, ", bar_nr);
 101                }
 102                else
 103                {
 104                        if ((bar_size & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
 105                            PCI_BASE_ADDRESS_MEM_TYPE_64)
 106                                found_mem64 = 1;
 107
 108                        bar_size &= PCI_BASE_ADDRESS_MEM_MASK;
 109                        upper_limit = &pciauto_upper_memspc;
 110                        DBG("PCI Autoconfig: BAR %d, Mem, ", bar_nr);
 111                }
 112
 113                /* Allocate a base address (bar_size is negative!) */
 114                *upper_limit = (*upper_limit + bar_size) & bar_size;
 115
 116                /* Write it out and update our limit */
 117                pci_write_config_dword(dev, bar, *upper_limit);
 118
 119                /*
 120                 * If we are a 64-bit decoder then increment to the
 121                 * upper 32 bits of the bar and force it to locate
 122                 * in the lower 4GB of memory.
 123                 */
 124
 125                if (found_mem64)
 126                        pci_write_config_dword(dev, (bar+=4), 0x00000000);
 127
 128                DBG("size=0x%x, address=0x%x\n", ~bar_size + 1, *upper_limit);
 129        }
 130}
 131
 132/* Initialize the interrupt number. */
 133
 134static void __init
 135pciauto_setup_irq(struct pci_controller* pci_ctrl,struct pci_dev *dev,int devfn)
 136{
 137        u8 pin;
 138        int irq = 0;
 139
 140        pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 141
 142        /* Fix illegal pin numbers. */
 143
 144        if (pin == 0 || pin > 4)
 145                pin = 1;
 146
 147        if (pci_ctrl->map_irq)
 148                irq = pci_ctrl->map_irq(dev, PCI_SLOT(devfn), pin);
 149
 150        if (irq == -1)
 151                irq = 0;
 152
 153        DBG("PCI Autoconfig: Interrupt %d, pin %d\n", irq, pin);
 154
 155        pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 156}
 157
 158
 159static void __init
 160pciauto_prescan_setup_bridge(struct pci_dev *dev, int current_bus,
 161                             int sub_bus, int *iosave, int *memsave)
 162{
 163        /* Configure bus number registers */
 164        pci_write_config_byte(dev, PCI_PRIMARY_BUS, current_bus);
 165        pci_write_config_byte(dev, PCI_SECONDARY_BUS, sub_bus + 1);
 166        pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, 0xff);
 167
 168        /* Round memory allocator to 1MB boundary */
 169        pciauto_upper_memspc &= ~(0x100000 - 1);
 170        *memsave = pciauto_upper_memspc;
 171
 172        /* Round I/O allocator to 4KB boundary */
 173        pciauto_upper_iospc &= ~(0x1000 - 1);
 174        *iosave = pciauto_upper_iospc;
 175
 176        /* Set up memory and I/O filter limits, assume 32-bit I/O space */
 177        pci_write_config_word(dev, PCI_MEMORY_LIMIT,
 178                              ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
 179        pci_write_config_byte(dev, PCI_IO_LIMIT,
 180                              ((pciauto_upper_iospc - 1) & 0x0000f000) >> 8);
 181        pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
 182                              ((pciauto_upper_iospc - 1) & 0xffff0000) >> 16);
 183}
 184
 185static void __init
 186pciauto_postscan_setup_bridge(struct pci_dev *dev, int current_bus, int sub_bus,
 187                              int *iosave, int *memsave)
 188{
 189        int cmdstat;
 190
 191        /* Configure bus number registers */
 192        pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, sub_bus);
 193
 194        /*
 195         * Round memory allocator to 1MB boundary.
 196         * If no space used, allocate minimum.
 197         */
 198        pciauto_upper_memspc &= ~(0x100000 - 1);
 199        if (*memsave == pciauto_upper_memspc)
 200                pciauto_upper_memspc -= 0x00100000;
 201
 202        pci_write_config_word(dev, PCI_MEMORY_BASE, pciauto_upper_memspc >> 16);
 203
 204        /* Allocate 1MB for pre-fretch */
 205        pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT,
 206                              ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
 207
 208        pciauto_upper_memspc -= 0x100000;
 209
 210        pci_write_config_word(dev, PCI_PREF_MEMORY_BASE,
 211                              pciauto_upper_memspc >> 16);
 212
 213        /* Round I/O allocator to 4KB boundary */
 214        pciauto_upper_iospc &= ~(0x1000 - 1);
 215        if (*iosave == pciauto_upper_iospc)
 216                pciauto_upper_iospc -= 0x1000;
 217
 218        pci_write_config_byte(dev, PCI_IO_BASE,
 219                              (pciauto_upper_iospc & 0x0000f000) >> 8);
 220        pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
 221                              pciauto_upper_iospc >> 16);
 222
 223        /* Enable memory and I/O accesses, enable bus master */
 224        pci_read_config_dword(dev, PCI_COMMAND, &cmdstat);
 225        pci_write_config_dword(dev, PCI_COMMAND,
 226                               cmdstat |
 227                               PCI_COMMAND_IO |
 228                               PCI_COMMAND_MEMORY |
 229                               PCI_COMMAND_MASTER);
 230}
 231
 232/*
 233 * Scan the current PCI bus.
 234 */
 235
 236
 237int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus)
 238{
 239        int sub_bus, pci_devfn, pci_class, cmdstat, found_multi=0;
 240        unsigned short vid;
 241        unsigned char header_type;
 242        struct pci_dev *dev = &pciauto_dev;
 243
 244        pciauto_dev.bus = &pciauto_bus;
 245        pciauto_dev.sysdata = pci_ctrl;
 246        pciauto_bus.ops = pci_ctrl->ops;
 247
 248        /*
 249         * Fetch our I/O and memory space upper boundaries used
 250         * to allocated base addresses on this pci_controller.
 251         */
 252
 253        if (current_bus == pci_ctrl->first_busno)
 254        {
 255                pciauto_upper_iospc = pci_ctrl->io_resource.end + 1;
 256                pciauto_upper_memspc = pci_ctrl->mem_resources[0].end + 1;
 257        }
 258
 259        sub_bus = current_bus;
 260
 261        for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++)
 262        {
 263                /* Skip our host bridge */
 264                if ((current_bus == pci_ctrl->first_busno) && (pci_devfn == 0))
 265                        continue;
 266
 267                if (PCI_FUNC(pci_devfn) && !found_multi)
 268                        continue;
 269
 270                pciauto_bus.number = current_bus;
 271                pciauto_dev.devfn = pci_devfn;
 272
 273                /* If config space read fails from this device, move on */
 274                if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type))
 275                        continue;
 276
 277                if (!PCI_FUNC(pci_devfn))
 278                        found_multi = header_type & 0x80;
 279                pci_read_config_word(dev, PCI_VENDOR_ID, &vid);
 280
 281                if (vid == 0xffff || vid == 0x0000) {
 282                        found_multi = 0;
 283                        continue;
 284                }
 285
 286                pci_read_config_dword(dev, PCI_CLASS_REVISION, &pci_class);
 287
 288                if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
 289
 290                        int iosave, memsave;
 291
 292                        DBG("PCI Autoconfig: Found P2P bridge, device %d\n",
 293                            PCI_SLOT(pci_devfn));
 294
 295                        /* Allocate PCI I/O and/or memory space */
 296                        pciauto_setup_bars(dev, PCI_BASE_ADDRESS_1);
 297
 298                        pciauto_prescan_setup_bridge(dev, current_bus, sub_bus,
 299                                        &iosave, &memsave);
 300                        sub_bus = pciauto_bus_scan(pci_ctrl, sub_bus+1);
 301                        pciauto_postscan_setup_bridge(dev, current_bus, sub_bus,
 302                                        &iosave, &memsave);
 303                        pciauto_bus.number = current_bus;
 304
 305                        continue;
 306
 307                }
 308
 309
 310#if 0
 311                /* Skip legacy mode IDE controller */
 312
 313                if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
 314
 315                        unsigned char prg_iface;
 316                        pci_read_config_byte(dev, PCI_CLASS_PROG, &prg_iface);
 317
 318                        if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
 319                                DBG("PCI Autoconfig: Skipping legacy mode "
 320                                    "IDE controller\n");
 321                                continue;
 322                        }
 323                }
 324#endif
 325
 326                /*
 327                 * Found a peripheral, enable some standard
 328                 * settings
 329                 */
 330
 331                pci_read_config_dword(dev, PCI_COMMAND, &cmdstat);
 332                pci_write_config_dword(dev, PCI_COMMAND,
 333                                cmdstat |
 334                                        PCI_COMMAND_IO |
 335                                        PCI_COMMAND_MEMORY |
 336                                        PCI_COMMAND_MASTER);
 337                pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
 338
 339                /* Allocate PCI I/O and/or memory space */
 340                DBG("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n",
 341                    current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn) );
 342
 343                pciauto_setup_bars(dev, PCI_BASE_ADDRESS_5);
 344                pciauto_setup_irq(pci_ctrl, dev, pci_devfn);
 345        }
 346        return sub_bus;
 347}
 348