55109b57be1f6452056e117dcc0adf65ebeb53d1
[coreboot.git] / src / northbridge / amd / agesa / family12 / northbridge.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2011 Advanced Micro Devices, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  */
19
20 #include <console/console.h>
21 #include <arch/io.h>
22 #include <stdint.h>
23 #include <device/device.h>
24 #include <device/pci.h>
25 #include <device/pci_ids.h>
26 #include <device/hypertransport.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <bitops.h>
30 #include <cpu/cpu.h>
31
32 #include <cpu/x86/lapic.h>
33
34 #include "chip.h"
35 #include "northbridge.h"
36 #include "SbEarly.h"
37 #include "agesawrapper.h"
38
39 //#define FX_DEVS NODE_NUMS
40 #define FX_DEVS 1
41
42 static device_t __f0_dev[FX_DEVS];
43 static device_t __f1_dev[FX_DEVS];
44 static device_t __f2_dev[FX_DEVS];
45 static device_t __f4_dev[FX_DEVS];
46 static unsigned fx_devs=0;
47
48
49 device_t get_node_pci(u32 nodeid, u32 fn)
50 {
51     return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB + nodeid, fn));
52 }
53
54
55 static void get_fx_devs(void)
56 {
57     int i;
58     for(i = 0; i < FX_DEVS; i++) {
59         __f0_dev[i] = get_node_pci(i, 0);
60         __f1_dev[i] = get_node_pci(i, 1);
61         __f2_dev[i] = get_node_pci(i, 2);
62         __f4_dev[i] = get_node_pci(i, 4);
63         if (__f0_dev[i] != NULL && __f1_dev[i] != NULL)
64             fx_devs = i+1;
65     }
66     if (__f1_dev[0] == NULL || __f0_dev[0] == NULL || fx_devs == 0) {
67         die("Cannot find 0:0x18.[0|1]\n");
68     }
69 }
70
71
72 static u32 f1_read_config32(unsigned reg)
73 {
74     if (fx_devs == 0)
75         get_fx_devs();
76     return pci_read_config32(__f1_dev[0], reg);
77 }
78
79
80 static void f1_write_config32(unsigned reg, u32 value)
81 {
82     int i;
83     if (fx_devs == 0)
84         get_fx_devs();
85     for(i = 0; i < fx_devs; i++) {
86         device_t dev;
87         dev = __f1_dev[i];
88         if (dev && dev->enabled) {
89             pci_write_config32(dev, reg, value);
90         }
91     }
92 }
93
94
95 static u32 amdfam12_nodeid(device_t dev)
96 {
97     printk(BIOS_DEBUG, "Fam12h - northbridge.c - amdfam12_nodeid\n");
98     return (dev->path.pci.devfn >> 3) - CONFIG_CDB;
99 }
100
101
102 #include "amdfam12_conf.c"
103
104
105 static void northbridge_init(device_t dev)
106 {
107   printk(BIOS_DEBUG, "Northbridge init\n");
108 }
109
110
111 static void set_vga_enable_reg(u32 nodeid, u32 linkn)
112 {
113     u32 val;
114
115     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - set_vga_enable_reg - Start.\n");
116     val =  1 | (nodeid<<4) | (linkn<<12);
117     /* it will routing (1)mmio  0xa0000:0xbffff (2) io 0x3b0:0x3bb,
118      0x3c0:0x3df */
119     f1_write_config32(0xf4, val);
120
121     printk(BIOS_DEBUG, "Fam12h - northbridge.c - set_vga_enable_reg - End.\n");
122 }
123
124
125 static int reg_useable(unsigned reg, device_t goal_dev, unsigned goal_nodeid,
126             unsigned goal_link)
127 {
128     struct resource *res;
129     unsigned nodeid, link = 0;
130     int result;
131     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - reg_useable - Start.\n");
132     res = 0;
133     for(nodeid = 0; !res && (nodeid < fx_devs); nodeid++) {
134         device_t dev;
135         dev = __f0_dev[nodeid];
136         if (!dev)
137             continue;
138         for(link = 0; !res && (link < 8); link++) {
139             res = probe_resource(dev, IOINDEX(0x1000 + reg, link));
140         }
141     }
142     result = 2;
143     if (res) {
144         result = 0;
145         if (    (goal_link == (link - 1)) &&
146             (goal_nodeid == (nodeid - 1)) &&
147             (res->flags <= 1)) {
148             result = 1;
149         }
150     }
151     printk(BIOS_DEBUG, "Fam12h - northbridge.c - reg_useable - End.\n");
152     return result;
153 }
154
155 static struct resource *amdfam12_find_iopair(device_t dev, unsigned nodeid, unsigned link)
156 {
157     struct resource *resource;
158     u32 result, reg;
159     resource = 0;
160     reg = 0;
161         result = reg_useable(0xc0, dev, nodeid, link);
162         if (result >= 1) {
163             /* I have been allocated this one */
164             reg = 0xc0;
165     }
166
167     //Ext conf space
168     if(!reg) {
169         //because of Extend conf space, we will never run out of reg, but we need one index to differ them. so same node and same link can have multi range
170         u32 index = get_io_addr_index(nodeid, link);
171         reg = 0x110+ (index<<24) + (4<<20); // index could be 0, 255
172     }
173
174         resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
175
176     return resource;
177 }
178
179 static struct resource *amdfam12_find_mempair(device_t dev, u32 nodeid, u32 link)
180 {
181     struct resource *resource;
182     u32 free_reg, reg;
183     resource = 0;
184     free_reg = 0;
185     for(reg = 0x80; reg <= 0xb8; reg += 0x8) {
186         int result;
187         result = reg_useable(reg, dev, nodeid, link);
188         if (result == 1) {
189             /* I have been allocated this one */
190             break;
191         }
192         else if (result > 1) {
193             /* I have a free register pair */
194             free_reg = reg;
195         }
196     }
197     if (reg > 0xb8) {
198         reg = free_reg;
199     }
200
201     //Ext conf space
202     if(!reg) {
203         //because of Extend conf space, we will never run out of reg,
204         // but we need one index to differ them. so same node and
205         // same link can have multi range
206         u32 index = get_mmio_addr_index(nodeid, link);
207         reg = 0x110+ (index<<24) + (6<<20); // index could be 0, 63
208
209     }
210     resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
211     return resource;
212 }
213
214
215 static void amdfam12_link_read_bases(device_t dev, u32 nodeid, u32 link)
216 {
217     struct resource *resource;
218
219     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - amdfam12_link_read_bases - Start.\n");
220     /* Initialize the io space constraints on the current bus */
221     resource = amdfam12_find_iopair(dev, nodeid, link);
222     if (resource) {
223         u32 align;
224 #if CONFIG_EXT_CONF_SUPPORT == 1
225         if((resource->index & 0x1fff) == 0x1110) { // ext
226             align = 8;
227         }
228         else
229 #endif
230             align = log2(HT_IO_HOST_ALIGN);
231         resource->base  = 0;
232         resource->size  = 0;
233         resource->align = align;
234         resource->gran  = align;
235         resource->limit = 0xffffUL;
236         resource->flags = IORESOURCE_IO | IORESOURCE_BRIDGE;
237     }
238
239     /* Initialize the prefetchable memory constraints on the current bus */
240     resource = amdfam12_find_mempair(dev, nodeid, link);
241     if (resource) {
242         resource->base = 0;
243         resource->size = 0;
244         resource->align = log2(HT_MEM_HOST_ALIGN);
245         resource->gran = log2(HT_MEM_HOST_ALIGN);
246         resource->limit = 0xffffffffffULL;
247         resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
248         resource->flags |= IORESOURCE_BRIDGE;
249
250 #if CONFIG_EXT_CONF_SUPPORT == 1
251         if((resource->index & 0x1fff) == 0x1110) { // ext
252             normalize_resource(resource);
253         }
254 #endif
255
256     }
257
258     /* Initialize the memory constraints on the current bus */
259     resource = amdfam12_find_mempair(dev, nodeid, link);
260     if (resource) {
261         resource->base = 0;
262         resource->size = 0;
263         resource->align = log2(HT_MEM_HOST_ALIGN);
264         resource->gran = log2(HT_MEM_HOST_ALIGN);
265         resource->limit = 0xffffffffffULL;
266         resource->flags = IORESOURCE_MEM | IORESOURCE_BRIDGE;
267 #if CONFIG_EXT_CONF_SUPPORT == 1
268         if((resource->index & 0x1fff) == 0x1110) { // ext
269             normalize_resource(resource);
270         }
271 #endif
272     }
273     printk(BIOS_DEBUG, "Fam12h - northbridge.c - amdfam12_link_read_bases - End.\n");
274 }
275
276 static u32 my_find_pci_tolm(struct bus *bus, u32 tolm)
277 {
278     struct resource *min;
279     min = 0;
280     search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min);
281     if (min && tolm > min->base) {
282         tolm = min->base;
283     }
284     return tolm;
285 }
286
287 #if CONFIG_HW_MEM_HOLE_SIZEK != 0
288
289 struct hw_mem_hole_info {
290     unsigned hole_startk;
291     int node_id;
292 };
293
294 static struct hw_mem_hole_info get_hw_mem_hole_info(void)
295 {
296         struct hw_mem_hole_info mem_hole;
297         int i;
298
299         mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK;
300         mem_hole.node_id = -1;
301
302         struct dram_base_mask_t d;
303         u32 hole;
304         d = get_dram_base_mask(0);
305         if(d.mask & 1) {
306             hole = pci_read_config32(__f1_dev[0], 0xf0);
307             if(hole & 1) { // we find the hole
308                 mem_hole.hole_startk = (hole & (0xff<<24)) >> 10;
309                 mem_hole.node_id = 0; // record the node No with hole
310             }
311         }
312
313 #if 0
314         // We need to double check if there is speical set on base reg and limit reg 
315             // are not continous instead of hole, it will find out it's hole_startk
316         if(mem_hole.node_id==-1) {
317             resource_t limitk_pri = 0;
318             struct dram_base_mask_t d;
319             resource_t base_k, limit_k;
320             d = get_dram_base_mask(0);
321             if(d.base & 1) {
322                 base_k = ((resource_t)(d.base & 0x1fffff00)) <<9;
323                 if(base_k <= 4 *1024 * 1024) {
324                     if(limitk_pri != base_k) { // we find the hole
325                         mem_hole.hole_startk = (unsigned)limitk_pri; // must be below 4G
326                         mem_hole.node_id = 0;
327                     }
328                 }
329
330                 limit_k = ((resource_t)((d.mask + 0x00000100) & 0x1fffff00)) << 9;
331                 limitk_pri = limit_k;
332             }
333         }
334 #endif
335         
336         return mem_hole;
337 }
338 #endif
339
340 #if CONFIG_WRITE_HIGH_TABLES==1
341 #define HIGH_TABLES_SIZE 64 // maximum size of high tables in KB
342 extern uint64_t high_tables_base, high_tables_size;
343 #endif
344
345 #if CONFIG_GFXUMA == 1
346 extern uint64_t uma_memory_base, uma_memory_size;
347
348 static void add_uma_resource(struct device *dev, int index)
349 {
350     struct resource *resource;
351
352     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - add_uma_resource - Start.\n");
353
354     resource = new_resource(dev, index);
355     resource->base = (resource_t) uma_memory_base;
356     resource->size = (resource_t) uma_memory_size;
357     resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
358         IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
359     printk(BIOS_DEBUG, "Fam12h - northbridge.c - add_uma_resource - End.\n");
360 }
361 #endif
362
363 static void read_resources(device_t dev)
364 {
365     u32 nodeid;
366     struct bus *link;
367
368     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - read_resources - Start.\n");
369
370     nodeid = amdfam12_nodeid(dev);
371     for(link = dev->link_list; link; link = link->next) {
372         if (link->children) {
373             amdfam12_link_read_bases(dev, nodeid, link->link_num);
374         }
375     }
376     printk(BIOS_DEBUG, "Fam12h - northbridge.c - read_resources - End.\n");
377 }
378
379
380 static void set_resource(device_t dev, struct resource *resource,
381                 u32 nodeid)
382 {
383     resource_t rbase, rend;
384     unsigned reg, link_num;
385     char buf[50];
386
387     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - set_resource - Start.\n");
388
389     /* Make certain the resource has actually been set */
390     if (!(resource->flags & IORESOURCE_ASSIGNED)) {
391         return;
392     }
393
394     /* If I have already stored this resource don't worry about it */
395     if (resource->flags & IORESOURCE_STORED) {
396         return;
397     }
398
399     /* Only handle PCI memory and IO resources */
400     if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
401         return;
402
403     /* Ensure I am actually looking at a resource of function 1 */
404     if ((resource->index & 0xffff) < 0x1000) {
405         return;
406     }
407     /* Get the base address */
408     rbase = resource->base;
409
410     /* Get the limit (rounded up) */
411     rend  = resource_end(resource);
412
413     /* Get the register and link */
414     reg  = resource->index & 0xfff; // 4k
415     link_num = IOINDEX_LINK(resource->index);
416
417     if (resource->flags & IORESOURCE_IO) {
418         set_io_addr_reg(dev, nodeid, link_num, reg, rbase>>8, rend>>8);
419     }
420     else if (resource->flags & IORESOURCE_MEM) {
421         set_mmio_addr_reg(nodeid, link_num, reg, (resource->index >>24), rbase>>8, rend>>8, 1) ;// [39:8]
422     }
423     resource->flags |= IORESOURCE_STORED;
424     sprintf(buf, " <node %x link %x>",
425         nodeid, link_num);
426     report_resource_stored(dev, resource, buf);
427     printk(BIOS_DEBUG, "Fam12h - northbridge.c - set_resource - End.\n");
428 }
429
430
431 #if CONFIG_CONSOLE_VGA_MULTI
432 extern device_t vga_pri;    // the primary vga device, defined in device.c
433 #endif
434
435 static void create_vga_resource(device_t dev, unsigned nodeid)
436 {
437     struct bus *link;
438
439     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - create_vga_resource - Start.\n");
440
441     /* find out which link the VGA card is connected,
442      * we only deal with the 'first' vga card */
443     for (link = dev->link_list; link; link = link->next) {
444         if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
445 #if CONFIG_CONSOLE_VGA_MULTI
446             printk(BIOS_DEBUG, "VGA: vga_pri bus num = %d bus range [%d,%d]\n", vga_pri->bus->secondary,
447                 link->secondary,link->subordinate);
448             /* We need to make sure the vga_pri is under the link */
449             if((vga_pri->bus->secondary >= link->secondary ) &&
450                 (vga_pri->bus->secondary <= link->subordinate )
451             )
452 #endif
453             break;
454         }
455     }
456
457     /* no VGA card installed */
458     if (link == NULL)
459         return;
460
461     printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, link->link_num);
462     set_vga_enable_reg(nodeid, link->link_num);
463     printk(BIOS_DEBUG, "Fam12h - northbridge.c - create_vga_resource - End.\n");
464 }
465
466
467 static void set_resources(device_t dev)
468 {
469     unsigned nodeid;
470     struct bus *bus;
471     struct resource *res;
472
473     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - set_resources - Start.\n");
474  
475     /* Find the nodeid */
476     nodeid = amdfam12_nodeid(dev);
477
478     create_vga_resource(dev, nodeid);
479
480     /* Set each resource we have found */
481     for(res = dev->resource_list; res; res = res->next) {
482         set_resource(dev, res, nodeid);
483     }
484
485     for(bus = dev->link_list; bus; bus = bus->next) {
486         if (bus->children) {
487             assign_resources(bus);
488         }
489     }
490     printk(BIOS_DEBUG, "Fam12h - northbridge.c - set_resources - End.\n");
491 }
492
493
494 /* Domain/Root Complex related code */
495
496 static void domain_read_resources(device_t dev)
497 {
498     unsigned reg;
499
500     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - domain_read_resources - Start.\n");
501
502     /* Find the already assigned resource pairs */
503     get_fx_devs();
504     for(reg = 0x80; reg <= 0xc0; reg+= 0x08) {
505         u32 base, limit;
506         base  = f1_read_config32(reg);
507         limit = f1_read_config32(reg + 0x04);
508         /* Is this register allocated? */
509         if ((base & 3) != 0) {
510             unsigned nodeid, reg_link;
511             device_t reg_dev;
512             if(reg<0xc0) { // mmio
513                 nodeid = (limit & 0xf) + (base&0x30);
514             } else { // io
515                 nodeid =  (limit & 0xf) + ((base>>4)&0x30);
516             }
517             reg_link = (limit >> 4) & 7;
518             reg_dev = __f0_dev[nodeid];
519             if (reg_dev) {
520                 /* Reserve the resource  */
521                 struct resource *res;
522                 res = new_resource(reg_dev, IOINDEX(0x1000 + reg, reg_link));
523                 if (res) {
524                     res->flags = 1;
525                 }
526             }
527         }
528     }
529     /* FIXME: do we need to check extend conf space?
530        I don't believe that much preset value */
531
532 #if CONFIG_PCI_64BIT_PREF_MEM == 0
533 //-    pci_domain_read_resources(dev);
534
535     struct resource *resource;
536         /* Initialize the system-wide I/O space constraints. */
537         resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
538     resource->base  = 0x1000;
539         resource->limit = 0xffffUL;
540         resource->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
541                      IORESOURCE_ASSIGNED;
542
543         /* Initialize the system-wide memory resources constraints. */
544         resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
545         resource->base  = 0xc0000000ULL;
546         resource->limit = 0xdfffffffULL;
547         resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
548                      IORESOURCE_ASSIGNED;
549 #else
550     struct bus *link;
551     struct resource *resource;
552     for(link=dev->link_list; link; link = link->next) {
553         /* Initialize the system wide io space constraints */
554         resource = new_resource(dev, 0|(link->link_num<<2));
555         resource->base  = 0x400;
556         resource->limit = 0xffffUL;
557         resource->flags = IORESOURCE_IO;
558
559         /* Initialize the system wide prefetchable memory resources constraints */
560         resource = new_resource(dev, 1|(link->link_num<<2));
561         resource->limit = 0xfcffffffffULL;
562         resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
563
564         /* Initialize the system wide memory resources constraints */
565         resource = new_resource(dev, 2|(link->link_num<<2));
566         resource->limit = 0xfcffffffffULL;
567         resource->flags = IORESOURCE_MEM;
568     }
569 #endif
570     printk(BIOS_DEBUG, "Fam12h - northbridge.c - domain_read_resources - End.\n");
571 }
572
573
574 static void domain_set_resources(device_t dev)
575 {
576   u32 val;
577     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - domain_set_resources - Start.\n");
578     printk(BIOS_DEBUG, "  amsr - incoming dev = %08lx\n",dev);
579
580
581 #if CONFIG_PCI_64BIT_PREF_MEM == 1
582     struct resource *io, *mem1, *mem2;
583     struct resource *res;
584 #endif
585     unsigned long mmio_basek;
586     u32 pci_tolm;
587     int i, idx;
588     struct bus *link;
589 #if CONFIG_HW_MEM_HOLE_SIZEK != 0
590     struct hw_mem_hole_info mem_hole;
591     u32 reset_memhole = 1;
592 #endif
593
594 #if CONFIG_PCI_64BIT_PREF_MEM == 1
595
596 printk(BIOS_DEBUG, "adsr - CONFIG_PCI_64BIT_PREF_MEM is true.\n");
597     for(link = dev->link_list; link; link = link->next) {
598         /* Now reallocate the pci resources memory with the
599          * highest addresses I can manage.
600          */
601         mem1 = find_resource(dev, 1|(link->link_num<<2));
602         mem2 = find_resource(dev, 2|(link->link_num<<2));
603
604         printk(BIOS_DEBUG, "base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
605             mem1->base, mem1->limit, mem1->size, mem1->align);
606         printk(BIOS_DEBUG, "base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
607             mem2->base, mem2->limit, mem2->size, mem2->align);
608
609         /* See if both resources have roughly the same limits */
610         if (((mem1->limit <= 0xffffffff) && (mem2->limit <= 0xffffffff)) ||
611             ((mem1->limit > 0xffffffff) && (mem2->limit > 0xffffffff)))
612         {
613             /* If so place the one with the most stringent alignment first
614              */
615             if (mem2->align > mem1->align) {
616                 struct resource *tmp;
617                 tmp = mem1;
618                 mem1 = mem2;
619                 mem2 = tmp;
620             }
621             /* Now place the memory as high up as it will go */
622             mem2->base = resource_max(mem2);
623             mem1->limit = mem2->base - 1;
624             mem1->base = resource_max(mem1);
625         }
626         else {
627             /* Place the resources as high up as they will go */
628             mem2->base = resource_max(mem2);
629             mem1->base = resource_max(mem1);
630         }
631
632         printk(BIOS_DEBUG, "base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
633             mem1->base, mem1->limit, mem1->size, mem1->align);
634         printk(BIOS_DEBUG, "base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
635             mem2->base, mem2->limit, mem2->size, mem2->align);
636     }
637
638     for(res = &dev->resource_list; res; res = res->next)
639     {
640         res->flags |= IORESOURCE_ASSIGNED;
641         res->flags |= IORESOURCE_STORED;
642         report_resource_stored(dev, res, "");
643     }
644 #endif
645
646     pci_tolm = 0xffffffffUL;
647     for(link = dev->link_list; link; link = link->next) {
648         pci_tolm = my_find_pci_tolm(link, pci_tolm);
649     }
650
651     // FIXME handle interleaved nodes. If you fix this here, please fix
652     // amdk8, too.
653     mmio_basek = pci_tolm >> 10;
654     /* Round mmio_basek to something the processor can support */
655     mmio_basek &= ~((1 << 6) -1);
656
657     // FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M
658     // MMIO hole. If you fix this here, please fix amdk8, too.
659     /* Round the mmio hole to 64M */
660     mmio_basek &= ~((64*1024) - 1);
661
662 #if CONFIG_HW_MEM_HOLE_SIZEK != 0
663 /* if the hw mem hole is already set in raminit stage, here we will compare
664  * mmio_basek and hole_basek. if mmio_basek is bigger that hole_basek and will
665  * use hole_basek as mmio_basek and we don't need to reset hole.
666  * otherwise We reset the hole to the mmio_basek
667  */
668
669     mem_hole = get_hw_mem_hole_info();
670
671     // Use hole_basek as mmio_basek, and we don't need to reset hole anymore
672     if ((mem_hole.node_id !=  -1) && (mmio_basek > mem_hole.hole_startk)) {
673         mmio_basek = mem_hole.hole_startk;
674         reset_memhole = 0;
675     }
676 #endif
677
678     idx = 0x10;
679
680     struct dram_base_mask_t d;
681     resource_t basek, limitk, sizek; // 4 1T
682
683     d = get_dram_base_mask(0);
684
685     if (d.mask & 1) {
686         basek = ((resource_t)(d.base)) << 8;
687         limitk = (resource_t)((d.mask << 8) | 0xFFFFFF);
688 printk(BIOS_DEBUG, "adsr: (before) basek = %llx, limitk = %llx.\n",basek,limitk);
689
690         /* Convert these values to multiples of 1K for ease of math. */
691         basek >>= 10;
692         limitk >>= 10;
693         sizek = limitk - basek + 1;
694
695 printk(BIOS_DEBUG, "adsr: (after) basek = %llx, limitk = %llx, sizek = %llx.\n",basek,limitk,sizek);
696
697         /* see if we need a hole from 0xa0000 to 0xbffff */
698         if ((basek < 640) && (sizek > 768)) {
699 printk(BIOS_DEBUG, "adsr - 0xa0000 to 0xbffff resource.\n");
700             ram_resource(dev, (idx | 0), basek, 640 - basek);
701             idx += 0x10;
702             basek = 768;
703             sizek = limitk - 768;
704         }
705
706
707 printk(BIOS_DEBUG, "adsr: mmio_basek=%08x, basek=%08x, limitk=%08x\n",  mmio_basek, basek, limitk);
708
709         /* split the region to accomodate pci memory space */
710         if ( (basek < 4*1024*1024 ) && (limitk > mmio_basek) ) {
711             if (basek <= mmio_basek) {
712                 unsigned pre_sizek;
713                 pre_sizek = mmio_basek - basek;
714                 if(pre_sizek>0) {
715                     ram_resource(dev, idx, basek, pre_sizek);
716                     idx += 0x10;
717                     sizek -= pre_sizek;
718 #if CONFIG_WRITE_HIGH_TABLES==1
719                     if (high_tables_base==0) {
720                     /* Leave some space for ACPI, PIRQ and MP tables */
721 #if CONFIG_GFXUMA == 1
722                         high_tables_base = uma_memory_base - (HIGH_TABLES_SIZE * 1024);
723 #else
724                         high_tables_base = (mmio_basek - HIGH_TABLES_SIZE) * 1024;
725 #endif
726                         high_tables_size = HIGH_TABLES_SIZE * 1024;
727                         printk(BIOS_DEBUG, " split: %dK table at =%08llx\n", HIGH_TABLES_SIZE,
728                                  high_tables_base);
729                     }
730 #endif
731                 }
732
733                 basek = mmio_basek;
734             }
735             if ((basek + sizek) <= 4*1024*1024) {
736                 sizek = 0;
737             }
738             else {
739                 basek = 4*1024*1024;
740                 sizek -= (4*1024*1024 - mmio_basek);
741             }
742         }
743
744         ram_resource(dev, (idx | 0), basek, sizek);
745         idx += 0x10;
746 #if CONFIG_WRITE_HIGH_TABLES==1
747         printk(BIOS_DEBUG, "%d: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",
748                  0, mmio_basek, basek, limitk);
749         if (high_tables_base==0) {
750         /* Leave some space for ACPI, PIRQ and MP tables */
751 #if CONFIG_GFXUMA == 1
752             high_tables_base = uma_memory_base - (HIGH_TABLES_SIZE * 1024);
753             printk(BIOS_DEBUG, "  adsr - uma_memory_base = %x.\n",uma_memory_base);
754 #else
755             high_tables_base = (limitk - HIGH_TABLES_SIZE) * 1024;
756 #endif
757             high_tables_size = HIGH_TABLES_SIZE * 1024;
758         }
759 #endif
760     }
761 printk(BIOS_DEBUG, "  adsr - mmio_basek = %x.\n",mmio_basek);
762 printk(BIOS_DEBUG, "  adsr - high_tables_size = %x.\n",high_tables_size);
763
764 #if CONFIG_GFXUMA == 1
765     printk(BIOS_DEBUG, "adsr - adding uma resource.\n");
766     add_uma_resource(dev, 7);
767 #endif
768
769     for(link = dev->link_list; link; link = link->next) {
770         if (link->children) {
771             assign_resources(link);
772         }
773     }
774 printk(BIOS_DEBUG, "  adsr - leaving this lovely routine.\n");
775     printk(BIOS_DEBUG, "Fam12h - northbridge.c - domain_set_resources - End.\n");
776 }
777
778
779 static void domain_enable_resources(device_t dev)
780 {
781 //  u32 val;
782   /* Must be called after PCI enumeration and resource allocation */
783 //  printk(BIOS_DEBUG, "\nFam12h - northbridge.c - domain_enable_resources - agesawrapper_amdinitmid - Start.\n");
784   printk(BIOS_DEBUG, "\nFam12h - northbridge.c - domain_enable_resources - Start.\n");
785 //  val = agesawrapper_amdinitmid (); 
786 //  if(val) {
787 //    printk(BIOS_DEBUG, "agesawrapper_amdinitmid failed: %x \n", val);
788 //  }
789 //  printk(BIOS_DEBUG, "Fam12h - northbridge.c - domain_enable_resources - agesawrapper_amdinitmid - End.\n");
790   printk(BIOS_DEBUG, "Fam12h - northbridge.c - domain_enable_resources - End.\n");
791 }
792
793
794 /* Bus related code */
795
796
797 static void cpu_bus_read_resources(device_t dev)
798 {
799     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - cpu_bus_read_resources - Start.\n");
800
801 #if CONFIG_MMCONF_SUPPORT
802     struct resource *resource = new_resource(dev, 0xc0010058);
803     resource->base = CONFIG_MMCONF_BASE_ADDRESS;
804     resource->size = CONFIG_MMCONF_BUS_NUMBER * 4096*256;
805     resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
806         IORESOURCE_FIXED | IORESOURCE_STORED |  IORESOURCE_ASSIGNED;
807 #endif
808     printk(BIOS_DEBUG, "Fam12h - northbridge.c - cpu_bus_read_resources - End.\n");
809 }
810
811 static void cpu_bus_set_resources(device_t dev)
812 {
813     struct resource *resource = find_resource(dev, 0xc0010058);
814
815     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - cpu_bus_set_resources - Start.\n");
816     if (resource) {
817         report_resource_stored(dev, resource, " <mmconfig>");
818     }
819     pci_dev_set_resources(dev);
820     printk(BIOS_DEBUG, "Fam12h - northbridge.c - cpu_bus_set_resources - End.\n");
821 }
822  
823 static void cpu_bus_init(device_t dev)
824 {
825     u32 val;
826
827     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - cpu_bus_init - Start.\n");
828     initialize_cpus(dev->link_list);
829
830 #if CONFIG_SOUTHBRIDGE_AMD_CIMX_SB900
831     /* Must be called after PCI enumeration and resource allocation */
832     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - cpu_bus_init - sb_After_Pci_Init - Start.\n");
833     sb_After_Pci_Init (); 
834     printk(BIOS_DEBUG, "Fam12h - northbridge.c - cpu_bus_init - sb_After_Pci_Init - End.\n");
835 #endif // #if CONFIG_SOUTHBRIDGE_AMD_CIMX_SB900
836
837 #if CONFIG_SOUTHBRIDGE_AMD_CIMX_SB900
838     /* Must be called after PCI enumeration and resource allocation */
839     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - cpu_bus_init - sb_Mid_Post_Init - Start.\n");
840     sb_Mid_Post_Init (); 
841     printk(BIOS_DEBUG, "Fam12h - northbridge.c - cpu_bus_init - sb_Mid_Post_Init - End.\n");
842 #endif // #if CONFIG_SOUTHBRIDGE_AMD_CIMX_SB900
843
844     /* Must be called after PCI enumeration and resource allocation */
845     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - cpu_bus_init - agesawrapper_amdinitmid - Start.\n");
846     val = agesawrapper_amdinitmid (); 
847     if(val) {
848         printk(BIOS_DEBUG, "agesawrapper_amdinitmid failed: %x \n", val);
849     }
850     printk(BIOS_DEBUG, "Fam12h - northbridge.c - cpu_bus_init - agesawrapper_amdinitmid - End.\n");
851     printk(BIOS_DEBUG, "Fam12h - northbridge.c - cpu_bus_init - End.\n");
852 }
853
854
855 /* North Bridge Structures */
856
857 static struct device_operations northbridge_operations = {
858     .read_resources   = read_resources,
859     .set_resources    = set_resources,
860   .enable_resources = pci_dev_enable_resources,
861   .init             = northbridge_init,
862   .enable           = 0,
863   .ops_pci          = 0,
864 };
865
866
867 static const struct pci_driver northbridge_driver __pci_driver = {
868     .ops = &northbridge_operations,
869     .vendor = PCI_VENDOR_ID_AMD,
870     .device = 0x1705,
871 };
872
873
874 struct chip_operations northbridge_amd_agesa_family12_ops = {
875     CHIP_NAME("AMD Family 12h Northbridge")
876     .enable_dev = 0,
877 };
878
879
880 /* Root Complex Structures */
881
882
883 static struct device_operations pci_domain_ops = {
884     .read_resources   = domain_read_resources,
885     .set_resources    = domain_set_resources,
886     .enable_resources = domain_enable_resources,
887     .init             = NULL,
888     .scan_bus         = pci_domain_scan_bus,
889 };
890
891
892 static struct device_operations cpu_bus_ops = {
893     .read_resources   = cpu_bus_read_resources,
894     .set_resources    = cpu_bus_set_resources,
895     .enable_resources = NULL,
896     .init             = cpu_bus_init,
897     .scan_bus         = 0,
898 };
899
900
901 static void root_complex_enable_dev(struct device *dev)
902 {
903     printk(BIOS_DEBUG, "\nFam12h - northbridge.c - root_complex_enable_dev - Start.\n");
904     /* Set the operations if it is a special bus type */
905     if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
906         dev->ops = &pci_domain_ops;
907     }
908     else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
909         dev->ops = &cpu_bus_ops;
910     }
911     printk(BIOS_DEBUG, "Fam12h - northbridge.c - root_complex_enable_dev - End.\n");
912 }
913
914
915 struct chip_operations northbridge_amd_agesa_family12_root_complex_ops = {
916     CHIP_NAME("AMD Family 12h Root Complex")
917     .enable_dev = root_complex_enable_dev,
918 };