blob: 0f41c3a72da5f5cf042052554a3add718c238946 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* pci-vdk.c: MB93090-MB00 (VDK) PCI support
2 *
3 * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/types.h>
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/pci.h>
16#include <linux/init.h>
17#include <linux/ioport.h>
18#include <linux/delay.h>
19#include <linux/slab.h>
20
21#include <asm/segment.h>
22#include <asm/io.h>
23#include <asm/mb-regs.h>
24#include <asm/mb86943a.h>
25#include "pci-frv.h"
26
27unsigned int __nongpreldata pci_probe = 1;
28
29int __nongpreldata pcibios_last_bus = -1;
30struct pci_bus *__nongpreldata pci_root_bus;
31struct pci_ops *__nongpreldata pci_root_ops;
32
33/*
34 * Functions for accessing PCI configuration space
35 */
36
37#define CONFIG_CMD(bus, dev, where) \
38 (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
39
40#define __set_PciCfgAddr(A) writel((A), (volatile void __iomem *) __region_CS1 + 0x80)
41
42#define __get_PciCfgDataB(A) readb((volatile void __iomem *) __region_CS1 + 0x88 + ((A) & 3))
43#define __get_PciCfgDataW(A) readw((volatile void __iomem *) __region_CS1 + 0x88 + ((A) & 2))
44#define __get_PciCfgDataL(A) readl((volatile void __iomem *) __region_CS1 + 0x88)
45
46#define __set_PciCfgDataB(A,V) \
47 writeb((V), (volatile void __iomem *) __region_CS1 + 0x88 + (3 - ((A) & 3)))
48
49#define __set_PciCfgDataW(A,V) \
50 writew((V), (volatile void __iomem *) __region_CS1 + 0x88 + (2 - ((A) & 2)))
51
52#define __set_PciCfgDataL(A,V) \
53 writel((V), (volatile void __iomem *) __region_CS1 + 0x88)
54
55#define __get_PciBridgeDataB(A) readb((volatile void __iomem *) __region_CS1 + 0x800 + (A))
56#define __get_PciBridgeDataW(A) readw((volatile void __iomem *) __region_CS1 + 0x800 + (A))
57#define __get_PciBridgeDataL(A) readl((volatile void __iomem *) __region_CS1 + 0x800 + (A))
58
59#define __set_PciBridgeDataB(A,V) writeb((V), (volatile void __iomem *) __region_CS1 + 0x800 + (A))
60#define __set_PciBridgeDataW(A,V) writew((V), (volatile void __iomem *) __region_CS1 + 0x800 + (A))
61#define __set_PciBridgeDataL(A,V) writel((V), (volatile void __iomem *) __region_CS1 + 0x800 + (A))
62
63static inline int __query(const struct pci_dev *dev)
64{
65// return dev->bus->number==0 && (dev->devfn==PCI_DEVFN(0,0));
66// return dev->bus->number==1;
67// return dev->bus->number==0 &&
68// (dev->devfn==PCI_DEVFN(2,0) || dev->devfn==PCI_DEVFN(3,0));
69 return 0;
70}
71
72/*****************************************************************************/
73/*
74 *
75 */
76static int pci_frv_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
77 u32 *val)
78{
79 u32 _value;
80
81 if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
82 _value = __get_PciBridgeDataL(where & ~3);
83 }
84 else {
85 __set_PciCfgAddr(CONFIG_CMD(bus, devfn, where));
86 _value = __get_PciCfgDataL(where & ~3);
87 }
88
89 switch (size) {
90 case 1:
91 _value = _value >> ((where & 3) * 8);
92 break;
93
94 case 2:
95 _value = _value >> ((where & 2) * 8);
96 break;
97
98 case 4:
99 break;
100
101 default:
102 BUG();
103 }
104
105 *val = _value;
106 return PCIBIOS_SUCCESSFUL;
107}
108
109static int pci_frv_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
110 u32 value)
111{
112 switch (size) {
113 case 1:
114 if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
115 __set_PciBridgeDataB(where, value);
116 }
117 else {
118 __set_PciCfgAddr(CONFIG_CMD(bus, devfn, where));
119 __set_PciCfgDataB(where, value);
120 }
121 break;
122
123 case 2:
124 if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
125 __set_PciBridgeDataW(where, value);
126 }
127 else {
128 __set_PciCfgAddr(CONFIG_CMD(bus, devfn, where));
129 __set_PciCfgDataW(where, value);
130 }
131 break;
132
133 case 4:
134 if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) {
135 __set_PciBridgeDataL(where, value);
136 }
137 else {
138 __set_PciCfgAddr(CONFIG_CMD(bus, devfn, where));
139 __set_PciCfgDataL(where, value);
140 }
141 break;
142
143 default:
144 BUG();
145 }
146
147 return PCIBIOS_SUCCESSFUL;
148}
149
150static struct pci_ops pci_direct_frv = {
151 pci_frv_read_config,
152 pci_frv_write_config,
153};
154
155/*
156 * Before we decide to use direct hardware access mechanisms, we try to do some
157 * trivial checks to ensure it at least _seems_ to be working -- we just test
158 * whether bus 00 contains a host bridge (this is similar to checking
159 * techniques used in XFree86, but ours should be more reliable since we
160 * attempt to make use of direct access hints provided by the PCI BIOS).
161 *
162 * This should be close to trivial, but it isn't, because there are buggy
163 * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
164 */
165static int __init pci_sanity_check(struct pci_ops *o)
166{
167 struct pci_bus bus; /* Fake bus and device */
168 u32 id;
169
170 bus.number = 0;
171
172 if (o->read(&bus, 0, PCI_VENDOR_ID, 4, &id) == PCIBIOS_SUCCESSFUL) {
173 printk("PCI: VDK Bridge device:vendor: %08x\n", id);
174 if (id == 0x200e10cf)
175 return 1;
176 }
177
178 printk("PCI: VDK Bridge: Sanity check failed\n");
179 return 0;
180}
181
182static struct pci_ops * __init pci_check_direct(void)
183{
184 unsigned long flags;
185
186 local_irq_save(flags);
187
188 /* check if access works */
189 if (pci_sanity_check(&pci_direct_frv)) {
190 local_irq_restore(flags);
191 printk("PCI: Using configuration frv\n");
192// request_mem_region(0xBE040000, 256, "FRV bridge");
193// request_mem_region(0xBFFFFFF4, 12, "PCI frv");
194 return &pci_direct_frv;
195 }
196
197 local_irq_restore(flags);
198 return NULL;
199}
200
201/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 * Discover remaining PCI buses in case there are peer host bridges.
203 * We use the number of last PCI bus provided by the PCI BIOS.
204 */
205static void __init pcibios_fixup_peer_bridges(void)
206{
207 struct pci_bus bus;
208 struct pci_dev dev;
209 int n;
210 u16 l;
211
212 if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
213 return;
214 printk("PCI: Peer bridge fixup\n");
215 for (n=0; n <= pcibios_last_bus; n++) {
216 if (pci_find_bus(0, n))
217 continue;
218 bus.number = n;
219 bus.ops = pci_root_ops;
220 dev.bus = &bus;
221 for(dev.devfn=0; dev.devfn<256; dev.devfn += 8)
222 if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) &&
223 l != 0x0000 && l != 0xffff) {
224 printk("Found device at %02x:%02x [%04x]\n", n, dev.devfn, l);
225 printk("PCI: Discovered peer bus %02x\n", n);
226 pci_scan_bus(n, pci_root_ops, NULL);
227 break;
228 }
229 }
230}
231
232/*
233 * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
234 */
235
236static void __init pci_fixup_umc_ide(struct pci_dev *d)
237{
238 /*
239 * UM8886BF IDE controller sets region type bits incorrectly,
240 * therefore they look like memory despite of them being I/O.
241 */
242 int i;
243
244 printk("PCI: Fixing base address flags for device %s\n", pci_name(d));
245 for(i=0; i<4; i++)
246 d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
247}
248
249static void __init pci_fixup_ide_bases(struct pci_dev *d)
250{
251 int i;
252
253 /*
254 * PCI IDE controllers use non-standard I/O port decoding, respect it.
255 */
256 if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
257 return;
258 printk("PCI: IDE base address fixup for %s\n", pci_name(d));
259 for(i=0; i<4; i++) {
260 struct resource *r = &d->resource[i];
261 if ((r->start & ~0x80) == 0x374) {
262 r->start |= 2;
263 r->end = r->start;
264 }
265 }
266}
267
268static void __init pci_fixup_ide_trash(struct pci_dev *d)
269{
270 int i;
271
272 /*
273 * There exist PCI IDE controllers which have utter garbage
274 * in first four base registers. Ignore that.
275 */
276 printk("PCI: IDE base address trash cleared for %s\n", pci_name(d));
277 for(i=0; i<4; i++)
278 d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;
279}
280
281static void __devinit pci_fixup_latency(struct pci_dev *d)
282{
283 /*
284 * SiS 5597 and 5598 chipsets require latency timer set to
285 * at most 32 to avoid lockups.
286 */
287 DBG("PCI: Setting max latency to 32\n");
288 pcibios_max_latency = 32;
289}
290
291DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide);
292DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash);
293DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency);
294DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency);
295DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
296
297/*
298 * Called after each bus is probed, but before its children
299 * are examined.
300 */
301
302void __init pcibios_fixup_bus(struct pci_bus *bus)
303{
304#if 0
305 printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number);
306#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 pci_read_bridge_bases(bus);
308
309 if (bus->number == 0) {
310 struct list_head *ln;
311 struct pci_dev *dev;
312 for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
313 dev = pci_dev_b(ln);
314 if (dev->devfn == 0) {
315 dev->resource[0].start = 0;
316 dev->resource[0].end = 0;
317 }
318 }
319 }
320}
321
322/*
323 * Initialization. Try all known PCI access methods. Note that we support
324 * using both PCI BIOS and direct access: in such cases, we use I/O ports
325 * to access config space, but we still keep BIOS order of cards to be
326 * compatible with 2.0.X. This should go away some day.
327 */
328
329int __init pcibios_init(void)
330{
331 struct pci_ops *dir = NULL;
332
333 if (!mb93090_mb00_detected)
334 return -ENXIO;
335
336 __reg_MB86943_sl_ctl |= MB86943_SL_CTL_DRCT_MASTER_SWAP | MB86943_SL_CTL_DRCT_SLAVE_SWAP;
337
338 __reg_MB86943_ecs_base(1) = ((__region_CS2 + 0x01000000) >> 9) | 0x08000000;
339 __reg_MB86943_ecs_base(2) = ((__region_CS2 + 0x00000000) >> 9) | 0x08000000;
340
341 *(volatile uint32_t *) (__region_CS1 + 0x848) = 0xe0000000;
342 *(volatile uint32_t *) (__region_CS1 + 0x8b8) = 0x00000000;
343
344 __reg_MB86943_sl_pci_io_base = (__region_CS2 + 0x04000000) >> 9;
345 __reg_MB86943_sl_pci_mem_base = (__region_CS2 + 0x08000000) >> 9;
346 __reg_MB86943_pci_sl_io_base = __region_CS2 + 0x04000000;
347 __reg_MB86943_pci_sl_mem_base = __region_CS2 + 0x08000000;
348 mb();
349
David Howells04668872007-08-01 19:04:51 +0100350 /* enable PCI arbitration */
351 __reg_MB86943_pci_arbiter = MB86943_PCIARB_EN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352
353 ioport_resource.start = (__reg_MB86943_sl_pci_io_base << 9) & 0xfffffc00;
354 ioport_resource.end = (__reg_MB86943_sl_pci_io_range << 9) | 0x3ff;
355 ioport_resource.end += ioport_resource.start;
356
David Howells9dec17e2006-07-10 04:44:51 -0700357 printk("PCI IO window: %08llx-%08llx\n",
358 (unsigned long long) ioport_resource.start,
359 (unsigned long long) ioport_resource.end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
361 iomem_resource.start = (__reg_MB86943_sl_pci_mem_base << 9) & 0xfffffc00;
362
363 /* Reserve somewhere to write to flush posted writes. */
364 iomem_resource.start += 0x400;
365
366 iomem_resource.end = (__reg_MB86943_sl_pci_mem_range << 9) | 0x3ff;
367 iomem_resource.end += iomem_resource.start;
368
David Howells9dec17e2006-07-10 04:44:51 -0700369 printk("PCI MEM window: %08llx-%08llx\n",
370 (unsigned long long) iomem_resource.start,
371 (unsigned long long) iomem_resource.end);
372 printk("PCI DMA memory: %08lx-%08lx\n",
373 dma_coherent_mem_start, dma_coherent_mem_end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
375 if (!pci_probe)
376 return -ENXIO;
377
378 dir = pci_check_direct();
379 if (dir)
380 pci_root_ops = dir;
381 else {
382 printk("PCI: No PCI bus detected\n");
383 return -ENXIO;
384 }
385
386 printk("PCI: Probing PCI hardware\n");
387 pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL);
388
389 pcibios_irq_init();
390 pcibios_fixup_peer_bridges();
391 pcibios_fixup_irqs();
392 pcibios_resource_survey();
393
394 return 0;
395}
396
397arch_initcall(pcibios_init);
398
399char * __init pcibios_setup(char *str)
400{
401 if (!strcmp(str, "off")) {
402 pci_probe = 0;
403 return NULL;
404 } else if (!strncmp(str, "lastbus=", 8)) {
405 pcibios_last_bus = simple_strtol(str+8, NULL, 0);
406 return NULL;
407 }
408 return str;
409}
410
411int pcibios_enable_device(struct pci_dev *dev, int mask)
412{
413 int err;
414
Bjorn Helgaas9bd8f9c2008-10-15 16:50:48 +0100415 if ((err = pci_enable_resources(dev, mask)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 return err;
Eric W. Biedermanbba6f6f2007-03-28 15:36:09 +0200417 if (!dev->msi_enabled)
418 pcibios_enable_irq(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 return 0;
420}