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