*** empty log message ***
[coreboot.git] / src / northbridge / intel / e7501 / northbridge.c
1 #include <console/console.h>
2 #include <arch/io.h>
3 #include <stdint.h>
4 #include <mem.h>
5 #include <part/sizeram.h>
6 #include <device/device.h>
7 #include <device/pci.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <bitops.h>
11 #include "chip.h"
12 #if 0
13 struct mem_range *sizeram(void)
14 {
15         static struct mem_range mem[4];
16         /* the units of tolm are 64 KB */
17         /* the units of drb16 are 64 MB */
18         uint16_t tolm, remapbase, remaplimit, drb16;
19         uint16_t tolm_r, remapbase_r, remaplimit_r;
20         uint8_t  drb;
21         int remap_high;
22         device_t dev;
23
24         dev = dev_find_slot(0, 0); // d0f0
25         if (!dev) {
26                 printk_err("Cannot find PCI: 0:0\n");
27                 return 0;
28         }
29         
30         /* Calculate and report the top of low memory and 
31          * any remapping.
32          */
33         /* Test if the remap memory high option is set */
34         remap_high = 0;
35 //        if(get_option(&remap_high, "remap_memory_high")){
36 //                remap_high = 0;
37 //        }
38         printk_debug("remap_high is %d\n", remap_high);
39         /* get out the value of the highest DRB. This tells the end of 
40          * physical memory. The units are ticks of 64 MB i.e. 1 means
41          * 64 MB. 
42          */
43         drb = pci_read_config8(dev, 0x67);
44         drb16 = (uint16_t)drb;
45         if(remap_high && (drb16 > 0x08)) {
46                 /* We only come here if we have at least 512MB of memory,
47                  * so it is safe to hard code tolm.
48                  * 0x2000 means 512MB 
49                  */
50
51                 tolm = 0x2000;
52                 /* i.e 0x40 * 0x40 is 0x1000 which is 4 GB */
53                 if(drb16 > 0x0040) {
54                         /* There is more than 4GB of memory put
55                          * the remap window at the end of ram.
56                          */
57                         remapbase = drb16;
58                         remaplimit = remapbase + 0x38;
59                 }
60                 else {
61                         remapbase = 0x0040;
62                         remaplimit = remapbase + (drb16-8);
63                 }
64         }
65         else {
66                 tolm = (uint16_t)((dev_root.resource[1].base >> 16)&0x0f800);
67                 if((tolm>>8) >= (drb16<<2)) {
68                         tolm = (drb16<<10);
69                         remapbase = 0x3ff;
70                         remaplimit = 0;
71                 }
72                 else {
73                         remapbase = drb16;
74                         remaplimit = remapbase + ((0x0040-(tolm>>10))-1);
75                 }
76         }
77         /* Write the ram configruation registers,
78          * preserving the reserved bits.
79          */
80         tolm_r = pci_read_config16(dev, 0xc4);
81         tolm |= (tolm_r & 0x7ff); 
82         pci_write_config16(dev, 0xc4, tolm);
83         remapbase_r = pci_read_config16(dev, 0xc6);
84         remapbase |= (remapbase_r & 0xfc00);
85         pci_write_config16(dev, 0xc6, remapbase);
86         remaplimit_r = pci_read_config16(dev, 0xc8);
87         remaplimit |= (remaplimit_r & 0xfc00);
88         pci_write_config16(dev, 0xc8, remaplimit);
89
90 #if 0
91     printk_debug("mem info tolm = %x, drb = %x, pci_memory_base = %x, remap = %x-%x\n",tolm,drb,pci_memory_base,remapbase,remaplimit);
92 #endif
93         
94         mem[0].basek = 0;
95         mem[0].sizek = 640;
96         mem[1].basek = 768;
97         /* Convert size in 64K bytes to size in K bytes */
98         mem[1].sizek = (tolm << 6) - mem[1].basek;
99         mem[2].basek = 0;
100         mem[2].sizek = 0;
101         if ((drb << 16) > (tolm << 6)) {
102                 /* We don't need to consider the remap window
103                  * here because we put it immediately after the
104                  * rest of ram.
105                  * All we must do is calculate the amount
106                  * of unused memory and report it at 4GB.
107                  */
108                 mem[2].basek = 4096*1024;
109                 mem[2].sizek = (drb << 16) - (tolm << 6);
110         }
111         mem[3].basek = 0;
112         mem[3].sizek = 0;
113         
114         return mem;
115 }
116 #endif
117
118 #define BRIDGE_IO_MASK (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH)
119
120 static void pci_domain_read_resources(device_t dev)
121 {
122         struct resource *resource;
123         unsigned reg;
124
125         /* Initialize the system wide io space constraints */
126         resource = new_resource(dev, 0);
127         resource->base  = 0x400;
128         resource->limit = 0xffffUL;
129         resource->flags = IORESOURCE_IO;
130         compute_allocate_resource(&dev->link[0], resource,
131                 IORESOURCE_IO, IORESOURCE_IO);
132
133         /* Initialize the system wide prefetchable memory resources constraints */
134         resource = new_resource(dev, 1);
135         resource->limit = 0xfcffffffffULL;
136         resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
137         compute_allocate_resource(&dev->link[0], resource,
138                 IORESOURCE_MEM | IORESOURCE_PREFETCH,
139                 IORESOURCE_MEM | IORESOURCE_PREFETCH);
140
141         /* Initialize the system wide memory resources constraints */
142         resource = new_resource(dev, 2);
143         resource->limit = 0xfcffffffffULL;
144         resource->flags = IORESOURCE_MEM;
145         compute_allocate_resource(&dev->link[0], resource,
146                 IORESOURCE_MEM | IORESOURCE_PREFETCH,
147                 IORESOURCE_MEM);
148 }
149
150 static void ram_resource(device_t dev, unsigned long index,
151         unsigned long basek, unsigned long sizek)
152 {
153         struct resource *resource;
154
155         if (!sizek) {
156                 return;
157         }
158         resource = new_resource(dev, index);
159         resource->base  = ((resource_t)basek) << 10;
160         resource->size  = ((resource_t)sizek) << 10;
161         resource->flags =  IORESOURCE_MEM | IORESOURCE_CACHEABLE | \
162                 IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
163 }
164
165 static void pci_domain_set_resources(device_t dev)
166 {
167         struct resource *io, *mem1, *mem2;
168         struct resource *resource, *last;
169         unsigned long mmio_basek;
170         uint32_t pci_tolm;
171         int idx;
172         uint8_t  drb;
173         unsigned basek, sizek;
174         device_t dev_memctrl;
175
176 #if 0
177         /* Place the IO devices somewhere safe */
178         io = find_resource(dev, 0);
179         io->base = DEVICE_IO_START;
180 #endif
181 #if 1
182         /* Now reallocate the pci resources memory with the
183          * highest addresses I can manage.
184          */
185         mem1 = find_resource(dev, 1);
186         mem2 = find_resource(dev, 2);
187
188 #if 1
189                 printk_debug("base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
190                         mem1->base, mem1->limit, mem1->size, mem1->align);
191                 printk_debug("base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
192                         mem2->base, mem2->limit, mem2->size, mem2->align);
193 #endif
194
195         /* See if both resources have roughly the same limits */
196         if (((mem1->limit <= 0xffffffff) && (mem2->limit <= 0xffffffff)) ||
197                 ((mem1->limit > 0xffffffff) && (mem2->limit > 0xffffffff)))
198         {
199                 /* If so place the one with the most stringent alignment first
200                  */
201                 if (mem2->align > mem1->align) {
202                         struct resource *tmp;
203                         tmp = mem1;
204                         mem1 = mem2;
205                         mem2 = tmp;
206                 }
207                 /* Now place the memory as high up as it will go */
208                 mem2->base = resource_max(mem2);
209                 mem1->limit = mem2->base - 1;
210                 mem1->base = resource_max(mem1);
211         }
212         else {
213                 /* Place the resources as high up as they will go */
214                 mem2->base = resource_max(mem2);
215                 mem1->base = resource_max(mem1);
216         }
217
218 #if 1
219                 printk_debug("base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
220                         mem1->base, mem1->limit, mem1->size, mem1->align);
221                 printk_debug("base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
222                         mem2->base, mem2->limit, mem2->size, mem2->align);
223 #endif
224 #endif
225         pci_tolm = 0xffffffffUL;
226         last = &dev->resource[dev->resources];
227         for(resource = &dev->resource[0]; resource < last; resource++)
228         {
229 #if 1
230                 resource->flags |= IORESOURCE_ASSIGNED;
231                 resource->flags &= ~IORESOURCE_STORED;
232 #endif
233                 compute_allocate_resource(&dev->link[0], resource,
234                         BRIDGE_IO_MASK, resource->flags & BRIDGE_IO_MASK);
235
236                 resource->flags |= IORESOURCE_STORED;
237                 report_resource_stored(dev, resource, "");
238
239                 if ((resource->flags & IORESOURCE_MEM) &&
240                         (pci_tolm > resource->base))
241                 {
242                         pci_tolm = resource->base;
243                 }
244         }
245
246 #warning "FIXME handle interleaved nodes"
247         mmio_basek = pci_tolm >> 10;
248         /* Round mmio_basek to something the processor can support */
249         mmio_basek &= ~((1 << 6) -1);
250
251 #if 1
252 #warning "FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M MMIO hole"
253         /* Round the mmio hold to 64M */
254         mmio_basek &= ~((64*1024) - 1);
255 #endif
256
257         dev_memctrl = dev_find_slot(0, 0); // d0f0
258         drb = pci_read_config8(dev_memctrl, 0x67);
259
260         idx = 10;
261
262         basek = 0;
263         sizek = 640;
264         ram_resource(dev, idx++, basek, sizek);
265
266         basek = 768;
267         sizek = mmio_basek - basek;
268         ram_resource(dev, idx++, basek, sizek);
269
270         if ((drb << 16) > mmio_basek) {
271                 /* We don't need to consider the remap window
272                  * here because we put it immediately after the
273                  * rest of ram.
274                  * All we must do is calculate the amount
275                  * of unused memory and report it at 4GB.
276                  */
277                 basek = 4096*1024;
278                 sizek = (drb << 16) - mmio_basek;
279                 ram_resource(dev, idx++, basek, sizek);
280         }
281
282         assign_resources(&dev->link[0]);
283 }
284
285 static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
286 {
287         max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
288         return max;
289 }
290
291 static struct device_operations pci_domain_ops = {
292         .read_resources   = pci_domain_read_resources,
293         .set_resources    = pci_domain_set_resources,
294         .enable_resources = enable_childrens_resources,
295         .init             = 0,
296         .scan_bus         = pci_domain_scan_bus,
297 };  
298
299 static unsigned int cpu_bus_scan(device_t dev, unsigned int max)
300 {
301         struct bus *cpu_bus;
302         unsigned reg;
303         int i;
304
305         /* Find which cpus are present */
306         cpu_bus = &dev->link[0];
307         for(i = 0; i < 7; i+=6) {
308                 device_t dev, cpu;
309                 struct device_path cpu_path;
310 #if 0
311 //How to identify Intel CPU
312                 /* Find the cpu's memory controller */
313                 dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 0));
314 #endif
315
316                 /* Build the cpu device path */
317                 cpu_path.type = DEVICE_PATH_APIC;
318                 cpu_path.u.apic.apic_id = i;
319
320                 /* See if I can find the cpu */
321                 cpu = find_dev_path(cpu_bus, &cpu_path);
322 #if 0
323                 /* Enable the cpu if I have the processor */
324                 if (dev && dev->enabled) {
325                         if (!cpu) {
326                                 cpu = alloc_dev(cpu_bus, &cpu_path);
327                         }
328                         if (cpu) {
329                                 cpu->enabled = 1;
330                         }
331                 }
332
333                 /* Disable the cpu if I don't have the processor */
334                 if (cpu && (!dev || !dev->enabled)) {
335                         cpu->enabled = 0;
336                 }
337 #else
338                 cpu->enabled = 1;
339 #endif
340                 /* Report what I have done */
341                 if (cpu) {
342                         printk_debug("CPU: %s %s\n",
343                                 dev_path(cpu), cpu->enabled?"enabled":"disabled");
344                 }
345         }
346         return max;
347 }
348
349 static void cpu_bus_init(device_t dev)
350 {
351         initialize_cpus(&dev->link[0]);
352 }
353
354 static void cpu_bus_noop(device_t dev)
355 {
356 }
357
358 static struct device_operations cpu_bus_ops = {
359         .read_resources   = cpu_bus_noop,
360         .set_resources    = cpu_bus_noop,
361         .enable_resources = cpu_bus_noop,
362         .init             = cpu_bus_init,
363         .scan_bus         = cpu_bus_scan,
364 };
365
366 static void enable_dev(struct device *dev)
367 {
368         struct device_path path;
369
370         /* Set the operations if it is a special bus type */
371         if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
372                 dev->ops = &pci_domain_ops;
373         }
374         else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
375                 dev->ops = &cpu_bus_ops;
376         }
377 }
378 struct chip_operations northbridge_intel_e7501_ops = {
379         .name      = "intel E7501 Northbridge",
380         .enable_dev = enable_dev,
381 };