diff options
Diffstat (limited to 'arch/ppc/boot/simple/pci.c')
-rw-r--r-- | arch/ppc/boot/simple/pci.c | 274 |
1 files changed, 0 insertions, 274 deletions
diff --git a/arch/ppc/boot/simple/pci.c b/arch/ppc/boot/simple/pci.c deleted file mode 100644 index b0f673c8b7d9..000000000000 --- a/arch/ppc/boot/simple/pci.c +++ /dev/null | |||
@@ -1,274 +0,0 @@ | |||
1 | /* Stand alone funtions for QSpan Tundra support. | ||
2 | */ | ||
3 | #include <linux/types.h> | ||
4 | #include <linux/pci.h> | ||
5 | #include <asm/mpc8xx.h> | ||
6 | |||
7 | extern void puthex(unsigned long val); | ||
8 | extern void puts(const char *); | ||
9 | |||
10 | /* To map PCI devices, you first write 0xffffffff into the device | ||
11 | * base address registers. When the register is read back, the | ||
12 | * number of most significant '1' bits describes the amount of address | ||
13 | * space needed for mapping. If the most significant bit is not set, | ||
14 | * either the device does not use that address register, or it has | ||
15 | * a fixed address that we can't change. After the address is assigned, | ||
16 | * the command register has to be written to enable the card. | ||
17 | */ | ||
18 | typedef struct { | ||
19 | u_char pci_bus; | ||
20 | u_char pci_devfn; | ||
21 | ushort pci_command; | ||
22 | uint pci_addrs[6]; | ||
23 | } pci_map_t; | ||
24 | |||
25 | /* We should probably dynamically allocate these structures. | ||
26 | */ | ||
27 | #define MAX_PCI_DEVS 32 | ||
28 | int pci_dev_cnt; | ||
29 | pci_map_t pci_map[MAX_PCI_DEVS]; | ||
30 | |||
31 | void pci_conf_write(int bus, int device, int func, int reg, uint writeval); | ||
32 | void pci_conf_read(int bus, int device, int func, int reg, void *readval); | ||
33 | void probe_addresses(int bus, int devfn); | ||
34 | void map_pci_addrs(void); | ||
35 | |||
36 | extern int | ||
37 | qs_pci_read_config_byte(unsigned char bus, unsigned char dev_fn, | ||
38 | unsigned char offset, unsigned char *val); | ||
39 | extern int | ||
40 | qs_pci_read_config_word(unsigned char bus, unsigned char dev_fn, | ||
41 | unsigned char offset, unsigned short *val); | ||
42 | extern int | ||
43 | qs_pci_read_config_dword(unsigned char bus, unsigned char dev_fn, | ||
44 | unsigned char offset, unsigned int *val); | ||
45 | extern int | ||
46 | qs_pci_write_config_byte(unsigned char bus, unsigned char dev_fn, | ||
47 | unsigned char offset, unsigned char val); | ||
48 | extern int | ||
49 | qs_pci_write_config_word(unsigned char bus, unsigned char dev_fn, | ||
50 | unsigned char offset, unsigned short val); | ||
51 | extern int | ||
52 | qs_pci_write_config_dword(unsigned char bus, unsigned char dev_fn, | ||
53 | unsigned char offset, unsigned int val); | ||
54 | |||
55 | |||
56 | /* This is a really stripped version of PCI bus scan. All we are | ||
57 | * looking for are devices that exist. | ||
58 | */ | ||
59 | void | ||
60 | pci_scanner(int addr_probe) | ||
61 | { | ||
62 | unsigned int devfn, l, class, bus_number; | ||
63 | unsigned char hdr_type, is_multi; | ||
64 | |||
65 | is_multi = 0; | ||
66 | bus_number = 0; | ||
67 | for (devfn = 0; devfn < 0xff; ++devfn) { | ||
68 | /* The device numbers are comprised of upper 5 bits of | ||
69 | * device number and lower 3 bits of multi-function number. | ||
70 | */ | ||
71 | if ((devfn & 7) && !is_multi) { | ||
72 | /* Don't scan multifunction addresses if this is | ||
73 | * not a multifunction device. | ||
74 | */ | ||
75 | continue; | ||
76 | } | ||
77 | |||
78 | /* Read the header to determine card type. | ||
79 | */ | ||
80 | qs_pci_read_config_byte(bus_number, devfn, PCI_HEADER_TYPE, | ||
81 | &hdr_type); | ||
82 | |||
83 | /* If this is a base device number, check the header to | ||
84 | * determine if it is mulifunction. | ||
85 | */ | ||
86 | if ((devfn & 7) == 0) | ||
87 | is_multi = hdr_type & 0x80; | ||
88 | |||
89 | /* Check to see if the board is really in the slot. | ||
90 | */ | ||
91 | qs_pci_read_config_dword(bus_number, devfn, PCI_VENDOR_ID, &l); | ||
92 | /* some broken boards return 0 if a slot is empty: */ | ||
93 | if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || | ||
94 | l == 0xffff0000) { | ||
95 | /* Nothing there. | ||
96 | */ | ||
97 | is_multi = 0; | ||
98 | continue; | ||
99 | } | ||
100 | |||
101 | /* If we are not performing an address probe, | ||
102 | * just simply print out some information. | ||
103 | */ | ||
104 | if (!addr_probe) { | ||
105 | qs_pci_read_config_dword(bus_number, devfn, | ||
106 | PCI_CLASS_REVISION, &class); | ||
107 | |||
108 | class >>= 8; /* upper 3 bytes */ | ||
109 | |||
110 | #if 0 | ||
111 | printf("Found (%3d:%d): vendor 0x%04x, device 0x%04x, class 0x%06x\n", | ||
112 | (devfn >> 3), (devfn & 7), | ||
113 | (l & 0xffff), (l >> 16) & 0xffff, class); | ||
114 | #else | ||
115 | puts("Found ("); puthex(devfn >> 3); | ||
116 | puts(":"); puthex(devfn & 7); | ||
117 | puts("): vendor "); puthex(l & 0xffff); | ||
118 | puts(", device "); puthex((l >> 16) & 0xffff); | ||
119 | puts(", class "); puthex(class); puts("\n"); | ||
120 | #endif | ||
121 | } | ||
122 | else { | ||
123 | /* If this is a "normal" device, build address list. | ||
124 | */ | ||
125 | if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) | ||
126 | probe_addresses(bus_number, devfn); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | /* Now map the boards. | ||
131 | */ | ||
132 | if (addr_probe) | ||
133 | map_pci_addrs(); | ||
134 | } | ||
135 | |||
136 | /* Probe addresses for the specified device. This is a destructive | ||
137 | * operation because it writes the registers. | ||
138 | */ | ||
139 | void | ||
140 | probe_addresses(bus, devfn) | ||
141 | { | ||
142 | int i; | ||
143 | uint pciaddr; | ||
144 | ushort pcicmd; | ||
145 | pci_map_t *pm; | ||
146 | |||
147 | if (pci_dev_cnt >= MAX_PCI_DEVS) { | ||
148 | puts("Too many PCI devices\n"); | ||
149 | return; | ||
150 | } | ||
151 | |||
152 | pm = &pci_map[pci_dev_cnt++]; | ||
153 | |||
154 | pm->pci_bus = bus; | ||
155 | pm->pci_devfn = devfn; | ||
156 | |||
157 | for (i=0; i<6; i++) { | ||
158 | qs_pci_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_0 + (i * 4), -1); | ||
159 | qs_pci_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0 + (i * 4), | ||
160 | &pciaddr); | ||
161 | pm->pci_addrs[i] = pciaddr; | ||
162 | qs_pci_read_config_word(bus, devfn, PCI_COMMAND, &pcicmd); | ||
163 | pm->pci_command = pcicmd; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | /* Map the cards into the PCI space. The PCI has separate memory | ||
168 | * and I/O spaces. In addition, some memory devices require mapping | ||
169 | * below 1M. The least significant 4 bits of the address register | ||
170 | * provide information. If this is an I/O device, only the LS bit | ||
171 | * is used to indicate that, so I/O devices can be mapped to a two byte | ||
172 | * boundard. Memory addresses can be mapped to a 32 byte boundary. | ||
173 | * The QSpan implementations usually have a 1Gbyte space for each | ||
174 | * memory and I/O spaces. | ||
175 | * | ||
176 | * This isn't a terribly fancy algorithm. I just map the spaces from | ||
177 | * the top starting with the largest address space. When finished, | ||
178 | * the registers are written and the card enabled. | ||
179 | * | ||
180 | * While the Tundra can map a large address space on most boards, we | ||
181 | * need to be careful because it may overlap other devices (like IMMR). | ||
182 | */ | ||
183 | #define MEMORY_SPACE_SIZE 0x20000000 | ||
184 | #define IO_SPACE_SIZE 0x20000000 | ||
185 | |||
186 | void | ||
187 | map_pci_addrs() | ||
188 | { | ||
189 | uint pci_mem_top, pci_mem_low; | ||
190 | uint pci_io_top; | ||
191 | uint addr_mask, reg_addr, space; | ||
192 | int i, j; | ||
193 | pci_map_t *pm; | ||
194 | |||
195 | pci_mem_top = MEMORY_SPACE_SIZE; | ||
196 | pci_io_top = IO_SPACE_SIZE; | ||
197 | pci_mem_low = (1 * 1024 * 1024); /* Below one meg addresses */ | ||
198 | |||
199 | /* We can't map anything more than the maximum space, but test | ||
200 | * for it anyway to catch devices out of range. | ||
201 | */ | ||
202 | addr_mask = 0x80000000; | ||
203 | |||
204 | do { | ||
205 | space = (~addr_mask) + 1; /* Size of the space */ | ||
206 | for (i=0; i<pci_dev_cnt; i++) { | ||
207 | pm = &pci_map[i]; | ||
208 | for (j=0; j<6; j++) { | ||
209 | /* If the MS bit is not set, this has either | ||
210 | * already been mapped, or is not used. | ||
211 | */ | ||
212 | reg_addr = pm->pci_addrs[j]; | ||
213 | if ((reg_addr & 0x80000000) == 0) | ||
214 | continue; | ||
215 | if (reg_addr & PCI_BASE_ADDRESS_SPACE_IO) { | ||
216 | if ((reg_addr & PCI_BASE_ADDRESS_IO_MASK) != addr_mask) | ||
217 | continue; | ||
218 | if (pci_io_top < space) { | ||
219 | puts("Out of PCI I/O space\n"); | ||
220 | } | ||
221 | else { | ||
222 | pci_io_top -= space; | ||
223 | pm->pci_addrs[j] = pci_io_top; | ||
224 | pm->pci_command |= PCI_COMMAND_IO; | ||
225 | } | ||
226 | } | ||
227 | else { | ||
228 | if ((reg_addr & PCI_BASE_ADDRESS_MEM_MASK) != addr_mask) | ||
229 | continue; | ||
230 | |||
231 | /* Memory space. Test if below 1M. | ||
232 | */ | ||
233 | if (reg_addr & PCI_BASE_ADDRESS_MEM_TYPE_1M) { | ||
234 | if (pci_mem_low < space) { | ||
235 | puts("Out of PCI 1M space\n"); | ||
236 | } | ||
237 | else { | ||
238 | pci_mem_low -= space; | ||
239 | pm->pci_addrs[j] = pci_mem_low; | ||
240 | } | ||
241 | } | ||
242 | else { | ||
243 | if (pci_mem_top < space) { | ||
244 | puts("Out of PCI Mem space\n"); | ||
245 | } | ||
246 | else { | ||
247 | pci_mem_top -= space; | ||
248 | pm->pci_addrs[j] = pci_mem_top; | ||
249 | } | ||
250 | } | ||
251 | pm->pci_command |= PCI_COMMAND_MEMORY; | ||
252 | } | ||
253 | } | ||
254 | } | ||
255 | addr_mask >>= 1; | ||
256 | addr_mask |= 0x80000000; | ||
257 | } while (addr_mask != 0xfffffffe); | ||
258 | |||
259 | /* Now, run the list one more time and map everything. | ||
260 | */ | ||
261 | for (i=0; i<pci_dev_cnt; i++) { | ||
262 | pm = &pci_map[i]; | ||
263 | for (j=0; j<6; j++) { | ||
264 | qs_pci_write_config_dword(pm->pci_bus, pm->pci_devfn, | ||
265 | PCI_BASE_ADDRESS_0 + (j * 4), pm->pci_addrs[j]); | ||
266 | } | ||
267 | |||
268 | /* Enable memory or address mapping. | ||
269 | */ | ||
270 | qs_pci_write_config_word(pm->pci_bus, pm->pci_devfn, PCI_COMMAND, | ||
271 | pm->pci_command); | ||
272 | } | ||
273 | } | ||
274 | |||