The ARRAY_SIZE macro is convenient, yet mostly unused. Switch lots of
[coreboot.git] / src / northbridge / via / vt8623 / northbridge.c
1 #include <console/console.h>
2 #include <arch/io.h>
3 #include <stdint.h>
4 #include <device/device.h>
5 #include <device/pci.h>
6 #include <device/hypertransport.h>
7 #include <device/pci_ids.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <bitops.h>
11 #include <cpu/cpu.h>
12 #include <cpu/x86/mtrr.h>
13 #include <cpu/x86/msr.h>
14 #include "chip.h"
15 #include "northbridge.h"
16
17 /*
18  * This fixup is based on capturing values from an Award bios.  Without
19  * this fixup the DMA write performance is awful (i.e. hdparm -t /dev/hda is 20x
20  * slower than normal, ethernet drops packets).
21  * Apparently these registers govern some sort of bus master behavior.
22  */
23 #if 0
24 static void dump_dev(device_t dev)
25 {
26         int i,j;
27         
28         for(i = 0; i < 256; i += 16) {
29                 printk_debug("0x%x: ", i);
30                 for(j = 0; j < 16; j++) {
31                         printk_debug("%02x ", pci_read_config8(dev, i+j));
32                 }
33                 printk_debug("\n");
34         }
35 }
36 #endif
37
38 static void northbridge_init(device_t dev) 
39 {
40         device_t fb_dev;
41         unsigned long fb;
42         unsigned char c;
43
44         printk_debug("VT8623 random fixup ...\n");
45         pci_write_config8(dev,  0x0d, 0x08);
46         pci_write_config8(dev,  0x70, 0x82);
47         pci_write_config8(dev,  0x71, 0xc8);
48         pci_write_config8(dev,  0x72, 0x00);
49         pci_write_config8(dev,  0x73, 0x01);
50         pci_write_config8(dev,  0x74, 0x01);
51         pci_write_config8(dev,  0x75, 0x08);
52         pci_write_config8(dev,  0x76, 0x52);
53         pci_write_config8(dev,  0x13, 0xd0);
54         pci_write_config8(dev,  0x84, 0x80);
55         pci_write_config16(dev, 0x80, 0x610f);
56         pci_write_config32(dev, 0x88, 0x00000002);
57         
58         fb_dev = dev_find_device(PCI_VENDOR_ID_VIA, 0x3122, 0);
59         if (fb_dev) {
60                 /* Fixup GART and framebuffer addresses properly.
61                  * First setup frame buffer properly.
62                  */
63                 //fb = pci_read_config32(dev, 0x10);       /* Base addres of framebuffer */
64                 fb = 0xd0000000;
65                 printk_debug("Frame buffer at %8x\n",fb);
66
67                 c = pci_read_config8(dev, 0xe1) & 0xf0;  /* size of vga */
68                 c |= fb>>28;  /* upper nibble of frame buffer address */
69                 c = 0xdd;
70                 pci_write_config8(dev, 0xe1, c);
71                 c = 0x81;                                /* enable framebuffer */
72                 pci_write_config8(dev, 0xe0, c);
73                 pci_write_config8(dev, 0xe2, 0x42);      /* 'cos award does */
74         }
75         //dump_dev(dev);
76 }
77
78 static void nullfunc(){}
79
80 static struct device_operations northbridge_operations = {
81         .read_resources   = nullfunc,
82         .set_resources    = pci_dev_set_resources,
83         .enable_resources = pci_dev_enable_resources,
84         .init             = northbridge_init
85 };
86
87 static const struct pci_driver northbridge_driver __pci_driver = {
88         .ops = &northbridge_operations,
89         .vendor = PCI_VENDOR_ID_VIA,
90         .device = PCI_DEVICE_ID_VIA_8623,
91 };
92
93 static void agp_init(device_t dev)
94 {
95         printk_debug("VT8623 AGP random fixup ...\n");
96
97         pci_write_config8(dev, 0x3e, 0x0c);
98         pci_write_config8(dev, 0x40, 0x83);
99         pci_write_config8(dev, 0x41, 0xc5);
100         pci_write_config8(dev, 0x43, 0x44);
101         pci_write_config8(dev, 0x44, 0x34);
102         pci_write_config8(dev, 0x83, 0x02);
103         //dump_dev(dev);
104 }
105
106 static struct device_operations agp_operations = {
107         .read_resources   = nullfunc,
108         .set_resources    = pci_dev_set_resources,
109         .enable_resources = pci_bus_enable_resources,
110         .init             = agp_init,
111         .scan_bus         = pci_scan_bridge,
112         .ops_pci          = 0,
113 };
114
115 static const struct pci_driver agp_driver __pci_driver = {
116         .ops = &agp_operations,
117         .vendor = PCI_VENDOR_ID_VIA,
118         .device = PCI_DEVICE_ID_VIA_8633_1,
119 };
120
121 static void vga_init(device_t dev)
122 {
123 //      unsigned long fb;
124         msr_t clocks1,clocks2,instructions,setup;
125
126         printk_debug("VGA random fixup ...\n");
127         pci_write_config8(dev, 0x04, 0x07);
128         pci_write_config8(dev, 0x0d, 0x20);
129         pci_write_config32(dev,0x10,0xd8000008);
130         pci_write_config32(dev,0x14,0xdc000000);
131
132         //dump_dev(dev);
133         
134         // set up performnce counters for debugging vga init sequence
135         //setup.lo = 0x1c0; // count instructions
136         //wrmsr(0x187,setup);
137         //instructions.hi = 0;
138         //instructions.lo = 0;
139         //wrmsr(0xc2,instructions);
140         //clocks1 = rdmsr(0x10);
141
142         
143 #if 0
144         /* code to make vga init go through the emulator - as of yet this does not workfor the epia-m */
145         dev->on_mainboard=1;
146         dev->rom_address = (void *)0xfffc0000;
147
148         pci_dev_init(dev);
149         
150         call_bios_interrupt(0x10,0x4f1f,0x8003,1,0);
151         
152         //clocks2 = rdmsr(0x10);
153         //instructions = rdmsr(0xc2);
154         
155         printk_debug("Clocks 1 = %08x:%08x\n",clocks1.hi,clocks1.lo);
156         printk_debug("Clocks 2 = %08x:%08x\n",clocks2.hi,clocks2.lo);
157         printk_debug("Instructions = %08x:%08x\n",instructions.hi,instructions.lo);
158
159 #else
160
161         /* code to make vga init run in real mode - does work but against the current coreboot philosophy */
162         printk_debug("INSTALL REAL-MODE IDT\n");
163         setup_realmode_idt();
164         printk_debug("DO THE VGA BIOS\n");
165         do_vgabios();
166
167         //clocks2 = rdmsr(0x10);
168         //instructions = rdmsr(0xc2);
169         
170         //printk_debug("Clocks 1 = %08x:%08x\n",clocks1.hi,clocks1.lo);
171         //printk_debug("Clocks 2 = %08x:%08x\n",clocks2.hi,clocks2.lo);
172         //printk_debug("Instructions = %08x:%08x\n",instructions.hi,instructions.lo);
173
174         vga_enable_console();
175         
176 #endif
177
178
179         pci_write_config32(dev,0x30,0);
180
181         /* Set the vga mtrrs - disable for the moment as the add_var_mtrr function has vapourised */
182 #if 0
183         add_var_mtrr( 0xd0000000 >> 10, 0x08000000>>10, MTRR_TYPE_WRCOMB);
184         fb = pci_read_config32(dev,0x10); // get the fb address
185         add_var_mtrr( fb>>10, 8192, MTRR_TYPE_WRCOMB);
186 #endif
187 }
188
189 static void vga_read_resources(device_t dev)
190 {
191
192         dev->rom_address = (void *)0xfffc0000;
193         dev->on_mainboard=1;
194         pci_dev_read_resources(dev);
195
196 }
197
198 static struct device_operations vga_operations = {
199         .read_resources   = vga_read_resources,
200         .set_resources    = pci_dev_set_resources,
201         .enable_resources = pci_dev_enable_resources,
202         .init             = vga_init,
203         .ops_pci          = 0,
204 };
205
206 static const struct pci_driver vga_driver __pci_driver = {
207         .ops = &vga_operations,
208         .vendor = PCI_VENDOR_ID_VIA,
209         .device = 0x3122,
210 };
211
212
213 #define BRIDGE_IO_MASK (IORESOURCE_IO | IORESOURCE_MEM)
214
215 static void pci_domain_read_resources(device_t dev)
216 {
217         struct resource *resource;
218
219         printk_spew("Entering vt8623 pci_domain_read_resources.\n");
220
221         /* Initialize the system wide io space constraints */
222         resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0,0));
223         resource->limit = 0xffffUL;
224         resource->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
225                 IORESOURCE_ASSIGNED;
226
227         /* Initialize the system wide memory resources constraints */
228         resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1,0));
229         resource->limit = 0xffffffffULL;
230         resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
231                 IORESOURCE_ASSIGNED;
232
233         printk_spew("Leaving vt8623 pci_domain_read_resources.\n");
234 }
235
236 static void ram_resource(device_t dev, unsigned long index,
237         unsigned long basek, unsigned long sizek)
238 {
239         struct resource *resource;
240
241         if (!sizek) {
242                 return;
243         }
244         resource = new_resource(dev, index);
245         resource->base  = ((resource_t)basek) << 10;
246         resource->size  = ((resource_t)sizek) << 10;
247         resource->flags =  IORESOURCE_MEM | IORESOURCE_CACHEABLE | \
248                 IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
249 }
250
251 static void tolm_test(void *gp, struct device *dev, struct resource *new)
252 {
253         struct resource **best_p = gp;
254         struct resource *best;
255         best = *best_p;
256         if (!best || (best->base > new->base)) {
257                 best = new;
258         }
259         *best_p = best;
260 }
261
262 static uint32_t find_pci_tolm(struct bus *bus)
263 {
264         struct resource *min;
265         uint32_t tolm;
266         min = 0;
267         search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min);
268         tolm = 0xffffffffUL;
269         if (min && tolm > min->base) {
270                 tolm = min->base;
271         }
272         return tolm;
273 }
274
275 static void pci_domain_set_resources(device_t dev)
276 {
277         static const uint8_t ramregs[] = {0x5a, 0x5b, 0x5c, 0x5d };
278         device_t mc_dev;
279         uint32_t pci_tolm;
280
281         printk_spew("Entering vt8623 pci_domain_set_resources.\n");
282
283         pci_tolm = find_pci_tolm(&dev->link[0]);
284         mc_dev = dev->link[0].children;
285         if (mc_dev) {
286                 unsigned long tomk, tolmk;
287                 unsigned char rambits;
288                 int i, idx;
289
290                 for(rambits = 0, i = 0; i < ARRAY_SIZE(ramregs); i++) {
291                         unsigned char reg;
292                         reg = pci_read_config8(mc_dev, ramregs[i]);
293                         /* these are ENDING addresses, not sizes. 
294                          * if there is memory in this slot, then reg will be > rambits.
295                          * So we just take the max, that gives us total. 
296                          * We take the highest one to cover for once and future coreboot
297                          * bugs. We warn about bugs.
298                          */
299                         if (reg > rambits)
300                                 rambits = reg;
301                         if (reg < rambits)
302                                 printk_err("ERROR! register 0x%x is not set!\n", 
303                                         ramregs[i]);
304                 }
305                 printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*16*1024);
306                 tomk = rambits*16*1024 - 32768;
307                 /* Compute the top of Low memory */
308                 tolmk = pci_tolm >> 10;
309                 if (tolmk >= tomk) {
310                         /* The PCI hole does does not overlap the memory.
311                          */
312                         tolmk = tomk;
313                 }
314                 /* Report the memory regions */
315                 idx = 10;
316                 ram_resource(dev, idx++, 0, 640);               /* first 640k */
317                 ram_resource(dev, idx++, 768, tolmk - 768);     /* leave a hole for vga */
318         }
319         assign_resources(&dev->link[0]);
320 }
321
322 static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
323 {
324         printk_spew("Entering vt8623 pci_domain_scan_bus.\n");
325
326         max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
327         return max;
328 }
329
330 static struct device_operations pci_domain_ops = {
331         .read_resources   = pci_domain_read_resources,
332         .set_resources    = pci_domain_set_resources,
333         .enable_resources = enable_childrens_resources,
334         .init             = 0,
335         .scan_bus         = pci_domain_scan_bus,
336 };  
337
338 static void cpu_bus_init(device_t dev)
339 {
340         initialize_cpus(&dev->link[0]);
341 }
342
343 static void cpu_bus_noop(device_t dev)
344 {
345 }
346
347 static struct device_operations cpu_bus_ops = {
348         .read_resources   = cpu_bus_noop,
349         .set_resources    = cpu_bus_noop,
350         .enable_resources = cpu_bus_noop,
351         .init             = cpu_bus_init,
352         .scan_bus         = 0,
353 };
354
355 static void enable_dev(struct device *dev)
356 {
357         printk_spew("In vt8623 enable_dev for device %s.\n", dev_path(dev));
358
359         /* Set the operations if it is a special bus type */
360         if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
361                 dev->ops = &pci_domain_ops;
362                 pci_set_method(dev);
363         }
364         else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
365                 dev->ops = &cpu_bus_ops;
366         }
367 }
368
369 struct chip_operations northbridge_via_vt8623_ops = {
370         CHIP_NAME("VIA VT8623 Northbridge")
371         .enable_dev = enable_dev,
372 };