b0c1672f5db76f2b3d9a9fc3069ff987632b964e
[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
10
11 struct ioapicreg {
12         unsigned int reg;
13         unsigned int value_low, value_high;
14 };
15
16 static struct ioapicreg ioapicregvalues[] = {
17 #define ALL             (0xff << 24)
18 #define NONE            (0)
19 #define DISABLED        (1 << 16)
20 #define ENABLED         (0 << 16)
21 #define TRIGGER_EDGE    (0 << 15)
22 #define TRIGGER_LEVEL   (1 << 15)
23 #define POLARITY_HIGH   (0 << 13)
24 #define POLARITY_LOW    (1 << 13)
25 #define PHYSICAL_DEST   (0 << 11)
26 #define LOGICAL_DEST    (1 << 11)
27 #define ExtINT          (7 << 8)
28 #define NMI             (4 << 8)
29 #define SMI             (2 << 8)
30 #define INT             (1 << 8)
31         /* IO-APIC virtual wire mode configuration */
32         /* mask, trigger, polarity, destination, delivery, vector */
33         {   0, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT, NONE},
34         {   1, DISABLED, NONE},
35         {   2, DISABLED, NONE},
36         {   3, DISABLED, NONE},
37         {   4, DISABLED, NONE},
38         {   5, DISABLED, NONE},
39         {   6, DISABLED, NONE},
40         {   7, DISABLED, NONE},
41         {   8, DISABLED, NONE},
42         {   9, DISABLED, NONE},
43         {  10, DISABLED, NONE},
44         {  11, DISABLED, NONE},
45         {  12, DISABLED, NONE},
46         {  13, DISABLED, NONE},
47         {  14, DISABLED, NONE},
48         {  15, DISABLED, NONE},
49         {  16, DISABLED, NONE},
50         {  17, DISABLED, NONE},
51         {  18, DISABLED, NONE},
52         {  19, DISABLED, NONE},
53         {  20, DISABLED, NONE},
54         {  21, DISABLED, NONE},
55         {  22, DISABLED, NONE},
56         {  23, DISABLED, NONE},
57         /* Be careful and don't write past the end... */
58 };
59
60 static void setup_ioapic(void)
61 {
62         int i;
63         unsigned long value_low, value_high;
64         unsigned long ioapic_base = 0xfec00000;
65         volatile unsigned long *l;
66         struct ioapicreg *a = ioapicregvalues;
67
68         l = (unsigned long *) ioapic_base;
69
70         for (i = 0; i < sizeof(ioapicregvalues) / sizeof(ioapicregvalues[0]);
71              i++, a++) {
72                 l[0] = (a->reg * 2) + 0x10;
73                 l[4] = a->value_low;
74                 value_low = l[4];
75                 l[0] = (a->reg *2) + 0x11;
76                 l[4] = a->value_high;
77                 value_high = l[4];
78                 if ((i==0) && (value_low == 0xffffffff)) {
79                         printk_warning("IO APIC not responding.\n");
80                         return;
81                 }
82                 printk_spew("for IRQ, reg 0x%08x value 0x%08x 0x%08x\n", 
83                         a->reg, a->value_low, a->value_high);
84         }
85 }
86
87 static void lpc_init(struct device *dev)
88 {
89         uint8_t byte;
90         uint16_t word;
91         int pwr_on=-1;
92
93         printk_debug("lpc_init\n");
94
95         /* IO APIC initialization */
96         byte = pci_read_config8(dev, 0x4B);
97         byte |= 1;
98         pci_write_config8(dev, 0x4B, byte);
99         setup_ioapic();
100
101         /* posted memory write enable */
102         byte = pci_read_config8(dev, 0x46);
103         pci_write_config8(dev, 0x46, byte | (1<<0));
104
105 //BY LYH
106         /* Disable AC97 and Ethernet */
107         word = pci_read_config16(dev, 0x48);
108         pci_write_config16(dev, 0x48, word & ~((1<<5)|(1<<6)|(1<<9)));
109 //BY LYH END
110  
111
112         /* power after power fail */
113         byte = pci_read_config8(dev, 0x43);
114         if (pwr_on) { 
115                 byte &= ~(1<<6);
116         } else {
117                 byte |= (1<<6);
118         }
119         pci_write_config8(dev, 0x43, byte);
120
121
122 }
123
124 static void amd8111_lpc_read_resources(device_t dev)
125 {
126         unsigned int reg;
127
128         /* Get the normal pci resources of this device */
129         pci_dev_read_resources(dev);
130
131         /* Find my place in the resource list */
132         reg = dev->resources;
133
134         /* Add an extra subtractive resource for both memory and I/O */
135         dev->resource[reg].base  = 0;
136         dev->resource[reg].size  = 0;
137         dev->resource[reg].align = 0;
138         dev->resource[reg].gran  = 0;
139         dev->resource[reg].limit = 0;
140         dev->resource[reg].flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_SET;
141         dev->resource[reg].index = 0;
142         reg++;
143         
144         dev->resource[reg].base  = 0;
145         dev->resource[reg].size  = 0;
146         dev->resource[reg].align = 0;
147         dev->resource[reg].gran  = 0;
148         dev->resource[reg].limit = 0;
149         dev->resource[reg].flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_SET;
150         dev->resource[reg].index = 0;
151         reg++;
152         
153         dev->resources = reg;
154 }
155
156 static struct device_operations lpc_ops  = {
157         .read_resources   = amd8111_lpc_read_resources,
158         .set_resources    = pci_dev_set_resources,
159         .enable_resources = pci_dev_enable_resources,
160         .init             = lpc_init,
161         .scan_bus         = walk_static_devices,
162 };
163
164 static struct pci_driver lpc_driver __pci_driver = {
165         .ops    = &lpc_ops,
166         .vendor = PCI_VENDOR_ID_AMD,
167         .device = PCI_DEVICE_ID_AMD_8111_ISA,
168 };