blob: 19fb81415e7316bc0cc83693c91fbac0f5e4d315 [file] [log] [blame]
WANG Siyuan05639412015-05-20 14:44:32 +08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2015 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.
WANG Siyuan05639412015-05-20 14:44:32 +080014 */
15
16#include <console/console.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020017#include <device/pci_ops.h>
WANG Siyuan05639412015-05-20 14:44:32 +080018#include <arch/acpi.h>
19#include <stdint.h>
20#include <device/device.h>
21#include <device/pci.h>
22#include <device/pci_ids.h>
23#include <device/hypertransport.h>
24#include <stdlib.h>
25#include <string.h>
26#include <lib.h>
27#include <cpu/cpu.h>
WANG Siyuan05639412015-05-20 14:44:32 +080028#include <Porting.h>
29#include <AGESA.h>
30#include <FieldAccessors.h>
WANG Siyuan05639412015-05-20 14:44:32 +080031#include <Topology.h>
Elyes HAOUAS400ce552018-10-12 10:54:30 +020032#include <cpu/x86/lapic.h>
33#include <cpu/amd/msr.h>
34#include <cpu/amd/mtrr.h>
Elyes HAOUAS400ce552018-10-12 10:54:30 +020035#include <arch/acpigen.h>
Kyösti Mälkkibbd23772019-01-10 05:41:23 +020036#include <northbridge/amd/pi/nb_common.h>
Kyösti Mälkkied8d2772017-07-15 17:12:44 +030037#include <northbridge/amd/agesa/agesa_helper.h>
Kyösti Mälkki903ce252016-11-25 11:21:02 +020038#if IS_ENABLED(CONFIG_BINARYPI_LEGACY_WRAPPER)
WANG Siyuan05639412015-05-20 14:44:32 +080039#include <northbridge/amd/pi/agesawrapper.h>
40#include <northbridge/amd/pi/agesawrapper_call.h>
Kyösti Mälkki903ce252016-11-25 11:21:02 +020041#endif
WANG Siyuan05639412015-05-20 14:44:32 +080042
Kyösti Mälkki113f6702018-05-20 20:12:32 +030043#define MAX_NODE_NUMS MAX_NODES
WANG Siyuan05639412015-05-20 14:44:32 +080044
WANG Siyuan05639412015-05-20 14:44:32 +080045typedef struct dram_base_mask {
46 u32 base; //[47:27] at [28:8]
47 u32 mask; //[47:27] at [28:8] and enable at bit 0
48} dram_base_mask_t;
49
50static unsigned node_nums;
51static unsigned sblink;
Kyösti Mälkki90ac7362018-05-20 20:59:52 +030052static struct device *__f0_dev[MAX_NODE_NUMS];
53static struct device *__f1_dev[MAX_NODE_NUMS];
54static struct device *__f2_dev[MAX_NODE_NUMS];
55static struct device *__f4_dev[MAX_NODE_NUMS];
WANG Siyuan05639412015-05-20 14:44:32 +080056static unsigned fx_devs = 0;
57
58static dram_base_mask_t get_dram_base_mask(u32 nodeid)
59{
Kyösti Mälkki90ac7362018-05-20 20:59:52 +030060 struct device *dev;
WANG Siyuan05639412015-05-20 14:44:32 +080061 dram_base_mask_t d;
62 dev = __f1_dev[0];
63 u32 temp;
64 temp = pci_read_config32(dev, 0x44 + (nodeid << 3)); //[39:24] at [31:16]
65 d.mask = ((temp & 0xfff80000) >> (8 + 3)); // mask out DramMask [26:24] too
66 temp = pci_read_config32(dev, 0x144 + (nodeid << 3)) & 0xff; //[47:40] at [7:0]
67 d.mask |= temp << 21;
68 temp = pci_read_config32(dev, 0x40 + (nodeid << 3)); //[39:24] at [31:16]
69 d.mask |= (temp & 1); // enable bit
70 d.base = ((temp & 0xfff80000) >> (8 + 3)); // mask out DramBase [26:24) too
71 temp = pci_read_config32(dev, 0x140 + (nodeid << 3)) & 0xff; //[47:40] at [7:0]
72 d.base |= temp << 21;
73 return d;
74}
75
Kyösti Mälkki90ac7362018-05-20 20:59:52 +030076static void set_io_addr_reg(struct device *dev, u32 nodeid, u32 linkn, u32 reg,
WANG Siyuan05639412015-05-20 14:44:32 +080077 u32 io_min, u32 io_max)
78{
79 u32 i;
80 u32 tempreg;
81 /* io range allocation */
82 tempreg = (nodeid & 0xf) | ((nodeid & 0x30) << (8 - 4)) | (linkn << 4) | ((io_max & 0xf0)<<(12 - 4)); //limit
83 for (i = 0; i < node_nums; i++)
84 pci_write_config32(__f1_dev[i], reg + 4, tempreg);
85 tempreg = 3 | ((io_min & 0xf0) << (12 - 4)); //base :ISA and VGA ?
86 for (i = 0; i < node_nums; i++)
87 pci_write_config32(__f1_dev[i], reg, tempreg);
88}
89
90static void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index, u32 mmio_min, u32 mmio_max, u32 nodes)
91{
92 u32 i;
93 u32 tempreg;
94 /* io range allocation */
95 tempreg = (nodeid&0xf) | (linkn<<4) | (mmio_max&0xffffff00); //limit
Elyes HAOUASa8131602016-09-19 10:27:57 -060096 for (i = 0; i < nodes; i++)
WANG Siyuan05639412015-05-20 14:44:32 +080097 pci_write_config32(__f1_dev[i], reg+4, tempreg);
98 tempreg = 3 | (nodeid & 0x30) | (mmio_min&0xffffff00);
Elyes HAOUASa8131602016-09-19 10:27:57 -060099 for (i = 0; i < node_nums; i++)
WANG Siyuan05639412015-05-20 14:44:32 +0800100 pci_write_config32(__f1_dev[i], reg, tempreg);
101}
102
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300103static struct device *get_node_pci(u32 nodeid, u32 fn)
WANG Siyuan05639412015-05-20 14:44:32 +0800104{
Kyösti Mälkkibbd23772019-01-10 05:41:23 +0200105 return pcidev_on_root(DEV_CDB + nodeid, fn);
WANG Siyuan05639412015-05-20 14:44:32 +0800106}
107
108static void get_fx_devs(void)
109{
110 int i;
111 for (i = 0; i < MAX_NODE_NUMS; i++) {
112 __f0_dev[i] = get_node_pci(i, 0);
113 __f1_dev[i] = get_node_pci(i, 1);
114 __f2_dev[i] = get_node_pci(i, 2);
115 __f4_dev[i] = get_node_pci(i, 4);
116 if (__f0_dev[i] != NULL && __f1_dev[i] != NULL)
117 fx_devs = i+1;
118 }
119 if (__f1_dev[0] == NULL || __f0_dev[0] == NULL || fx_devs == 0) {
120 die("Cannot find 0:0x18.[0|1]\n");
121 }
Elyes HAOUASa8131602016-09-19 10:27:57 -0600122 printk(BIOS_DEBUG, "fx_devs = 0x%x\n", fx_devs);
WANG Siyuan05639412015-05-20 14:44:32 +0800123}
124
125static u32 f1_read_config32(unsigned reg)
126{
127 if (fx_devs == 0)
128 get_fx_devs();
129 return pci_read_config32(__f1_dev[0], reg);
130}
131
132static void f1_write_config32(unsigned reg, u32 value)
133{
134 int i;
135 if (fx_devs == 0)
136 get_fx_devs();
Elyes HAOUAS5a7e72f2016-08-23 21:36:02 +0200137 for (i = 0; i < fx_devs; i++) {
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300138 struct device *dev;
WANG Siyuan05639412015-05-20 14:44:32 +0800139 dev = __f1_dev[i];
140 if (dev && dev->enabled) {
141 pci_write_config32(dev, reg, value);
142 }
143 }
144}
145
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300146static u32 amdfam15_nodeid(struct device *dev)
WANG Siyuan05639412015-05-20 14:44:32 +0800147{
Kyösti Mälkkibbd23772019-01-10 05:41:23 +0200148 return (dev->path.pci.devfn >> 3) - DEV_CDB;
WANG Siyuan05639412015-05-20 14:44:32 +0800149}
150
151static void set_vga_enable_reg(u32 nodeid, u32 linkn)
152{
153 u32 val;
154
155 val = 1 | (nodeid << 4) | (linkn<<12);
156 /* it will routing
157 * (1)mmio 0xa0000:0xbffff
158 * (2)io 0x3b0:0x3bb, 0x3c0:0x3df
159 */
160 f1_write_config32(0xf4, val);
161
162}
163
164/**
165 * @return
166 * @retval 2 resoure does not exist, usable
167 * @retval 0 resource exists, not usable
168 * @retval 1 resource exist, resource has been allocated before
169 */
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300170static int reg_useable(unsigned reg, struct device *goal_dev, unsigned goal_nodeid,
WANG Siyuan05639412015-05-20 14:44:32 +0800171 unsigned goal_link)
172{
173 struct resource *res;
174 unsigned nodeid, link = 0;
175 int result;
176 res = 0;
177 for (nodeid = 0; !res && (nodeid < fx_devs); nodeid++) {
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300178 struct device *dev;
WANG Siyuan05639412015-05-20 14:44:32 +0800179 dev = __f0_dev[nodeid];
180 if (!dev)
181 continue;
182 for (link = 0; !res && (link < 8); link++)
183 res = probe_resource(dev, IOINDEX(0x1000 + reg, link));
184 }
185
186 if (!res)
187 result = 2;
188 else if ((goal_link == (link - 1)) &&
189 (goal_nodeid == (nodeid - 1)) &&
190 (res->flags <= 1)) {
191 result = 1;
192 }
193 else
194 result = 0;
195
196 return result;
197}
198
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300199static struct resource *amdfam15_find_iopair(struct device *dev, unsigned nodeid, unsigned link)
WANG Siyuan05639412015-05-20 14:44:32 +0800200{
201 struct resource *resource;
202 u32 free_reg, reg;
203 resource = 0;
204 free_reg = 0;
205 for (reg = 0xc0; reg <= 0xd8; reg += 0x8) {
206 int result;
207 result = reg_useable(reg, dev, nodeid, link);
208 if (result >= 1) {
209 free_reg = reg;
210 }
211 if (result == 1) {
212 /* resource allocated */
213 break;
214 }
215 }
216 resource = new_resource(dev, IOINDEX(0x1000 + free_reg, link));
217 return resource;
218}
219
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300220static struct resource *amdfam15_find_mempair(struct device *dev, u32 nodeid, u32 link)
WANG Siyuan05639412015-05-20 14:44:32 +0800221{
222 struct resource *resource;
223 u32 free_reg, reg;
224 resource = 0;
225 free_reg = 0;
226 for (reg = 0x80; reg <= 0xb8; reg += 0x8) {
227 int result;
228 result = reg_useable(reg, dev, nodeid, link);
229 if (result >= 1) {
230 free_reg = reg;
231 }
232 if (result == 1) {
233 /* I have been allocated this one */
234 break;
235 }
236 }
237 resource = new_resource(dev, IOINDEX(0x1000 + free_reg, link));
238 return resource;
239}
240
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300241static void amdfam15_link_read_bases(struct device *dev, u32 nodeid, u32 link)
WANG Siyuan05639412015-05-20 14:44:32 +0800242{
243 struct resource *resource;
244
245 /* Initialize the io space constraints on the current bus */
246 resource = amdfam15_find_iopair(dev, nodeid, link);
247 if (resource) {
248 resource->base = 0;
249 resource->size = 0;
250 resource->align = log2(HT_IO_HOST_ALIGN);
251 resource->gran = log2(HT_IO_HOST_ALIGN);
252 resource->limit = 0xffffUL;
253 resource->flags = IORESOURCE_IO | IORESOURCE_BRIDGE;
254 }
255
256 /* Initialize the prefetchable memory constraints on the current bus */
257 resource = amdfam15_find_mempair(dev, nodeid, link);
258 if (resource) {
259 resource->base = 0;
260 resource->size = 0;
261 resource->align = log2(HT_MEM_HOST_ALIGN);
262 resource->gran = log2(HT_MEM_HOST_ALIGN);
263 resource->limit = 0xffffffffffULL;
264 resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
265 resource->flags |= IORESOURCE_BRIDGE;
266 }
267
268 /* Initialize the memory constraints on the current bus */
269 resource = amdfam15_find_mempair(dev, nodeid, link);
270 if (resource) {
271 resource->base = 0;
272 resource->size = 0;
273 resource->align = log2(HT_MEM_HOST_ALIGN);
274 resource->gran = log2(HT_MEM_HOST_ALIGN);
275 resource->limit = 0xffffffffffULL;
276 resource->flags = IORESOURCE_MEM | IORESOURCE_BRIDGE;
277 }
278
279}
280
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300281static void read_resources(struct device *dev)
WANG Siyuan05639412015-05-20 14:44:32 +0800282{
283 u32 nodeid;
284 struct bus *link;
285
286 nodeid = amdfam15_nodeid(dev);
287 for (link = dev->link_list; link; link = link->next) {
288 if (link->children) {
289 amdfam15_link_read_bases(dev, nodeid, link->link_num);
290 }
291 }
Kyösti Mälkki625b9442015-05-27 07:58:22 +0300292
293 /*
294 * This MMCONF resource must be reserved in the PCI domain.
295 * It is not honored by the coreboot resource allocator if it is in
296 * the CPU_CLUSTER.
297 */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200298 mmconf_resource(dev, MMIO_CONF_BASE);
WANG Siyuan05639412015-05-20 14:44:32 +0800299}
300
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300301static void set_resource(struct device *dev, struct resource *resource, u32 nodeid)
WANG Siyuan05639412015-05-20 14:44:32 +0800302{
303 resource_t rbase, rend;
304 unsigned reg, link_num;
305 char buf[50];
306
307 /* Make certain the resource has actually been set */
308 if (!(resource->flags & IORESOURCE_ASSIGNED))
309 return;
310
311 /* If I have already stored this resource don't worry about it */
312 if (resource->flags & IORESOURCE_STORED)
313 return;
314
315 /* Only handle PCI memory and IO resources */
316 if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
317 return;
318
319 /* Ensure I am actually looking at a resource of function 1 */
320 if ((resource->index & 0xffff) < 0x1000)
321 return;
322
323 /* Get the base address */
324 rbase = resource->base;
325
326 /* Get the limit (rounded up) */
327 rend = resource_end(resource);
328
329 /* Get the register and link */
330 reg = resource->index & 0xfff; // 4k
331 link_num = IOINDEX_LINK(resource->index);
332
333 if (resource->flags & IORESOURCE_IO) {
334 set_io_addr_reg(dev, nodeid, link_num, reg, rbase>>8, rend>>8);
335 }
336 else if (resource->flags & IORESOURCE_MEM) {
Elyes HAOUAS7db506c2016-10-02 11:56:39 +0200337 set_mmio_addr_reg(nodeid, link_num, reg, (resource->index >>24), rbase>>8, rend>>8, node_nums); // [39:8]
WANG Siyuan05639412015-05-20 14:44:32 +0800338 }
339 resource->flags |= IORESOURCE_STORED;
340 snprintf(buf, sizeof(buf), " <node %x link %x>",
341 nodeid, link_num);
342 report_resource_stored(dev, resource, buf);
343}
344
345/**
346 * I tried to reuse the resource allocation code in set_resource()
347 * but it is too difficult to deal with the resource allocation magic.
348 */
349
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300350static void create_vga_resource(struct device *dev, unsigned nodeid)
WANG Siyuan05639412015-05-20 14:44:32 +0800351{
352 struct bus *link;
353
354 /* find out which link the VGA card is connected,
355 * we only deal with the 'first' vga card */
356 for (link = dev->link_list; link; link = link->next) {
357 if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
Martin Roth77a58b92017-06-24 14:45:48 -0600358#if IS_ENABLED(CONFIG_MULTIPLE_VGA_ADAPTERS)
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300359 extern struct device *vga_pri; // the primary vga device, defined in device.c
WANG Siyuan05639412015-05-20 14:44:32 +0800360 printk(BIOS_DEBUG, "VGA: vga_pri bus num = %d bus range [%d,%d]\n", vga_pri->bus->secondary,
361 link->secondary,link->subordinate);
362 /* We need to make sure the vga_pri is under the link */
Elyes HAOUASa8131602016-09-19 10:27:57 -0600363 if ((vga_pri->bus->secondary >= link->secondary) &&
364 (vga_pri->bus->secondary <= link->subordinate))
WANG Siyuan05639412015-05-20 14:44:32 +0800365#endif
366 break;
367 }
368 }
369
370 /* no VGA card installed */
371 if (link == NULL)
372 return;
373
374 printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, sblink);
375 set_vga_enable_reg(nodeid, sblink);
376}
377
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300378static void set_resources(struct device *dev)
WANG Siyuan05639412015-05-20 14:44:32 +0800379{
380 unsigned nodeid;
381 struct bus *bus;
382 struct resource *res;
383
384 /* Find the nodeid */
385 nodeid = amdfam15_nodeid(dev);
386
387 /* do we need this? */
388 create_vga_resource(dev, nodeid);
389
390 /* Set each resource we have found */
391 for (res = dev->resource_list; res; res = res->next) {
392 set_resource(dev, res, nodeid);
393 }
394
395 for (bus = dev->link_list; bus; bus = bus->next) {
396 if (bus->children) {
397 assign_resources(bus);
398 }
399 }
400}
401
402static void northbridge_init(struct device *dev)
403{
404}
405
406static unsigned long acpi_fill_hest(acpi_hest_t *hest)
407{
408 void *addr, *current;
409
410 /* Skip the HEST header. */
411 current = (void *)(hest + 1);
412
413 addr = agesawrapper_getlateinitptr(PICK_WHEA_MCE);
414 if (addr != NULL)
415 current += acpi_create_hest_error_source(hest, current, 0, (void *)((u32)addr + 2), *(UINT16 *)addr - 2);
416
417 addr = agesawrapper_getlateinitptr(PICK_WHEA_CMC);
418 if (addr != NULL)
419 current += acpi_create_hest_error_source(hest, current, 1, (void *)((u32)addr + 2), *(UINT16 *)addr - 2);
420
421 return (unsigned long)current;
422}
423
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300424static void northbridge_fill_ssdt_generator(struct device *device)
WANG Siyuan05639412015-05-20 14:44:32 +0800425{
426 msr_t msr;
427 char pscope[] = "\\_SB.PCI0";
428
429 acpigen_write_scope(pscope);
430 msr = rdmsr(TOP_MEM);
431 acpigen_write_name_dword("TOM1", msr.lo);
432 msr = rdmsr(TOP_MEM2);
433 /*
434 * Since XP only implements parts of ACPI 2.0, we can't use a qword
435 * here.
436 * See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt
437 * slide 22ff.
438 * Shift value right by 20 bit to make it fit into 32bit,
439 * giving us 1MB granularity and a limit of almost 4Exabyte of memory.
440 */
441 acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20);
442 acpigen_pop_len();
443}
444
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300445static unsigned long agesa_write_acpi_tables(struct device *device,
WANG Siyuan05639412015-05-20 14:44:32 +0800446 unsigned long current,
447 acpi_rsdp_t *rsdp)
448{
449 acpi_srat_t *srat;
450 acpi_slit_t *slit;
451 acpi_header_t *ssdt;
452 acpi_header_t *alib;
453 acpi_header_t *ivrs;
454 acpi_hest_t *hest;
455
456 /* HEST */
457 current = ALIGN(current, 8);
458 hest = (acpi_hest_t *)current;
459 acpi_write_hest((void *)current, acpi_fill_hest);
460 acpi_add_table(rsdp, (void *)current);
461 current += ((acpi_header_t *)current)->length;
462
463 current = ALIGN(current, 8);
464 printk(BIOS_DEBUG, "ACPI: * IVRS at %lx\n", current);
465 ivrs = agesawrapper_getlateinitptr(PICK_IVRS);
466 if (ivrs != NULL) {
467 memcpy((void *)current, ivrs, ivrs->length);
468 ivrs = (acpi_header_t *) current;
469 current += ivrs->length;
470 acpi_add_table(rsdp, ivrs);
471 } else {
472 printk(BIOS_DEBUG, " AGESA IVRS table NULL. Skipping.\n");
473 }
474
475 /* SRAT */
476 current = ALIGN(current, 8);
477 printk(BIOS_DEBUG, "ACPI: * SRAT at %lx\n", current);
478 srat = (acpi_srat_t *) agesawrapper_getlateinitptr (PICK_SRAT);
479 if (srat != NULL) {
480 memcpy((void *)current, srat, srat->header.length);
481 srat = (acpi_srat_t *) current;
482 current += srat->header.length;
483 acpi_add_table(rsdp, srat);
484 } else {
485 printk(BIOS_DEBUG, " AGESA SRAT table NULL. Skipping.\n");
486 }
487
488 /* SLIT */
489 current = ALIGN(current, 8);
490 printk(BIOS_DEBUG, "ACPI: * SLIT at %lx\n", current);
491 slit = (acpi_slit_t *) agesawrapper_getlateinitptr (PICK_SLIT);
492 if (slit != NULL) {
493 memcpy((void *)current, slit, slit->header.length);
494 slit = (acpi_slit_t *) current;
495 current += slit->header.length;
496 acpi_add_table(rsdp, slit);
497 } else {
498 printk(BIOS_DEBUG, " AGESA SLIT table NULL. Skipping.\n");
499 }
500
501 /* ALIB */
502 current = ALIGN(current, 16);
503 printk(BIOS_DEBUG, "ACPI: * AGESA ALIB SSDT at %lx\n", current);
504 alib = (acpi_header_t *)agesawrapper_getlateinitptr (PICK_ALIB);
505 if (alib != NULL) {
506 memcpy((void *)current, alib, alib->length);
507 alib = (acpi_header_t *) current;
508 current += alib->length;
509 acpi_add_table(rsdp, (void *)alib);
510 }
511 else {
512 printk(BIOS_DEBUG, " AGESA ALIB SSDT table NULL. Skipping.\n");
513 }
514
515 /* this pstate ssdt may cause Blue Screen: Fixed: Keep this comment for a while. */
516 /* SSDT */
517 current = ALIGN(current, 16);
518 printk(BIOS_DEBUG, "ACPI: * SSDT at %lx\n", current);
519 ssdt = (acpi_header_t *)agesawrapper_getlateinitptr (PICK_PSTATE);
520 if (ssdt != NULL) {
521 memcpy((void *)current, ssdt, ssdt->length);
522 ssdt = (acpi_header_t *) current;
523 current += ssdt->length;
524 }
525 else {
526 printk(BIOS_DEBUG, " AGESA PState table NULL. Skipping.\n");
527 }
528 acpi_add_table(rsdp,ssdt);
529
530 printk(BIOS_DEBUG, "ACPI: * SSDT for PState at %lx\n", current);
531 return current;
532}
533
534static struct device_operations northbridge_operations = {
535 .read_resources = read_resources,
536 .set_resources = set_resources,
537 .enable_resources = pci_dev_enable_resources,
538 .init = northbridge_init,
539 .acpi_fill_ssdt_generator = northbridge_fill_ssdt_generator,
540 .write_acpi_tables = agesa_write_acpi_tables,
541 .enable = 0,
542 .ops_pci = 0,
543};
544
545static const struct pci_driver family15_northbridge __pci_driver = {
546 .ops = &northbridge_operations,
547 .vendor = PCI_VENDOR_ID_AMD,
Marshall Dawson463f46e2016-10-14 20:46:08 -0600548 .device = PCI_DEVICE_ID_AMD_15H_MODEL_606F_NB_HT,
WANG Siyuan05639412015-05-20 14:44:32 +0800549};
550
551static void fam15_finalize(void *chip_info)
552{
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300553 struct device *dev;
WANG Siyuan05639412015-05-20 14:44:32 +0800554 u32 value;
Kyösti Mälkki33ff44c2018-05-22 01:15:22 +0300555 dev = pcidev_on_root(0, 0); /* clear IoapicSbFeatureEn */
WANG Siyuan05639412015-05-20 14:44:32 +0800556 pci_write_config32(dev, 0xF8, 0);
557 pci_write_config32(dev, 0xFC, 5); /* TODO: move it to dsdt.asl */
558
559 /* disable No Snoop */
Kyösti Mälkki33ff44c2018-05-22 01:15:22 +0300560 dev = pcidev_on_root(1, 1);
Kyösti Mälkki69f6fd42019-01-21 14:19:01 +0200561 if (dev != NULL) {
562 value = pci_read_config32(dev, 0x60);
563 value &= ~(1 << 11);
564 pci_write_config32(dev, 0x60, value);
565 }
WANG Siyuan05639412015-05-20 14:44:32 +0800566}
567
568struct chip_operations northbridge_amd_pi_00660F01_ops = {
569 CHIP_NAME("AMD FAM15 Northbridge")
570 .enable_dev = 0,
571 .final = fam15_finalize,
572};
573
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300574static void domain_read_resources(struct device *dev)
WANG Siyuan05639412015-05-20 14:44:32 +0800575{
576 unsigned reg;
577
578 /* Find the already assigned resource pairs */
579 get_fx_devs();
580 for (reg = 0x80; reg <= 0xd8; reg += 0x08) {
581 u32 base, limit;
582 base = f1_read_config32(reg);
583 limit = f1_read_config32(reg + 0x04);
584 /* Is this register allocated? */
585 if ((base & 3) != 0) {
586 unsigned nodeid, reg_link;
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300587 struct device *reg_dev;
WANG Siyuan05639412015-05-20 14:44:32 +0800588 if (reg < 0xc0) { // mmio
589 nodeid = (limit & 0xf) + (base & 0x30);
590 } else { // io
591 nodeid = (limit & 0xf) + ((base >> 4) & 0x30);
592 }
593 reg_link = (limit >> 4) & 7;
594 reg_dev = __f0_dev[nodeid];
595 if (reg_dev) {
596 /* Reserve the resource */
597 struct resource *res;
598 res = new_resource(reg_dev, IOINDEX(0x1000 + reg, reg_link));
599 if (res) {
600 res->flags = 1;
601 }
602 }
603 }
604 }
605 /* FIXME: do we need to check extend conf space?
606 I don't believe that much preset value */
607
608 pci_domain_read_resources(dev);
609}
610
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300611static void domain_enable_resources(struct device *dev)
WANG Siyuan05639412015-05-20 14:44:32 +0800612{
Kyösti Mälkki903ce252016-11-25 11:21:02 +0200613#if IS_ENABLED(CONFIG_BINARYPI_LEGACY_WRAPPER)
WANG Siyuan05639412015-05-20 14:44:32 +0800614 /* Must be called after PCI enumeration and resource allocation */
615 if (!acpi_is_wakeup_s3())
616 AGESAWRAPPER(amdinitmid);
617
618 printk(BIOS_DEBUG, " ader - leaving domain_enable_resources.\n");
Kyösti Mälkki903ce252016-11-25 11:21:02 +0200619#endif
WANG Siyuan05639412015-05-20 14:44:32 +0800620}
621
622#if CONFIG_HW_MEM_HOLE_SIZEK != 0
623struct hw_mem_hole_info {
624 unsigned hole_startk;
625 int node_id;
626};
627static struct hw_mem_hole_info get_hw_mem_hole_info(void)
628{
629 struct hw_mem_hole_info mem_hole;
630 int i;
631 mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK;
632 mem_hole.node_id = -1;
633 for (i = 0; i < node_nums; i++) {
634 dram_base_mask_t d;
635 u32 hole;
636 d = get_dram_base_mask(i);
637 if (!(d.mask & 1)) continue; // no memory on this node
638 hole = pci_read_config32(__f1_dev[i], 0xf0);
639 if (hole & 2) {
640 /* we find the hole */
641 mem_hole.hole_startk = (hole & (0xff<<24)) >> 10;
642 mem_hole.node_id = i; // record the node No with hole
643 break; // only one hole
644 }
645 }
646
647 /* We need to double check if there is special set on base reg and limit reg
648 * are not continuous instead of hole, it will find out its hole_startk.
649 */
650 if (mem_hole.node_id == -1) {
651 resource_t limitk_pri = 0;
652 for (i = 0; i < node_nums; i++) {
653 dram_base_mask_t d;
654 resource_t base_k, limit_k;
655 d = get_dram_base_mask(i);
656 if (!(d.base & 1))
657 continue;
658 base_k = ((resource_t)(d.base & 0x1fffff00)) <<9;
659 if (base_k > 4 *1024 * 1024) break; // don't need to go to check
660 if (limitk_pri != base_k) { // we find the hole
661 mem_hole.hole_startk = (unsigned)limitk_pri; // must beblow 4G
662 mem_hole.node_id = i;
663 break; //only one hole
664 }
665 limit_k = ((resource_t)(((d.mask & ~1) + 0x000FF) & 0x1fffff00)) << 9;
666 limitk_pri = limit_k;
667 }
668 }
669 return mem_hole;
670}
671#endif
672
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300673static void domain_set_resources(struct device *dev)
WANG Siyuan05639412015-05-20 14:44:32 +0800674{
675 unsigned long mmio_basek;
676 u32 pci_tolm;
WANG Siyuan05639412015-05-20 14:44:32 +0800677 int i, idx;
678 struct bus *link;
679#if CONFIG_HW_MEM_HOLE_SIZEK != 0
680 struct hw_mem_hole_info mem_hole;
681 u32 reset_memhole = 1;
682#endif
683
684 pci_tolm = 0xffffffffUL;
685 for (link = dev->link_list; link; link = link->next) {
686 pci_tolm = find_pci_tolm(link);
687 }
688
689 mmio_basek = pci_tolm >> 10;
690 /* Round mmio_basek to something the processor can support */
691 mmio_basek &= ~((1 << 6) -1);
692
693 /* FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M
694 * MMIO hole. If you fix this here, please fix amdk8, too.
695 */
696 /* Round the mmio hole to 64M */
697 mmio_basek &= ~((64*1024) - 1);
698
699#if CONFIG_HW_MEM_HOLE_SIZEK != 0
700 /* if the hw mem hole is already set in raminit stage, here we will compare
701 * mmio_basek and hole_basek. if mmio_basek is bigger that hole_basek and will
702 * use hole_basek as mmio_basek and we don't need to reset hole.
703 * otherwise We reset the hole to the mmio_basek
704 */
705
706 mem_hole = get_hw_mem_hole_info();
707
708 /* Use hole_basek as mmio_basek, and we don't need to reset hole anymore */
709 if ((mem_hole.node_id != -1) && (mmio_basek > mem_hole.hole_startk)) {
710 mmio_basek = mem_hole.hole_startk;
711 reset_memhole = 0;
712 }
713#endif
714
715 idx = 0x10;
716 for (i = 0; i < node_nums; i++) {
717 dram_base_mask_t d;
718 resource_t basek, limitk, sizek; // 4 1T
719
720 d = get_dram_base_mask(i);
721
722 if (!(d.mask & 1))
723 continue;
724 basek = ((resource_t)(d.base & 0x1fffff00)) << 9; // could overflow, we may lost 6 bit here
Elyes HAOUAS7db506c2016-10-02 11:56:39 +0200725 limitk = ((resource_t)(((d.mask & ~1) + 0x000FF) & 0x1fffff00)) << 9;
WANG Siyuan05639412015-05-20 14:44:32 +0800726
727 sizek = limitk - basek;
728
729 /* see if we need a hole from 0xa0000 to 0xbffff */
730 if ((basek < ((8*64)+(8*16))) && (sizek > ((8*64)+(16*16)))) {
731 ram_resource(dev, (idx | i), basek, ((8*64)+(8*16)) - basek);
732 idx += 0x10;
733 basek = (8*64)+(16*16);
734 sizek = limitk - ((8*64)+(16*16));
735
736 }
737
738 /* split the region to accommodate pci memory space */
Elyes HAOUASa8131602016-09-19 10:27:57 -0600739 if ((basek < 4*1024*1024) && (limitk > mmio_basek)) {
WANG Siyuan05639412015-05-20 14:44:32 +0800740 if (basek <= mmio_basek) {
741 unsigned pre_sizek;
742 pre_sizek = mmio_basek - basek;
Elyes HAOUASa8131602016-09-19 10:27:57 -0600743 if (pre_sizek > 0) {
WANG Siyuan05639412015-05-20 14:44:32 +0800744 ram_resource(dev, (idx | i), basek, pre_sizek);
745 idx += 0x10;
746 sizek -= pre_sizek;
WANG Siyuan05639412015-05-20 14:44:32 +0800747 }
748 basek = mmio_basek;
749 }
750 if ((basek + sizek) <= 4*1024*1024) {
751 sizek = 0;
752 }
753 else {
754 uint64_t topmem2 = bsp_topmem2();
755 basek = 4*1024*1024;
756 sizek = topmem2/1024 - basek;
757 }
758 }
759
760 ram_resource(dev, (idx | i), basek, sizek);
761 idx += 0x10;
762 printk(BIOS_DEBUG, "node %d: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",
763 i, mmio_basek, basek, limitk);
WANG Siyuan05639412015-05-20 14:44:32 +0800764 }
765
Kyösti Mälkkie87564f2017-04-15 20:07:53 +0300766 add_uma_resource_below_tolm(dev, 7);
WANG Siyuan05639412015-05-20 14:44:32 +0800767
Elyes HAOUAS5a7e72f2016-08-23 21:36:02 +0200768 for (link = dev->link_list; link; link = link->next) {
WANG Siyuan05639412015-05-20 14:44:32 +0800769 if (link->children) {
770 assign_resources(link);
771 }
772 }
773}
774
775static struct device_operations pci_domain_ops = {
776 .read_resources = domain_read_resources,
777 .set_resources = domain_set_resources,
778 .enable_resources = domain_enable_resources,
779 .init = NULL,
780 .scan_bus = pci_domain_scan_bus,
WANG Siyuan05639412015-05-20 14:44:32 +0800781};
782
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300783static void sysconf_init(struct device *dev) // first node
WANG Siyuan05639412015-05-20 14:44:32 +0800784{
785 sblink = (pci_read_config32(dev, 0x64)>>8) & 7; // don't forget sublink1
786 node_nums = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1; // NodeCnt[2:0]
787}
788
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300789static void add_more_links(struct device *dev, unsigned total_links)
WANG Siyuan05639412015-05-20 14:44:32 +0800790{
791 struct bus *link, *last = NULL;
792 int link_num;
793
794 for (link = dev->link_list; link; link = link->next)
795 last = link;
796
797 if (last) {
798 int links = total_links - last->link_num;
799 link_num = last->link_num;
800 if (links > 0) {
801 link = malloc(links*sizeof(*link));
802 if (!link)
803 die("Couldn't allocate more links!\n");
804 memset(link, 0, links*sizeof(*link));
805 last->next = link;
806 }
807 }
808 else {
809 link_num = -1;
810 link = malloc(total_links*sizeof(*link));
811 memset(link, 0, total_links*sizeof(*link));
812 dev->link_list = link;
813 }
814
815 for (link_num = link_num + 1; link_num < total_links; link_num++) {
816 link->link_num = link_num;
817 link->dev = dev;
818 link->next = link + 1;
819 last = link;
820 link = link->next;
821 }
822 last->next = NULL;
823}
824
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300825static void cpu_bus_scan(struct device *dev)
WANG Siyuan05639412015-05-20 14:44:32 +0800826{
827 struct bus *cpu_bus;
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300828 struct device *dev_mc;
WANG Siyuan05639412015-05-20 14:44:32 +0800829 int i,j;
830 int coreid_bits;
831 int core_max = 0;
832 unsigned ApicIdCoreIdSize;
833 unsigned core_nums;
834 int siblings = 0;
835 unsigned int family;
836 u32 modules = 0;
837 VOID* modules_ptr = &modules;
838 BUILD_OPT_CFG* options = NULL;
839 int ioapic_count = 0;
840
841 AmdGetValue(AMD_GLOBAL_USER_OPTIONS, (VOID**)&options, sizeof(options));
842 AmdGetValue(AMD_GLOBAL_NUM_MODULES, &modules_ptr, sizeof(modules));
Stefan Reinauerbc315092017-06-27 00:46:22 +0200843 modules = (*(u32 *)modules_ptr) & ((1ull << (sizeof(modules) * 8)) - 1);
WANG Siyuan05639412015-05-20 14:44:32 +0800844 ASSERT(modules > 0);
845 ASSERT(options);
846 ioapic_count = (int)options->CfgPlatNumIoApics;
847 ASSERT(ioapic_count > 0);
848
Kyösti Mälkkibbd23772019-01-10 05:41:23 +0200849 dev_mc = pcidev_on_root(DEV_CDB, 0);
WANG Siyuan05639412015-05-20 14:44:32 +0800850 if (!dev_mc) {
Kyösti Mälkkibbd23772019-01-10 05:41:23 +0200851 printk(BIOS_ERR, "0:%02x.0 not found", DEV_CDB);
WANG Siyuan05639412015-05-20 14:44:32 +0800852 die("");
853 }
854 sysconf_init(dev_mc);
WANG Siyuan05639412015-05-20 14:44:32 +0800855
856 /* Get Max Number of cores(MNC) */
Kyösti Mälkkid41feed2017-09-24 16:23:57 +0300857 coreid_bits = (cpuid_ecx(0x80000008) & 0x0000F000) >> 12;
WANG Siyuan05639412015-05-20 14:44:32 +0800858 core_max = 1 << (coreid_bits & 0x000F); //mnc
859
860 ApicIdCoreIdSize = ((cpuid_ecx(0x80000008)>>12) & 0xF);
861 if (ApicIdCoreIdSize) {
862 core_nums = (1 << ApicIdCoreIdSize) - 1;
863 } else {
864 core_nums = 3; //quad core
865 }
866
867 /* Find which cpus are present */
868 cpu_bus = dev->link_list;
869 for (i = 0; i < node_nums; i++) {
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300870 struct device *cdb_dev;
Kyösti Mälkkiedf51d22018-05-20 22:38:00 +0300871 unsigned devn;
WANG Siyuan05639412015-05-20 14:44:32 +0800872 struct bus *pbus;
873
Kyösti Mälkkibbd23772019-01-10 05:41:23 +0200874 devn = DEV_CDB + i;
WANG Siyuan05639412015-05-20 14:44:32 +0800875 pbus = dev_mc->bus;
WANG Siyuan05639412015-05-20 14:44:32 +0800876
877 /* Find the cpu's pci device */
Kyösti Mälkki33ff44c2018-05-22 01:15:22 +0300878 cdb_dev = pcidev_on_root(devn, 0);
WANG Siyuan05639412015-05-20 14:44:32 +0800879 if (!cdb_dev) {
880 /* If I am probing things in a weird order
881 * ensure all of the cpu's pci devices are found.
882 */
883 int fn;
Elyes HAOUAS5a7e72f2016-08-23 21:36:02 +0200884 for (fn = 0; fn <= 5; fn++) { //FBDIMM?
WANG Siyuan05639412015-05-20 14:44:32 +0800885 cdb_dev = pci_probe_dev(NULL, pbus,
886 PCI_DEVFN(devn, fn));
887 }
Kyösti Mälkki33ff44c2018-05-22 01:15:22 +0300888 cdb_dev = pcidev_on_root(devn, 0);
WANG Siyuan05639412015-05-20 14:44:32 +0800889 } else {
890 /* Ok, We need to set the links for that device.
891 * otherwise the device under it will not be scanned
892 */
893 add_more_links(cdb_dev, 4);
894 }
895
896 family = cpuid_eax(1);
897 family = (family >> 20) & 0xFF;
898 if (family == 6 || family == 7) {
899 /* f15 and f16 */
Kyösti Mälkki33ff44c2018-05-22 01:15:22 +0300900 cdb_dev = pcidev_on_root(devn, 5);
WANG Siyuan05639412015-05-20 14:44:32 +0800901 if (cdb_dev && cdb_dev->enabled) {
902 siblings = pci_read_config32(cdb_dev, 0x84);
903 siblings &= 0xFF;
904 }
905 } else {
906 /* default one core */
907 siblings = 0;
908 }
909 int enable_node = cdb_dev && cdb_dev->enabled;
Elyes HAOUASa8131602016-09-19 10:27:57 -0600910 printk(BIOS_SPEW, "%s family%xh, core_max = 0x%x, core_nums = 0x%x, siblings = 0x%x\n",
WANG Siyuan05639412015-05-20 14:44:32 +0800911 dev_path(cdb_dev), 0x0f + family, core_max, core_nums, siblings);
912
Elyes HAOUASa8131602016-09-19 10:27:57 -0600913 for (j = 0; j <= siblings; j++) {
WANG Siyuan05639412015-05-20 14:44:32 +0800914 u32 lapicid_start = 0;
915
916 /*
917 * APIC ID calucation is tightly coupled with AGESA v5 code.
918 * This calculation MUST match the assignment calculation done
919 * in LocalApicInitializationAtEarly() function.
920 * And reference GetLocalApicIdForCore()
921 *
922 * Apply apic enumeration rules
923 * For systems with >= 16 APICs, put the IO-APICs at 0..n and
924 * put the local-APICs at m..z
925 *
926 * This is needed because many IO-APIC devices only have 4 bits
927 * for their APIC id and therefore must reside at 0..15
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +0200928 */
WANG Siyuan05639412015-05-20 14:44:32 +0800929 if ((node_nums * core_max) + ioapic_count >= 0x10) {
930 lapicid_start = (ioapic_count - 1) / core_max;
931 lapicid_start = (lapicid_start + 1) * core_max;
Elyes HAOUASa8131602016-09-19 10:27:57 -0600932 printk(BIOS_SPEW, "lpaicid_start = 0x%x ", lapicid_start);
WANG Siyuan05639412015-05-20 14:44:32 +0800933 }
934 u32 apic_id = (lapicid_start * (i/modules + 1)) + ((i % modules) ? (j + (siblings + 1)) : j);
Elyes HAOUASa8131602016-09-19 10:27:57 -0600935 printk(BIOS_SPEW, "node 0x%x core 0x%x apicid = 0x%x\n",
WANG Siyuan05639412015-05-20 14:44:32 +0800936 i, j, apic_id);
937
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300938 struct device *cpu = add_cpu_device(cpu_bus, apic_id, enable_node);
WANG Siyuan05639412015-05-20 14:44:32 +0800939 if (cpu)
940 amd_cpu_topology(cpu, i, j);
941 } //j
942 }
943}
944
Kyösti Mälkki90ac7362018-05-20 20:59:52 +0300945static void cpu_bus_init(struct device *dev)
WANG Siyuan05639412015-05-20 14:44:32 +0800946{
947 initialize_cpus(dev->link_list);
948}
949
WANG Siyuan05639412015-05-20 14:44:32 +0800950static struct device_operations cpu_bus_ops = {
Kyösti Mälkki48f82a92016-12-02 16:02:30 +0200951 .read_resources = DEVICE_NOOP,
952 .set_resources = DEVICE_NOOP,
WANG Siyuan05639412015-05-20 14:44:32 +0800953 .enable_resources = DEVICE_NOOP,
954 .init = cpu_bus_init,
955 .scan_bus = cpu_bus_scan,
956};
957
958static void root_complex_enable_dev(struct device *dev)
959{
960 static int done = 0;
961
WANG Siyuan05639412015-05-20 14:44:32 +0800962 if (!done) {
963 setup_bsp_ramtop();
WANG Siyuan05639412015-05-20 14:44:32 +0800964 done = 1;
965 }
966
967 /* Set the operations if it is a special bus type */
968 if (dev->path.type == DEVICE_PATH_DOMAIN) {
969 dev->ops = &pci_domain_ops;
970 } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
971 dev->ops = &cpu_bus_ops;
972 }
973}
974
975struct chip_operations northbridge_amd_pi_00660F01_root_complex_ops = {
976 CHIP_NAME("AMD FAM16 Root Complex")
977 .enable_dev = root_complex_enable_dev,
978};
979
980/*********************************************************************
981 * Change the vendor / device IDs to match the generic VBIOS header. *
982 *********************************************************************/
983u32 map_oprom_vendev(u32 vendev)
984{
985 u32 new_vendev;
986 new_vendev =
987 ((0x10029870 <= vendev) && (vendev <= 0x1002987F)) ? 0x10029870 : vendev;
988
989 if (vendev != new_vendev)
990 printk(BIOS_NOTICE, "Mapping PCI device %8x to %8x\n", vendev, new_vendev);
991
992 return new_vendev;
993}