blob: 8323c1e20fafe5fcaf476193f06473f83d3e077f [file] [log] [blame]
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2003 by Eric Biederman
* Copyright (C) Stefan Reinauer
* Copyright (C) 2007 Advanced Micro Devices, Inc.
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
* Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
*
* 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.
*/
/* Turn off machine check triggers when reading
* pci space where there are no devices.
* This is necessary when scanning the bus for
* devices which is done by the kernel
*/
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <pc80/mc146818rtc.h>
#include <lib.h>
#include <cbmem.h>
#include <cpu/amd/model_10xxx_rev.h>
#include "amdfam10.h"
/**
* @brief Read resources for AGP aperture
*
* @param dev
*
* There is only one AGP aperture resource needed. The resource is added to
* the northbridge of BSP.
*
* The same trick can be used to augment legacy VGA resources which can
* be detect by generic pci reousrce allocator for VGA devices.
* BAD: it is more tricky than I think, the resource allocation code is
* implemented in a way to NOT DOING legacy VGA resource allocation on
* purpose :-(.
*/
static void mcf3_read_resources(struct device *dev)
{
struct resource *resource;
unsigned char gart;
/* Read the generic PCI resources */
pci_dev_read_resources(dev);
/* If we are not the first processor don't allocate the gart apeture */
if (dev->path.pci.devfn != PCI_DEVFN(CONFIG_CDB, 3)) {
return;
}
gart = 1;
get_option(&gart, "gart");
if (gart) {
/* Add a Gart apeture resource */
resource = new_resource(dev, 0x94);
resource->size = CONFIG_AGP_APERTURE_SIZE;
resource->align = log2(resource->size);
resource->gran = log2(resource->size);
resource->limit = 0xffffffff; /* 4G */
resource->flags = IORESOURCE_MEM;
}
}
static void set_agp_aperture(struct device *dev, uint32_t pci_id)
{
uint32_t dword;
struct resource *resource;
resource = probe_resource(dev, 0x94);
if (resource) {
struct device *pdev;
u32 gart_base, gart_acr;
/* Remember this resource has been stored */
resource->flags |= IORESOURCE_STORED;
/* Find the size of the GART aperture */
gart_acr = (0<<6)|(0<<5)|(0<<4)|((resource->gran - 25) << 1)|(0<<0);
/* Get the base address */
gart_base = ((resource->base) >> 25) & 0x00007fff;
/* Update the other northbriges */
pdev = 0;
while ((pdev = dev_find_device(PCI_VENDOR_ID_AMD, pci_id, pdev))) {
/* Store the GART size but don't enable it */
pci_write_config32(pdev, 0x90, gart_acr);
/* Store the GART base address */
pci_write_config32(pdev, 0x94, gart_base);
/* Don't set the GART Table base address */
pci_write_config32(pdev, 0x98, 0);
/* Report the resource has been stored... */
report_resource_stored(pdev, resource, " <gart>");
/* Errata 540 workaround */
dword = pci_read_config32(pdev, 0x90);
dword |= 0x1 << 6; /* DisGartTblWlkPrb = 0x1 */
pci_write_config32(pdev, 0x90, dword);
}
}
}
static void mcf3_set_resources_fam10h(struct device *dev)
{
/* Set the gart aperture */
set_agp_aperture(dev, 0x1203);
/* Set the generic PCI resources */
pci_dev_set_resources(dev);
}
static void mcf3_set_resources_fam15h_model10(struct device *dev)
{
/* Set the gart aperture */
set_agp_aperture(dev, 0x1403);
/* Set the generic PCI resources */
pci_dev_set_resources(dev);
}
static void mcf3_set_resources_fam15h(struct device *dev)
{
/* Set the gart aperture */
set_agp_aperture(dev, 0x1603);
/* Set the generic PCI resources */
pci_dev_set_resources(dev);
}
static void misc_control_init(struct device *dev)
{
uint32_t dword;
uint8_t nvram;
uint8_t boost_limit;
uint8_t current_boost;
printk(BIOS_DEBUG, "NB: Function 3 Misc Control.. ");
#if IS_ENABLED(CONFIG_DIMM_DDR3) && !IS_ENABLED(CONFIG_NORTHBRIDGE_AMD_AGESA)
uint8_t node;
uint8_t slot;
uint8_t dimm_present;
/* Restore DRAM MCA registers */
struct amdmct_memory_info *mem_info;
mem_info = cbmem_find(CBMEM_ID_AMDMCT_MEMINFO);
if (mem_info) {
node = PCI_SLOT(dev->path.pci.devfn) - 0x18;
/* Check node for installed DIMMs */
dimm_present = 0;
/* Check all slots for installed DIMMs */
for (slot = 0; slot < MAX_DIMMS_SUPPORTED; slot++) {
if (mem_info->dct_stat[node].DIMMPresent & (1 << slot)) {
dimm_present = 1;
break;
}
}
if (dimm_present) {
uint32_t mc4_status_high = pci_read_config32(dev, 0x4c);
uint32_t mc4_status_low = pci_read_config32(dev, 0x48);
if ((mc4_status_high & (0x1 << 31)) && (mc4_status_high != 0xffffffff)) {
printk(BIOS_WARNING, "\nWARNING: MC4 Machine Check Exception detected on node %d!\n"
"Signature: %08x%08x\n", node, mc4_status_high, mc4_status_low);
}
/* Clear MC4 error status */
pci_write_config32(dev, 0x48, 0x0);
pci_write_config32(dev, 0x4c, 0x0);
}
}
#endif
/* Disable Machine checks from Invalid Locations.
* This is needed for PC backwards compatibility.
*/
dword = pci_read_config32(dev, 0x44);
dword |= (1<<6) | (1<<25);
pci_write_config32(dev, 0x44, dword);
boost_limit = 0xf;
if (get_option(&nvram, "maximum_p_state_limit") == CB_SUCCESS)
boost_limit = nvram & 0xf;
/* Set P-state maximum value */
dword = pci_read_config32(dev, 0xdc);
current_boost = (dword >> 8) & 0x7;
if (boost_limit > current_boost)
boost_limit = current_boost;
dword &= ~(0x7 << 8);
dword |= (boost_limit & 0x7) << 8;
pci_write_config32(dev, 0xdc, dword);
printk(BIOS_DEBUG, "done.\n");
}
static struct device_operations mcf3_ops_fam10h = {
.read_resources = mcf3_read_resources,
.set_resources = mcf3_set_resources_fam10h,
.enable_resources = pci_dev_enable_resources,
.init = misc_control_init,
.scan_bus = 0,
.ops_pci = 0,
};
static struct device_operations mcf3_ops_fam15h_model10 = {
.read_resources = mcf3_read_resources,
.set_resources = mcf3_set_resources_fam15h_model10,
.enable_resources = pci_dev_enable_resources,
.init = misc_control_init,
.scan_bus = 0,
.ops_pci = 0,
};
static struct device_operations mcf3_ops_fam15h = {
.read_resources = mcf3_read_resources,
.set_resources = mcf3_set_resources_fam15h,
.enable_resources = pci_dev_enable_resources,
.init = misc_control_init,
.scan_bus = 0,
.ops_pci = 0,
};
static const struct pci_driver mcf3_driver __pci_driver = {
.ops = &mcf3_ops_fam10h,
.vendor = PCI_VENDOR_ID_AMD,
.device = 0x1203,
};
static const struct pci_driver mcf3_driver_fam15_model10 __pci_driver = {
.ops = &mcf3_ops_fam15h_model10,
.vendor = PCI_VENDOR_ID_AMD,
.device = 0x1403,
};
static const struct pci_driver mcf3_driver_fam15 __pci_driver = {
.ops = &mcf3_ops_fam15h,
.vendor = PCI_VENDOR_ID_AMD,
.device = 0x1603,
};