xref: /linux/arch/mips/pci/ops-sni.c (revision e5451c8f8330e03ad3cfa16048b4daf961af434f)
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   */
set_config_address(unsigned int busno,unsigned int devfn,int reg)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  
pcimt_read(struct pci_bus * bus,unsigned int devfn,int reg,int size,u32 * val)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  
pcimt_write(struct pci_bus * bus,unsigned int devfn,int reg,int size,u32 val)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  
pcit_set_config_address(unsigned int busno,unsigned int devfn,int reg)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  
pcit_read(struct pci_bus * bus,unsigned int devfn,int reg,int size,u32 * val)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  
pcit_write(struct pci_bus * bus,unsigned int devfn,int reg,int size,u32 val)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