coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
northbridge.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <device/pci_ops.h>
5 #include <acpi/acpi.h>
6 #include <acpi/acpigen.h>
7 #include <stdint.h>
8 #include <device/device.h>
9 #include <device/pci.h>
10 #include <device/pci_ids.h>
11 #include <string.h>
12 #include <lib.h>
13 #include <cpu/cpu.h>
14 #include <cpu/amd/msr.h>
15 #include <cpu/amd/mtrr.h>
19 #include <sb_cimx.h>
20 
21 #define FX_DEVS 1
22 
23 static struct device *__f0_dev[FX_DEVS];
24 static struct device *__f1_dev[FX_DEVS];
25 static struct device *__f2_dev[FX_DEVS];
26 static struct device *__f4_dev[FX_DEVS];
27 static unsigned int fx_devs = 0;
28 
30 {
31  return 0;
32 }
33 
35 {
36  return 0;
37 }
38 
39 static void set_io_addr_reg(struct device *dev, u32 nodeid, u32 linkn, u32 reg,
40  u32 io_min, u32 io_max)
41 {
42 
43  u32 tempreg;
44  /* io range allocation */
45  tempreg = (nodeid & 0xf) | ((nodeid & 0x30) << (8 - 4)) | (linkn << 4) |
46  ((io_max & 0xf0) << (12 - 4)); //limit
47  pci_write_config32(__f1_dev[0], reg+4, tempreg);
48 
49  tempreg = 3 | ((io_min & 0xf0) << (12 - 4)); //base :ISA and VGA ?
50  pci_write_config32(__f1_dev[0], reg, tempreg);
51 }
52 
53 static void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index,
54  u32 mmio_min, u32 mmio_max, u32 nodes)
55 {
56 
57  u32 tempreg;
58  /* io range allocation */
59  tempreg = (nodeid & 0xf) | (linkn << 4) | (mmio_max & 0xffffff00);
60  pci_write_config32(__f1_dev[0], reg + 4, tempreg);
61  tempreg = 3 | (nodeid & 0x30) | (mmio_min & 0xffffff00);
62  pci_write_config32(__f1_dev[0], reg, tempreg);
63 }
64 
65 static struct device *get_node_pci(u32 nodeid, u32 fn)
66 {
67  return pcidev_on_root(DEV_CDB + nodeid, fn);
68 }
69 
70 static void get_fx_devs(void)
71 {
72  int i;
73  for (i = 0; i < FX_DEVS; i++) {
74  __f0_dev[i] = get_node_pci(i, 0);
75  __f1_dev[i] = get_node_pci(i, 1);
76  __f2_dev[i] = get_node_pci(i, 2);
77  __f4_dev[i] = get_node_pci(i, 4);
78  if (__f0_dev[i] != NULL && __f1_dev[i] != NULL)
79  fx_devs = i + 1;
80  }
81  if (__f1_dev[0] == NULL || __f0_dev[0] == NULL || fx_devs == 0) {
82  die("Cannot find 0:0x18.[0|1]\n");
83  }
84 }
85 
86 static u32 f1_read_config32(unsigned int reg)
87 {
88  if (fx_devs == 0)
89  get_fx_devs();
90  return pci_read_config32(__f1_dev[0], reg);
91 }
92 
93 static void f1_write_config32(unsigned int reg, u32 value)
94 {
95  int i;
96  if (fx_devs == 0)
97  get_fx_devs();
98  for (i = 0; i < fx_devs; i++) {
99  struct device *dev;
100  dev = __f1_dev[i];
101  if (dev && dev->enabled) {
102  pci_write_config32(dev, reg, value);
103  }
104  }
105 }
106 
107 static int get_dram_base_limit(u32 nodeid, resource_t *basek, resource_t *limitk)
108 {
109  u32 temp;
110 
111  if (fx_devs == 0)
112  get_fx_devs();
113 
114 
115  temp = pci_read_config32(__f1_dev[nodeid], 0x40 + (nodeid << 3)); //[39:24] at [31:16]
116  if (!(temp & 1))
117  return 0; // this memory range is not enabled
118  /*
119  * BKDG: {DramBase[35:24], 00_0000h} <= address[35:0] so shift left by 8 bits
120  * for physical address and the convert to KiB by shifting 10 bits left
121  */
122  *basek = ((temp & 0x0fff0000)) >> (10 - 8);
123  /*
124  * BKDG address[35:0] <= {DramLimit[35:24], FF_FFFFh} converted as above but
125  * ORed with 0xffff to get real limit before shifting.
126  */
127  temp = pci_read_config32(__f1_dev[nodeid], 0x44 + (nodeid << 3)); //[39:24] at [31:16]
128  *limitk = ((temp & 0x0fff0000) | 0xffff) >> (10 - 8);
129  *limitk += 1; // round up last byte
130 
131  return 1;
132 }
133 
134 static u32 amdfam14_nodeid(struct device *dev)
135 {
136  return (dev->path.pci.devfn >> 3) - DEV_CDB;
137 }
138 
139 static void northbridge_init(struct device *dev)
140 {
141  printk(BIOS_DEBUG, "Northbridge init\n");
142 }
143 
144 static void set_vga_enable_reg(u32 nodeid, u32 linkn)
145 {
146  u32 val;
147 
148  val = 1 | (nodeid << 4) | (linkn << 12);
149  /* it will routing (1)mmio 0xa0000:0xbffff (2) io 0x3b0:0x3bb,
150  0x3c0:0x3df */
151  f1_write_config32(0xf4, val);
152 
153 }
154 
155 static int reg_useable(unsigned int reg, struct device *goal_dev,
156  unsigned int goal_nodeid, unsigned int goal_link)
157 {
158  struct resource *res;
159  unsigned int nodeid, link = 0;
160  int result;
161  res = 0;
162  for (nodeid = 0; !res && (nodeid < fx_devs); nodeid++) {
163  struct device *dev;
164  dev = __f0_dev[nodeid];
165  if (!dev)
166  continue;
167  for (link = 0; !res && (link < 8); link++) {
168  res = probe_resource(dev, IOINDEX(0x1000 + reg, link));
169  }
170  }
171  result = 2;
172  if (res) {
173  result = 0;
174  if ((goal_link == (link - 1)) &&
175  (goal_nodeid == (nodeid - 1)) && (res->flags <= 1)) {
176  result = 1;
177  }
178  }
179  return result;
180 }
181 
182 static struct resource *amdfam14_find_iopair(struct device *dev,
183  unsigned int nodeid, unsigned int link)
184 {
185  struct resource *resource;
186  u32 result, reg;
187  resource = 0;
188  reg = 0;
189  result = reg_useable(0xc0, dev, nodeid, link);
190  if (result >= 1) {
191  /* I have been allocated this one */
192  reg = 0xc0;
193  }
194  /* Ext conf space */
195  if (!reg) {
196  /* Because of Extend conf space, we will never run out of reg,
197  * but we need one index to differ them. So,same node and same
198  * link can have multi range
199  */
201  reg = 0x110 + (index << 24) + (4 << 20); // index could be 0, 255
202  }
203 
204  resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
205 
206  return resource;
207 }
208 
209 static struct resource *amdfam14_find_mempair(struct device *dev, u32 nodeid,
210  u32 link)
211 {
212  struct resource *resource;
213  u32 free_reg, reg;
214  resource = 0;
215  free_reg = 0;
216  for (reg = 0x80; reg <= 0xb8; reg += 0x8) {
217  int result;
218  result = reg_useable(reg, dev, nodeid, link);
219  if (result == 1) {
220  /* I have been allocated this one */
221  break;
222  } else if (result > 1) {
223  /* I have a free register pair */
224  free_reg = reg;
225  }
226  }
227  if (reg > 0xb8) {
228  reg = free_reg;
229  }
230  /* Ext conf space */
231  if (!reg) {
232  /* Because of Extend conf space, we will never run out of reg,
233  * but we need one index to differ them. So,same node and same
234  * link can have multi range
235  */
237  reg = 0x110 + (index << 24) + (6 << 20); // index could be 0, 63
238 
239  }
240  resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
241  return resource;
242 }
243 
244 static void amdfam14_link_read_bases(struct device *dev, u32 nodeid, u32 link)
245 {
246  struct resource *resource;
247 
248  /* Initialize the io space constraints on the current bus */
249  resource = amdfam14_find_iopair(dev, nodeid, link);
250  if (resource) {
251  u32 align;
253  resource->base = 0;
254  resource->size = 0;
255  resource->align = align;
256  resource->gran = align;
257  resource->limit = 0xffffUL;
259  }
260 
261  /* Initialize the prefetchable memory constraints on the current bus */
262  resource = amdfam14_find_mempair(dev, nodeid, link);
263  if (resource) {
264  resource->base = 0;
265  resource->size = 0;
268  resource->limit = 0xffffffffffULL;
271  }
272 
273  /* Initialize the memory constraints on the current bus */
274  resource = amdfam14_find_mempair(dev, nodeid, link);
275  if (resource) {
276  resource->base = 0;
277  resource->size = 0;
280  resource->limit = 0xffffffffffULL;
282  }
283 }
284 
285 static u32 my_find_pci_tolm(struct bus *bus, u32 tolm)
286 {
287  struct resource *min;
288  unsigned long mask_match = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
289  min = 0;
290  search_bus_resources(bus, mask_match, mask_match, tolm_test,
291  &min);
292  if (min && tolm > min->base) {
293  tolm = min->base;
294  }
295  return tolm;
296 }
297 
298 #if CONFIG_HW_MEM_HOLE_SIZEK != 0
299 
300 struct hw_mem_hole_info {
301  unsigned int hole_startk;
302  int node_id;
303 };
304 
305 static struct hw_mem_hole_info get_hw_mem_hole_info(void)
306 {
307  struct hw_mem_hole_info mem_hole;
308 
309  mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK;
310  mem_hole.node_id = -1;
311 
312  resource_t basek, limitk;
313  u32 hole;
314 
315  if (get_dram_base_limit(0, &basek, &limitk)) {
316  hole = pci_read_config32(__f1_dev[0], 0xf0);
317  if (hole & 1) { // we find the hole
318  mem_hole.hole_startk = (hole & (0xff << 24)) >> 10;
319  mem_hole.node_id = 0; // record the node No with hole
320  }
321  }
322  return mem_hole;
323 }
324 #endif
325 
326 static void nb_read_resources(struct device *dev)
327 {
328  u32 nodeid;
329  struct bus *link;
330 
331  printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
332 
334  for (link = dev->link_list; link; link = link->next) {
335  if (link->children) {
337  }
338  }
339 
340  /*
341  * This MMCONF resource must be reserved in the PCI domain.
342  * It is not honored by the coreboot resource allocator if it is in
343  * the CPU_CLUSTER.
344  */
346 }
347 
348 static void set_resource(struct device *dev, struct resource *resource,
349  u32 nodeid)
350 {
351  resource_t rbase, rend;
352  unsigned int reg, link_num;
353  char buf[50];
354 
355  printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
356 
357  /* Make certain the resource has actually been set */
358  if (!(resource->flags & IORESOURCE_ASSIGNED)) {
359  return;
360  }
361 
362  /* If I have already stored this resource don't worry about it */
364  return;
365  }
366 
367  /* Only handle PCI memory and IO resources */
369  return;
370 
371  /* Ensure I am actually looking at a resource of function 1 */
372  if ((resource->index & 0xffff) < 0x1000) {
373  return;
374  }
375  /* Get the base address */
376  rbase = resource->base;
377 
378  /* Get the limit (rounded up) */
379  rend = resource_end(resource);
380 
381  /* Get the register and link */
382  reg = resource->index & 0xfff; // 4k
384 
385  if (resource->flags & IORESOURCE_IO) {
386  set_io_addr_reg(dev, nodeid, link_num, reg, rbase >> 8,
387  rend >> 8);
388  } else if (resource->flags & IORESOURCE_MEM) {
390  rbase >> 8, rend >> 8, 1); // [39:8]
391  }
393  snprintf(buf, sizeof(buf), " <node %x link %x>", nodeid, link_num);
395 }
396 
397 #if CONFIG(CONSOLE_VGA_MULTI)
398 extern struct device *vga_pri; // the primary vga device, defined in device.c
399 #endif
400 
401 static void create_vga_resource(struct device *dev, unsigned int nodeid)
402 {
403  struct bus *link;
404 
405  printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
406 
407  /* find out which link the VGA card is connected,
408  * we only deal with the 'first' vga card */
409  for (link = dev->link_list; link; link = link->next) {
410  if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
411 #if CONFIG(CONSOLE_VGA_MULTI)
413  "VGA: vga_pri bus num = %d bus range [%d,%d]\n",
414  vga_pri->bus->secondary, link->secondary,
415  link->subordinate);
416  /* We need to make sure the vga_pri is under the link */
417  if ((vga_pri->bus->secondary >= link->secondary) &&
418  (vga_pri->bus->secondary <= link->subordinate))
419 #endif
420  break;
421  }
422  }
423 
424  /* no VGA card installed */
425  if (link == NULL)
426  return;
427 
428  printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n",
429  dev_path(dev), nodeid, link->link_num);
431 }
432 
433 static void nb_set_resources(struct device *dev)
434 {
435  unsigned int nodeid;
436  struct bus *bus;
437  struct resource *res;
438 
439  printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
440 
441  /* Find the nodeid */
442  nodeid = amdfam14_nodeid(dev);
443 
445 
446  /* Set each resource we have found */
447  for (res = dev->resource_list; res; res = res->next) {
448  set_resource(dev, res, nodeid);
449  }
450 
451  for (bus = dev->link_list; bus; bus = bus->next) {
452  if (bus->children) {
454  }
455  }
456 }
457 
458 /* Domain/Root Complex related code */
459 
460 static void domain_read_resources(struct device *dev)
461 {
462  unsigned int reg;
463 
464  printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
465 
466  /* Find the already assigned resource pairs */
467  get_fx_devs();
468  for (reg = 0x80; reg <= 0xc0; reg += 0x08) {
469  u32 base, limit;
470  base = f1_read_config32(reg);
471  limit = f1_read_config32(reg + 0x04);
472  /* Is this register allocated? */
473  if ((base & 3) != 0) {
474  unsigned int nodeid, reg_link;
475  struct device *reg_dev;
476  if (reg < 0xc0) { // mmio
477  nodeid = (limit & 0xf) + (base & 0x30);
478  } else { // io
479  nodeid = (limit & 0xf) + ((base >> 4) & 0x30);
480  }
481  reg_link = (limit >> 4) & 7;
482  reg_dev = __f0_dev[nodeid];
483  if (reg_dev) {
484  /* Reserve the resource */
485  struct resource *res;
486  res =
487  new_resource(reg_dev,
488  IOINDEX(0x1000 + reg,
489  reg_link));
490  if (res) {
491  res->flags = 1;
492  }
493  }
494  }
495  }
496  /* FIXME: do we need to check extend conf space?
497  I don't believe that much preset value */
498 
500 }
501 
502 static void domain_set_resources(struct device *dev)
503 {
504  printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
505  printk(BIOS_DEBUG, " amsr - incoming dev = %p\n", dev);
506 
507  unsigned long mmio_basek;
508  u32 pci_tolm;
509  int idx;
510  struct bus *link;
511 #if CONFIG_HW_MEM_HOLE_SIZEK != 0
512  struct hw_mem_hole_info mem_hole;
513 #endif
514 
515  pci_tolm = 0xffffffffUL;
516  for (link = dev->link_list; link; link = link->next) {
517  pci_tolm = my_find_pci_tolm(link, pci_tolm);
518  }
519 
520  // FIXME handle interleaved nodes. If you fix this here, please fix
521  // amdk8, too.
522  mmio_basek = pci_tolm >> 10;
523  /* Round mmio_basek to something the processor can support */
524  mmio_basek &= ~((1 << 6) - 1);
525 
526  // FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M
527  // MMIO hole. If you fix this here, please fix amdk8, too.
528  /* Round the mmio hole to 64M */
529  mmio_basek &= ~((64 * 1024) - 1);
530 
531 #if CONFIG_HW_MEM_HOLE_SIZEK != 0
532 /* if the hw mem hole is already set in raminit stage, here we will compare
533  * mmio_basek and hole_basek. if mmio_basek is bigger that hole_basek and will
534  * use hole_basek as mmio_basek and we don't need to reset hole.
535  * otherwise We reset the hole to the mmio_basek
536  */
537 
538  mem_hole = get_hw_mem_hole_info();
539 
540  // Use hole_basek as mmio_basek, and we don't need to reset hole anymore
541  if ((mem_hole.node_id != -1) && (mmio_basek > mem_hole.hole_startk))
542  mmio_basek = mem_hole.hole_startk;
543 #endif
544 
545  idx = 0x10;
546  resource_t basek, limitk, sizek; // 4 1T
547 
548  if (get_dram_base_limit(0, &basek, &limitk)) {
549  sizek = limitk - basek;
550 
551  printk(BIOS_DEBUG, "adsr: basek = %llx, limitk = %llx, sizek = %llx.\n",
552  basek, limitk, sizek);
553 
554  /* See if we need a hole from 0xa0000 (640K) to 0xbffff (768K) */
555  if (basek < 640 && sizek > 768) {
556  printk(BIOS_DEBUG,"adsr - 0xa0000 to 0xbffff resource.\n");
557  ram_resource(dev, (idx | 0), basek, 640 - basek);
558  idx += 0x10;
559  basek = 768;
560  sizek = limitk - basek;
561  }
562 
564  "adsr: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",
565  mmio_basek, basek, limitk);
566 
567  /* split the region to accommodate pci memory space */
568  if ((basek < 4 * 1024 * 1024) && (limitk > mmio_basek)) {
569  if (basek <= mmio_basek) {
570  unsigned int pre_sizek;
571  pre_sizek = mmio_basek - basek;
572  if (pre_sizek > 0) {
573  ram_resource(dev, idx, basek,
574  pre_sizek);
575  idx += 0x10;
576  sizek -= pre_sizek;
577  }
578  basek = mmio_basek;
579  }
580  if ((basek + sizek) <= 4 * 1024 * 1024) {
581  sizek = 0;
582  } else {
583  basek = 4 * 1024 * 1024;
584  sizek -= (4 * 1024 * 1024 - mmio_basek);
585  }
586  }
587 
588  ram_resource(dev, (idx | 0), basek, sizek);
589  idx += 0x10;
591  "%d: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n", 0,
592  mmio_basek, basek, limitk);
593  }
594  printk(BIOS_DEBUG, " adsr - mmio_basek = %lx.\n", mmio_basek);
595 
597 
598  for (link = dev->link_list; link; link = link->next) {
599  if (link->children) {
600  assign_resources(link);
601  }
602  }
603  printk(BIOS_DEBUG, " adsr - leaving this lovely routine.\n");
604 }
605 
606 static const char *domain_acpi_name(const struct device *dev)
607 {
608  if (dev->path.type == DEVICE_PATH_DOMAIN)
609  return "PCI0";
610 
611  return NULL;
612 }
613 
614 /* Bus related code */
615 
616 static void cpu_bus_scan(struct device *dev)
617 {
618  struct bus *cpu_bus = dev->link_list;
619  struct device *cpu;
620  int apic_id, cores_found;
621 
622  /* There is only one node for fam14, but there may be multiple cores. */
623  cpu = pcidev_on_root(0x18, 0);
624  if (!cpu)
625  printk(BIOS_ERR, "%02x:%02x.0 not found", 0, 0x18);
626 
627  cores_found = (pci_read_config32(pcidev_on_root(0x18, 0x3),
628  0xe8) >> 12) & 3;
629  printk(BIOS_DEBUG, " AP siblings=%d\n", cores_found);
630 
631  for (apic_id = 0; apic_id <= cores_found; apic_id++) {
632  cpu = add_cpu_device(cpu_bus, apic_id, 1);
633  if (cpu)
634  amd_cpu_topology(cpu, 0, apic_id);
635  }
636 }
637 
638 static void cpu_bus_init(struct device *dev)
639 {
641 }
642 
643 /* North Bridge Structures */
644 
646 {
647  msr_t msr;
648  char pscope[] = "\\_SB.PCI0";
649 
650  acpigen_write_scope(pscope);
651  msr = rdmsr(TOP_MEM);
652  acpigen_write_name_dword("TOM1", msr.lo);
653  msr = rdmsr(TOP_MEM2);
654  /*
655  * Since XP only implements parts of ACPI 2.0, we can't use a qword
656  * here.
657  * See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt
658  * slide 22ff.
659  * Shift value right by 20 bit to make it fit into 32bit,
660  * giving us 1MB granularity and a limit of almost 4Exabyte of memory.
661  */
662  acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20);
663  acpigen_pop_len();
664 }
665 
666 static unsigned long acpi_fill_hest(acpi_hest_t *hest)
667 {
668  void *addr, *current;
669 
670  /* Skip the HEST header. */
671  current = (void *)(hest + 1);
672 
674  if (addr != NULL)
675  current += acpi_create_hest_error_source(hest, current, 0,
676  addr + 2, *(UINT16 *)addr - 2);
677 
679  if (addr != NULL)
680  current += acpi_create_hest_error_source(hest, current, 1,
681  addr + 2, *(UINT16 *)addr - 2);
682 
683  return (unsigned long)current;
684 }
685 
687 {
688  unsigned int len = ssdt->length - sizeof(acpi_header_t);
689  unsigned int i;
690 
691  for (i = sizeof(acpi_header_t); i < len; i++) {
692  /* Search for _PR_ scope and replace it with _SB_ */
693  if (*(uint32_t *)((unsigned long)ssdt + i) == 0x5f52505f)
694  *(uint32_t *)((unsigned long)ssdt + i) = 0x5f42535f;
695  }
696  /* Recalculate checksum */
697  ssdt->checksum = 0;
698  ssdt->checksum = acpi_checksum((void *)ssdt, ssdt->length);
699 }
700 
701 static unsigned long agesa_write_acpi_tables(const struct device *device,
702  unsigned long current,
703  acpi_rsdp_t *rsdp)
704 {
705  acpi_srat_t *srat;
706  acpi_slit_t *slit;
707  acpi_header_t *ssdt;
708  acpi_header_t *alib;
709  acpi_hest_t *hest;
710 
711  /* HEST */
712  current = ALIGN(current, 8);
713  hest = (acpi_hest_t *)current;
715  acpi_add_table(rsdp, hest);
716  current += hest->header.length;
717 
718  /* SRAT */
719  current = ALIGN(current, 8);
720  printk(BIOS_DEBUG, "ACPI: * SRAT at %lx\n", current);
722  if (srat != NULL) {
723  memcpy((void *)current, srat, srat->header.length);
724  srat = (acpi_srat_t *) current;
725  current += srat->header.length;
726  acpi_add_table(rsdp, srat);
727  }
728  else {
729  printk(BIOS_DEBUG, " AGESA SRAT table NULL. Skipping.\n");
730  }
731 
732  /* SLIT */
733  current = ALIGN(current, 8);
734  printk(BIOS_DEBUG, "ACPI: * SLIT at %lx\n", current);
736  if (slit != NULL) {
737  memcpy((void *)current, slit, slit->header.length);
738  slit = (acpi_slit_t *) current;
739  current += slit->header.length;
740  acpi_add_table(rsdp, slit);
741  }
742  else {
743  printk(BIOS_DEBUG, " AGESA SLIT table NULL. Skipping.\n");
744  }
745 
746  /* SSDT */
747  current = ALIGN(current, 16);
748  printk(BIOS_DEBUG, "ACPI: * AGESA ALIB SSDT at %lx\n", current);
750  if (alib != NULL) {
751  memcpy((void *)current, alib, alib->length);
752  alib = (acpi_header_t *) current;
753  current += alib->length;
754  acpi_add_table(rsdp, (void *)alib);
755  } else {
756  printk(BIOS_DEBUG, " AGESA ALIB SSDT table NULL. Skipping.\n");
757  }
758 
759  /* The DSDT needs additional work for the AGESA SSDT Pstate table */
760  /* Keep the comment for a while. */
761  current = ALIGN(current, 16);
762  printk(BIOS_DEBUG, "ACPI: * AGESA SSDT Pstate at %lx\n", current);
764  if (ssdt != NULL) {
765  hexdump(ssdt, ssdt->length);
767  hexdump(ssdt, ssdt->length);
768  memcpy((void *)current, ssdt, ssdt->length);
769  ssdt = (acpi_header_t *) current;
770  current += ssdt->length;
771  acpi_add_table(rsdp,ssdt);
772  } else {
773  printk(BIOS_DEBUG, " AGESA SSDT Pstate table NULL. Skipping.\n");
774  }
775 
776  return current;
777 }
778 
781  .set_resources = nb_set_resources,
782  .enable_resources = pci_dev_enable_resources,
783  .acpi_fill_ssdt = northbridge_fill_ssdt_generator,
784  .write_acpi_tables = agesa_write_acpi_tables,
785  .init = northbridge_init,
786  .enable = 0,.ops_pci = 0,
787 };
788 
789 static const struct pci_driver northbridge_driver __pci_driver = {
790  .ops = &northbridge_operations,
791  .vendor = PCI_VID_AMD,
792  .device = 0x1510,
793 };
794 
796  CHIP_NAME("AMD Family 14h Northbridge")
797  .enable_dev = 0,
798 };
799 
800 /* Root Complex Structures */
801 
802 static struct device_operations pci_domain_ops = {
804  .set_resources = domain_set_resources,
805  .scan_bus = pci_domain_scan_bus,
806  .acpi_name = domain_acpi_name,
807 };
808 
809 static struct device_operations cpu_bus_ops = {
811  .set_resources = noop_set_resources,
812  .init = cpu_bus_init,
813  .scan_bus = cpu_bus_scan,
814 };
815 
816 static void root_complex_enable_dev(struct device *dev)
817 {
818  /* Set the operations if it is a special bus type */
819  if (dev->path.type == DEVICE_PATH_DOMAIN) {
820  dev->ops = &pci_domain_ops;
821  } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
822  dev->ops = &cpu_bus_ops;
823  }
824 }
825 
827  CHIP_NAME("AMD Family 14h Root Complex")
828  .enable_dev = root_complex_enable_dev,
829 };
830 
831 /********************************************************************
832 * Change the vendor / device IDs to match the generic VBIOS header.
833 ********************************************************************/
835 {
836  u32 new_vendev = vendev;
837 
838  switch (vendev) {
839  case 0x10029809:
840  case 0x10029808:
841  case 0x10029807:
842  case 0x10029806:
843  case 0x10029805:
844  case 0x10029804:
845  case 0x10029803:
846  new_vendev = 0x10029802;
847  break;
848  }
849 
850  return new_vendev;
851 }
void acpi_add_table(acpi_rsdp_t *rsdp, void *table)
Add an ACPI table to the RSDT (and XSDT) structure, recalculate length and checksum.
Definition: acpi.c:49
u8 acpi_checksum(u8 *table, u32 length)
Definition: acpi.c:35
unsigned long acpi_create_hest_error_source(acpi_hest_t *hest, acpi_hest_esd_t *esd, u16 type, void *data, u16 data_len)
Definition: acpi.c:1372
void acpi_write_hest(acpi_hest_t *hest, unsigned long(*acpi_fill_hest)(acpi_hest_t *hest))
Definition: acpi.c:1433
void acpigen_pop_len(void)
Definition: acpigen.c:37
void acpigen_write_scope(const char *name)
Definition: acpigen.c:326
void acpigen_write_name_dword(const char *name, uint32_t val)
Definition: acpigen.c:158
@ PICK_PSTATE
Definition: agesa_helper.h:11
@ PICK_WHEA_CMC
Definition: agesa_helper.h:15
@ PICK_SRAT
Definition: agesa_helper.h:12
@ PICK_SLIT
Definition: agesa_helper.h:13
@ PICK_WHEA_MCE
Definition: agesa_helper.h:14
@ PICK_ALIB
Definition: agesa_helper.h:16
#define TOP_MEM
Definition: mtrr.h:34
#define TOP_MEM2
Definition: mtrr.h:35
void add_uma_resource_below_tolm(struct device *nb, int idx)
Definition: amd_mtrr.c:8
pte_t value
Definition: mmu.c:91
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
static u32 addr
Definition: cirrus.c:14
#define printk(level,...)
Definition: stdlib.h:16
void __noreturn die(const char *fmt,...)
Definition: die.c:17
static __always_inline unsigned long nodeid(void)
Definition: smihandler.c:53
struct device * add_cpu_device(struct bus *cpu_bus, unsigned int apic_id, int enabled)
Definition: cpu_device.c:6
void assign_resources(struct bus *bus)
Assign the computed resources to the devices on the bus.
Definition: device.c:268
struct device * vga_pri
Definition: device.c:186
DEVTREE_CONST struct device * pcidev_on_root(uint8_t dev, uint8_t fn)
Definition: device_const.c:260
struct resource * new_resource(struct device *dev, unsigned int index)
See if a resource structure already exists for a given index and if not allocate one.
Definition: device_util.c:346
void mmconf_resource(struct device *dev, unsigned long index)
Definition: device_util.c:857
void tolm_test(void *gp, struct device *dev, struct resource *new)
Definition: device_util.c:870
struct resource * probe_resource(const struct device *dev, unsigned int index)
See if a resource structure already exists for a given index.
Definition: device_util.c:323
void report_resource_stored(struct device *dev, const struct resource *resource, const char *comment)
Print the resource that was just stored.
Definition: device_util.c:508
resource_t resource_end(const struct resource *resource)
Compute the maximum address that is part of a resource.
Definition: device_util.c:445
void search_bus_resources(struct bus *bus, unsigned long type_mask, unsigned long type, resource_search_t search, void *gp)
Definition: device_util.c:531
const char * dev_path(const struct device *dev)
Definition: device_util.c:149
void * agesawrapper_getlateinitptr(int pick)
Definition: acpi_tables.c:34
struct acpi_table_header acpi_header_t
#define ALIGN
Definition: asm.h:22
#define MMIO_CONF_BASE
Definition: msr.h:24
static __always_inline msr_t rdmsr(unsigned int index)
Definition: msr.h:146
#define CHIP_NAME(X)
Definition: device.h:32
static void noop_read_resources(struct device *dev)
Standard device operations function pointers shims.
Definition: device.h:73
static void noop_set_resources(struct device *dev)
Definition: device.h:74
#define ram_resource(dev, idx, basek, sizek)
Definition: device.h:321
#define amd_cpu_topology(cpu, node, core)
Definition: device.h:233
static __always_inline void pci_write_config32(const struct device *dev, u16 reg, u32 val)
Definition: pci_ops.h:76
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
void initialize_cpus(struct bus *cpu_bus)
void hexdump(const void *memory, size_t length)
Definition: hexdump.c:7
static int log2(u32 x)
Definition: lib.h:53
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
static uint8_t * buf
Definition: uart.c:7
result
Definition: mrc_cache.c:35
#define HT_IO_HOST_ALIGN
Definition: nb_common.h:6
#define DEV_CDB
Definition: nb_common.h:9
#define HT_MEM_HOST_ALIGN
Definition: nb_common.h:7
static void cpu_bus_init(struct device *dev)
Definition: northbridge.c:638
static void get_fx_devs(void)
Definition: northbridge.c:70
static void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index, u32 mmio_min, u32 mmio_max, u32 nodes)
Definition: northbridge.c:53
#define FX_DEVS
Definition: northbridge.c:21
struct chip_operations northbridge_amd_agesa_family14_root_complex_ops
Definition: northbridge.c:826
static u32 my_find_pci_tolm(struct bus *bus, u32 tolm)
Definition: northbridge.c:285
static struct device_operations cpu_bus_ops
Definition: northbridge.c:809
static int reg_useable(unsigned int reg, struct device *goal_dev, unsigned int goal_nodeid, unsigned int goal_link)
Definition: northbridge.c:155
static void nb_read_resources(struct device *dev)
Definition: northbridge.c:326
static int get_dram_base_limit(u32 nodeid, resource_t *basek, resource_t *limitk)
Definition: northbridge.c:107
static const struct pci_driver northbridge_driver __pci_driver
Definition: northbridge.c:789
static struct resource * amdfam14_find_iopair(struct device *dev, unsigned int nodeid, unsigned int link)
Definition: northbridge.c:182
static struct device_operations pci_domain_ops
Definition: northbridge.c:802
static struct device * __f4_dev[FX_DEVS]
Definition: northbridge.c:26
static void set_io_addr_reg(struct device *dev, u32 nodeid, u32 linkn, u32 reg, u32 io_min, u32 io_max)
Definition: northbridge.c:39
static void root_complex_enable_dev(struct device *dev)
Definition: northbridge.c:816
static u32 get_mmio_addr_index(u32 nodeid, u32 linkn)
Definition: northbridge.c:34
static void f1_write_config32(unsigned int reg, u32 value)
Definition: northbridge.c:93
static void set_resource(struct device *dev, struct resource *resource, u32 nodeid)
Definition: northbridge.c:348
u32 map_oprom_vendev(u32 vendev)
Definition: northbridge.c:834
static void create_vga_resource(struct device *dev, unsigned int nodeid)
Definition: northbridge.c:401
static void northbridge_fill_ssdt_generator(const struct device *device)
Definition: northbridge.c:645
static struct resource * amdfam14_find_mempair(struct device *dev, u32 nodeid, u32 link)
Definition: northbridge.c:209
static void cpu_bus_scan(struct device *dev)
Definition: northbridge.c:616
static unsigned int fx_devs
Definition: northbridge.c:27
static void nb_set_resources(struct device *dev)
Definition: northbridge.c:433
static struct device * __f1_dev[FX_DEVS]
Definition: northbridge.c:24
static struct device_operations northbridge_operations
Definition: northbridge.c:779
static u32 amdfam14_nodeid(struct device *dev)
Definition: northbridge.c:134
static void set_vga_enable_reg(u32 nodeid, u32 linkn)
Definition: northbridge.c:144
static struct device * get_node_pci(u32 nodeid, u32 fn)
Definition: northbridge.c:65
static void domain_set_resources(struct device *dev)
Definition: northbridge.c:502
struct chip_operations northbridge_amd_agesa_family14_ops
Definition: northbridge.c:795
static unsigned long agesa_write_acpi_tables(const struct device *device, unsigned long current, acpi_rsdp_t *rsdp)
Definition: northbridge.c:701
static void amdfam14_link_read_bases(struct device *dev, u32 nodeid, u32 link)
Definition: northbridge.c:244
static const char * domain_acpi_name(const struct device *dev)
Definition: northbridge.c:606
static unsigned long acpi_fill_hest(acpi_hest_t *hest)
Definition: northbridge.c:666
static void domain_read_resources(struct device *dev)
Definition: northbridge.c:460
static u32 f1_read_config32(unsigned int reg)
Definition: northbridge.c:86
static struct device * __f0_dev[FX_DEVS]
Definition: northbridge.c:23
static void patch_ssdt_processor_scope(acpi_header_t *ssdt)
Definition: northbridge.c:686
static struct device * __f2_dev[FX_DEVS]
Definition: northbridge.c:25
static void northbridge_init(struct device *dev)
Definition: northbridge.c:139
static u32 get_io_addr_index(u32 nodeid, u32 linkn)
Definition: northbridge.c:29
@ DEVICE_PATH_CPU_CLUSTER
Definition: path.h:14
@ DEVICE_PATH_DOMAIN
Definition: path.h:13
#define PCI_BRIDGE_CTL_VGA
Definition: pci_def.h:139
void pci_domain_read_resources(struct device *dev)
Definition: pci_device.c:547
void pci_dev_enable_resources(struct device *dev)
Definition: pci_device.c:721
void pci_domain_scan_bus(struct device *dev)
Scan a PCI domain.
Definition: pci_device.c:1610
#define PCI_VID_AMD
Definition: pci_ids.h:496
#define IOINDEX(IDX, LINK)
Definition: resource.h:60
#define IORESOURCE_MEM
Definition: resource.h:10
#define IORESOURCE_STORED
Definition: resource.h:32
#define IORESOURCE_ASSIGNED
Definition: resource.h:34
#define IORESOURCE_IO
Definition: resource.h:9
u64 resource_t
Definition: resource.h:43
#define IOINDEX_LINK(IDX)
Definition: resource.h:61
#define IORESOURCE_PREFETCH
Definition: resource.h:17
#define IORESOURCE_BRIDGE
Definition: resource.h:26
uintptr_t base
Definition: uart.c:17
#define NULL
Definition: stddef.h:19
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
acpi_header_t header
Definition: acpi.h:877
Definition: acpi.h:82
acpi_header_t header
Definition: acpi.h:347
acpi_header_t header
Definition: acpi.h:291
Definition: device.h:76
DEVTREE_CONST struct bus * next
Definition: device.h:80
unsigned int bridge_ctrl
Definition: device.h:81
DEVTREE_CONST struct device * children
Definition: device.h:79
unsigned char link_num
Definition: device.h:83
uint16_t subordinate
Definition: device.h:85
DEVTREE_CONST struct device * dev
Definition: device.h:78
uint16_t secondary
Definition: device.h:84
void(* read_resources)(struct device *dev)
Definition: device.h:39
struct pci_path pci
Definition: path.h:116
enum device_path_type type
Definition: path.h:114
Definition: device.h:107
struct device_path path
Definition: device.h:115
struct device_operations * ops
Definition: device.h:143
DEVTREE_CONST struct bus * bus
Definition: device.h:108
DEVTREE_CONST struct bus * link_list
Definition: device.h:139
DEVTREE_CONST struct resource * resource_list
Definition: device.h:134
unsigned int enabled
Definition: device.h:122
unsigned int hi
Definition: msr.h:112
unsigned int lo
Definition: msr.h:111
unsigned int devfn
Definition: path.h:54
unsigned long flags
Definition: resource.h:49
unsigned char align
Definition: resource.h:51
resource_t limit
Definition: resource.h:47
unsigned char gran
Definition: resource.h:52
resource_t base
Definition: resource.h:45
unsigned long index
Definition: resource.h:50
resource_t size
Definition: resource.h:46
DEVTREE_CONST struct resource * next
Definition: resource.h:48
u8 val
Definition: sys.c:300
int snprintf(char *buf, size_t size, const char *fmt,...)
Note: This file is only for POSIX compatibility, and is meant to be chain-included via string....
Definition: vsprintf.c:35
typedef void(X86APIP X86EMU_intrFuncs)(int num)