Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * SNI specific PCI support for RM200/RM300.
0007  *
0008  * Copyright (C) 1997 - 2000, 2003 Ralf Baechle <ralf@linux-mips.org>
0009  */
0010 #include <linux/kernel.h>
0011 #include <linux/pci.h>
0012 #include <linux/types.h>
0013 #include <asm/sni.h>
0014 
0015 /*
0016  * It seems that on the RM200 only lower 3 bits of the 5 bit PCI device
0017  * address are decoded.  We therefore manually have to reject attempts at
0018  * reading outside this range.  Being on the paranoid side we only do this
0019  * test for bus 0 and hope forwarding and decoding work properly for any
0020  * subordinated busses.
0021  *
0022  * ASIC PCI only supports type 1 config cycles.
0023  */
0024 static int set_config_address(unsigned int busno, unsigned int devfn, int reg)
0025 {
0026     if ((devfn > 255) || (reg > 255))
0027         return PCIBIOS_BAD_REGISTER_NUMBER;
0028 
0029     if (busno == 0 && devfn >= PCI_DEVFN(8, 0))
0030         return PCIBIOS_DEVICE_NOT_FOUND;
0031 
0032     *(volatile u32 *)PCIMT_CONFIG_ADDRESS =
0033          ((busno    & 0xff) << 16) |
0034          ((devfn    & 0xff) <<  8) |
0035           (reg      & 0xfc);
0036 
0037     return PCIBIOS_SUCCESSFUL;
0038 }
0039 
0040 static int pcimt_read(struct pci_bus *bus, unsigned int devfn, int reg,
0041               int size, u32 * val)
0042 {
0043     int res;
0044 
0045     if ((res = set_config_address(bus->number, devfn, reg)))
0046         return res;
0047 
0048     switch (size) {
0049     case 1:
0050         *val = inb(PCIMT_CONFIG_DATA + (reg & 3));
0051         break;
0052     case 2:
0053         *val = inw(PCIMT_CONFIG_DATA + (reg & 2));
0054         break;
0055     case 4:
0056         *val = inl(PCIMT_CONFIG_DATA);
0057         break;
0058     }
0059 
0060     return 0;
0061 }
0062 
0063 static int pcimt_write(struct pci_bus *bus, unsigned int devfn, int reg,
0064                int size, u32 val)
0065 {
0066     int res;
0067 
0068     if ((res = set_config_address(bus->number, devfn, reg)))
0069         return res;
0070 
0071     switch (size) {
0072     case 1:
0073         outb(val, PCIMT_CONFIG_DATA + (reg & 3));
0074         break;
0075     case 2:
0076         outw(val, PCIMT_CONFIG_DATA + (reg & 2));
0077         break;
0078     case 4:
0079         outl(val, PCIMT_CONFIG_DATA);
0080         break;
0081     }
0082 
0083     return 0;
0084 }
0085 
0086 struct pci_ops sni_pcimt_ops = {
0087     .read = pcimt_read,
0088     .write = pcimt_write,
0089 };
0090 
0091 static int pcit_set_config_address(unsigned int busno, unsigned int devfn, int reg)
0092 {
0093     if ((devfn > 255) || (reg > 255) || (busno > 255))
0094         return PCIBIOS_BAD_REGISTER_NUMBER;
0095 
0096     outl((1 << 31) | ((busno & 0xff) << 16) | ((devfn & 0xff) << 8) | (reg & 0xfc), 0xcf8);
0097     return PCIBIOS_SUCCESSFUL;
0098 }
0099 
0100 static int pcit_read(struct pci_bus *bus, unsigned int devfn, int reg,
0101               int size, u32 * val)
0102 {
0103     int res;
0104 
0105     /*
0106      * on bus 0 we need to check, whether there is a device answering
0107      * for the devfn by doing a config write and checking the result. If
0108      * we don't do it, we will get a data bus error
0109      */
0110     if (bus->number == 0) {
0111         pcit_set_config_address(0, 0, 0x68);
0112         outl(inl(0xcfc) | 0xc0000000, 0xcfc);
0113         if ((res = pcit_set_config_address(0, devfn, 0)))
0114             return res;
0115         outl(0xffffffff, 0xcfc);
0116         pcit_set_config_address(0, 0, 0x68);
0117         if (inl(0xcfc) & 0x100000)
0118             return PCIBIOS_DEVICE_NOT_FOUND;
0119     }
0120     if ((res = pcit_set_config_address(bus->number, devfn, reg)))
0121         return res;
0122 
0123     switch (size) {
0124     case 1:
0125         *val = inb(PCIMT_CONFIG_DATA + (reg & 3));
0126         break;
0127     case 2:
0128         *val = inw(PCIMT_CONFIG_DATA + (reg & 2));
0129         break;
0130     case 4:
0131         *val = inl(PCIMT_CONFIG_DATA);
0132         break;
0133     }
0134     return 0;
0135 }
0136 
0137 static int pcit_write(struct pci_bus *bus, unsigned int devfn, int reg,
0138                int size, u32 val)
0139 {
0140     int res;
0141 
0142     if ((res = pcit_set_config_address(bus->number, devfn, reg)))
0143         return res;
0144 
0145     switch (size) {
0146     case 1:
0147         outb(val, PCIMT_CONFIG_DATA + (reg & 3));
0148         break;
0149     case 2:
0150         outw(val, PCIMT_CONFIG_DATA + (reg & 2));
0151         break;
0152     case 4:
0153         outl(val, PCIMT_CONFIG_DATA);
0154         break;
0155     }
0156 
0157     return 0;
0158 }
0159 
0160 
0161 struct pci_ops sni_pcit_ops = {
0162     .read = pcit_read,
0163     .write = pcit_write,
0164 };