blob: 8d829251520d28df03cb2a34f43c1c76e8526933 [file] [log] [blame]
efdesign987c0c64e2011-06-20 19:56:06 -07001/*
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
efdesign987c0c64e2011-06-20 19:56:06 -070018 */
19
20#include <console/console.h>
Vladimir Serbinenko46a86f22014-10-08 22:38:54 +020021#include <arch/acpi.h>
22#include <arch/acpigen.h>
efdesign987c0c64e2011-06-20 19:56:06 -070023#include <arch/io.h>
24#include <stdint.h>
25#include <device/device.h>
26#include <device/pci.h>
27#include <device/pci_ids.h>
28#include <device/hypertransport.h>
29#include <stdlib.h>
30#include <string.h>
Ronald G. Minnich5079a0d2012-11-27 11:32:38 -080031#include <lib.h>
efdesign987c0c64e2011-06-20 19:56:06 -070032#include <cpu/cpu.h>
Stefan Reinauer30b46ce2012-03-16 10:26:39 -070033#include <cbmem.h>
efdesign987c0c64e2011-06-20 19:56:06 -070034
35#include <cpu/x86/lapic.h>
Kyösti Mälkkid4821fc2012-07-11 08:02:24 +030036#include <cpu/amd/mtrr.h>
efdesign987c0c64e2011-06-20 19:56:06 -070037
Corey Osgood5a7e1272013-07-28 05:36:45 -040038#include "sb_cimx.h"
Kyösti Mälkkif21c2ac2014-10-19 09:35:18 +030039#include <northbridge/amd/agesa/agesawrapper.h>
efdesign987c0c64e2011-06-20 19:56:06 -070040
41//#define FX_DEVS NODE_NUMS
42#define FX_DEVS 1
43
44static device_t __f0_dev[FX_DEVS];
45static device_t __f1_dev[FX_DEVS];
46static device_t __f2_dev[FX_DEVS];
47static device_t __f4_dev[FX_DEVS];
48static unsigned fx_devs=0;
49
Edward O'Callaghan541ac592014-11-21 00:37:02 +110050static device_t get_node_pci(u32 nodeid, u32 fn)
efdesign987c0c64e2011-06-20 19:56:06 -070051{
zbao49bb26a42012-08-03 15:44:42 +080052 if ((CONFIG_CDB + nodeid) < 32) {
53 return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB + nodeid, fn));
54 } else {
55 return dev_find_slot(CONFIG_CBB-1, PCI_DEVFN(CONFIG_CDB + nodeid - 32, fn));
56 }
efdesign987c0c64e2011-06-20 19:56:06 -070057}
58
efdesign987c0c64e2011-06-20 19:56:06 -070059static void get_fx_devs(void)
60{
61 int i;
62 for(i = 0; i < FX_DEVS; i++) {
63 __f0_dev[i] = get_node_pci(i, 0);
64 __f1_dev[i] = get_node_pci(i, 1);
65 __f2_dev[i] = get_node_pci(i, 2);
66 __f4_dev[i] = get_node_pci(i, 4);
67 if (__f0_dev[i] != NULL && __f1_dev[i] != NULL)
68 fx_devs = i+1;
69 }
70 if (__f1_dev[0] == NULL || __f0_dev[0] == NULL || fx_devs == 0) {
71 die("Cannot find 0:0x18.[0|1]\n");
72 }
73}
74
75
76static u32 f1_read_config32(unsigned reg)
77{
78 if (fx_devs == 0)
79 get_fx_devs();
80 return pci_read_config32(__f1_dev[0], reg);
81}
82
83
84static void f1_write_config32(unsigned reg, u32 value)
85{
86 int i;
87 if (fx_devs == 0)
88 get_fx_devs();
89 for(i = 0; i < fx_devs; i++) {
90 device_t dev;
91 dev = __f1_dev[i];
92 if (dev && dev->enabled) {
93 pci_write_config32(dev, reg, value);
94 }
95 }
96}
97
98
99static u32 amdfam12_nodeid(device_t dev)
100{
Mike Loptien7407f432013-01-31 10:17:02 -0700101 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700102 return (dev->path.pci.devfn >> 3) - CONFIG_CDB;
103}
104
105
106#include "amdfam12_conf.c"
107
108
109static void northbridge_init(device_t dev)
110{
111 printk(BIOS_DEBUG, "Northbridge init\n");
112}
113
114
115static void set_vga_enable_reg(u32 nodeid, u32 linkn)
116{
117 u32 val;
118
Mike Loptien7407f432013-01-31 10:17:02 -0700119 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700120 val = 1 | (nodeid<<4) | (linkn<<12);
121 /* it will routing (1)mmio 0xa0000:0xbffff (2) io 0x3b0:0x3bb,
122 0x3c0:0x3df */
123 f1_write_config32(0xf4, val);
124
Mike Loptien7407f432013-01-31 10:17:02 -0700125 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700126}
127
128
129static int reg_useable(unsigned reg, device_t goal_dev, unsigned goal_nodeid,
130 unsigned goal_link)
131{
132 struct resource *res;
133 unsigned nodeid, link = 0;
134 int result;
Mike Loptien7407f432013-01-31 10:17:02 -0700135 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700136 res = 0;
137 for(nodeid = 0; !res && (nodeid < fx_devs); nodeid++) {
138 device_t dev;
139 dev = __f0_dev[nodeid];
140 if (!dev)
141 continue;
142 for(link = 0; !res && (link < 8); link++) {
143 res = probe_resource(dev, IOINDEX(0x1000 + reg, link));
144 }
145 }
146 result = 2;
147 if (res) {
148 result = 0;
149 if ( (goal_link == (link - 1)) &&
150 (goal_nodeid == (nodeid - 1)) &&
151 (res->flags <= 1)) {
152 result = 1;
153 }
154 }
Mike Loptien7407f432013-01-31 10:17:02 -0700155 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700156 return result;
157}
158
159static struct resource *amdfam12_find_iopair(device_t dev, unsigned nodeid, unsigned link)
160{
161 struct resource *resource;
162 u32 result, reg;
163 resource = 0;
164 reg = 0;
165 result = reg_useable(0xc0, dev, nodeid, link);
166 if (result >= 1) {
167 /* I have been allocated this one */
168 reg = 0xc0;
169 }
170
171 //Ext conf space
172 if(!reg) {
173 //because of Extend conf space, we will never run out of reg, but we need one index to differ them. so same node and same link can have multi range
174 u32 index = get_io_addr_index(nodeid, link);
175 reg = 0x110+ (index<<24) + (4<<20); // index could be 0, 255
176 }
177
178 resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
179
180 return resource;
181}
182
183static struct resource *amdfam12_find_mempair(device_t dev, u32 nodeid, u32 link)
184{
185 struct resource *resource;
186 u32 free_reg, reg;
187 resource = 0;
188 free_reg = 0;
189 for(reg = 0x80; reg <= 0xb8; reg += 0x8) {
190 int result;
191 result = reg_useable(reg, dev, nodeid, link);
192 if (result == 1) {
193 /* I have been allocated this one */
194 break;
195 }
196 else if (result > 1) {
197 /* I have a free register pair */
198 free_reg = reg;
199 }
200 }
201 if (reg > 0xb8) {
202 reg = free_reg;
203 }
204
205 //Ext conf space
206 if(!reg) {
207 //because of Extend conf space, we will never run out of reg,
208 // but we need one index to differ them. so same node and
209 // same link can have multi range
210 u32 index = get_mmio_addr_index(nodeid, link);
211 reg = 0x110+ (index<<24) + (6<<20); // index could be 0, 63
212
213 }
214 resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
215 return resource;
216}
217
218
219static void amdfam12_link_read_bases(device_t dev, u32 nodeid, u32 link)
220{
221 struct resource *resource;
222
Mike Loptien7407f432013-01-31 10:17:02 -0700223 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700224 /* Initialize the io space constraints on the current bus */
225 resource = amdfam12_find_iopair(dev, nodeid, link);
226 if (resource) {
227 u32 align;
Patrick Georgie1667822012-05-05 15:29:32 +0200228#if CONFIG_EXT_CONF_SUPPORT
efdesign987c0c64e2011-06-20 19:56:06 -0700229 if((resource->index & 0x1fff) == 0x1110) { // ext
230 align = 8;
231 }
232 else
233#endif
234 align = log2(HT_IO_HOST_ALIGN);
235 resource->base = 0;
236 resource->size = 0;
237 resource->align = align;
238 resource->gran = align;
239 resource->limit = 0xffffUL;
240 resource->flags = IORESOURCE_IO | IORESOURCE_BRIDGE;
241 }
242
243 /* Initialize the prefetchable memory constraints on the current bus */
244 resource = amdfam12_find_mempair(dev, nodeid, link);
245 if (resource) {
246 resource->base = 0;
247 resource->size = 0;
248 resource->align = log2(HT_MEM_HOST_ALIGN);
249 resource->gran = log2(HT_MEM_HOST_ALIGN);
250 resource->limit = 0xffffffffffULL;
251 resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
252 resource->flags |= IORESOURCE_BRIDGE;
253
Patrick Georgie1667822012-05-05 15:29:32 +0200254#if CONFIG_EXT_CONF_SUPPORT
efdesign987c0c64e2011-06-20 19:56:06 -0700255 if((resource->index & 0x1fff) == 0x1110) { // ext
256 normalize_resource(resource);
257 }
258#endif
259
260 }
261
262 /* Initialize the memory constraints on the current bus */
263 resource = amdfam12_find_mempair(dev, nodeid, link);
264 if (resource) {
265 resource->base = 0;
266 resource->size = 0;
267 resource->align = log2(HT_MEM_HOST_ALIGN);
268 resource->gran = log2(HT_MEM_HOST_ALIGN);
269 resource->limit = 0xffffffffffULL;
270 resource->flags = IORESOURCE_MEM | IORESOURCE_BRIDGE;
Patrick Georgie1667822012-05-05 15:29:32 +0200271#if CONFIG_EXT_CONF_SUPPORT
efdesign987c0c64e2011-06-20 19:56:06 -0700272 if((resource->index & 0x1fff) == 0x1110) { // ext
273 normalize_resource(resource);
274 }
275#endif
276 }
Mike Loptien7407f432013-01-31 10:17:02 -0700277 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700278}
279
280static u32 my_find_pci_tolm(struct bus *bus, u32 tolm)
281{
282 struct resource *min;
283 min = 0;
284 search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min);
285 if (min && tolm > min->base) {
286 tolm = min->base;
287 }
288 return tolm;
289}
290
291#if CONFIG_HW_MEM_HOLE_SIZEK != 0
292
293struct hw_mem_hole_info {
294 unsigned hole_startk;
295 int node_id;
296};
297
298static struct hw_mem_hole_info get_hw_mem_hole_info(void)
299{
300 struct hw_mem_hole_info mem_hole;
efdesign987c0c64e2011-06-20 19:56:06 -0700301
302 mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK;
303 mem_hole.node_id = -1;
304
305 struct dram_base_mask_t d;
306 u32 hole;
307 d = get_dram_base_mask(0);
308 if(d.mask & 1) {
309 hole = pci_read_config32(__f1_dev[0], 0xf0);
310 if(hole & 1) { // we find the hole
311 mem_hole.hole_startk = (hole & (0xff<<24)) >> 10;
312 mem_hole.node_id = 0; // record the node No with hole
313 }
314 }
315
316#if 0
Kyösti Mälkki2f9b3af2014-06-26 05:30:54 +0300317 /* We need to double check if there is special set on base reg and limit reg
318 * are not continuous instead of hole, it will find out its hole_startk.
319 */
efdesign987c0c64e2011-06-20 19:56:06 -0700320 if(mem_hole.node_id==-1) {
321 resource_t limitk_pri = 0;
322 struct dram_base_mask_t d;
323 resource_t base_k, limit_k;
324 d = get_dram_base_mask(0);
325 if(d.base & 1) {
326 base_k = ((resource_t)(d.base & 0x1fffff00)) <<9;
327 if(base_k <= 4 *1024 * 1024) {
328 if(limitk_pri != base_k) { // we find the hole
329 mem_hole.hole_startk = (unsigned)limitk_pri; // must be below 4G
330 mem_hole.node_id = 0;
331 }
332 }
333
334 limit_k = ((resource_t)((d.mask + 0x00000100) & 0x1fffff00)) << 9;
335 limitk_pri = limit_k;
336 }
337 }
338#endif
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700339
efdesign987c0c64e2011-06-20 19:56:06 -0700340 return mem_hole;
341}
342#endif
343
efdesign987c0c64e2011-06-20 19:56:06 -0700344static void read_resources(device_t dev)
345{
346 u32 nodeid;
347 struct bus *link;
348
Mike Loptien7407f432013-01-31 10:17:02 -0700349 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700350
351 nodeid = amdfam12_nodeid(dev);
352 for(link = dev->link_list; link; link = link->next) {
353 if (link->children) {
354 amdfam12_link_read_bases(dev, nodeid, link->link_num);
355 }
356 }
Mike Loptien7407f432013-01-31 10:17:02 -0700357 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700358}
359
360
361static void set_resource(device_t dev, struct resource *resource,
362 u32 nodeid)
363{
364 resource_t rbase, rend;
365 unsigned reg, link_num;
366 char buf[50];
367
Mike Loptien7407f432013-01-31 10:17:02 -0700368 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700369
370 /* Make certain the resource has actually been set */
371 if (!(resource->flags & IORESOURCE_ASSIGNED)) {
372 return;
373 }
374
375 /* If I have already stored this resource don't worry about it */
376 if (resource->flags & IORESOURCE_STORED) {
377 return;
378 }
379
380 /* Only handle PCI memory and IO resources */
381 if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
382 return;
383
384 /* Ensure I am actually looking at a resource of function 1 */
385 if ((resource->index & 0xffff) < 0x1000) {
386 return;
387 }
388 /* Get the base address */
389 rbase = resource->base;
390
391 /* Get the limit (rounded up) */
392 rend = resource_end(resource);
393
394 /* Get the register and link */
395 reg = resource->index & 0xfff; // 4k
396 link_num = IOINDEX_LINK(resource->index);
397
398 if (resource->flags & IORESOURCE_IO) {
399 set_io_addr_reg(dev, nodeid, link_num, reg, rbase>>8, rend>>8);
400 }
401 else if (resource->flags & IORESOURCE_MEM) {
402 set_mmio_addr_reg(nodeid, link_num, reg, (resource->index >>24), rbase>>8, rend>>8, 1) ;// [39:8]
403 }
404 resource->flags |= IORESOURCE_STORED;
Vladimir Serbinenkoa37383d2013-11-26 02:41:26 +0100405 snprintf(buf, sizeof (buf), " <node %x link %x>",
efdesign987c0c64e2011-06-20 19:56:06 -0700406 nodeid, link_num);
407 report_resource_stored(dev, resource, buf);
Mike Loptien7407f432013-01-31 10:17:02 -0700408 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700409}
410
411
efdesign983f5ebd62011-09-14 13:47:17 -0600412#if CONFIG_CONSOLE_VGA_MULTI
efdesign987c0c64e2011-06-20 19:56:06 -0700413extern device_t vga_pri; // the primary vga device, defined in device.c
414#endif
415
416static void create_vga_resource(device_t dev, unsigned nodeid)
417{
418 struct bus *link;
419
Mike Loptien7407f432013-01-31 10:17:02 -0700420 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700421
422 /* find out which link the VGA card is connected,
423 * we only deal with the 'first' vga card */
424 for (link = dev->link_list; link; link = link->next) {
425 if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
efdesign983f5ebd62011-09-14 13:47:17 -0600426#if CONFIG_CONSOLE_VGA_MULTI
efdesign987c0c64e2011-06-20 19:56:06 -0700427 printk(BIOS_DEBUG, "VGA: vga_pri bus num = %d bus range [%d,%d]\n", vga_pri->bus->secondary,
428 link->secondary,link->subordinate);
429 /* We need to make sure the vga_pri is under the link */
430 if((vga_pri->bus->secondary >= link->secondary ) &&
431 (vga_pri->bus->secondary <= link->subordinate )
432 )
433#endif
434 break;
435 }
436 }
437
438 /* no VGA card installed */
439 if (link == NULL)
440 return;
441
442 printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, link->link_num);
443 set_vga_enable_reg(nodeid, link->link_num);
Mike Loptien7407f432013-01-31 10:17:02 -0700444 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700445}
446
447
448static void set_resources(device_t dev)
449{
450 unsigned nodeid;
451 struct bus *bus;
452 struct resource *res;
453
Mike Loptien7407f432013-01-31 10:17:02 -0700454 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700455
efdesign987c0c64e2011-06-20 19:56:06 -0700456 /* Find the nodeid */
457 nodeid = amdfam12_nodeid(dev);
458
459 create_vga_resource(dev, nodeid);
460
461 /* Set each resource we have found */
462 for(res = dev->resource_list; res; res = res->next) {
463 set_resource(dev, res, nodeid);
464 }
465
466 for(bus = dev->link_list; bus; bus = bus->next) {
467 if (bus->children) {
468 assign_resources(bus);
469 }
470 }
Mike Loptien7407f432013-01-31 10:17:02 -0700471 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700472}
473
Kyösti Mälkki6b5eb1c2012-07-19 19:26:43 +0300474static void setup_uma_memory(void)
Kyösti Mälkkid4821fc2012-07-11 08:02:24 +0300475{
476#if CONFIG_GFXUMA
Kyösti Mälkkidbc47392012-08-05 12:11:40 +0300477 uint32_t topmem = (uint32_t) bsp_topmem();
Kyösti Mälkkid4821fc2012-07-11 08:02:24 +0300478 uint32_t sys_mem;
479
Kyösti Mälkkid4821fc2012-07-11 08:02:24 +0300480 /* refer to UMA Size Consideration in Family12h BKDG. */
481 /* Please reference MemNGetUmaSizeLN () */
482 /*
483 * Total system memory UMASize
484 * >= 2G 512M
485 * >=1G 256M
486 * <1G 64M
487 */
Kyösti Mälkkidbc47392012-08-05 12:11:40 +0300488 sys_mem = topmem + 0x1000000; // Ignore 16MB allocated for C6 when finding UMA size
489 if ((bsp_topmem2()>>32) || (sys_mem >= 0x80000000)) {
Kyösti Mälkkid4821fc2012-07-11 08:02:24 +0300490 uma_memory_size = 0x20000000; /* >= 2G memory, 512M recommended UMA */
491 } else if (sys_mem >= 0x40000000) {
492 uma_memory_size = 0x10000000; /* >= 1G memory, 256M recommended UMA */
493 } else {
494 uma_memory_size = 0x4000000; /* <1G memory, 64M recommended UMA */
495 }
Kyösti Mälkkidbc47392012-08-05 12:11:40 +0300496 uma_memory_base = topmem - uma_memory_size; /* TOP_MEM1 */
Kyösti Mälkkid4821fc2012-07-11 08:02:24 +0300497 printk(BIOS_INFO, "%s: uma size 0x%08llx, memory start 0x%08llx\n",
498 __func__, uma_memory_size, uma_memory_base);
Kyösti Mälkkid4821fc2012-07-11 08:02:24 +0300499#endif
500}
efdesign987c0c64e2011-06-20 19:56:06 -0700501
502/* Domain/Root Complex related code */
503
504static void domain_read_resources(device_t dev)
505{
506 unsigned reg;
507
Mike Loptien7407f432013-01-31 10:17:02 -0700508 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700509
510 /* Find the already assigned resource pairs */
511 get_fx_devs();
512 for(reg = 0x80; reg <= 0xc0; reg+= 0x08) {
513 u32 base, limit;
514 base = f1_read_config32(reg);
515 limit = f1_read_config32(reg + 0x04);
516 /* Is this register allocated? */
517 if ((base & 3) != 0) {
518 unsigned nodeid, reg_link;
519 device_t reg_dev;
520 if(reg<0xc0) { // mmio
521 nodeid = (limit & 0xf) + (base&0x30);
522 } else { // io
523 nodeid = (limit & 0xf) + ((base>>4)&0x30);
524 }
525 reg_link = (limit >> 4) & 7;
526 reg_dev = __f0_dev[nodeid];
527 if (reg_dev) {
528 /* Reserve the resource */
529 struct resource *res;
530 res = new_resource(reg_dev, IOINDEX(0x1000 + reg, reg_link));
531 if (res) {
532 res->flags = 1;
533 }
534 }
535 }
536 }
537 /* FIXME: do we need to check extend conf space?
538 I don't believe that much preset value */
539
Patrick Georgie1667822012-05-05 15:29:32 +0200540#if !CONFIG_PCI_64BIT_PREF_MEM
efdesign987c0c64e2011-06-20 19:56:06 -0700541//- pci_domain_read_resources(dev);
542
543 struct resource *resource;
544 /* Initialize the system-wide I/O space constraints. */
545 resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
546 resource->base = 0x1000;
547 resource->limit = 0xffffUL;
548 resource->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
549 IORESOURCE_ASSIGNED;
550
551 /* Initialize the system-wide memory resources constraints. */
552 resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
553 resource->base = 0xc0000000ULL;
554 resource->limit = 0xdfffffffULL;
555 resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
556 IORESOURCE_ASSIGNED;
557#else
558 struct bus *link;
559 struct resource *resource;
560 for(link=dev->link_list; link; link = link->next) {
561 /* Initialize the system wide io space constraints */
562 resource = new_resource(dev, 0|(link->link_num<<2));
563 resource->base = 0x400;
564 resource->limit = 0xffffUL;
565 resource->flags = IORESOURCE_IO;
566
567 /* Initialize the system wide prefetchable memory resources constraints */
568 resource = new_resource(dev, 1|(link->link_num<<2));
569 resource->limit = 0xfcffffffffULL;
570 resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
571
572 /* Initialize the system wide memory resources constraints */
573 resource = new_resource(dev, 2|(link->link_num<<2));
574 resource->limit = 0xfcffffffffULL;
575 resource->flags = IORESOURCE_MEM;
576 }
577#endif
Mike Loptien7407f432013-01-31 10:17:02 -0700578 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700579}
580
581
582static void domain_set_resources(device_t dev)
583{
Mike Loptien7407f432013-01-31 10:17:02 -0700584 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
Martin Roth92f03c02013-02-10 14:53:35 -0700585 printk(BIOS_DEBUG, " amsr - incoming dev = %08x\n", (u32) dev);
efdesign987c0c64e2011-06-20 19:56:06 -0700586
Patrick Georgie1667822012-05-05 15:29:32 +0200587#if CONFIG_PCI_64BIT_PREF_MEM
efdesign987c0c64e2011-06-20 19:56:06 -0700588 struct resource *io, *mem1, *mem2;
589 struct resource *res;
590#endif
591 unsigned long mmio_basek;
592 u32 pci_tolm;
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300593 u64 ramtop = 0;
Martin Roth92f03c02013-02-10 14:53:35 -0700594 int idx;
efdesign987c0c64e2011-06-20 19:56:06 -0700595 struct bus *link;
596#if CONFIG_HW_MEM_HOLE_SIZEK != 0
597 struct hw_mem_hole_info mem_hole;
598 u32 reset_memhole = 1;
599#endif
600
Patrick Georgie1667822012-05-05 15:29:32 +0200601#if CONFIG_PCI_64BIT_PREF_MEM
efdesign987c0c64e2011-06-20 19:56:06 -0700602
603printk(BIOS_DEBUG, "adsr - CONFIG_PCI_64BIT_PREF_MEM is true.\n");
604 for(link = dev->link_list; link; link = link->next) {
605 /* Now reallocate the pci resources memory with the
606 * highest addresses I can manage.
607 */
608 mem1 = find_resource(dev, 1|(link->link_num<<2));
609 mem2 = find_resource(dev, 2|(link->link_num<<2));
610
611 printk(BIOS_DEBUG, "base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
612 mem1->base, mem1->limit, mem1->size, mem1->align);
613 printk(BIOS_DEBUG, "base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
614 mem2->base, mem2->limit, mem2->size, mem2->align);
615
616 /* See if both resources have roughly the same limits */
617 if (((mem1->limit <= 0xffffffff) && (mem2->limit <= 0xffffffff)) ||
618 ((mem1->limit > 0xffffffff) && (mem2->limit > 0xffffffff)))
619 {
620 /* If so place the one with the most stringent alignment first
621 */
622 if (mem2->align > mem1->align) {
623 struct resource *tmp;
624 tmp = mem1;
625 mem1 = mem2;
626 mem2 = tmp;
627 }
628 /* Now place the memory as high up as it will go */
629 mem2->base = resource_max(mem2);
630 mem1->limit = mem2->base - 1;
631 mem1->base = resource_max(mem1);
632 }
633 else {
634 /* Place the resources as high up as they will go */
635 mem2->base = resource_max(mem2);
636 mem1->base = resource_max(mem1);
637 }
638
639 printk(BIOS_DEBUG, "base1: 0x%08Lx limit1: 0x%08Lx size: 0x%08Lx align: %d\n",
640 mem1->base, mem1->limit, mem1->size, mem1->align);
641 printk(BIOS_DEBUG, "base2: 0x%08Lx limit2: 0x%08Lx size: 0x%08Lx align: %d\n",
642 mem2->base, mem2->limit, mem2->size, mem2->align);
643 }
644
645 for(res = &dev->resource_list; res; res = res->next)
646 {
647 res->flags |= IORESOURCE_ASSIGNED;
648 res->flags |= IORESOURCE_STORED;
649 report_resource_stored(dev, res, "");
650 }
651#endif
652
653 pci_tolm = 0xffffffffUL;
654 for(link = dev->link_list; link; link = link->next) {
655 pci_tolm = my_find_pci_tolm(link, pci_tolm);
656 }
657
658 // FIXME handle interleaved nodes. If you fix this here, please fix
659 // amdk8, too.
660 mmio_basek = pci_tolm >> 10;
661 /* Round mmio_basek to something the processor can support */
662 mmio_basek &= ~((1 << 6) -1);
663
664 // FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M
665 // MMIO hole. If you fix this here, please fix amdk8, too.
666 /* Round the mmio hole to 64M */
667 mmio_basek &= ~((64*1024) - 1);
668
669#if CONFIG_HW_MEM_HOLE_SIZEK != 0
670/* if the hw mem hole is already set in raminit stage, here we will compare
671 * mmio_basek and hole_basek. if mmio_basek is bigger that hole_basek and will
672 * use hole_basek as mmio_basek and we don't need to reset hole.
673 * otherwise We reset the hole to the mmio_basek
674 */
675
676 mem_hole = get_hw_mem_hole_info();
677
678 // Use hole_basek as mmio_basek, and we don't need to reset hole anymore
679 if ((mem_hole.node_id != -1) && (mmio_basek > mem_hole.hole_startk)) {
680 mmio_basek = mem_hole.hole_startk;
681 reset_memhole = 0;
682 }
683#endif
684
685 idx = 0x10;
686
687 struct dram_base_mask_t d;
688 resource_t basek, limitk, sizek; // 4 1T
689
690 d = get_dram_base_mask(0);
691
692 if (d.mask & 1) {
693 basek = ((resource_t)(d.base)) << 8;
694 limitk = (resource_t)((d.mask << 8) | 0xFFFFFF);
695printk(BIOS_DEBUG, "adsr: (before) basek = %llx, limitk = %llx.\n",basek,limitk);
696
697 /* Convert these values to multiples of 1K for ease of math. */
698 basek >>= 10;
699 limitk >>= 10;
700 sizek = limitk - basek + 1;
701
702printk(BIOS_DEBUG, "adsr: (after) basek = %llx, limitk = %llx, sizek = %llx.\n",basek,limitk,sizek);
703
704 /* see if we need a hole from 0xa0000 to 0xbffff */
705 if ((basek < 640) && (sizek > 768)) {
706printk(BIOS_DEBUG, "adsr - 0xa0000 to 0xbffff resource.\n");
707 ram_resource(dev, (idx | 0), basek, 640 - basek);
708 idx += 0x10;
709 basek = 768;
710 sizek = limitk - 768;
711 }
712
Martin Roth92f03c02013-02-10 14:53:35 -0700713 printk(BIOS_DEBUG,
714 "adsr: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",
715 mmio_basek, basek, limitk);
efdesign987c0c64e2011-06-20 19:56:06 -0700716
Kyösti Mälkki26c65432014-06-26 05:30:54 +0300717 /* split the region to accommodate pci memory space */
efdesign987c0c64e2011-06-20 19:56:06 -0700718 if ( (basek < 4*1024*1024 ) && (limitk > mmio_basek) ) {
719 if (basek <= mmio_basek) {
720 unsigned pre_sizek;
721 pre_sizek = mmio_basek - basek;
722 if(pre_sizek>0) {
723 ram_resource(dev, idx, basek, pre_sizek);
724 idx += 0x10;
725 sizek -= pre_sizek;
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300726 if (!ramtop)
727 ramtop = mmio_basek * 1024;
efdesign987c0c64e2011-06-20 19:56:06 -0700728 }
efdesign987c0c64e2011-06-20 19:56:06 -0700729 basek = mmio_basek;
730 }
731 if ((basek + sizek) <= 4*1024*1024) {
732 sizek = 0;
733 }
734 else {
735 basek = 4*1024*1024;
736 sizek -= (4*1024*1024 - mmio_basek);
737 }
738 }
739
740 ram_resource(dev, (idx | 0), basek, sizek);
741 idx += 0x10;
efdesign987c0c64e2011-06-20 19:56:06 -0700742 printk(BIOS_DEBUG, "%d: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",
743 0, mmio_basek, basek, limitk);
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300744 if (!ramtop)
745 ramtop = limitk * 1024;
efdesign987c0c64e2011-06-20 19:56:06 -0700746 }
Martin Roth92f03c02013-02-10 14:53:35 -0700747 printk(BIOS_DEBUG, " adsr - mmio_basek = %lx.\n", mmio_basek);
efdesign987c0c64e2011-06-20 19:56:06 -0700748
Patrick Georgie1667822012-05-05 15:29:32 +0200749#if CONFIG_GFXUMA
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300750 set_top_of_ram(uma_memory_base);
Kyösti Mälkki63f8c082012-07-10 13:27:26 +0300751 uma_resource(dev, 7, uma_memory_base >> 10, uma_memory_size >> 10);
Kyösti Mälkki2b790f62013-09-03 05:25:57 +0300752#else
753 set_top_of_ram(ramtop);
efdesign987c0c64e2011-06-20 19:56:06 -0700754#endif
755
756 for(link = dev->link_list; link; link = link->next) {
757 if (link->children) {
758 assign_resources(link);
759 }
760 }
761printk(BIOS_DEBUG, " adsr - leaving this lovely routine.\n");
Mike Loptien7407f432013-01-31 10:17:02 -0700762 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700763}
764
765
766static void domain_enable_resources(device_t dev)
767{
Kyösti Mälkki232ae172014-07-07 18:16:55 +0300768 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
769
770 /* Must be called after PCI enumeration and resource allocation */
771#if CONFIG_AMD_SB_CIMX
772 sb_After_Pci_Init();
773 sb_Mid_Post_Init();
774#endif
775
Kyösti Mälkkib139b5e2014-10-20 07:41:20 +0300776 /* Enable MMIO on AMD CPU Address Map Controller */
777 agesawrapper_amdinitcpuio();
778
Kyösti Mälkki1aa35c62014-10-21 14:19:04 +0300779 agesawrapper_amdinitmid();
Kyösti Mälkki232ae172014-07-07 18:16:55 +0300780 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700781}
782
783
784/* Bus related code */
785
786
787static void cpu_bus_read_resources(device_t dev)
788{
Mike Loptien7407f432013-01-31 10:17:02 -0700789 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700790
791#if CONFIG_MMCONF_SUPPORT
792 struct resource *resource = new_resource(dev, 0xc0010058);
793 resource->base = CONFIG_MMCONF_BASE_ADDRESS;
794 resource->size = CONFIG_MMCONF_BUS_NUMBER * 4096*256;
795 resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
796 IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
797#endif
Mike Loptien7407f432013-01-31 10:17:02 -0700798 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700799}
800
801static void cpu_bus_set_resources(device_t dev)
802{
803 struct resource *resource = find_resource(dev, 0xc0010058);
804
Mike Loptien7407f432013-01-31 10:17:02 -0700805 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700806 if (resource) {
807 report_resource_stored(dev, resource, " <mmconfig>");
808 }
809 pci_dev_set_resources(dev);
Mike Loptien7407f432013-01-31 10:17:02 -0700810 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700811}
Stefan Reinauer5ff7c132011-10-31 12:56:45 -0700812
efdesign987c0c64e2011-06-20 19:56:06 -0700813static void cpu_bus_init(device_t dev)
814{
Mike Loptien7407f432013-01-31 10:17:02 -0700815 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700816 initialize_cpus(dev->link_list);
Mike Loptien7407f432013-01-31 10:17:02 -0700817 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700818}
819
820
821/* North Bridge Structures */
822
Vladimir Serbinenko46a86f22014-10-08 22:38:54 +0200823
824unsigned long acpi_fill_hest(acpi_hest_t *hest)
825{
826 void *addr, *current;
827
828 /* Skip the HEST header. */
829 current = (void *)(hest + 1);
830
831 addr = agesawrapper_getlateinitptr(PICK_WHEA_MCE);
832 if (addr != NULL)
833 current += acpi_create_hest_error_source(hest, current, 0, (void *)((u32)addr + 2), *(UINT16 *)addr - 2);
834
835 addr = agesawrapper_getlateinitptr(PICK_WHEA_CMC);
836 if (addr != NULL)
837 current += acpi_create_hest_error_source(hest, current, 1, (void *)((u32)addr + 2), *(UINT16 *)addr - 2);
838
839 return (unsigned long)current;
840}
841
842/* Implemented with AGESA-specific code. Dummy to keep linker happy. */
843unsigned long acpi_fill_slit(unsigned long current)
844{
845 return current;
846}
847
848/* Implemented with AGESA-specific code. Dummy to keep linker happy. */
849unsigned long acpi_fill_srat(unsigned long current)
850{
851 return current;
852}
853
854static void northbridge_fill_ssdt_generator(void)
855{
856 msr_t msr;
857 char pscope[] = "\\_SB.PCI0";
858
859 acpigen_write_scope(pscope);
860 msr = rdmsr(TOP_MEM);
861 acpigen_write_name_dword("TOM1", msr.lo);
862 msr = rdmsr(TOP_MEM2);
863 /*
864 * Since XP only implements parts of ACPI 2.0, we can't use a qword
865 * here.
866 * See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt
867 * slide 22ff.
868 * Shift value right by 20 bit to make it fit into 32bit,
869 * giving us 1MB granularity and a limit of almost 4Exabyte of memory.
870 */
871 acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20);
872 acpigen_pop_len();
873}
874
875static unsigned long agesa_write_acpi_tables(unsigned long current,
876 acpi_rsdp_t *rsdp)
877{
878 acpi_srat_t *srat;
879 acpi_slit_t *slit;
880 acpi_header_t *ssdt;
881 acpi_hest_t *hest;
882
883 /* HEST */
884 current = ALIGN(current, 8);
885 hest = (acpi_hest_t *)current;
886 acpi_write_hest((void *)current);
887 acpi_add_table(rsdp, (void *)current);
888 current += ((acpi_header_t *)current)->length;
889
890 /* SRAT */
891 current = ALIGN(current, 8);
892 printk(BIOS_DEBUG, "ACPI: * SRAT at %lx\n", current);
893 srat = (acpi_srat_t *) agesawrapper_getlateinitptr (PICK_SRAT);
894 if (srat != NULL) {
895 memcpy((void *)current, srat, srat->header.length);
896 srat = (acpi_srat_t *) current;
897 //acpi_create_srat(srat);
898 current += srat->header.length;
899 acpi_add_table(rsdp, srat);
900 }
901
902 /* SLIT */
903 current = ALIGN(current, 8);
904 printk(BIOS_DEBUG, "ACPI: * SLIT at %lx\n", current);
905 slit = (acpi_slit_t *) agesawrapper_getlateinitptr (PICK_SLIT);
906 if (slit != NULL) {
907 memcpy((void *)current, slit, slit->header.length);
908 slit = (acpi_slit_t *) current;
909 //acpi_create_slit(slit);
910 current += slit->header.length;
911 acpi_add_table(rsdp, slit);
912 }
913
914 /* SSDT */
915 current = ALIGN(current, 16);
916 printk(BIOS_DEBUG, "ACPI: * SSDT at %lx\n", current);
917 ssdt = (acpi_header_t *)agesawrapper_getlateinitptr (PICK_PSTATE);
918 if (ssdt != NULL) {
919 memcpy((void *)current, ssdt, ssdt->length);
920 ssdt = (acpi_header_t *) current;
921 current += ssdt->length;
922 acpi_add_table(rsdp,ssdt);
923 }
924
925 printk(BIOS_DEBUG, "ACPI: * SSDT for PState at %lx\n", current);
926
927 return current;
928}
929
930
efdesign987c0c64e2011-06-20 19:56:06 -0700931static struct device_operations northbridge_operations = {
932 .read_resources = read_resources,
933 .set_resources = set_resources,
Vladimir Serbinenko46a86f22014-10-08 22:38:54 +0200934 .acpi_fill_ssdt_generator = northbridge_fill_ssdt_generator,
935 .write_acpi_tables = agesa_write_acpi_tables,
efdesign987c0c64e2011-06-20 19:56:06 -0700936 .enable_resources = pci_dev_enable_resources,
937 .init = northbridge_init,
938 .enable = 0,
939 .ops_pci = 0,
940};
941
942
943static const struct pci_driver northbridge_driver __pci_driver = {
944 .ops = &northbridge_operations,
945 .vendor = PCI_VENDOR_ID_AMD,
946 .device = 0x1705,
947};
948
949
950struct chip_operations northbridge_amd_agesa_family12_ops = {
951 CHIP_NAME("AMD Family 12h Northbridge")
952 .enable_dev = 0,
953};
954
955
956/* Root Complex Structures */
957
958
959static struct device_operations pci_domain_ops = {
960 .read_resources = domain_read_resources,
961 .set_resources = domain_set_resources,
962 .enable_resources = domain_enable_resources,
963 .init = NULL,
964 .scan_bus = pci_domain_scan_bus,
965};
966
967
968static struct device_operations cpu_bus_ops = {
969 .read_resources = cpu_bus_read_resources,
970 .set_resources = cpu_bus_set_resources,
971 .enable_resources = NULL,
972 .init = cpu_bus_init,
973 .scan_bus = 0,
974};
975
976
977static void root_complex_enable_dev(struct device *dev)
978{
Mike Loptien7407f432013-01-31 10:17:02 -0700979 printk(BIOS_DEBUG, "\nFam12h - northbridge.c - %s - Start.\n",__func__);
Kyösti Mälkki87213b62012-08-27 20:00:33 +0300980 static int done = 0;
981
982 /* Do not delay UMA setup, as a device on the PCI bus may evaluate
983 the global uma_memory variables already in its enable function. */
984 if (!done) {
985 setup_bsp_ramtop();
986 setup_uma_memory();
987 done = 1;
988 }
989
efdesign987c0c64e2011-06-20 19:56:06 -0700990 /* Set the operations if it is a special bus type */
Stefan Reinauer4aff4452013-02-12 14:17:15 -0800991 if (dev->path.type == DEVICE_PATH_DOMAIN) {
efdesign987c0c64e2011-06-20 19:56:06 -0700992 dev->ops = &pci_domain_ops;
993 }
Stefan Reinauer0aa37c42013-02-12 15:20:54 -0800994 else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
efdesign987c0c64e2011-06-20 19:56:06 -0700995 dev->ops = &cpu_bus_ops;
996 }
Mike Loptien7407f432013-01-31 10:17:02 -0700997 printk(BIOS_DEBUG, "Fam12h - northbridge.c - %s - End.\n",__func__);
efdesign987c0c64e2011-06-20 19:56:06 -0700998}
999
1000
1001struct chip_operations northbridge_amd_agesa_family12_root_complex_ops = {
1002 CHIP_NAME("AMD Family 12h Root Complex")
1003 .enable_dev = root_complex_enable_dev,
1004};