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