1e72fb05991f7984d017b1aad95f32915e0eeeae
[coreboot.git] / src / arch / ppc / lib / pci_ops.c
1 #include <console/console.h>
2 #include <arch/pciconf.h>
3 #include <device/pci.h>
4 #include <device/pci_ids.h>
5 #include <device/pci_ops.h>
6
7 static const struct pci_ops *conf;
8 struct pci_ops {
9         uint8_t (*read8) (uint8_t bus, int devfn, int where);
10         uint16_t (*read16) (uint8_t bus, int devfn, int where);
11         uint32_t (*read32) (uint8_t bus, int devfn, int where);
12         int (*write8) (uint8_t bus, int devfn, int where, uint8_t val);
13         int (*write16) (uint8_t bus, int devfn, int where, uint16_t val);
14         int (*write32) (uint8_t bus, int devfn, int where, uint32_t val);
15 };
16
17 struct pci_ops pci_direct_ppc;
18
19 /*
20  * Before we decide to use direct hardware access mechanisms, we try to do some
21  * trivial checks to ensure it at least _seems_ to be working -- we just test
22  * whether bus 00 contains a host bridge (this is similar to checking
23  * techniques used in XFree86, but ours should be more reliable since we
24  * attempt to make use of direct access hints provided by the PCI BIOS).
25  *
26  * This should be close to trivial, but it isn't, because there are buggy
27  * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
28  */
29 static int pci_sanity_check(const struct pci_ops *o)
30 {
31         uint16_t class, vendor;
32         uint8_t bus;
33         int devfn;
34 #define PCI_CLASS_BRIDGE_HOST           0x0600
35 #define PCI_CLASS_DISPLAY_VGA           0x0300
36 #define PCI_VENDOR_ID_COMPAQ            0x0e11
37 #define PCI_VENDOR_ID_INTEL             0x8086
38 #define PCI_VENDOR_ID_MOTOROLA          0x1057
39 #define PCI_VENDOR_ID_IBM               0x1014
40
41         for (bus = 0, devfn = 0; devfn < 0x100; devfn++) {
42                 class = o->read16(bus, devfn, PCI_CLASS_DEVICE);
43                 vendor = o->read16(bus, devfn, PCI_VENDOR_ID);
44                 if (((class == PCI_CLASS_BRIDGE_HOST) || 
45                      (class == PCI_CLASS_DISPLAY_VGA)) ||
46                         ((vendor == PCI_VENDOR_ID_INTEL) || 
47                         (vendor == PCI_VENDOR_ID_COMPAQ) ||
48                         (vendor == PCI_VENDOR_ID_MOTOROLA) ||
49                         (vendor == PCI_VENDOR_ID_IBM))) {
50                         return 1;
51                 }
52         }
53
54         printk_err("PCI: Sanity check failed\n");
55         return 0;
56 }
57
58 uint8_t pci_read_config8(device_t dev, unsigned where)
59 {
60         return conf->read8(dev->bus->secondary, dev->path.u.pci.devfn, where);
61 }
62
63 uint16_t pci_read_config16(struct device *dev, unsigned where)
64 {
65         return conf->read16(dev->bus->secondary, dev->path.u.pci.devfn, where);
66 }
67
68 uint32_t pci_read_config32(struct device *dev, unsigned where)
69 {
70         return conf->read32(dev->bus->secondary, dev->path.u.pci.devfn, where);
71 }
72
73 void pci_write_config8(struct device *dev, unsigned where, uint8_t val)
74 {
75         conf->write8(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
76 }
77
78 void pci_write_config16(struct device *dev, unsigned where, uint16_t val)
79 {
80         conf->write16(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
81 }
82
83 void pci_write_config32(struct device *dev, unsigned where, uint32_t val)
84 {
85         conf->write32(dev->bus->secondary, dev->path.u.pci.devfn, where, val);
86 }
87
88 /** Set the method to be used for PCI
89  */
90 void pci_set_method(void)
91 {
92         conf = &pci_direct_ppc;
93         pci_sanity_check(conf);
94 }
95
96 struct pci_ops pci_direct_ppc =
97 {
98     pci_ppc_read_config8,
99     pci_ppc_read_config16,
100     pci_ppc_read_config32,
101     pci_ppc_write_config8,
102     pci_ppc_write_config16,
103     pci_ppc_write_config32     
104 };
105