linux-old/arch/m68k/kernel/bios32.c
<<
>>
Prefs
   1/*
   2 * bios32.c - PCI BIOS functions for m68k systems.
   3 *
   4 * Written by Wout Klaren.
   5 *
   6 * Based on the DEC Alpha bios32.c by Dave Rusling and David Mosberger.
   7 */
   8
   9#include <linux/config.h>
  10#include <linux/init.h>
  11#include <linux/kernel.h>
  12
  13#if 0
  14# define DBG_DEVS(args)         printk args
  15#else
  16# define DBG_DEVS(args)
  17#endif
  18
  19#ifdef CONFIG_PCI
  20
  21/*
  22 * PCI support for Linux/m68k. Currently only the Hades is supported.
  23 *
  24 * The support for PCI bridges in the DEC Alpha version has
  25 * been removed in this version.
  26 */
  27
  28#include <linux/pci.h>
  29#include <linux/slab.h>
  30#include <linux/mm.h>
  31
  32#include <asm/io.h>
  33#include <asm/pci.h>
  34#include <asm/uaccess.h>
  35
  36#define KB              1024
  37#define MB              (1024*KB)
  38#define GB              (1024*MB)
  39
  40#define MAJOR_REV       0
  41#define MINOR_REV       5
  42
  43/*
  44 * Align VAL to ALIGN, which must be a power of two.
  45 */
  46
  47#define ALIGN(val,align)        (((val) + ((align) - 1)) & ~((align) - 1))
  48
  49#define MAX(val1, val2)         (((val1) > (val2)) ? val1 : val2)
  50
  51/*
  52 * Offsets relative to the I/O and memory base addresses from where resources
  53 * are allocated.
  54 */
  55
  56#define IO_ALLOC_OFFSET         0x00004000
  57#define MEM_ALLOC_OFFSET        0x04000000
  58
  59/*
  60 * Declarations of hardware specific initialisation functions.
  61 */
  62
  63extern struct pci_bus_info *init_hades_pci(void);
  64
  65/*
  66 * Bus info structure of the PCI bus. A pointer to this structure is
  67 * put in the sysdata member of the pci_bus structure.
  68 */
  69
  70static struct pci_bus_info *bus_info;
  71
  72static int pci_modify = 1;              /* If set, layout the PCI bus ourself. */
  73static int skip_vga = 0;                /* If set do not modify base addresses
  74                                           of vga cards.*/
  75static int disable_pci_burst = 0;       /* If set do not allow PCI bursts. */
  76
  77static unsigned int io_base;
  78static unsigned int mem_base;
  79
  80struct pci_fixup pcibios_fixups[] =
  81{
  82        { 0 }
  83};
  84
  85/*
  86 * static void disable_dev(struct pci_dev *dev)
  87 *
  88 * Disable PCI device DEV so that it does not respond to I/O or memory
  89 * accesses.
  90 *
  91 * Parameters:
  92 *
  93 * dev  - device to disable.
  94 */
  95
  96static void __init disable_dev(struct pci_dev *dev)
  97{
  98        struct pci_bus *bus;
  99        unsigned short cmd;
 100
 101        if (((dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA) ||
 102             (dev->class >> 8 == PCI_CLASS_DISPLAY_VGA) ||
 103             (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga)
 104                return;
 105
 106        bus = dev->bus;
 107        pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
 108
 109        cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER);
 110        pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND, cmd);
 111}
 112
 113/*
 114 * static void layout_dev(struct pci_dev *dev)
 115 *
 116 * Layout memory and I/O for a device.
 117 *
 118 * Parameters:
 119 *
 120 * device       - device to layout memory and I/O for.
 121 */
 122
 123static void __init layout_dev(struct pci_dev *dev)
 124{
 125        struct pci_bus *bus;
 126        unsigned short cmd;
 127        unsigned int base, mask, size, reg;
 128        unsigned int alignto;
 129        int i;
 130
 131        /*
 132         * Skip video cards if requested.
 133         */
 134
 135        if (((dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA) ||
 136             (dev->class >> 8 == PCI_CLASS_DISPLAY_VGA) ||
 137             (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga)
 138                return;
 139
 140        bus = dev->bus;
 141        pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
 142
 143        for (reg = PCI_BASE_ADDRESS_0, i = 0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++)
 144        {
 145                /*
 146                 * Figure out how much space and of what type this
 147                 * device wants.
 148                 */
 149
 150                pcibios_write_config_dword(bus->number, dev->devfn, reg,
 151                                           0xffffffff);
 152                pcibios_read_config_dword(bus->number, dev->devfn, reg, &base);
 153
 154                if (!base)
 155                {
 156                        /* this base-address register is unused */
 157                        dev->resource[i].start = 0;
 158                        dev->resource[i].end = 0;
 159                        dev->resource[i].flags = 0;
 160                        continue;
 161                }
 162
 163                /*
 164                 * We've read the base address register back after
 165                 * writing all ones and so now we must decode it.
 166                 */
 167
 168                if (base & PCI_BASE_ADDRESS_SPACE_IO)
 169                {
 170                        /*
 171                         * I/O space base address register.
 172                         */
 173
 174                        cmd |= PCI_COMMAND_IO;
 175
 176                        base &= PCI_BASE_ADDRESS_IO_MASK;
 177                        mask = (~base << 1) | 0x1;
 178                        size = (mask & base) & 0xffffffff;
 179
 180                        /*
 181                         * Align to multiple of size of minimum base.
 182                         */
 183
 184                        alignto = MAX(0x040, size) ;
 185                        base = ALIGN(io_base, alignto);
 186                        io_base = base + size;
 187                        pcibios_write_config_dword(bus->number, dev->devfn,
 188                                                   reg, base | PCI_BASE_ADDRESS_SPACE_IO);
 189
 190                        dev->resource[i].start = base;
 191                        dev->resource[i].end = dev->resource[i].start + size - 1;
 192                        dev->resource[i].flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;
 193
 194                        DBG_DEVS(("layout_dev: IO address: %lX\n", base));
 195                }
 196                else
 197                {
 198                        unsigned int type;
 199
 200                        /*
 201                         * Memory space base address register.
 202                         */
 203
 204                        cmd |= PCI_COMMAND_MEMORY;
 205                        type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
 206                        base &= PCI_BASE_ADDRESS_MEM_MASK;
 207                        mask = (~base << 1) | 0x1;
 208                        size = (mask & base) & 0xffffffff;
 209                        switch (type)
 210                        {
 211                        case PCI_BASE_ADDRESS_MEM_TYPE_32:
 212                        case PCI_BASE_ADDRESS_MEM_TYPE_64:
 213                                break;
 214
 215                        case PCI_BASE_ADDRESS_MEM_TYPE_1M:
 216                                printk("bios32 WARNING: slot %d, function %d "
 217                                       "requests memory below 1MB---don't "
 218                                       "know how to do that.\n",
 219                                       PCI_SLOT(dev->devfn),
 220                                       PCI_FUNC(dev->devfn));
 221                                continue;
 222                        }
 223
 224                        /*
 225                         * Align to multiple of size of minimum base.
 226                         */
 227
 228                        alignto = MAX(0x1000, size) ;
 229                        base = ALIGN(mem_base, alignto);
 230                        mem_base = base + size;
 231                        pcibios_write_config_dword(bus->number, dev->devfn,
 232                                                   reg, base);
 233
 234                        dev->resource[i].start = base;
 235                        dev->resource[i].end = dev->resource[i].start + size - 1;
 236                        dev->resource[i].flags = IORESOURCE_MEM;
 237
 238                        if (type == PCI_BASE_ADDRESS_MEM_TYPE_64)
 239                        {
 240                                /*
 241                                 * 64-bit address, set the highest 32 bits
 242                                 * to zero.
 243                                 */
 244
 245                                reg += 4;
 246                                pcibios_write_config_dword(bus->number, dev->devfn,
 247                                                           reg, 0);
 248
 249                                i++;
 250                                dev->resource[i].start = 0;
 251                                dev->resource[i].end = 0;
 252                                dev->resource[i].flags = 0;
 253                        }
 254                }
 255        }
 256
 257        /*
 258         * Enable device:
 259         */
 260
 261        if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED ||
 262            dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
 263            dev->class >> 8 == PCI_CLASS_DISPLAY_VGA ||
 264            dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)
 265        {
 266                /*
 267                 * All of these (may) have I/O scattered all around
 268                 * and may not use i/o-base address registers at all.
 269                 * So we just have to always enable I/O to these
 270                 * devices.
 271                 */
 272                cmd |= PCI_COMMAND_IO;
 273        }
 274
 275        pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND,
 276                                  cmd | PCI_COMMAND_MASTER);
 277
 278        pcibios_write_config_byte(bus->number, dev->devfn, PCI_LATENCY_TIMER,
 279                                  (disable_pci_burst) ? 0 : 32);
 280
 281        if (bus_info != NULL)
 282                bus_info->conf_device(bus->number, dev->devfn); /* Machine dependent configuration. */
 283
 284        DBG_DEVS(("layout_dev: bus %d  slot 0x%x  VID 0x%x  DID 0x%x  class 0x%x\n",
 285                  bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class));
 286}
 287
 288/*
 289 * static void layout_bus(struct pci_bus *bus)
 290 *
 291 * Layout memory and I/O for all devices on the given bus.
 292 *
 293 * Parameters:
 294 *
 295 * bus  - bus.
 296 */
 297
 298static void __init layout_bus(struct pci_bus *bus)
 299{
 300        unsigned int bio, bmem;
 301        struct pci_dev *dev;
 302
 303        DBG_DEVS(("layout_bus: starting bus %d\n", bus->number));
 304
 305        if (!bus->devices && !bus->children)
 306                return;
 307
 308        /*
 309         * Align the current bases on appropriate boundaries (4K for
 310         * IO and 1MB for memory).
 311         */
 312
 313        bio = io_base = ALIGN(io_base, 4*KB);
 314        bmem = mem_base = ALIGN(mem_base, 1*MB);
 315
 316        /*
 317         * PCI devices might have been setup by a PCI BIOS emulation
 318         * running under TOS. In these cases there is a
 319         * window during which two devices may have an overlapping
 320         * address range. To avoid this causing trouble, we first
 321         * turn off the I/O and memory address decoders for all PCI
 322         * devices.  They'll be re-enabled only once all address
 323         * decoders are programmed consistently.
 324         */
 325
 326        DBG_DEVS(("layout_bus: disable_dev for bus %d\n", bus->number));
 327
 328        for (dev = bus->devices; dev; dev = dev->sibling)
 329        {
 330                if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
 331                    (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA))
 332                        disable_dev(dev);
 333        }
 334
 335        /*
 336         * Allocate space to each device:
 337         */
 338
 339        DBG_DEVS(("layout_bus: starting bus %d devices\n", bus->number));
 340
 341        for (dev = bus->devices; dev; dev = dev->sibling)
 342        {
 343                if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
 344                    (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA))
 345                        layout_dev(dev);
 346        }
 347
 348        DBG_DEVS(("layout_bus: bus %d finished\n", bus->number));
 349}
 350
 351/*
 352 * static void pcibios_fixup(void)
 353 *
 354 * Layout memory and I/O of all devices on the PCI bus if 'pci_modify' is
 355 * true. This might be necessary because not every m68k machine with a PCI
 356 * bus has a PCI BIOS. This function should be called right after
 357 * pci_scan_bus() in pcibios_init().
 358 */
 359
 360static void __init pcibios_fixup(void)
 361{
 362        if (pci_modify)
 363        {
 364                /*
 365                 * Set base addresses for allocation of I/O and memory space.
 366                 */
 367
 368                io_base = bus_info->io_space.start + IO_ALLOC_OFFSET;
 369                mem_base = bus_info->mem_space.start + MEM_ALLOC_OFFSET;
 370
 371                /*
 372                 * Scan the tree, allocating PCI memory and I/O space.
 373                 */
 374
 375                layout_bus(pci_bus_b(pci_root.next));
 376        }
 377
 378        /*
 379         * Fix interrupt assignments, etc.
 380         */
 381
 382        bus_info->fixup(pci_modify);
 383}
 384
 385/*
 386 * static void pcibios_claim_resources(struct pci_bus *bus)
 387 *
 388 * Claim all resources that are assigned to devices on the given bus.
 389 *
 390 * Parameters:
 391 *
 392 * bus  - bus.
 393 */
 394
 395static void __init pcibios_claim_resources(struct pci_bus *bus)
 396{
 397        struct pci_dev *dev;
 398        int i;
 399
 400        while (bus)
 401        {
 402                for (dev = bus->devices; (dev != NULL); dev = dev->sibling)
 403                {
 404                        for (i = 0; i < PCI_NUM_RESOURCES; i++)
 405                        {
 406                                struct resource *r = &dev->resource[i];
 407                                struct resource *pr;
 408                                struct pci_bus_info *bus_info = (struct pci_bus_info *) dev->sysdata;
 409
 410                                if ((r->start == 0) || (r->parent != NULL))
 411                                        continue;
 412#if 1
 413                                if (r->flags & IORESOURCE_IO)
 414                                        pr = &bus_info->io_space;
 415                                else
 416                                        pr = &bus_info->mem_space;
 417#else
 418                                if (r->flags & IORESOURCE_IO)
 419                                        pr = &ioport_resource;
 420                                else
 421                                        pr = &iomem_resource;
 422#endif
 423                                if (request_resource(pr, r) < 0)
 424                                {
 425                                        printk(KERN_ERR "PCI: Address space collision on region %d of device %s\n", i, dev->name);
 426                                }
 427                        }
 428                }
 429
 430                if (bus->children)
 431                        pcibios_claim_resources(bus->children);
 432
 433                bus = bus->next;
 434        }
 435}
 436
 437/*
 438 * int pcibios_assign_resource(struct pci_dev *dev, int i)
 439 *
 440 * Assign a new address to a PCI resource.
 441 *
 442 * Parameters:
 443 *
 444 * dev  - device.
 445 * i    - resource.
 446 *
 447 * Result: 0 if successful.
 448 */
 449
 450int __init pcibios_assign_resource(struct pci_dev *dev, int i)
 451{
 452        struct resource *r = &dev->resource[i];
 453        struct resource *pr = pci_find_parent_resource(dev, r);
 454        unsigned long size = r->end + 1;
 455
 456        if (!pr)
 457                return -EINVAL;
 458
 459        if (r->flags & IORESOURCE_IO)
 460        {
 461                if (size > 0x100)
 462                        return -EFBIG;
 463
 464                if (allocate_resource(pr, r, size, bus_info->io_space.start +
 465                                      IO_ALLOC_OFFSET,  bus_info->io_space.end, 1024))
 466                        return -EBUSY;
 467        }
 468        else
 469        {
 470                if (allocate_resource(pr, r, size, bus_info->mem_space.start +
 471                                      MEM_ALLOC_OFFSET, bus_info->mem_space.end, size))
 472                        return -EBUSY;
 473        }
 474
 475        if (i < 6)
 476                pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, r->start);
 477
 478        return 0;
 479}
 480
 481void __init pcibios_fixup_bus(struct pci_bus *bus)
 482{
 483        struct pci_dev *dev;
 484        void *sysdata;
 485
 486        sysdata = (bus->parent) ? bus->parent->sysdata : bus->sysdata;
 487
 488        for (dev = bus->devices; (dev != NULL); dev = dev->sibling)
 489                dev->sysdata = sysdata;
 490}
 491
 492void __init pcibios_init(void)
 493{
 494        printk("Linux/m68k PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
 495
 496        bus_info = NULL;
 497#ifdef CONFIG_HADES
 498        if (MACH_IS_HADES)
 499                bus_info = init_hades_pci();
 500#endif
 501        if (bus_info != NULL)
 502        {
 503                printk("PCI: Probing PCI hardware\n");
 504                pci_scan_bus(0, bus_info->m68k_pci_ops, bus_info);
 505                pcibios_fixup();
 506                pcibios_claim_resources(pci_root);
 507        }
 508        else
 509                printk("PCI: No PCI bus detected\n");
 510}
 511
 512char * __init pcibios_setup(char *str)
 513{
 514        if (!strcmp(str, "nomodify"))
 515        {
 516                pci_modify = 0;
 517                return NULL;
 518        }
 519        else if (!strcmp(str, "skipvga"))
 520        {
 521                skip_vga = 1;
 522                return NULL;
 523        }
 524        else if (!strcmp(str, "noburst"))
 525        {
 526                disable_pci_burst = 1;
 527                return NULL;
 528        }
 529
 530        return str;
 531}
 532#endif /* CONFIG_PCI */
 533
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.