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