blob: ff57ea08d80fc9d0b612afca8e48b2104a643d11 [file] [log] [blame]
Angel Pons4b429832020-04-02 23:48:50 +02001/* SPDX-License-Identifier: GPL-2.0-only */
zbao2c08f6a2012-07-02 15:32:58 +08002
3#include <console/console.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02004#include <device/pci_ops.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -07005#include <acpi/acpi.h>
6#include <acpi/acpigen.h>
zbao2c08f6a2012-07-02 15:32:58 +08007#include <stdint.h>
8#include <device/device.h>
9#include <device/pci.h>
10#include <device/pci_ids.h>
zbao2c08f6a2012-07-02 15:32:58 +080011#include <string.h>
Ronald G. Minnich5079a0d2012-11-27 11:32:38 -080012#include <lib.h>
zbao2c08f6a2012-07-02 15:32:58 +080013#include <cpu/cpu.h>
Martin Roth73e86a82013-01-17 16:28:30 -070014#include <AGESA.h>
zbao2c08f6a2012-07-02 15:32:58 +080015#include <cpu/x86/lapic.h>
Elyes HAOUAS400ce552018-10-12 10:54:30 +020016#include <cpu/amd/msr.h>
Kyösti Mälkkidbc47392012-08-05 12:11:40 +030017#include <cpu/amd/mtrr.h>
zbao2c08f6a2012-07-02 15:32:58 +080018#include <Porting.h>
zbao2c08f6a2012-07-02 15:32:58 +080019#include <Options.h>
20#include <Topology.h>
Angel Ponsec5cf152020-11-10 20:42:07 +010021#include <northbridge/amd/nb_common.h>
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020022#include <northbridge/amd/agesa/state_machine.h>
Kyösti Mälkkid610c582017-03-05 06:28:18 +020023#include <northbridge/amd/agesa/agesa_helper.h>
zbao2c08f6a2012-07-02 15:32:58 +080024
Kyösti Mälkki113f6702018-05-20 20:12:32 +030025#define MAX_NODE_NUMS MAX_NODES
zbao2c08f6a2012-07-02 15:32:58 +080026
Subrata Banikb1434fc2019-03-15 22:20:41 +053027static unsigned int node_nums;
28static unsigned int sblink;
Kyösti Mälkkie2c2a4c2018-05-20 20:59:52 +030029static struct device *__f0_dev[MAX_NODE_NUMS];
30static struct device *__f1_dev[MAX_NODE_NUMS];
31static struct device *__f2_dev[MAX_NODE_NUMS];
32static struct device *__f4_dev[MAX_NODE_NUMS];
Subrata Banikb1434fc2019-03-15 22:20:41 +053033static unsigned int fx_devs = 0;
zbao2c08f6a2012-07-02 15:32:58 +080034
Kyösti Mälkkie2c2a4c2018-05-20 20:59:52 +030035static struct device *get_node_pci(u32 nodeid, u32 fn)
zbao2c08f6a2012-07-02 15:32:58 +080036{
Kyösti Mälkki3d3152e2019-01-10 09:05:30 +020037 return pcidev_on_root(DEV_CDB + nodeid, fn);
zbao2c08f6a2012-07-02 15:32:58 +080038}
39
40static void get_fx_devs(void)
41{
42 int i;
43 for (i = 0; i < MAX_NODE_NUMS; i++) {
44 __f0_dev[i] = get_node_pci(i, 0);
45 __f1_dev[i] = get_node_pci(i, 1);
46 __f2_dev[i] = get_node_pci(i, 2);
47 __f4_dev[i] = get_node_pci(i, 4);
48 if (__f0_dev[i] != NULL && __f1_dev[i] != NULL)
Elyes Haouas3adfde92022-07-16 09:36:01 +020049 fx_devs = i + 1;
zbao2c08f6a2012-07-02 15:32:58 +080050 }
51 if (__f1_dev[0] == NULL || __f0_dev[0] == NULL || fx_devs == 0) {
52 die("Cannot find 0:0x18.[0|1]\n");
53 }
54 printk(BIOS_DEBUG, "fx_devs=0x%x\n", fx_devs);
55}
56
Subrata Banikb1434fc2019-03-15 22:20:41 +053057static u32 f1_read_config32(unsigned int reg)
zbao2c08f6a2012-07-02 15:32:58 +080058{
59 if (fx_devs == 0)
60 get_fx_devs();
61 return pci_read_config32(__f1_dev[0], reg);
62}
63
Subrata Banikb1434fc2019-03-15 22:20:41 +053064static void f1_write_config32(unsigned int reg, u32 value)
zbao2c08f6a2012-07-02 15:32:58 +080065{
66 int i;
67 if (fx_devs == 0)
68 get_fx_devs();
Elyes HAOUAS5a7e72f2016-08-23 21:36:02 +020069 for (i = 0; i < fx_devs; i++) {
Kyösti Mälkkie2c2a4c2018-05-20 20:59:52 +030070 struct device *dev;
zbao2c08f6a2012-07-02 15:32:58 +080071 dev = __f1_dev[i];
72 if (dev && dev->enabled) {
73 pci_write_config32(dev, reg, value);
74 }
75 }
76}
77
Michał Żygowski88a0ce62021-05-05 09:52:59 +020078static int get_dram_base_limit(u32 nodeid, resource_t *basek, resource_t *limitk)
79{
80 u32 temp;
81
82 if (fx_devs == 0)
83 get_fx_devs();
84
85
86 temp = pci_read_config32(__f1_dev[nodeid], 0x40 + (nodeid << 3)); //[39:24] at [31:16]
87 if (!(temp & 1))
88 return 0; // this memory range is not enabled
89 /*
90 * BKDG: {DramBase[47:24], 00_0000h} <= address[47:0] so shift left by 8 bits
91 * for physical address and the convert to KiB by shifting 10 bits left
92 */
93 *basek = ((temp & 0xffff0000)) >> (10 - 8);
94 /* Now high bits [47:40] */
95 temp = pci_read_config32(__f1_dev[nodeid], 0x140 + (nodeid << 3)); //[47:40] at [7:0]
96 *basek = *basek | ((resource_t)temp << (40 - 10));
97 /*
98 * BKDG address[39:0] <= {DramLimit[47:24], FF_FFFFh} converted as above but
99 * ORed with 0xffff to get real limit before shifting.
100 */
101 temp = pci_read_config32(__f1_dev[nodeid], 0x44 + (nodeid << 3)); //[39:24] at [31:16]
102 *limitk = ((temp & 0xffff0000) | 0xffff) >> (10 - 8);
103 /* Now high bits [47:40] */
104 temp = pci_read_config32(__f1_dev[nodeid], 0x144 + (nodeid << 3)); //[47:40] at [7:0]
105 *limitk = *limitk | ((resource_t)temp << (40 - 10));
106 *limitk += 1; // round up last byte
107
108 return 1;
109}
110
Kyösti Mälkki2900d4b2017-07-25 14:55:29 +0300111static u32 amdfam15_nodeid(struct device *dev)
zbao2c08f6a2012-07-02 15:32:58 +0800112{
Kyösti Mälkki3d3152e2019-01-10 09:05:30 +0200113 return (dev->path.pci.devfn >> 3) - DEV_CDB;
zbao2c08f6a2012-07-02 15:32:58 +0800114}
115
116static void set_vga_enable_reg(u32 nodeid, u32 linkn)
117{
118 u32 val;
119
Elyes HAOUAS27e18012017-06-27 23:14:51 +0200120 val = 1 | (nodeid << 4) | (linkn << 12);
zbao2c08f6a2012-07-02 15:32:58 +0800121 /* it will routing
122 * (1)mmio 0xa0000:0xbffff
123 * (2)io 0x3b0:0x3bb, 0x3c0:0x3df
124 */
125 f1_write_config32(0xf4, val);
126
127}
128
Kyösti Mälkki2900d4b2017-07-25 14:55:29 +0300129static void nb_read_resources(struct device *dev)
zbao2c08f6a2012-07-02 15:32:58 +0800130{
Steven Sherk1cbabb02013-02-01 09:22:35 -0700131 /*
Stefan Reinauer4aff4452013-02-12 14:17:15 -0800132 * This MMCONF resource must be reserved in the PCI domain.
Steven Sherk1cbabb02013-02-01 09:22:35 -0700133 * It is not honored by the coreboot resource allocator if it is in
Stefan Reinauer0aa37c42013-02-12 15:20:54 -0800134 * the CPU_CLUSTER.
Steven Sherk1cbabb02013-02-01 09:22:35 -0700135 */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200136 mmconf_resource(dev, MMIO_CONF_BASE);
zbao2c08f6a2012-07-02 15:32:58 +0800137
Arthur Heymans6fa6e112022-10-13 18:26:04 +0200138 /* There should be no BAR on this device. */
zbao2c08f6a2012-07-02 15:32:58 +0800139}
140
141/**
142 * I tried to reuse the resource allocation code in set_resource()
143 * but it is too difficult to deal with the resource allocation magic.
144 */
145
Subrata Banikb1434fc2019-03-15 22:20:41 +0530146static void create_vga_resource(struct device *dev, unsigned int nodeid)
zbao2c08f6a2012-07-02 15:32:58 +0800147{
148 struct bus *link;
149
150 /* find out which link the VGA card is connected,
151 * we only deal with the 'first' vga card */
152 for (link = dev->link_list; link; link = link->next) {
153 if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
Julius Wernercd49cce2019-03-05 16:53:33 -0800154#if CONFIG(MULTIPLE_VGA_ADAPTERS)
Kyösti Mälkki2900d4b2017-07-25 14:55:29 +0300155 extern struct device *vga_pri; // the primary vga device, defined in device.c
zbao2c08f6a2012-07-02 15:32:58 +0800156 printk(BIOS_DEBUG, "VGA: vga_pri bus num = %d bus range [%d,%d]\n", vga_pri->bus->secondary,
Elyes Haouas3adfde92022-07-16 09:36:01 +0200157 link->secondary, link->subordinate);
zbao2c08f6a2012-07-02 15:32:58 +0800158 /* We need to make sure the vga_pri is under the link */
Elyes HAOUAS1d8daa62016-09-18 08:50:54 +0200159 if ((vga_pri->bus->secondary >= link->secondary) &&
Kyösti Mälkki2900d4b2017-07-25 14:55:29 +0300160 (vga_pri->bus->secondary <= link->subordinate))
zbao2c08f6a2012-07-02 15:32:58 +0800161#endif
162 break;
163 }
164 }
165
166 /* no VGA card installed */
167 if (link == NULL)
168 return;
169
170 printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, sblink);
171 set_vga_enable_reg(nodeid, sblink);
172}
173
Kyösti Mälkki2900d4b2017-07-25 14:55:29 +0300174static void nb_set_resources(struct device *dev)
zbao2c08f6a2012-07-02 15:32:58 +0800175{
Subrata Banikb1434fc2019-03-15 22:20:41 +0530176 unsigned int nodeid;
zbao2c08f6a2012-07-02 15:32:58 +0800177
178 /* Find the nodeid */
179 nodeid = amdfam15_nodeid(dev);
180
181 create_vga_resource(dev, nodeid); //TODO: do we need this?
zbao2c08f6a2012-07-02 15:32:58 +0800182}
183
Vladimir Serbinenko807127f2014-11-09 13:36:18 +0100184static unsigned long acpi_fill_hest(acpi_hest_t *hest)
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200185{
186 void *addr, *current;
187
188 /* Skip the HEST header. */
189 current = (void *)(hest + 1);
190
191 addr = agesawrapper_getlateinitptr(PICK_WHEA_MCE);
192 if (addr != NULL)
Stefan Reinauer77a1d1a2015-07-21 12:48:17 -0700193 current += acpi_create_hest_error_source(hest, current, 0,
194 addr + 2, *(UINT16 *)addr - 2);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200195
196 addr = agesawrapper_getlateinitptr(PICK_WHEA_CMC);
197 if (addr != NULL)
Stefan Reinauer77a1d1a2015-07-21 12:48:17 -0700198 current += acpi_create_hest_error_source(hest, current, 1,
199 addr + 2, *(UINT16 *)addr - 2);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200200
201 return (unsigned long)current;
202}
203
Furquan Shaikh7536a392020-04-24 21:59:21 -0700204static void northbridge_fill_ssdt_generator(const struct device *device)
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200205{
206 msr_t msr;
207 char pscope[] = "\\_SB.PCI0";
208
209 acpigen_write_scope(pscope);
210 msr = rdmsr(TOP_MEM);
211 acpigen_write_name_dword("TOM1", msr.lo);
212 msr = rdmsr(TOP_MEM2);
213 /*
214 * Since XP only implements parts of ACPI 2.0, we can't use a qword
215 * here.
216 * See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt
217 * slide 22ff.
218 * Shift value right by 20 bit to make it fit into 32bit,
219 * giving us 1MB granularity and a limit of almost 4Exabyte of memory.
220 */
221 acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20);
222 acpigen_pop_len();
223}
224
Michał Żygowski9550e972020-03-20 13:56:46 +0100225static void patch_ssdt_processor_scope(acpi_header_t *ssdt)
226{
227 unsigned int len = ssdt->length - sizeof(acpi_header_t);
228 unsigned int i;
229
230 for (i = sizeof(acpi_header_t); i < len; i++) {
231 /* Search for _PR_ scope and replace it with _SB_ */
232 if (*(uint32_t *)((unsigned long)ssdt + i) == 0x5f52505f)
233 *(uint32_t *)((unsigned long)ssdt + i) = 0x5f42535f;
234 }
235 /* Recalculate checksum */
236 ssdt->checksum = 0;
237 ssdt->checksum = acpi_checksum((void *)ssdt, ssdt->length);
238}
239
Furquan Shaikh0f007d82020-04-24 06:41:18 -0700240static unsigned long agesa_write_acpi_tables(const struct device *device,
Alexander Couzens83fc32f2015-04-12 22:28:37 +0200241 unsigned long current,
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200242 acpi_rsdp_t *rsdp)
243{
244 acpi_srat_t *srat;
245 acpi_slit_t *slit;
246 acpi_header_t *ssdt;
247 acpi_header_t *alib;
248 acpi_header_t *ivrs;
249 acpi_hest_t *hest;
250
251 /* HEST */
Elyes Haouasd6b6b222022-10-10 12:34:21 +0200252 current = ALIGN_UP(current, 8);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200253 hest = (acpi_hest_t *)current;
Arthur Heymanscc66ff32022-03-23 21:33:15 +0100254 acpi_write_hest(hest, acpi_fill_hest);
255 acpi_add_table(rsdp, hest);
256 current += hest->header.length;
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200257
Elyes Haouasd6b6b222022-10-10 12:34:21 +0200258 current = ALIGN_UP(current, 8);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200259 printk(BIOS_DEBUG, "ACPI: * IVRS at %lx\n", current);
260 ivrs = agesawrapper_getlateinitptr(PICK_IVRS);
261 if (ivrs != NULL) {
262 memcpy((void *)current, ivrs, ivrs->length);
Elyes Haouas3adfde92022-07-16 09:36:01 +0200263 ivrs = (acpi_header_t *)current;
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200264 current += ivrs->length;
265 acpi_add_table(rsdp, ivrs);
266 } else {
267 printk(BIOS_DEBUG, " AGESA IVRS table NULL. Skipping.\n");
268 }
269
270 /* SRAT */
Elyes Haouasd6b6b222022-10-10 12:34:21 +0200271 current = ALIGN_UP(current, 8);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200272 printk(BIOS_DEBUG, "ACPI: * SRAT at %lx\n", current);
Elyes Haouas3adfde92022-07-16 09:36:01 +0200273 srat = (acpi_srat_t *)agesawrapper_getlateinitptr(PICK_SRAT);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200274 if (srat != NULL) {
275 memcpy((void *)current, srat, srat->header.length);
Elyes Haouas3adfde92022-07-16 09:36:01 +0200276 srat = (acpi_srat_t *)current;
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200277 current += srat->header.length;
278 acpi_add_table(rsdp, srat);
279 } else {
280 printk(BIOS_DEBUG, " AGESA SRAT table NULL. Skipping.\n");
281 }
282
283 /* SLIT */
Elyes Haouasd6b6b222022-10-10 12:34:21 +0200284 current = ALIGN_UP(current, 8);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200285 printk(BIOS_DEBUG, "ACPI: * SLIT at %lx\n", current);
Elyes Haouas3adfde92022-07-16 09:36:01 +0200286 slit = (acpi_slit_t *)agesawrapper_getlateinitptr(PICK_SLIT);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200287 if (slit != NULL) {
288 memcpy((void *)current, slit, slit->header.length);
Elyes Haouas3adfde92022-07-16 09:36:01 +0200289 slit = (acpi_slit_t *)current;
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200290 current += slit->header.length;
291 acpi_add_table(rsdp, slit);
292 } else {
293 printk(BIOS_DEBUG, " AGESA SLIT table NULL. Skipping.\n");
294 }
295
296 /* ALIB */
Elyes Haouasd6b6b222022-10-10 12:34:21 +0200297 current = ALIGN_UP(current, 16);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200298 printk(BIOS_DEBUG, "ACPI: * AGESA ALIB SSDT at %lx\n", current);
Elyes Haouas3adfde92022-07-16 09:36:01 +0200299 alib = (acpi_header_t *)agesawrapper_getlateinitptr(PICK_ALIB);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200300 if (alib != NULL) {
301 memcpy((void *)current, alib, alib->length);
Elyes Haouas3adfde92022-07-16 09:36:01 +0200302 alib = (acpi_header_t *)current;
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200303 current += alib->length;
304 acpi_add_table(rsdp, (void *)alib);
305 }
306 else {
307 printk(BIOS_DEBUG, " AGESA ALIB SSDT table NULL. Skipping.\n");
308 }
309
310 /* this pstate ssdt may cause Blue Screen: Fixed: Keep this comment for a while. */
311 /* SSDT */
Elyes Haouasd6b6b222022-10-10 12:34:21 +0200312 current = ALIGN_UP(current, 16);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200313 printk(BIOS_DEBUG, "ACPI: * SSDT at %lx\n", current);
Elyes Haouas3adfde92022-07-16 09:36:01 +0200314 ssdt = (acpi_header_t *)agesawrapper_getlateinitptr(PICK_PSTATE);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200315 if (ssdt != NULL) {
Michał Żygowski9550e972020-03-20 13:56:46 +0100316 patch_ssdt_processor_scope(ssdt);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200317 memcpy((void *)current, ssdt, ssdt->length);
Elyes Haouas3adfde92022-07-16 09:36:01 +0200318 ssdt = (acpi_header_t *)current;
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200319 current += ssdt->length;
320 }
321 else {
322 printk(BIOS_DEBUG, " AGESA PState table NULL. Skipping.\n");
323 }
Elyes Haouas3adfde92022-07-16 09:36:01 +0200324 acpi_add_table(rsdp, ssdt);
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200325
326 printk(BIOS_DEBUG, "ACPI: * SSDT for PState at %lx\n", current);
327
328 return current;
329}
330
zbao2c08f6a2012-07-02 15:32:58 +0800331static struct device_operations northbridge_operations = {
Steven Sherkf4340582013-01-29 16:13:35 -0700332 .read_resources = nb_read_resources,
333 .set_resources = nb_set_resources,
zbao2c08f6a2012-07-02 15:32:58 +0800334 .enable_resources = pci_dev_enable_resources,
Nico Huber68680dd2020-03-31 17:34:52 +0200335 .acpi_fill_ssdt = northbridge_fill_ssdt_generator,
Vladimir Serbinenko56f46d82014-10-08 22:06:27 +0200336 .write_acpi_tables = agesa_write_acpi_tables,
zbao2c08f6a2012-07-02 15:32:58 +0800337};
338
339static const struct pci_driver family15_northbridge __pci_driver = {
340 .ops = &northbridge_operations,
Felix Singer43b7f412022-03-07 04:34:52 +0100341 .vendor = PCI_VID_AMD,
342 .device = PCI_DID_AMD_15H_MODEL_101F_NB_HT,
zbao2c08f6a2012-07-02 15:32:58 +0800343};
344
345static const struct pci_driver family10_northbridge __pci_driver = {
346 .ops = &northbridge_operations,
Felix Singer43b7f412022-03-07 04:34:52 +0100347 .vendor = PCI_VID_AMD,
348 .device = PCI_DID_AMD_10H_NB_HT,
zbao2c08f6a2012-07-02 15:32:58 +0800349};
350
351struct chip_operations northbridge_amd_agesa_family15tn_ops = {
352 CHIP_NAME("AMD FAM15 Northbridge")
353 .enable_dev = 0,
354};
355
Kyösti Mälkki2900d4b2017-07-25 14:55:29 +0300356static void domain_read_resources(struct device *dev)
zbao2c08f6a2012-07-02 15:32:58 +0800357{
Subrata Banikb1434fc2019-03-15 22:20:41 +0530358 unsigned int reg;
zbao2c08f6a2012-07-02 15:32:58 +0800359
360 /* Find the already assigned resource pairs */
361 get_fx_devs();
Elyes Haouas3adfde92022-07-16 09:36:01 +0200362 for (reg = 0x80; reg <= 0xd8; reg += 0x08) {
zbao2c08f6a2012-07-02 15:32:58 +0800363 u32 base, limit;
364 base = f1_read_config32(reg);
365 limit = f1_read_config32(reg + 0x04);
366 /* Is this register allocated? */
367 if ((base & 3) != 0) {
Subrata Banikb1434fc2019-03-15 22:20:41 +0530368 unsigned int nodeid, reg_link;
Kyösti Mälkkie2c2a4c2018-05-20 20:59:52 +0300369 struct device *reg_dev;
Elyes HAOUAS1d8daa62016-09-18 08:50:54 +0200370 if (reg < 0xc0) { // mmio
Elyes Haouas3adfde92022-07-16 09:36:01 +0200371 nodeid = (limit & 0xf) + (base & 0x30);
zbao2c08f6a2012-07-02 15:32:58 +0800372 } else { // io
Elyes Haouas3adfde92022-07-16 09:36:01 +0200373 nodeid = (limit & 0xf) + ((base >> 4) & 0x30);
zbao2c08f6a2012-07-02 15:32:58 +0800374 }
375 reg_link = (limit >> 4) & 7;
376 reg_dev = __f0_dev[nodeid];
377 if (reg_dev) {
378 /* Reserve the resource */
379 struct resource *res;
380 res = new_resource(reg_dev, IOINDEX(0x1000 + reg, reg_link));
381 if (res) {
382 res->flags = 1;
383 }
384 }
385 }
386 }
387 /* FIXME: do we need to check extend conf space?
388 I don't believe that much preset value */
389
zbao2c08f6a2012-07-02 15:32:58 +0800390 pci_domain_read_resources(dev);
zbao2c08f6a2012-07-02 15:32:58 +0800391}
392
zbao2c08f6a2012-07-02 15:32:58 +0800393#if CONFIG_HW_MEM_HOLE_SIZEK != 0
394struct hw_mem_hole_info {
Subrata Banikb1434fc2019-03-15 22:20:41 +0530395 unsigned int hole_startk;
zbao2c08f6a2012-07-02 15:32:58 +0800396 int node_id;
397};
398static struct hw_mem_hole_info get_hw_mem_hole_info(void)
399{
400 struct hw_mem_hole_info mem_hole;
401 int i;
402 mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK;
403 mem_hole.node_id = -1;
404 for (i = 0; i < node_nums; i++) {
Michał Żygowski88a0ce62021-05-05 09:52:59 +0200405 resource_t basek, limitk;
zbao2c08f6a2012-07-02 15:32:58 +0800406 u32 hole;
Michał Żygowski88a0ce62021-05-05 09:52:59 +0200407 if (!get_dram_base_limit(i, &basek, &limitk))
408 continue; // no memory on this node
zbao2c08f6a2012-07-02 15:32:58 +0800409 hole = pci_read_config32(__f1_dev[i], 0xf0);
410 if (hole & 1) { // we find the hole
Elyes HAOUAS27e18012017-06-27 23:14:51 +0200411 mem_hole.hole_startk = (hole & (0xff << 24)) >> 10;
zbao2c08f6a2012-07-02 15:32:58 +0800412 mem_hole.node_id = i; // record the node No with hole
413 break; // only one hole
414 }
415 }
Kyösti Mälkki2f9b3af2014-06-26 05:30:54 +0300416
417 /* We need to double check if there is special set on base reg and limit reg
418 * are not continuous instead of hole, it will find out its hole_startk.
419 */
zbao2c08f6a2012-07-02 15:32:58 +0800420 if (mem_hole.node_id == -1) {
421 resource_t limitk_pri = 0;
Elyes HAOUAS1d8daa62016-09-18 08:50:54 +0200422 for (i = 0; i < node_nums; i++) {
zbao2c08f6a2012-07-02 15:32:58 +0800423 resource_t base_k, limit_k;
Michał Żygowski88a0ce62021-05-05 09:52:59 +0200424 if (!get_dram_base_limit(i, &base_k, &limit_k))
425 continue; // no memory on this node
Elyes Haouas3adfde92022-07-16 09:36:01 +0200426 if (base_k > 4 * 1024 * 1024) break; // don't need to go to check
zbao2c08f6a2012-07-02 15:32:58 +0800427 if (limitk_pri != base_k) { // we find the hole
Martin Roth468d02c2019-10-23 21:44:42 -0600428 mem_hole.hole_startk = (unsigned int)limitk_pri; // must beblow 4G
zbao2c08f6a2012-07-02 15:32:58 +0800429 mem_hole.node_id = i;
430 break; //only one hole
431 }
zbao2c08f6a2012-07-02 15:32:58 +0800432 limitk_pri = limit_k;
433 }
434 }
435 return mem_hole;
436}
437#endif
438
Kyösti Mälkki2900d4b2017-07-25 14:55:29 +0300439static void domain_set_resources(struct device *dev)
zbao2c08f6a2012-07-02 15:32:58 +0800440{
zbao2c08f6a2012-07-02 15:32:58 +0800441 unsigned long mmio_basek;
442 u32 pci_tolm;
443 int i, idx;
444 struct bus *link;
445#if CONFIG_HW_MEM_HOLE_SIZEK != 0
446 struct hw_mem_hole_info mem_hole;
zbao2c08f6a2012-07-02 15:32:58 +0800447#endif
448
zbao2c08f6a2012-07-02 15:32:58 +0800449 pci_tolm = 0xffffffffUL;
450 for (link = dev->link_list; link; link = link->next) {
451 pci_tolm = find_pci_tolm(link);
452 }
453
454 // FIXME handle interleaved nodes. If you fix this here, please fix
455 // amdk8, too.
456 mmio_basek = pci_tolm >> 10;
457 /* Round mmio_basek to something the processor can support */
Elyes Haouas3adfde92022-07-16 09:36:01 +0200458 mmio_basek &= ~((1 << 6) - 1);
zbao2c08f6a2012-07-02 15:32:58 +0800459
460 // FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M
461 // MMIO hole. If you fix this here, please fix amdk8, too.
462 /* Round the mmio hole to 64M */
Elyes Haouas3adfde92022-07-16 09:36:01 +0200463 mmio_basek &= ~((64 * 1024) - 1);
zbao2c08f6a2012-07-02 15:32:58 +0800464
465#if CONFIG_HW_MEM_HOLE_SIZEK != 0
466 /* if the hw mem hole is already set in raminit stage, here we will compare
467 * mmio_basek and hole_basek. if mmio_basek is bigger that hole_basek and will
468 * use hole_basek as mmio_basek and we don't need to reset hole.
469 * otherwise We reset the hole to the mmio_basek
470 */
471
472 mem_hole = get_hw_mem_hole_info();
473
474 // Use hole_basek as mmio_basek, and we don't need to reset hole anymore
Arthur Heymans99eab342022-03-23 21:34:20 +0100475 if ((mem_hole.node_id != -1) && (mmio_basek > mem_hole.hole_startk))
zbao2c08f6a2012-07-02 15:32:58 +0800476 mmio_basek = mem_hole.hole_startk;
zbao2c08f6a2012-07-02 15:32:58 +0800477#endif
478
479 idx = 0x10;
480 for (i = 0; i < node_nums; i++) {
zbao2c08f6a2012-07-02 15:32:58 +0800481 resource_t basek, limitk, sizek; // 4 1T
482
Michał Żygowski88a0ce62021-05-05 09:52:59 +0200483 if (!get_dram_base_limit(i, &basek, &limitk))
484 continue; // no memory on this node
zbao2c08f6a2012-07-02 15:32:58 +0800485
486 sizek = limitk - basek;
487
Elyes Haouas5213b192022-02-25 18:13:03 +0100488 /* See if we need a hole from 0xa0000 (640K) to 0xbffff (768K) */
Elyes Haouas9d8df302022-02-25 18:23:01 +0100489 if (basek < 640 && sizek > 768) {
Kyösti Mälkki27d62992022-05-24 20:25:58 +0300490 ram_resource_kb(dev, (idx | i), basek, 640 - basek);
zbao2c08f6a2012-07-02 15:32:58 +0800491 idx += 0x10;
Elyes Haouas9d8df302022-02-25 18:23:01 +0100492 basek = 768;
493 sizek = limitk - basek;
zbao2c08f6a2012-07-02 15:32:58 +0800494
495 }
496
Kyösti Mälkki26c65432014-06-26 05:30:54 +0300497 /* split the region to accommodate pci memory space */
Elyes Haouas3adfde92022-07-16 09:36:01 +0200498 if ((basek < 4 * 1024 * 1024) && (limitk > mmio_basek)) {
zbao2c08f6a2012-07-02 15:32:58 +0800499 if (basek <= mmio_basek) {
Subrata Banikb1434fc2019-03-15 22:20:41 +0530500 unsigned int pre_sizek;
zbao2c08f6a2012-07-02 15:32:58 +0800501 pre_sizek = mmio_basek - basek;
Elyes HAOUAS1d8daa62016-09-18 08:50:54 +0200502 if (pre_sizek > 0) {
Kyösti Mälkki27d62992022-05-24 20:25:58 +0300503 ram_resource_kb(dev, (idx | i), basek, pre_sizek);
zbao2c08f6a2012-07-02 15:32:58 +0800504 idx += 0x10;
505 sizek -= pre_sizek;
zbao2c08f6a2012-07-02 15:32:58 +0800506 }
507 basek = mmio_basek;
508 }
Elyes Haouas3adfde92022-07-16 09:36:01 +0200509 if ((basek + sizek) <= 4 * 1024 * 1024) {
zbao2c08f6a2012-07-02 15:32:58 +0800510 sizek = 0;
511 }
512 else {
Arthur Heymansc4350382021-10-28 12:35:39 +0200513 uint64_t topmem2 = amd_topmem2();
Elyes Haouas3adfde92022-07-16 09:36:01 +0200514 basek = 4 * 1024 * 1024;
515 sizek = topmem2 / 1024 - basek;
zbao2c08f6a2012-07-02 15:32:58 +0800516 }
517 }
518
Kyösti Mälkki27d62992022-05-24 20:25:58 +0300519 ram_resource_kb(dev, (idx | i), basek, sizek);
zbao2c08f6a2012-07-02 15:32:58 +0800520 idx += 0x10;
zbao2c08f6a2012-07-02 15:32:58 +0800521 printk(BIOS_DEBUG, "node %d: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",
522 i, mmio_basek, basek, limitk);
zbao2c08f6a2012-07-02 15:32:58 +0800523 }
524
Kyösti Mälkki61be3602017-04-15 20:07:53 +0300525 add_uma_resource_below_tolm(dev, 7);
zbao2c08f6a2012-07-02 15:32:58 +0800526
Elyes HAOUAS5a7e72f2016-08-23 21:36:02 +0200527 for (link = dev->link_list; link; link = link->next) {
zbao2c08f6a2012-07-02 15:32:58 +0800528 if (link->children) {
529 assign_resources(link);
530 }
531 }
532}
533
534static struct device_operations pci_domain_ops = {
535 .read_resources = domain_read_resources,
536 .set_resources = domain_set_resources,
zbao2c08f6a2012-07-02 15:32:58 +0800537 .scan_bus = pci_domain_scan_bus,
zbao2c08f6a2012-07-02 15:32:58 +0800538};
539
Kyösti Mälkkie2c2a4c2018-05-20 20:59:52 +0300540static void sysconf_init(struct device *dev) // first node
zbao2c08f6a2012-07-02 15:32:58 +0800541{
Elyes Haouas3adfde92022-07-16 09:36:01 +0200542 sblink = (pci_read_config32(dev, 0x64) >> 8) & 7; // don't forget sublink1
543 node_nums = ((pci_read_config32(dev, 0x60) >> 4) & 7) + 1; //NodeCnt[2:0]
zbao2c08f6a2012-07-02 15:32:58 +0800544}
545
Kyösti Mälkkie2c2a4c2018-05-20 20:59:52 +0300546static void cpu_bus_scan(struct device *dev)
zbao2c08f6a2012-07-02 15:32:58 +0800547{
548 struct bus *cpu_bus;
Kyösti Mälkkie2c2a4c2018-05-20 20:59:52 +0300549 struct device *dev_mc;
Elyes Haouas3adfde92022-07-16 09:36:01 +0200550 int i, j;
zbao2c08f6a2012-07-02 15:32:58 +0800551 int coreid_bits;
552 int core_max = 0;
Subrata Banikb1434fc2019-03-15 22:20:41 +0530553 unsigned int ApicIdCoreIdSize;
554 unsigned int core_nums;
zbao2c08f6a2012-07-02 15:32:58 +0800555 int siblings = 0;
556 unsigned int family;
557
Kyösti Mälkki3d3152e2019-01-10 09:05:30 +0200558 dev_mc = pcidev_on_root(DEV_CDB, 0);
zbao2c08f6a2012-07-02 15:32:58 +0800559 if (!dev_mc) {
Kyösti Mälkki3d3152e2019-01-10 09:05:30 +0200560 printk(BIOS_ERR, "0:%02x.0 not found", DEV_CDB);
zbao2c08f6a2012-07-02 15:32:58 +0800561 die("");
562 }
563 sysconf_init(dev_mc);
zbao2c08f6a2012-07-02 15:32:58 +0800564
565 /* Get Max Number of cores(MNC) */
Kyösti Mälkkid41feed2017-09-24 16:23:57 +0300566 coreid_bits = (cpuid_ecx(0x80000008) & 0x0000F000) >> 12;
zbao2c08f6a2012-07-02 15:32:58 +0800567 core_max = 1 << (coreid_bits & 0x000F); //mnc
568
Elyes Haouas3adfde92022-07-16 09:36:01 +0200569 ApicIdCoreIdSize = ((cpuid_ecx(0x80000008) >> 12) & 0xF);
zbao2c08f6a2012-07-02 15:32:58 +0800570 if (ApicIdCoreIdSize) {
571 core_nums = (1 << ApicIdCoreIdSize) - 1;
572 } else {
573 core_nums = 3; //quad core
574 }
575
576 /* Find which cpus are present */
577 cpu_bus = dev->link_list;
578 for (i = 0; i < node_nums; i++) {
Kyösti Mälkkie2c2a4c2018-05-20 20:59:52 +0300579 struct device *cdb_dev;
Subrata Banikb1434fc2019-03-15 22:20:41 +0530580 unsigned int devn;
zbao2c08f6a2012-07-02 15:32:58 +0800581 struct bus *pbus;
582
Kyösti Mälkki3d3152e2019-01-10 09:05:30 +0200583 devn = DEV_CDB + i;
zbao2c08f6a2012-07-02 15:32:58 +0800584 pbus = dev_mc->bus;
zbao2c08f6a2012-07-02 15:32:58 +0800585
586 /* Find the cpu's pci device */
Kyösti Mälkki4ad7f5b2018-05-22 01:15:17 +0300587 cdb_dev = pcidev_on_root(devn, 0);
zbao2c08f6a2012-07-02 15:32:58 +0800588 if (!cdb_dev) {
589 /* If I am probing things in a weird order
590 * ensure all of the cpu's pci devices are found.
591 */
592 int fn;
Elyes HAOUAS5a7e72f2016-08-23 21:36:02 +0200593 for (fn = 0; fn <= 5; fn++) { //FBDIMM?
zbao2c08f6a2012-07-02 15:32:58 +0800594 cdb_dev = pci_probe_dev(NULL, pbus,
595 PCI_DEVFN(devn, fn));
596 }
Kyösti Mälkki4ad7f5b2018-05-22 01:15:17 +0300597 cdb_dev = pcidev_on_root(devn, 0);
zbao2c08f6a2012-07-02 15:32:58 +0800598 } else {
599 /* Ok, We need to set the links for that device.
600 * otherwise the device under it will not be scanned
601 */
Kyösti Mälkki2a2d6132015-02-04 13:25:37 +0200602 add_more_links(cdb_dev, 4);
zbao2c08f6a2012-07-02 15:32:58 +0800603 }
604
605 family = cpuid_eax(1);
606 family = (family >> 20) & 0xFF;
607 if (family == 1) { //f10
608 u32 dword;
Kyösti Mälkki4ad7f5b2018-05-22 01:15:17 +0300609 cdb_dev = pcidev_on_root(devn, 3);
zbao2c08f6a2012-07-02 15:32:58 +0800610 dword = pci_read_config32(cdb_dev, 0xe8);
611 siblings = ((dword & BIT15) >> 13) | ((dword & (BIT13 | BIT12)) >> 12);
612 } else if (family == 6) {//f15
Kyösti Mälkki4ad7f5b2018-05-22 01:15:17 +0300613 cdb_dev = pcidev_on_root(devn, 5);
zbao2c08f6a2012-07-02 15:32:58 +0800614 if (cdb_dev && cdb_dev->enabled) {
615 siblings = pci_read_config32(cdb_dev, 0x84);
616 siblings &= 0xFF;
617 }
618 } else {
619 siblings = 0; //default one core
620 }
Kyösti Mälkkicd9fc1a2012-07-06 19:02:56 +0300621 int enable_node = cdb_dev && cdb_dev->enabled;
zbao2c08f6a2012-07-02 15:32:58 +0800622 printk(BIOS_SPEW, "%s family%xh, core_max=0x%x, core_nums=0x%x, siblings=0x%x\n",
623 dev_path(cdb_dev), 0x0f + family, core_max, core_nums, siblings);
624
Elyes HAOUAS1d8daa62016-09-18 08:50:54 +0200625 for (j = 0; j <= siblings; j++) {
zbao2c08f6a2012-07-02 15:32:58 +0800626 extern CONST OPTIONS_CONFIG_TOPOLOGY ROMDATA TopologyConfiguration;
627 u32 modules = TopologyConfiguration.PlatformNumberOfModules;
628 u32 lapicid_start = 0;
629
zbao2c08f6a2012-07-02 15:32:58 +0800630 /*
631 * APIC ID calucation is tightly coupled with AGESA v5 code.
632 * This calculation MUST match the assignment calculation done
633 * in LocalApicInitializationAtEarly() function.
634 * And reference GetLocalApicIdForCore()
635 *
Elyes HAOUASa5b0bc42020-02-20 20:04:29 +0100636 * Apply APIC enumeration rules
zbao2c08f6a2012-07-02 15:32:58 +0800637 * For systems with >= 16 APICs, put the IO-APICs at 0..n and
638 * put the local-APICs at m..z
639 *
640 * This is needed because many IO-APIC devices only have 4 bits
641 * for their APIC id and therefore must reside at 0..15
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +0200642 */
Kyösti Mälkki50036322016-05-18 13:35:21 +0300643
Elyes HAOUAS6e8b3c12016-09-02 19:22:00 +0200644 u8 plat_num_io_apics = 3; /* FIXME */
Kyösti Mälkki50036322016-05-18 13:35:21 +0300645
646 if ((node_nums * core_max) + plat_num_io_apics >= 0x10) {
647 lapicid_start = (plat_num_io_apics - 1) / core_max;
zbao2c08f6a2012-07-02 15:32:58 +0800648 lapicid_start = (lapicid_start + 1) * core_max;
649 printk(BIOS_SPEW, "lpaicid_start=0x%x ", lapicid_start);
650 }
Elyes Haouas3adfde92022-07-16 09:36:01 +0200651 u32 apic_id = (lapicid_start * (i / modules + 1)) + ((i % modules) ? (j + (siblings + 1)) : j);
zbao2c08f6a2012-07-02 15:32:58 +0800652 printk(BIOS_SPEW, "node 0x%x core 0x%x apicid=0x%x\n",
Kyösti Mälkkic33f1e92012-08-07 17:12:11 +0300653 i, j, apic_id);
zbao2c08f6a2012-07-02 15:32:58 +0800654
Kyösti Mälkkie2c2a4c2018-05-20 20:59:52 +0300655 struct device *cpu = add_cpu_device(cpu_bus, apic_id, enable_node);
Kyösti Mälkkic33f1e92012-08-07 17:12:11 +0300656 if (cpu)
657 amd_cpu_topology(cpu, i, j);
zbao2c08f6a2012-07-02 15:32:58 +0800658 } //j
659 }
zbao2c08f6a2012-07-02 15:32:58 +0800660}
661
Kyösti Mälkki2900d4b2017-07-25 14:55:29 +0300662static void cpu_bus_init(struct device *dev)
zbao2c08f6a2012-07-02 15:32:58 +0800663{
664 initialize_cpus(dev->link_list);
665}
666
zbao2c08f6a2012-07-02 15:32:58 +0800667static struct device_operations cpu_bus_ops = {
Nico Huber2f8ba692020-04-05 14:05:24 +0200668 .read_resources = noop_read_resources,
669 .set_resources = noop_set_resources,
zbao2c08f6a2012-07-02 15:32:58 +0800670 .init = cpu_bus_init,
671 .scan_bus = cpu_bus_scan,
672};
673
674static void root_complex_enable_dev(struct device *dev)
675{
zbao2c08f6a2012-07-02 15:32:58 +0800676 /* Set the operations if it is a special bus type */
Stefan Reinauer4aff4452013-02-12 14:17:15 -0800677 if (dev->path.type == DEVICE_PATH_DOMAIN) {
zbao2c08f6a2012-07-02 15:32:58 +0800678 dev->ops = &pci_domain_ops;
Stefan Reinauer0aa37c42013-02-12 15:20:54 -0800679 } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
zbao2c08f6a2012-07-02 15:32:58 +0800680 dev->ops = &cpu_bus_ops;
681 }
682}
683
684struct chip_operations northbridge_amd_agesa_family15tn_root_complex_ops = {
Kyösti Mälkki2900d4b2017-07-25 14:55:29 +0300685 CHIP_NAME("AMD Family 15tn Root Complex")
zbao2c08f6a2012-07-02 15:32:58 +0800686 .enable_dev = root_complex_enable_dev,
687};
Dave Frodincbf3d402012-12-05 08:20:12 -0700688
Edward O'Callaghanae5fd342014-11-20 19:58:09 +1100689/*********************************************************************
690 * Change the vendor / device IDs to match the generic VBIOS header. *
691 *********************************************************************/
Dave Frodincbf3d402012-12-05 08:20:12 -0700692u32 map_oprom_vendev(u32 vendev)
693{
Edward O'Callaghanae5fd342014-11-20 19:58:09 +1100694 u32 new_vendev = vendev;
Dave Frodincbf3d402012-12-05 08:20:12 -0700695
Elyes HAOUAS0ce41f12018-11-13 10:03:31 +0100696 switch (vendev) {
Bruce Griffith42e11f52013-07-08 18:19:08 -0600697 case 0x10029900: /* AMD Radeon HD 7660G (Trinity) */
698 case 0x10029901: /* AMD Radeon HD 7660D (Trinity) */
699 case 0x10029903: /* AMD Radeon HD 7640G (Trinity) */
700 case 0x10029904: /* AMD Radeon HD 7560D (Trinity) */
701 case 0x10029907: /* AMD Radeon HD 7620G (Trinity) */
702 case 0x10029908: /* AMD Radeon HD 7600G (Trinity) */
703 case 0x1002990A: /* AMD Radeon HD 7500G (Trinity) */
704 case 0x1002990B: /* AMD Radeon HD 8650G (Richland) */
705 case 0x1002990C: /* AMD Radeon HD 8670D (Richland) */
706 case 0x1002990D: /* AMD Radeon HD 8550G (Richland) */
707 case 0x1002990E: /* AMD Radeon HD 8570D (Richland) */
708 case 0x1002990F: /* AMD Radeon HD 8610G (Richland) */
709 case 0x10029910: /* AMD Radeon HD 7660G (Trinity) */
710 case 0x10029913: /* AMD Radeon HD 7640G (Trinity) */
711 case 0x10029917: /* AMD Radeon HD 7620G (Trinity) */
712 case 0x10029918: /* AMD Radeon HD 7600G (Trinity) */
713 case 0x10029919: /* AMD Radeon HD 7500G (Trinity) */
714 case 0x10029990: /* AMD Radeon HD 7520G (Trinity) */
715 case 0x10029991: /* AMD Radeon HD 7540D (Trinity) */
716 case 0x10029992: /* AMD Radeon HD 7420G (Trinity) */
717 case 0x10029993: /* AMD Radeon HD 7480D (Trinity) */
718 case 0x10029994: /* AMD Radeon HD 7400G (Trinity) */
719 case 0x10029995: /* AMD Radeon HD 8450G (Richland) */
720 case 0x10029996: /* AMD Radeon HD 8470D (Richland) */
721 case 0x10029997: /* AMD Radeon HD 8350G (Richland) */
722 case 0x10029998: /* AMD Radeon HD 8370D (Richland) */
723 case 0x10029999: /* AMD Radeon HD 8510G (Richland) */
724 case 0x1002999A: /* AMD Radeon HD 8410G (Richland) */
725 case 0x1002999B: /* AMD Radeon HD 8310G (Richland) */
726 case 0x1002999C: /* AMD Radeon HD 8650D (Richland) */
727 case 0x1002999D: /* AMD Radeon HD 8550D (Richland) */
728 case 0x100299A0: /* AMD Radeon HD 7520G (Trinity) */
729 case 0x100299A2: /* AMD Radeon HD 7420G (Trinity) */
730 case 0x100299A4: /* AMD Radeon HD 7400G (Trinity) */
Edward O'Callaghanae5fd342014-11-20 19:58:09 +1100731 new_vendev = 0x10029901;
Dave Frodincbf3d402012-12-05 08:20:12 -0700732 break;
733 }
734
735 return new_vendev;
736}