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