blob: 9f2555f78e8e822891a4625354b96d937998d15f [file] [log] [blame]
efdesign98b58640c2011-07-13 17:49:25 -07001/*
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
Patrick Georgib890a122015-03-26 15:17:45 +010017 * Foundation, Inc.
efdesign98b58640c2011-07-13 17:49:25 -070018 */
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>
Ronald G. Minnich5079a0d2012-11-27 11:32:38 -080029#include <lib.h>
efdesign98b58640c2011-07-13 17:49:25 -070030#include <cpu/cpu.h>
31#include <cpu/x86/lapic.h>
Stefan Reinauercc6c6152012-03-16 10:19:51 -070032#include <cbmem.h>
efdesign98b58640c2011-07-13 17:49:25 -070033
Patrick Georgie1667822012-05-05 15:29:32 +020034#if CONFIG_LOGICAL_CPUS
efdesign98b58640c2011-07-13 17:49:25 -070035#include <pc80/mc146818rtc.h>
36#endif
37
38#include <cpu/amd/amdfam10_sysconf.h>
39#include <Porting.h>
40#include <AGESA.h>
41#include <Options.h>
efdesign98b58640c2011-07-13 17:49:25 -070042#include "amdfam10.h"
efdesign98b58640c2011-07-13 17:49:25 -070043
44extern uint32_t agesawrapper_amdinitmid(void);
45
46typedef struct amdfam10_sysconf_t sys_info_conf_t;
47typedef struct dram_base_mask {
48 u32 base; //[47:27] at [28:8]
49 u32 mask; //[47:27] at [28:8] and enable at bit 0
50} dram_base_mask_t;
51
52
53struct amdfam10_sysconf_t sysconf;
54static device_t __f0_dev[NODE_NUMS];
55static device_t __f1_dev[NODE_NUMS];
56static device_t __f2_dev[NODE_NUMS];
57static device_t __f4_dev[NODE_NUMS];
58static unsigned fx_devs = 0;
59
efdesign98b58640c2011-07-13 17:49:25 -070060static dram_base_mask_t get_dram_base_mask(u32 nodeid)
61{
62 device_t dev;
63 dram_base_mask_t d;
64 dev = __f1_dev[0];
65
efdesign98b58640c2011-07-13 17:49:25 -070066 u32 temp;
67 temp = pci_read_config32(dev, 0x44 + (nodeid << 3)); //[39:24] at [31:16]
68 d.mask = ((temp & 0xfff80000)>>(8+3)); // mask out DramMask [26:24] too
69 temp = pci_read_config32(dev, 0x144 + (nodeid <<3)) & 0xff; //[47:40] at [7:0]
70 d.mask |= temp<<21;
71
72 temp = pci_read_config32(dev, 0x40 + (nodeid << 3)); //[39:24] at [31:16]
73 d.mask |= (temp & 1); // enable bit
74
75 d.base = ((temp & 0xfff80000)>>(8+3)); // mask out DramBase [26:24) too
76 temp = pci_read_config32(dev, 0x140 + (nodeid <<3)) & 0xff; //[47:40] at [7:0]
77 d.base |= temp<<21;
efdesign98b58640c2011-07-13 17:49:25 -070078 return d;
79}
80
efdesign98b58640c2011-07-13 17:49:25 -070081#if CONFIG_PCI_BUS_SEGN_BITS
82static u32 check_segn(device_t dev, u32 segbusn, u32 nodes,
83 sys_info_conf_t *sysinfo)
84{
85 //check segbusn here, We need every node have the same segn
86 if ((segbusn & 0xff)>(0xe0-1)) {// use next segn
87 u32 segn = (segbusn >> 8) & 0x0f;
88 segn++;
89 segbusn = segn<<8;
90 }
91 if (segbusn>>8) {
92 u32 val;
93 val = pci_read_config32(dev, 0x160);
94 val &= ~(0xf<<25);
95 val |= (segbusn & 0xf00)<<(25-8);
96 pci_write_config32(dev, 0x160, val);
97 }
98
99 return segbusn;
100}
101#endif
102
103static u32 get_io_addr_index(u32 nodeid, u32 linkn)
104{
105 u32 index;
106
107 for (index=0; index<256; index++) {
108 if ((sysconf.conf_io_addrx[index+4] == 0)) {
109 sysconf.conf_io_addr[index+4] = (nodeid & 0x3f) ;
110 sysconf.conf_io_addrx[index+4] = 1 | ((linkn & 0x7)<<4);
111 return index;
112 }
113 }
114
115 return 0;
116
117}
118
119static u32 get_mmio_addr_index(u32 nodeid, u32 linkn)
120{
121 u32 index;
122
123 for (index=0; index<64; index++) {
Edward O'Callaghancaac5ef2014-06-28 17:52:34 +1000124 if (sysconf.conf_mmio_addrx[index+8] == 0) {
efdesign98b58640c2011-07-13 17:49:25 -0700125 sysconf.conf_mmio_addr[index+8] = (nodeid & 0x3f) ;
126 sysconf.conf_mmio_addrx[index+8] = 1 | ((linkn & 0x7)<<4);
127 return index;
128 }
129 }
130
131 return 0;
132}
133
134static void store_conf_io_addr(u32 nodeid, u32 linkn, u32 reg, u32 index,
135 u32 io_min, u32 io_max)
136{
137 u32 val;
Kyösti Mälkkiac7402d2014-12-14 08:30:17 +0200138 /* io range allocation */
139 index = (reg-0xc0)>>3;
efdesign98b58640c2011-07-13 17:49:25 -0700140
141 val = (nodeid & 0x3f); // 6 bits used
142 sysconf.conf_io_addr[index] = val | ((io_max<<8) & 0xfffff000); //limit : with nodeid
143 val = 3 | ((linkn & 0x7)<<4) ; // 8 bits used
144 sysconf.conf_io_addrx[index] = val | ((io_min<<8) & 0xfffff000); // base : with enable bit
145
146 if (sysconf.io_addr_num<(index+1))
147 sysconf.io_addr_num = index+1;
148}
149
150static void store_conf_mmio_addr(u32 nodeid, u32 linkn, u32 reg, u32 index,
151 u32 mmio_min, u32 mmio_max)
152{
153 u32 val;
Kyösti Mälkkiac7402d2014-12-14 08:30:17 +0200154 /* io range allocation */
155 index = (reg-0x80)>>3;
efdesign98b58640c2011-07-13 17:49:25 -0700156
157 val = (nodeid & 0x3f) ; // 6 bits used
158 sysconf.conf_mmio_addr[index] = val | (mmio_max & 0xffffff00); //limit : with nodeid and linkn
159 val = 3 | ((linkn & 0x7)<<4) ; // 8 bits used
160 sysconf.conf_mmio_addrx[index] = val | (mmio_min & 0xffffff00); // base : with enable bit
161
162 if (sysconf.mmio_addr_num<(index+1))
163 sysconf.mmio_addr_num = index+1;
164}
165
166static void set_io_addr_reg(device_t dev, u32 nodeid, u32 linkn, u32 reg,
167 u32 io_min, u32 io_max)
168{
169
170 u32 i;
171 u32 tempreg;
efdesign98b58640c2011-07-13 17:49:25 -0700172
Kyösti Mälkkiac7402d2014-12-14 08:30:17 +0200173 /* io range allocation */
174 tempreg = (nodeid&0xf) | ((nodeid & 0x30)<<(8-4)) | (linkn<<4) | ((io_max&0xf0)<<(12-4)); //limit
175 for (i=0; i<sysconf.nodes; i++)
176 pci_write_config32(__f1_dev[i], reg+4, tempreg);
177
178 tempreg = 3 /*| ( 3<<4)*/ | ((io_min&0xf0)<<(12-4)); //base :ISA and VGA ?
efdesign98b58640c2011-07-13 17:49:25 -0700179#if 0
Kyösti Mälkkiac7402d2014-12-14 08:30:17 +0200180 // FIXME: can we use VGA reg instead?
181 if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
182 printk(BIOS_SPEW, "%s, enabling legacy VGA IO forwarding for %s link %s\n",
183 __func__, dev_path(dev), link);
184 tempreg |= PCI_IO_BASE_VGA_EN;
efdesign98b58640c2011-07-13 17:49:25 -0700185 }
Kyösti Mälkkiac7402d2014-12-14 08:30:17 +0200186 if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_NO_ISA) {
187 tempreg |= PCI_IO_BASE_NO_ISA;
efdesign98b58640c2011-07-13 17:49:25 -0700188 }
189#endif
Kyösti Mälkkiac7402d2014-12-14 08:30:17 +0200190 for (i=0; i<sysconf.nodes; i++)
191 pci_write_config32(__f1_dev[i], reg, tempreg);
efdesign98b58640c2011-07-13 17:49:25 -0700192}
193
194static void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index, u32 mmio_min, u32 mmio_max, u32 nodes)
195{
196
197 u32 i;
198 u32 tempreg;
efdesign98b58640c2011-07-13 17:49:25 -0700199
Kyösti Mälkkiac7402d2014-12-14 08:30:17 +0200200 /* io range allocation */
201 tempreg = (nodeid&0xf) | (linkn<<4) | (mmio_max&0xffffff00); //limit
202 for (i=0; i<nodes; i++)
203 pci_write_config32(__f1_dev[i], reg+4, tempreg);
204 tempreg = 3 | (nodeid & 0x30) | (mmio_min&0xffffff00);
205 for (i=0; i<sysconf.nodes; i++)
206 pci_write_config32(__f1_dev[i], reg, tempreg);
efdesign98b58640c2011-07-13 17:49:25 -0700207}
208
209static device_t get_node_pci(u32 nodeid, u32 fn)
210{
zbao49bb26a42012-08-03 15:44:42 +0800211#if NODE_NUMS + CONFIG_CDB >= 32
212 if ((CONFIG_CDB + nodeid) < 32) {
efdesign98b58640c2011-07-13 17:49:25 -0700213 return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB + nodeid, fn));
214 } else {
215 return dev_find_slot(CONFIG_CBB-1, PCI_DEVFN(CONFIG_CDB + nodeid - 32, fn));
216 }
217
218#else
219 return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB + nodeid, fn));
220#endif
221}
222
223static unsigned int read_nb_cfg_54(void)
224{
225 msr_t msr;
226 msr = rdmsr(NB_CFG_MSR);
227 return (( msr.hi >> (54-32)) & 1);
228}
229
230static void get_fx_devs(void)
231{
232 int i;
233 for (i = 0; i < NODE_NUMS; i++) {
234 __f0_dev[i] = get_node_pci(i, 0);
235 __f1_dev[i] = get_node_pci(i, 1);
236 __f2_dev[i] = get_node_pci(i, 2);
237 __f4_dev[i] = get_node_pci(i, 4);
238 if (__f0_dev[i] != NULL && __f1_dev[i] != NULL)
239 fx_devs = i+1;
240 }
241 if (__f1_dev[0] == NULL || __f0_dev[0] == NULL || fx_devs == 0) {
242 die("Cannot find 0:0x18.[0|1]\n");
243 }
244}
245
246static u32 f1_read_config32(unsigned reg)
247{
248 if (fx_devs == 0)
249 get_fx_devs();
250 return pci_read_config32(__f1_dev[0], reg);
251}
252
253static void f1_write_config32(unsigned reg, u32 value)
254{
255 int i;
256 if (fx_devs == 0)
257 get_fx_devs();
258 for(i = 0; i < fx_devs; i++) {
259 device_t dev;
260 dev = __f1_dev[i];
261 if (dev && dev->enabled) {
262 pci_write_config32(dev, reg, value);
263 }
264 }
265}
266
267static u32 amdfam10_nodeid(device_t dev)
268{
269#if NODE_NUMS == 64
270 unsigned busn;
271 busn = dev->bus->secondary;
272 if (busn != CONFIG_CBB) {
273 return (dev->path.pci.devfn >> 3) - CONFIG_CDB + 32;
274 } else {
275 return (dev->path.pci.devfn >> 3) - CONFIG_CDB;
276 }
277
278#else
279 return (dev->path.pci.devfn >> 3) - CONFIG_CDB;
280#endif
281}
282
283static void set_vga_enable_reg(u32 nodeid, u32 linkn)
284{
285 u32 val;
286
287 val = 1 | (nodeid<<4) | (linkn<<12);
288 /* it will routing (1)mmio 0xa0000:0xbffff (2) io 0x3b0:0x3bb,
289 0x3c0:0x3df */
290 f1_write_config32(0xf4, val);
291
292}
293
294static int reg_useable(unsigned reg, device_t goal_dev, unsigned goal_nodeid,
295 unsigned goal_link)
296{
297 struct resource *res;
298 unsigned nodeid, link = 0;
299 int result;
300 res = 0;
301 for (nodeid = 0; !res && (nodeid < fx_devs); nodeid++) {
302 device_t dev;
303 dev = __f0_dev[nodeid];
304 if (!dev)
305 continue;
306 for (link = 0; !res && (link < 8); link++) {
307 res = probe_resource(dev, IOINDEX(0x1000 + reg, link));
308 }
309 }
310 result = 2;
311 if (res) {
312 result = 0;
313 if ( (goal_link == (link - 1)) &&
314 (goal_nodeid == (nodeid - 1)) &&
315 (res->flags <= 1)) {
316 result = 1;
317 }
318 }
319 return result;
320}
321
322static struct resource *amdfam10_find_iopair(device_t dev, unsigned nodeid, unsigned link)
323{
324 struct resource *resource;
325 u32 free_reg, reg;
326 resource = 0;
327 free_reg = 0;
328
329 for (reg = 0xc0; reg <= 0xd8; reg += 0x8) {
330 int result;
331 result = reg_useable(reg, dev, nodeid, link);
332 if (result == 1) {
333 /* I have been allocated this one */
334 break;
335 }
336 else if (result > 1) {
337 /* I have a free register pair */
338 free_reg = reg;
339 }
340 }
341 if (reg > 0xd8) {
342 reg = free_reg; // if no free, the free_reg still be 0
343 }
344
345 //Ext conf space
346 if(!reg) {
347 //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
348 u32 index = get_io_addr_index(nodeid, link);
349 reg = 0x110+ (index<<24) + (4<<20); // index could be 0, 255
350 }
351
352 resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
353
354 return resource;
355}
356
357static struct resource *amdfam10_find_mempair(device_t dev, u32 nodeid, u32 link)
358{
359 struct resource *resource;
360 u32 free_reg, reg;
361 resource = 0;
362 free_reg = 0;
363
364 for (reg = 0x80; reg <= 0xb8; reg += 0x8) {
365 int result;
366 result = reg_useable(reg, dev, nodeid, link);
367 if (result == 1) {
368 /* I have been allocated this one */
369 break;
370 }
371 else if (result > 1) {
372 /* I have a free register pair */
373 free_reg = reg;
374 }
375 }
376 if (reg > 0xb8) {
377 reg = free_reg;
378 }
379
380 //Ext conf space
381 if (!reg) {
382 //because of Extend conf space, we will never run out of reg,
383 // but we need one index to differ them. so same node and
384 // same link can have multi range
385 u32 index = get_mmio_addr_index(nodeid, link);
386 reg = 0x110+ (index<<24) + (6<<20); // index could be 0, 63
387
388 }
389 resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
390 return resource;
391}
392
393static void amdfam10_link_read_bases(device_t dev, u32 nodeid, u32 link)
394{
395 struct resource *resource;
396
397 /* Initialize the io space constraints on the current bus */
398 resource = amdfam10_find_iopair(dev, nodeid, link);
399 if (resource) {
400 u32 align;
Kyösti Mälkkiac7402d2014-12-14 08:30:17 +0200401 align = log2(HT_IO_HOST_ALIGN);
efdesign98b58640c2011-07-13 17:49:25 -0700402 resource->base = 0;
403 resource->size = 0;
404 resource->align = align;
405 resource->gran = align;
406 resource->limit = 0xffffUL;
407 resource->flags = IORESOURCE_IO | IORESOURCE_BRIDGE;
408 }
409
410 /* Initialize the prefetchable memory constraints on the current bus */
411 resource = amdfam10_find_mempair(dev, nodeid, link);
412 if (resource) {
413 resource->base = 0;
414 resource->size = 0;
415 resource->align = log2(HT_MEM_HOST_ALIGN);
416 resource->gran = log2(HT_MEM_HOST_ALIGN);
417 resource->limit = 0xffffffffffULL;
418 resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
419 resource->flags |= IORESOURCE_BRIDGE;
efdesign98b58640c2011-07-13 17:49:25 -0700420 }
421
422 /* Initialize the memory constraints on the current bus */
423 resource = amdfam10_find_mempair(dev, nodeid, link);
424 if (resource) {
425 resource->base = 0;
426 resource->size = 0;
427 resource->align = log2(HT_MEM_HOST_ALIGN);
428 resource->gran = log2(HT_MEM_HOST_ALIGN);
429 resource->limit = 0xffffffffffULL;
430 resource->flags = IORESOURCE_MEM | IORESOURCE_BRIDGE;
efdesign98b58640c2011-07-13 17:49:25 -0700431 }
432}
433
434static void amdfam10_read_resources(device_t dev)
435{
436 u32 nodeid;
437 struct bus *link;
438 nodeid = amdfam10_nodeid(dev);
439 for (link = dev->link_list; link; link = link->next) {
440 if (link->children) {
441 amdfam10_link_read_bases(dev, nodeid, link->link_num);
442 }
443 }
444}
445
446static void amdfam10_set_resource(device_t dev, struct resource *resource,
447 u32 nodeid)
448{
449 resource_t rbase, rend;
450 unsigned reg, link_num;
451 char buf[50];
452
453 /* Make certain the resource has actually been set */
454 if (!(resource->flags & IORESOURCE_ASSIGNED)) {
455 return;
456 }
457
458 /* If I have already stored this resource don't worry about it */
459 if (resource->flags & IORESOURCE_STORED) {
460 return;
461 }
462
463 /* Only handle PCI memory and IO resources */
464 if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
465 return;
466
467 /* Ensure I am actually looking at a resource of function 1 */
468 if ((resource->index & 0xffff) < 0x1000) {
469 return;
470 }
471 /* Get the base address */
472 rbase = resource->base;
473
474 /* Get the limit (rounded up) */
475 rend = resource_end(resource);
476
477 /* Get the register and link */
478 reg = resource->index & 0xfff; // 4k
479 link_num = IOINDEX_LINK(resource->index);
480
481 if (resource->flags & IORESOURCE_IO) {
482
483 set_io_addr_reg(dev, nodeid, link_num, reg, rbase>>8, rend>>8);
484 store_conf_io_addr(nodeid, link_num, reg, (resource->index >> 24), rbase>>8, rend>>8);
485 }
486 else if (resource->flags & IORESOURCE_MEM) {
487 set_mmio_addr_reg(nodeid, link_num, reg, (resource->index >>24), rbase>>8, rend>>8, sysconf.nodes) ;// [39:8]
488 store_conf_mmio_addr(nodeid, link_num, reg, (resource->index >>24), rbase>>8, rend>>8);
489 }
490 resource->flags |= IORESOURCE_STORED;
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100491 snprintf(buf, sizeof (buf), " <node %x link %x>",
efdesign98b58640c2011-07-13 17:49:25 -0700492 nodeid, link_num);
493 report_resource_stored(dev, resource, buf);
494}
495
496/**
497 * I tried to reuse the resource allocation code in amdfam10_set_resource()
498 * but it is too difficult to deal with the resource allocation magic.
499 */
500
501static void amdfam10_create_vga_resource(device_t dev, unsigned nodeid)
502{
503 struct bus *link;
504
505 /* find out which link the VGA card is connected,
506 * we only deal with the 'first' vga card */
507 for (link = dev->link_list; link; link = link->next) {
508 if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
Patrick Georgie1667822012-05-05 15:29:32 +0200509#if CONFIG_MULTIPLE_VGA_ADAPTERS
efdesign98b58640c2011-07-13 17:49:25 -0700510 extern device_t vga_pri; // the primary vga device, defined in device.c
511 printk(BIOS_DEBUG, "VGA: vga_pri bus num = %d bus range [%d,%d]\n", vga_pri->bus->secondary,
512 link->secondary,link->subordinate);
513 /* We need to make sure the vga_pri is under the link */
514 if((vga_pri->bus->secondary >= link->secondary ) &&
515 (vga_pri->bus->secondary <= link->subordinate )
516 )
517#endif
518 break;
519 }
520 }
521
522 /* no VGA card installed */
523 if (link == NULL)
524 return;
525
526 printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, link->link_num);
527 set_vga_enable_reg(nodeid, link->link_num);
528}
529
530static void amdfam10_set_resources(device_t dev)
531{
532 unsigned nodeid;
533 struct bus *bus;
534 struct resource *res;
535
536 /* Find the nodeid */
537 nodeid = amdfam10_nodeid(dev);
538
539 amdfam10_create_vga_resource(dev, nodeid);
540
541 /* Set each resource we have found */
542 for (res = dev->resource_list; res; res = res->next) {
543 amdfam10_set_resource(dev, res, nodeid);
544 }
545
546 for (bus = dev->link_list; bus; bus = bus->next) {
547 if (bus->children) {
548 assign_resources(bus);
549 }
550 }
551}
552
553static void mcf0_control_init(struct device *dev)
554{
555}
556
Kyösti Mälkki6ccf1192015-03-12 05:56:22 +0200557static unsigned amdfam10_scan_chains(device_t dev, unsigned unused)
efdesign98b58640c2011-07-13 17:49:25 -0700558{
559 unsigned nodeid;
560 struct bus *link;
561 unsigned sblink = sysconf.sblk;
562 device_t io_hub = NULL;
563 u32 next_unitid = 0xff;
Kyösti Mälkki6ccf1192015-03-12 05:56:22 +0200564 unsigned int max = dev->bus->subordinate;
efdesign98b58640c2011-07-13 17:49:25 -0700565
566 nodeid = amdfam10_nodeid(dev);
567 if (nodeid == 0) {
568 for (link = dev->link_list; link; link = link->next) {
569 if (link->link_num == sblink) { /* devicetree put IO Hub on link_lsit[3] */
570 io_hub = link->children;
571 if (!io_hub || !io_hub->enabled) {
572 die("I can't find the IO Hub, or IO Hub not enabled, please check the device tree.\n");
573 }
574 /* Now that nothing is overlapping it is safe to scan the children. */
575 max = pci_scan_bus(link, 0x00, ((next_unitid - 1) << 3) | 7, 0);
576 }
577 }
578 }
579
Kyösti Mälkki6ccf1192015-03-12 05:56:22 +0200580 dev->bus->subordinate = max;
581
582 return unused;
efdesign98b58640c2011-07-13 17:49:25 -0700583}
584
585static struct device_operations northbridge_operations = {
586 .read_resources = amdfam10_read_resources,
587 .set_resources = amdfam10_set_resources,
588 .enable_resources = pci_dev_enable_resources,
589 .init = mcf0_control_init,
590 .scan_bus = amdfam10_scan_chains,
591 .enable = 0,
592 .ops_pci = 0,
593};
594
595static const struct pci_driver mcf0_driver __pci_driver = {
596 .ops = &northbridge_operations,
597 .vendor = PCI_VENDOR_ID_AMD,
598 .device = 0x1200,
599};
600
601struct chip_operations northbridge_amd_agesa_family10_ops = {
602 CHIP_NAME("AMD FAM10 Northbridge")
603 .enable_dev = 0,
604};
605
606
607static void amdfam10_domain_read_resources(device_t dev)
608{
609 unsigned reg;
610
611 /* Find the already assigned resource pairs */
612 get_fx_devs();
613 for (reg = 0x80; reg <= 0xd8; reg+= 0x08) {
614 u32 base, limit;
615 base = f1_read_config32(reg);
616 limit = f1_read_config32(reg + 0x04);
617 /* Is this register allocated? */
618 if ((base & 3) != 0) {
619 unsigned nodeid, reg_link;
620 device_t reg_dev;
621 if (reg<0xc0) { // mmio
622 nodeid = (limit & 0xf) + (base&0x30);
623 } else { // io
624 nodeid = (limit & 0xf) + ((base>>4)&0x30);
625 }
626 reg_link = (limit >> 4) & 7;
627 reg_dev = __f0_dev[nodeid];
628 if (reg_dev) {
629 /* Reserve the resource */
630 struct resource *res;
631 res = new_resource(reg_dev, IOINDEX(0x1000 + reg, reg_link));
632 if (res) {
633 res->flags = 1;
634 }
635 }
636 }
637 }
638 /* FIXME: do we need to check extend conf space?
639 I don't believe that much preset value */
640
Patrick Georgie1667822012-05-05 15:29:32 +0200641#if !CONFIG_PCI_64BIT_PREF_MEM
efdesign98b58640c2011-07-13 17:49:25 -0700642 pci_domain_read_resources(dev);
643#else
644 struct bus *link;
645 struct resource *resource;
646 for (link=dev->link_list; link; link = link->next) {
647 /* Initialize the system wide io space constraints */
648 resource = new_resource(dev, 0|(link->link_num<<2));
649 resource->base = 0x400;
650 resource->limit = 0xffffUL;
651 resource->flags = IORESOURCE_IO;
652
653 /* Initialize the system wide prefetchable memory resources constraints */
654 resource = new_resource(dev, 1|(link->link_num<<2));
655 resource->limit = 0xfcffffffffULL;
656 resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
657
658 /* Initialize the system wide memory resources constraints */
659 resource = new_resource(dev, 2|(link->link_num<<2));
660 resource->limit = 0xfcffffffffULL;
661 resource->flags = IORESOURCE_MEM;
662 }
663#endif
664}
665
666static void amdfam10_domain_enable_resources(device_t dev)
667{
efdesign98b58640c2011-07-13 17:49:25 -0700668 /* Must be called after PCI enumeration and resource allocation */
Mike Loptien6eced512013-01-31 10:19:31 -0700669 printk(BIOS_DEBUG, "\nFam10 - %s: AmdInitMid.\n", __func__);
Kyösti Mälkki1aa35c62014-10-21 14:19:04 +0300670 agesawrapper_amdinitmid();
Mike Loptien6eced512013-01-31 10:19:31 -0700671 printk(BIOS_DEBUG, " ader - leaving %s.\n", __func__);
efdesign98b58640c2011-07-13 17:49:25 -0700672}
673
674
675static u32 my_find_pci_tolm(struct bus *bus, u32 tolm)
676{
677 struct resource *min;
678 min = 0;
679 search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min);
680 if (min && tolm > min->base) {
681 tolm = min->base;
682 }
683 return tolm;
684}
685
686#if CONFIG_HW_MEM_HOLE_SIZEK != 0
687struct hw_mem_hole_info {
688 unsigned hole_startk;
689 int node_id;
690};
691
692static struct hw_mem_hole_info get_hw_mem_hole_info(void)
693{
694 struct hw_mem_hole_info mem_hole;
695 int i;
696
697 mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK;
698 mem_hole.node_id = -1;
699
700 for (i = 0; i < sysconf.nodes; i++) {
701 dram_base_mask_t d;
702 u32 hole;
703 d = get_dram_base_mask(i);
704 if (!(d.mask & 1)) continue; // no memory on this node
705
706 hole = pci_read_config32(__f1_dev[i], 0xf0);
707 if (hole & 1) { // we find the hole
708 mem_hole.hole_startk = (hole & (0xff<<24)) >> 10;
709 mem_hole.node_id = i; // record the node No with hole
710 break; // only one hole
711 }
712 }
713
Kyösti Mälkki2f9b3af2014-06-26 05:30:54 +0300714 /* We need to double check if there is special set on base reg and limit reg
715 * are not continuous instead of hole, it will find out its hole_startk.
716 */
efdesign98b58640c2011-07-13 17:49:25 -0700717 if (mem_hole.node_id == -1) {
718 resource_t limitk_pri = 0;
719 for (i=0; i<sysconf.nodes; i++) {
720 dram_base_mask_t d;
721 resource_t base_k, limit_k;
722 d = get_dram_base_mask(i);
723 if (!(d.base & 1)) continue;
724
725 base_k = ((resource_t)(d.base & 0x1fffff00)) <<9;
726 if (base_k > 4 *1024 * 1024) break; // don't need to go to check
727 if (limitk_pri != base_k) { // we find the hole
728 mem_hole.hole_startk = (unsigned)limitk_pri; // must beblow 4G
729 mem_hole.node_id = i;
730 break; //only one hole
731 }
732
733 limit_k = ((resource_t)((d.mask + 0x00000100) & 0x1fffff00)) << 9;
734 limitk_pri = limit_k;
735 }
736 }
737 return mem_hole;
738}
739#endif
740
efdesign98b58640c2011-07-13 17:49:25 -0700741static void amdfam10_domain_set_resources(device_t dev)
742{
Patrick Georgie1667822012-05-05 15:29:32 +0200743#if CONFIG_PCI_64BIT_PREF_MEM
efdesign98b58640c2011-07-13 17:49:25 -0700744 struct resource *io, *mem1, *mem2;
745 struct resource *res;
746#endif
747 unsigned long mmio_basek;
748 u32 pci_tolm;
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300749 u64 ramtop = 0;
efdesign98b58640c2011-07-13 17:49:25 -0700750 int i, idx;
751 struct bus *link;
752#if CONFIG_HW_MEM_HOLE_SIZEK != 0
753 struct hw_mem_hole_info mem_hole;
754 u32 reset_memhole = 1;
755#endif
756
Patrick Georgie1667822012-05-05 15:29:32 +0200757#if CONFIG_PCI_64BIT_PREF_MEM
efdesign98b58640c2011-07-13 17:49:25 -0700758
759 for (link = dev->link_list; link; link = link->next) {
760 /* Now reallocate the pci resources memory with the
761 * highest addresses I can manage.
762 */
763 mem1 = find_resource(dev, 1|(link->link_num<<2));
764 mem2 = find_resource(dev, 2|(link->link_num<<2));
765
766 printk(BIOS_DEBUG, "base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
767 mem1->base, mem1->limit, mem1->size, mem1->align);
768 printk(BIOS_DEBUG, "base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
769 mem2->base, mem2->limit, mem2->size, mem2->align);
770
771 /* See if both resources have roughly the same limits */
772 if (((mem1->limit <= 0xffffffff) && (mem2->limit <= 0xffffffff)) ||
773 ((mem1->limit > 0xffffffff) && (mem2->limit > 0xffffffff)))
774 {
775 /* If so place the one with the most stringent alignment first
776 */
777 if (mem2->align > mem1->align) {
778 struct resource *tmp;
779 tmp = mem1;
780 mem1 = mem2;
781 mem2 = tmp;
782 }
783 /* Now place the memory as high up as it will go */
784 mem2->base = resource_max(mem2);
785 mem1->limit = mem2->base - 1;
786 mem1->base = resource_max(mem1);
787 }
788 else {
789 /* Place the resources as high up as they will go */
790 mem2->base = resource_max(mem2);
791 mem1->base = resource_max(mem1);
792 }
793
794 printk(BIOS_DEBUG, "base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
795 mem1->base, mem1->limit, mem1->size, mem1->align);
796 printk(BIOS_DEBUG, "base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
797 mem2->base, mem2->limit, mem2->size, mem2->align);
798 }
799
800 for (res = &dev->resource_list; res; res = res->next)
801 {
802 res->flags |= IORESOURCE_ASSIGNED;
803 res->flags |= IORESOURCE_STORED;
804 report_resource_stored(dev, res, "");
805 }
806#endif
807
808 pci_tolm = 0xffffffffUL;
809 for (link = dev->link_list; link; link = link->next) {
810 pci_tolm = my_find_pci_tolm(link, pci_tolm);
811 }
812
813 // FIXME handle interleaved nodes. If you fix this here, please fix
814 // amdk8, too.
815 mmio_basek = pci_tolm >> 10;
816 /* Round mmio_basek to something the processor can support */
817 mmio_basek &= ~((1 << 6) -1);
818
819 // FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M
820 // MMIO hole. If you fix this here, please fix amdk8, too.
821 /* Round the mmio hole to 64M */
822 mmio_basek &= ~((64*1024) - 1);
823
824#if CONFIG_HW_MEM_HOLE_SIZEK != 0
825/* if the hw mem hole is already set in raminit stage, here we will compare
826 * mmio_basek and hole_basek. if mmio_basek is bigger that hole_basek and will
827 * use hole_basek as mmio_basek and we don't need to reset hole.
828 * otherwise We reset the hole to the mmio_basek
829 */
830
831 mem_hole = get_hw_mem_hole_info();
832
833 // Use hole_basek as mmio_basek, and we don't need to reset hole anymore
834 if ((mem_hole.node_id != -1) && (mmio_basek > mem_hole.hole_startk)) {
835 mmio_basek = mem_hole.hole_startk;
836 reset_memhole = 0;
837 }
838
839#endif
840
841 idx = 0x10;
842 for (i = 0; i < sysconf.nodes; i++) {
843 dram_base_mask_t d;
844 resource_t basek, limitk, sizek; // 4 1T
845 d = get_dram_base_mask(i);
846
847 if (!(d.mask & 1)) continue;
848 basek = ((resource_t)(d.base & 0x1fffff00)) << 9; // could overflow, we may lost 6 bit here
849 limitk = ((resource_t)((d.mask + 0x00000100) & 0x1fffff00)) << 9 ;
850 sizek = limitk - basek;
851
852 /* see if we need a hole from 0xa0000 to 0xbffff */
853 if ((basek < ((8*64)+(8*16))) && (sizek > ((8*64)+(16*16)))) {
854 ram_resource(dev, (idx | i), basek, ((8*64)+(8*16)) - basek);
855 idx += 0x10;
856 basek = (8*64)+(16*16);
857 sizek = limitk - ((8*64)+(16*16));
858
859 }
860
861 //printk(BIOS_DEBUG, "node %d : mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n", i, mmio_basek, basek, limitk);
862
Kyösti Mälkki26c65432014-06-26 05:30:54 +0300863 /* split the region to accommodate pci memory space */
efdesign98b58640c2011-07-13 17:49:25 -0700864 if ((basek < 4*1024*1024 ) && (limitk > mmio_basek)) {
865 if (basek <= mmio_basek) {
866 unsigned pre_sizek;
867 pre_sizek = mmio_basek - basek;
868 if (pre_sizek>0) {
869 ram_resource(dev, (idx | i), basek, pre_sizek);
870 idx += 0x10;
871 sizek -= pre_sizek;
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300872 if (!ramtop)
873 ramtop = mmio_basek * 1024;
efdesign98b58640c2011-07-13 17:49:25 -0700874 }
875 basek = mmio_basek;
876 }
877 if ((basek + sizek) <= 4*1024*1024) {
878 sizek = 0;
879 }
880 else {
881 basek = 4*1024*1024;
882 sizek -= (4*1024*1024 - mmio_basek);
883 }
884 }
885
efdesign98b58640c2011-07-13 17:49:25 -0700886 ram_resource(dev, (idx | i), basek, sizek);
887 idx += 0x10;
efdesign98b58640c2011-07-13 17:49:25 -0700888 printk(BIOS_DEBUG, "node %d: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",
889 i, mmio_basek, basek, limitk);
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300890 if (!ramtop)
891 ramtop = limitk * 1024;
efdesign98b58640c2011-07-13 17:49:25 -0700892 }
893
Patrick Georgie1667822012-05-05 15:29:32 +0200894#if CONFIG_GFXUMA
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300895 set_top_of_ram(uma_memory_base);
Kyösti Mälkki63f8c082012-07-10 13:27:26 +0300896 uma_resource(dev, 7, uma_memory_base >> 10, uma_memory_size >> 10);
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300897#else
898 set_top_of_ram(ramtop);
efdesign98b58640c2011-07-13 17:49:25 -0700899#endif
900
901 for(link = dev->link_list; link; link = link->next) {
902 if (link->children) {
903 assign_resources(link);
904 }
905 }
906}
907
908static u32 amdfam10_domain_scan_bus(device_t dev, u32 max)
909{
910 u32 reg;
911 int i;
912 struct bus *link;
913 /* Unmap all of the HT chains */
914 for (reg = 0xe0; reg <= 0xec; reg += 4) {
915 f1_write_config32(reg, 0);
916 }
efdesign98b58640c2011-07-13 17:49:25 -0700917
918 for (link = dev->link_list; link; link = link->next) {
Kyösti Mälkki6ccf1192015-03-12 05:56:22 +0200919 link->secondary = dev->bus->subordinate;
920 link->subordinate = pci_scan_bus(link, PCI_DEVFN(CONFIG_CDB, 0), 0xff, link->secondary);
921 dev->bus->subordinate = link->subordinate;
efdesign98b58640c2011-07-13 17:49:25 -0700922 }
923
924 /* Tune the hypertransport transaction for best performance.
925 * Including enabling relaxed ordering if it is safe.
926 */
927 get_fx_devs();
928 for (i = 0; i < fx_devs; i++) {
929 device_t f0_dev;
930 f0_dev = __f0_dev[i];
931 if (f0_dev && f0_dev->enabled) {
932 u32 httc;
933 httc = pci_read_config32(f0_dev, HT_TRANSACTION_CONTROL);
934 httc &= ~HTTC_RSP_PASS_PW;
935 if (!dev->link_list->disable_relaxed_ordering) {
936 httc |= HTTC_RSP_PASS_PW;
937 }
938 printk(BIOS_SPEW, "%s passpw: %s\n",
939 dev_path(dev),
940 (!dev->link_list->disable_relaxed_ordering)?
941 "enabled":"disabled");
942 pci_write_config32(f0_dev, HT_TRANSACTION_CONTROL, httc);
943 }
944 }
945 return max;
946}
947
948
949static struct device_operations pci_domain_ops = {
950 .read_resources = amdfam10_domain_read_resources,
951 .set_resources = amdfam10_domain_set_resources,
952 .enable_resources = amdfam10_domain_enable_resources,
Edward O'Callaghane9e1d7a2015-01-02 15:11:49 +1100953 .init = DEVICE_NOOP,
efdesign98b58640c2011-07-13 17:49:25 -0700954 .scan_bus = amdfam10_domain_scan_bus,
Kyösti Mälkki872c9222013-07-03 09:44:28 +0300955 .ops_pci_bus = pci_bus_default_ops,
efdesign98b58640c2011-07-13 17:49:25 -0700956};
957
958
959static void sysconf_init(device_t dev) // first node
960{
961 sysconf.sblk = (pci_read_config32(dev, 0x64)>>8) & 7; // don't forget sublink1
962 sysconf.segbit = 0;
963 sysconf.ht_c_num = 0;
964
965 unsigned ht_c_index;
966
967 for (ht_c_index=0; ht_c_index<32; ht_c_index++) {
968 sysconf.ht_c_conf_bus[ht_c_index] = 0;
969 }
970
971 sysconf.nodes = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1; //NodeCnt[2:0]
972
973 /* Find the bootstrap processors apicid */
974 sysconf.bsp_apicid = lapicid();
975}
976
977static void add_more_links(device_t dev, unsigned total_links)
978{
979 struct bus *link, *last = NULL;
980 int link_num;
981
982 for (link = dev->link_list; link; link = link->next)
983 last = link;
984
985 if (last) {
986 int links = total_links - last->link_num;
987 link_num = last->link_num;
988 if (links > 0) {
989 link = malloc(links*sizeof(*link));
990 if (!link)
991 die("Couldn't allocate more links!\n");
992 memset(link, 0, links*sizeof(*link));
993 last->next = link;
994 }
995 }
996 else {
997 link_num = -1;
998 link = malloc(total_links*sizeof(*link));
999 memset(link, 0, total_links*sizeof(*link));
1000 dev->link_list = link;
1001 }
1002
1003 for (link_num = link_num + 1; link_num < total_links; link_num++) {
1004 link->link_num = link_num;
1005 link->dev = dev;
1006 link->next = link + 1;
1007 last = link;
1008 link = link->next;
1009 }
1010 last->next = NULL;
1011}
1012
efdesign98b58640c2011-07-13 17:49:25 -07001013static u32 cpu_bus_scan(device_t dev, u32 max)
1014{
1015 struct bus *cpu_bus;
1016 device_t dev_mc;
1017#if CONFIG_CBB
1018 device_t pci_domain;
1019#endif
1020 int i,j;
1021 int nodes;
1022 unsigned nb_cfg_54;
1023 unsigned siblings;
1024 int cores_found;
1025 int disable_siblings;
1026 unsigned ApicIdCoreIdSize;
1027
1028 nb_cfg_54 = 0;
1029 ApicIdCoreIdSize = (cpuid_ecx(0x80000008)>>12 & 0xf);
1030 if (ApicIdCoreIdSize) {
1031 siblings = (1<<ApicIdCoreIdSize)-1;
1032 } else {
1033 siblings = 3; //quad core
1034 }
1035
1036 disable_siblings = !CONFIG_LOGICAL_CPUS;
Patrick Georgie1667822012-05-05 15:29:32 +02001037#if CONFIG_LOGICAL_CPUS
efdesign98b58640c2011-07-13 17:49:25 -07001038 get_option(&disable_siblings, "multi_core");
1039#endif
1040
1041 // How can I get the nb_cfg_54 of every node's nb_cfg_54 in bsp???
1042 nb_cfg_54 = read_nb_cfg_54();
1043
1044#if CONFIG_CBB
1045 dev_mc = dev_find_slot(0, PCI_DEVFN(CONFIG_CDB, 0)); //0x00
1046 if (dev_mc && dev_mc->bus) {
1047 printk(BIOS_DEBUG, "%s found", dev_path(dev_mc));
1048 pci_domain = dev_mc->bus->dev;
Stefan Reinauer4aff4452013-02-12 14:17:15 -08001049 if (pci_domain && (pci_domain->path.type == DEVICE_PATH_DOMAIN)) {
efdesign98b58640c2011-07-13 17:49:25 -07001050 printk(BIOS_DEBUG, "\n%s move to ",dev_path(dev_mc));
1051 dev_mc->bus->secondary = CONFIG_CBB; // move to 0xff
1052 printk(BIOS_DEBUG, "%s",dev_path(dev_mc));
1053
1054 } else {
1055 printk(BIOS_DEBUG, " but it is not under pci_domain directly ");
1056 }
1057 printk(BIOS_DEBUG, "\n");
1058 }
1059 dev_mc = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 0));
1060 if (!dev_mc) {
1061 dev_mc = dev_find_slot(0, PCI_DEVFN(0x18, 0));
1062 if (dev_mc && dev_mc->bus) {
1063 printk(BIOS_DEBUG, "%s found\n", dev_path(dev_mc));
1064 pci_domain = dev_mc->bus->dev;
Stefan Reinauer4aff4452013-02-12 14:17:15 -08001065 if (pci_domain && (pci_domain->path.type == DEVICE_PATH_DOMAIN)) {
efdesign98b58640c2011-07-13 17:49:25 -07001066 if ((pci_domain->link_list) && (pci_domain->link_list->children == dev_mc)) {
1067 printk(BIOS_DEBUG, "%s move to ",dev_path(dev_mc));
1068 dev_mc->bus->secondary = CONFIG_CBB; // move to 0xff
1069 printk(BIOS_DEBUG, "%s\n",dev_path(dev_mc));
1070 while (dev_mc) {
1071 printk(BIOS_DEBUG, "%s move to ",dev_path(dev_mc));
1072 dev_mc->path.pci.devfn -= PCI_DEVFN(0x18,0);
1073 printk(BIOS_DEBUG, "%s\n",dev_path(dev_mc));
1074 dev_mc = dev_mc->sibling;
1075 }
1076 }
1077 }
1078 }
1079 }
1080
1081#endif
1082
1083 dev_mc = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 0));
1084 if (!dev_mc) {
1085 printk(BIOS_ERR, "%02x:%02x.0 not found", CONFIG_CBB, CONFIG_CDB);
1086 die("");
1087 }
1088
1089 sysconf_init(dev_mc);
1090
1091 nodes = sysconf.nodes;
1092
1093#if CONFIG_CBB && (NODE_NUMS > 32)
1094 if (nodes>32) { // need to put node 32 to node 63 to bus 0xfe
1095 if (pci_domain->link_list && !pci_domain->link_list->next) {
1096 struct bus *new_link = new_link(pci_domain);
1097 pci_domain->link_list->next = new_link;
1098 new_link->link_num = 1;
1099 new_link->dev = pci_domain;
1100 new_link->children = 0;
1101 printk(BIOS_DEBUG, "%s links now 2\n", dev_path(pci_domain));
1102 }
1103 pci_domain->link_list->next->secondary = CONFIG_CBB - 1;
1104 }
1105#endif
1106 /* Find which cpus are present */
1107 cpu_bus = dev->link_list;
1108 for (i = 0; i < nodes; i++) {
Kyösti Mälkkicd9fc1a2012-07-06 19:02:56 +03001109 device_t cdb_dev;
efdesign98b58640c2011-07-13 17:49:25 -07001110 unsigned busn, devn;
1111 struct bus *pbus;
1112
1113 busn = CONFIG_CBB;
1114 devn = CONFIG_CDB+i;
1115 pbus = dev_mc->bus;
1116#if CONFIG_CBB && (NODE_NUMS > 32)
1117 if (i>=32) {
1118 busn--;
1119 devn-=32;
1120 pbus = pci_domain->link_list->next);
1121 }
1122#endif
1123
1124 /* Find the cpu's pci device */
1125 cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 0));
1126 if (!cdb_dev) {
1127 /* If I am probing things in a weird order
1128 * ensure all of the cpu's pci devices are found.
1129 */
1130 int fn;
1131 for(fn = 0; fn <= 5; fn++) { //FBDIMM?
1132 cdb_dev = pci_probe_dev(NULL, pbus,
1133 PCI_DEVFN(devn, fn));
1134 }
1135 cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 0));
1136 }
1137 if (cdb_dev) {
1138 /* Ok, We need to set the links for that device.
1139 * otherwise the device under it will not be scanned
1140 */
Kyösti Mälkki225da642015-02-04 13:46:12 +02001141 add_more_links(cdb_dev, 8);
efdesign98b58640c2011-07-13 17:49:25 -07001142 }
1143
1144 cores_found = 0; // one core
1145 cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 3));
Kyösti Mälkkicd9fc1a2012-07-06 19:02:56 +03001146 int enable_node = cdb_dev && cdb_dev->enabled;
1147 if (enable_node) {
efdesign98b58640c2011-07-13 17:49:25 -07001148 j = pci_read_config32(cdb_dev, 0xe8);
1149 cores_found = (j >> 12) & 3; // dev is func 3
1150 if (siblings > 3)
1151 cores_found |= (j >> 13) & 4;
1152 printk(BIOS_DEBUG, " %s siblings=%d\n", dev_path(cdb_dev), cores_found);
1153 }
1154
1155 u32 jj;
1156 if (disable_siblings) {
1157 jj = 0;
1158 } else {
1159 jj = cores_found;
1160 }
1161
1162 for (j = 0; j <=jj; j++ ) {
1163 extern CONST OPTIONS_CONFIG_TOPOLOGY ROMDATA TopologyConfiguration;
1164 u32 modules = TopologyConfiguration.PlatformNumberOfModules;
1165 u32 lapicid_start = 0;
1166
efdesign98b58640c2011-07-13 17:49:25 -07001167 /*
1168 * APIC ID calucation is tightly coupled with AGESA v5 code.
1169 * This calculation MUST match the assignment calculation done
1170 * in LocalApicInitializationAtEarly() function.
1171 * And reference GetLocalApicIdForCore()
1172 *
1173 * Apply apic enumeration rules
1174 * For systems with >= 16 APICs, put the IO-APICs at 0..n and
1175 * put the local-APICs at m..z
1176 * For systems with < 16 APICs, put the Local-APICs at 0..n and
1177 * put the IO-APICs at (n + 1)..z
1178 */
1179 if (nodes * (cores_found + 1) >= 0x10) {
1180 lapicid_start = 0x10;
1181 }
Kyösti Mälkkic33f1e92012-08-07 17:12:11 +03001182 u32 apic_id = (lapicid_start * (i/modules + 1)) + ((i % modules) ? (j + (cores_found + 1)) : j);
efdesign98b58640c2011-07-13 17:49:25 -07001183
Kyösti Mälkkic33f1e92012-08-07 17:12:11 +03001184 device_t cpu = add_cpu_device(cpu_bus, apic_id, enable_node);
1185 if (cpu)
1186 amd_cpu_topology(cpu, i, j);
efdesign98b58640c2011-07-13 17:49:25 -07001187 } //j
1188 }
1189 return max;
1190}
1191
1192static void cpu_bus_init(device_t dev)
1193{
1194 initialize_cpus(dev->link_list);
1195}
1196
efdesign98b58640c2011-07-13 17:49:25 -07001197static void cpu_bus_read_resources(device_t dev)
1198{
1199#if CONFIG_MMCONF_SUPPORT
1200 struct resource *resource = new_resource(dev, 0xc0010058);
1201 resource->base = CONFIG_MMCONF_BASE_ADDRESS;
1202 resource->size = CONFIG_MMCONF_BUS_NUMBER * 4096*256;
1203 resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
1204 IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
1205#endif
1206}
1207
1208static void cpu_bus_set_resources(device_t dev)
1209{
1210 struct resource *resource = find_resource(dev, 0xc0010058);
1211 if (resource) {
1212 report_resource_stored(dev, resource, " <mmconfig>");
1213 }
1214 pci_dev_set_resources(dev);
1215}
1216
1217static struct device_operations cpu_bus_ops = {
1218 .read_resources = cpu_bus_read_resources,
1219 .set_resources = cpu_bus_set_resources,
Edward O'Callaghan812d2a42014-10-31 08:17:23 +11001220 .enable_resources = DEVICE_NOOP,
efdesign98b58640c2011-07-13 17:49:25 -07001221 .init = cpu_bus_init,
1222 .scan_bus = cpu_bus_scan,
1223};
1224
1225static void root_complex_enable_dev(struct device *dev)
1226{
Kyösti Mälkki87213b62012-08-27 20:00:33 +03001227 static int done = 0;
1228
1229 /* Do not delay UMA setup, as a device on the PCI bus may evaluate
1230 the global uma_memory variables already in its enable function. */
1231 if (!done) {
1232 setup_bsp_ramtop();
1233#if CONFIG_GFXUMA
1234#error Northbridge does not set uma_memory_base or uma_memory_size.
1235 setup_uma_memory();
1236#endif
1237 done = 1;
1238 }
1239
efdesign98b58640c2011-07-13 17:49:25 -07001240 /* Set the operations if it is a special bus type */
Stefan Reinauer4aff4452013-02-12 14:17:15 -08001241 if (dev->path.type == DEVICE_PATH_DOMAIN) {
efdesign98b58640c2011-07-13 17:49:25 -07001242 dev->ops = &pci_domain_ops;
1243 }
Stefan Reinauer0aa37c42013-02-12 15:20:54 -08001244 else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
efdesign98b58640c2011-07-13 17:49:25 -07001245 dev->ops = &cpu_bus_ops;
1246 }
1247}
1248
1249struct chip_operations northbridge_amd_agesa_family10_root_complex_ops = {
1250 CHIP_NAME("AMD FAM10 Root Complex")
1251 .enable_dev = root_complex_enable_dev,
1252};