fixed minor bug in APG bridge code. Use AGP_APERTURE_SIZE instead of IOMMU_APERTURE_SIZE
[coreboot.git] / src / northbridge / amd / amdk8 / misc_control.c
1 /* Turn off machine check triggers when reading
2  * pci space where there are no devices.
3  * This is necessary when scaning the bus for
4  * devices which is done by the kernel
5  *
6  * written in 2003 by Eric Biederman
7  * 
8  *  - Athlon64 workarounds by Stefan Reinauer
9  *  - "reset once" logic by Yinghai Lu
10  */
11
12 #include <console/console.h>
13 #include <device/device.h>
14 #include <device/pci.h>
15 #include <device/pci_ids.h>
16 #include <device/pci_ops.h>
17 #include <part/hard_reset.h>
18 #include "./cpu_rev.c"
19 #include "amdk8.h"
20
21 static void mcf3_read_resources(device_t dev)
22 {
23         struct resource *resource;
24
25         /* Read the generic PCI resources */
26         pci_dev_read_resources(dev);
27
28         /* If we are not the first processor don't allocate the gart apeture */
29         if (dev->path.u.pci.devfn != PCI_DEVFN(0x18, 0x3)) {
30                 return;
31         }
32                 
33         /* Add a 64M Gart apeture resource */
34         if (dev->resources < MAX_RESOURCES) {
35                 resource = &dev->resource[dev->resources];
36                 dev->resources++;
37                 resource->base  = 0;
38                 resource->size  = AGP_APERTURE_SIZE;
39                 resource->align = log2(resource->size);
40                 resource->gran  = log2(resource->size);
41                 resource->limit = 0xffffffff; /* 4G */
42                 resource->flags = IORESOURCE_MEM;
43                 resource->index = 0x94;
44         } else {
45                 printk_err("%s Unexpeted resource shortage\n", dev_path(dev));
46         }
47 }
48
49 static void mcf3_set_resources(device_t dev)
50 {
51         struct resource *resource, *last;
52         last = &dev->resource[dev->resources];
53         for (resource = &dev->resource[0]; resource < last; resource++) {
54                 if (resource->index == 0x94) {
55                         device_t pdev;
56                         uint32_t base;
57                         uint32_t size;
58                         
59                         size = (0<<6)|(0<<5)|(0<<4)|
60                             ((log2(resource->size) - 25) << 1)|(0<<0);
61                         base = ((resource->base) >> 25) & 0x00007fff;
62                         pdev = 0;
63                         while (pdev = dev_find_device(PCI_VENDOR_ID_AMD, 0x1103, pdev)) {
64                                 /* I want a 64M GART apeture */
65                                 pci_write_config32(pdev, 0x90, (0<<6)|(0<<5)|(0<<4)|(1<<1)|(0<<0));
66                                 /* Store the GART base address */
67                                 pci_write_config32(pdev, 0x94, base);
68                                 /* Don't set the GART Table base address */
69                                 pci_write_config32(pdev, 0x98, 0);
70
71                                 printk_debug("%s %02x <- [0x%08lx - 0x%08lx] mem <gart>\n",
72                                              dev_path(pdev), resource->index, resource->base,
73                                              resource->base + resource->size - 1);
74                         }
75                         /* Remember this resource has been stored */
76                         resource->flags |= IORESOURCE_STORED;
77                 }
78         }
79         /* Set the generic PCI resources */
80         pci_dev_set_resources(dev);
81 }
82
83 static void misc_control_init(struct device *dev)
84 {
85         uint32_t cmd, cmd_ref;
86         int needs_reset;
87         struct device *f0_dev, *f2_dev;
88         
89         printk_debug("NB: Function 3 Misc Control.. ");
90         needs_reset = 0;
91
92         /* Disable Machine checks from Invalid Locations.
93          * This is needed for PC backwards compatibility.
94          */
95         cmd = pci_read_config32(dev, 0x44);
96         cmd |= (1<<6) | (1<<25);
97         pci_write_config32(dev, 0x44, cmd );
98         if (is_cpu_pre_c0()) {
99
100                 /* Errata 58
101                  * Disable CPU low power states C2, C1 and throttling 
102                  */
103                 cmd = pci_read_config32(dev, 0x80);
104                 cmd &= ~(1<<0);
105                 pci_write_config32(dev, 0x80, cmd );
106                 cmd = pci_read_config32(dev, 0x84);
107                 cmd &= ~(1<<24);
108                 cmd &= ~(1<<8);
109                 pci_write_config32(dev, 0x84, cmd );
110
111                 /* Errata 66
112                  * Limit the number of downstream posted requests to 1 
113                  */
114                 cmd = pci_read_config32(dev, 0x70);
115                 if ((cmd & (3 << 0)) != 2) {
116                         cmd &= ~(3<<0);
117                         cmd |= (2<<0);
118                         pci_write_config32(dev, 0x70, cmd );
119                         needs_reset = 1;
120                 }
121                 cmd = pci_read_config32(dev, 0x7c);
122                 if ((cmd & (3 << 4)) != 0) {
123                         cmd &= ~(3<<4);
124                         cmd |= (0<<4);
125                         pci_write_config32(dev, 0x7c, cmd );
126                         needs_reset = 1;
127                 }
128                 /* Clock Power/Timing Low */
129                 cmd = pci_read_config32(dev, 0xd4);
130                 if (cmd != 0x000D0001) {
131                         cmd = 0x000D0001;
132                         pci_write_config32(dev, 0xd4, cmd);
133                         needs_reset = 1; /* Needed? */
134                 }
135         }
136         else {
137                 uint32_t dcl;
138                 f2_dev = dev_find_slot(0, dev->path.u.pci.devfn - 3 + 2);
139                 /* Errata 98 
140                  * Set Clk Ramp Hystersis to 7
141                  * Clock Power/Timing Low
142                  */
143                 cmd_ref = 0x04e20707; /* Registered */
144                 dcl = pci_read_config32(f2_dev, DRAM_CONFIG_LOW);
145                 if (dcl & DCL_UnBufDimm) {
146                         cmd_ref = 0x000D0701; /* Unbuffered */
147                 }
148                 cmd = pci_read_config32(dev, 0xd4);
149                 if(cmd != cmd_ref) {
150                         pci_write_config32(dev, 0xd4, cmd_ref );
151                         needs_reset = 1; /* Needed? */
152                 }
153         }
154 #if CONFIG_MAX_CPUS > 1 
155 /* Single CPU systems don't seem to need this. It might cause resets? (YhLu) */
156         /* Optimize the Link read pointers */
157         f0_dev = dev_find_slot(0, dev->path.u.pci.devfn - 3);
158         if (f0_dev) {
159                 int link;
160                 cmd_ref = cmd = pci_read_config32(dev, 0xdc);
161                 for(link = 0; link < 3; link++) {
162                         uint32_t link_type;
163                         unsigned reg;
164                         /* This works on an Athlon64 because unimplemented links return 0 */
165                         reg = 0x98 + (link * 0x20);
166                         link_type = pci_read_config32(f0_dev, reg);
167                         if (link_type & LinkConnected) {
168                                 cmd &= 0xff << (link *8);
169                                 /* FIXME this assumes the device on the other side is an AMD device */
170                                 cmd |= 0x25 << (link *8);
171                         }
172                 }
173                 if (cmd != cmd_ref) {
174                         pci_write_config32(dev, 0xdc, cmd);
175                         needs_reset = 1;
176                 }
177         }
178         else {
179                 printk_err("Missing f0 device!\n");
180         }
181 #endif 
182         if (needs_reset) {
183                 printk_debug("resetting cpu\n");
184                 hard_reset();
185         }
186         printk_debug("done.\n");
187 }
188
189
190 static struct device_operations mcf3_ops  = {
191         .read_resources   = mcf3_read_resources,
192         .set_resources    = mcf3_set_resources,
193         .enable_resources = pci_dev_enable_resources,
194         .init             = misc_control_init,
195         .scan_bus         = 0,
196 };
197
198 static struct pci_driver mcf3_driver __pci_driver = {
199         .ops    = &mcf3_ops,
200         .vendor = PCI_VENDOR_ID_AMD,
201         .device = 0x1103,
202 };