- First pass through with with device tree enhancement merge. Most of the mechanisms...
[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 <pc80/mc146818rtc.h>
19 #include <bitops.h>
20 #include "./cpu_rev.c"
21 #include "amdk8.h"
22
23 /**
24  * @brief Read resources for AGP aperture
25  *
26  * @param 
27  *
28  * There is only one AGP aperture resource needed. The resoruce is added to
29  * the northbridge of BSP.
30  *
31  * The same trick can be used to augment legacy VGA resources which can
32  * be detect by generic pci reousrce allocator for VGA devices.
33  * BAD: it is more tricky than I think, the resource allocation code is
34  * implemented in a way to NOT DOING legacy VGA resource allcation on
35  * purpose :-(.
36  */
37 static void mcf3_read_resources(device_t dev)
38 {
39         struct resource *resource;
40         unsigned char iommu;
41         /* Read the generic PCI resources */
42         pci_dev_read_resources(dev);
43
44         /* If we are not the first processor don't allocate the gart apeture */
45         if (dev->path.u.pci.devfn != PCI_DEVFN(0x18, 0x3)) {
46                 return;
47         }
48
49         iommu = 1;
50         get_option(&iommu, "iommu");
51
52         if (iommu) {
53                 /* Add a Gart apeture resource */
54                 resource = new_resource(dev, 0x94);
55                 resource->size = iommu?AGP_APERTURE_SIZE:1;
56                 resource->align = log2(resource->size);
57                 resource->gran  = log2(resource->size);
58                 resource->limit = 0xffffffff; /* 4G */
59                 resource->flags = IORESOURCE_MEM;
60         }
61 }
62
63 static void set_agp_aperture(device_t dev)
64 {
65         struct resource *resource;
66                 
67         resource = probe_resource(dev, 0x94);
68         if (resource) {
69                 device_t pdev;
70                 uint32_t gart_base, gart_acr;
71                 /* Remember this resource has been stored */
72                 resource->flags |= IORESOURCE_STORED;
73
74                 /*Find the size of the GART aperture */
75                 gart_acr  = (0<<6)|(0<<5)|(0<<4)| ((log2(resource->size) - 25) << 1)|(0<<0);
76
77                 /* Get the base address */
78                 gart_base = ((resource->base) >> 25) & 0x00007fff;
79                 
80                 /* Update the other northbriges */
81                 pdev = 0;
82                 while (pdev = dev_find_device(PCI_VENDOR_ID_AMD, 0x1103, pdev)) {
83                         /* Store GART size but don't enable it */
84                         pci_write_config32(pdev, 0x90, gart_acr);
85
86                         /* Store the GART base address */
87                         pci_write_config32(pdev, 0x94, gart_base);
88
89                         /* Don't set the GART Table base address */
90                         pci_write_config32(pdev, 0x98, 0);
91                         
92                         /* Report the resource has been stored... */
93                         report_resource_stored(pdev, resource, " <gart>");
94                 }
95         }
96 }
97
98 static void mcf3_set_resources(device_t dev)
99 {
100         /* Set the gart apeture */
101         set_agp_aperture(dev);
102
103         /* Set the generic PCI resources */
104         pci_dev_set_resources(dev);
105 }
106
107 static void misc_control_init(struct device *dev)
108 {
109         uint32_t cmd, cmd_ref;
110         int needs_reset;
111         struct device *f0_dev, *f2_dev;
112         
113         printk_debug("NB: Function 3 Misc Control.. ");
114         needs_reset = 0;
115
116         /* Disable Machine checks from Invalid Locations.
117          * This is needed for PC backwards compatibility.
118          */
119         cmd = pci_read_config32(dev, 0x44);
120         cmd |= (1<<6) | (1<<25);
121         pci_write_config32(dev, 0x44, cmd );
122         if (is_cpu_pre_c0()) {
123
124                 /* Errata 58
125                  * Disable CPU low power states C2, C1 and throttling 
126                  */
127                 cmd = pci_read_config32(dev, 0x80);
128                 cmd &= ~(1<<0);
129                 pci_write_config32(dev, 0x80, cmd );
130                 cmd = pci_read_config32(dev, 0x84);
131                 cmd &= ~(1<<24);
132                 cmd &= ~(1<<8);
133                 pci_write_config32(dev, 0x84, cmd );
134
135                 /* Errata 66
136                  * Limit the number of downstream posted requests to 1 
137                  */
138                 cmd = pci_read_config32(dev, 0x70);
139                 if ((cmd & (3 << 0)) != 2) {
140                         cmd &= ~(3<<0);
141                         cmd |= (2<<0);
142                         pci_write_config32(dev, 0x70, cmd );
143                         needs_reset = 1;
144                 }
145                 cmd = pci_read_config32(dev, 0x7c);
146                 if ((cmd & (3 << 4)) != 0) {
147                         cmd &= ~(3<<4);
148                         cmd |= (0<<4);
149                         pci_write_config32(dev, 0x7c, cmd );
150                         needs_reset = 1;
151                 }
152                 /* Clock Power/Timing Low */
153                 cmd = pci_read_config32(dev, 0xd4);
154                 if (cmd != 0x000D0001) {
155                         cmd = 0x000D0001;
156                         pci_write_config32(dev, 0xd4, cmd);
157                         needs_reset = 1; /* Needed? */
158                 }
159         }
160         else {
161                 uint32_t dcl;
162                 f2_dev = dev_find_slot(0, dev->path.u.pci.devfn - 3 + 2);
163                 /* Errata 98 
164                  * Set Clk Ramp Hystersis to 7
165                  * Clock Power/Timing Low
166                  */
167                 cmd_ref = 0x04e20707; /* Registered */
168                 dcl = pci_read_config32(f2_dev, DRAM_CONFIG_LOW);
169                 if (dcl & DCL_UnBufDimm) {
170                         cmd_ref = 0x000D0701; /* Unbuffered */
171                 }
172                 cmd = pci_read_config32(dev, 0xd4);
173                 if(cmd != cmd_ref) {
174                         pci_write_config32(dev, 0xd4, cmd_ref );
175                         needs_reset = 1; /* Needed? */
176                 }
177         }
178 #if CONFIG_MAX_CPUS > 1 
179 /* Single CPU systems don't seem to need this. It might cause resets? (YhLu) */
180         /* Optimize the Link read pointers */
181         f0_dev = dev_find_slot(0, dev->path.u.pci.devfn - 3);
182         if (f0_dev) {
183                 int link;
184                 cmd_ref = cmd = pci_read_config32(dev, 0xdc);
185                 for(link = 0; link < 3; link++) {
186                         uint32_t link_type;
187                         unsigned reg;
188                         /* This works on an Athlon64 because unimplemented links return 0 */
189                         reg = 0x98 + (link * 0x20);
190                         link_type = pci_read_config32(f0_dev, reg);
191                         if (link_type & LinkConnected) {
192                                 cmd &= 0xff << (link *8);
193                                 /* FIXME this assumes the device on the other side is an AMD device */
194                                 cmd |= 0x25 << (link *8);
195                         }
196                 }
197                 if (cmd != cmd_ref) {
198                         pci_write_config32(dev, 0xdc, cmd);
199                         needs_reset = 1;
200                 }
201         }
202         else {
203                 printk_err("Missing f0 device!\n");
204         }
205 #endif 
206         if (needs_reset) {
207                 printk_debug("resetting cpu\n");
208                 hard_reset();
209         }
210         printk_debug("done.\n");
211 }
212
213
214 static struct device_operations mcf3_ops  = {
215         .read_resources   = mcf3_read_resources,
216         .set_resources    = mcf3_set_resources,
217         .enable_resources = pci_dev_enable_resources,
218         .init             = misc_control_init,
219         .scan_bus         = 0,
220 };
221
222 static struct pci_driver mcf3_driver __pci_driver = {
223         .ops    = &mcf3_ops,
224         .vendor = PCI_VENDOR_ID_AMD,
225         .device = 0x1103,
226 };