Add constants for fast path resume copying
[coreboot.git] / src / northbridge / intel / e7520 / northbridge.c
1 #include <console/console.h>
2 #include <arch/io.h>
3 #include <stdint.h>
4 #include <device/device.h>
5 #include <device/pci.h>
6 #include <device/pci_ids.h>
7 #include <device/hypertransport.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <bitops.h>
11 #include <cpu/cpu.h>
12 #include "chip.h"
13 #include "northbridge.h"
14 #include "e7520.h"
15
16
17 static unsigned int max_bus;
18
19 #if CONFIG_WRITE_HIGH_TABLES==1
20 #include <cbmem.h>
21 #endif
22
23 static void pci_domain_set_resources(device_t dev)
24 {
25         device_t mc_dev;
26         uint32_t pci_tolm;
27
28         pci_tolm = find_pci_tolm(dev->link_list);
29
30 #if 1
31         printk(BIOS_DEBUG, "PCI mem marker = %x\n", pci_tolm);
32 #endif
33         /* FIXME Me temporary hack */
34         if(pci_tolm > 0xe0000000)
35                 pci_tolm = 0xe0000000;
36         /* Ensure pci_tolm is 128M aligned */
37         pci_tolm &= 0xf8000000;
38         mc_dev = dev->link_list->children;
39         if (mc_dev) {
40                 /* Figure out which areas are/should be occupied by RAM.
41                  * This is all computed in kilobytes and converted to/from
42                  * the memory controller right at the edges.
43                  * Having different variables in different units is
44                  * too confusing to get right.  Kilobytes are good up to
45                  * 4 Terabytes of RAM...
46                  */
47                 uint16_t tolm_r, remapbase_r, remaplimit_r, remapoffset_r;
48                 unsigned long tomk, tolmk;
49                 unsigned long remapbasek, remaplimitk, remapoffsetk;
50
51                 /* Get the Top of Memory address, units are 128M */
52                 tomk = ((unsigned long)pci_read_config16(mc_dev, TOM)) << 17;
53                 /* Compute the Top of Low Memory */
54                 tolmk = (pci_tolm  & 0xf8000000) >> 10;
55
56                 if (tolmk >= tomk) {
57                         /* The PCI hole does not overlap memory
58                          * we won't use the remap window.
59                          */
60                         tolmk = tomk;
61                         remapbasek   = 0x3ff << 16;
62                         remaplimitk  = 0 << 16;
63                         remapoffsetk = 0 << 16;
64                 }
65                 else {
66                         /* The PCI memory hole overlaps memory
67                          * setup the remap window.
68                          */
69                         /* Find the bottom of the remap window
70                          * is it above 4G?
71                          */
72                         remapbasek = 4*1024*1024;
73                         if (tomk > remapbasek) {
74                                 remapbasek = tomk;
75                         }
76                         /* Find the limit of the remap window */
77                         remaplimitk  = (remapbasek + (4*1024*1024 - tolmk) - (1 << 16));
78                         /* Find the offset of the remap window from tolm */
79                         remapoffsetk = remapbasek - tolmk;
80                 }
81                 /* Write the ram configruation registers,
82                  * preserving the reserved bits.
83                  */
84                 tolm_r = pci_read_config16(mc_dev, 0xc4);
85                 tolm_r = ((tolmk >> 17) << 11) | (tolm_r & 0x7ff);
86                 pci_write_config16(mc_dev, 0xc4, tolm_r);
87
88                 remapbase_r = pci_read_config16(mc_dev, 0xc6);
89                 remapbase_r = (remapbasek >> 16) | (remapbase_r & 0xfc00);
90                 pci_write_config16(mc_dev, 0xc6, remapbase_r);
91
92                 remaplimit_r = pci_read_config16(mc_dev, 0xc8);
93                 remaplimit_r = (remaplimitk >> 16) | (remaplimit_r & 0xfc00);
94                 pci_write_config16(mc_dev, 0xc8, remaplimit_r);
95
96                 remapoffset_r = pci_read_config16(mc_dev, 0xca);
97                 remapoffset_r = (remapoffsetk >> 16) | (remapoffset_r & 0xfc00);
98                 pci_write_config16(mc_dev, 0xca, remapoffset_r);
99
100                 /* Report the memory regions */
101                 ram_resource(dev, 3,   0, 640);
102                 ram_resource(dev, 4, 768, (tolmk - 768));
103                 if (tomk > 4*1024*1024) {
104                         ram_resource(dev, 5, 4096*1024, tomk - 4*1024*1024);
105                 }
106                 if (remaplimitk >= remapbasek) {
107                         ram_resource(dev, 6, remapbasek,
108                                 (remaplimitk + 64*1024) - remapbasek);
109                 }
110
111 #if CONFIG_WRITE_HIGH_TABLES==1
112                 /* Leave some space for ACPI, PIRQ and MP tables */
113                 high_tables_base = (tolmk * 1024) - HIGH_MEMORY_SIZE;
114                 high_tables_size = HIGH_MEMORY_SIZE;
115 #endif
116         }
117         assign_resources(dev->link_list);
118 }
119
120 static u32 e7520_domain_scan_bus(device_t dev, u32 max)
121 {
122         max_bus = pci_domain_scan_bus(dev, max);
123         return max_bus;
124 }
125
126 static struct device_operations pci_domain_ops = {
127         .read_resources   = pci_domain_read_resources,
128         .set_resources    = pci_domain_set_resources,
129         .enable_resources = NULL,
130         .init             = NULL,
131         .scan_bus         = e7520_domain_scan_bus,
132         .ops_pci_bus      = &pci_cf8_conf1, /* Do we want to use the memory mapped space here? */
133 };
134
135 static void mc_read_resources(device_t dev)
136 {
137         struct resource *resource;
138
139         pci_dev_read_resources(dev);
140
141         resource = new_resource(dev, 0xcf);
142         resource->base = 0xe0000000;
143         resource->size = max_bus * 4096*256;
144         resource->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |  IORESOURCE_ASSIGNED;
145 }
146
147 static void mc_set_resources(device_t dev)
148 {
149         struct resource *resource;
150
151         resource = find_resource(dev, 0xcf);
152         if (resource) {
153                 report_resource_stored(dev, resource, "<mmconfig>");
154         }
155         pci_dev_set_resources(dev);
156 }
157
158 static void intel_set_subsystem(device_t dev, unsigned vendor, unsigned device)
159 {
160         pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
161                 ((device & 0xffff) << 16) | (vendor & 0xffff));
162 }
163
164 static struct pci_operations intel_pci_ops = {
165         .set_subsystem = intel_set_subsystem,
166 };
167
168 static struct device_operations mc_ops = {
169         .read_resources   = mc_read_resources,
170         .set_resources    = mc_set_resources,
171         .enable_resources = pci_dev_enable_resources,
172         .init             = 0,
173         .scan_bus         = 0,
174         .ops_pci          = &intel_pci_ops,
175 };
176
177 static const struct pci_driver mc_driver __pci_driver = {
178         .ops = &mc_ops,
179         .vendor = PCI_VENDOR_ID_INTEL,
180         .device = 0x3590,
181 };
182
183 static void cpu_bus_init(device_t dev)
184 {
185         initialize_cpus(dev->link_list);
186 }
187
188 static void cpu_bus_noop(device_t dev)
189 {
190 }
191
192 static struct device_operations cpu_bus_ops = {
193         .read_resources   = cpu_bus_noop,
194         .set_resources    = cpu_bus_noop,
195         .enable_resources = cpu_bus_noop,
196         .init             = cpu_bus_init,
197         .scan_bus         = 0,
198 };
199
200
201 static void enable_dev(device_t dev)
202 {
203         /* Set the operations if it is a special bus type */
204         if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
205                 dev->ops = &pci_domain_ops;
206         }
207         else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
208                 dev->ops = &cpu_bus_ops;
209         }
210 }
211
212 struct chip_operations northbridge_intel_e7520_ops = {
213         CHIP_NAME("Intel E7520 Northbridge")
214         .enable_dev = enable_dev,
215 };