cec09192b700a836ab07fe3920c2dd02152ac233
[coreboot.git] / src / southbridge / intel / i82801dbm / i82801dbm_lpc.c
1 /*
2  * (C) 2003 Linux Networx, SuSE Linux AG
3  * (C) 2004 Tyan Computer
4  */
5 #include <console/console.h>
6 #include <device/device.h>
7 #include <device/pci.h>
8 #include <device/pci_ids.h>
9 #include <device/pci_ops.h>
10 #include <pc80/mc146818rtc.h>
11 #include <pc80/isa-dma.h>
12 #include <arch/io.h>
13 #include "i82801dbm.h"
14
15
16
17 #define NMI_OFF 0
18
19 void i82801dbm_enable_ioapic( struct device *dev) 
20 {
21         uint32_t dword;
22         volatile uint32_t *ioapic_sba = (volatile uint32_t *)0xfec00000;
23         volatile uint32_t *ioapic_sbd = (volatile uint32_t *)0xfec00010;
24
25         dword = pci_read_config32(dev, GEN_CNTL);
26         dword |= (3 << 7); /* enable ioapic */
27         dword |= (1 <<13); /* coprocessor error enable */
28         dword |= (1 << 1); /* delay transaction enable */
29         dword |= (1 << 2); /* DMA collection buf enable */
30         pci_write_config32(dev, GEN_CNTL, dword);
31         printk_debug("ioapic southbridge enabled %x\n",dword);
32         *ioapic_sba=0;
33         *ioapic_sbd=(2<<24);
34         //lyh *ioapic_sba=3;
35         //lyh *ioapic_sbd=1;    
36         *ioapic_sba=0;
37         dword=*ioapic_sbd;
38         printk_debug("Southbridge apic id = %x\n",dword);
39         if(dword!=(2<<24))
40                 for(;;);
41         //lyh *ioapic_sba=3;
42         //lyh dword=*ioapic_sbd;
43         //lyh printk_debug("Southbridge apic DT = %x\n",dword);
44         //lyh if(dword!=1)
45         //lyh   for(;;);
46
47
48 }
49 void i82801dbm_enable_serial_irqs( struct device *dev)
50 {
51         pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0<< 0));
52 }
53 void i82801dbm_lpc_route_dma( struct device *dev, uint8_t mask) 
54 {
55         uint16_t word;
56         int i;
57         word = pci_read_config16(dev, PCI_DMA_CFG);
58         word &= ((1 << 10) - (1 << 8));
59         for(i = 0; i < 8; i++) {
60                 if (i == 4)
61                         continue;
62                 word |= ((mask & (1 << i))? 3:1) << (i*2);
63         }
64         pci_write_config16(dev, PCI_DMA_CFG, word);
65 }
66 void i82801dbm_rtc_init(struct device *dev)
67 {
68         uint8_t byte;
69         uint32_t dword;
70         int rtc_failed;
71         byte = pci_read_config8(dev, GEN_PMCON_3);
72         rtc_failed = byte & RTC_FAILED;
73         if (rtc_failed) {
74                 byte &= ~(1 << 1); /* preserve the power fail state */
75                 pci_write_config8(dev, GEN_PMCON_3, byte);
76         }
77         dword = pci_read_config32(dev, GEN_STS);
78         rtc_failed |= dword & (1 << 2);
79         rtc_init(rtc_failed);
80 }
81
82
83 void i82801dbm_1f0_misc(struct device *dev)
84 {
85         pci_write_config16(dev, PCICMD, 0x014f);
86         pci_write_config32(dev, PMBASE, 0x00001001);
87         pci_write_config8(dev, ACPI_CNTL, 0x10);
88         pci_write_config32(dev, GPIO_BASE, 0x00001181);
89         pci_write_config8(dev, GPIO_CNTL, 0x10);
90         pci_write_config32(dev, PIRQA_ROUT, 0x0A05030B);
91         pci_write_config8(dev, PIRQE_ROUT, 0x07);
92         pci_write_config8(dev, RTC_CONF, 0x04);
93         pci_write_config8(dev, COM_DEC, 0x10);  //lyh E0->
94         pci_write_config16(dev, LPC_EN, 0x000F);  //LYH 000D->
95 }
96
97 static void enable_hpet(struct device *dev)
98 {
99         const unsigned long hpet_address = 0xfed0000;
100
101         uint32_t dword;
102         uint32_t code = (0 & 0x3);
103         
104         dword = pci_read_config32(dev, GEN_CNTL);
105         dword |= (1 << 17); /* enable hpet */
106         /*Bits [16:15]Memory Address Range
107         00 FED0_0000h - FED0_03FFh
108         01 FED0_1000h - FED0_13FFh
109         10 FED0_2000h - FED0_23FFh
110         11 FED0_3000h - FED0_33FFh*/
111
112         dword &= ~(3 << 15); /* clear it */
113         dword |= (code<<15);
114
115         printk_debug("enabling HPET @0x%x\n", hpet_address | (code <<12) );
116 }
117
118 static void lpc_init(struct device *dev)
119 {
120         uint8_t byte;
121         int pwr_on=-1;
122         int nmi_option;
123
124         /* IO APIC initialization */
125         i82801dbm_enable_ioapic(dev);
126
127         i82801dbm_enable_serial_irqs(dev);
128
129 #ifdef SUSPICIOUS_LOOKING_CODE  
130         // The ICH-4 datasheet does not mention this configuration register. 
131         // This code may have been inherited (incorrectly) from code for the AMD 766 southbridge,
132         // which *does* support this functionality.
133
134         /* posted memory write enable */
135         byte = pci_read_config8(dev, 0x46);
136         pci_write_config8(dev, 0x46, byte | (1<<0)); 
137 #endif
138
139         /* power after power fail */
140                 /* FIXME this doesn't work! */
141         /* Which state do we want to goto after g3 (power restored)?
142          * 0 == S0 Full On
143          * 1 == S5 Soft Off
144          */
145         pci_write_config8(dev, GEN_PMCON_3, pwr_on?0:1);
146         printk_info("set power %s after power fail\n", pwr_on?"on":"off");
147 #if 0
148         /* Enable Error reporting */
149         /* Set up sync flood detected */
150         byte = pci_read_config8(dev, 0x47);
151         byte |= (1 << 1);
152         pci_write_config8(dev, 0x47, byte);
153 #endif
154
155         /* Set up NMI on errors */
156     byte = inb(0x61);
157     byte &= ~(1 << 3); /* IOCHK# NMI Enable */
158     byte &= ~(1 << 2); /* PCI SERR# Enable */
159     outb(byte, 0x61);
160     byte = inb(0x70);
161         nmi_option = NMI_OFF;
162         get_option(&nmi_option, "nmi");
163         if (nmi_option) {                       
164         byte &= ~(1 << 7); /* set NMI */
165         outb(byte, 0x70);
166         }
167         
168         /* Initialize the real time clock */
169         i82801dbm_rtc_init(dev);
170
171         i82801dbm_lpc_route_dma(dev, 0xff);
172
173         /* Initialize isa dma */
174         isa_dma_init();
175
176         i82801dbm_1f0_misc(dev);
177         /* Initialize the High Precision Event Timers */
178         enable_hpet(dev);
179 }
180
181 static void i82801dbm_lpc_read_resources(device_t dev)
182 {
183         struct resource *res;
184
185         /* Get the normal pci resources of this device */
186         pci_dev_read_resources(dev);
187
188         /* Add an extra subtractive resource for both memory and I/O */
189         res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
190         res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
191
192         res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
193         res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
194 }
195
196 static void i82801dbm_lpc_enable_resources(device_t dev)
197 {
198         pci_dev_enable_resources(dev);
199         enable_childrens_resources(dev);
200 }
201
202 static struct device_operations lpc_ops  = {
203         .read_resources   = i82801dbm_lpc_read_resources,
204         .set_resources    = pci_dev_set_resources,
205         .enable_resources = i82801dbm_lpc_enable_resources,
206         .init             = lpc_init,
207         .scan_bus         = scan_static_bus,
208         .enable           = i82801dbm_enable,
209 };
210
211 static const struct pci_driver lpc_driver __pci_driver = {
212         .ops    = &lpc_ops,
213         .vendor = PCI_VENDOR_ID_INTEL,
214         .device = PCI_DEVICE_ID_INTEL_82801DBM_LPC,
215 };