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