added via vt8231
[coreboot.git] / src / southbridge / via / vt8231 / vt8231.c
1
2 #include <arch/io.h>
3 #include <device/pci.h>
4 #include <device/chip.h>
5 #include <console/console.h>
6 #include "vt8231.h"
7 #include "chip.h"
8
9
10
11 void usb_on(int enable)
12 {
13         unsigned char regval;
14
15         /* Base 8231 controller */
16         struct pci_dev *dev0 = pci_find_device(PCI_VENDOR_ID_VIA, \
17                                                 PCI_DEVICE_ID_VIA_8231, 0);
18         /* USB controller 1 */
19         struct pci_dev *dev2 = pci_find_device(PCI_VENDOR_ID_VIA, \
20                                                 PCI_DEVICE_ID_VIA_82C586_2, 0);
21         /* USB controller 2 */
22         struct pci_dev *dev3 = pci_find_device(PCI_VENDOR_ID_VIA, \
23                                                 PCI_DEVICE_ID_VIA_82C586_2, \
24                                                 dev2);
25
26         /* enable USB1 */
27         if(dev2) {
28           if (enable) {
29             pci_write_config_byte(dev2, 0x3c, 0x05);
30             pci_write_config_byte(dev2, 0x04, 0x07);
31           } else {
32             pci_write_config_byte(dev2, 0x3c, 0x00);
33             pci_write_config_byte(dev2, 0x04, 0x00);
34           }
35         }
36
37         if(dev0) {
38             pci_read_config_byte(dev0, 0x50, &regval);
39             if (enable) 
40               regval &= ~(0x10);    
41             else
42               regval |= 0x10;                 
43             pci_write_config_byte(dev0, 0x50, regval);
44         }
45
46         /* enable USB2 */
47         if(dev3) {
48           if (enable) {
49             pci_write_config_byte(dev3, 0x3c, 0x05);
50             pci_write_config_byte(dev3, 0x04, 0x07);
51           } else {
52             pci_write_config_byte(dev3, 0x3c, 0x00);
53             pci_write_config_byte(dev3, 0x04, 0x00);
54           }
55         }
56
57         if(dev0) {
58             pci_read_config_byte(dev0, 0x50, &regval);
59             if (enable) 
60               regval &= ~(0x20);    
61             else
62               regval |= 0x20;    
63             pci_write_config_byte(dev0, 0x50, regval);
64         }
65
66 }
67
68 void keyboard_on()
69 {
70         unsigned char regval;
71
72         /* Base 8231 controller */
73         struct pci_dev *dev0 = pci_find_device(PCI_VENDOR_ID_VIA, \
74                                                 PCI_DEVICE_ID_VIA_8231, 0);
75
76         /* kevinh/Ispiri - update entire function to use 
77            new pci_write_config_byte */
78
79         if (dev0) {
80             pci_read_config_byte(dev0, 0x51, &regval);
81             regval |= 0x0f; 
82             pci_write_config_byte(dev0, 0x51, regval);
83         }
84         pc_keyboard_init();
85
86 }
87
88 void nvram_on()
89 {
90         /*
91          * the VIA 8231 South has a very different nvram setup than the 
92          * piix4e ...
93          * turn on ProMedia nvram.
94          * TO DO: use the PciWriteByte function here.
95          */
96
97         /*
98          * kevinh/Ispiri - I don't think this is the correct address/value
99          * intel_conf_writeb(0x80008841, 0xFF);
100          */
101 }
102
103
104 /*
105  * Enable the ethernet device and turn off stepping (because it is integrated 
106  * inside the southbridge)
107  */
108 void ethernet_fixup()
109 {
110         struct pci_dev  *dev, *edev;
111         u8              byte;
112
113         printk_info("Ethernet fixup\n");
114
115         edev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_7, 0);
116         if (edev != NULL) {
117                 printk_debug("Configuring VIA LAN\n");
118
119                 /* We don't need stepping - though the device supports it */
120                 pci_read_config_byte(edev, PCI_COMMAND, &byte);
121                 byte &= ~PCI_COMMAND_WAIT;
122                 pci_write_config_byte(edev, PCI_COMMAND, byte);
123         } else {
124                 printk_debug("VIA LAN not found\n");
125         }
126 }
127
128
129 void southbridge_fixup()
130 {
131         unsigned char enables;
132         struct pci_dev *dev0;
133         struct pci_dev *dev1;
134         struct pci_dev *devpwr;
135
136         // to do: use the pcibios_find function here, instead of 
137         // hard coding the devfn. 
138         // done - kevinh/Ispiri
139
140         /* Base 8231 controller */
141         dev0 = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
142         /* IDE controller */
143         dev1 = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, \
144                                         0);
145         /* Power management controller */
146          devpwr = pci_find_device(PCI_VENDOR_ID_VIA, \
147                                         PCI_DEVICE_ID_VIA_8231_4, 0);
148
149         // enable the internal I/O decode
150         enables = pci_read_config_byte(dev0, 0x6C, &enables);
151         enables |= 0x80;
152         pci_write_config_byte(dev0, 0x6C, enables);
153
154         // Map 4MB of FLASH into the address space
155         pci_write_config_byte(dev0, 0x41, 0x7f);
156
157         // Set bit 6 of 0x40, because Award does it (IO recovery time)
158         // IMPORTANT FIX - EISA 0x4d0 decoding must be on so that PCI 
159         // interrupts can be properly marked as level triggered.
160         enables = pci_read_config_byte(dev0, 0x40, &enables); enables |= 0x44;
161         pci_write_config_byte(dev0, 0x40, enables);
162
163         // Set 0x42 to 0xf0 to match Award bios
164         enables = pci_read_config_byte(dev0, 0x42, &enables);
165         enables |= 0xf0;
166         pci_write_config_byte(dev0, 0x42, enables);
167
168         // Set bit 3 of 0x4a, to match award (dummy pci request)
169         enables = pci_read_config_byte(dev0, 0x4a, &enables);
170         enables |= 0x08;
171         pci_write_config_byte(dev0, 0x4a, enables);
172
173         // Set bit 3 of 0x4f to match award (use INIT# as cpu reset)
174         enables = pci_read_config_byte(dev0, 0x4f, &enables);
175         enables |= 0x08;
176         pci_write_config_byte(dev0, 0x4f, enables);
177
178         // Set 0x58 to 0x03 to match Award
179         pci_write_config_byte(dev0, 0x58, 0x03);
180
181         // enable the ethernet/RTC
182         if(dev0) {
183             pci_read_config_byte(dev0, 0x51, &enables);
184             enables |= 0x18; 
185             pci_write_config_byte(dev0, 0x51, enables);
186         }
187         
188
189         // enable com1 and com2. 
190         if (conf->enable_com_ports) {
191           enables = pci_read_config_byte(dev0, 0x6e, &enables);
192           /* 0x80 is enable com port b, 0x10 is to make it com2, 0x8
193            * is enable com port a as com1 kevinh/Ispiri - Old code
194            * thought 0x01 would make it com1, that was wrong /*
195            * enables = 0x80 | 0x10 | 0x8 ; pci_write_config_byte(dev0,
196            * 0x6e, enables); // note: this is also a redo of some port
197            * of assembly, but we want everything up.
198            */
199
200            /* set com1 to 115 kbaud not clear how to do this yet.
201             * forget it; done in assembly.
202             */
203 #endif
204
205         // enable IDE, since Linux won't do it.
206         // First do some more things to devfn (17,0)
207         // note: this should already be cleared, according to the book. 
208         pci_read_config_byte(dev0, 0x50, &enables);
209         printk_debug("IDE enable in reg. 50 is 0x%x\n", enables);
210         enables &= ~8; // need manifest constant here!
211         printk_debug("set IDE reg. 50 to 0x%x\n", enables);
212         pci_write_config_byte(dev0, 0x50, enables);
213
214         // set default interrupt values (IDE)
215         pci_read_config_byte(dev0, 0x4c, &enables);
216         printk_debug("IRQs in reg. 4c are 0x%x\n", enables & 0xf);
217         // clear out whatever was there. 
218         enables &= ~0xf;
219         enables |= 4;
220         printk_debug("setting reg. 4c to 0x%x\n", enables);
221         pci_write_config_byte(dev0, 0x4c, enables);
222         
223         // set up the serial port interrupts. 
224         // com2 to 3, com1 to 4
225         pci_write_config_byte(dev0, 0x46, 0x04);
226         pci_write_config_byte(dev0, 0x47, 0x03);
227
228         //
229         // Power management setup
230         //
231         // Set ACPI base address to IO 0x4000
232         pci_write_config_dword(devpwr, 0x48, 0x4001);
233
234         // Enable ACPI access (and setup like award)
235         pci_write_config_byte(devpwr, 0x41, 0x84);
236
237         // Set hardware monitor base address to IO 0x6000
238         pci_write_config_dword(devpwr, 0x70, 0x6001);
239
240         // Enable hardware monitor (and setup like award)
241         pci_write_config_byte(devpwr, 0x74, 0x01);
242
243         // set IO base address to 0x5000
244         pci_write_config_dword(devpwr, 0x90, 0x5001);
245
246         // Enable SMBus 
247         pci_write_config_byte(devpwr, 0xd2, 0x01);
248
249         //
250         // IDE setup
251         //
252         if (conf->enable_native_ide) {
253           // Run the IDE controller in 'compatiblity mode - i.e. don't use PCI
254         // interrupts.  Using PCI ints confuses linux for some reason.
255           
256           pci_read_config_byte(dev1, 0x42, &enables);
257           printk_debug("enables in reg 0x42 0x%x\n", enables);
258           enables &= ~0xc0;             // compatability mode
259           pci_write_config_byte(dev1, 0x42, enables);
260           pci_read_config_byte(dev1, 0x42, &enables);
261           printk_debug("enables in reg 0x42 read back as 0x%x\n", enables);
262         }
263
264         pci_read_config_byte(dev1, 0x40, &enables);
265         printk_debug("enables in reg 0x40 0x%x\n", enables);
266         enables |= 3;
267         pci_write_config_byte(dev1, 0x40, enables);
268         pci_read_config_byte(dev1, 0x40, &enables);
269         printk_debug("enables in reg 0x40 read back as 0x%x\n", enables);
270
271         // Enable prefetch buffers
272         pci_read_config_byte(dev1, 0x41, &enables);
273         enables |= 0xf0;
274         pci_write_config_byte(dev1, 0x41, enables);
275
276         // Lower thresholds (cause award does it)
277         pci_read_config_byte(dev1, 0x43, &enables);
278         enables &= ~0x0f;
279         enables |=  0x05;
280         pci_write_config_byte(dev1, 0x43, enables);
281
282         // PIO read prefetch counter (cause award does it)
283         pci_write_config_byte(dev1, 0x44, 0x18);
284
285         // Use memory read multiple
286         pci_write_config_byte(dev1, 0x45, 0x1c);
287
288         // address decoding. 
289         // we want "flexible", i.e. 1f0-1f7 etc. or native PCI
290         // kevinh@ispiri.com - the standard linux drivers seem ass slow when 
291         // used in native mode - I've changed back to classic
292         pci_read_config_byte(dev1, 0x9, &enables);
293         printk_debug("enables in reg 0x9 0x%x\n", enables);
294         // by the book, set the low-order nibble to 0xa. 
295         if (conf->enable_native_ide) {
296           enables &= ~0xf;
297           // cf/cg silicon needs an 'f' here. 
298           enables |= 0xf;
299         } else {
300           enables &= ~0x5;
301         }
302
303         pci_write_config_byte(dev1, 0x9, enables);
304         pci_read_config_byte(dev1, 0x9, &enables);
305         printk_debug("enables in reg 0x9 read back as 0x%x\n", enables);
306
307         // standard bios sets master bit. 
308         pci_read_config_byte(dev1, 0x4, &enables);
309         printk_debug("command in reg 0x4 0x%x\n", enables);
310         enables |= 7;
311         
312         // No need for stepping - kevinh@ispiri.com
313         enables &= ~0x80;
314
315         pci_write_config_byte(dev1, 0x4, enables);
316         pci_read_config_byte(dev1, 0x4, &enables);
317         printk_debug("command in reg 0x4 reads back as 0x%x\n", enables);
318
319         if (! conf->enable_native_ide) {
320           // Use compatability mode - per award bios
321           pci_write_config_dword(dev1, 0x10, 0x0);
322           pci_write_config_dword(dev1, 0x14, 0x0);
323           pci_write_config_dword(dev1, 0x18, 0x0);
324           pci_write_config_dword(dev1, 0x1c, 0x0);
325           
326           // Force interrupts to use compat mode - just like Award bios
327           pci_write_config_byte(dev1, 0x3d, 00);
328           pci_write_config_byte(dev1, 0x3c, 0xff);
329         }
330
331
332         ethernet_fixup();
333
334         // Start the rtc
335         rtc_init(0);
336 }
337
338 static void 
339 southbridge_init(struct chip *chip, enum chip_pass pass)
340 {
341
342         struct southbridge_via_vt8231_config *conf = 
343                 (struct southbridge_via_vt8231_config *)chip->chip_info;
344
345         switch (pass) {
346         case CONF_PASS_POST_PCI:
347                 vt8231_init(conf);
348                 break;
349
350         default:
351                 /* nothing yet */
352                 break;
353         }
354 }
355
356 struct chip_control southbridge_via_vt8231_control = {
357         enable: southbridge_init,
358         name:   "VIA vt8231"
359 };