blob: 00294b2934871faf1f2b7475f9694781b0a0bd9a [file] [log] [blame]
Frank Vibrans39fca802011-02-14 18:35:15 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011 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 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Paul Menzela46a7122013-02-23 18:37:27 +010017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Frank Vibrans39fca802011-02-14 18:35:15 +000018 */
19
20#include <console/console.h>
21#include <arch/io.h>
Kyösti Mälkki8ae16a42014-06-19 20:44:34 +030022#include <arch/acpi.h>
Frank Vibrans39fca802011-02-14 18:35:15 +000023#include <stdint.h>
24#include <device/device.h>
25#include <device/pci.h>
26#include <device/pci_ids.h>
27#include <device/hypertransport.h>
28#include <stdlib.h>
29#include <string.h>
Ronald G. Minnich5079a0d2012-11-27 11:32:38 -080030#include <lib.h>
Frank Vibrans39fca802011-02-14 18:35:15 +000031#include <cpu/cpu.h>
Marc Jones5750ed22012-03-15 13:21:41 -060032#include <cbmem.h>
Frank Vibrans39fca802011-02-14 18:35:15 +000033
34#include <cpu/x86/lapic.h>
Kyösti Mälkki55fff9302012-07-11 08:02:39 +030035#include <cpu/amd/mtrr.h>
Frank Vibrans39fca802011-02-14 18:35:15 +000036
efdesign983f5ebd62011-09-14 13:47:17 -060037#include "agesawrapper.h"
Kyösti Mälkki7b23ae02014-07-04 16:14:37 +030038#include <northbridge/amd/agesa/agesawrapper_call.h>
Frank Vibrans39fca802011-02-14 18:35:15 +000039#include "northbridge.h"
Kerry Shefeed3292011-08-18 18:03:44 +080040#if CONFIG_AMD_SB_CIMX
41#include <sb_cimx.h>
42#endif
Frank Vibrans39fca802011-02-14 18:35:15 +000043
Frank Vibrans39fca802011-02-14 18:35:15 +000044//#define FX_DEVS NODE_NUMS
45#define FX_DEVS 1
46
47static device_t __f0_dev[FX_DEVS];
48static device_t __f1_dev[FX_DEVS];
49static device_t __f2_dev[FX_DEVS];
50static device_t __f4_dev[FX_DEVS];
Marc Jones8d595692012-03-15 12:55:26 -060051static unsigned fx_devs = 0;
Frank Vibrans39fca802011-02-14 18:35:15 +000052
Edward O'Callaghan541ac592014-11-21 00:37:02 +110053static device_t get_node_pci(u32 nodeid, u32 fn)
Frank Vibrans39fca802011-02-14 18:35:15 +000054{
zbao49bb26a42012-08-03 15:44:42 +080055 if ((CONFIG_CDB + nodeid) < 32) {
56 return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB + nodeid, fn));
57 } else {
58 return dev_find_slot(CONFIG_CBB-1, PCI_DEVFN(CONFIG_CDB + nodeid - 32, fn));
59 }
Frank Vibrans39fca802011-02-14 18:35:15 +000060}
61
Frank Vibrans39fca802011-02-14 18:35:15 +000062static void get_fx_devs(void)
63{
Marc Jones8d595692012-03-15 12:55:26 -060064 int i;
65 for (i = 0; i < FX_DEVS; i++) {
66 __f0_dev[i] = get_node_pci(i, 0);
67 __f1_dev[i] = get_node_pci(i, 1);
68 __f2_dev[i] = get_node_pci(i, 2);
69 __f4_dev[i] = get_node_pci(i, 4);
70 if (__f0_dev[i] != NULL && __f1_dev[i] != NULL)
71 fx_devs = i + 1;
72 }
73 if (__f1_dev[0] == NULL || __f0_dev[0] == NULL || fx_devs == 0) {
74 die("Cannot find 0:0x18.[0|1]\n");
75 }
Frank Vibrans39fca802011-02-14 18:35:15 +000076}
77
Frank Vibrans39fca802011-02-14 18:35:15 +000078static u32 f1_read_config32(unsigned reg)
79{
Marc Jones8d595692012-03-15 12:55:26 -060080 if (fx_devs == 0)
81 get_fx_devs();
82 return pci_read_config32(__f1_dev[0], reg);
Frank Vibrans39fca802011-02-14 18:35:15 +000083}
84
Frank Vibrans39fca802011-02-14 18:35:15 +000085static void f1_write_config32(unsigned reg, u32 value)
86{
Marc Jones8d595692012-03-15 12:55:26 -060087 int i;
88 if (fx_devs == 0)
89 get_fx_devs();
90 for (i = 0; i < fx_devs; i++) {
91 device_t dev;
92 dev = __f1_dev[i];
93 if (dev && dev->enabled) {
94 pci_write_config32(dev, reg, value);
95 }
96 }
Frank Vibrans39fca802011-02-14 18:35:15 +000097}
98
Frank Vibrans39fca802011-02-14 18:35:15 +000099static u32 amdfam14_nodeid(device_t dev)
100{
Marc Jones8d595692012-03-15 12:55:26 -0600101 return (dev->path.pci.devfn >> 3) - CONFIG_CDB;
Frank Vibrans39fca802011-02-14 18:35:15 +0000102}
103
Frank Vibrans39fca802011-02-14 18:35:15 +0000104#include "amdfam14_conf.c"
105
Frank Vibrans39fca802011-02-14 18:35:15 +0000106static void northbridge_init(device_t dev)
107{
Marc Jones8d595692012-03-15 12:55:26 -0600108 printk(BIOS_DEBUG, "Northbridge init\n");
Frank Vibrans39fca802011-02-14 18:35:15 +0000109}
110
Frank Vibrans39fca802011-02-14 18:35:15 +0000111static void set_vga_enable_reg(u32 nodeid, u32 linkn)
112{
Marc Jones8d595692012-03-15 12:55:26 -0600113 u32 val;
Frank Vibrans39fca802011-02-14 18:35:15 +0000114
Marc Jones8d595692012-03-15 12:55:26 -0600115 val = 1 | (nodeid << 4) | (linkn << 12);
116 /* it will routing (1)mmio 0xa0000:0xbffff (2) io 0x3b0:0x3bb,
117 0x3c0:0x3df */
118 f1_write_config32(0xf4, val);
Frank Vibrans39fca802011-02-14 18:35:15 +0000119
120}
121
Frank Vibrans39fca802011-02-14 18:35:15 +0000122static int reg_useable(unsigned reg, device_t goal_dev, unsigned goal_nodeid,
Marc Jones8d595692012-03-15 12:55:26 -0600123 unsigned goal_link)
Frank Vibrans39fca802011-02-14 18:35:15 +0000124{
Marc Jones8d595692012-03-15 12:55:26 -0600125 struct resource *res;
126 unsigned nodeid, link = 0;
127 int result;
128 res = 0;
129 for (nodeid = 0; !res && (nodeid < fx_devs); nodeid++) {
130 device_t dev;
131 dev = __f0_dev[nodeid];
132 if (!dev)
133 continue;
134 for (link = 0; !res && (link < 8); link++) {
135 res = probe_resource(dev, IOINDEX(0x1000 + reg, link));
136 }
137 }
138 result = 2;
139 if (res) {
140 result = 0;
141 if ((goal_link == (link - 1)) &&
142 (goal_nodeid == (nodeid - 1)) && (res->flags <= 1)) {
143 result = 1;
144 }
145 }
146 return result;
Frank Vibrans39fca802011-02-14 18:35:15 +0000147}
148
Marc Jones8d595692012-03-15 12:55:26 -0600149static struct resource *amdfam14_find_iopair(device_t dev, unsigned nodeid,
150 unsigned link)
Frank Vibrans39fca802011-02-14 18:35:15 +0000151{
Marc Jones8d595692012-03-15 12:55:26 -0600152 struct resource *resource;
153 u32 result, reg;
154 resource = 0;
155 reg = 0;
156 result = reg_useable(0xc0, dev, nodeid, link);
157 if (result >= 1) {
158 /* I have been allocated this one */
159 reg = 0xc0;
160 }
161 /* Ext conf space */
162 if (!reg) {
163 /* Because of Extend conf space, we will never run out of reg,
164 * but we need one index to differ them. So ,same node and same
165 * link can have multi range
166 */
167 u32 index = get_io_addr_index(nodeid, link);
168 reg = 0x110 + (index << 24) + (4 << 20); // index could be 0, 255
169 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000170
Marc Jones8d595692012-03-15 12:55:26 -0600171 resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
Frank Vibrans39fca802011-02-14 18:35:15 +0000172
Marc Jones8d595692012-03-15 12:55:26 -0600173 return resource;
Frank Vibrans39fca802011-02-14 18:35:15 +0000174}
175
Marc Jones8d595692012-03-15 12:55:26 -0600176static struct resource *amdfam14_find_mempair(device_t dev, u32 nodeid,
177 u32 link)
Frank Vibrans39fca802011-02-14 18:35:15 +0000178{
Marc Jones8d595692012-03-15 12:55:26 -0600179 struct resource *resource;
180 u32 free_reg, reg;
181 resource = 0;
182 free_reg = 0;
183 for (reg = 0x80; reg <= 0xb8; reg += 0x8) {
184 int result;
185 result = reg_useable(reg, dev, nodeid, link);
186 if (result == 1) {
187 /* I have been allocated this one */
188 break;
189 } else if (result > 1) {
190 /* I have a free register pair */
191 free_reg = reg;
192 }
193 }
194 if (reg > 0xb8) {
195 reg = free_reg;
196 }
197 /* Ext conf space */
198 if (!reg) {
199 /* Because of Extend conf space, we will never run out of reg,
200 * but we need one index to differ them. So ,same node and same
201 * link can have multi range
202 */
203 u32 index = get_mmio_addr_index(nodeid, link);
204 reg = 0x110 + (index << 24) + (6 << 20); // index could be 0, 63
Frank Vibrans39fca802011-02-14 18:35:15 +0000205
Marc Jones8d595692012-03-15 12:55:26 -0600206 }
207 resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
208 return resource;
Frank Vibrans39fca802011-02-14 18:35:15 +0000209}
210
Frank Vibrans39fca802011-02-14 18:35:15 +0000211static void amdfam14_link_read_bases(device_t dev, u32 nodeid, u32 link)
212{
Marc Jones8d595692012-03-15 12:55:26 -0600213 struct resource *resource;
Frank Vibrans39fca802011-02-14 18:35:15 +0000214
Marc Jones8d595692012-03-15 12:55:26 -0600215 /* Initialize the io space constraints on the current bus */
216 resource = amdfam14_find_iopair(dev, nodeid, link);
217 if (resource) {
218 u32 align;
Patrick Georgie1667822012-05-05 15:29:32 +0200219#if CONFIG_EXT_CONF_SUPPORT
Marc Jones8d595692012-03-15 12:55:26 -0600220 if ((resource->index & 0x1fff) == 0x1110) { // ext
221 align = 8;
222 } else
Frank Vibrans39fca802011-02-14 18:35:15 +0000223#endif
Marc Jones8d595692012-03-15 12:55:26 -0600224 align = log2(HT_IO_HOST_ALIGN);
225 resource->base = 0;
226 resource->size = 0;
227 resource->align = align;
228 resource->gran = align;
229 resource->limit = 0xffffUL;
230 resource->flags = IORESOURCE_IO | IORESOURCE_BRIDGE;
231 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000232
Marc Jones8d595692012-03-15 12:55:26 -0600233 /* Initialize the prefetchable memory constraints on the current bus */
234 resource = amdfam14_find_mempair(dev, nodeid, link);
235 if (resource) {
236 resource->base = 0;
237 resource->size = 0;
238 resource->align = log2(HT_MEM_HOST_ALIGN);
239 resource->gran = log2(HT_MEM_HOST_ALIGN);
240 resource->limit = 0xffffffffffULL;
241 resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
242 resource->flags |= IORESOURCE_BRIDGE;
Frank Vibrans39fca802011-02-14 18:35:15 +0000243
Patrick Georgie1667822012-05-05 15:29:32 +0200244#if CONFIG_EXT_CONF_SUPPORT
Marc Jones8d595692012-03-15 12:55:26 -0600245 if ((resource->index & 0x1fff) == 0x1110) { // ext
246 normalize_resource(resource);
247 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000248#endif
249
Marc Jones8d595692012-03-15 12:55:26 -0600250 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000251
Marc Jones8d595692012-03-15 12:55:26 -0600252 /* Initialize the memory constraints on the current bus */
253 resource = amdfam14_find_mempair(dev, nodeid, link);
254 if (resource) {
255 resource->base = 0;
256 resource->size = 0;
257 resource->align = log2(HT_MEM_HOST_ALIGN);
258 resource->gran = log2(HT_MEM_HOST_ALIGN);
259 resource->limit = 0xffffffffffULL;
260 resource->flags = IORESOURCE_MEM | IORESOURCE_BRIDGE;
Patrick Georgie1667822012-05-05 15:29:32 +0200261#if CONFIG_EXT_CONF_SUPPORT
Marc Jones8d595692012-03-15 12:55:26 -0600262 if ((resource->index & 0x1fff) == 0x1110) { // ext
263 normalize_resource(resource);
264 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000265#endif
Marc Jones8d595692012-03-15 12:55:26 -0600266 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000267}
268
269static u32 my_find_pci_tolm(struct bus *bus, u32 tolm)
270{
Marc Jones8d595692012-03-15 12:55:26 -0600271 struct resource *min;
272 min = 0;
273 search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test,
274 &min);
275 if (min && tolm > min->base) {
276 tolm = min->base;
277 }
278 return tolm;
Frank Vibrans39fca802011-02-14 18:35:15 +0000279}
280
281#if CONFIG_HW_MEM_HOLE_SIZEK != 0
282
283struct hw_mem_hole_info {
Marc Jones8d595692012-03-15 12:55:26 -0600284 unsigned hole_startk;
285 int node_id;
Frank Vibrans39fca802011-02-14 18:35:15 +0000286};
287
288static struct hw_mem_hole_info get_hw_mem_hole_info(void)
289{
Marc Jones8d595692012-03-15 12:55:26 -0600290 struct hw_mem_hole_info mem_hole;
Frank Vibrans39fca802011-02-14 18:35:15 +0000291
Marc Jones8d595692012-03-15 12:55:26 -0600292 mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK;
293 mem_hole.node_id = -1;
Frank Vibrans39fca802011-02-14 18:35:15 +0000294
Marc Jones8d595692012-03-15 12:55:26 -0600295 struct dram_base_mask_t d;
296 u32 hole;
297 d = get_dram_base_mask(0);
298 if (d.mask & 1) {
299 hole = pci_read_config32(__f1_dev[0], 0xf0);
300 if (hole & 1) { // we find the hole
301 mem_hole.hole_startk = (hole & (0xff << 24)) >> 10;
302 mem_hole.node_id = 0; // record the node No with hole
303 }
304 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000305#if 0
Kyösti Mälkki2f9b3af2014-06-26 05:30:54 +0300306 /* We need to double check if there is special set on base reg and limit reg
307 * are not continuous instead of hole, it will find out its hole_startk.
Marc Jones8d595692012-03-15 12:55:26 -0600308 */
309 if (mem_hole.node_id == -1) {
310 resource_t limitk_pri = 0;
311 struct dram_base_mask_t d;
312 resource_t base_k, limit_k;
313 d = get_dram_base_mask(0);
314 if (d.base & 1) {
315 base_k = ((resource_t) (d.base & 0x1fffff00)) << 9;
316 if (base_k <= 4 * 1024 * 1024) {
317 if (limitk_pri != base_k) { // we find the hole
318 mem_hole.hole_startk = (unsigned)limitk_pri; // must be below 4G
319 mem_hole.node_id = 0;
320 }
321 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000322
Marc Jones8d595692012-03-15 12:55:26 -0600323 limit_k =
324 ((resource_t) ((d.mask + 0x00000100) & 0x1fffff00))
325 << 9;
326 limitk_pri = limit_k;
327 }
328 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000329#endif
efdesign9805a89ab2011-06-20 17:38:49 -0700330
Marc Jones8d595692012-03-15 12:55:26 -0600331 return mem_hole;
Frank Vibrans39fca802011-02-14 18:35:15 +0000332}
333#endif
334
Marc Jones8a49ac72013-01-16 17:02:20 -0700335static void nb_read_resources(device_t dev)
Frank Vibrans39fca802011-02-14 18:35:15 +0000336{
Marc Jones8d595692012-03-15 12:55:26 -0600337 u32 nodeid;
338 struct bus *link;
Frank Vibrans39fca802011-02-14 18:35:15 +0000339
Mike Loptien58089e82013-01-29 15:45:09 -0700340 printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
Frank Vibrans39fca802011-02-14 18:35:15 +0000341
Marc Jones8d595692012-03-15 12:55:26 -0600342 nodeid = amdfam14_nodeid(dev);
343 for (link = dev->link_list; link; link = link->next) {
344 if (link->children) {
345 amdfam14_link_read_bases(dev, nodeid, link->link_num);
346 }
347 }
Marc Jonesd5c998b2013-01-16 17:14:24 -0700348
349 /*
Stefan Reinauer4aff4452013-02-12 14:17:15 -0800350 * This MMCONF resource must be reserved in the PCI domain.
Marc Jonesd5c998b2013-01-16 17:14:24 -0700351 * It is not honored by the coreboot resource allocator if it is in
Stefan Reinauer0aa37c42013-02-12 15:20:54 -0800352 * the CPU_CLUSTER.
Marc Jonesd5c998b2013-01-16 17:14:24 -0700353 */
354#if CONFIG_MMCONF_SUPPORT
355 struct resource *resource = new_resource(dev, 0xc0010058);
356 resource->base = CONFIG_MMCONF_BASE_ADDRESS;
357 resource->size = CONFIG_MMCONF_BUS_NUMBER * 4096 * 256;
358 resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
359 IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
360#endif
Frank Vibrans39fca802011-02-14 18:35:15 +0000361}
362
Marc Jones8d595692012-03-15 12:55:26 -0600363static void set_resource(device_t dev, struct resource *resource, u32 nodeid)
Frank Vibrans39fca802011-02-14 18:35:15 +0000364{
Marc Jones8d595692012-03-15 12:55:26 -0600365 resource_t rbase, rend;
366 unsigned reg, link_num;
367 char buf[50];
Frank Vibrans39fca802011-02-14 18:35:15 +0000368
Mike Loptien58089e82013-01-29 15:45:09 -0700369 printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
Frank Vibrans39fca802011-02-14 18:35:15 +0000370
Marc Jones8d595692012-03-15 12:55:26 -0600371 /* Make certain the resource has actually been set */
372 if (!(resource->flags & IORESOURCE_ASSIGNED)) {
373 return;
374 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000375
Marc Jones8d595692012-03-15 12:55:26 -0600376 /* If I have already stored this resource don't worry about it */
377 if (resource->flags & IORESOURCE_STORED) {
378 return;
379 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000380
Marc Jones8d595692012-03-15 12:55:26 -0600381 /* Only handle PCI memory and IO resources */
382 if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
383 return;
Frank Vibrans39fca802011-02-14 18:35:15 +0000384
Marc Jones8d595692012-03-15 12:55:26 -0600385 /* Ensure I am actually looking at a resource of function 1 */
386 if ((resource->index & 0xffff) < 0x1000) {
387 return;
388 }
389 /* Get the base address */
390 rbase = resource->base;
Frank Vibrans39fca802011-02-14 18:35:15 +0000391
Marc Jones8d595692012-03-15 12:55:26 -0600392 /* Get the limit (rounded up) */
393 rend = resource_end(resource);
Frank Vibrans39fca802011-02-14 18:35:15 +0000394
Marc Jones8d595692012-03-15 12:55:26 -0600395 /* Get the register and link */
396 reg = resource->index & 0xfff; // 4k
397 link_num = IOINDEX_LINK(resource->index);
Frank Vibrans39fca802011-02-14 18:35:15 +0000398
Marc Jones8d595692012-03-15 12:55:26 -0600399 if (resource->flags & IORESOURCE_IO) {
400 set_io_addr_reg(dev, nodeid, link_num, reg, rbase >> 8,
401 rend >> 8);
402 } else if (resource->flags & IORESOURCE_MEM) {
403 set_mmio_addr_reg(nodeid, link_num, reg, (resource->index >> 24),
404 rbase >> 8, rend >> 8, 1); // [39:8]
405 }
406 resource->flags |= IORESOURCE_STORED;
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100407 snprintf(buf, sizeof (buf), " <node %x link %x>", nodeid, link_num);
Marc Jones8d595692012-03-15 12:55:26 -0600408 report_resource_stored(dev, resource, buf);
Frank Vibrans39fca802011-02-14 18:35:15 +0000409}
410
efdesign983f5ebd62011-09-14 13:47:17 -0600411#if CONFIG_CONSOLE_VGA_MULTI
Marc Jones8d595692012-03-15 12:55:26 -0600412extern device_t vga_pri; // the primary vga device, defined in device.c
Frank Vibrans39fca802011-02-14 18:35:15 +0000413#endif
414
415static void create_vga_resource(device_t dev, unsigned nodeid)
416{
Marc Jones8d595692012-03-15 12:55:26 -0600417 struct bus *link;
Frank Vibrans39fca802011-02-14 18:35:15 +0000418
Mike Loptien58089e82013-01-29 15:45:09 -0700419 printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
Frank Vibrans39fca802011-02-14 18:35:15 +0000420
Marc Jones8d595692012-03-15 12:55:26 -0600421 /* find out which link the VGA card is connected,
422 * we only deal with the 'first' vga card */
423 for (link = dev->link_list; link; link = link->next) {
424 if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
efdesign983f5ebd62011-09-14 13:47:17 -0600425#if CONFIG_CONSOLE_VGA_MULTI
Marc Jones8d595692012-03-15 12:55:26 -0600426 printk(BIOS_DEBUG,
427 "VGA: vga_pri bus num = %d bus range [%d,%d]\n",
428 vga_pri->bus->secondary, link->secondary,
429 link->subordinate);
430 /* We need to make sure the vga_pri is under the link */
431 if ((vga_pri->bus->secondary >= link->secondary) &&
432 (vga_pri->bus->secondary <= link->subordinate))
Frank Vibrans39fca802011-02-14 18:35:15 +0000433#endif
Marc Jones8d595692012-03-15 12:55:26 -0600434 break;
435 }
436 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000437
Marc Jones8d595692012-03-15 12:55:26 -0600438 /* no VGA card installed */
439 if (link == NULL)
440 return;
Frank Vibrans39fca802011-02-14 18:35:15 +0000441
Marc Jones8d595692012-03-15 12:55:26 -0600442 printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n",
443 dev_path(dev), nodeid, link->link_num);
444 set_vga_enable_reg(nodeid, link->link_num);
Frank Vibrans39fca802011-02-14 18:35:15 +0000445}
446
Marc Jones8a49ac72013-01-16 17:02:20 -0700447static void nb_set_resources(device_t dev)
Frank Vibrans39fca802011-02-14 18:35:15 +0000448{
Marc Jones8d595692012-03-15 12:55:26 -0600449 unsigned nodeid;
450 struct bus *bus;
451 struct resource *res;
Frank Vibrans39fca802011-02-14 18:35:15 +0000452
Mike Loptien58089e82013-01-29 15:45:09 -0700453 printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
efdesign9805a89ab2011-06-20 17:38:49 -0700454
Marc Jones8d595692012-03-15 12:55:26 -0600455 /* Find the nodeid */
456 nodeid = amdfam14_nodeid(dev);
Frank Vibrans39fca802011-02-14 18:35:15 +0000457
Marc Jones8d595692012-03-15 12:55:26 -0600458 create_vga_resource(dev, nodeid);
Frank Vibrans39fca802011-02-14 18:35:15 +0000459
Marc Jones8d595692012-03-15 12:55:26 -0600460 /* Set each resource we have found */
461 for (res = dev->resource_list; res; res = res->next) {
462 set_resource(dev, res, nodeid);
463 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000464
Marc Jones8d595692012-03-15 12:55:26 -0600465 for (bus = dev->link_list; bus; bus = bus->next) {
466 if (bus->children) {
467 assign_resources(bus);
468 }
469 }
Marc Jonesd5c998b2013-01-16 17:14:24 -0700470
471 /* Print the MMCONF region if it has been reserved. */
472 res = find_resource(dev, 0xc0010058);
473 if (res) {
474 report_resource_stored(dev, res, " <mmconfig>");
475 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000476}
477
Frank Vibrans39fca802011-02-14 18:35:15 +0000478/* Domain/Root Complex related code */
479
480static void domain_read_resources(device_t dev)
481{
Marc Jones8d595692012-03-15 12:55:26 -0600482 unsigned reg;
Frank Vibrans39fca802011-02-14 18:35:15 +0000483
Mike Loptien58089e82013-01-29 15:45:09 -0700484 printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
Frank Vibrans39fca802011-02-14 18:35:15 +0000485
Marc Jones8d595692012-03-15 12:55:26 -0600486 /* Find the already assigned resource pairs */
487 get_fx_devs();
488 for (reg = 0x80; reg <= 0xc0; reg += 0x08) {
489 u32 base, limit;
490 base = f1_read_config32(reg);
491 limit = f1_read_config32(reg + 0x04);
492 /* Is this register allocated? */
493 if ((base & 3) != 0) {
494 unsigned nodeid, reg_link;
495 device_t reg_dev;
496 if (reg < 0xc0) { // mmio
497 nodeid = (limit & 0xf) + (base & 0x30);
498 } else { // io
499 nodeid = (limit & 0xf) + ((base >> 4) & 0x30);
500 }
501 reg_link = (limit >> 4) & 7;
502 reg_dev = __f0_dev[nodeid];
503 if (reg_dev) {
504 /* Reserve the resource */
505 struct resource *res;
506 res =
507 new_resource(reg_dev,
508 IOINDEX(0x1000 + reg,
509 reg_link));
510 if (res) {
511 res->flags = 1;
512 }
513 }
514 }
515 }
516 /* FIXME: do we need to check extend conf space?
517 I don't believe that much preset value */
Frank Vibrans39fca802011-02-14 18:35:15 +0000518
Patrick Georgie1667822012-05-05 15:29:32 +0200519#if !CONFIG_PCI_64BIT_PREF_MEM
Marc Jones8d595692012-03-15 12:55:26 -0600520 pci_domain_read_resources(dev);
Frank Vibrans39fca802011-02-14 18:35:15 +0000521#else
Marc Jones8d595692012-03-15 12:55:26 -0600522 struct bus *link;
523 struct resource *resource;
524 for (link = dev->link_list; link; link = link->next) {
525 /* Initialize the system wide io space constraints */
526 resource = new_resource(dev, 0 | (link->link_num << 2));
527 resource->base = 0x400;
528 resource->limit = 0xffffUL;
529 resource->flags = IORESOURCE_IO;
Frank Vibrans39fca802011-02-14 18:35:15 +0000530
Marc Jones8d595692012-03-15 12:55:26 -0600531 /* Initialize the system wide prefetchable memory resources constraints */
532 resource = new_resource(dev, 1 | (link->link_num << 2));
533 resource->limit = 0xfcffffffffULL;
534 resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
Frank Vibrans39fca802011-02-14 18:35:15 +0000535
Marc Jones8d595692012-03-15 12:55:26 -0600536 /* Initialize the system wide memory resources constraints */
537 resource = new_resource(dev, 2 | (link->link_num << 2));
538 resource->limit = 0xfcffffffffULL;
539 resource->flags = IORESOURCE_MEM;
540 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000541#endif
542}
543
Kyösti Mälkki6b5eb1c2012-07-19 19:26:43 +0300544static void setup_uma_memory(void)
Kyösti Mälkki55fff9302012-07-11 08:02:39 +0300545{
546#if CONFIG_GFXUMA
Kyösti Mälkkidbc47392012-08-05 12:11:40 +0300547 uint32_t topmem = (uint32_t) bsp_topmem();
Kyösti Mälkki55fff9302012-07-11 08:02:39 +0300548 uint32_t sys_mem;
549
Kyösti Mälkki55fff9302012-07-11 08:02:39 +0300550 /* refer to UMA Size Consideration in Family14h BKDG. */
Kyösti Mälkkidbc47392012-08-05 12:11:40 +0300551 sys_mem = topmem + 0x1000000; // Ignore 16MB allocated for C6 when finding UMA size, refer MemNGetUmaSizeON()
552 if ((bsp_topmem2()>>32) || (sys_mem >= 0x80000000)) {
Kyösti Mälkki55fff9302012-07-11 08:02:39 +0300553 uma_memory_size = 0x18000000; /* >= 2G memory, 384M recommended UMA */
554 }
555 else {
556 if (sys_mem >= 0x40000000) {
557 uma_memory_size = 0x10000000; /* >= 1G memory, 256M recommended UMA */
558 } else {
559 uma_memory_size = 0x4000000; /* <1G memory, 64M recommended UMA */
560 }
561 }
562
Kyösti Mälkkidbc47392012-08-05 12:11:40 +0300563 uma_memory_base = topmem - uma_memory_size; /* TOP_MEM1 */
Kyösti Mälkki55fff9302012-07-11 08:02:39 +0300564 printk(BIOS_INFO, "%s: uma size 0x%08llx, memory start 0x%08llx\n",
565 __func__, uma_memory_size, uma_memory_base);
Kyösti Mälkki55fff9302012-07-11 08:02:39 +0300566#endif
567}
568
Frank Vibrans39fca802011-02-14 18:35:15 +0000569static void domain_set_resources(device_t dev)
570{
Mike Loptien58089e82013-01-29 15:45:09 -0700571 printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
Marc Jones8d595692012-03-15 12:55:26 -0600572 printk(BIOS_DEBUG, " amsr - incoming dev = %08x\n", (u32) dev);
Frank Vibrans39fca802011-02-14 18:35:15 +0000573
Patrick Georgie1667822012-05-05 15:29:32 +0200574#if CONFIG_PCI_64BIT_PREF_MEM
Marc Jones8d595692012-03-15 12:55:26 -0600575 struct resource *io, *mem1, *mem2;
576 struct resource *res;
Frank Vibrans39fca802011-02-14 18:35:15 +0000577#endif
Marc Jones8d595692012-03-15 12:55:26 -0600578 unsigned long mmio_basek;
579 u32 pci_tolm;
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300580 u64 ramtop = 0;
Marc Jones8d595692012-03-15 12:55:26 -0600581 int idx;
582 struct bus *link;
Frank Vibrans39fca802011-02-14 18:35:15 +0000583#if CONFIG_HW_MEM_HOLE_SIZEK != 0
Marc Jones8d595692012-03-15 12:55:26 -0600584 struct hw_mem_hole_info mem_hole;
585 u32 reset_memhole = 1;
Frank Vibrans39fca802011-02-14 18:35:15 +0000586#endif
587
Patrick Georgie1667822012-05-05 15:29:32 +0200588#if CONFIG_PCI_64BIT_PREF_MEM
Frank Vibrans39fca802011-02-14 18:35:15 +0000589
Marc Jones8d595692012-03-15 12:55:26 -0600590 printk(BIOS_DEBUG, "adsr - CONFIG_PCI_64BIT_PREF_MEM is true.\n");
591 for (link = dev->link_list; link; link = link->next) {
592 /* Now reallocate the pci resources memory with the
593 * highest addresses I can manage.
594 */
595 mem1 = find_resource(dev, 1 | (link->link_num << 2));
596 mem2 = find_resource(dev, 2 | (link->link_num << 2));
Frank Vibrans39fca802011-02-14 18:35:15 +0000597
Marc Jones8d595692012-03-15 12:55:26 -0600598 printk(BIOS_DEBUG,
599 "base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
600 (u32) (mem1->base), (u32) (mem1->limit),
601 (u32) (mem1->size), u32) (mem1->align));
602 printk(BIOS_DEBUG,
603 "base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
604 (u32) (mem2->base), (u32) (mem2->limit),
605 (u32) (mem2->size), (u32) (mem2->align));
Frank Vibrans39fca802011-02-14 18:35:15 +0000606
Marc Jones8d595692012-03-15 12:55:26 -0600607 /* See if both resources have roughly the same limits */
608 if (((mem1->limit <= 0xffffffff) && (mem2->limit <= 0xffffffff))
609 || ((mem1->limit > 0xffffffff)
610 && (mem2->limit > 0xffffffff))) {
611 /* If so place the one with the most stringent alignment first
612 */
613 if (mem2->align > mem1->align) {
614 struct resource *tmp;
615 tmp = mem1;
616 mem1 = mem2;
617 mem2 = tmp;
618 }
619 /* Now place the memory as high up as it will go */
620 mem2->base = resource_max(mem2);
621 mem1->limit = mem2->base - 1;
622 mem1->base = resource_max(mem1);
623 } else {
624 /* Place the resources as high up as they will go */
625 mem2->base = resource_max(mem2);
626 mem1->base = resource_max(mem1);
627 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000628
Marc Jones8d595692012-03-15 12:55:26 -0600629 printk(BIOS_DEBUG,
630 "base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
631 mem1->base, mem1->limit, mem1->size, mem1->align);
632 printk(BIOS_DEBUG,
633 "base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
634 mem2->base, mem2->limit, mem2->size, mem2->align);
635 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000636
Marc Jones8d595692012-03-15 12:55:26 -0600637 for (res = &dev->resource_list; res; res = res->next) {
638 res->flags |= IORESOURCE_ASSIGNED;
639 res->flags |= IORESOURCE_STORED;
640 report_resource_stored(dev, res, "");
641 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000642#endif
643
Marc Jones8d595692012-03-15 12:55:26 -0600644 pci_tolm = 0xffffffffUL;
645 for (link = dev->link_list; link; link = link->next) {
646 pci_tolm = my_find_pci_tolm(link, pci_tolm);
647 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000648
Marc Jones8d595692012-03-15 12:55:26 -0600649 // FIXME handle interleaved nodes. If you fix this here, please fix
650 // amdk8, too.
651 mmio_basek = pci_tolm >> 10;
652 /* Round mmio_basek to something the processor can support */
653 mmio_basek &= ~((1 << 6) - 1);
Frank Vibrans39fca802011-02-14 18:35:15 +0000654
Marc Jones8d595692012-03-15 12:55:26 -0600655 // FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M
656 // MMIO hole. If you fix this here, please fix amdk8, too.
657 /* Round the mmio hole to 64M */
658 mmio_basek &= ~((64 * 1024) - 1);
Frank Vibrans39fca802011-02-14 18:35:15 +0000659
660#if CONFIG_HW_MEM_HOLE_SIZEK != 0
661/* if the hw mem hole is already set in raminit stage, here we will compare
662 * mmio_basek and hole_basek. if mmio_basek is bigger that hole_basek and will
663 * use hole_basek as mmio_basek and we don't need to reset hole.
664 * otherwise We reset the hole to the mmio_basek
665 */
666
Marc Jones8d595692012-03-15 12:55:26 -0600667 mem_hole = get_hw_mem_hole_info();
Frank Vibrans39fca802011-02-14 18:35:15 +0000668
Marc Jones8d595692012-03-15 12:55:26 -0600669 // Use hole_basek as mmio_basek, and we don't need to reset hole anymore
670 if ((mem_hole.node_id != -1) && (mmio_basek > mem_hole.hole_startk)) {
671 mmio_basek = mem_hole.hole_startk;
672 reset_memhole = 0;
673 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000674#endif
675
Marc Jones8d595692012-03-15 12:55:26 -0600676 idx = 0x10;
Frank Vibrans39fca802011-02-14 18:35:15 +0000677
Marc Jones8d595692012-03-15 12:55:26 -0600678 struct dram_base_mask_t d;
679 resource_t basek, limitk, sizek; // 4 1T
Frank Vibrans39fca802011-02-14 18:35:15 +0000680
Marc Jones8d595692012-03-15 12:55:26 -0600681 d = get_dram_base_mask(0);
Frank Vibrans39fca802011-02-14 18:35:15 +0000682
Marc Jones8d595692012-03-15 12:55:26 -0600683 if (d.mask & 1) {
684 basek = ((resource_t) ((u64) d.base)) << 8;
685 limitk = (resource_t) (((u64) d.mask << 8) | 0xFFFFFF);
686 printk(BIOS_DEBUG,
687 "adsr: (before) basek = %llx, limitk = %llx.\n", basek,
688 limitk);
Frank Vibrans39fca802011-02-14 18:35:15 +0000689
Marc Jones8d595692012-03-15 12:55:26 -0600690 /* Convert these values to multiples of 1K for ease of math. */
691 basek >>= 10;
692 limitk >>= 10;
693 sizek = limitk - basek + 1;
Frank Vibrans39fca802011-02-14 18:35:15 +0000694
Marc Jones8d595692012-03-15 12:55:26 -0600695 printk(BIOS_DEBUG,
696 "adsr: (after) basek = %llx, limitk = %llx, sizek = %llx.\n",
697 basek, limitk, sizek);
Frank Vibrans39fca802011-02-14 18:35:15 +0000698
Marc Jones8d595692012-03-15 12:55:26 -0600699 /* see if we need a hole from 0xa0000 to 0xbffff */
700 if ((basek < 640) && (sizek > 768)) {
701 printk(BIOS_DEBUG,"adsr - 0xa0000 to 0xbffff resource.\n");
702 ram_resource(dev, (idx | 0), basek, 640 - basek);
703 idx += 0x10;
704 basek = 768;
705 sizek = limitk - 768;
706 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000707
Marc Jones8d595692012-03-15 12:55:26 -0600708 printk(BIOS_DEBUG,
709 "adsr: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",
710 mmio_basek, basek, limitk);
Frank Vibrans39fca802011-02-14 18:35:15 +0000711
Kyösti Mälkki26c65432014-06-26 05:30:54 +0300712 /* split the region to accommodate pci memory space */
Marc Jones8d595692012-03-15 12:55:26 -0600713 if ((basek < 4 * 1024 * 1024) && (limitk > mmio_basek)) {
714 if (basek <= mmio_basek) {
715 unsigned pre_sizek;
716 pre_sizek = mmio_basek - basek;
717 if (pre_sizek > 0) {
718 ram_resource(dev, idx, basek,
719 pre_sizek);
720 idx += 0x10;
721 sizek -= pre_sizek;
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300722 if (!ramtop)
723 ramtop = mmio_basek * 1024;
Marc Jones8d595692012-03-15 12:55:26 -0600724 }
Marc Jones8d595692012-03-15 12:55:26 -0600725 basek = mmio_basek;
726 }
727 if ((basek + sizek) <= 4 * 1024 * 1024) {
728 sizek = 0;
729 } else {
730 basek = 4 * 1024 * 1024;
731 sizek -= (4 * 1024 * 1024 - mmio_basek);
732 }
733 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000734
Marc Jones8d595692012-03-15 12:55:26 -0600735 ram_resource(dev, (idx | 0), basek, sizek);
736 idx += 0x10;
Marc Jones8d595692012-03-15 12:55:26 -0600737 printk(BIOS_DEBUG,
738 "%d: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n", 0,
739 mmio_basek, basek, limitk);
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300740 if (!ramtop)
741 ramtop = limitk * 1024;
Marc Jones8d595692012-03-15 12:55:26 -0600742 }
743 printk(BIOS_DEBUG, " adsr - mmio_basek = %lx.\n", mmio_basek);
Frank Vibrans39fca802011-02-14 18:35:15 +0000744
Patrick Georgie1667822012-05-05 15:29:32 +0200745#if CONFIG_GFXUMA
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300746 set_top_of_ram(uma_memory_base);
Kyösti Mälkki63f8c082012-07-10 13:27:26 +0300747 uma_resource(dev, 7, uma_memory_base >> 10, uma_memory_size >> 10);
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300748#else
749 set_top_of_ram(ramtop);
Frank Vibrans39fca802011-02-14 18:35:15 +0000750#endif
751
Marc Jones8d595692012-03-15 12:55:26 -0600752 for (link = dev->link_list; link; link = link->next) {
753 if (link->children) {
754 assign_resources(link);
755 }
756 }
757 printk(BIOS_DEBUG, " adsr - leaving this lovely routine.\n");
Frank Vibrans39fca802011-02-14 18:35:15 +0000758}
759
zbaof7223732012-04-13 13:42:15 +0800760static void domain_enable_resources(device_t dev)
761{
Kerry Shefeed3292011-08-18 18:03:44 +0800762#if CONFIG_AMD_SB_CIMX
Kyösti Mälkkic551caa2014-06-20 12:31:23 +0300763 if (!acpi_is_wakeup_s3()) {
zbaof7223732012-04-13 13:42:15 +0800764 sb_After_Pci_Init();
765 sb_Mid_Post_Init();
766 } else {
767 sb_After_Pci_Restore_Init();
768 }
Kerry Shefeed3292011-08-18 18:03:44 +0800769#endif
770
Marc Jones8d595692012-03-15 12:55:26 -0600771 /* Must be called after PCI enumeration and resource allocation */
Mike Loptien58089e82013-01-29 15:45:09 -0700772 printk(BIOS_DEBUG, "\nFam14h - %s\n", __func__);
zbaof7223732012-04-13 13:42:15 +0800773
Kyösti Mälkki7b23ae02014-07-04 16:14:37 +0300774 if (!acpi_is_wakeup_s3())
775 AGESAWRAPPER(amdinitmid);
efdesign9805a89ab2011-06-20 17:38:49 -0700776
Marc Jones8d595692012-03-15 12:55:26 -0600777 printk(BIOS_DEBUG, " ader - leaving domain_enable_resources.\n");
Frank Vibrans39fca802011-02-14 18:35:15 +0000778}
779
Frank Vibrans39fca802011-02-14 18:35:15 +0000780/* Bus related code */
781
Edward O'Callaghan2837ab22014-11-06 08:57:40 +1100782static u32 cpu_bus_scan(struct device *dev, u32 max)
zbaof7223732012-04-13 13:42:15 +0800783{
Kyösti Mälkkic33f1e92012-08-07 17:12:11 +0300784 struct bus *cpu_bus = dev->link_list;
Scott Duplichan9ab3c6c2011-05-15 21:45:46 +0000785 device_t cpu;
zbaof7223732012-04-13 13:42:15 +0800786 int apic_id, cores_found;
Scott Duplichan9ab3c6c2011-05-15 21:45:46 +0000787
zbaof7223732012-04-13 13:42:15 +0800788 /* There is only one node for fam14, but there may be multiple cores. */
789 cpu = dev_find_slot(0, PCI_DEVFN(0x18, 0));
790 if (!cpu)
791 printk(BIOS_ERR, "ERROR: %02x:%02x.0 not found", 0, 0x18);
Scott Duplichan9ab3c6c2011-05-15 21:45:46 +0000792
zbaof7223732012-04-13 13:42:15 +0800793 cores_found = (pci_read_config32(dev_find_slot(0,PCI_DEVFN(0x18,0x3)), 0xe8) >> 12) & 3;
794 printk(BIOS_DEBUG, " AP siblings=%d\n", cores_found);
795
zbaof7223732012-04-13 13:42:15 +0800796 for (apic_id = 0; apic_id <= cores_found; apic_id++) {
Kyösti Mälkkic33f1e92012-08-07 17:12:11 +0300797 cpu = add_cpu_device(cpu_bus, apic_id, 1);
798 if (cpu)
799 amd_cpu_topology(cpu, 0, apic_id);
Marc Jones8d595692012-03-15 12:55:26 -0600800 }
zbaof7223732012-04-13 13:42:15 +0800801 return max;
802}
803
804static void cpu_bus_init(device_t dev)
805{
806 initialize_cpus(dev->link_list);
Frank Vibrans39fca802011-02-14 18:35:15 +0000807}
808
Frank Vibrans39fca802011-02-14 18:35:15 +0000809/* North Bridge Structures */
810
811static struct device_operations northbridge_operations = {
Marc Jones8a49ac72013-01-16 17:02:20 -0700812 .read_resources = nb_read_resources,
813 .set_resources = nb_set_resources,
Marc Jones8d595692012-03-15 12:55:26 -0600814 .enable_resources = pci_dev_enable_resources,
815 .init = northbridge_init,
816 .enable = 0,.ops_pci = 0,
Frank Vibrans39fca802011-02-14 18:35:15 +0000817};
818
Frank Vibrans39fca802011-02-14 18:35:15 +0000819static const struct pci_driver northbridge_driver __pci_driver = {
Marc Jones8d595692012-03-15 12:55:26 -0600820 .ops = &northbridge_operations,
821 .vendor = PCI_VENDOR_ID_AMD,
822 .device = 0x1510,
Frank Vibrans39fca802011-02-14 18:35:15 +0000823};
824
efdesign9805a89ab2011-06-20 17:38:49 -0700825struct chip_operations northbridge_amd_agesa_family14_ops = {
Marc Jones8d595692012-03-15 12:55:26 -0600826 CHIP_NAME("AMD Family 14h Northbridge")
827 .enable_dev = 0,
Frank Vibrans39fca802011-02-14 18:35:15 +0000828};
829
Frank Vibrans39fca802011-02-14 18:35:15 +0000830/* Root Complex Structures */
831
Frank Vibrans39fca802011-02-14 18:35:15 +0000832static struct device_operations pci_domain_ops = {
Marc Jones8d595692012-03-15 12:55:26 -0600833 .read_resources = domain_read_resources,
834 .set_resources = domain_set_resources,
835 .enable_resources = domain_enable_resources,
836 .init = NULL,
837 .scan_bus = pci_domain_scan_bus,
Frank Vibrans39fca802011-02-14 18:35:15 +0000838};
839
Frank Vibrans39fca802011-02-14 18:35:15 +0000840static struct device_operations cpu_bus_ops = {
Edward O'Callaghan2837ab22014-11-06 08:57:40 +1100841 .read_resources = DEVICE_NOOP,
842 .set_resources = DEVICE_NOOP,
Marc Jones8d595692012-03-15 12:55:26 -0600843 .enable_resources = NULL,
844 .init = cpu_bus_init,
zbaof7223732012-04-13 13:42:15 +0800845 .scan_bus = cpu_bus_scan,
Frank Vibrans39fca802011-02-14 18:35:15 +0000846};
847
Kyösti Mälkki87213b62012-08-27 20:00:33 +0300848static void root_complex_enable_dev(struct device *dev)
849{
850 static int done = 0;
851
852 /* Do not delay UMA setup, as a device on the PCI bus may evaluate
853 the global uma_memory variables already in its enable function. */
854 if (!done) {
855 setup_bsp_ramtop();
856 setup_uma_memory();
857 done = 1;
858 }
859
Marc Jones8d595692012-03-15 12:55:26 -0600860 /* Set the operations if it is a special bus type */
Stefan Reinauer4aff4452013-02-12 14:17:15 -0800861 if (dev->path.type == DEVICE_PATH_DOMAIN) {
Marc Jones8d595692012-03-15 12:55:26 -0600862 dev->ops = &pci_domain_ops;
Stefan Reinauer0aa37c42013-02-12 15:20:54 -0800863 } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
Marc Jones8d595692012-03-15 12:55:26 -0600864 dev->ops = &cpu_bus_ops;
865 }
Frank Vibrans39fca802011-02-14 18:35:15 +0000866}
867
efdesign9805a89ab2011-06-20 17:38:49 -0700868struct chip_operations northbridge_amd_agesa_family14_root_complex_ops = {
Marc Jones8d595692012-03-15 12:55:26 -0600869 CHIP_NAME("AMD Family 14h Root Complex")
870 .enable_dev = root_complex_enable_dev,
Frank Vibrans39fca802011-02-14 18:35:15 +0000871};