blob: 7c37ff8d7180120241ea013737ef7d783e576a5e [file] [log] [blame]
Angel Pons4b429832020-04-02 23:48:50 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Frank Vibrans39fca802011-02-14 18:35:15 +00002
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>
Frank Vibrans39fca802011-02-14 18:35:15 +00007#include <stdint.h>
8#include <device/device.h>
9#include <device/pci.h>
10#include <device/pci_ids.h>
Frank Vibrans39fca802011-02-14 18:35:15 +000011#include <string.h>
Ronald G. Minnich5079a0d2012-11-27 11:32:38 -080012#include <lib.h>
Frank Vibrans39fca802011-02-14 18:35:15 +000013#include <cpu/cpu.h>
Elyes HAOUAS400ce552018-10-12 10:54:30 +020014#include <cpu/amd/msr.h>
Kyösti Mälkki55fff9302012-07-11 08:02:39 +030015#include <cpu/amd/mtrr.h>
Kyösti Mälkki3d3152e2019-01-10 09:05:30 +020016#include <northbridge/amd/agesa/nb_common.h>
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020017#include <northbridge/amd/agesa/state_machine.h>
Kyösti Mälkkid610c582017-03-05 06:28:18 +020018#include <northbridge/amd/agesa/agesa_helper.h>
Kerry Shefeed3292011-08-18 18:03:44 +080019#include <sb_cimx.h>
Frank Vibrans39fca802011-02-14 18:35:15 +000020
Frank Vibrans39fca802011-02-14 18:35:15 +000021#define FX_DEVS 1
22
Kyösti Mälkkie2c2a4c2018-05-20 20:59:52 +030023static struct device *__f0_dev[FX_DEVS];
24static struct device *__f1_dev[FX_DEVS];
25static struct device *__f2_dev[FX_DEVS];
26static struct device *__f4_dev[FX_DEVS];
Subrata Banikb1434fc2019-03-15 22:20:41 +053027static unsigned int fx_devs = 0;
Frank Vibrans39fca802011-02-14 18:35:15 +000028
Kyösti Mälkki2b218e32019-01-15 11:14:28 +020029struct dram_base_mask_t {
30 u32 base; //[47:27] at [28:8]
31 u32 mask; //[47:27] at [28:8] and enable at bit 0
32};
33
34static struct dram_base_mask_t get_dram_base_mask(u32 nodeid)
35{
36 struct device *dev;
37 struct dram_base_mask_t d;
Kyösti Mälkki2b218e32019-01-15 11:14:28 +020038 dev = __f1_dev[0];
Kyösti Mälkki2b218e32019-01-15 11:14:28 +020039
40 u32 temp;
41 temp = pci_read_config32(dev, 0x44); //[39:24] at [31:16]
42 d.mask = (temp & 0xffff0000); // mask out DramMask [26:24] too
43
44 temp = pci_read_config32(dev, 0x40); //[35:24] at [27:16]
45 d.mask |= (temp & 1); // read enable bit
46
47 d.base = (temp & 0x0fff0000); // mask out DramBase [26:24) too
48
49 return d;
50}
51
52static u32 get_io_addr_index(u32 nodeid, u32 linkn)
53{
54 return 0;
55}
56
57static u32 get_mmio_addr_index(u32 nodeid, u32 linkn)
58{
59 return 0;
60}
61
62static void set_io_addr_reg(struct device *dev, u32 nodeid, u32 linkn, u32 reg,
63 u32 io_min, u32 io_max)
64{
65
66 u32 tempreg;
67 /* io range allocation */
68 tempreg = (nodeid & 0xf) | ((nodeid & 0x30) << (8 - 4)) | (linkn << 4) |
69 ((io_max & 0xf0) << (12 - 4)); //limit
70 pci_write_config32(__f1_dev[0], reg+4, tempreg);
71
72 tempreg = 3 | ((io_min & 0xf0) << (12 - 4)); //base :ISA and VGA ?
73 pci_write_config32(__f1_dev[0], reg, tempreg);
74}
75
76static void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index,
77 u32 mmio_min, u32 mmio_max, u32 nodes)
78{
79
80 u32 tempreg;
81 /* io range allocation */
82 tempreg = (nodeid & 0xf) | (linkn << 4) | (mmio_max & 0xffffff00);
83 pci_write_config32(__f1_dev[0], reg + 4, tempreg);
84 tempreg = 3 | (nodeid & 0x30) | (mmio_min & 0xffffff00);
85 pci_write_config32(__f1_dev[0], reg, tempreg);
86}
87
Kyösti Mälkkie2c2a4c2018-05-20 20:59:52 +030088static struct device *get_node_pci(u32 nodeid, u32 fn)
Frank Vibrans39fca802011-02-14 18:35:15 +000089{
Kyösti Mälkki3d3152e2019-01-10 09:05:30 +020090 return pcidev_on_root(DEV_CDB + nodeid, fn);
Frank Vibrans39fca802011-02-14 18:35:15 +000091}
92
Frank Vibrans39fca802011-02-14 18:35:15 +000093static void get_fx_devs(void)
94{
Marc Jones8d595692012-03-15 12:55:26 -060095 int i;
96 for (i = 0; i < FX_DEVS; i++) {
97 __f0_dev[i] = get_node_pci(i, 0);
98 __f1_dev[i] = get_node_pci(i, 1);
99 __f2_dev[i] = get_node_pci(i, 2);
100 __f4_dev[i] = get_node_pci(i, 4);
101 if (__f0_dev[i] != NULL && __f1_dev[i] != NULL)
102 fx_devs = i + 1;
103 }
104 if (__f1_dev[0] == NULL || __f0_dev[0] == NULL || fx_devs == 0) {
105 die("Cannot find 0:0x18.[0|1]\n");
106 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000107}
108
Subrata Banikb1434fc2019-03-15 22:20:41 +0530109static u32 f1_read_config32(unsigned int reg)
Frank Vibrans39fca802011-02-14 18:35:15 +0000110{
Marc Jones8d595692012-03-15 12:55:26 -0600111 if (fx_devs == 0)
112 get_fx_devs();
113 return pci_read_config32(__f1_dev[0], reg);
Frank Vibrans39fca802011-02-14 18:35:15 +0000114}
115
Subrata Banikb1434fc2019-03-15 22:20:41 +0530116static void f1_write_config32(unsigned int reg, u32 value)
Frank Vibrans39fca802011-02-14 18:35:15 +0000117{
Marc Jones8d595692012-03-15 12:55:26 -0600118 int i;
119 if (fx_devs == 0)
120 get_fx_devs();
121 for (i = 0; i < fx_devs; i++) {
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200122 struct device *dev;
Marc Jones8d595692012-03-15 12:55:26 -0600123 dev = __f1_dev[i];
124 if (dev && dev->enabled) {
125 pci_write_config32(dev, reg, value);
126 }
127 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000128}
129
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200130static u32 amdfam14_nodeid(struct device *dev)
Frank Vibrans39fca802011-02-14 18:35:15 +0000131{
Kyösti Mälkki3d3152e2019-01-10 09:05:30 +0200132 return (dev->path.pci.devfn >> 3) - DEV_CDB;
Frank Vibrans39fca802011-02-14 18:35:15 +0000133}
134
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200135static void northbridge_init(struct device *dev)
Frank Vibrans39fca802011-02-14 18:35:15 +0000136{
Marc Jones8d595692012-03-15 12:55:26 -0600137 printk(BIOS_DEBUG, "Northbridge init\n");
Frank Vibrans39fca802011-02-14 18:35:15 +0000138}
139
Frank Vibrans39fca802011-02-14 18:35:15 +0000140static void set_vga_enable_reg(u32 nodeid, u32 linkn)
141{
Marc Jones8d595692012-03-15 12:55:26 -0600142 u32 val;
Frank Vibrans39fca802011-02-14 18:35:15 +0000143
Marc Jones8d595692012-03-15 12:55:26 -0600144 val = 1 | (nodeid << 4) | (linkn << 12);
145 /* it will routing (1)mmio 0xa0000:0xbffff (2) io 0x3b0:0x3bb,
146 0x3c0:0x3df */
147 f1_write_config32(0xf4, val);
Frank Vibrans39fca802011-02-14 18:35:15 +0000148
149}
150
Subrata Banikb1434fc2019-03-15 22:20:41 +0530151static int reg_useable(unsigned int reg, struct device *goal_dev,
152 unsigned int goal_nodeid, unsigned int goal_link)
Frank Vibrans39fca802011-02-14 18:35:15 +0000153{
Marc Jones8d595692012-03-15 12:55:26 -0600154 struct resource *res;
Subrata Banikb1434fc2019-03-15 22:20:41 +0530155 unsigned int nodeid, link = 0;
Marc Jones8d595692012-03-15 12:55:26 -0600156 int result;
157 res = 0;
158 for (nodeid = 0; !res && (nodeid < fx_devs); nodeid++) {
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200159 struct device *dev;
Marc Jones8d595692012-03-15 12:55:26 -0600160 dev = __f0_dev[nodeid];
161 if (!dev)
162 continue;
163 for (link = 0; !res && (link < 8); link++) {
164 res = probe_resource(dev, IOINDEX(0x1000 + reg, link));
165 }
166 }
167 result = 2;
168 if (res) {
169 result = 0;
170 if ((goal_link == (link - 1)) &&
171 (goal_nodeid == (nodeid - 1)) && (res->flags <= 1)) {
172 result = 1;
173 }
174 }
175 return result;
Frank Vibrans39fca802011-02-14 18:35:15 +0000176}
177
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200178static struct resource *amdfam14_find_iopair(struct device *dev,
Subrata Banikb1434fc2019-03-15 22:20:41 +0530179 unsigned int nodeid, unsigned int link)
Frank Vibrans39fca802011-02-14 18:35:15 +0000180{
Marc Jones8d595692012-03-15 12:55:26 -0600181 struct resource *resource;
182 u32 result, reg;
183 resource = 0;
184 reg = 0;
185 result = reg_useable(0xc0, dev, nodeid, link);
186 if (result >= 1) {
187 /* I have been allocated this one */
188 reg = 0xc0;
189 }
190 /* Ext conf space */
191 if (!reg) {
192 /* Because of Extend conf space, we will never run out of reg,
Elyes HAOUASa342f392018-10-17 10:56:26 +0200193 * but we need one index to differ them. So,same node and same
Marc Jones8d595692012-03-15 12:55:26 -0600194 * link can have multi range
195 */
196 u32 index = get_io_addr_index(nodeid, link);
197 reg = 0x110 + (index << 24) + (4 << 20); // index could be 0, 255
198 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000199
Marc Jones8d595692012-03-15 12:55:26 -0600200 resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
Frank Vibrans39fca802011-02-14 18:35:15 +0000201
Marc Jones8d595692012-03-15 12:55:26 -0600202 return resource;
Frank Vibrans39fca802011-02-14 18:35:15 +0000203}
204
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200205static struct resource *amdfam14_find_mempair(struct device *dev, u32 nodeid,
Marc Jones8d595692012-03-15 12:55:26 -0600206 u32 link)
Frank Vibrans39fca802011-02-14 18:35:15 +0000207{
Marc Jones8d595692012-03-15 12:55:26 -0600208 struct resource *resource;
209 u32 free_reg, reg;
210 resource = 0;
211 free_reg = 0;
212 for (reg = 0x80; reg <= 0xb8; reg += 0x8) {
213 int result;
214 result = reg_useable(reg, dev, nodeid, link);
215 if (result == 1) {
216 /* I have been allocated this one */
217 break;
218 } else if (result > 1) {
219 /* I have a free register pair */
220 free_reg = reg;
221 }
222 }
223 if (reg > 0xb8) {
224 reg = free_reg;
225 }
226 /* Ext conf space */
227 if (!reg) {
228 /* Because of Extend conf space, we will never run out of reg,
Elyes HAOUASa342f392018-10-17 10:56:26 +0200229 * but we need one index to differ them. So,same node and same
Marc Jones8d595692012-03-15 12:55:26 -0600230 * link can have multi range
231 */
232 u32 index = get_mmio_addr_index(nodeid, link);
233 reg = 0x110 + (index << 24) + (6 << 20); // index could be 0, 63
Frank Vibrans39fca802011-02-14 18:35:15 +0000234
Marc Jones8d595692012-03-15 12:55:26 -0600235 }
236 resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
237 return resource;
Frank Vibrans39fca802011-02-14 18:35:15 +0000238}
239
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200240static void amdfam14_link_read_bases(struct device *dev, u32 nodeid, u32 link)
Frank Vibrans39fca802011-02-14 18:35:15 +0000241{
Marc Jones8d595692012-03-15 12:55:26 -0600242 struct resource *resource;
Frank Vibrans39fca802011-02-14 18:35:15 +0000243
Marc Jones8d595692012-03-15 12:55:26 -0600244 /* Initialize the io space constraints on the current bus */
245 resource = amdfam14_find_iopair(dev, nodeid, link);
246 if (resource) {
247 u32 align;
Kyösti Mälkkiac7402d2014-12-14 08:30:17 +0200248 align = log2(HT_IO_HOST_ALIGN);
Marc Jones8d595692012-03-15 12:55:26 -0600249 resource->base = 0;
250 resource->size = 0;
251 resource->align = align;
252 resource->gran = align;
253 resource->limit = 0xffffUL;
254 resource->flags = IORESOURCE_IO | IORESOURCE_BRIDGE;
255 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000256
Marc Jones8d595692012-03-15 12:55:26 -0600257 /* Initialize the prefetchable memory constraints on the current bus */
258 resource = amdfam14_find_mempair(dev, nodeid, link);
259 if (resource) {
260 resource->base = 0;
261 resource->size = 0;
262 resource->align = log2(HT_MEM_HOST_ALIGN);
263 resource->gran = log2(HT_MEM_HOST_ALIGN);
264 resource->limit = 0xffffffffffULL;
265 resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
266 resource->flags |= IORESOURCE_BRIDGE;
Marc Jones8d595692012-03-15 12:55:26 -0600267 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000268
Marc Jones8d595692012-03-15 12:55:26 -0600269 /* Initialize the memory constraints on the current bus */
270 resource = amdfam14_find_mempair(dev, nodeid, link);
271 if (resource) {
272 resource->base = 0;
273 resource->size = 0;
274 resource->align = log2(HT_MEM_HOST_ALIGN);
275 resource->gran = log2(HT_MEM_HOST_ALIGN);
276 resource->limit = 0xffffffffffULL;
277 resource->flags = IORESOURCE_MEM | IORESOURCE_BRIDGE;
Marc Jones8d595692012-03-15 12:55:26 -0600278 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000279}
280
281static u32 my_find_pci_tolm(struct bus *bus, u32 tolm)
282{
Marc Jones8d595692012-03-15 12:55:26 -0600283 struct resource *min;
Furquan Shaikhafaae8a2020-05-18 16:00:53 -0700284 unsigned long mask_match = IORESOURCE_MEM | IORESOURCE_ASSIGNED;
Marc Jones8d595692012-03-15 12:55:26 -0600285 min = 0;
Furquan Shaikhafaae8a2020-05-18 16:00:53 -0700286 search_bus_resources(bus, mask_match, mask_match, tolm_test,
Marc Jones8d595692012-03-15 12:55:26 -0600287 &min);
288 if (min && tolm > min->base) {
289 tolm = min->base;
290 }
291 return tolm;
Frank Vibrans39fca802011-02-14 18:35:15 +0000292}
293
294#if CONFIG_HW_MEM_HOLE_SIZEK != 0
295
296struct hw_mem_hole_info {
Subrata Banikb1434fc2019-03-15 22:20:41 +0530297 unsigned int hole_startk;
Marc Jones8d595692012-03-15 12:55:26 -0600298 int node_id;
Frank Vibrans39fca802011-02-14 18:35:15 +0000299};
300
301static struct hw_mem_hole_info get_hw_mem_hole_info(void)
302{
Marc Jones8d595692012-03-15 12:55:26 -0600303 struct hw_mem_hole_info mem_hole;
Frank Vibrans39fca802011-02-14 18:35:15 +0000304
Marc Jones8d595692012-03-15 12:55:26 -0600305 mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK;
306 mem_hole.node_id = -1;
Frank Vibrans39fca802011-02-14 18:35:15 +0000307
Marc Jones8d595692012-03-15 12:55:26 -0600308 struct dram_base_mask_t d;
309 u32 hole;
310 d = get_dram_base_mask(0);
311 if (d.mask & 1) {
312 hole = pci_read_config32(__f1_dev[0], 0xf0);
313 if (hole & 1) { // we find the hole
314 mem_hole.hole_startk = (hole & (0xff << 24)) >> 10;
315 mem_hole.node_id = 0; // record the node No with hole
316 }
317 }
Marc Jones8d595692012-03-15 12:55:26 -0600318 return mem_hole;
Frank Vibrans39fca802011-02-14 18:35:15 +0000319}
320#endif
321
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200322static void nb_read_resources(struct device *dev)
Frank Vibrans39fca802011-02-14 18:35:15 +0000323{
Marc Jones8d595692012-03-15 12:55:26 -0600324 u32 nodeid;
325 struct bus *link;
Frank Vibrans39fca802011-02-14 18:35:15 +0000326
Mike Loptien58089e82013-01-29 15:45:09 -0700327 printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
Frank Vibrans39fca802011-02-14 18:35:15 +0000328
Marc Jones8d595692012-03-15 12:55:26 -0600329 nodeid = amdfam14_nodeid(dev);
330 for (link = dev->link_list; link; link = link->next) {
331 if (link->children) {
332 amdfam14_link_read_bases(dev, nodeid, link->link_num);
333 }
334 }
Marc Jonesd5c998b2013-01-16 17:14:24 -0700335
336 /*
Stefan Reinauer4aff4452013-02-12 14:17:15 -0800337 * This MMCONF resource must be reserved in the PCI domain.
Marc Jonesd5c998b2013-01-16 17:14:24 -0700338 * It is not honored by the coreboot resource allocator if it is in
Stefan Reinauer0aa37c42013-02-12 15:20:54 -0800339 * the CPU_CLUSTER.
Marc Jonesd5c998b2013-01-16 17:14:24 -0700340 */
Elyes HAOUAS400ce552018-10-12 10:54:30 +0200341 mmconf_resource(dev, MMIO_CONF_BASE);
Frank Vibrans39fca802011-02-14 18:35:15 +0000342}
343
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200344static void set_resource(struct device *dev, struct resource *resource,
345 u32 nodeid)
Frank Vibrans39fca802011-02-14 18:35:15 +0000346{
Marc Jones8d595692012-03-15 12:55:26 -0600347 resource_t rbase, rend;
Subrata Banikb1434fc2019-03-15 22:20:41 +0530348 unsigned int reg, link_num;
Marc Jones8d595692012-03-15 12:55:26 -0600349 char buf[50];
Frank Vibrans39fca802011-02-14 18:35:15 +0000350
Mike Loptien58089e82013-01-29 15:45:09 -0700351 printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
Frank Vibrans39fca802011-02-14 18:35:15 +0000352
Marc Jones8d595692012-03-15 12:55:26 -0600353 /* Make certain the resource has actually been set */
354 if (!(resource->flags & IORESOURCE_ASSIGNED)) {
355 return;
356 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000357
Marc Jones8d595692012-03-15 12:55:26 -0600358 /* If I have already stored this resource don't worry about it */
359 if (resource->flags & IORESOURCE_STORED) {
360 return;
361 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000362
Marc Jones8d595692012-03-15 12:55:26 -0600363 /* Only handle PCI memory and IO resources */
364 if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
365 return;
Frank Vibrans39fca802011-02-14 18:35:15 +0000366
Marc Jones8d595692012-03-15 12:55:26 -0600367 /* Ensure I am actually looking at a resource of function 1 */
368 if ((resource->index & 0xffff) < 0x1000) {
369 return;
370 }
371 /* Get the base address */
372 rbase = resource->base;
Frank Vibrans39fca802011-02-14 18:35:15 +0000373
Marc Jones8d595692012-03-15 12:55:26 -0600374 /* Get the limit (rounded up) */
375 rend = resource_end(resource);
Frank Vibrans39fca802011-02-14 18:35:15 +0000376
Marc Jones8d595692012-03-15 12:55:26 -0600377 /* Get the register and link */
378 reg = resource->index & 0xfff; // 4k
379 link_num = IOINDEX_LINK(resource->index);
Frank Vibrans39fca802011-02-14 18:35:15 +0000380
Marc Jones8d595692012-03-15 12:55:26 -0600381 if (resource->flags & IORESOURCE_IO) {
382 set_io_addr_reg(dev, nodeid, link_num, reg, rbase >> 8,
383 rend >> 8);
384 } else if (resource->flags & IORESOURCE_MEM) {
385 set_mmio_addr_reg(nodeid, link_num, reg, (resource->index >> 24),
386 rbase >> 8, rend >> 8, 1); // [39:8]
387 }
388 resource->flags |= IORESOURCE_STORED;
Elyes HAOUAS0d4b11a2016-10-03 21:57:21 +0200389 snprintf(buf, sizeof(buf), " <node %x link %x>", nodeid, link_num);
Marc Jones8d595692012-03-15 12:55:26 -0600390 report_resource_stored(dev, resource, buf);
Frank Vibrans39fca802011-02-14 18:35:15 +0000391}
392
Julius Wernercd49cce2019-03-05 16:53:33 -0800393#if CONFIG(CONSOLE_VGA_MULTI)
Kyösti Mälkkie2c2a4c2018-05-20 20:59:52 +0300394extern struct device *vga_pri; // the primary vga device, defined in device.c
Frank Vibrans39fca802011-02-14 18:35:15 +0000395#endif
396
Subrata Banikb1434fc2019-03-15 22:20:41 +0530397static void create_vga_resource(struct device *dev, unsigned int nodeid)
Frank Vibrans39fca802011-02-14 18:35:15 +0000398{
Marc Jones8d595692012-03-15 12:55:26 -0600399 struct bus *link;
Frank Vibrans39fca802011-02-14 18:35:15 +0000400
Mike Loptien58089e82013-01-29 15:45:09 -0700401 printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
Frank Vibrans39fca802011-02-14 18:35:15 +0000402
Marc Jones8d595692012-03-15 12:55:26 -0600403 /* find out which link the VGA card is connected,
404 * we only deal with the 'first' vga card */
405 for (link = dev->link_list; link; link = link->next) {
406 if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
Julius Wernercd49cce2019-03-05 16:53:33 -0800407#if CONFIG(CONSOLE_VGA_MULTI)
Marc Jones8d595692012-03-15 12:55:26 -0600408 printk(BIOS_DEBUG,
409 "VGA: vga_pri bus num = %d bus range [%d,%d]\n",
410 vga_pri->bus->secondary, link->secondary,
411 link->subordinate);
412 /* We need to make sure the vga_pri is under the link */
413 if ((vga_pri->bus->secondary >= link->secondary) &&
414 (vga_pri->bus->secondary <= link->subordinate))
Frank Vibrans39fca802011-02-14 18:35:15 +0000415#endif
Marc Jones8d595692012-03-15 12:55:26 -0600416 break;
417 }
418 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000419
Marc Jones8d595692012-03-15 12:55:26 -0600420 /* no VGA card installed */
421 if (link == NULL)
422 return;
Frank Vibrans39fca802011-02-14 18:35:15 +0000423
Marc Jones8d595692012-03-15 12:55:26 -0600424 printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n",
425 dev_path(dev), nodeid, link->link_num);
426 set_vga_enable_reg(nodeid, link->link_num);
Frank Vibrans39fca802011-02-14 18:35:15 +0000427}
428
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200429static void nb_set_resources(struct device *dev)
Frank Vibrans39fca802011-02-14 18:35:15 +0000430{
Subrata Banikb1434fc2019-03-15 22:20:41 +0530431 unsigned int nodeid;
Marc Jones8d595692012-03-15 12:55:26 -0600432 struct bus *bus;
433 struct resource *res;
Frank Vibrans39fca802011-02-14 18:35:15 +0000434
Mike Loptien58089e82013-01-29 15:45:09 -0700435 printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
efdesign9805a89ab2011-06-20 17:38:49 -0700436
Marc Jones8d595692012-03-15 12:55:26 -0600437 /* Find the nodeid */
438 nodeid = amdfam14_nodeid(dev);
Frank Vibrans39fca802011-02-14 18:35:15 +0000439
Marc Jones8d595692012-03-15 12:55:26 -0600440 create_vga_resource(dev, nodeid);
Frank Vibrans39fca802011-02-14 18:35:15 +0000441
Marc Jones8d595692012-03-15 12:55:26 -0600442 /* Set each resource we have found */
443 for (res = dev->resource_list; res; res = res->next) {
444 set_resource(dev, res, nodeid);
445 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000446
Marc Jones8d595692012-03-15 12:55:26 -0600447 for (bus = dev->link_list; bus; bus = bus->next) {
448 if (bus->children) {
449 assign_resources(bus);
450 }
451 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000452}
453
Frank Vibrans39fca802011-02-14 18:35:15 +0000454/* Domain/Root Complex related code */
455
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200456static void domain_read_resources(struct device *dev)
Frank Vibrans39fca802011-02-14 18:35:15 +0000457{
Subrata Banikb1434fc2019-03-15 22:20:41 +0530458 unsigned int reg;
Frank Vibrans39fca802011-02-14 18:35:15 +0000459
Mike Loptien58089e82013-01-29 15:45:09 -0700460 printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
Frank Vibrans39fca802011-02-14 18:35:15 +0000461
Marc Jones8d595692012-03-15 12:55:26 -0600462 /* Find the already assigned resource pairs */
463 get_fx_devs();
464 for (reg = 0x80; reg <= 0xc0; reg += 0x08) {
465 u32 base, limit;
466 base = f1_read_config32(reg);
467 limit = f1_read_config32(reg + 0x04);
468 /* Is this register allocated? */
469 if ((base & 3) != 0) {
Subrata Banikb1434fc2019-03-15 22:20:41 +0530470 unsigned int nodeid, reg_link;
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200471 struct device *reg_dev;
Marc Jones8d595692012-03-15 12:55:26 -0600472 if (reg < 0xc0) { // mmio
473 nodeid = (limit & 0xf) + (base & 0x30);
474 } else { // io
475 nodeid = (limit & 0xf) + ((base >> 4) & 0x30);
476 }
477 reg_link = (limit >> 4) & 7;
478 reg_dev = __f0_dev[nodeid];
479 if (reg_dev) {
480 /* Reserve the resource */
481 struct resource *res;
482 res =
483 new_resource(reg_dev,
484 IOINDEX(0x1000 + reg,
485 reg_link));
486 if (res) {
487 res->flags = 1;
488 }
489 }
490 }
491 }
492 /* FIXME: do we need to check extend conf space?
493 I don't believe that much preset value */
Frank Vibrans39fca802011-02-14 18:35:15 +0000494
Marc Jones8d595692012-03-15 12:55:26 -0600495 pci_domain_read_resources(dev);
Frank Vibrans39fca802011-02-14 18:35:15 +0000496}
497
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200498static void domain_set_resources(struct device *dev)
Frank Vibrans39fca802011-02-14 18:35:15 +0000499{
Mike Loptien58089e82013-01-29 15:45:09 -0700500 printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
Stefan Reinauer29e65482015-06-18 01:18:09 -0700501 printk(BIOS_DEBUG, " amsr - incoming dev = %p\n", dev);
Frank Vibrans39fca802011-02-14 18:35:15 +0000502
Marc Jones8d595692012-03-15 12:55:26 -0600503 unsigned long mmio_basek;
504 u32 pci_tolm;
505 int idx;
506 struct bus *link;
Frank Vibrans39fca802011-02-14 18:35:15 +0000507#if CONFIG_HW_MEM_HOLE_SIZEK != 0
Marc Jones8d595692012-03-15 12:55:26 -0600508 struct hw_mem_hole_info mem_hole;
509 u32 reset_memhole = 1;
Frank Vibrans39fca802011-02-14 18:35:15 +0000510#endif
511
Marc Jones8d595692012-03-15 12:55:26 -0600512 pci_tolm = 0xffffffffUL;
513 for (link = dev->link_list; link; link = link->next) {
514 pci_tolm = my_find_pci_tolm(link, pci_tolm);
515 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000516
Marc Jones8d595692012-03-15 12:55:26 -0600517 // FIXME handle interleaved nodes. If you fix this here, please fix
518 // amdk8, too.
519 mmio_basek = pci_tolm >> 10;
520 /* Round mmio_basek to something the processor can support */
521 mmio_basek &= ~((1 << 6) - 1);
Frank Vibrans39fca802011-02-14 18:35:15 +0000522
Marc Jones8d595692012-03-15 12:55:26 -0600523 // FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M
524 // MMIO hole. If you fix this here, please fix amdk8, too.
525 /* Round the mmio hole to 64M */
526 mmio_basek &= ~((64 * 1024) - 1);
Frank Vibrans39fca802011-02-14 18:35:15 +0000527
528#if CONFIG_HW_MEM_HOLE_SIZEK != 0
529/* if the hw mem hole is already set in raminit stage, here we will compare
530 * mmio_basek and hole_basek. if mmio_basek is bigger that hole_basek and will
531 * use hole_basek as mmio_basek and we don't need to reset hole.
532 * otherwise We reset the hole to the mmio_basek
533 */
534
Marc Jones8d595692012-03-15 12:55:26 -0600535 mem_hole = get_hw_mem_hole_info();
Frank Vibrans39fca802011-02-14 18:35:15 +0000536
Marc Jones8d595692012-03-15 12:55:26 -0600537 // Use hole_basek as mmio_basek, and we don't need to reset hole anymore
538 if ((mem_hole.node_id != -1) && (mmio_basek > mem_hole.hole_startk)) {
539 mmio_basek = mem_hole.hole_startk;
540 reset_memhole = 0;
541 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000542#endif
543
Marc Jones8d595692012-03-15 12:55:26 -0600544 idx = 0x10;
Frank Vibrans39fca802011-02-14 18:35:15 +0000545
Marc Jones8d595692012-03-15 12:55:26 -0600546 struct dram_base_mask_t d;
547 resource_t basek, limitk, sizek; // 4 1T
Frank Vibrans39fca802011-02-14 18:35:15 +0000548
Marc Jones8d595692012-03-15 12:55:26 -0600549 d = get_dram_base_mask(0);
Frank Vibrans39fca802011-02-14 18:35:15 +0000550
Marc Jones8d595692012-03-15 12:55:26 -0600551 if (d.mask & 1) {
552 basek = ((resource_t) ((u64) d.base)) << 8;
553 limitk = (resource_t) (((u64) d.mask << 8) | 0xFFFFFF);
554 printk(BIOS_DEBUG,
555 "adsr: (before) basek = %llx, limitk = %llx.\n", basek,
556 limitk);
Frank Vibrans39fca802011-02-14 18:35:15 +0000557
Marc Jones8d595692012-03-15 12:55:26 -0600558 /* Convert these values to multiples of 1K for ease of math. */
559 basek >>= 10;
560 limitk >>= 10;
561 sizek = limitk - basek + 1;
Frank Vibrans39fca802011-02-14 18:35:15 +0000562
Marc Jones8d595692012-03-15 12:55:26 -0600563 printk(BIOS_DEBUG,
564 "adsr: (after) basek = %llx, limitk = %llx, sizek = %llx.\n",
565 basek, limitk, sizek);
Frank Vibrans39fca802011-02-14 18:35:15 +0000566
Marc Jones8d595692012-03-15 12:55:26 -0600567 /* see if we need a hole from 0xa0000 to 0xbffff */
568 if ((basek < 640) && (sizek > 768)) {
569 printk(BIOS_DEBUG,"adsr - 0xa0000 to 0xbffff resource.\n");
570 ram_resource(dev, (idx | 0), basek, 640 - basek);
571 idx += 0x10;
572 basek = 768;
573 sizek = limitk - 768;
574 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000575
Marc Jones8d595692012-03-15 12:55:26 -0600576 printk(BIOS_DEBUG,
577 "adsr: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",
578 mmio_basek, basek, limitk);
Frank Vibrans39fca802011-02-14 18:35:15 +0000579
Kyösti Mälkki26c65432014-06-26 05:30:54 +0300580 /* split the region to accommodate pci memory space */
Marc Jones8d595692012-03-15 12:55:26 -0600581 if ((basek < 4 * 1024 * 1024) && (limitk > mmio_basek)) {
582 if (basek <= mmio_basek) {
Subrata Banikb1434fc2019-03-15 22:20:41 +0530583 unsigned int pre_sizek;
Marc Jones8d595692012-03-15 12:55:26 -0600584 pre_sizek = mmio_basek - basek;
585 if (pre_sizek > 0) {
586 ram_resource(dev, idx, basek,
587 pre_sizek);
588 idx += 0x10;
589 sizek -= pre_sizek;
Marc Jones8d595692012-03-15 12:55:26 -0600590 }
Marc Jones8d595692012-03-15 12:55:26 -0600591 basek = mmio_basek;
592 }
593 if ((basek + sizek) <= 4 * 1024 * 1024) {
594 sizek = 0;
595 } else {
596 basek = 4 * 1024 * 1024;
597 sizek -= (4 * 1024 * 1024 - mmio_basek);
598 }
599 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000600
Marc Jones8d595692012-03-15 12:55:26 -0600601 ram_resource(dev, (idx | 0), basek, sizek);
602 idx += 0x10;
Marc Jones8d595692012-03-15 12:55:26 -0600603 printk(BIOS_DEBUG,
604 "%d: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n", 0,
605 mmio_basek, basek, limitk);
Marc Jones8d595692012-03-15 12:55:26 -0600606 }
607 printk(BIOS_DEBUG, " adsr - mmio_basek = %lx.\n", mmio_basek);
Frank Vibrans39fca802011-02-14 18:35:15 +0000608
Kyösti Mälkki61be3602017-04-15 20:07:53 +0300609 add_uma_resource_below_tolm(dev, 7);
Frank Vibrans39fca802011-02-14 18:35:15 +0000610
Marc Jones8d595692012-03-15 12:55:26 -0600611 for (link = dev->link_list; link; link = link->next) {
612 if (link->children) {
613 assign_resources(link);
614 }
615 }
616 printk(BIOS_DEBUG, " adsr - leaving this lovely routine.\n");
Frank Vibrans39fca802011-02-14 18:35:15 +0000617}
618
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600619static const char *domain_acpi_name(const struct device *dev)
Tobias Diedrichd8a2c1f2017-02-20 02:46:19 +0100620{
621 if (dev->path.type == DEVICE_PATH_DOMAIN)
622 return "PCI0";
623
624 return NULL;
625}
626
Frank Vibrans39fca802011-02-14 18:35:15 +0000627/* Bus related code */
628
Kyösti Mälkki580e7222015-03-19 21:04:23 +0200629static void cpu_bus_scan(struct device *dev)
zbaof7223732012-04-13 13:42:15 +0800630{
Kyösti Mälkkic33f1e92012-08-07 17:12:11 +0300631 struct bus *cpu_bus = dev->link_list;
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200632 struct device *cpu;
zbaof7223732012-04-13 13:42:15 +0800633 int apic_id, cores_found;
Scott Duplichan9ab3c6c2011-05-15 21:45:46 +0000634
zbaof7223732012-04-13 13:42:15 +0800635 /* There is only one node for fam14, but there may be multiple cores. */
Kyösti Mälkki4ad7f5b2018-05-22 01:15:17 +0300636 cpu = pcidev_on_root(0x18, 0);
zbaof7223732012-04-13 13:42:15 +0800637 if (!cpu)
638 printk(BIOS_ERR, "ERROR: %02x:%02x.0 not found", 0, 0x18);
Scott Duplichan9ab3c6c2011-05-15 21:45:46 +0000639
Kyösti Mälkki4ad7f5b2018-05-22 01:15:17 +0300640 cores_found = (pci_read_config32(pcidev_on_root(0x18, 0x3),
641 0xe8) >> 12) & 3;
zbaof7223732012-04-13 13:42:15 +0800642 printk(BIOS_DEBUG, " AP siblings=%d\n", cores_found);
643
zbaof7223732012-04-13 13:42:15 +0800644 for (apic_id = 0; apic_id <= cores_found; apic_id++) {
Kyösti Mälkkic33f1e92012-08-07 17:12:11 +0300645 cpu = add_cpu_device(cpu_bus, apic_id, 1);
646 if (cpu)
647 amd_cpu_topology(cpu, 0, apic_id);
Marc Jones8d595692012-03-15 12:55:26 -0600648 }
zbaof7223732012-04-13 13:42:15 +0800649}
650
Elyes HAOUAS0d7c7a82018-05-09 17:58:33 +0200651static void cpu_bus_init(struct device *dev)
zbaof7223732012-04-13 13:42:15 +0800652{
653 initialize_cpus(dev->link_list);
Frank Vibrans39fca802011-02-14 18:35:15 +0000654}
655
Frank Vibrans39fca802011-02-14 18:35:15 +0000656/* North Bridge Structures */
657
Furquan Shaikh7536a392020-04-24 21:59:21 -0700658static void northbridge_fill_ssdt_generator(const struct device *device)
Vladimir Serbinenko4ab588b2014-10-08 21:18:31 +0200659{
660 msr_t msr;
661 char pscope[] = "\\_SB.PCI0";
662
663 acpigen_write_scope(pscope);
664 msr = rdmsr(TOP_MEM);
665 acpigen_write_name_dword("TOM1", msr.lo);
666 msr = rdmsr(TOP_MEM2);
667 /*
668 * Since XP only implements parts of ACPI 2.0, we can't use a qword
669 * here.
670 * See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt
671 * slide 22ff.
672 * Shift value right by 20 bit to make it fit into 32bit,
673 * giving us 1MB granularity and a limit of almost 4Exabyte of memory.
674 */
675 acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20);
676 acpigen_pop_len();
677}
678
Vladimir Serbinenko807127f2014-11-09 13:36:18 +0100679static unsigned long acpi_fill_hest(acpi_hest_t *hest)
Vladimir Serbinenko4ab588b2014-10-08 21:18:31 +0200680{
681 void *addr, *current;
682
683 /* Skip the HEST header. */
684 current = (void *)(hest + 1);
685
686 addr = agesawrapper_getlateinitptr(PICK_WHEA_MCE);
687 if (addr != NULL)
Stefan Reinauer29e65482015-06-18 01:18:09 -0700688 current += acpi_create_hest_error_source(hest, current, 0,
689 addr + 2, *(UINT16 *)addr - 2);
Vladimir Serbinenko4ab588b2014-10-08 21:18:31 +0200690
691 addr = agesawrapper_getlateinitptr(PICK_WHEA_CMC);
692 if (addr != NULL)
Stefan Reinauer29e65482015-06-18 01:18:09 -0700693 current += acpi_create_hest_error_source(hest, current, 1,
694 addr + 2, *(UINT16 *)addr - 2);
Vladimir Serbinenko4ab588b2014-10-08 21:18:31 +0200695
696 return (unsigned long)current;
697}
698
Michał Żygowski9550e972020-03-20 13:56:46 +0100699static void patch_ssdt_processor_scope(acpi_header_t *ssdt)
700{
701 unsigned int len = ssdt->length - sizeof(acpi_header_t);
702 unsigned int i;
703
704 for (i = sizeof(acpi_header_t); i < len; i++) {
705 /* Search for _PR_ scope and replace it with _SB_ */
706 if (*(uint32_t *)((unsigned long)ssdt + i) == 0x5f52505f)
707 *(uint32_t *)((unsigned long)ssdt + i) = 0x5f42535f;
708 }
709 /* Recalculate checksum */
710 ssdt->checksum = 0;
711 ssdt->checksum = acpi_checksum((void *)ssdt, ssdt->length);
712}
713
Furquan Shaikh0f007d82020-04-24 06:41:18 -0700714static unsigned long agesa_write_acpi_tables(const struct device *device,
Alexander Couzens83fc32f2015-04-12 22:28:37 +0200715 unsigned long current,
Vladimir Serbinenko4ab588b2014-10-08 21:18:31 +0200716 acpi_rsdp_t *rsdp)
717{
718 acpi_srat_t *srat;
719 acpi_slit_t *slit;
720 acpi_header_t *ssdt;
721 acpi_header_t *alib;
722 acpi_hest_t *hest;
723
724 /* HEST */
725 current = ALIGN(current, 8);
726 hest = (acpi_hest_t *)current;
Vladimir Serbinenko807127f2014-11-09 13:36:18 +0100727 acpi_write_hest((void *)current, acpi_fill_hest);
Vladimir Serbinenko4ab588b2014-10-08 21:18:31 +0200728 acpi_add_table(rsdp, (void *)current);
729 current += ((acpi_header_t *)current)->length;
730
731 /* SRAT */
732 current = ALIGN(current, 8);
733 printk(BIOS_DEBUG, "ACPI: * SRAT at %lx\n", current);
734 srat = (acpi_srat_t *) agesawrapper_getlateinitptr (PICK_SRAT);
735 if (srat != NULL) {
736 memcpy((void *)current, srat, srat->header.length);
737 srat = (acpi_srat_t *) current;
738 current += srat->header.length;
739 acpi_add_table(rsdp, srat);
740 }
741 else {
742 printk(BIOS_DEBUG, " AGESA SRAT table NULL. Skipping.\n");
743 }
744
745 /* SLIT */
746 current = ALIGN(current, 8);
747 printk(BIOS_DEBUG, "ACPI: * SLIT at %lx\n", current);
748 slit = (acpi_slit_t *) agesawrapper_getlateinitptr (PICK_SLIT);
749 if (slit != NULL) {
750 memcpy((void *)current, slit, slit->header.length);
751 slit = (acpi_slit_t *) current;
752 current += slit->header.length;
753 acpi_add_table(rsdp, slit);
754 }
755 else {
756 printk(BIOS_DEBUG, " AGESA SLIT table NULL. Skipping.\n");
757 }
758
759 /* SSDT */
760 current = ALIGN(current, 16);
761 printk(BIOS_DEBUG, "ACPI: * AGESA ALIB SSDT at %lx\n", current);
762 alib = (acpi_header_t *)agesawrapper_getlateinitptr (PICK_ALIB);
763 if (alib != NULL) {
764 memcpy((void *)current, alib, alib->length);
765 alib = (acpi_header_t *) current;
766 current += alib->length;
767 acpi_add_table(rsdp, (void *)alib);
768 } else {
769 printk(BIOS_DEBUG, " AGESA ALIB SSDT table NULL. Skipping.\n");
770 }
771
772 /* The DSDT needs additional work for the AGESA SSDT Pstate table */
773 /* Keep the comment for a while. */
774 current = ALIGN(current, 16);
775 printk(BIOS_DEBUG, "ACPI: * AGESA SSDT Pstate at %lx\n", current);
776 ssdt = (acpi_header_t *)agesawrapper_getlateinitptr (PICK_PSTATE);
777 if (ssdt != NULL) {
Michał Żygowski9550e972020-03-20 13:56:46 +0100778 hexdump(ssdt, ssdt->length);
779 patch_ssdt_processor_scope(ssdt);
780 hexdump(ssdt, ssdt->length);
Vladimir Serbinenko4ab588b2014-10-08 21:18:31 +0200781 memcpy((void *)current, ssdt, ssdt->length);
782 ssdt = (acpi_header_t *) current;
783 current += ssdt->length;
784 acpi_add_table(rsdp,ssdt);
785 } else {
786 printk(BIOS_DEBUG, " AGESA SSDT Pstate table NULL. Skipping.\n");
787 }
788
789 return current;
790}
791
Frank Vibrans39fca802011-02-14 18:35:15 +0000792static struct device_operations northbridge_operations = {
Marc Jones8a49ac72013-01-16 17:02:20 -0700793 .read_resources = nb_read_resources,
794 .set_resources = nb_set_resources,
Marc Jones8d595692012-03-15 12:55:26 -0600795 .enable_resources = pci_dev_enable_resources,
Nico Huber68680dd2020-03-31 17:34:52 +0200796 .acpi_fill_ssdt = northbridge_fill_ssdt_generator,
Vladimir Serbinenko4ab588b2014-10-08 21:18:31 +0200797 .write_acpi_tables = agesa_write_acpi_tables,
Marc Jones8d595692012-03-15 12:55:26 -0600798 .init = northbridge_init,
799 .enable = 0,.ops_pci = 0,
Frank Vibrans39fca802011-02-14 18:35:15 +0000800};
801
Frank Vibrans39fca802011-02-14 18:35:15 +0000802static const struct pci_driver northbridge_driver __pci_driver = {
Marc Jones8d595692012-03-15 12:55:26 -0600803 .ops = &northbridge_operations,
804 .vendor = PCI_VENDOR_ID_AMD,
805 .device = 0x1510,
Frank Vibrans39fca802011-02-14 18:35:15 +0000806};
807
efdesign9805a89ab2011-06-20 17:38:49 -0700808struct chip_operations northbridge_amd_agesa_family14_ops = {
Marc Jones8d595692012-03-15 12:55:26 -0600809 CHIP_NAME("AMD Family 14h Northbridge")
810 .enable_dev = 0,
Frank Vibrans39fca802011-02-14 18:35:15 +0000811};
812
Frank Vibrans39fca802011-02-14 18:35:15 +0000813/* Root Complex Structures */
814
Frank Vibrans39fca802011-02-14 18:35:15 +0000815static struct device_operations pci_domain_ops = {
Marc Jones8d595692012-03-15 12:55:26 -0600816 .read_resources = domain_read_resources,
817 .set_resources = domain_set_resources,
Marc Jones8d595692012-03-15 12:55:26 -0600818 .scan_bus = pci_domain_scan_bus,
Tobias Diedrichd8a2c1f2017-02-20 02:46:19 +0100819 .acpi_name = domain_acpi_name,
Frank Vibrans39fca802011-02-14 18:35:15 +0000820};
821
Frank Vibrans39fca802011-02-14 18:35:15 +0000822static struct device_operations cpu_bus_ops = {
Nico Huber2f8ba692020-04-05 14:05:24 +0200823 .read_resources = noop_read_resources,
824 .set_resources = noop_set_resources,
Marc Jones8d595692012-03-15 12:55:26 -0600825 .init = cpu_bus_init,
zbaof7223732012-04-13 13:42:15 +0800826 .scan_bus = cpu_bus_scan,
Frank Vibrans39fca802011-02-14 18:35:15 +0000827};
828
Kyösti Mälkki87213b62012-08-27 20:00:33 +0300829static void root_complex_enable_dev(struct device *dev)
830{
831 static int done = 0;
832
Kyösti Mälkki87213b62012-08-27 20:00:33 +0300833 if (!done) {
834 setup_bsp_ramtop();
Kyösti Mälkki87213b62012-08-27 20:00:33 +0300835 done = 1;
836 }
837
Marc Jones8d595692012-03-15 12:55:26 -0600838 /* Set the operations if it is a special bus type */
Stefan Reinauer4aff4452013-02-12 14:17:15 -0800839 if (dev->path.type == DEVICE_PATH_DOMAIN) {
Marc Jones8d595692012-03-15 12:55:26 -0600840 dev->ops = &pci_domain_ops;
Stefan Reinauer0aa37c42013-02-12 15:20:54 -0800841 } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
Marc Jones8d595692012-03-15 12:55:26 -0600842 dev->ops = &cpu_bus_ops;
843 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000844}
845
efdesign9805a89ab2011-06-20 17:38:49 -0700846struct chip_operations northbridge_amd_agesa_family14_root_complex_ops = {
Marc Jones8d595692012-03-15 12:55:26 -0600847 CHIP_NAME("AMD Family 14h Root Complex")
848 .enable_dev = root_complex_enable_dev,
Frank Vibrans39fca802011-02-14 18:35:15 +0000849};
Kyösti Mälkki2b218e32019-01-15 11:14:28 +0200850
851/********************************************************************
852* Change the vendor / device IDs to match the generic VBIOS header.
853********************************************************************/
854u32 map_oprom_vendev(u32 vendev)
855{
856 u32 new_vendev = vendev;
857
858 switch (vendev) {
859 case 0x10029809:
860 case 0x10029808:
861 case 0x10029807:
862 case 0x10029806:
863 case 0x10029805:
864 case 0x10029804:
865 case 0x10029803:
866 new_vendev = 0x10029802;
867 break;
868 }
869
870 return new_vendev;
871}