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