linux/arch/mn10300/unit-asb2305/pci.c
<<
>>
Prefs
   1/* ASB2305 PCI support
   2 *
   3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 * Derived from arch/i386/kernel/pci-pc.c
   6 *      (c) 1999--2000 Martin Mares <mj@suse.cz>
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public Licence
  10 * as published by the Free Software Foundation; either version
  11 * 2 of the Licence, or (at your option) any later version.
  12 */
  13#include <linux/types.h>
  14#include <linux/kernel.h>
  15#include <linux/sched.h>
  16#include <linux/pci.h>
  17#include <linux/init.h>
  18#include <linux/ioport.h>
  19#include <linux/delay.h>
  20#include <asm/io.h>
  21#include "pci-asb2305.h"
  22
  23unsigned int pci_probe = 1;
  24
  25int pcibios_last_bus = -1;
  26struct pci_bus *pci_root_bus;
  27struct pci_ops *pci_root_ops;
  28
  29/*
  30 * The accessible PCI window does not cover the entire CPU address space, but
  31 * there are devices we want to access outside of that window, so we need to
  32 * insert specific PCI bus resources instead of using the platform-level bus
  33 * resources directly for the PCI root bus.
  34 *
  35 * These are configured and inserted by pcibios_init() and are attached to the
  36 * root bus by pcibios_fixup_bus().
  37 */
  38static struct resource pci_ioport_resource = {
  39        .name   = "PCI IO",
  40        .start  = 0xbe000000,
  41        .end    = 0xbe03ffff,
  42        .flags  = IORESOURCE_IO,
  43};
  44
  45static struct resource pci_iomem_resource = {
  46        .name   = "PCI mem",
  47        .start  = 0xb8000000,
  48        .end    = 0xbbffffff,
  49        .flags  = IORESOURCE_MEM,
  50};
  51
  52/*
  53 * Functions for accessing PCI configuration space
  54 */
  55
  56#define CONFIG_CMD(bus, devfn, where) \
  57        (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
  58
  59#define MEM_PAGING_REG  (*(volatile __u32 *) 0xBFFFFFF4)
  60#define CONFIG_ADDRESS  (*(volatile __u32 *) 0xBFFFFFF8)
  61#define CONFIG_DATAL(X) (*(volatile __u32 *) 0xBFFFFFFC)
  62#define CONFIG_DATAW(X) (*(volatile __u16 *) (0xBFFFFFFC + ((X) & 2)))
  63#define CONFIG_DATAB(X) (*(volatile __u8  *) (0xBFFFFFFC + ((X) & 3)))
  64
  65#define BRIDGEREGB(X)   (*(volatile __u8  *) (0xBE040000 + (X)))
  66#define BRIDGEREGW(X)   (*(volatile __u16 *) (0xBE040000 + (X)))
  67#define BRIDGEREGL(X)   (*(volatile __u32 *) (0xBE040000 + (X)))
  68
  69static inline int __query(const struct pci_bus *bus, unsigned int devfn)
  70{
  71#if 0
  72        return bus->number == 0 && (devfn == PCI_DEVFN(0, 0));
  73        return bus->number == 1;
  74        return bus->number == 0 &&
  75                (devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(3, 0));
  76#endif
  77        return 1;
  78}
  79
  80/*
  81 * translate Linuxcentric addresses to PCI bus addresses
  82 */
  83void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
  84                             struct resource *res)
  85{
  86        if (res->flags & IORESOURCE_IO) {
  87                region->start = (res->start & 0x00ffffff);
  88                region->end   = (res->end   & 0x00ffffff);
  89        }
  90
  91        if (res->flags & IORESOURCE_MEM) {
  92                region->start = (res->start & 0x03ffffff) | MEM_PAGING_REG;
  93                region->end   = (res->end   & 0x03ffffff) | MEM_PAGING_REG;
  94        }
  95
  96#if 0
  97        printk(KERN_DEBUG "RES->BUS: %lx-%lx => %lx-%lx\n",
  98               res->start, res->end, region->start, region->end);
  99#endif
 100}
 101EXPORT_SYMBOL(pcibios_resource_to_bus);
 102
 103/*
 104 * translate PCI bus addresses to Linuxcentric addresses
 105 */
 106void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 107                             struct pci_bus_region *region)
 108{
 109        if (res->flags & IORESOURCE_IO) {
 110                res->start = (region->start & 0x00ffffff) | 0xbe000000;
 111                res->end   = (region->end   & 0x00ffffff) | 0xbe000000;
 112        }
 113
 114        if (res->flags & IORESOURCE_MEM) {
 115                res->start = (region->start & 0x03ffffff) | 0xb8000000;
 116                res->end   = (region->end   & 0x03ffffff) | 0xb8000000;
 117        }
 118
 119#if 0
 120        printk(KERN_INFO "BUS->RES: %lx-%lx => %lx-%lx\n",
 121               region->start, region->end, res->start, res->end);
 122#endif
 123}
 124EXPORT_SYMBOL(pcibios_bus_to_resource);
 125
 126/*
 127 *
 128 */
 129static int pci_ampci_read_config_byte(struct pci_bus *bus, unsigned int devfn,
 130                                      int where, u32 *_value)
 131{
 132        u32 rawval, value;
 133
 134        if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
 135                value = BRIDGEREGB(where);
 136                __pcbdebug("=> %02hx", &BRIDGEREGL(where), value);
 137        } else {
 138                CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
 139                rawval = CONFIG_ADDRESS;
 140                value = CONFIG_DATAB(where);
 141                if (__query(bus, devfn))
 142                        __pcidebug("=> %02hx", bus, devfn, where, value);
 143        }
 144
 145        *_value = value;
 146        return PCIBIOS_SUCCESSFUL;
 147}
 148
 149static int pci_ampci_read_config_word(struct pci_bus *bus, unsigned int devfn,
 150                                      int where, u32 *_value)
 151{
 152        u32 rawval, value;
 153
 154        if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
 155                value = BRIDGEREGW(where);
 156                __pcbdebug("=> %04hx", &BRIDGEREGL(where), value);
 157        } else {
 158                CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
 159                rawval = CONFIG_ADDRESS;
 160                value = CONFIG_DATAW(where);
 161                if (__query(bus, devfn))
 162                        __pcidebug("=> %04hx", bus, devfn, where, value);
 163        }
 164
 165        *_value = value;
 166        return PCIBIOS_SUCCESSFUL;
 167}
 168
 169static int pci_ampci_read_config_dword(struct pci_bus *bus, unsigned int devfn,
 170                                       int where, u32 *_value)
 171{
 172        u32 rawval, value;
 173
 174        if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
 175                value = BRIDGEREGL(where);
 176                __pcbdebug("=> %08x", &BRIDGEREGL(where), value);
 177        } else {
 178                CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
 179                rawval = CONFIG_ADDRESS;
 180                value = CONFIG_DATAL(where);
 181                if (__query(bus, devfn))
 182                        __pcidebug("=> %08x", bus, devfn, where, value);
 183        }
 184
 185        *_value = value;
 186        return PCIBIOS_SUCCESSFUL;
 187}
 188
 189static int pci_ampci_write_config_byte(struct pci_bus *bus, unsigned int devfn,
 190                                       int where, u8 value)
 191{
 192        u32 rawval;
 193
 194        if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
 195                __pcbdebug("<= %02x", &BRIDGEREGB(where), value);
 196                BRIDGEREGB(where) = value;
 197        } else {
 198                if (bus->number == 0 &&
 199                    (devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(3, 0))
 200                    )
 201                        __pcidebug("<= %02x", bus, devfn, where, value);
 202                CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
 203                rawval = CONFIG_ADDRESS;
 204                CONFIG_DATAB(where) = value;
 205        }
 206        return PCIBIOS_SUCCESSFUL;
 207}
 208
 209static int pci_ampci_write_config_word(struct pci_bus *bus, unsigned int devfn,
 210                                       int where, u16 value)
 211{
 212        u32 rawval;
 213
 214        if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
 215                __pcbdebug("<= %04hx", &BRIDGEREGW(where), value);
 216                BRIDGEREGW(where) = value;
 217        } else {
 218                if (__query(bus, devfn))
 219                        __pcidebug("<= %04hx", bus, devfn, where, value);
 220                CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
 221                rawval = CONFIG_ADDRESS;
 222                CONFIG_DATAW(where) = value;
 223        }
 224        return PCIBIOS_SUCCESSFUL;
 225}
 226
 227static int pci_ampci_write_config_dword(struct pci_bus *bus, unsigned int devfn,
 228                                        int where, u32 value)
 229{
 230        u32 rawval;
 231
 232        if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
 233                __pcbdebug("<= %08x", &BRIDGEREGL(where), value);
 234                BRIDGEREGL(where) = value;
 235        } else {
 236                if (__query(bus, devfn))
 237                        __pcidebug("<= %08x", bus, devfn, where, value);
 238                CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
 239                rawval = CONFIG_ADDRESS;
 240                CONFIG_DATAL(where) = value;
 241        }
 242        return PCIBIOS_SUCCESSFUL;
 243}
 244
 245static int pci_ampci_read_config(struct pci_bus *bus, unsigned int devfn,
 246                                 int where, int size, u32 *val)
 247{
 248        switch (size) {
 249        case 1:
 250                return pci_ampci_read_config_byte(bus, devfn, where, val);
 251        case 2:
 252                return pci_ampci_read_config_word(bus, devfn, where, val);
 253        case 4:
 254                return pci_ampci_read_config_dword(bus, devfn, where, val);
 255        default:
 256                BUG();
 257                return -EOPNOTSUPP;
 258        }
 259}
 260
 261static int pci_ampci_write_config(struct pci_bus *bus, unsigned int devfn,
 262                                  int where, int size, u32 val)
 263{
 264        switch (size) {
 265        case 1:
 266                return pci_ampci_write_config_byte(bus, devfn, where, val);
 267        case 2:
 268                return pci_ampci_write_config_word(bus, devfn, where, val);
 269        case 4:
 270                return pci_ampci_write_config_dword(bus, devfn, where, val);
 271        default:
 272                BUG();
 273                return -EOPNOTSUPP;
 274        }
 275}
 276
 277static struct pci_ops pci_direct_ampci = {
 278        pci_ampci_read_config,
 279        pci_ampci_write_config,
 280};
 281
 282/*
 283 * Before we decide to use direct hardware access mechanisms, we try to do some
 284 * trivial checks to ensure it at least _seems_ to be working -- we just test
 285 * whether bus 00 contains a host bridge (this is similar to checking
 286 * techniques used in XFree86, but ours should be more reliable since we
 287 * attempt to make use of direct access hints provided by the PCI BIOS).
 288 *
 289 * This should be close to trivial, but it isn't, because there are buggy
 290 * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
 291 */
 292static int __init pci_sanity_check(struct pci_ops *o)
 293{
 294        struct pci_bus bus;             /* Fake bus and device */
 295        u32 x;
 296
 297        bus.number = 0;
 298
 299        if ((!o->read(&bus, 0, PCI_CLASS_DEVICE, 2, &x) &&
 300             (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) ||
 301            (!o->read(&bus, 0, PCI_VENDOR_ID, 2, &x) &&
 302             (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)))
 303                return 1;
 304
 305        printk(KERN_ERR "PCI: Sanity check failed\n");
 306        return 0;
 307}
 308
 309static int __init pci_check_direct(void)
 310{
 311        unsigned long flags;
 312
 313        local_irq_save(flags);
 314
 315        /*
 316         * Check if access works.
 317         */
 318        if (pci_sanity_check(&pci_direct_ampci)) {
 319                local_irq_restore(flags);
 320                printk(KERN_INFO "PCI: Using configuration ampci\n");
 321                request_mem_region(0xBE040000, 256, "AMPCI bridge");
 322                request_mem_region(0xBFFFFFF4, 12, "PCI ampci");
 323                request_mem_region(0xBC000000, 32 * 1024 * 1024, "PCI SRAM");
 324                return 0;
 325        }
 326
 327        local_irq_restore(flags);
 328        return -ENODEV;
 329}
 330
 331static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
 332{
 333        unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM;
 334        struct resource *devr = &dev->resource[idx], *busr;
 335
 336        if (dev->bus) {
 337                pci_bus_for_each_resource(dev->bus, busr, i) {
 338                        if (!busr || (busr->flags ^ devr->flags) & type_mask)
 339                                continue;
 340
 341                        if (devr->start &&
 342                            devr->start >= busr->start &&
 343                            devr->end <= busr->end)
 344                                return 1;
 345                }
 346        }
 347
 348        return 0;
 349}
 350
 351static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
 352{
 353        struct pci_bus_region region;
 354        int i;
 355        int limit;
 356
 357        if (dev->bus->number != 0)
 358                return;
 359
 360        limit = (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) ?
 361                PCI_BRIDGE_RESOURCES : PCI_NUM_RESOURCES;
 362
 363        for (i = 0; i < limit; i++) {
 364                if (!dev->resource[i].flags)
 365                        continue;
 366
 367                region.start = dev->resource[i].start;
 368                region.end = dev->resource[i].end;
 369                pcibios_bus_to_resource(dev, &dev->resource[i], &region);
 370                if (is_valid_resource(dev, i))
 371                        pci_claim_resource(dev, i);
 372        }
 373}
 374
 375/*
 376 *  Called after each bus is probed, but before its children
 377 *  are examined.
 378 */
 379void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 380{
 381        struct pci_dev *dev;
 382
 383        if (bus->number == 0) {
 384                bus->resource[0] = &pci_ioport_resource;
 385                bus->resource[1] = &pci_iomem_resource;
 386        }
 387
 388        if (bus->self) {
 389                pci_read_bridge_bases(bus);
 390                pcibios_fixup_device_resources(bus->self);
 391        }
 392
 393        list_for_each_entry(dev, &bus->devices, bus_list)
 394                pcibios_fixup_device_resources(dev);
 395}
 396
 397/*
 398 * Initialization. Try all known PCI access methods. Note that we support
 399 * using both PCI BIOS and direct access: in such cases, we use I/O ports
 400 * to access config space, but we still keep BIOS order of cards to be
 401 * compatible with 2.0.X. This should go away some day.
 402 */
 403static int __init pcibios_init(void)
 404{
 405        ioport_resource.start   = 0xA0000000;
 406        ioport_resource.end     = 0xDFFFFFFF;
 407        iomem_resource.start    = 0xA0000000;
 408        iomem_resource.end      = 0xDFFFFFFF;
 409
 410        if (insert_resource(&iomem_resource, &pci_iomem_resource) < 0)
 411                panic("Unable to insert PCI IOMEM resource\n");
 412        if (insert_resource(&ioport_resource, &pci_ioport_resource) < 0)
 413                panic("Unable to insert PCI IOPORT resource\n");
 414
 415        if (!pci_probe)
 416                return 0;
 417
 418        if (pci_check_direct() < 0) {
 419                printk(KERN_WARNING "PCI: No PCI bus detected\n");
 420                return 0;
 421        }
 422
 423        printk(KERN_INFO "PCI: Probing PCI hardware [mempage %08x]\n",
 424               MEM_PAGING_REG);
 425
 426        pci_root_bus = pci_scan_bus(0, &pci_direct_ampci, NULL);
 427
 428        pcibios_irq_init();
 429        pcibios_fixup_irqs();
 430        pcibios_resource_survey();
 431        return 0;
 432}
 433
 434arch_initcall(pcibios_init);
 435
 436char *__init pcibios_setup(char *str)
 437{
 438        if (!strcmp(str, "off")) {
 439                pci_probe = 0;
 440                return NULL;
 441
 442        } else if (!strncmp(str, "lastbus=", 8)) {
 443                pcibios_last_bus = simple_strtol(str+8, NULL, 0);
 444                return NULL;
 445        }
 446
 447        return str;
 448}
 449
 450int pcibios_enable_device(struct pci_dev *dev, int mask)
 451{
 452        int err;
 453
 454        err = pci_enable_resources(dev, mask);
 455        if (err == 0)
 456                pcibios_enable_irq(dev);
 457        return err;
 458}
 459
 460/*
 461 * disable the ethernet chipset
 462 */
 463static void __init unit_disable_pcnet(struct pci_bus *bus, struct pci_ops *o)
 464{
 465        u32 x;
 466
 467        bus->number = 0;
 468
 469        o->read (bus, PCI_DEVFN(2, 0), PCI_VENDOR_ID,           4, &x);
 470        o->read (bus, PCI_DEVFN(2, 0), PCI_COMMAND,             2, &x);
 471        x |= PCI_COMMAND_MASTER |
 472                PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
 473                PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
 474        o->write(bus, PCI_DEVFN(2, 0), PCI_COMMAND,             2, x);
 475        o->read (bus, PCI_DEVFN(2, 0), PCI_COMMAND,             2, &x);
 476        o->write(bus, PCI_DEVFN(2, 0), PCI_BASE_ADDRESS_0,      4, 0x00030001);
 477        o->read (bus, PCI_DEVFN(2, 0), PCI_BASE_ADDRESS_0,      4, &x);
 478
 479#define RDP (*(volatile u32 *) 0xBE030010)
 480#define RAP (*(volatile u32 *) 0xBE030014)
 481#define __set_RAP(X) do { RAP = (X); x = RAP; } while (0)
 482#define __set_RDP(X) do { RDP = (X); x = RDP; } while (0)
 483#define __get_RDP() ({ RDP & 0xffff; })
 484
 485        __set_RAP(0);
 486        __set_RDP(0x0004);      /* CSR0 = STOP */
 487
 488        __set_RAP(88);          /* check CSR88 indicates an Am79C973 */
 489        BUG_ON(__get_RDP() != 0x5003);
 490
 491        for (x = 0; x < 100; x++)
 492                asm volatile("nop");
 493
 494        __set_RDP(0x0004);      /* CSR0 = STOP */
 495}
 496
 497/*
 498 * initialise the unit hardware
 499 */
 500asmlinkage void __init unit_pci_init(void)
 501{
 502        struct pci_bus bus;             /* Fake bus and device */
 503        struct pci_ops *o = &pci_direct_ampci;
 504        u32 x;
 505
 506        set_intr_level(XIRQ1, NUM2GxICR_LEVEL(CONFIG_PCI_IRQ_LEVEL));
 507
 508        memset(&bus, 0, sizeof(bus));
 509
 510        MEM_PAGING_REG = 0xE8000000;
 511
 512        /* we need to set up the bridge _now_ or we won't be able to access the
 513         * PCI config registers
 514         */
 515        BRIDGEREGW(PCI_COMMAND) |=
 516                PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
 517                PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_MASTER;
 518        BRIDGEREGW(PCI_STATUS)          = 0xF800;
 519        BRIDGEREGB(PCI_LATENCY_TIMER)   = 0x10;
 520        BRIDGEREGL(PCI_BASE_ADDRESS_0)  = 0x80000000;
 521        BRIDGEREGB(PCI_INTERRUPT_LINE)  = 1;
 522        BRIDGEREGL(0x48)                = 0x98000000;   /* AMPCI base addr */
 523        BRIDGEREGB(0x41)                = 0x00;         /* secondary bus
 524                                                         * number */
 525        BRIDGEREGB(0x42)                = 0x01;         /* subordinate bus
 526                                                         * number */
 527        BRIDGEREGB(0x44)                = 0x01;
 528        BRIDGEREGL(0x50)                = 0x00000001;
 529        BRIDGEREGL(0x58)                = 0x00001002;
 530        BRIDGEREGL(0x5C)                = 0x00000011;
 531
 532        /* we also need to set up the PCI-PCI bridge */
 533        bus.number = 0;
 534
 535        /* IO: 0x00000000-0x00020000 */
 536        o->read (&bus, PCI_DEVFN(3, 0), PCI_COMMAND,            2, &x);
 537        x |= PCI_COMMAND_MASTER |
 538                PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
 539                PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
 540        o->write(&bus, PCI_DEVFN(3, 0), PCI_COMMAND,            2, x);
 541
 542        o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE,            1, &x);
 543        o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16,    4, &x);
 544        o->read (&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE,        4, &x);
 545        o->read (&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE,   4, &x);
 546
 547        o->write(&bus, PCI_DEVFN(3, 0), PCI_IO_BASE,            1, 0x01);
 548        o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE,            1, &x);
 549        o->write(&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16,    4, 0x00020000);
 550        o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16,    4, &x);
 551        o->write(&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE,        4, 0xEBB0EA00);
 552        o->read (&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE,        4, &x);
 553        o->write(&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE,   4, 0xE9F0E800);
 554        o->read (&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE,   4, &x);
 555
 556        unit_disable_pcnet(&bus, o);
 557}
 558