~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/pci/ops-sni.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * This file is subject to the terms and conditions of the GNU General Public
  3  * License.  See the file "COPYING" in the main directory of this archive
  4  * for more details.
  5  *
  6  * SNI specific PCI support for RM200/RM300.
  7  *
  8  * Copyright (C) 1997 - 2000, 2003 Ralf Baechle <ralf@linux-mips.org>
  9  */
 10 #include <linux/kernel.h>
 11 #include <linux/pci.h>
 12 #include <linux/types.h>
 13 #include <asm/sni.h>
 14 
 15 /*
 16  * It seems that on the RM200 only lower 3 bits of the 5 bit PCI device
 17  * address are decoded.  We therefore manually have to reject attempts at
 18  * reading outside this range.  Being on the paranoid side we only do this
 19  * test for bus 0 and hope forwarding and decoding work properly for any
 20  * subordinated busses.
 21  *
 22  * ASIC PCI only supports type 1 config cycles.
 23  */
 24 static int set_config_address(unsigned int busno, unsigned int devfn, int reg)
 25 {
 26         if ((devfn > 255) || (reg > 255))
 27                 return PCIBIOS_BAD_REGISTER_NUMBER;
 28 
 29         if (busno == 0 && devfn >= PCI_DEVFN(8, 0))
 30                 return PCIBIOS_DEVICE_NOT_FOUND;
 31 
 32         *(volatile u32 *)PCIMT_CONFIG_ADDRESS =
 33                  ((busno    & 0xff) << 16) |
 34                  ((devfn    & 0xff) <<  8) |
 35                   (reg      & 0xfc);
 36 
 37         return PCIBIOS_SUCCESSFUL;
 38 }
 39 
 40 static int pcimt_read(struct pci_bus *bus, unsigned int devfn, int reg,
 41                       int size, u32 * val)
 42 {
 43         int res;
 44 
 45         if ((res = set_config_address(bus->number, devfn, reg)))
 46                 return res;
 47 
 48         switch (size) {
 49         case 1:
 50                 *val = inb(PCIMT_CONFIG_DATA + (reg & 3));
 51                 break;
 52         case 2:
 53                 *val = inw(PCIMT_CONFIG_DATA + (reg & 2));
 54                 break;
 55         case 4:
 56                 *val = inl(PCIMT_CONFIG_DATA);
 57                 break;
 58         }
 59 
 60         return 0;
 61 }
 62 
 63 static int pcimt_write(struct pci_bus *bus, unsigned int devfn, int reg,
 64                        int size, u32 val)
 65 {
 66         int res;
 67 
 68         if ((res = set_config_address(bus->number, devfn, reg)))
 69                 return res;
 70 
 71         switch (size) {
 72         case 1:
 73                 outb(val, PCIMT_CONFIG_DATA + (reg & 3));
 74                 break;
 75         case 2:
 76                 outw(val, PCIMT_CONFIG_DATA + (reg & 2));
 77                 break;
 78         case 4:
 79                 outl(val, PCIMT_CONFIG_DATA);
 80                 break;
 81         }
 82 
 83         return 0;
 84 }
 85 
 86 struct pci_ops sni_pcimt_ops = {
 87         .read = pcimt_read,
 88         .write = pcimt_write,
 89 };
 90 
 91 static int pcit_set_config_address(unsigned int busno, unsigned int devfn, int reg)
 92 {
 93         if ((devfn > 255) || (reg > 255) || (busno > 255))
 94                 return PCIBIOS_BAD_REGISTER_NUMBER;
 95 
 96         outl((1 << 31) | ((busno & 0xff) << 16) | ((devfn & 0xff) << 8) | (reg & 0xfc), 0xcf8);
 97         return PCIBIOS_SUCCESSFUL;
 98 }
 99 
100 static int pcit_read(struct pci_bus *bus, unsigned int devfn, int reg,
101                       int size, u32 * val)
102 {
103         int res;
104 
105         /*
106          * on bus 0 we need to check, whether there is a device answering
107          * for the devfn by doing a config write and checking the result. If
108          * we don't do it, we will get a data bus error
109          */
110         if (bus->number == 0) {
111                 pcit_set_config_address(0, 0, 0x68);
112                 outl(inl(0xcfc) | 0xc0000000, 0xcfc);
113                 if ((res = pcit_set_config_address(0, devfn, 0)))
114                         return res;
115                 outl(0xffffffff, 0xcfc);
116                 pcit_set_config_address(0, 0, 0x68);
117                 if (inl(0xcfc) & 0x100000)
118                         return PCIBIOS_DEVICE_NOT_FOUND;
119         }
120         if ((res = pcit_set_config_address(bus->number, devfn, reg)))
121                 return res;
122 
123         switch (size) {
124         case 1:
125                 *val = inb(PCIMT_CONFIG_DATA + (reg & 3));
126                 break;
127         case 2:
128                 *val = inw(PCIMT_CONFIG_DATA + (reg & 2));
129                 break;
130         case 4:
131                 *val = inl(PCIMT_CONFIG_DATA);
132                 break;
133         }
134         return 0;
135 }
136 
137 static int pcit_write(struct pci_bus *bus, unsigned int devfn, int reg,
138                        int size, u32 val)
139 {
140         int res;
141 
142         if ((res = pcit_set_config_address(bus->number, devfn, reg)))
143                 return res;
144 
145         switch (size) {
146         case 1:
147                 outb(val, PCIMT_CONFIG_DATA + (reg & 3));
148                 break;
149         case 2:
150                 outw(val, PCIMT_CONFIG_DATA + (reg & 2));
151                 break;
152         case 4:
153                 outl(val, PCIMT_CONFIG_DATA);
154                 break;
155         }
156 
157         return 0;
158 }
159 
160 
161 struct pci_ops sni_pcit_ops = {
162         .read = pcit_read,
163         .write = pcit_write,
164 };
165 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php