better support enable_dev for amd8111
[coreboot.git] / src / southbridge / amd / amd8111 / amd8111_lpc.c
1 /*
2  * (C) 2003 Linux Networx, SuSE Linux AG
3  */
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <device/pci_ids.h>
8 #include <device/pci_ops.h>
9 #include <pc80/mc146818rtc.h>
10 #include "amd8111.h"
11
12 void isa_dma_init(void); /* from /pc80/isa-dma.c */
13
14 #define NMI_OFF 0
15
16 struct ioapicreg {
17         unsigned int reg;
18         unsigned int value_low, value_high;
19 };
20
21 static struct ioapicreg ioapicregvalues[] = {
22 #define ALL             (0xff << 24)
23 #define NONE            (0)
24 #define DISABLED        (1 << 16)
25 #define ENABLED         (0 << 16)
26 #define TRIGGER_EDGE    (0 << 15)
27 #define TRIGGER_LEVEL   (1 << 15)
28 #define POLARITY_HIGH   (0 << 13)
29 #define POLARITY_LOW    (1 << 13)
30 #define PHYSICAL_DEST   (0 << 11)
31 #define LOGICAL_DEST    (1 << 11)
32 #define ExtINT          (7 << 8)
33 #define NMI             (4 << 8)
34 #define SMI             (2 << 8)
35 #define INT             (1 << 8)
36         /* IO-APIC virtual wire mode configuration */
37         /* mask, trigger, polarity, destination, delivery, vector */
38         {   0, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT, NONE},
39         {   1, DISABLED, NONE},
40         {   2, DISABLED, NONE},
41         {   3, DISABLED, NONE},
42         {   4, DISABLED, NONE},
43         {   5, DISABLED, NONE},
44         {   6, DISABLED, NONE},
45         {   7, DISABLED, NONE},
46         {   8, DISABLED, NONE},
47         {   9, DISABLED, NONE},
48         {  10, DISABLED, NONE},
49         {  11, DISABLED, NONE},
50         {  12, DISABLED, NONE},
51         {  13, DISABLED, NONE},
52         {  14, DISABLED, NONE},
53         {  15, DISABLED, NONE},
54         {  16, DISABLED, NONE},
55         {  17, DISABLED, NONE},
56         {  18, DISABLED, NONE},
57         {  19, DISABLED, NONE},
58         {  20, DISABLED, NONE},
59         {  21, DISABLED, NONE},
60         {  22, DISABLED, NONE},
61         {  23, DISABLED, NONE},
62         /* Be careful and don't write past the end... */
63 };
64
65 static void setup_ioapic(void)
66 {
67         int i;
68         unsigned long value_low, value_high;
69         unsigned long ioapic_base = 0xfec00000;
70         volatile unsigned long *l;
71         struct ioapicreg *a = ioapicregvalues;
72
73         l = (unsigned long *) ioapic_base;
74
75         for (i = 0; i < sizeof(ioapicregvalues) / sizeof(ioapicregvalues[0]);
76              i++, a++) {
77                 l[0] = (a->reg * 2) + 0x10;
78                 l[4] = a->value_low;
79                 value_low = l[4];
80                 l[0] = (a->reg *2) + 0x11;
81                 l[4] = a->value_high;
82                 value_high = l[4];
83                 if ((i==0) && (value_low == 0xffffffff)) {
84                         printk_warning("IO APIC not responding.\n");
85                         return;
86                 }
87                 printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n", 
88                             a->reg, a->value_low, a->value_high);
89         }
90 }
91
92 static void enable_hpet(struct device *dev)
93 {
94         unsigned long hpet_address;
95         
96         pci_write_config32(dev,0xa0, 0xfed00001);
97         hpet_address=pci_read_config32(dev,0xa0)& 0xfffffffe;
98         printk_debug("enabling HPET @0x%x\n", hpet_address);
99 }
100
101 static void lpc_init(struct device *dev)
102 {
103         uint8_t byte;
104         int pwr_on=-1;
105         int nmi_option;
106
107         /* IO APIC initialization */
108         byte = pci_read_config8(dev, 0x4B);
109         byte |= 1;
110         pci_write_config8(dev, 0x4B, byte);
111         setup_ioapic();
112
113         /* posted memory write enable */
114         byte = pci_read_config8(dev, 0x46);
115         pci_write_config8(dev, 0x46, byte | (1<<0)); 
116
117         /* power after power fail */
118         byte = pci_read_config8(dev, 0x43);
119         if (pwr_on) { 
120                 byte &= ~(1<<6);
121         } else {
122                 byte |= (1<<6);
123         }
124         pci_write_config8(dev, 0x43, byte);
125
126         /* Enable Port 92 fast reset */
127         byte = pci_read_config8(dev, 0x41);
128         byte |= (1 << 5);
129         pci_write_config8(dev, 0x41, byte);
130
131         /* Enable Error reporting */
132         /* Set up sync flood detected */
133         byte = pci_read_config8(dev, 0x47);
134         byte |= (1 << 1);
135         pci_write_config8(dev, 0x47, byte);
136
137         /* Set up NMI on errors */
138         byte = pci_read_config8(dev, 0x40);
139         byte |= (1 << 1); /* clear PW2LPC error */
140         byte |= (1 << 6); /* clear LPCERR */
141         pci_write_config8(dev, 0x40, byte);
142         nmi_option = NMI_OFF;
143         get_option(&nmi_option, "nmi");
144         if (nmi_option) {                       
145                 byte |= (1 << 7); /* set NMI */
146                 pci_write_config8(dev, 0x40, byte);
147         }
148         
149         /* Initialize the real time clock */
150         rtc_init(0);
151
152         /* Initialize isa dma */
153         isa_dma_init();
154
155         /* Initialize the High Precision Event Timers */
156         enable_hpet(dev);
157 }
158
159 static void amd8111_lpc_read_resources(device_t dev)
160 {
161         unsigned int reg;
162
163         /* Get the normal pci resources of this device */
164         pci_dev_read_resources(dev);
165
166         /* Find my place in the resource list */
167         reg = dev->resources;
168
169         /* Add an extra subtractive resource for both memory and I/O */
170         dev->resource[reg].base  = 0;
171         dev->resource[reg].size  = 0;
172         dev->resource[reg].align = 0;
173         dev->resource[reg].gran  = 0;
174         dev->resource[reg].limit = 0;
175         dev->resource[reg].flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
176         dev->resource[reg].index = 0;
177         reg++;
178         
179         dev->resource[reg].base  = 0;
180         dev->resource[reg].size  = 0;
181         dev->resource[reg].align = 0;
182         dev->resource[reg].gran  = 0;
183         dev->resource[reg].limit = 0;
184         dev->resource[reg].flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
185         dev->resource[reg].index = 0;
186         reg++;
187         
188         dev->resources = reg;
189 }
190
191 static struct device_operations lpc_ops  = {
192         .read_resources   = amd8111_lpc_read_resources,
193         .set_resources    = pci_dev_set_resources,
194         .enable_resources = pci_dev_enable_resources,
195         .init             = lpc_init,
196         .scan_bus         = scan_static_bus,
197 //      .enable           = amd8111_enable,
198 };
199
200 static struct pci_driver lpc_driver __pci_driver = {
201         .ops    = &lpc_ops,
202         .vendor = PCI_VENDOR_ID_AMD,
203         .device = PCI_DEVICE_ID_AMD_8111_ISA,
204 };