0766b22e7bfcc9cc0303c036b7c362b2862d3162
[coreboot.git] / src / southbridge / intel / pxhd / pxhd_bridge.c
1 /*
2  * (C) 2003-2004 Linux Networx
3  */
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <device/pci_ids.h>
8 #include <device/pci_ops.h>
9 #include <device/pcix.h>
10 #include <pc80/mc146818rtc.h>
11 #include <arch/ioapic.h>
12 #include <delay.h>
13 #include "pxhd.h"
14
15 static void pxhd_enable(device_t dev)
16 {
17         device_t bridge;
18         uint16_t value;
19         if ((dev->path.pci.devfn & 1) == 0) {
20                 /* Can we enable/disable the bridges? */
21                 return;
22         }
23         bridge = dev_find_slot(dev->bus->secondary, dev->path.pci.devfn & ~1);
24         if (!bridge) {
25                 printk_err("Cannot find bridge for ioapic: %s\n",
26                            dev_path(dev));
27                 return;
28         }
29         value = pci_read_config16(bridge, 0x40);
30         value &= ~(1 << 13);
31         if (!dev->enabled) {
32                 value |= (1 << 13);
33         }
34         pci_write_config16(bridge, 0x40, value);
35 }
36
37
38 #define NMI_OFF 0
39
40 static unsigned int pxhd_scan_bridge(device_t dev, unsigned int max)
41 {
42         int bus_100Mhz = 0;
43
44         dev->link[0].dev = dev;
45         dev->links = 1;
46
47         get_option(&bus_100Mhz, "pxhd_bus_speed_100");
48         if(bus_100Mhz) {
49                 uint16_t word;
50
51                 printk_debug("setting pxhd bus to 100 Mhz\n");
52                 /* set to pcix 100 mhz */
53                 word = pci_read_config16(dev, 0x40);
54                 word &= ~(3 << 14);
55                 word |= (1 << 14);
56                 word &= ~(3 << 9);
57                 word |= (2 << 9);
58                 pci_write_config16(dev, 0x40, word);
59                 
60                 /* reset the bus to make the new frequencies effective */
61                 pci_bus_reset(&dev->link[0]);
62         }       
63         return pcix_scan_bridge(dev, max);
64 }
65 static void pcix_init(device_t dev)
66 {
67         /* Bridge control ISA enable */
68         pci_write_config8(dev, 0x3e, 0x07);
69
70 #warning "Please review lots of dead code here."
71 #if 0
72         int nmi_option;
73         uint32_t dword;
74         uint16_t word;
75         uint8_t byte;
76
77         /* Enable memory write and invalidate ??? */
78         byte = pci_read_config8(dev, 0x04);
79         byte |= 0x10;
80         pci_write_config8(dev, 0x04, byte);
81         
82         /* Set drive strength */
83         word = pci_read_config16(dev, 0xe0);
84         word = 0x0404;
85         pci_write_config16(dev, 0xe0, word);
86         word = pci_read_config16(dev, 0xe4);
87         word = 0x0404;
88         pci_write_config16(dev, 0xe4, word);
89         
90         /* Set impedance */
91         word = pci_read_config16(dev, 0xe8);
92         word = 0x0404;
93         pci_write_config16(dev, 0xe8, word);
94
95         /* Set discard unrequested prefetch data */
96         word = pci_read_config16(dev, 0x4c);
97         word |= 1;
98         pci_write_config16(dev, 0x4c, word);
99         
100         /* Set split transaction limits */
101         word = pci_read_config16(dev, 0xa8);
102         pci_write_config16(dev, 0xaa, word);
103         word = pci_read_config16(dev, 0xac);
104         pci_write_config16(dev, 0xae, word);
105
106         /* Set up error reporting, enable all */
107         /* system error enable */
108         dword = pci_read_config32(dev, 0x04);
109         dword |= (1<<8);
110         pci_write_config32(dev, 0x04, dword);
111         
112         /* system and error parity enable */
113         dword = pci_read_config32(dev, 0x3c);
114         dword |= (3<<16);
115         pci_write_config32(dev, 0x3c, dword);
116         
117         /* NMI enable */
118         nmi_option = NMI_OFF;
119         get_option(&nmi_option, "nmi");
120         if(nmi_option) {
121                 dword = pci_read_config32(dev, 0x44);
122                 dword |= (1<<0);
123                 pci_write_config32(dev, 0x44, dword);
124         }
125         
126         /* Set up CRC flood enable */
127         dword = pci_read_config32(dev, 0xc0);
128         if(dword) {  /* do device A only */
129                 dword = pci_read_config32(dev, 0xc4);
130                 dword |= (1<<1);
131                 pci_write_config32(dev, 0xc4, dword);
132                 dword = pci_read_config32(dev, 0xc8);
133                 dword |= (1<<1);
134                 pci_write_config32(dev, 0xc8, dword);
135         }
136         
137         return;
138 #endif
139 }
140
141 static struct device_operations pcix_ops  = {
142         .read_resources   = pci_bus_read_resources,
143         .set_resources    = pci_dev_set_resources,
144         .enable_resources = pci_bus_enable_resources,
145         .init             = pcix_init,
146         .scan_bus         = pxhd_scan_bridge,
147         .reset_bus        = pci_bus_reset,
148         .ops_pci          = 0,
149 };
150
151 static const struct pci_driver pcix_driver __pci_driver = {
152         .ops    = &pcix_ops,
153         .vendor = PCI_VENDOR_ID_INTEL,
154         .device = 0x0329,
155 };
156
157 static const struct pci_driver pcix_driver2 __pci_driver = {
158         .ops    = &pcix_ops,
159         .vendor = PCI_VENDOR_ID_INTEL,
160         .device = 0x032a,
161 };
162
163 static void ioapic_init(device_t dev)
164 {
165         uint32_t value, ioapic_base;
166         /* Enable bus mastering so IOAPICs work */
167         value = pci_read_config16(dev, PCI_COMMAND);
168         value |= PCI_COMMAND_MASTER;
169         pci_write_config16(dev, PCI_COMMAND, value);
170
171         ioapic_base = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
172
173         setup_ioapic(ioapic_base, 0); // Don't rename IOAPIC ID
174 }
175
176 static void intel_set_subsystem(device_t dev, unsigned vendor, unsigned device)
177 {
178         pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, 
179                 ((device & 0xffff) << 16) | (vendor & 0xffff));
180 }
181
182 static struct pci_operations intel_ops_pci = {
183         .set_subsystem = intel_set_subsystem,
184 };
185
186 static struct device_operations ioapic_ops = {
187         .read_resources   = pci_dev_read_resources,
188         .set_resources    = pci_dev_set_resources,
189         .enable_resources = pci_dev_enable_resources,
190         .init             = ioapic_init,
191         .scan_bus         = 0,
192         .enable           = pxhd_enable,
193         .ops_pci          = &intel_ops_pci,
194 };
195
196 static const struct pci_driver ioapic_driver __pci_driver = {
197         .ops    = &ioapic_ops,
198         .vendor = PCI_VENDOR_ID_INTEL,
199         .device = 0x0326,
200         
201 };
202
203 static const struct pci_driver ioapic2_driver __pci_driver = {
204         .ops    = &ioapic_ops,
205         .vendor = PCI_VENDOR_ID_INTEL,
206         .device = 0x0327,
207         
208 };
209
210 struct chip_operations southbridge_intel_pxhd_ops = {
211         CHIP_NAME("Intel PXHD Southbridge")
212         .enable_dev = pxhd_enable,
213 };