c026197973815e37db8712c5fd47e0b6c7f3c1ac
[coreboot.git] / src / northbridge / via / vt8623 / northbridge.c
1 #include <console/console.h>
2 #include <arch/io.h>
3 #include <stdint.h>
4 #include <mem.h>
5 #include <part/sizeram.h>
6 #include <device/device.h>
7 #include <device/pci.h>
8 #include <device/hypertransport.h>
9 #include <device/pci_ids.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <bitops.h>
13 #include <cpu/p6/mtrr.h>
14 #include "chip.h"
15 #include "northbridge.h"
16
17 static const uint8_t ramregs[] = {0x5a, 0x5b, 0x5c, 0x5d };
18
19 struct mem_range *sizeram(void)
20 {
21         unsigned long mmio_basek;
22         static struct mem_range mem[10];
23         device_t dev;
24         int i, idx;
25         unsigned char rambits;
26
27         dev = dev_find_slot(0, 0);
28         if (!dev) {
29                 printk_err("Cannot find PCI: 0:0\n");
30                 return 0;
31         }
32         mem[0].basek = 0;
33         mem[0].sizek = 0xa0000 >>10; // first 640k
34         mem[1].basek = 0xc0000 >>10; // leave a hole for vga
35         idx = 2;
36         while(idx < sizeof(mem)/sizeof(mem[0])) {
37                 mem[idx].basek = 0;
38                 mem[idx].sizek = 0;
39                 idx++;
40         }
41         for(rambits = 0, i = 0; i < sizeof(ramregs)/sizeof(ramregs[0]); i++) {
42                 unsigned char reg;
43                 reg = pci_read_config8(dev, ramregs[i]);
44                 /* these are ENDING addresses, not sizes. 
45                  * if there is memory in this slot, then reg will be > rambits.
46                  * So we just take the max, that gives us total. 
47                  * We take the highest one to cover for once and future linuxbios
48                  * bugs. We warn about bugs.
49                  */
50                 if (reg > rambits)
51                         rambits = reg;
52                 if (reg < rambits)
53                         printk_err("ERROR! register 0x%x is not set!\n", 
54                                 ramregs[i]);
55         }
56         
57         printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*16*1024);
58         mem[1].sizek = rambits*16*1024 - 32768 - (0xc0000 >> 10);
59 #if 1
60         for(i = 0; i < idx; i++) {
61                 printk_debug("mem[%d].basek = %08x mem[%d].sizek = %08x\n",
62                         i, mem[i].basek, i, mem[i].sizek);
63         }
64 #endif
65
66         return mem;
67 }
68 static void enumerate(struct chip *chip)
69 {
70         extern struct device_operations default_pci_ops_bus;
71         chip_enumerate(chip);
72         chip->dev->ops = &default_pci_ops_bus;
73 }
74
75 /*
76  * This fixup is based on capturing values from an Award bios.  Without
77  * this fixup the DMA write performance is awful (i.e. hdparm -t /dev/hda is 20x
78  * slower than normal, ethernet drops packets).
79  * Apparently these registers govern some sort of bus master behavior.
80  */
81 static void random_fixup() {
82         device_t pcidev0 = dev_find_slot(0, 0);
83         device_t pcidev1,pcidev2;
84         unsigned long fb;
85         unsigned char c;
86
87         printk_debug("VT8623 random fixup ...\n");
88         if (pcidev0) {
89                 pci_write_config8(pcidev0, 0x0d, 0x08);
90                 pci_write_config8(pcidev0, 0x70, 0x82);
91                 pci_write_config8(pcidev0, 0x71, 0xc8);
92                 pci_write_config8(pcidev0, 0x72, 0x0);
93                 pci_write_config8(pcidev0, 0x73, 0x01);
94                 pci_write_config8(pcidev0, 0x74, 0x01);
95                 pci_write_config8(pcidev0, 0x75, 0x08);
96                 pci_write_config8(pcidev0, 0x76, 0x52);
97                 pci_write_config8(pcidev0, 0x13, 0xd0);
98                 pci_write_config8(pcidev0, 0x84, 0x80);
99                 pci_write_config16(pcidev0,0x80, 0x610f);
100                 pci_write_config32(pcidev0,0x88, 0x02);
101         }
102         printk_debug("VT8623 AGP random fixup ...\n");
103         pcidev1 = dev_find_device(PCI_VENDOR_ID_VIA,0xb091,0);
104         if( pcidev1) {
105                 pci_write_config8(pcidev1,0x3e,0x0c);
106                 pci_write_config8(pcidev1,0x40,0x83);
107                 pci_write_config8(pcidev1,0x41,0xc5);
108                 pci_write_config8(pcidev1,0x43,0x44);
109                 pci_write_config8(pcidev1,0x44,0x34);
110                 pci_write_config8(pcidev1,0x83,0x02);
111         }
112         printk_debug("VGA random fixup ...\n");
113         pcidev2 = dev_find_device(PCI_VENDOR_ID_VIA,0x3122,0);
114         if( pcidev2 ){
115                 pci_write_config8(pcidev2,0x04,0x07);
116                 pci_write_config8(pcidev2,0x0d,0x20);
117         }
118         // fixup GART and framebuffer addresses properly
119         // first set up frame buffer properly
120         fb = pci_read_config32(pcidev2,0x10);  // base address of framebuffer
121         printk_debug("Frame buffer at %8x\n",fb);
122         c = pci_read_config8(pcidev0,0xe1) & 0xf0;    // size of vga
123         c |= fb>>28;  // upper nibble of frame buffer address
124         pci_write_config8(pcidev0,0xe1,c);
125         c = (fb>>20) | 1; // enable framebuffer
126         pci_write_config8(pcidev0,0xe0,c);
127         pci_write_config8(pcidev0,0xe2,0x42); // 'cos award does
128
129         
130 }
131 static void set_vga_mtrrs(void)
132 {
133         device_t pcidev = dev_find_device(PCI_VENDOR_ID_VIA,0x3122,0);
134         unsigned long fb;
135
136         add_var_mtrr( 0xd0000000 >> 10, 0x08000000>>10, MTRR_TYPE_WRCOMB);
137         fb = pci_read_config32(pcidev,0x10); // get the fb address
138         add_var_mtrr( fb>>10, 8192, MTRR_TYPE_WRCOMB);
139         
140
141 }
142
143 static void northbridge_init(struct chip *chip, enum chip_pass pass)
144 {
145
146         struct northbridge_via_vt8623_config *conf = 
147                 (struct northbridge_via_vt8623_config *)chip->chip_info;
148
149         switch (pass) {
150         case CONF_PASS_PRE_PCI:
151                 break;
152                 
153         case CONF_PASS_POST_PCI:
154                 random_fixup();
155                 break;
156                 
157         case CONF_PASS_PRE_BOOT:
158                 set_vga_mtrrs();
159                 break;
160                 
161         default:
162                 /* nothing yet */
163                 break;
164         }
165 }
166
167 struct chip_control northbridge_via_vt8623_control = {
168         .enumerate = enumerate,
169         .enable    = northbridge_init,
170         .name      = "VIA vt8623 Northbridge",
171 };