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