blob: 8e3c13c4855cf7630826f223a6596b5976b89600 [file] [log] [blame]
Marc Jones1587dc82017-05-15 18:55:11 -06001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2015-2016 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
16
17#include <arch/io.h>
18#include <arch/acpi.h>
19#include <arch/acpigen.h>
20#include <cbmem.h>
21#include <chip.h>
22#include <console/console.h>
23#include <cpu/amd/amdfam15.h>
24#include <cpu/amd/mtrr.h>
25#include <cpu/cpu.h>
26#include <device/device.h>
27#include <device/pci.h>
28#include <device/pci_ids.h>
29#include <device/hypertransport.h>
30#include <lib.h>
31#include <agesawrapper.h>
32#include <agesawrapper_call.h>
33#include <soc/northbridge.h>
34#include <stdint.h>
35#include <stdlib.h>
36#include <string.h>
37
38/*
39 * AMD vendorcode files. Place at the end so coreboot defaults and maintained
40 * and not set by vendorcode
41 */
42#include <AGESA.h>
43#include <cpuRegisters.h>
44#include <FieldAccessors.h>
45#include <Options.h>
46#include <Porting.h>
47#include <Topology.h>
48
49#define MAX_NODE_NUMS (MAX_NODES * MAX_DIES)
50
Martin Roth59981982017-07-13 11:05:35 -070051#if IS_ENABLED(CONFIG_EXT_CONF_SUPPORT)
Marc Jones1587dc82017-05-15 18:55:11 -060052#error CONFIG_EXT_CONF_SUPPORT == 1 not support anymore!
53#endif
54
55typedef struct dram_base_mask {
Marshall Dawson4e101ad2017-06-15 12:17:38 -060056 u32 base; /* [47:27] at [28:8] */
57 u32 mask; /* [47:27] at [28:8] and enable at bit 0 */
Marc Jones1587dc82017-05-15 18:55:11 -060058} dram_base_mask_t;
59
Marshall Dawson4e101ad2017-06-15 12:17:38 -060060static unsigned int node_nums;
Marc Jones1587dc82017-05-15 18:55:11 -060061static device_t __f0_dev;
62static device_t __f1_dev;
63static device_t __f2_dev;
64static device_t __f4_dev;
Marshall Dawson4e101ad2017-06-15 12:17:38 -060065static unsigned int fx_dev = 0;
Marc Jones1587dc82017-05-15 18:55:11 -060066
67static dram_base_mask_t get_dram_base_mask(u32 nodeid)
68{
69 device_t dev = __f1_dev;
70 dram_base_mask_t d;
71 u32 temp;
Marshall Dawson4e101ad2017-06-15 12:17:38 -060072
73 /* [39:24] at [31:16] */
74 temp = pci_read_config32(dev, 0x44 + (nodeid << 3));
75
76 /* mask out DramMask [26:24] too */
77 d.mask = ((temp & 0xfff80000) >> (8 + 3));
78
79 /* [47:40] at [7:0] */
80 temp = pci_read_config32(dev, 0x144 + (nodeid << 3)) & 0xff;
Marc Jones1587dc82017-05-15 18:55:11 -060081 d.mask |= temp << 21;
Marshall Dawson4e101ad2017-06-15 12:17:38 -060082
83 temp = pci_read_config32(dev, 0x40 + (nodeid << 3));
84 d.mask |= (temp & 1); /* enable bit */
85 d.base = ((temp & 0xfff80000) >> (8 + 3));
86 temp = pci_read_config32(dev, 0x140 + (nodeid << 3)) & 0xff;
Marc Jones1587dc82017-05-15 18:55:11 -060087 d.base |= temp << 21;
88 return d;
89}
90
91static void set_io_addr_reg(device_t dev, u32 nodeid, u32 linkn, u32 reg,
92 u32 io_min, u32 io_max)
93{
94 u32 tempreg;
Marshall Dawson4e101ad2017-06-15 12:17:38 -060095 /* io range allocation. Limit */
96 tempreg = (nodeid & 0xf) | ((nodeid & 0x30) << (8 - 4)) | (linkn << 4)
97 | ((io_max & 0xf0) << (12 - 4));
Marc Jones1587dc82017-05-15 18:55:11 -060098 pci_write_config32(__f1_dev, reg + 4, tempreg);
Marshall Dawson4e101ad2017-06-15 12:17:38 -060099 tempreg = 3 | ((io_min & 0xf0) << (12 - 4)); /* base: ISA and VGA ? */
Marc Jones1587dc82017-05-15 18:55:11 -0600100 pci_write_config32(__f1_dev, reg, tempreg);
101}
102
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600103static void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index,
104 u32 mmio_min, u32 mmio_max)
Marc Jones1587dc82017-05-15 18:55:11 -0600105{
106 u32 tempreg;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600107 /* io range allocation. Limit */
108 tempreg = (nodeid & 0xf) | (linkn << 4) | (mmio_max & 0xffffff00);
Marc Jones1587dc82017-05-15 18:55:11 -0600109 pci_write_config32(__f1_dev, reg + 4, tempreg);
110 tempreg = 3 | (nodeid & 0x30) | (mmio_min & 0xffffff00);
111 pci_write_config32(__f1_dev, reg, tempreg);
112}
113
114static device_t get_node_pci(u32 fn)
115{
116 return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, fn));
117}
118
119static void get_fx_dev(void)
120{
121 __f0_dev = get_node_pci(0);
122 __f1_dev = get_node_pci(1);
123 __f2_dev = get_node_pci(2);
124 __f4_dev = get_node_pci(4);
125 fx_dev = 1;
126
127 if (__f1_dev == NULL || __f0_dev == NULL || fx_dev == 0)
128 die("Cannot find 0:0x18.[0|1]\n");
129}
130
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600131static u32 f1_read_config32(unsigned int reg)
Marc Jones1587dc82017-05-15 18:55:11 -0600132{
133 if (fx_dev == 0)
134 get_fx_dev();
135 return pci_read_config32(__f1_dev, reg);
136}
137
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600138static void f1_write_config32(unsigned int reg, u32 value)
Marc Jones1587dc82017-05-15 18:55:11 -0600139{
140 if (fx_dev == 0)
141 get_fx_dev();
142 pci_write_config32(__f1_dev, reg, value);
143}
144
Marc Jones1587dc82017-05-15 18:55:11 -0600145static void read_resources(device_t dev)
146{
Marc Jones1587dc82017-05-15 18:55:11 -0600147 /*
148 * This MMCONF resource must be reserved in the PCI domain.
149 * It is not honored by the coreboot resource allocator if it is in
150 * the CPU_CLUSTER.
151 */
152 mmconf_resource(dev, 0xc0010058);
153}
154
155static void set_resource(device_t dev, struct resource *resource, u32 nodeid)
156{
157 resource_t rbase, rend;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600158 unsigned int reg, link_num;
Marc Jones1587dc82017-05-15 18:55:11 -0600159 char buf[50];
160
161 /* Make certain the resource has actually been set */
162 if (!(resource->flags & IORESOURCE_ASSIGNED))
163 return;
164
165 /* If I have already stored this resource don't worry about it */
166 if (resource->flags & IORESOURCE_STORED)
167 return;
168
169 /* Only handle PCI memory and IO resources */
170 if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
171 return;
172
173 /* Ensure I am actually looking at a resource of function 1 */
174 if ((resource->index & 0xffff) < 0x1000)
175 return;
176
177 /* Get the base address */
178 rbase = resource->base;
179
180 /* Get the limit (rounded up) */
181 rend = resource_end(resource);
182
183 /* Get the register and link */
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600184 reg = resource->index & 0xfff; /* 4k */
Marc Jones1587dc82017-05-15 18:55:11 -0600185 link_num = IOINDEX_LINK(resource->index);
186
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600187 if (resource->flags & IORESOURCE_IO)
Marc Jones1587dc82017-05-15 18:55:11 -0600188 set_io_addr_reg(dev, nodeid, link_num, reg, rbase>>8, rend>>8);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600189 else if (resource->flags & IORESOURCE_MEM)
190 set_mmio_addr_reg(nodeid, link_num, reg,
191 (resource->index >> 24), rbase >> 8, rend >> 8);
192
Marc Jones1587dc82017-05-15 18:55:11 -0600193 resource->flags |= IORESOURCE_STORED;
194 snprintf(buf, sizeof(buf), " <node %x link %x>",
195 nodeid, link_num);
196 report_resource_stored(dev, resource, buf);
197}
198
199/**
200 * I tried to reuse the resource allocation code in set_resource()
201 * but it is too difficult to deal with the resource allocation magic.
202 */
203
204static void create_vga_resource(device_t dev)
205{
206 struct bus *link;
207
208 /* find out which link the VGA card is connected,
209 * we only deal with the 'first' vga card */
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600210 for (link = dev->link_list ; link ; link = link->next)
Marc Jones1587dc82017-05-15 18:55:11 -0600211 if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA)
212 break;
Marc Jones1587dc82017-05-15 18:55:11 -0600213
214 /* no VGA card installed */
215 if (link == NULL)
216 return;
217
Marshall Dawsone2697de2017-09-06 10:46:36 -0600218 printk(BIOS_DEBUG, "VGA: %s has VGA device\n", dev_path(dev));
219 f1_write_config32(0xf4, 1); /* Route A0000-BFFFF, IO 3B0-3BB 3C0-3DF */
Marc Jones1587dc82017-05-15 18:55:11 -0600220}
221
222static void set_resources(device_t dev)
223{
224 struct bus *bus;
225 struct resource *res;
226
227
228 /* do we need this? */
229 create_vga_resource(dev);
230
231 /* Set each resource we have found */
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600232 for (res = dev->resource_list ; res ; res = res->next)
Marc Jones1587dc82017-05-15 18:55:11 -0600233 set_resource(dev, res, 0);
Marc Jones1587dc82017-05-15 18:55:11 -0600234
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600235 for (bus = dev->link_list ; bus ; bus = bus->next)
236 if (bus->children)
Marc Jones1587dc82017-05-15 18:55:11 -0600237 assign_resources(bus);
Marc Jones1587dc82017-05-15 18:55:11 -0600238}
239
240static void northbridge_init(struct device *dev)
241{
242}
243
244static unsigned long acpi_fill_hest(acpi_hest_t *hest)
245{
246 void *addr, *current;
247
248 /* Skip the HEST header. */
249 current = (void *)(hest + 1);
250
251 addr = agesawrapper_getlateinitptr(PICK_WHEA_MCE);
252 if (addr != NULL)
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600253 current += acpi_create_hest_error_source(hest, current, 0,
254 (void *)((u32)addr + 2), *(UINT16 *)addr - 2);
Marc Jones1587dc82017-05-15 18:55:11 -0600255
256 addr = agesawrapper_getlateinitptr(PICK_WHEA_CMC);
257 if (addr != NULL)
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600258 current += acpi_create_hest_error_source(hest, current, 1,
259 (void *)((u32)addr + 2), *(UINT16 *)addr - 2);
Marc Jones1587dc82017-05-15 18:55:11 -0600260
261 return (unsigned long)current;
262}
263
264static void northbridge_fill_ssdt_generator(device_t device)
265{
266 msr_t msr;
267 char pscope[] = "\\_SB.PCI0";
268
269 acpigen_write_scope(pscope);
270 msr = rdmsr(TOP_MEM);
271 acpigen_write_name_dword("TOM1", msr.lo);
272 msr = rdmsr(TOP_MEM2);
273 /*
274 * Since XP only implements parts of ACPI 2.0, we can't use a qword
275 * here.
276 * See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt
277 * slide 22ff.
278 * Shift value right by 20 bit to make it fit into 32bit,
279 * giving us 1MB granularity and a limit of almost 4Exabyte of memory.
280 */
281 acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20);
282 acpigen_pop_len();
283}
284
285static unsigned long agesa_write_acpi_tables(device_t device,
286 unsigned long current,
287 acpi_rsdp_t *rsdp)
288{
289 acpi_srat_t *srat;
290 acpi_slit_t *slit;
291 acpi_header_t *ssdt;
292 acpi_header_t *alib;
293 acpi_header_t *ivrs;
294 acpi_hest_t *hest;
295
296 /* HEST */
297 current = ALIGN(current, 8);
298 hest = (acpi_hest_t *)current;
299 acpi_write_hest((void *)current, acpi_fill_hest);
300 acpi_add_table(rsdp, (void *)current);
301 current += ((acpi_header_t *)current)->length;
302
303 current = ALIGN(current, 8);
304 printk(BIOS_DEBUG, "ACPI: * IVRS at %lx\n", current);
305 ivrs = agesawrapper_getlateinitptr(PICK_IVRS);
306 if (ivrs != NULL) {
307 memcpy((void *)current, ivrs, ivrs->length);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600308 ivrs = (acpi_header_t *)current;
Marc Jones1587dc82017-05-15 18:55:11 -0600309 current += ivrs->length;
310 acpi_add_table(rsdp, ivrs);
311 } else {
312 printk(BIOS_DEBUG, " AGESA IVRS table NULL. Skipping.\n");
313 }
314
315 /* SRAT */
316 current = ALIGN(current, 8);
317 printk(BIOS_DEBUG, "ACPI: * SRAT at %lx\n", current);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600318 srat = (acpi_srat_t *)agesawrapper_getlateinitptr(PICK_SRAT);
Marc Jones1587dc82017-05-15 18:55:11 -0600319 if (srat != NULL) {
320 memcpy((void *)current, srat, srat->header.length);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600321 srat = (acpi_srat_t *)current;
Marc Jones1587dc82017-05-15 18:55:11 -0600322 current += srat->header.length;
323 acpi_add_table(rsdp, srat);
324 } else {
325 printk(BIOS_DEBUG, " AGESA SRAT table NULL. Skipping.\n");
326 }
327
328 /* SLIT */
329 current = ALIGN(current, 8);
330 printk(BIOS_DEBUG, "ACPI: * SLIT at %lx\n", current);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600331 slit = (acpi_slit_t *)agesawrapper_getlateinitptr(PICK_SLIT);
Marc Jones1587dc82017-05-15 18:55:11 -0600332 if (slit != NULL) {
333 memcpy((void *)current, slit, slit->header.length);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600334 slit = (acpi_slit_t *)current;
Marc Jones1587dc82017-05-15 18:55:11 -0600335 current += slit->header.length;
336 acpi_add_table(rsdp, slit);
337 } else {
338 printk(BIOS_DEBUG, " AGESA SLIT table NULL. Skipping.\n");
339 }
340
341 /* ALIB */
342 current = ALIGN(current, 16);
343 printk(BIOS_DEBUG, "ACPI: * AGESA ALIB SSDT at %lx\n", current);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600344 alib = (acpi_header_t *)agesawrapper_getlateinitptr(PICK_ALIB);
Marc Jones1587dc82017-05-15 18:55:11 -0600345 if (alib != NULL) {
346 memcpy((void *)current, alib, alib->length);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600347 alib = (acpi_header_t *)current;
Marc Jones1587dc82017-05-15 18:55:11 -0600348 current += alib->length;
349 acpi_add_table(rsdp, (void *)alib);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600350 } else {
351 printk(BIOS_DEBUG, " AGESA ALIB SSDT table NULL."
352 " Skipping.\n");
Marc Jones1587dc82017-05-15 18:55:11 -0600353 }
354
Marc Jones1587dc82017-05-15 18:55:11 -0600355 current = ALIGN(current, 16);
356 printk(BIOS_DEBUG, "ACPI: * SSDT at %lx\n", current);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600357 ssdt = (acpi_header_t *)agesawrapper_getlateinitptr(PICK_PSTATE);
Marc Jones1587dc82017-05-15 18:55:11 -0600358 if (ssdt != NULL) {
359 memcpy((void *)current, ssdt, ssdt->length);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600360 ssdt = (acpi_header_t *)current;
Marc Jones1587dc82017-05-15 18:55:11 -0600361 current += ssdt->length;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600362 } else {
Marc Jones1587dc82017-05-15 18:55:11 -0600363 printk(BIOS_DEBUG, " AGESA PState table NULL. Skipping.\n");
364 }
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600365 acpi_add_table(rsdp, ssdt);
Marc Jones1587dc82017-05-15 18:55:11 -0600366
367 printk(BIOS_DEBUG, "ACPI: * SSDT for PState at %lx\n", current);
368 return current;
369}
370
371static struct device_operations northbridge_operations = {
372 .read_resources = read_resources,
373 .set_resources = set_resources,
374 .enable_resources = pci_dev_enable_resources,
375 .init = northbridge_init,
376 .acpi_fill_ssdt_generator = northbridge_fill_ssdt_generator,
377 .write_acpi_tables = agesa_write_acpi_tables,
378 .enable = 0,
379 .ops_pci = 0,
380};
381
382static const struct pci_driver family15_northbridge __pci_driver = {
383 .ops = &northbridge_operations,
384 .vendor = PCI_VENDOR_ID_AMD,
385 .device = PCI_DEVICE_ID_AMD_15H_MODEL_707F_NB_HT,
386};
387
388void fam15_finalize(void *chip_info)
389{
390 device_t dev;
391 u32 value;
392 dev = dev_find_slot(0, PCI_DEVFN(0, 0)); /* clear IoapicSbFeatureEn */
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600393 pci_write_config32(dev, 0xf8, 0);
394 pci_write_config32(dev, 0xfc, 5); /* TODO: move it to dsdt.asl */
Marc Jones1587dc82017-05-15 18:55:11 -0600395
396 /* disable No Snoop */
397 dev = dev_find_slot(0, PCI_DEVFN(1, 1));
398 value = pci_read_config32(dev, 0x60);
399 value &= ~(1 << 11);
400 pci_write_config32(dev, 0x60, value);
401}
402
403void domain_read_resources(device_t dev)
404{
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600405 unsigned int reg;
Marc Jones1587dc82017-05-15 18:55:11 -0600406
407 /* Find the already assigned resource pairs */
408 get_fx_dev();
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600409 for (reg = 0x80 ; reg <= 0xd8 ; reg += 0x08) {
Marc Jones1587dc82017-05-15 18:55:11 -0600410 u32 base, limit;
411 base = f1_read_config32(reg);
412 limit = f1_read_config32(reg + 0x04);
413 /* Is this register allocated? */
414 if ((base & 3) != 0) {
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600415 unsigned int nodeid, reg_link;
Marc Jones1587dc82017-05-15 18:55:11 -0600416 device_t reg_dev;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600417 if (reg < 0xc0) /* mmio */
Marc Jones1587dc82017-05-15 18:55:11 -0600418 nodeid = (limit & 0xf) + (base & 0x30);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600419 else /* io */
Marc Jones1587dc82017-05-15 18:55:11 -0600420 nodeid = (limit & 0xf) + ((base >> 4) & 0x30);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600421
Marc Jones1587dc82017-05-15 18:55:11 -0600422 reg_link = (limit >> 4) & 7;
423 reg_dev = __f0_dev;
424 if (reg_dev) {
425 /* Reserve the resource */
426 struct resource *res;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600427 res = new_resource(reg_dev,
428 IOINDEX(0x1000 + reg,
429 reg_link));
430 if (res)
Marc Jones1587dc82017-05-15 18:55:11 -0600431 res->flags = 1;
Marc Jones1587dc82017-05-15 18:55:11 -0600432 }
433 }
434 }
435 /* FIXME: do we need to check extend conf space?
436 I don't believe that much preset value */
437
438 pci_domain_read_resources(dev);
439}
440
441void domain_enable_resources(device_t dev)
442{
443 if (acpi_is_wakeup_s3())
444 AGESAWRAPPER(fchs3laterestore);
445
446 /* Must be called after PCI enumeration and resource allocation */
447 if (!acpi_is_wakeup_s3())
448 AGESAWRAPPER(amdinitmid);
449
450 printk(BIOS_DEBUG, " ader - leaving domain_enable_resources.\n");
451}
452
453#if CONFIG_HW_MEM_HOLE_SIZEK != 0
454struct hw_mem_hole_info {
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600455 unsigned int hole_startk;
Marc Jones1587dc82017-05-15 18:55:11 -0600456 int node_id;
457};
458
459static struct hw_mem_hole_info get_hw_mem_hole_info(void)
460{
461 struct hw_mem_hole_info mem_hole;
462 mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK;
463 mem_hole.node_id = -1;
464 dram_base_mask_t d;
465 u32 hole;
466 d = get_dram_base_mask(0);
467 hole = pci_read_config32(__f1_dev, 0xf0);
468 if (hole & 2) {
469 /* We found the hole */
470 mem_hole.hole_startk = (hole & (0xff << 24)) >> 10;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600471 mem_hole.node_id = 0; /* record the node # with hole */
Marc Jones1587dc82017-05-15 18:55:11 -0600472 }
473
474 return mem_hole;
475}
476#endif
477
478void domain_set_resources(device_t dev)
479{
480 unsigned long mmio_basek;
481 u32 pci_tolm;
482 int i, idx;
483 struct bus *link;
484#if CONFIG_HW_MEM_HOLE_SIZEK != 0
485 struct hw_mem_hole_info mem_hole;
486 u32 reset_memhole = 1;
487#endif
488
489 pci_tolm = 0xffffffffUL;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600490 for (link = dev->link_list ; link ; link = link->next)
Marc Jones1587dc82017-05-15 18:55:11 -0600491 pci_tolm = find_pci_tolm(link);
Marc Jones1587dc82017-05-15 18:55:11 -0600492
493 mmio_basek = pci_tolm >> 10;
494 /* Round mmio_basek to something the processor can support */
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600495 mmio_basek &= ~((1 << 6) - 1);
Marc Jones1587dc82017-05-15 18:55:11 -0600496
497 /* FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M
498 * MMIO hole. If you fix this here, please fix amdk8, too.
499 */
500 /* Round the mmio hole to 64M */
501 mmio_basek &= ~((64 * 1024) - 1);
502
503#if CONFIG_HW_MEM_HOLE_SIZEK != 0
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600504 /* if the hw mem hole is already set in raminit stage, here we will
505 * compare mmio_basek and hole_basek. if mmio_basek is bigger that
506 * hole_basek and will use hole_basek as mmio_basek and we don't need
507 * to reset hole. Otherwise we reset the hole to the mmio_basek
Marc Jones1587dc82017-05-15 18:55:11 -0600508 */
509
510 mem_hole = get_hw_mem_hole_info();
511
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600512 /* Use hole_basek as mmio_basek, and no need to reset hole anymore */
Marc Jones1587dc82017-05-15 18:55:11 -0600513 if ((mem_hole.node_id != -1) && (mmio_basek > mem_hole.hole_startk)) {
514 mmio_basek = mem_hole.hole_startk;
515 reset_memhole = 0;
516 }
517#endif
518
519 idx = 0x10;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600520 for (i = 0 ; i < node_nums ; i++) {
Marc Jones1587dc82017-05-15 18:55:11 -0600521 dram_base_mask_t d;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600522 resource_t basek, limitk, sizek; /* 4 1T */
Marc Jones1587dc82017-05-15 18:55:11 -0600523
524 d = get_dram_base_mask(i);
525
526 if (!(d.mask & 1))
527 continue;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600528 /* could overflow, we may lose 6 bit here */
529 basek = ((resource_t)(d.base & 0x1fffff00)) << 9;
530 limitk = ((resource_t)(((d.mask & ~1) + 0x000ff)
531 & 0x1fffff00)) << 9;
Marc Jones1587dc82017-05-15 18:55:11 -0600532
533 sizek = limitk - basek;
534
535 /* see if we need a hole from 0xa0000 to 0xbffff */
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600536 if ((basek < ((8 * 64) + (8 * 16))) && (sizek > ((8 * 64) +
537 (16 * 16)))) {
538 ram_resource(dev, (idx | i), basek,
539 ((8 * 64) + (8 * 16)) - basek);
Marc Jones1587dc82017-05-15 18:55:11 -0600540 idx += 0x10;
541 basek = (8 * 64) + (16 * 16);
542 sizek = limitk - ((8 * 64) + (16 * 16));
543
544 }
545
546 /* split the region to accommodate pci memory space */
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600547 if ((basek < 4 * 1024 * 1024) && (limitk > mmio_basek)) {
Marc Jones1587dc82017-05-15 18:55:11 -0600548 if (basek <= mmio_basek) {
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600549 unsigned int pre_sizek;
Marc Jones1587dc82017-05-15 18:55:11 -0600550 pre_sizek = mmio_basek - basek;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600551 if (pre_sizek > 0) {
552 ram_resource(dev, (idx | i), basek,
553 pre_sizek);
Marc Jones1587dc82017-05-15 18:55:11 -0600554 idx += 0x10;
555 sizek -= pre_sizek;
556 }
557 basek = mmio_basek;
558 }
559 if ((basek + sizek) <= 4 * 1024 * 1024) {
560 sizek = 0;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600561 } else {
Marc Jones1587dc82017-05-15 18:55:11 -0600562 uint64_t topmem2 = bsp_topmem2();
563 basek = 4 * 1024 * 1024;
564 sizek = topmem2 / 1024 - basek;
565 }
566 }
567
568 ram_resource(dev, (idx | i), basek, sizek);
569 idx += 0x10;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600570 printk(BIOS_DEBUG, "node %d: mmio_basek=%08lx, basek=%08llx,"
571 " limitk=%08llx\n", i, mmio_basek, basek,
572 limitk);
Marc Jones1587dc82017-05-15 18:55:11 -0600573 }
574
575 add_uma_resource_below_tolm(dev, 7);
576
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600577 for (link = dev->link_list ; link ; link = link->next)
578 if (link->children)
Marc Jones1587dc82017-05-15 18:55:11 -0600579 assign_resources(link);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600580
Marc Jones1587dc82017-05-15 18:55:11 -0600581 /*
582 * Reserve everything between A segment and 1MB:
583 *
584 * 0xa0000 - 0xbffff: legacy VGA
585 * 0xc0000 - 0xfffff: RAM
586 */
587 mmio_resource(dev, 0xa0000, 0xa0000 / KiB, 0x20000 / KiB);
588 reserved_ram_resource(dev, 0xc0000, 0xc0000 / KiB, 0x40000 / KiB);
589}
590
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600591/* first node */
592static void sysconf_init(device_t dev)
Marc Jones1587dc82017-05-15 18:55:11 -0600593{
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600594 /* NodeCnt[2:0] */
595 node_nums = ((pci_read_config32(dev, 0x60) >> 4) & 7) + 1;
Marc Jones1587dc82017-05-15 18:55:11 -0600596}
597
Marc Jones1587dc82017-05-15 18:55:11 -0600598void cpu_bus_scan(device_t dev)
599{
600 struct bus *cpu_bus;
601 device_t cpu;
602 device_t cdb_dev;
603 device_t dev_mc;
604 int j;
605 int core_max;
606 int core_nums;
607 int siblings;
608 int family;
609 int enable_node;
610 u32 lapicid_start;
611 u32 apic_id;
612 u32 pccount;
613
614
615 dev_mc = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 0));
616 if (!dev_mc) {
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600617 printk(BIOS_ERR, "%02x:%02x.0 not found", CONFIG_CBB,
618 CONFIG_CDB);
Marc Jones1587dc82017-05-15 18:55:11 -0600619 die("");
620 }
621 sysconf_init(dev_mc); /* sets global node_nums */
622
623 if (node_nums != 1)
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600624 die("node_nums != 1. This is an SOC."
625 " Something is terribly wrong.");
Marc Jones1587dc82017-05-15 18:55:11 -0600626
627 /* Get max and actual number of cores */
628 pccount = cpuid_ecx(AMD_CPUID_ASIZE_PCCOUNT);
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600629 core_max = 1 << ((pccount >> 12) & 0xf);
Marc Jones1587dc82017-05-15 18:55:11 -0600630 core_nums = (pccount & 0xF);
631
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600632 family = (cpuid_eax(1) >> 20) & 0xff;
Marc Jones1587dc82017-05-15 18:55:11 -0600633
634 cdb_dev = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 5));
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600635 siblings = pci_read_config32(cdb_dev, 0x84) & 0xff;
Marc Jones1587dc82017-05-15 18:55:11 -0600636
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600637 printk(BIOS_SPEW, "%s family%xh, core_max=%d, core_nums=%d,"
638 " siblings=%d\n", dev_path(cdb_dev), 0x0f + family,
639 core_max, core_nums, siblings);
Marc Jones1587dc82017-05-15 18:55:11 -0600640
641 /*
642 * APIC ID calucation is tightly coupled with AGESA v5 code.
643 * This calculation MUST match the assignment calculation done
644 * in LocalApicInitializationAtEarly() function.
645 * And reference GetLocalApicIdForCore()
646 *
647 * Apply apic enumeration rules
648 * For systems with >= 16 APICs, put the IO-APICs at 0..n and
649 * put the local-APICs at m..z
650 *
651 * This is needed because many IO-APIC devices only have 4 bits
652 * for their APIC id and therefore must reside at 0..15
653 */
654
655 /*
656 * While the above statement is true, we know some things about
657 * this silicon. It is an SOC and can't have >= 16 APICs, but
658 * we will start numbering at 0x10. We also know there is only
659 * on physical node (module in AMD speak).
660 */
661
662 lapicid_start = 0x10; /* Get this from devicetree? see comment above. */
Martin Kepplinger9460a982017-06-29 10:57:55 +0200663 enable_node = cdb_dev->enabled;
Marc Jones1587dc82017-05-15 18:55:11 -0600664 cpu_bus = dev->link_list;
665
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600666 for (j = 0 ; j <= siblings ; j++) {
Marc Jones1587dc82017-05-15 18:55:11 -0600667 apic_id = lapicid_start + j;
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600668 printk(BIOS_SPEW, "lapicid_start 0x%x, node 0x%x, core 0x%x,"
669 " apicid=0x%x\n", lapicid_start, node_nums,
670 j, apic_id);
Marc Jones1587dc82017-05-15 18:55:11 -0600671
672 cpu = add_cpu_device(cpu_bus, apic_id, enable_node);
673 if (cpu)
674 amd_cpu_topology(cpu, node_nums, j);
675 }
676}
677
678/*********************************************************************
679 * Change the vendor / device IDs to match the generic VBIOS header. *
680 *********************************************************************/
681u32 map_oprom_vendev(u32 vendev)
682{
683 u32 new_vendev;
684 new_vendev =
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600685 ((vendev >= 0x100298e0) && (vendev <= 0x100298ef)) ?
686 0x100298e0 : vendev;
Marc Jones1587dc82017-05-15 18:55:11 -0600687
688 if (vendev != new_vendev)
Marshall Dawson4e101ad2017-06-15 12:17:38 -0600689 printk(BIOS_NOTICE, "Mapping PCI device %8x to %8x\n",
690 vendev, new_vendev);
Marc Jones1587dc82017-05-15 18:55:11 -0600691
692 return new_vendev;
693}