- Bump the LinuxBIOS major version
[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 <console/console.h>
8 #include "vt8231.h"
9 #include "chip.h"
10
11 void pc_keyboard_init(void);
12
13 void hard_reset(void) 
14 {
15         printk_err("NO HARD RESET ON VT8231! FIX ME!\n");
16 }
17
18 static void usb_on(int enable)
19 {
20         unsigned char regval;
21
22         /* Base 8231 controller */
23         device_t dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
24         /* USB controller 1 */
25         device_t dev2 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, 0);
26         /* USB controller 2 */
27         device_t dev3 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, dev2);
28         
29         /* enable USB1 */
30         if(dev2) {
31                 if (enable) {
32                         pci_write_config8(dev2, 0x3c, 0x05);
33                         pci_write_config8(dev2, 0x04, 0x07);
34                 } else {
35                         pci_write_config8(dev2, 0x3c, 0x00);
36                         pci_write_config8(dev2, 0x04, 0x00);
37                 }
38         }
39         
40         if(dev0) {
41                 regval = pci_read_config8(dev0, 0x50);
42                 if (enable) 
43                         regval &= ~(0x10);    
44                 else
45                         regval |= 0x10;               
46                 pci_write_config8(dev0, 0x50, regval);
47         }
48         
49         /* enable USB2 */
50         if(dev3) {
51                 if (enable) {
52                         pci_write_config8(dev3, 0x3c, 0x05);
53                         pci_write_config8(dev3, 0x04, 0x07);
54                 } else {
55                         pci_write_config8(dev3, 0x3c, 0x00);
56                         pci_write_config8(dev3, 0x04, 0x00);
57                 }
58         }
59         
60         if(dev0) {
61                 regval = pci_read_config8(dev0, 0x50);
62                 if (enable) 
63                         regval &= ~(0x20);    
64                 else
65                         regval |= 0x20;    
66                 pci_write_config8(dev0, 0x50, regval);
67         }
68 }
69
70 static void keyboard_on(void)
71 {
72         unsigned char regval;
73         
74         /* Base 8231 controller */
75         device_t dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
76         
77         /* kevinh/Ispiri - update entire function to use 
78            new pci_write_config8 */
79
80         if (dev0) {
81                 regval = pci_read_config8(dev0, 0x51);
82                 regval |= 0x0f; 
83                 pci_write_config8(dev0, 0x51, regval);
84         }
85         init_pc_keyboard(0x60, 0x64, 0);
86 }
87
88 static void nvram_on(void)
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 static void ethernet_fixup()
109 {
110         device_t        edev;
111         uint8_t         byte;
112
113         printk_info("Ethernet fixup\n");
114
115         edev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_7, 0);
116         if (edev) {
117                 printk_debug("Configuring VIA LAN\n");
118                 
119                 /* We don't need stepping - though the device supports it */
120                 byte = pci_read_config8(edev, PCI_COMMAND);
121                 byte &= ~PCI_COMMAND_WAIT;
122                 pci_write_config8(edev, PCI_COMMAND, byte);
123         } else {
124                 printk_debug("VIA LAN not found\n");
125         }
126 }
127
128
129 /* we need to do things in this function so that PCI scan will find 
130  * them.  One problem here is that we can't use ANY of the new device 
131  * stuff. This work here precedes all that.      
132  * Fundamental problem with linuxbios V2 architecture.
133  * You can't do pci control in the C code without having done a PCI scan.
134  * But in some cases you need to to pci control in the c code before doing
135  * a PCI scan. But you can't use arch/romcc_io.h (the code you need) because
136  * that has functions with the same name but different type signatures
137  * (e.g. device_t). This needs to get fixed. We need low-level pci scans
138  * in the C code. 
139  */
140 static void vt8231_pci_enable(struct southbridge_via_vt8231_config *conf) 
141 {
142         /*
143           unsigned long busdevfn = 0x8000;
144           if (conf->enable_ide) {
145           printk_debug("%s: enabling IDE function\n", __FUNCTION__);
146           }
147         */
148 }
149
150 /* PIRQ init
151  */
152 void pci_assign_irqs(unsigned bus, unsigned slot, const unsigned char pIntAtoD[4]);
153
154
155 static const unsigned char southbridgeIrqs[4] = { 11, 5, 10, 12 };
156 static const unsigned char enetIrqs[4] = { 11, 5, 10, 12 };
157 static const unsigned char slotIrqs[4] = { 5, 10, 12, 11 };
158
159 /*
160         Our IDSEL mappings are as follows
161         PCI slot is AD31          (device 15) (00:14.0)
162         Southbridge is AD28       (device 12) (00:11.0)
163 */
164 static void pci_routing_fixup(void)
165 {
166         device_t dev;
167
168         dev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
169         printk_info("%s: dev is %p\n", __FUNCTION__, dev);
170         if (dev) {
171                 /* initialize PCI interupts - these assignments depend
172                    on the PCB routing of PINTA-D 
173
174                    PINTA = IRQ11
175                    PINTB = IRQ5
176                    PINTC = IRQ10
177                    PINTD = IRQ12
178                 */
179                 pci_write_config8(dev, 0x55, 0xb0);
180                 pci_write_config8(dev, 0x56, 0xa5);
181                 pci_write_config8(dev, 0x57, 0xc0);
182         }
183
184         // Standard southbridge components
185         printk_info("setting southbridge\n");
186         pci_assign_irqs(0, 0x11, southbridgeIrqs);
187
188         // Ethernet built into southbridge
189         printk_info("setting ethernet\n");
190         pci_assign_irqs(0, 0x12, enetIrqs);
191
192         // PCI slot
193         printk_info("setting pci slot\n");
194         pci_assign_irqs(0, 0x14, slotIrqs);
195         printk_info("%s: DONE\n", __FUNCTION__);
196 }
197
198
199 void
200 dump_south(void)
201 {
202         device_t dev0;
203         dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
204         int i,j;
205         
206         for(i = 0; i < 256; i += 16) {
207                 printk_debug("0x%x: ", i);
208                 for(j = 0; j < 16; j++) {
209                         printk_debug("%02x ", pci_read_config8(dev0, i+j));
210                 }
211                 printk_debug("\n");
212         }
213 }
214
215 static void vt8231_init(struct southbridge_via_vt8231_config *conf)
216 {
217         unsigned char enables;
218         device_t dev0;
219         device_t dev1;
220         device_t devpwr;
221         
222         // to do: use the pcibios_find function here, instead of 
223         // hard coding the devfn. 
224         // done - kevinh/Ispiri
225         printk_debug("vt8231 init\n");
226         /* Base 8231 controller */
227         dev0 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, 0);
228         /* IDE controller */
229         dev1 = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, 0);
230         /* Power management controller */
231         devpwr = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4, 0);
232
233         // enable the internal I/O decode
234         enables = pci_read_config8(dev0, 0x6C);
235         enables |= 0x80;
236         pci_write_config8(dev0, 0x6C, enables);
237         
238         // Map 4MB of FLASH into the address space
239         pci_write_config8(dev0, 0x41, 0x7f);
240         
241         // Set bit 6 of 0x40, because Award does it (IO recovery time)
242         // IMPORTANT FIX - EISA 0x4d0 decoding must be on so that PCI 
243         // interrupts can be properly marked as level triggered.
244         enables = pci_read_config8(dev0, 0x40);
245         pci_write_config8(dev0, 0x40, enables);
246         
247         // Set 0x42 to 0xf0 to match Award bios
248         enables = pci_read_config8(dev0, 0x42);
249         enables |= 0xf0;
250         pci_write_config8(dev0, 0x42, enables);
251         
252         // Set bit 3 of 0x4a, to match award (dummy pci request)
253         enables = pci_read_config8(dev0, 0x4a);
254         enables |= 0x08;
255         pci_write_config8(dev0, 0x4a, enables);
256         
257         // Set bit 3 of 0x4f to match award (use INIT# as cpu reset)
258         enables = pci_read_config8(dev0, 0x4f);
259         enables |= 0x08;
260         pci_write_config8(dev0, 0x4f, enables);
261         
262         // Set 0x58 to 0x03 to match Award
263         pci_write_config8(dev0, 0x58, 0x03);
264         
265         // enable the ethernet/RTC
266         if(dev0) {
267                 enables = pci_read_config8(dev0, 0x51);
268                 enables |= 0x18; 
269                 pci_write_config8(dev0, 0x51, enables);
270         }
271         
272         
273         // enable com1 and com2. 
274         if (conf->enable_com_ports) {
275                 enables = pci_read_config8(dev0, 0x6e);
276                 
277                 /* 0x80 is enable com port b, 0x10 is to make it com2, 0x8
278                  * is enable com port a as com1 kevinh/Ispiri - Old code
279                  * thought 0x01 would make it com1, that was wrong enables =
280                  * 0x80 | 0x10 | 0x8 ; pci_write_config8(dev0, 0x6e,
281                  * enables); // note: this is also a redo of some port of
282                  * assembly, but we want everything up.
283                  */
284                 
285                 /* set com1 to 115 kbaud not clear how to do this yet.
286                  * forget it; done in assembly.
287                  */
288
289         }
290         // enable IDE, since Linux won't do it.
291         // First do some more things to devfn (17,0)
292         // note: this should already be cleared, according to the book. 
293         enables = pci_read_config8(dev0, 0x50);
294         printk_debug("IDE enable in reg. 50 is 0x%x\n", enables);
295         enables &= ~8; // need manifest constant here!
296         printk_debug("set IDE reg. 50 to 0x%x\n", enables);
297         pci_write_config8(dev0, 0x50, enables);
298         
299         // set default interrupt values (IDE)
300         enables = pci_read_config8(dev0, 0x4c);
301         printk_debug("IRQs in reg. 4c are 0x%x\n", enables & 0xf);
302         // clear out whatever was there. 
303         enables &= ~0xf;
304         enables |= 4;
305         printk_debug("setting reg. 4c to 0x%x\n", enables);
306         pci_write_config8(dev0, 0x4c, enables);
307         
308         // set up the serial port interrupts. 
309         // com2 to 3, com1 to 4
310         pci_write_config8(dev0, 0x46, 0x04);
311         pci_write_config8(dev0, 0x47, 0x03);
312         pci_write_config8(dev0, 0x6e, 0x98);
313         //
314         // Power management setup
315         //
316         // Set ACPI base address to IO 0x4000
317         pci_write_config32(devpwr, 0x48, 0x4001);
318         
319         // Enable ACPI access (and setup like award)
320         pci_write_config8(devpwr, 0x41, 0x84);
321         
322         // Set hardware monitor base address to IO 0x6000
323         pci_write_config32(devpwr, 0x70, 0x6001);
324         
325         // Enable hardware monitor (and setup like award)
326         pci_write_config8(devpwr, 0x74, 0x01);
327         
328         // set IO base address to 0x5000
329         pci_write_config32(devpwr, 0x90, 0x5001);
330         
331         // Enable SMBus 
332         pci_write_config8(devpwr, 0xd2, 0x01);
333         
334         //
335         // IDE setup
336         //
337         if (! conf->enable_native_ide) {
338                 // Run the IDE controller in 'compatiblity mode - i.e. don't use PCI
339                 // interrupts.  Using PCI ints confuses linux for some reason.
340                 
341                 printk_info("%s: enabling compatibility IDE addresses\n", __FUNCTION__);
342                 enables = pci_read_config8(dev1, 0x42);
343                 printk_debug("enables in reg 0x42 0x%x\n", enables);
344                 enables &= ~0xc0;               // compatability mode
345                 pci_write_config8(dev1, 0x42, enables);
346                 enables = pci_read_config8(dev1, 0x42);
347                 printk_debug("enables in reg 0x42 read back as 0x%x\n", enables);
348         }
349         
350         enables = pci_read_config8(dev1, 0x40);
351         printk_debug("enables in reg 0x40 0x%x\n", enables);
352         enables |= 3;
353         pci_write_config8(dev1, 0x40, enables);
354         enables = pci_read_config8(dev1, 0x40);
355         printk_debug("enables in reg 0x40 read back as 0x%x\n", enables);
356         
357         // Enable prefetch buffers
358         enables = pci_read_config8(dev1, 0x41);
359         enables |= 0xf0;
360         pci_write_config8(dev1, 0x41, enables);
361         
362         // Lower thresholds (cause award does it)
363         enables = pci_read_config8(dev1, 0x43);
364         enables &= ~0x0f;
365         enables |=  0x05;
366         pci_write_config8(dev1, 0x43, enables);
367         
368         // PIO read prefetch counter (cause award does it)
369         pci_write_config8(dev1, 0x44, 0x18);
370         
371         // Use memory read multiple
372         pci_write_config8(dev1, 0x45, 0x1c);
373         
374         // address decoding. 
375         // we want "flexible", i.e. 1f0-1f7 etc. or native PCI
376         // kevinh@ispiri.com - the standard linux drivers seem ass slow when 
377         // used in native mode - I've changed back to classic
378         enables = pci_read_config8(dev1, 0x9);
379         printk_debug("enables in reg 0x9 0x%x\n", enables);
380         // by the book, set the low-order nibble to 0xa. 
381         if (conf->enable_native_ide) {
382                 enables &= ~0xf;
383                 // cf/cg silicon needs an 'f' here. 
384                 enables |= 0xf;
385         } else {
386                 enables &= ~0x5;
387         }
388         
389         pci_write_config8(dev1, 0x9, enables);
390         enables = pci_read_config8(dev1, 0x9);
391         printk_debug("enables in reg 0x9 read back as 0x%x\n", enables);
392         
393         // standard bios sets master bit. 
394         enables = pci_read_config8(dev1, 0x4);
395         printk_debug("command in reg 0x4 0x%x\n", enables);
396         enables |= 7;
397         
398         // No need for stepping - kevinh@ispiri.com
399         enables &= ~0x80;
400         
401         pci_write_config8(dev1, 0x4, enables);
402         enables = pci_read_config8(dev1, 0x4);
403         printk_debug("command in reg 0x4 reads back as 0x%x\n", enables);
404         
405         if (! conf->enable_native_ide) {
406                 // Use compatability mode - per award bios
407                 pci_write_config32(dev1, 0x10, 0x0);
408                 pci_write_config32(dev1, 0x14, 0x0);
409                 pci_write_config32(dev1, 0x18, 0x0);
410                 pci_write_config32(dev1, 0x1c, 0x0);
411                 
412                 // Force interrupts to use compat mode - just like Award bios
413                 pci_write_config8(dev1, 0x3d, 00);
414                 pci_write_config8(dev1, 0x3c, 0xff);
415         }
416         
417         
418         /* set up isa bus -- i/o recovery time, rom write enable, extend-ale */
419         pci_write_config8(dev0, 0x40, 0x54);
420         ethernet_fixup();
421         
422         // Start the rtc
423         rtc_init(0);
424 }
425
426 static void southbridge_init(struct chip *chip, enum chip_pass pass)
427 {
428
429         struct southbridge_via_vt8231_config *conf = 
430                 (struct southbridge_via_vt8231_config *)chip->chip_info;
431
432         switch (pass) {
433         case CONF_PASS_PRE_PCI:
434                 vt8231_pci_enable(conf);
435                 break;
436                 
437         case CONF_PASS_POST_PCI:
438                 vt8231_init(conf);
439                 pci_routing_fixup();
440                 break;
441
442         case CONF_PASS_PRE_BOOT:
443                 dump_south();
444                 break;
445                 
446         default:
447                 /* nothing yet */
448                 break;
449         }
450 }
451
452 struct chip_operations southbridge_via_vt8231_control = {
453         .enable    = southbridge_init,
454         .name      = "VIA vt8231"
455 };