aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/amd/amdfam10/northbridge.c
diff options
context:
space:
mode:
authorArthur Heymans <arthur@aheymans.xyz>2019-11-19 15:46:49 +0100
committerKyösti Mälkki <kyosti.malkki@gmail.com>2019-11-20 19:08:30 +0000
commitffcac3eb502bbe0acbb30d6fe804f00e07461a7a (patch)
treed5deda572bb252a683a5ece24a5c4916ee198836 /src/northbridge/amd/amdfam10/northbridge.c
parent1ca978ee6529251ed80b47da679be7adc75fa46a (diff)
nb/amd/fam10: Drop support
Relocatable ramstage, postcar stage and C_ENVIRONMENT_BOOTBLOCK are now mandatory features, which this platform lacks. Change-Id: If36ef0749dbb661f731fb04829bd7e2202ebb422 Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/c/coreboot/+/36962 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: HAOUAS Elyes <ehaouas@noos.fr> Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Diffstat (limited to 'src/northbridge/amd/amdfam10/northbridge.c')
-rw-r--r--src/northbridge/amd/amdfam10/northbridge.c1928
1 files changed, 0 insertions, 1928 deletions
diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c
deleted file mode 100644
index df1d947cdb..0000000000
--- a/src/northbridge/amd/amdfam10/northbridge.c
+++ /dev/null
@@ -1,1928 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
- * Copyright (C) 2015 - 2017 Timothy Pearson <tpearson@raptorengineering.com>, Raptor Engineering
- * Copyright (C) 2007 Advanced Micro Devices, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <console/console.h>
-#include <device/pci_ops.h>
-#include <stdint.h>
-#include <device/device.h>
-#include <device/pci.h>
-#include <device/pci_ids.h>
-#include <device/hypertransport.h>
-#include <stdlib.h>
-#include <string.h>
-#include <lib.h>
-#include <smbios.h>
-#include <cpu/cpu.h>
-#include <delay.h>
-#include <cpu/x86/lapic.h>
-#include <cpu/x86/cache.h>
-#include <cpu/amd/mtrr.h>
-#include <cpu/amd/amdfam10_sysconf.h>
-#include <cpu/amd/msr.h>
-#include <cpu/amd/family_10h-family_15h/ram_calc.h>
-#include <types.h>
-
-#if CONFIG(LOGICAL_CPUS)
-#include <cpu/amd/multicore.h>
-#include <pc80/mc146818rtc.h>
-#endif
-
-#include "northbridge.h"
-#include "amdfam10.h"
-#include "ht_config.h"
-#include "chip.h"
-
-#if CONFIG_HW_MEM_HOLE_SIZEK != 0
-#include <cpu/amd/model_10xxx_rev.h>
-#endif
-
-#if CONFIG(DIMM_DDR3)
-#include "../amdmct/mct_ddr3/s3utils.h"
-#endif
-
-struct amdfam10_sysconf_t sysconf;
-u8 pirq_router_bus;
-
-#define FX_DEVS NODE_NUMS
-static struct device *__f0_dev[FX_DEVS];
-struct device *__f1_dev[FX_DEVS];
-static struct device *__f2_dev[FX_DEVS];
-static struct device *__f4_dev[FX_DEVS];
-static unsigned int fx_devs = 0;
-
-struct device *get_node_pci(u32 nodeid, u32 fn)
-{
-#if NODE_NUMS + CONFIG_CDB >= 32
- if ((CONFIG_CDB + nodeid) < 32) {
- return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB + nodeid, fn));
- } else {
- return dev_find_slot(CONFIG_CBB-1, PCI_DEVFN(CONFIG_CDB + nodeid - 32, fn));
- }
-
-#else
- return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB + nodeid, fn));
-#endif
-}
-
-static void get_fx_devs(void)
-{
- int i;
- for (i = 0; i < FX_DEVS; i++) {
- __f0_dev[i] = get_node_pci(i, 0);
- __f1_dev[i] = get_node_pci(i, 1);
- __f2_dev[i] = get_node_pci(i, 2);
- __f4_dev[i] = get_node_pci(i, 4);
- if (__f0_dev[i] != NULL && __f1_dev[i] != NULL)
- fx_devs = i+1;
- }
- if (__f1_dev[0] == NULL || __f0_dev[0] == NULL || fx_devs == 0) {
- die("Cannot find 0:0x18.[0|1]\n");
- }
-}
-
-static u32 f1_read_config32(unsigned int reg)
-{
- if (fx_devs == 0)
- get_fx_devs();
- return pci_read_config32(__f1_dev[0], reg);
-}
-
-static void f1_write_config32(unsigned int reg, u32 value)
-{
- int i;
- if (fx_devs == 0)
- get_fx_devs();
- for (i = 0; i < fx_devs; i++) {
- struct device *dev;
- dev = __f1_dev[i];
- if (dev && dev->enabled) {
- pci_write_config32(dev, reg, value);
- }
- }
-}
-
-u32 amdfam10_nodeid(struct device *dev)
-{
-#if NODE_NUMS == 64
- unsigned int busn;
- busn = dev->bus->secondary;
- if (busn != CONFIG_CBB) {
- return (dev->path.pci.devfn >> 3) - CONFIG_CDB + 32;
- } else {
- return (dev->path.pci.devfn >> 3) - CONFIG_CDB;
- }
-
-#else
- return (dev->path.pci.devfn >> 3) - CONFIG_CDB;
-#endif
-}
-
-static void set_vga_enable_reg(u32 nodeid, u32 linkn)
-{
- u32 val;
-
- val = 1 | (nodeid<<4) | (linkn<<12);
- /* it will routing (1)mmio 0xa0000:0xbffff (2) io 0x3b0:0x3bb,
- 0x3c0:0x3df */
- f1_write_config32(0xf4, val);
-
-}
-
-typedef enum {
- HT_ROUTE_CLOSE,
- HT_ROUTE_SCAN,
- HT_ROUTE_FINAL,
-} scan_state;
-
-static void ht_route_link(struct bus *link, scan_state mode)
-{
- struct bus *parent = link->dev->bus;
- u32 busses;
-
- if (mode == HT_ROUTE_SCAN) {
- if (parent->subordinate == 0)
- link->secondary = 0;
- else
- link->secondary = parent->subordinate + 1;
-
- link->subordinate = link->secondary;
- }
-
- /* Configure the bus numbers for this bridge: the configuration
- * transactions will not be propagated by the bridge if it is
- * not correctly configured
- */
- busses = pci_read_config32(link->dev, link->cap + 0x14);
- busses &= ~(0xff << 8);
- busses |= parent->secondary & 0xff;
- if (mode == HT_ROUTE_CLOSE)
- busses |= 0xff << 8;
- else if (mode == HT_ROUTE_SCAN)
- busses |= ((u32) link->secondary & 0xff) << 8;
- else if (mode == HT_ROUTE_FINAL)
- busses |= ((u32) link->secondary & 0xff) << 8;
- pci_write_config32(link->dev, link->cap + 0x14, busses);
-
- if (mode == HT_ROUTE_FINAL) {
- if (CONFIG(HT_CHAIN_DISTRIBUTE))
- parent->subordinate = ALIGN_UP(link->subordinate, 8) - 1;
- else
- parent->subordinate = link->subordinate;
- }
-}
-
-static void amd_g34_fixup(struct bus *link, struct device *dev)
-{
- uint32_t nodeid = amdfam10_nodeid(dev);
- uint8_t rev_gte_d = 0;
- uint8_t dual_node = 0;
- uint32_t f3xe8;
-
- if (cpuid_eax(0x80000001) >= 0x8)
- /* Revision D or later */
- rev_gte_d = 1;
-
- if (rev_gte_d || is_fam15h()) {
- f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
-
- /* Check for dual node capability */
- if (f3xe8 & 0x20000000)
- dual_node = 1;
-
- if (dual_node) {
- /* Each G34 processor contains a defective HT link.
- * See the BKDG Rev 3.62 section 2.7.1.5 for details.
- */
- f3xe8 = pci_read_config32(get_node_pci(nodeid, 3), 0xe8);
- uint8_t internal_node_number = ((f3xe8 & 0xc0000000) >> 30);
- if (internal_node_number == 0) {
- /* Node 0 */
- if (link->link_num == 6) /* Link 2 Sublink 1 */
- printk(BIOS_DEBUG, "amdfam10_scan_chain(): node %d (internal node ID %d): skipping defective HT link\n", nodeid, internal_node_number);
- } else {
- /* Node 1 */
- if (link->link_num == 5) /* Link 1 Sublink 1 */
- printk(BIOS_DEBUG, "amdfam10_scan_chain(): node %d (internal node ID %d): skipping defective HT link\n", nodeid, internal_node_number);
- }
- }
- }
-}
-
-static void amdfam10_scan_chain(struct bus *link)
-{
- unsigned int next_unitid;
-
- /* See if there is an available configuration space mapping
- * register in function 1.
- */
- if (get_ht_c_index(link) >= 4)
- return;
-
- /* Set up the primary, secondary and subordinate bus numbers.
- * We have no idea how many busses are behind this bridge yet,
- * so we set the subordinate bus number to 0xff for the moment.
- */
-
- ht_route_link(link, HT_ROUTE_SCAN);
-
- /* set the config map space */
- set_config_map_reg(link);
-
- /* Now we can scan all of the subordinate busses i.e. the
- * chain on the hypertranport link
- */
-
- next_unitid = hypertransport_scan_chain(link);
-
- /* Now that nothing is overlapping it is safe to scan the children. */
- pci_scan_bus(link, 0x00, ((next_unitid - 1) << 3) | 7);
-
- ht_route_link(link, HT_ROUTE_FINAL);
-
- /* We know the number of busses behind this bridge. Set the
- * subordinate bus number to it's real value
- */
- if (0) {
- /* Clear the extend reg. */
- clear_config_map_reg(link);
- }
-
- set_config_map_reg(link);
-
- store_ht_c_conf_bus(link);
-}
-
-/* Do sb ht chain at first, in case s2885 put sb chain
- * (8131/8111) on link2, but put 8151 on link0.
- */
-static void relocate_sb_ht_chain(void)
-{
- struct device *dev;
- struct bus *link, *prev = NULL;
- u8 sblink;
-
- dev = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 0));
- sblink = (pci_read_config32(dev, 0x64)>>8) & 7;
- link = dev->link_list;
-
- while (link) {
- if (link->link_num == sblink) {
- if (!prev)
- return;
- prev->next = link->next;
- link->next = dev->link_list;
- dev->link_list = link;
- return;
- }
- prev = link;
- link = link->next;
- }
-}
-
-static void trim_ht_chain(struct device *dev)
-{
- struct bus *link;
-
- /* Check for connected link. */
- for (link = dev->link_list; link; link = link->next) {
- link->cap = 0x80 + (link->link_num * 0x20);
- link->ht_link_up = ht_is_non_coherent_link(link);
- }
-}
-
-static void amdfam10_scan_chains(struct device *dev)
-{
- struct bus *link;
-
-#if CONFIG(CPU_AMD_SOCKET_G34_NON_AGESA)
- if (is_fam15h()) {
- uint8_t current_link_number = 0;
-
- for (link = dev->link_list; link; link = link->next) {
- /* The following links have changed position in Fam15h G34 processors:
- * Fam10 Fam15
- * Node 0
- * L3 --> L1
- * L0 --> L3
- * L1 --> L2
- * L2 --> L0
- * Node 1
- * L0 --> L0
- * L1 --> L3
- * L2 --> L1
- * L3 --> L2
- */
- if (link->link_num == 0)
- link->link_num = 3;
- else if (link->link_num == 1)
- link->link_num = 2;
- else if (link->link_num == 2)
- link->link_num = 0;
- else if (link->link_num == 3)
- link->link_num = 1;
- else if (link->link_num == 5)
- link->link_num = 7;
- else if (link->link_num == 6)
- link->link_num = 5;
- else if (link->link_num == 7)
- link->link_num = 6;
-
- current_link_number++;
- if (current_link_number > 3)
- current_link_number = 0;
- }
- }
-#endif
-
- /* Do sb ht chain at first, in case s2885 put sb chain (8131/8111) on link2, but put 8151 on link0 */
- trim_ht_chain(dev);
-
- for (link = dev->link_list; link; link = link->next) {
- if (link->ht_link_up) {
- if (CONFIG(CPU_AMD_MODEL_10XXX))
- amd_g34_fixup(link, dev);
- amdfam10_scan_chain(link);
- }
- }
-}
-
-
-static int reg_useable(unsigned int reg, struct device *goal_dev, unsigned int goal_nodeid,
- unsigned int goal_link)
-{
- struct resource *res;
- unsigned int nodeid, link = 0;
- int result;
- res = 0;
- for (nodeid = 0; !res && (nodeid < fx_devs); nodeid++) {
- struct device *dev;
- dev = __f0_dev[nodeid];
- if (!dev)
- continue;
- for (link = 0; !res && (link < 8); link++) {
- res = probe_resource(dev, IOINDEX(0x1000 + reg, link));
- }
- }
- result = 2;
- if (res) {
- result = 0;
- if ( (goal_link == (link - 1)) &&
- (goal_nodeid == (nodeid - 1)) &&
- (res->flags <= 1)) {
- result = 1;
- }
- }
- return result;
-}
-
-static struct resource *amdfam10_find_iopair(struct device *dev, unsigned int nodeid, unsigned int link)
-{
- struct resource *resource;
- u32 free_reg, reg;
- resource = 0;
- free_reg = 0;
- for (reg = 0xc0; reg <= 0xd8; reg += 0x8) {
- int result;
- result = reg_useable(reg, dev, nodeid, link);
- if (result == 1) {
- /* I have been allocated this one */
- break;
- } else if (result > 1) {
- /* I have a free register pair */
- free_reg = reg;
- }
- }
- if (reg > 0xd8) {
- reg = free_reg; // if no free, the free_reg still be 0
- }
-
- //Ext conf space
- if (!reg) {
- //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
- u32 index = get_io_addr_index(nodeid, link);
- reg = 0x110+ (index<<24) + (4<<20); // index could be 0, 255
- }
-
- resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
-
- return resource;
-}
-
-static struct resource *amdfam10_find_mempair(struct device *dev, u32 nodeid, u32 link)
-{
- struct resource *resource;
- u32 free_reg, reg;
- resource = 0;
- free_reg = 0;
- for (reg = 0x80; reg <= 0xb8; reg += 0x8) {
- int result;
- result = reg_useable(reg, dev, nodeid, link);
- if (result == 1) {
- /* I have been allocated this one */
- break;
- } else if (result > 1) {
- /* I have a free register pair */
- free_reg = reg;
- }
- }
- if (reg > 0xb8) {
- reg = free_reg;
- }
-
- //Ext conf space
- if (!reg) {
- //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
- u32 index = get_mmio_addr_index(nodeid, link);
- reg = 0x110+ (index<<24) + (6<<20); // index could be 0, 63
-
- }
- resource = new_resource(dev, IOINDEX(0x1000 + reg, link));
- return resource;
-}
-
-
-static void amdfam10_link_read_bases(struct device *dev, u32 nodeid, u32 link)
-{
- struct resource *resource;
-
- /* Initialize the io space constraints on the current bus */
- resource = amdfam10_find_iopair(dev, nodeid, link);
- if (resource) {
- u32 align;
- align = log2(HT_IO_HOST_ALIGN);
- resource->base = 0;
- resource->size = 0;
- resource->align = align;
- resource->gran = align;
- resource->limit = 0xffffUL;
- resource->flags = IORESOURCE_IO | IORESOURCE_BRIDGE;
- }
-
- /* Initialize the prefetchable memory constraints on the current bus */
- resource = amdfam10_find_mempair(dev, nodeid, link);
- if (resource) {
- resource->base = 0;
- resource->size = 0;
- resource->align = log2(HT_MEM_HOST_ALIGN);
- resource->gran = log2(HT_MEM_HOST_ALIGN);
- resource->limit = 0xffffffffffULL;
- resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
- resource->flags |= IORESOURCE_BRIDGE;
- }
-
- /* Initialize the memory constraints on the current bus */
- resource = amdfam10_find_mempair(dev, nodeid, link);
- if (resource) {
- resource->base = 0;
- resource->size = 0;
- resource->align = log2(HT_MEM_HOST_ALIGN);
- resource->gran = log2(HT_MEM_HOST_ALIGN);
- resource->limit = 0xffffffffffULL;
- resource->flags = IORESOURCE_MEM | IORESOURCE_BRIDGE;
- }
-}
-
-static void amdfam10_read_resources(struct device *dev)
-{
- u32 nodeid;
- struct bus *link;
- nodeid = amdfam10_nodeid(dev);
- for (link = dev->link_list; link; link = link->next) {
- if (link->children) {
- amdfam10_link_read_bases(dev, nodeid, link->link_num);
- }
- }
-}
-
-static void amdfam10_set_resource(struct device *dev, struct resource *resource,
- u32 nodeid)
-{
- resource_t rbase, rend;
- unsigned int reg, link_num;
- char buf[50];
-
- /* Make certain the resource has actually been set */
- if (!(resource->flags & IORESOURCE_ASSIGNED)) {
- return;
- }
-
- /* If I have already stored this resource don't worry about it */
- if (resource->flags & IORESOURCE_STORED) {
- return;
- }
-
- /* Only handle PCI memory and IO resources */
- if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
- return;
-
- /* Ensure I am actually looking at a resource of function 1 */
- if ((resource->index & 0xffff) < 0x1000) {
- return;
- }
- /* Get the base address */
- rbase = resource->base;
-
- /* Get the limit (rounded up) */
- rend = resource_end(resource);
-
- /* Get the register and link */
- reg = resource->index & 0xfff; // 4k
- link_num = IOINDEX_LINK(resource->index);
-
- if (resource->flags & IORESOURCE_IO) {
-
- set_io_addr_reg(dev, nodeid, link_num, reg, rbase>>8, rend>>8);
- store_conf_io_addr(nodeid, link_num, reg, (resource->index >> 24), rbase>>8, rend>>8);
- } else if (resource->flags & IORESOURCE_MEM) {
- set_mmio_addr_reg(nodeid, link_num, reg, (resource->index >>24), rbase>>8, rend>>8, sysconf.nodes); // [39:8]
- store_conf_mmio_addr(nodeid, link_num, reg, (resource->index >>24), rbase>>8, rend>>8);
- }
- resource->flags |= IORESOURCE_STORED;
- snprintf(buf, sizeof(buf), " <node %x link %x>",
- nodeid, link_num);
- report_resource_stored(dev, resource, buf);
-}
-
-/**
- * I tried to reuse the resource allocation code in amdfam10_set_resource()
- * but it is too difficult to deal with the resource allocation magic.
- */
-
-static void amdfam10_create_vga_resource(struct device *dev, unsigned int nodeid)
-{
- struct bus *link;
- struct resource *res;
-
- /* find out which link the VGA card is connected,
- * we only deal with the 'first' vga card */
- for (link = dev->link_list; link; link = link->next) {
- if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
-#if CONFIG(MULTIPLE_VGA_ADAPTERS)
- extern struct device *vga_pri; // the primary vga device, defined in device.c
- printk(BIOS_DEBUG, "VGA: vga_pri bus num = %d bus range [%d,%d]\n", vga_pri->bus->secondary,
- link->secondary,link->subordinate);
- /* We need to make sure the vga_pri is under the link */
- if ((vga_pri->bus->secondary >= link->secondary) &&
- (vga_pri->bus->secondary <= link->subordinate))
-#endif
- break;
- }
- }
-
- /* no VGA card installed */
- if (link == NULL)
- return;
-
- printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, link->link_num);
- set_vga_enable_reg(nodeid, link->link_num);
-
- /* Redirect VGA memory access to MMIO
- * This signals the Family 10h resource parser
- * to add a new MMIO mapping to the Range 11
- * MMIO control registers (starting at F1x1B8),
- * and also reserves the resource in the E820 map.
- */
- res = new_resource(dev, IOINDEX(0x1000 + 0x1b8, link->link_num));
- res->base = 0xa0000;
- res->size = 0x20000;
- res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
- amdfam10_set_resource(dev, res, nodeid);
-}
-
-static void amdfam10_set_resources(struct device *dev)
-{
- unsigned int nodeid;
- struct bus *bus;
- struct resource *res;
-
- /* Find the nodeid */
- nodeid = amdfam10_nodeid(dev);
-
- amdfam10_create_vga_resource(dev, nodeid);
-
- /* Set each resource we have found */
- for (res = dev->resource_list; res; res = res->next) {
- amdfam10_set_resource(dev, res, nodeid);
- }
-
- for (bus = dev->link_list; bus; bus = bus->next) {
- if (bus->children) {
- assign_resources(bus);
- }
- }
-}
-
-static void mcf0_control_init(struct device *dev)
-{
-}
-
-#if CONFIG(HAVE_ACPI_TABLES)
-static const char *amdfam10_northbridge_acpi_name(const struct device *dev)
-{
- return "";
-}
-#endif
-
-static struct device_operations northbridge_operations = {
- .read_resources = amdfam10_read_resources,
- .set_resources = amdfam10_set_resources,
- .enable_resources = pci_dev_enable_resources,
- .init = mcf0_control_init,
- .scan_bus = amdfam10_scan_chains,
-#if CONFIG(HAVE_ACPI_TABLES)
- .write_acpi_tables = northbridge_write_acpi_tables,
- .acpi_fill_ssdt_generator = northbridge_acpi_write_vars,
- .acpi_name = amdfam10_northbridge_acpi_name,
-#endif
- .enable = 0,
- .ops_pci = 0,
-};
-
-static const struct pci_driver mcf0_driver __pci_driver = {
- .ops = &northbridge_operations,
- .vendor = PCI_VENDOR_ID_AMD,
- .device = 0x1200,
-};
-
-static void amdfam10_nb_init(void *chip_info)
-{
- relocate_sb_ht_chain();
-}
-
-static const struct pci_driver mcf0_driver_fam15_model10 __pci_driver = {
- .ops = &northbridge_operations,
- .vendor = PCI_VENDOR_ID_AMD,
- .device = 0x1400,
-};
-
-static const struct pci_driver mcf0_driver_fam15 __pci_driver = {
- .ops = &northbridge_operations,
- .vendor = PCI_VENDOR_ID_AMD,
- .device = 0x1600,
-};
-
-struct chip_operations northbridge_amd_amdfam10_ops = {
- CHIP_NAME("AMD Family 10h/15h Northbridge")
- .enable_dev = 0,
- .init = amdfam10_nb_init,
-};
-
-static void amdfam10_domain_read_resources(struct device *dev)
-{
- unsigned int reg;
- uint8_t nvram;
- uint8_t enable_cc6;
-
- /* Find the already assigned resource pairs */
- get_fx_devs();
- for (reg = 0x80; reg <= 0xd8; reg+= 0x08) {
- u32 base, limit;
- base = f1_read_config32(reg);
- limit = f1_read_config32(reg + 0x04);
- /* Is this register allocated? */
- if ((base & 3) != 0) {
- unsigned int nodeid, reg_link;
- struct device *reg_dev;
- if (reg < 0xc0) { // mmio
- nodeid = (limit & 0xf) + (base&0x30);
- } else { // io
- nodeid = (limit & 0xf) + ((base>>4)&0x30);
- }
- reg_link = (limit >> 4) & 7;
- reg_dev = __f0_dev[nodeid];
- if (reg_dev) {
- /* Reserve the resource */
- struct resource *res;
- res = new_resource(reg_dev, IOINDEX(0x1000 + reg, reg_link));
- if (res) {
- res->flags = 1;
- }
- }
- }
- }
- /* FIXME: do we need to check extend conf space?
- I don't believe that much preset value */
-
- pci_domain_read_resources(dev);
-
- /* We have MMCONF_SUPPORT, create the resource window. */
- mmconf_resource(dev, MMIO_CONF_BASE);
-
- /* Reserve lower DRAM region to force PCI MMIO region to correct location above 0xefffffff */
- ram_resource(dev, 7, 0, rdmsr(TOP_MEM).lo >> 10);
-
- if (is_fam15h()) {
- enable_cc6 = 0;
- if (get_option(&nvram, "cpu_cc6_state") == CB_SUCCESS)
- enable_cc6 = !!nvram;
-
- if (enable_cc6) {
- uint8_t node;
- uint8_t interleaved;
- int8_t range;
- uint8_t max_node;
- uint64_t max_range_limit;
- uint32_t dword;
- uint32_t dword2;
- uint64_t qword;
- uint8_t num_nodes;
-
- /* Find highest DRAM range (DramLimitAddr) */
- num_nodes = 0;
- max_node = 0;
- interleaved = 0;
- max_range_limit = 0;
- struct device *node_dev;
- for (node = 0; node < FX_DEVS; node++) {
- node_dev = get_node_pci(node, 0);
- /* Test for node presence */
- if ((!node_dev) || (pci_read_config32(node_dev, PCI_VENDOR_ID) == 0xffffffff))
- continue;
-
- num_nodes++;
- for (range = 0; range < 8; range++) {
- dword = pci_read_config32(get_node_pci(node, 1), 0x40 + (range * 0x8));
- if (!(dword & 0x3))
- continue;
-
- if ((dword >> 8) & 0x7)
- interleaved = 1;
-
- dword = pci_read_config32(get_node_pci(node, 1), 0x44 + (range * 0x8));
- dword2 = pci_read_config32(get_node_pci(node, 1), 0x144 + (range * 0x8));
- qword = 0xffffff;
- qword |= ((((uint64_t)dword) >> 16) & 0xffff) << 24;
- qword |= (((uint64_t)dword2) & 0xff) << 40;
-
- if (qword > max_range_limit) {
- max_range_limit = qword;
- max_node = dword & 0x7;
- }
- }
- }
-
- /* Calculate CC6 storage area size */
- if (interleaved)
- qword = (uint64_t)0x1000000 * num_nodes;
- else
- qword = 0x1000000;
-
- /* FIXME
- * The BKDG appears to be incorrect as to the location of the CC6 save region
- * lower boundary on non-interleaved systems, causing lockups on attempted write
- * to the CC6 save region.
- *
- * For now, work around by allocating the maximum possible CC6 save region size.
- *
- * Determine if this is a BKDG error or a setup problem and remove this warning!
- */
- qword = (0x1 << 27);
- max_range_limit = (((uint64_t)(pci_read_config32(get_node_pci(max_node, 1), 0x124) & 0x1fffff)) << 27) - 1;
-
- printk(BIOS_INFO, "Reserving CC6 save segment base: %08llx size: %08llx\n", (max_range_limit + 1), qword);
-
- /* Reserve the CC6 save segment */
- reserved_ram_resource(dev, 8, (max_range_limit + 1) >> 10, qword >> 10);
- }
- }
-}
-
-static u32 my_find_pci_tolm(struct bus *bus, u32 tolm)
-{
- struct resource *min;
- min = 0;
- search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min);
- if (min && tolm > min->base) {
- tolm = min->base;
- }
- return tolm;
-}
-
-#if CONFIG_HW_MEM_HOLE_SIZEK != 0
-
-struct hw_mem_hole_info {
- unsigned int hole_startk;
- int node_id;
-};
-
-static struct hw_mem_hole_info get_hw_mem_hole_info(void)
-{
- struct hw_mem_hole_info mem_hole;
- int i;
-
- mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK;
- mem_hole.node_id = -1;
-
- for (i = 0; i < sysconf.nodes; i++) {
- struct dram_base_mask_t d;
- u32 hole;
- d = get_dram_base_mask(i);
- if (!(d.mask & 1)) continue; // no memory on this node
-
- hole = pci_read_config32(__f1_dev[i], 0xf0);
- if (hole & 1) { // we find the hole
- mem_hole.hole_startk = (hole & (0xff<<24)) >> 10;
- mem_hole.node_id = i; // record the node No with hole
- break; // only one hole
- }
- }
-
- /* We need to double check if there is special set on base reg and limit reg
- * are not continuous instead of hole, it will find out its hole_startk.
- */
- if (mem_hole.node_id==-1) {
- resource_t limitk_pri = 0;
- for (i = 0; i < sysconf.nodes; i++) {
- struct dram_base_mask_t d;
- resource_t base_k, limit_k;
- d = get_dram_base_mask(i);
- if (!(d.base & 1)) continue;
-
- base_k = ((resource_t)(d.base & 0x1fffff00)) <<9;
- if (base_k > 4 *1024 * 1024) break; // don't need to go to check
- if (limitk_pri != base_k) { // we find the hole
- mem_hole.hole_startk = (unsigned int)limitk_pri; // must beblow 4G
- mem_hole.node_id = i;
- break; //only one hole
- }
-
- limit_k = ((resource_t)((d.mask + 0x00000100) & 0x1fffff00)) << 9;
- limitk_pri = limit_k;
- }
- }
- return mem_hole;
-}
-
-#endif
-
-#include <cbmem.h>
-
-static void setup_uma_memory(void)
-{
-#if CONFIG(GFXUMA)
- uint32_t topmem = (uint32_t) bsp_topmem();
- uma_memory_size = get_uma_memory_size(topmem);
- uma_memory_base = topmem - uma_memory_size; /* TOP_MEM1 */
- printk(BIOS_INFO, "%s: uma size 0x%08llx, memory start 0x%08llx\n",
- __func__, uma_memory_size, uma_memory_base);
-#endif
-}
-
-static void amdfam10_domain_set_resources(struct device *dev)
-{
- unsigned long mmio_basek;
- u32 pci_tolm;
- int i, idx;
- struct bus *link;
-#if CONFIG_HW_MEM_HOLE_SIZEK != 0
- struct hw_mem_hole_info mem_hole;
-#endif
-
- pci_tolm = 0xffffffffUL;
- for (link = dev->link_list; link; link = link->next) {
- pci_tolm = my_find_pci_tolm(link, pci_tolm);
- }
-
- // FIXME handle interleaved nodes. If you fix this here, please fix
- // amdk8, too.
- mmio_basek = pci_tolm >> 10;
- /* Round mmio_basek to something the processor can support */
- mmio_basek &= ~((1 << 6) -1);
-
- // FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M
- // MMIO hole. If you fix this here, please fix amdk8, too.
- /* Round the mmio hole to 64M */
- mmio_basek &= ~((64*1024) - 1);
-
-#if CONFIG_HW_MEM_HOLE_SIZEK != 0
-/* if the hw mem hole is already set in raminit stage, here we will compare
- * mmio_basek and hole_basek. if mmio_basek is bigger that hole_basek and will
- * use hole_basek as mmio_basek and we don't need to reset hole.
- * otherwise We reset the hole to the mmio_basek
- */
-
- mem_hole = get_hw_mem_hole_info();
-
- // Use hole_basek as mmio_basek, and we don't need to reset hole anymore
- if ((mem_hole.node_id != -1) && (mmio_basek > mem_hole.hole_startk)) {
- mmio_basek = mem_hole.hole_startk;
- }
-
-#endif
-
- idx = 0x10;
- for (i = 0; i < sysconf.nodes; i++) {
- struct dram_base_mask_t d;
- resource_t basek, limitk, sizek; // 4 1T
- d = get_dram_base_mask(i);
-
- if (!(d.mask & 1)) continue;
- basek = ((resource_t)(d.base & 0x1fffff00)) << 9; // could overflow, we may lost 6 bit here
- limitk = ((resource_t)((d.mask + 0x00000100) & 0x1fffff00)) << 9;
- sizek = limitk - basek;
-
- /* see if we need a hole from 0xa0000 to 0xbffff */
- if ((basek < ((8*64)+(8*16))) && (sizek > ((8*64)+(16*16)))) {
- ram_resource(dev, (idx | i), basek, ((8*64)+(8*16)) - basek);
- idx += 0x10;
- basek = (8*64)+(16*16);
- sizek = limitk - ((8*64)+(16*16));
-
- }
-
- /* split the region to accommodate pci memory space */
- if ((basek < 4*1024*1024) && (limitk > mmio_basek)) {
- if (basek <= mmio_basek) {
- unsigned int pre_sizek;
- pre_sizek = mmio_basek - basek;
- if (pre_sizek > 0) {
- ram_resource(dev, (idx | i), basek, pre_sizek);
- idx += 0x10;
- sizek -= pre_sizek;
- }
- basek = mmio_basek;
- }
- if ((basek + sizek) <= 4*1024*1024) {
- sizek = 0;
- } else {
- basek = 4*1024*1024;
- sizek -= (4*1024*1024 - mmio_basek);
- }
- }
-
- ram_resource(dev, (idx | i), basek, sizek);
- idx += 0x10;
- printk(BIOS_DEBUG, "%d: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",
- i, mmio_basek, basek, limitk);
- }
-
-#if CONFIG(GFXUMA)
- uma_resource(dev, 7, uma_memory_base >> 10, uma_memory_size >> 10);
-#endif
-
- for (link = dev->link_list; link; link = link->next) {
- if (link->children) {
- assign_resources(link);
- }
- }
-}
-
-static void amdfam10_domain_scan_bus(struct device *dev)
-{
- u32 reg;
- int i;
- struct bus *link;
- /* Unmap all of the HT chains */
- for (reg = 0xe0; reg <= 0xec; reg += 4) {
- f1_write_config32(reg, 0);
- }
-
- for (link = dev->link_list; link; link = link->next) {
- link->secondary = dev->bus->subordinate;
- pci_scan_bus(link, PCI_DEVFN(CONFIG_CDB, 0), 0xff);
- dev->bus->subordinate = link->subordinate;
- }
-
- /* Tune the hypertransport transaction for best performance.
- * Including enabling relaxed ordering if it is safe.
- */
- get_fx_devs();
- for (i = 0; i < fx_devs; i++) {
- struct device *f0_dev;
- f0_dev = __f0_dev[i];
- if (f0_dev && f0_dev->enabled) {
- u32 httc;
- httc = pci_read_config32(f0_dev, HT_TRANSACTION_CONTROL);
- httc &= ~HTTC_RSP_PASS_PW;
- if (!dev->link_list->disable_relaxed_ordering) {
- httc |= HTTC_RSP_PASS_PW;
- }
- printk(BIOS_SPEW, "%s passpw: %s\n",
- dev_path(dev),
- (!dev->link_list->disable_relaxed_ordering)?
- "enabled":"disabled");
- pci_write_config32(f0_dev, HT_TRANSACTION_CONTROL, httc);
- }
- }
-}
-
-#if CONFIG(GENERATE_SMBIOS_TABLES)
-static int amdfam10_get_smbios_data16(int *count, int handle,
- unsigned long *current)
-{
- struct amdmct_memory_info *mem_info;
- mem_info = cbmem_find(CBMEM_ID_AMDMCT_MEMINFO);
- if (mem_info == NULL)
- return 0; /* can't find amdmct information in cbmem */
-
- struct device *dev = get_node_pci(0, 0);
- struct northbridge_amd_amdfam10_config *config = dev->chip_info;
-
- int node;
- int slot;
-
- struct smbios_type16 *t = (struct smbios_type16 *)*current;
- int len = sizeof(struct smbios_type16);
-
- memset(t, 0, sizeof(struct smbios_type16));
- t->type = SMBIOS_PHYS_MEMORY_ARRAY;
- t->handle = handle;
- t->length = len - 2;
- t->location = MEMORY_ARRAY_LOCATION_SYSTEM_BOARD;
- t->use = MEMORY_ARRAY_USE_SYSTEM;
- t->memory_error_correction = MEMORY_ARRAY_ECC_NONE;
- if ((mem_info->ecc_enabled)
- && (mem_info->mct_stat.GStatus & (1 << GSB_ECCDIMMs))
- && !(mem_info->mct_stat.GStatus & (1 << GSB_DramECCDis)))
- /* Single-bit ECC enabled */
- t->memory_error_correction = MEMORY_ARRAY_ECC_SINGLE_BIT;
- t->maximum_capacity = config->maximum_memory_capacity / 1024; /* Convert to kilobytes */
- t->memory_error_information_handle = 0xFFFE; /* no error information handle available */
-
- t->number_of_memory_devices = 0;
- /* Check all nodes for installed DIMMs */
- for (node = 0; node < MAX_NODES_SUPPORTED; node++)
- /* Check all slots for installed DIMMs */
- for (slot = 0; slot < MAX_DIMMS_SUPPORTED; slot++)
- if (mem_info->dct_stat[node].DIMMPresent & (1 << slot))
- /* Found an installed DIMM; increment count */
- t->number_of_memory_devices++;
-
- *current += len;
- *count += 1;
- return len;
-}
-
-static uint16_t amdmct_mct_speed_enum_to_mhz(uint8_t speed)
-{
- if (is_fam15h()) {
- if (CONFIG(DIMM_DDR3)) {
- switch (speed) {
- case 0x4:
- return 333;
- case 0x6:
- return 400;
- case 0xa:
- return 533;
- case 0xe:
- return 667;
- case 0x12:
- return 800;
- case 0x16:
- return 933;
- default:
- return 0;
- }
- } else {
- return 0;
- }
- } else {
- if (CONFIG(DIMM_DDR2)) {
- switch (speed) {
- case 1:
- return 200;
- case 2:
- return 266;
- case 3:
- return 333;
- case 4:
- return 400;
- case 5:
- return 533;
- default:
- return 0;
- }
- } else if (CONFIG(DIMM_DDR3)) {
- switch (speed) {
- case 3:
- return 333;
- case 4:
- return 400;
- case 5:
- return 533;
- case 6:
- return 667;
- case 7:
- return 800;
- default:
- return 0;
- }
- } else {
- return 0;
- }
- }
-}
-
-static int amdfam10_get_smbios_data17(int *count, int handle, int parent_handle,
- unsigned long *current)
-{
- struct amdmct_memory_info *mem_info;
- mem_info = cbmem_find(CBMEM_ID_AMDMCT_MEMINFO);
- if (mem_info == NULL)
- return 0; /* can't find amdmct information in cbmem */
-
- int single_len;
- int len = 0;
- int node;
- int slot;
-
- /* Check all nodes for installed DIMMs */
- for (node = 0; node < MAX_NODES_SUPPORTED; node++) {
- /* Get configured RAM bus speed */
- uint16_t speed;
- speed = amdmct_mct_speed_enum_to_mhz(mem_info->dct_stat[node].Speed);
-
- /* Get maximum RAM bus speed */
- uint16_t max_speed;
- max_speed = amdmct_mct_speed_enum_to_mhz(mem_info->dct_stat[node].DIMMAutoSpeed);
-
- /* Check all slots for installed DIMMs */
- for (slot = 0; slot < MAX_DIMMS_SUPPORTED; slot++) {
- if (mem_info->dct_stat[node].DIMMPresent & (1 << slot)) {
- /* Found an installed DIMM; populate tables */
- struct smbios_type17 *t = (struct smbios_type17 *)*current;
- char string_buffer[256];
-
- /* Initialize structure */
- memset(t, 0, sizeof(struct smbios_type17));
-
- /* Calculate the total module size in bytes:
- * Primary data width * 2^(#rows) * 2^(#cols) * #banks * #ranks
- */
- uint8_t width, rows, cols, banks, ranks;
- uint64_t chip_size;
- uint32_t chip_width;
- rows = mem_info->dct_stat[node].DimmRows[slot];
- cols = mem_info->dct_stat[node].DimmCols[slot];
- ranks = mem_info->dct_stat[node].DimmRanks[slot];
- banks = mem_info->dct_stat[node].DimmBanks[slot];
-#if CONFIG(DIMM_DDR3)
- chip_size = mem_info->dct_stat[node].DimmChipSize[slot];
- chip_width = mem_info->dct_stat[node].DimmChipWidth[slot];
-#else
- chip_size = 0;
- chip_width = 0;
-#endif
- uint64_t dimm_size_bytes;
- if (CONFIG(DIMM_DDR3)) {
- width = mem_info->dct_stat[node].DimmWidth[slot];
- dimm_size_bytes = ((width / chip_width) * chip_size * ranks) / 8;
- } else {
- width = 8;
- dimm_size_bytes = width * (1ULL << rows) * (1ULL << cols) * banks * ranks;
- }
-
- memset(t, 0, sizeof(struct smbios_type17));
- t->type = SMBIOS_MEMORY_DEVICE;
- t->handle = handle;
- t->phys_memory_array_handle = parent_handle;
- t->length = sizeof(struct smbios_type17) - 2;
- if (dimm_size_bytes > 0x800000000) {
- t->size = 0x7FFF;
- t->extended_size = dimm_size_bytes >> 16;
- } else {
- t->size = dimm_size_bytes / (1024*1024);
- t->size &= (~0x8000); /* size specified in megabytes */
- }
- t->total_width = t->data_width = 64;
- if (mem_info->dct_stat[node].DimmECCPresent & (1 << slot))
- t->total_width += 8;
- t->attributes = 0;
- t->attributes |= ranks & 0xf; /* rank number is stored in the lowest 4 bits of the attributes field */
- t->form_factor = MEMORY_FORMFACTOR_DIMM;
- if (mem_info->dct_stat[node].Dual_Node_Package) {
- snprintf(string_buffer, sizeof(string_buffer), "NODE %d DIMM_%s%d", node >> 1,
- (mem_info->dct_stat[node].Internal_Node_ID)?((slot & 0x1)?"D":"C"):((slot & 0x1)?"B":"A"), (slot >> 1) + 1);
- } else {
- snprintf(string_buffer, sizeof(string_buffer), "NODE %d DIMM_%s%d", node, (slot & 0x1)?"B":"A", (slot >> 1) + 1);
- }
- t->device_locator = smbios_add_string(t->eos, string_buffer);
- if (CONFIG(DIMM_DDR2))
- t->memory_type = MEMORY_TYPE_DDR2;
- else if (CONFIG(DIMM_DDR3))
- t->memory_type = MEMORY_TYPE_DDR3;
- t->type_detail = MEMORY_TYPE_DETAIL_SYNCHRONOUS;
- if (mem_info->dct_stat[node].DimmRegistered[slot])
- t->type_detail |= MEMORY_TYPE_DETAIL_REGISTERED;
- else
- t->type_detail |= MEMORY_TYPE_DETAIL_UNBUFFERED;
- t->speed = max_speed;
- t->clock_speed = speed;
- smbios_fill_dimm_manufacturer_from_id(mem_info->dct_stat[node].DimmManufacturerID[slot], t);
- t->part_number = smbios_add_string(t->eos, mem_info->dct_stat[node].DimmPartNumber[slot]);
- if (mem_info->dct_stat[node].DimmSerialNumber[slot] == 0) {
- t->serial_number = smbios_add_string(t->eos, "None");
- } else {
- snprintf(string_buffer, sizeof(string_buffer), "%08X", mem_info->dct_stat[node].DimmSerialNumber[slot]);
- t->serial_number = smbios_add_string(t->eos, string_buffer);
- }
- if (CONFIG(DIMM_DDR2)) {
- /* JEDEC specifies 1.8V only, so assume that the memory is configured for 1.8V */
- t->minimum_voltage = 1800;
- t->maximum_voltage = 1800;
- t->configured_voltage = 1800;
- } else if (CONFIG(DIMM_DDR3)) {
-#if CONFIG(DIMM_DDR3)
- /* Find the maximum and minimum supported voltages */
- uint8_t supported_voltages = mem_info->dct_stat[node].DimmSupportedVoltages[slot];
- uint8_t configured_voltage = mem_info->dct_stat[node].DimmConfiguredVoltage[slot];
-
- if (supported_voltages & 0x8)
- t->minimum_voltage = 1150;
- else if (supported_voltages & 0x4)
- t->minimum_voltage = 1250;
- else if (supported_voltages & 0x2)
- t->minimum_voltage = 1350;
- else if (supported_voltages & 0x1)
- t->minimum_voltage = 1500;
-
- if (supported_voltages & 0x1)
- t->maximum_voltage = 1500;
- else if (supported_voltages & 0x2)
- t->maximum_voltage = 1350;
- else if (supported_voltages & 0x4)
- t->maximum_voltage = 1250;
- else if (supported_voltages & 0x8)
- t->maximum_voltage = 1150;
-
- if (configured_voltage & 0x8)
- t->configured_voltage = 1150;
- else if (configured_voltage & 0x4)
- t->configured_voltage = 1250;
- else if (configured_voltage & 0x2)
- t->configured_voltage = 1350;
- else if (configured_voltage & 0x1)
- t->configured_voltage = 1500;
-#endif
- }
- t->memory_error_information_handle = 0xFFFE; /* no error information handle available */
- single_len = t->length + smbios_string_table_len(t->eos);
- len += single_len;
- *current += single_len;
- handle++;
- *count += 1;
- }
- }
- }
-
- return len;
-}
-
-static int amdfam10_get_smbios_data(struct device *dev, int *handle, unsigned long *current)
-{
- int len;
- int count = 0;
- len = amdfam10_get_smbios_data16(&count, *handle, current);
- len += amdfam10_get_smbios_data17(&count, *handle + 1, *handle, current);
- *handle += count;
- return len;
-}
-#endif
-
-#if CONFIG(HAVE_ACPI_TABLES)
-static const char *amdfam10_domain_acpi_name(const struct device *dev)
-{
- if (dev->path.type == DEVICE_PATH_DOMAIN)
- return "PCI0";
-
- return NULL;
-}
-#endif
-
-static struct device_operations pci_domain_ops = {
- .read_resources = amdfam10_domain_read_resources,
- .set_resources = amdfam10_domain_set_resources,
- .enable_resources = NULL,
- .init = NULL,
- .scan_bus = amdfam10_domain_scan_bus,
-#if CONFIG(HAVE_ACPI_TABLES)
- .acpi_name = amdfam10_domain_acpi_name,
-#endif
-#if CONFIG(GENERATE_SMBIOS_TABLES)
- .get_smbios_data = amdfam10_get_smbios_data,
-#endif
-};
-
-static void sysconf_init(struct device *dev) // first node
-{
- sysconf.sblk = (pci_read_config32(dev, 0x64)>>8) & 7; // don't forget sublink1
- sysconf.segbit = 0;
- sysconf.ht_c_num = 0;
-
- unsigned int ht_c_index;
-
- for (ht_c_index = 0; ht_c_index < 32; ht_c_index++) {
- sysconf.ht_c_conf_bus[ht_c_index] = 0;
- }
-
- sysconf.nodes = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1;
-#if CONFIG_MAX_PHYSICAL_CPUS > 8
- sysconf.nodes += (((pci_read_config32(dev, 0x160)>>4) & 7)<<3);
-#endif
-
- sysconf.enabled_apic_ext_id = 0;
- sysconf.lift_bsp_apicid = 0;
-
- /* Find the bootstrap processors apicid */
- sysconf.bsp_apicid = lapicid();
- sysconf.apicid_offset = sysconf.bsp_apicid;
-
-#if CONFIG(ENABLE_APIC_EXT_ID)
- if (pci_read_config32(dev, 0x68) & (HTTC_APIC_EXT_ID|HTTC_APIC_EXT_BRD_CST))
- {
- sysconf.enabled_apic_ext_id = 1;
- }
- #if (CONFIG_APIC_ID_OFFSET > 0)
- if (sysconf.enabled_apic_ext_id) {
- if (sysconf.bsp_apicid == 0) {
- /* bsp apic id is not changed */
- sysconf.apicid_offset = CONFIG_APIC_ID_OFFSET;
- } else {
- sysconf.lift_bsp_apicid = 1;
- }
- }
- #endif
-#endif
-}
-
-static void remap_bsp_lapic(struct bus *cpu_bus)
-{
- struct device_path cpu_path;
- struct device *cpu;
- u32 bsp_lapic_id = lapicid();
-
- if (bsp_lapic_id) {
- cpu_path.type = DEVICE_PATH_APIC;
- cpu_path.apic.apic_id = 0;
- cpu = find_dev_path(cpu_bus, &cpu_path);
- if (cpu)
- cpu->path.apic.apic_id = bsp_lapic_id;
- }
-}
-
-static void cpu_bus_scan(struct device *dev)
-{
- struct bus *cpu_bus;
- struct device *dev_mc;
-#if CONFIG_CBB
- struct device *pci_domain;
-#endif
- int nvram = 0;
- int i,j;
- int nodes;
- unsigned int nb_cfg_54;
- unsigned int siblings;
- int cores_found;
- int disable_siblings;
- uint8_t disable_cu_siblings = 0;
- unsigned int ApicIdCoreIdSize;
-
- nb_cfg_54 = 0;
- ApicIdCoreIdSize = (cpuid_ecx(0x80000008)>>12 & 0xf);
- if (ApicIdCoreIdSize) {
- siblings = (1<<ApicIdCoreIdSize)-1;
- } else {
- siblings = 3; //quad core
- }
-
- disable_siblings = !CONFIG(LOGICAL_CPUS);
-#if CONFIG(LOGICAL_CPUS)
- get_option(&disable_siblings, "multi_core");
-#endif
-
- // How can I get the nb_cfg_54 of every node's nb_cfg_54 in bsp???
- nb_cfg_54 = read_nb_cfg_54();
-
-#if CONFIG_CBB
- dev_mc = pcidev_on_root(CONFIG_CDB, 0); //0x00
- if (dev_mc && dev_mc->bus) {
- printk(BIOS_DEBUG, "%s found", dev_path(dev_mc));
- pci_domain = dev_mc->bus->dev;
- if (pci_domain && (pci_domain->path.type == DEVICE_PATH_DOMAIN)) {
- printk(BIOS_DEBUG, "\n%s move to ",dev_path(dev_mc));
- dev_mc->bus->secondary = CONFIG_CBB; // move to 0xff
- printk(BIOS_DEBUG, "%s",dev_path(dev_mc));
-
- } else {
- printk(BIOS_DEBUG, " but it is not under pci_domain directly ");
- }
- printk(BIOS_DEBUG, "\n");
- }
- dev_mc = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 0));
- if (!dev_mc) {
- dev_mc = pcidev_on_root(0x18, 0);
- if (dev_mc && dev_mc->bus) {
- printk(BIOS_DEBUG, "%s found\n", dev_path(dev_mc));
- pci_domain = dev_mc->bus->dev;
- if (pci_domain && (pci_domain->path.type == DEVICE_PATH_DOMAIN)) {
- if ((pci_domain->link_list) && (pci_domain->link_list->children == dev_mc)) {
- printk(BIOS_DEBUG, "%s move to ",dev_path(dev_mc));
- dev_mc->bus->secondary = CONFIG_CBB; // move to 0xff
- printk(BIOS_DEBUG, "%s\n",dev_path(dev_mc));
- while (dev_mc) {
- printk(BIOS_DEBUG, "%s move to ",dev_path(dev_mc));
- dev_mc->path.pci.devfn -= PCI_DEVFN(0x18,0);
- printk(BIOS_DEBUG, "%s\n",dev_path(dev_mc));
- dev_mc = dev_mc->sibling;
- }
- }
- }
- }
- }
-
-#endif
-
- dev_mc = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 0));
- if (!dev_mc) {
- printk(BIOS_ERR, "%02x:%02x.0 not found", CONFIG_CBB, CONFIG_CDB);
- die("");
- }
-
- sysconf_init(dev_mc);
-
- nodes = sysconf.nodes;
-
-#if CONFIG_CBB && (NODE_NUMS > 32)
- if (nodes > 32) { // need to put node 32 to node 63 to bus 0xfe
- if (pci_domain->link_list && !pci_domain->link_list->next) {
- struct bus *new_link = new_link(pci_domain);
- pci_domain->link_list->next = new_link;
- new_link->link_num = 1;
- new_link->dev = pci_domain;
- new_link->children = 0;
- printk(BIOS_DEBUG, "%s links now 2\n", dev_path(pci_domain));
- }
- pci_domain->link_list->next->secondary = CONFIG_CBB - 1;
- }
-#endif
- /* Find which cpus are present */
- cpu_bus = dev->link_list;
-
- /* Always use the devicetree node with lapic_id 0 for BSP. */
- remap_bsp_lapic(cpu_bus);
-
- if (get_option(&nvram, "compute_unit_siblings") == CB_SUCCESS)
- disable_cu_siblings = !!nvram;
-
- if (disable_cu_siblings)
- printk(BIOS_DEBUG, "Disabling siblings on each compute unit as requested\n");
-
- for (i = 0; i < nodes; i++) {
- struct device *cdb_dev;
- unsigned int busn, devn;
- struct bus *pbus;
-
- uint8_t fam15h = 0;
- uint8_t rev_gte_d = 0;
- uint8_t dual_node = 0;
- uint32_t f3xe8;
- uint32_t model;
-
- busn = CONFIG_CBB;
- devn = CONFIG_CDB+i;
- pbus = dev_mc->bus;
-#if CONFIG_CBB && (NODE_NUMS > 32)
- if (i >= 32) {
- busn--;
- devn-=32;
- pbus = pci_domain->link_list->next;
- }
-#endif
-
- /* Find the cpu's pci device */
- cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 0));
- if (!cdb_dev) {
- /* If I am probing things in a weird order
- * ensure all of the cpu's pci devices are found.
- */
- int fn;
- for (fn = 0; fn <= 5; fn++) { //FBDIMM?
- cdb_dev = pci_probe_dev(NULL, pbus,
- PCI_DEVFN(devn, fn));
- }
- }
-
-
- /* Ok, We need to set the links for that device.
- * otherwise the device under it will not be scanned
- */
- cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 0));
- if (cdb_dev)
- add_more_links(cdb_dev, 4);
-
- cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 4));
- if (cdb_dev)
- add_more_links(cdb_dev, 4);
-
- f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8);
-
- model = cpuid_eax(0x80000001);
- model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
-
- if (is_fam15h()) {
- /* Family 15h or later */
- fam15h = 1;
- nb_cfg_54 = 1;
- }
-
- if ((model >= 0x8) || fam15h)
- /* Revision D or later */
- rev_gte_d = 1;
-
- if (rev_gte_d)
- /* Check for dual node capability */
- if (f3xe8 & 0x20000000)
- dual_node = 1;
-
- cores_found = 0; // one core
- if (fam15h)
- cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 5));
- else
- cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 3));
- int enable_node = cdb_dev && cdb_dev->enabled;
- if (enable_node) {
- if (fam15h) {
- cores_found = pci_read_config32(cdb_dev, 0x84) & 0xff;
- } else {
- j = pci_read_config32(cdb_dev, 0xe8);
- cores_found = (j >> 12) & 3; // dev is func 3
- if (siblings > 3)
- cores_found |= (j >> 13) & 4;
- }
- printk(BIOS_DEBUG, " %s siblings=%d\n", dev_path(cdb_dev), cores_found);
- }
-
- if (siblings > cores_found)
- siblings = cores_found;
-
- u32 jj;
- if (disable_siblings) {
- jj = 0;
- } else
- {
- jj = cores_found;
- }
-
- for (j = 0; j <=jj; j++) {
- u32 apic_id;
-
- if (dual_node) {
- apic_id = 0;
- if (fam15h) {
- apic_id |= ((i >> 1) & 0x3) << 5; /* Node ID */
- apic_id |= ((i & 0x1) * (siblings + 1)) + j; /* Core ID */
- } else {
- if (nb_cfg_54) {
- apic_id |= ((i >> 1) & 0x3) << 4; /* Node ID */
- apic_id |= ((i & 0x1) * (siblings + 1)) + j; /* Core ID */
- } else {
- apic_id |= i & 0x3; /* Node ID */
- apic_id |= (((i & 0x1) * (siblings + 1)) + j) << 4; /* Core ID */
- }
- }
- } else {
- if (fam15h) {
- apic_id = 0;
- apic_id |= (i & 0x7) << 4; /* Node ID */
- apic_id |= j & 0xf; /* Core ID */
- } else {
- apic_id = i * (nb_cfg_54?(siblings+1):1) + j * (nb_cfg_54?1:64); // ?
- }
- }
-
-#if CONFIG(ENABLE_APIC_EXT_ID) && (CONFIG_APIC_ID_OFFSET > 0)
- if (sysconf.enabled_apic_ext_id) {
- if (apic_id != 0 || sysconf.lift_bsp_apicid) {
- apic_id += sysconf.apicid_offset;
- }
- }
-#endif
- if (disable_cu_siblings && (j & 0x1))
- continue;
-
- struct device *cpu = add_cpu_device(cpu_bus, apic_id, enable_node);
- if (cpu)
- amd_cpu_topology(cpu, i, j);
- }
- }
-}
-
-static void detect_and_enable_probe_filter(struct device *dev)
-{
- uint32_t dword;
-
- uint8_t nvram;
- uint8_t enable_probe_filter;
-
- /* Check to see if the probe filter is allowed */
- enable_probe_filter = 1;
- if (get_option(&nvram, "probe_filter") == CB_SUCCESS)
- enable_probe_filter = !!nvram;
-
- if (!enable_probe_filter)
- return;
-
- uint8_t fam15h = 0;
- uint8_t rev_gte_d = 0;
- uint32_t model;
-
- model = cpuid_eax(0x80000001);
- model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
-
- if (is_fam15h()) {
- /* Family 15h or later */
- fam15h = 1;
- }
-
- if ((model >= 0x8) || fam15h)
- /* Revision D or later */
- rev_gte_d = 1;
-
- if (rev_gte_d && (sysconf.nodes > 1)) {
- /* Enable the probe filter */
- uint8_t i;
- uint8_t pfmode = 0x0;
-
- uint32_t f3x58[MAX_NODES_SUPPORTED];
- uint32_t f3x5c[MAX_NODES_SUPPORTED];
-
- printk(BIOS_DEBUG, "Enabling probe filter\n");
-
- /* Disable L3 and DRAM scrubbers and configure system for probe filter support */
- for (i = 0; i < sysconf.nodes; i++) {
- struct device *f2x_dev = pcidev_on_root(0x18 + i, 2);
- struct device *f3x_dev = pcidev_on_root(0x18 + i, 3);
-
- f3x58[i] = pci_read_config32(f3x_dev, 0x58);
- f3x5c[i] = pci_read_config32(f3x_dev, 0x5c);
- pci_write_config32(f3x_dev, 0x58, f3x58[i] & ~((0x1f << 24) | 0x1f));
- pci_write_config32(f3x_dev, 0x5c, f3x5c[i] & ~0x1);
-
- dword = pci_read_config32(f2x_dev, 0x1b0);
- dword &= ~(0x7 << 8); /* CohPrefPrbLmt = 0x0 */
- pci_write_config32(f2x_dev, 0x1b0, dword);
-
- msr_t msr = rdmsr_amd(BU_CFG2_MSR);
- msr.hi |= 1 << (42 - 32);
- wrmsr_amd(BU_CFG2_MSR, msr);
-
- if (is_fam15h()) {
- uint8_t subcache_size = 0x0;
- uint8_t pref_so_repl = 0x0;
- uint32_t f3x1c4 = pci_read_config32(f3x_dev, 0x1c4);
- if ((f3x1c4 & 0xffff) == 0xcccc) {
- subcache_size = 0x1;
- pref_so_repl = 0x2;
- pfmode = 0x3;
- } else {
- pfmode = 0x2;
- }
-
- dword = pci_read_config32(f3x_dev, 0x1d4);
- dword |= 0x1 << 29; /* PFLoIndexHashEn = 0x1 */
- dword &= ~(0x3 << 20); /* PFPreferredSORepl = pref_so_repl */
- dword |= (pref_so_repl & 0x3) << 20;
- dword |= 0x1 << 17; /* PFWayHashEn = 0x1 */
- dword |= 0xf << 12; /* PFSubCacheEn = 0xf */
- dword &= ~(0x3 << 10); /* PFSubCacheSize3 = subcache_size */
- dword |= (subcache_size & 0x3) << 10;
- dword &= ~(0x3 << 8); /* PFSubCacheSize2 = subcache_size */
- dword |= (subcache_size & 0x3) << 8;
- dword &= ~(0x3 << 6); /* PFSubCacheSize1 = subcache_size */
- dword |= (subcache_size & 0x3) << 6;
- dword &= ~(0x3 << 4); /* PFSubCacheSize0 = subcache_size */
- dword |= (subcache_size & 0x3) << 4;
- dword &= ~(0x3 << 2); /* PFWayNum = 0x2 */
- dword |= 0x2 << 2;
- pci_write_config32(f3x_dev, 0x1d4, dword);
- } else {
- pfmode = 0x2;
-
- dword = pci_read_config32(f3x_dev, 0x1d4);
- dword |= 0x1 << 29; /* PFLoIndexHashEn = 0x1 */
- dword &= ~(0x3 << 20); /* PFPreferredSORepl = 0x2 */
- dword |= 0x2 << 20;
- dword |= 0xf << 12; /* PFSubCacheEn = 0xf */
- dword &= ~(0x3 << 10); /* PFSubCacheSize3 = 0x0 */
- dword &= ~(0x3 << 8); /* PFSubCacheSize2 = 0x0 */
- dword &= ~(0x3 << 6); /* PFSubCacheSize1 = 0x0 */
- dword &= ~(0x3 << 4); /* PFSubCacheSize0 = 0x0 */
- dword &= ~(0x3 << 2); /* PFWayNum = 0x2 */
- dword |= 0x2 << 2;
- pci_write_config32(f3x_dev, 0x1d4, dword);
- }
- }
-
- udelay(40);
-
- disable_cache();
- wbinvd();
-
- /* Enable probe filter */
- for (i = 0; i < sysconf.nodes; i++) {
- struct device *f3x_dev = pcidev_on_root(0x18 + i, 3);
-
- dword = pci_read_config32(f3x_dev, 0x1c4);
- dword |= (0x1 << 31); /* L3TagInit = 1 */
- pci_write_config32(f3x_dev, 0x1c4, dword);
- do {
- } while (pci_read_config32(f3x_dev, 0x1c4) & (0x1 << 31));
-
- dword = pci_read_config32(f3x_dev, 0x1d4);
- dword &= ~0x3; /* PFMode = pfmode */
- dword |= pfmode & 0x3;
- pci_write_config32(f3x_dev, 0x1d4, dword);
- do {
- } while (!(pci_read_config32(f3x_dev, 0x1d4) & (0x1 << 19)));
- }
-
- if (is_fam15h()) {
- printk(BIOS_DEBUG, "Enabling ATM mode\n");
-
- /* Enable ATM mode */
- for (i = 0; i < sysconf.nodes; i++) {
- struct device *f0x_dev =
- pcidev_on_root(0x18 + i, 0);
- struct device *f3x_dev =
- pcidev_on_root(0x18 + i, 3);
-
- dword = pci_read_config32(f0x_dev, 0x68);
- dword |= (0x1 << 12); /* ATMModeEn = 1 */
- pci_write_config32(f0x_dev, 0x68, dword);
-
- dword = pci_read_config32(f3x_dev, 0x1b8);
- dword |= (0x1 << 27); /* L3ATMModeEn = 1 */
- pci_write_config32(f3x_dev, 0x1b8, dword);
- }
- }
-
- enable_cache();
-
- /* Reenable L3 and DRAM scrubbers */
- for (i = 0; i < sysconf.nodes; i++) {
- struct device *f3x_dev = pcidev_on_root(0x18 + i, 3);
-
- pci_write_config32(f3x_dev, 0x58, f3x58[i]);
- pci_write_config32(f3x_dev, 0x5c, f3x5c[i]);
- }
-
- }
-}
-
-static void detect_and_enable_cache_partitioning(struct device *dev)
-{
- uint8_t i;
- uint32_t dword;
-
- uint8_t nvram;
- uint8_t enable_l3_cache_partitioning;
-
- /* Check to see if cache partitioning is allowed */
- enable_l3_cache_partitioning = 0;
- if (get_option(&nvram, "l3_cache_partitioning") == CB_SUCCESS)
- enable_l3_cache_partitioning = !!nvram;
-
- if (!enable_l3_cache_partitioning)
- return;
-
- if (is_fam15h()) {
- printk(BIOS_DEBUG, "Enabling L3 cache partitioning\n");
-
- uint32_t f5x80;
- uint8_t cu_enabled;
- uint8_t compute_unit_count = 0;
-
- for (i = 0; i < sysconf.nodes; i++) {
- struct device *f3x_dev = pcidev_on_root(0x18 + i, 3);
- struct device *f4x_dev = pcidev_on_root(0x18 + i, 4);
- struct device *f5x_dev = pcidev_on_root(0x18 + i, 5);
-
- /* Determine the number of active compute units on this node */
- f5x80 = pci_read_config32(f5x_dev, 0x80);
- cu_enabled = f5x80 & 0xf;
- if (cu_enabled == 0x1)
- compute_unit_count = 1;
- if (cu_enabled == 0x3)
- compute_unit_count = 2;
- if (cu_enabled == 0x7)
- compute_unit_count = 3;
- if (cu_enabled == 0xf)
- compute_unit_count = 4;
-
- /* Disable BAN mode */
- dword = pci_read_config32(f3x_dev, 0x1b8);
- dword &= ~(0x7 << 19); /* L3BanMode = 0x0 */
- pci_write_config32(f3x_dev, 0x1b8, dword);
-
- /* Set up cache mapping */
- dword = pci_read_config32(f4x_dev, 0x1d4);
- if (compute_unit_count == 1) {
- dword |= 0xf; /* ComputeUnit0SubCacheEn = 0xf */
- }
- if (compute_unit_count == 2) {
- dword &= ~(0xf << 4); /* ComputeUnit1SubCacheEn = 0xc */
- dword |= (0xc << 4);
- dword &= ~0xf; /* ComputeUnit0SubCacheEn = 0x3 */
- dword |= 0x3;
- }
- if (compute_unit_count == 3) {
- dword &= ~(0xf << 8); /* ComputeUnit2SubCacheEn = 0x8 */
- dword |= (0x8 << 8);
- dword &= ~(0xf << 4); /* ComputeUnit1SubCacheEn = 0x4 */
- dword |= (0x4 << 4);
- dword &= ~0xf; /* ComputeUnit0SubCacheEn = 0x3 */
- dword |= 0x3;
- }
- if (compute_unit_count == 4) {
- dword &= ~(0xf << 12); /* ComputeUnit3SubCacheEn = 0x8 */
- dword |= (0x8 << 12);
- dword &= ~(0xf << 8); /* ComputeUnit2SubCacheEn = 0x4 */
- dword |= (0x4 << 8);
- dword &= ~(0xf << 4); /* ComputeUnit1SubCacheEn = 0x2 */
- dword |= (0x2 << 4);
- dword &= ~0xf; /* ComputeUnit0SubCacheEn = 0x1 */
- dword |= 0x1;
- }
- pci_write_config32(f4x_dev, 0x1d4, dword);
-
- /* Enable cache partitioning */
- pci_write_config32(f4x_dev, 0x1d4, dword);
- if (compute_unit_count == 1) {
- dword &= ~(0xf << 26); /* MaskUpdateForComputeUnit = 0x1 */
- dword |= (0x1 << 26);
- } else if (compute_unit_count == 2) {
- dword &= ~(0xf << 26); /* MaskUpdateForComputeUnit = 0x3 */
- dword |= (0x3 << 26);
- } else if (compute_unit_count == 3) {
- dword &= ~(0xf << 26); /* MaskUpdateForComputeUnit = 0x7 */
- dword |= (0x7 << 26);
- } else if (compute_unit_count == 4) {
- dword |= (0xf << 26); /* MaskUpdateForComputeUnit = 0xf */
- }
- pci_write_config32(f4x_dev, 0x1d4, dword);
- }
- }
-}
-
-static void cpu_bus_init(struct device *dev)
-{
- detect_and_enable_probe_filter(dev);
- detect_and_enable_cache_partitioning(dev);
- initialize_cpus(dev->link_list);
-}
-
-static struct device_operations cpu_bus_ops = {
- .read_resources = DEVICE_NOOP,
- .set_resources = DEVICE_NOOP,
- .enable_resources = DEVICE_NOOP,
- .init = cpu_bus_init,
- .scan_bus = cpu_bus_scan,
-};
-
-static void root_complex_enable_dev(struct device *dev)
-{
- static int done = 0;
-
- /* Do not delay UMA setup, as a device on the PCI bus may evaluate
- the global uma_memory variables already in its enable function. */
- if (!done) {
- setup_bsp_ramtop();
- setup_uma_memory();
- done = 1;
- }
-
- /* Set the operations if it is a special bus type */
- if (dev->path.type == DEVICE_PATH_DOMAIN) {
- dev->ops = &pci_domain_ops;
- } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
- dev->ops = &cpu_bus_ops;
- }
-}
-
-static void root_complex_finalize(void *chip_info) {
-#if CONFIG(HAVE_ACPI_RESUME) && CONFIG(DIMM_DDR3)
- save_mct_information_to_nvram();
-#endif
-}
-
-struct chip_operations northbridge_amd_amdfam10_root_complex_ops = {
- CHIP_NAME("AMD Family 10h/15h Root Complex")
- .enable_dev = root_complex_enable_dev,
- .final = root_complex_finalize,
-};