linux/arch/mips/pci/ops-nile4.c
<<
>>
Prefs
   1#include <linux/kernel.h>
   2#include <linux/init.h>
   3#include <linux/pci.h>
   4#include <asm/bootinfo.h>
   5
   6#include <asm/lasat/lasat.h>
   7#include <asm/nile4.h>
   8
   9#define PCI_ACCESS_READ  0
  10#define PCI_ACCESS_WRITE 1
  11
  12#define LO(reg) (reg / 4)
  13#define HI(reg) (reg / 4 + 1)
  14
  15volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE;
  16
  17static DEFINE_SPINLOCK(nile4_pci_lock);
  18
  19static int nile4_pcibios_config_access(unsigned char access_type,
  20        struct pci_bus *bus, unsigned int devfn, int where, u32 *val)
  21{
  22        unsigned char busnum = bus->number;
  23        u32 adr, mask, err;
  24
  25        if ((busnum == 0) && (PCI_SLOT(devfn) > 8))
  26                /* The addressing scheme chosen leaves room for just
  27                 * 8 devices on the first busnum (besides the PCI
  28                 * controller itself) */
  29                return PCIBIOS_DEVICE_NOT_FOUND;
  30
  31        if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) {
  32                /* Access controller registers directly */
  33                if (access_type == PCI_ACCESS_WRITE) {
  34                        vrc_pciregs[(0x200 + where) >> 2] = *val;
  35                } else {
  36                        *val = vrc_pciregs[(0x200 + where) >> 2];
  37                }
  38                return PCIBIOS_SUCCESSFUL;
  39        }
  40
  41        /* Temporarily map PCI Window 1 to config space */
  42        mask = vrc_pciregs[LO(NILE4_PCIINIT1)];
  43        vrc_pciregs[LO(NILE4_PCIINIT1)] = 0x0000001a | (busnum ? 0x200 : 0);
  44
  45        /* Clear PCI Error register. This also clears the Error Type
  46         * bits in the Control register */
  47        vrc_pciregs[LO(NILE4_PCIERR)] = 0;
  48        vrc_pciregs[HI(NILE4_PCIERR)] = 0;
  49
  50        /* Setup address */
  51        if (busnum == 0)
  52                adr =
  53                    KSEG1ADDR(PCI_WINDOW1) +
  54                    ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8)
  55                     | (where & ~3));
  56        else
  57                adr = KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) |
  58                      (where & ~3);
  59
  60        if (access_type == PCI_ACCESS_WRITE)
  61                *(u32 *) adr = *val;
  62        else
  63                *val = *(u32 *) adr;
  64
  65        /* Check for master or target abort */
  66        err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7;
  67
  68        /* Restore PCI Window 1 */
  69        vrc_pciregs[LO(NILE4_PCIINIT1)] = mask;
  70
  71        if (err)
  72                return PCIBIOS_DEVICE_NOT_FOUND;
  73
  74        return PCIBIOS_SUCCESSFUL;
  75}
  76
  77static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn,
  78        int where, int size, u32 *val)
  79{
  80        unsigned long flags;
  81        u32 data = 0;
  82        int err;
  83
  84        if ((size == 2) && (where & 1))
  85                return PCIBIOS_BAD_REGISTER_NUMBER;
  86        else if ((size == 4) && (where & 3))
  87                return PCIBIOS_BAD_REGISTER_NUMBER;
  88
  89        spin_lock_irqsave(&nile4_pci_lock, flags);
  90        err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
  91                                        &data);
  92        spin_unlock_irqrestore(&nile4_pci_lock, flags);
  93
  94        if (err)
  95                return err;
  96
  97        if (size == 1)
  98                *val = (data >> ((where & 3) << 3)) & 0xff;
  99        else if (size == 2)
 100                *val = (data >> ((where & 3) << 3)) & 0xffff;
 101        else
 102                *val = data;
 103
 104        return PCIBIOS_SUCCESSFUL;
 105}
 106
 107static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn,
 108        int where, int size, u32 val)
 109{
 110        unsigned long flags;
 111        u32 data = 0;
 112        int err;
 113
 114        if ((size == 2) && (where & 1))
 115                return PCIBIOS_BAD_REGISTER_NUMBER;
 116        else if ((size == 4) && (where & 3))
 117                return PCIBIOS_BAD_REGISTER_NUMBER;
 118
 119        spin_lock_irqsave(&nile4_pci_lock, flags);
 120        err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
 121                                          &data);
 122        spin_unlock_irqrestore(&nile4_pci_lock, flags);
 123
 124        if (err)
 125                return err;
 126
 127        if (size == 1)
 128                data = (data & ~(0xff << ((where & 3) << 3))) |
 129                    (val << ((where & 3) << 3));
 130        else if (size == 2)
 131                data = (data & ~(0xffff << ((where & 3) << 3))) |
 132                    (val << ((where & 3) << 3));
 133        else
 134                data = val;
 135
 136        if (nile4_pcibios_config_access
 137            (PCI_ACCESS_WRITE, bus, devfn, where, &data))
 138                return -1;
 139
 140        return PCIBIOS_SUCCESSFUL;
 141}
 142
 143struct pci_ops nile4_pci_ops = {
 144        .read = nile4_pcibios_read,
 145        .write = nile4_pcibios_write,
 146};
 147