5913063606890a1c10e864c048cdd5aff785f21b
[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 <delay.h>
12 #include "pxhd.h"
13
14 static void pxhd_enable(device_t dev)
15 {
16         device_t bridge;
17         uint16_t value;
18         if ((dev->path.pci.devfn & 1) == 0) {
19                 /* Can we enable/disable the bridges? */
20                 return;
21         }
22         bridge = dev_find_slot(dev->bus->secondary, dev->path.pci.devfn & ~1);
23         if (!bridge) {
24                 printk_err("Cannot find bridge for ioapic: %s\n",
25                            dev_path(dev));
26                 return;
27         }
28         value = pci_read_config16(bridge, 0x40);
29         value &= ~(1 << 13);
30         if (!dev->enabled) {
31                 value |= (1 << 13);
32         }
33         pci_write_config16(bridge, 0x40, value);
34 }
35
36
37 #define NMI_OFF 0
38
39 static unsigned int pxhd_scan_bridge(device_t dev, unsigned int max)
40 {
41         int bus_100Mhz = 0;
42
43         dev->link[0].dev = dev;
44         dev->links = 1;
45
46         get_option(&bus_100Mhz, "pxhd_bus_speed_100");
47         if(bus_100Mhz) {
48                 uint16_t word;
49
50                 printk_debug("setting pxhd bus to 100 Mhz\n");
51                 /* set to pcix 100 mhz */
52                 word = pci_read_config16(dev, 0x40);
53                 word &= ~(3 << 14);
54                 word |= (1 << 14);
55                 word &= ~(3 << 9);
56                 word |= (2 << 9);
57                 pci_write_config16(dev, 0x40, word);
58                 
59                 /* reset the bus to make the new frequencies effective */
60                 pci_bus_reset(&dev->link[0]);
61         }       
62         return pcix_scan_bridge(dev, max);
63 }
64 static void pcix_init(device_t dev)
65 {
66         uint32_t dword;
67         uint16_t word;
68         uint8_t byte;
69         int nmi_option;
70
71         /* Bridge control ISA enable */
72         pci_write_config8(dev, 0x3e, 0x07);
73
74 #if 0
75
76         /* Enable memory write and invalidate ??? */
77         byte = pci_read_config8(dev, 0x04);
78         byte |= 0x10;
79         pci_write_config8(dev, 0x04, byte);
80         
81         /* Set drive strength */
82         word = pci_read_config16(dev, 0xe0);
83         word = 0x0404;
84         pci_write_config16(dev, 0xe0, word);
85         word = pci_read_config16(dev, 0xe4);
86         word = 0x0404;
87         pci_write_config16(dev, 0xe4, word);
88         
89         /* Set impedance */
90         word = pci_read_config16(dev, 0xe8);
91         word = 0x0404;
92         pci_write_config16(dev, 0xe8, word);
93
94         /* Set discard unrequested prefetch data */
95         word = pci_read_config16(dev, 0x4c);
96         word |= 1;
97         pci_write_config16(dev, 0x4c, word);
98         
99         /* Set split transaction limits */
100         word = pci_read_config16(dev, 0xa8);
101         pci_write_config16(dev, 0xaa, word);
102         word = pci_read_config16(dev, 0xac);
103         pci_write_config16(dev, 0xae, word);
104
105         /* Set up error reporting, enable all */
106         /* system error enable */
107         dword = pci_read_config32(dev, 0x04);
108         dword |= (1<<8);
109         pci_write_config32(dev, 0x04, dword);
110         
111         /* system and error parity enable */
112         dword = pci_read_config32(dev, 0x3c);
113         dword |= (3<<16);
114         pci_write_config32(dev, 0x3c, dword);
115         
116         /* NMI enable */
117         nmi_option = NMI_OFF;
118         get_option(&nmi_option, "nmi");
119         if(nmi_option) {
120                 dword = pci_read_config32(dev, 0x44);
121                 dword |= (1<<0);
122                 pci_write_config32(dev, 0x44, dword);
123         }
124         
125         /* Set up CRC flood enable */
126         dword = pci_read_config32(dev, 0xc0);
127         if(dword) {  /* do device A only */
128                 dword = pci_read_config32(dev, 0xc4);
129                 dword |= (1<<1);
130                 pci_write_config32(dev, 0xc4, dword);
131                 dword = pci_read_config32(dev, 0xc8);
132                 dword |= (1<<1);
133                 pci_write_config32(dev, 0xc8, dword);
134         }
135         
136         return;
137 #endif
138 }
139
140 static struct device_operations pcix_ops  = {
141         .read_resources   = pci_bus_read_resources,
142         .set_resources    = pci_dev_set_resources,
143         .enable_resources = pci_bus_enable_resources,
144         .init             = pcix_init,
145         .scan_bus         = pxhd_scan_bridge,
146         .reset_bus        = pci_bus_reset,
147         .ops_pci          = 0,
148 };
149
150 static const struct pci_driver pcix_driver __pci_driver = {
151         .ops    = &pcix_ops,
152         .vendor = PCI_VENDOR_ID_INTEL,
153         .device = 0x0329,
154 };
155
156 static const struct pci_driver pcix_driver2 __pci_driver = {
157         .ops    = &pcix_ops,
158         .vendor = PCI_VENDOR_ID_INTEL,
159         .device = 0x032a,
160 };
161
162 #define ALL             (0xff << 24)
163 #define NONE            (0)
164 #define DISABLED        (1 << 16)
165 #define ENABLED         (0 << 16)
166 #define TRIGGER_EDGE    (0 << 15)
167 #define TRIGGER_LEVEL   (1 << 15)
168 #define POLARITY_HIGH   (0 << 13)
169 #define POLARITY_LOW    (1 << 13)
170 #define PHYSICAL_DEST   (0 << 11)
171 #define LOGICAL_DEST    (1 << 11)
172 #define ExtINT          (7 << 8)
173 #define NMI             (4 << 8)
174 #define SMI             (2 << 8)
175 #define INT             (1 << 8)
176         /* IO-APIC virtual wire mode configuration */
177         /* mask, trigger, polarity, destination, delivery, vector */
178
179 static void setup_ioapic(device_t dev)
180 {
181         int i;
182         unsigned long value_low, value_high;
183         unsigned long ioapic_base;
184         volatile unsigned long *l;
185         unsigned interrupts;
186
187         ioapic_base = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
188         l = (unsigned long *) ioapic_base;
189
190         /* Enable front side bus delivery */
191         l[0] = 0x03;
192         l[4] = 1;
193
194         l[0] = 0x01;
195         interrupts = (l[04] >> 16) & 0xff;
196         for (i = 0; i < interrupts; i++) {
197                 l[0] = (i * 2) + 0x10;
198                 l[4] = DISABLED;
199                 value_low = l[4];
200                 l[0] = (i * 2) + 0x11;
201                 l[4] = NONE; /* Should this be an address? */
202                 value_high = l[4];
203                 if (value_low == 0xffffffff) {
204                         printk_warning("IO APIC not responding.\n");
205                         return;
206                 }
207         }
208 }
209
210 static void ioapic_init(device_t dev)
211 {
212         uint32_t value;
213         /* Enable bus mastering so IOAPICs work */
214         value = pci_read_config16(dev, PCI_COMMAND);
215         value |= PCI_COMMAND_MASTER;
216         pci_write_config16(dev, PCI_COMMAND, value);
217
218         setup_ioapic(dev);
219 }
220
221 static void intel_set_subsystem(device_t dev, unsigned vendor, unsigned device)
222 {
223         pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, 
224                 ((device & 0xffff) << 16) | (vendor & 0xffff));
225 }
226
227 static struct pci_operations intel_ops_pci = {
228         .set_subsystem = intel_set_subsystem,
229 };
230
231 static struct device_operations ioapic_ops = {
232         .read_resources   = pci_dev_read_resources,
233         .set_resources    = pci_dev_set_resources,
234         .enable_resources = pci_dev_enable_resources,
235         .init             = ioapic_init,
236         .scan_bus         = 0,
237         .enable           = pxhd_enable,
238         .ops_pci          = &intel_ops_pci,
239 };
240
241 static const struct pci_driver ioapic_driver __pci_driver = {
242         .ops    = &ioapic_ops,
243         .vendor = PCI_VENDOR_ID_INTEL,
244         .device = 0x0326,
245         
246 };
247
248 static const struct pci_driver ioapic2_driver __pci_driver = {
249         .ops    = &ioapic_ops,
250         .vendor = PCI_VENDOR_ID_INTEL,
251         .device = 0x0327,
252         
253 };
254
255 struct chip_operations southbridge_intel_pxhd_ops = {
256         CHIP_NAME("Intel PXHD Southbridge")
257         .enable_dev = pxhd_enable,
258 };