AMD Kabini: Add northbridge AGESA wrapper (new AMD processor)
src/arch/x86/boot/tables.c and src/include/device/pci_ids.h are also changed because these two files depend on F16kb northbridge macros Change-Id: Iedc842f0b230826675703fc78ed8001a978319c5 Reviewed-by: Marc Jones <marc.jones@se-eng.com> Signed-off-by: Bruce Griffith <Bruce.Griffith@se-eng.com> Reviewed-by: Bruce Griffith <bruce.griffith@se-eng.com> Tested-by: Bruce Griffith <bruce.griffith@se-eng.com> Reviewed-on: http://review.coreboot.org/3782 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth <martin.roth@se-eng.com>
This commit is contained in:
parent
5d7d09c4ab
commit
3e32cc00d1
|
@ -214,7 +214,7 @@ struct lb_memory *write_tables(void)
|
||||||
*/
|
*/
|
||||||
cbmem_add(CBMEM_ID_RESUME, HIGH_MEMORY_SAVE);
|
cbmem_add(CBMEM_ID_RESUME, HIGH_MEMORY_SAVE);
|
||||||
#endif
|
#endif
|
||||||
#if CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY14 || CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_TN
|
#if CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY14 || CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_TN || CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY16_KB
|
||||||
cbmem_add(CBMEM_ID_RESUME_SCRATCH, CONFIG_HIGH_SCRATCH_MEMORY_SIZE);
|
cbmem_add(CBMEM_ID_RESUME_SCRATCH, CONFIG_HIGH_SCRATCH_MEMORY_SIZE);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -286,6 +286,7 @@
|
||||||
|
|
||||||
#define PCI_DEVICE_ID_AMD_15H_MODEL_000F_NB_HT 0x1600
|
#define PCI_DEVICE_ID_AMD_15H_MODEL_000F_NB_HT 0x1600
|
||||||
#define PCI_DEVICE_ID_AMD_15H_MODEL_001F_NB_HT 0x1400
|
#define PCI_DEVICE_ID_AMD_15H_MODEL_001F_NB_HT 0x1400
|
||||||
|
#define PCI_DEVICE_ID_AMD_16H_MODEL_000F_NB_HT 0x1536
|
||||||
#define PCI_DEVICE_ID_AMD_10H_NB_HT 0x1200
|
#define PCI_DEVICE_ID_AMD_10H_NB_HT 0x1200
|
||||||
#define PCI_DEVICE_ID_AMD_15H_NB_IOMMU 0x1419
|
#define PCI_DEVICE_ID_AMD_15H_NB_IOMMU 0x1419
|
||||||
|
|
||||||
|
|
|
@ -36,5 +36,6 @@ source src/northbridge/amd/agesa/family12/Kconfig
|
||||||
source src/northbridge/amd/agesa/family14/Kconfig
|
source src/northbridge/amd/agesa/family14/Kconfig
|
||||||
source src/northbridge/amd/agesa/family15/Kconfig
|
source src/northbridge/amd/agesa/family15/Kconfig
|
||||||
source src/northbridge/amd/agesa/family15tn/Kconfig
|
source src/northbridge/amd/agesa/family15tn/Kconfig
|
||||||
|
source src/northbridge/amd/agesa/family16kb/Kconfig
|
||||||
|
|
||||||
endif # NORTHBRIDGE_AMD_AGESA
|
endif # NORTHBRIDGE_AMD_AGESA
|
||||||
|
|
|
@ -21,3 +21,4 @@ subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY12) += family12
|
||||||
subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY14) += family14
|
subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY14) += family14
|
||||||
subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15) += family15
|
subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15) += family15
|
||||||
subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_TN) += family15tn
|
subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY15_TN) += family15tn
|
||||||
|
subdirs-$(CONFIG_NORTHBRIDGE_AMD_AGESA_FAMILY16_KB) += family16kb
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
##
|
||||||
|
## This file is part of the coreboot project.
|
||||||
|
##
|
||||||
|
## Copyright (C) 2007-2009 coresystems GmbH
|
||||||
|
##
|
||||||
|
## 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.
|
||||||
|
##
|
||||||
|
## You should have received a copy of the GNU General Public License
|
||||||
|
## along with this program; if not, write to the Free Software
|
||||||
|
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
##
|
||||||
|
config NORTHBRIDGE_AMD_AGESA_FAMILY16_KB
|
||||||
|
bool
|
||||||
|
select MMCONF_SUPPORT
|
||||||
|
|
||||||
|
if NORTHBRIDGE_AMD_AGESA_FAMILY16_KB
|
||||||
|
|
||||||
|
config HW_MEM_HOLE_SIZEK
|
||||||
|
hex
|
||||||
|
default 0x100000
|
||||||
|
|
||||||
|
config HW_MEM_HOLE_SIZE_AUTO_INC
|
||||||
|
bool
|
||||||
|
default n
|
||||||
|
|
||||||
|
config MMCONF_BASE_ADDRESS
|
||||||
|
hex
|
||||||
|
default 0xA0000000
|
||||||
|
|
||||||
|
config MMCONF_BUS_NUMBER
|
||||||
|
int
|
||||||
|
default 256
|
||||||
|
|
||||||
|
endif
|
|
@ -0,0 +1,25 @@
|
||||||
|
#
|
||||||
|
# This file is part of the coreboot project.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2012 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.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
#
|
||||||
|
|
||||||
|
romstage-y += fam16kb_callouts.c
|
||||||
|
romstage-y += dimmSpd.c
|
||||||
|
|
||||||
|
ramstage-y += northbridge.c
|
||||||
|
ramstage-y += fam16kb_callouts.c
|
||||||
|
ramstage-y += dimmSpd.c
|
|
@ -0,0 +1,302 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No includes in this file because it is included into northbridge.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct dram_base_mask_t {
|
||||||
|
u32 base; //[47:27] at [28:8]
|
||||||
|
u32 mask; //[47:27] at [28:8] and enable at bit 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dram_base_mask_t get_dram_base_mask(u32 nodeid)
|
||||||
|
{
|
||||||
|
device_t dev;
|
||||||
|
struct dram_base_mask_t d;
|
||||||
|
#if defined(__PRE_RAM__)
|
||||||
|
dev = PCI_DEV(CONFIG_CBB, CONFIG_CDB, 1);
|
||||||
|
#else
|
||||||
|
dev = __f1_dev[0];
|
||||||
|
#endif // defined(__PRE_RAM__)
|
||||||
|
|
||||||
|
u32 temp;
|
||||||
|
temp = pci_read_config32(dev, 0x44); //[39:24] at [31:16]
|
||||||
|
d.mask = (temp & 0xffff0000); // mask out DramMask [26:24] too
|
||||||
|
|
||||||
|
temp = pci_read_config32(dev, 0x40); //[35:24] at [27:16]
|
||||||
|
d.mask |= (temp & 1); // read enable bit
|
||||||
|
|
||||||
|
d.base = (temp & 0x0fff0000); // mask out DramBase [26:24) too
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_EXT_CONF_SUPPORT
|
||||||
|
static void set_addr_map_reg_4_6_in_one_node(u32 nodeid, u32 cfg_map_dest,
|
||||||
|
u32 busn_min, u32 busn_max,
|
||||||
|
u32 type)
|
||||||
|
{
|
||||||
|
device_t dev;
|
||||||
|
u32 i;
|
||||||
|
u32 tempreg;
|
||||||
|
u32 index_min, index_max;
|
||||||
|
u32 dest_min, dest_max;
|
||||||
|
index_min = busn_min>>2; dest_min = busn_min - (index_min<<2);
|
||||||
|
index_max = busn_max>>2; dest_max = busn_max - (index_max<<2);
|
||||||
|
|
||||||
|
// three case: index_min==index_max, index_min+1=index_max; index_min+1<index_max
|
||||||
|
#if defined(__PRE_RAM__)
|
||||||
|
dev = NODE_PCI(nodeid, 1);
|
||||||
|
#else
|
||||||
|
dev = __f1_dev[nodeid];
|
||||||
|
#endif // defined(__PRE_RAM__)
|
||||||
|
if(index_min== index_max) {
|
||||||
|
pci_write_config32(dev, 0x110, index_min | (type<<28));
|
||||||
|
tempreg = pci_read_config32(dev, 0x114);
|
||||||
|
for(i=dest_min; i<=dest_max; i++) {
|
||||||
|
tempreg &= ~(0xff<<(i*8));
|
||||||
|
tempreg |= (cfg_map_dest<<(i*8));
|
||||||
|
}
|
||||||
|
pci_write_config32(dev, 0x110, index_min | (type<<28)); // do i need to write it again
|
||||||
|
pci_write_config32(dev, 0x114, tempreg);
|
||||||
|
} else if(index_min<index_max) {
|
||||||
|
pci_write_config32(dev, 0x110, index_min | (type<<28));
|
||||||
|
tempreg = pci_read_config32(dev, 0x114);
|
||||||
|
for(i=dest_min; i<=3; i++) {
|
||||||
|
tempreg &= ~(0xff<<(i*8));
|
||||||
|
tempreg |= (cfg_map_dest<<(i*8));
|
||||||
|
}
|
||||||
|
pci_write_config32(dev, 0x110, index_min | (type<<28)); // do i need to write it again
|
||||||
|
pci_write_config32(dev, 0x114, tempreg);
|
||||||
|
|
||||||
|
pci_write_config32(dev, 0x110, index_max | (type<<28));
|
||||||
|
tempreg = pci_read_config32(dev, 0x114);
|
||||||
|
for(i=0; i<=dest_max; i++) {
|
||||||
|
tempreg &= ~(0xff<<(i*8));
|
||||||
|
tempreg |= (cfg_map_dest<<(i*8));
|
||||||
|
}
|
||||||
|
pci_write_config32(dev, 0x110, index_max | (type<<28)); // do i need to write it again
|
||||||
|
pci_write_config32(dev, 0x114, tempreg);
|
||||||
|
if((index_max-index_min)>1) {
|
||||||
|
tempreg = 0;
|
||||||
|
for(i=0; i<=3; i++) {
|
||||||
|
tempreg &= ~(0xff<<(i*8));
|
||||||
|
tempreg |= (cfg_map_dest<<(i*8));
|
||||||
|
}
|
||||||
|
for(i=index_min+1; i<index_max;i++) {
|
||||||
|
pci_write_config32(dev, 0x110, i | (type<<28));
|
||||||
|
pci_write_config32(dev, 0x114, tempreg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // CONFIG_EXT_CONF_SUPPORT
|
||||||
|
|
||||||
|
#if defined(__PRE_RAM__)
|
||||||
|
static void set_ht_c_io_addr_reg(u32 nodeid, u32 linkn, u32 ht_c_index,
|
||||||
|
u32 io_min, u32 io_max, u32 nodes)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
u32 tempreg;
|
||||||
|
device_t dev;
|
||||||
|
|
||||||
|
#if CONFIG_EXT_CONF_SUPPORT
|
||||||
|
if(ht_c_index<4) {
|
||||||
|
#endif
|
||||||
|
/* io range allocation */
|
||||||
|
tempreg = (nodeid&0xf) | ((nodeid & 0x30)<<(8-4)) | (linkn<<4) | ((io_max&0xf0)<<(12-4)); //limit
|
||||||
|
for(i=0; i<nodes; i++) {
|
||||||
|
dev = NODE_PCI(i, 1);
|
||||||
|
pci_write_config32(dev, 0xC4 + ht_c_index * 8, tempreg);
|
||||||
|
}
|
||||||
|
tempreg = 3 /*| ( 3<<4)*/ | ((io_min&0xf0)<<(12-4)); //base :ISA and VGA ?
|
||||||
|
for(i=0; i<nodes; i++){
|
||||||
|
dev = NODE_PCI(i, 1);
|
||||||
|
pci_write_config32(dev, 0xC0 + ht_c_index * 8, tempreg);
|
||||||
|
}
|
||||||
|
#if CONFIG_EXT_CONF_SUPPORT
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 cfg_map_dest;
|
||||||
|
u32 j;
|
||||||
|
|
||||||
|
// if ht_c_index > 3, We should use extend space
|
||||||
|
|
||||||
|
if(io_min>io_max) return;
|
||||||
|
|
||||||
|
// for nodeid at first
|
||||||
|
cfg_map_dest = (1<<7) | (1<<6) | (linkn<<0);
|
||||||
|
|
||||||
|
set_addr_map_reg_4_6_in_one_node(nodeid, cfg_map_dest, io_min, io_max, 4);
|
||||||
|
|
||||||
|
// all other nodes
|
||||||
|
cfg_map_dest = (1<<7) | (0<<6) | (nodeid<<0);
|
||||||
|
for(j = 0; j< nodes; j++) {
|
||||||
|
if(j== nodeid) continue;
|
||||||
|
set_addr_map_reg_4_6_in_one_node(j,cfg_map_dest, io_min, io_max, 4);
|
||||||
|
}
|
||||||
|
#endif // CONFIG_EXT_CONF_SUPPORT
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_ht_c_io_addr_reg(u32 nodeid, u32 linkn, u32 ht_c_index,
|
||||||
|
u32 io_min, u32 io_max, u32 nodes)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
device_t dev;
|
||||||
|
#if CONFIG_EXT_CONF_SUPPORT
|
||||||
|
if(ht_c_index<4) {
|
||||||
|
#endif
|
||||||
|
/* io range allocation */
|
||||||
|
for(i=0; i<nodes; i++) {
|
||||||
|
dev = NODE_PCI(i, 1);
|
||||||
|
pci_write_config32(dev, 0xC4 + ht_c_index * 8, 0);
|
||||||
|
pci_write_config32(dev, 0xC0 + ht_c_index * 8, 0);
|
||||||
|
}
|
||||||
|
#if CONFIG_EXT_CONF_SUPPORT
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// : if hc_c_index > 3, We should use io_min, io_max to clear extend space
|
||||||
|
u32 cfg_map_dest;
|
||||||
|
u32 j;
|
||||||
|
|
||||||
|
// all nodes
|
||||||
|
cfg_map_dest = 0;
|
||||||
|
for(j = 0; j< nodes; j++) {
|
||||||
|
set_addr_map_reg_4_6_in_one_node(j,cfg_map_dest, io_min, io_max, 4);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif // defined(__PRE_RAM__)
|
||||||
|
|
||||||
|
#if !defined(__PRE_RAM__)
|
||||||
|
static u32 get_io_addr_index(u32 nodeid, u32 linkn)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
u32 index;
|
||||||
|
|
||||||
|
for(index=0; index<256; index++) {
|
||||||
|
if((sysconf.conf_io_addrx[index+4] == 0)){
|
||||||
|
sysconf.conf_io_addr[index+4] = (nodeid & 0x3f) ;
|
||||||
|
sysconf.conf_io_addrx[index+4] = 1 | ((linkn & 0x7)<<4);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 get_mmio_addr_index(u32 nodeid, u32 linkn)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
u32 index;
|
||||||
|
|
||||||
|
for(index=0; index<64; index++) {
|
||||||
|
if((sysconf.conf_mmio_addrx[index+8] == 0)){
|
||||||
|
sysconf.conf_mmio_addr[index+8] = (nodeid & 0x3f) ;
|
||||||
|
sysconf.conf_mmio_addrx[index+8] = 1 | ((linkn & 0x7)<<4);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_io_addr_reg(device_t dev, u32 nodeid, u32 linkn, u32 reg,
|
||||||
|
u32 io_min, u32 io_max)
|
||||||
|
{
|
||||||
|
|
||||||
|
u32 tempreg;
|
||||||
|
#if CONFIG_EXT_CONF_SUPPORT
|
||||||
|
if(reg!=0x110) {
|
||||||
|
#endif
|
||||||
|
/* io range allocation */
|
||||||
|
tempreg = (nodeid&0xf) | ((nodeid & 0x30)<<(8-4)) | (linkn<<4) | ((io_max&0xf0)<<(12-4)); //limit
|
||||||
|
pci_write_config32(__f1_dev[0], reg+4, tempreg);
|
||||||
|
|
||||||
|
tempreg = 3 /*| ( 3<<4)*/ | ((io_min&0xf0)<<(12-4)); //base :ISA and VGA ?
|
||||||
|
#if 0
|
||||||
|
// FIXME: can we use VGA reg instead?
|
||||||
|
if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
|
||||||
|
printk(BIOS_SPEW, "%s, enabling legacy VGA IO forwarding for %s link %s\n",
|
||||||
|
__func__, dev_path(dev), link);
|
||||||
|
tempreg |= PCI_IO_BASE_VGA_EN;
|
||||||
|
}
|
||||||
|
if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_NO_ISA) {
|
||||||
|
tempreg |= PCI_IO_BASE_NO_ISA;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
pci_write_config32(__f1_dev[0], reg, tempreg);
|
||||||
|
#if CONFIG_EXT_CONF_SUPPORT
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 cfg_map_dest;
|
||||||
|
u32 j;
|
||||||
|
// if ht_c_index > 3, We should use extend space
|
||||||
|
if(io_min>io_max) return;
|
||||||
|
// for nodeid at first
|
||||||
|
cfg_map_dest = (1<<7) | (1<<6) | (linkn<<0);
|
||||||
|
|
||||||
|
set_addr_map_reg_4_6_in_one_node(nodeid, cfg_map_dest, io_min, io_max, 4);
|
||||||
|
#endif // CONFIG_EXT_CONF_SUPPORT
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index, u32 mmio_min, u32 mmio_max, u32 nodes)
|
||||||
|
{
|
||||||
|
|
||||||
|
u32 tempreg;
|
||||||
|
#if CONFIG_EXT_CONF_SUPPORT
|
||||||
|
if(reg!=0x110) {
|
||||||
|
#endif
|
||||||
|
/* io range allocation */
|
||||||
|
tempreg = (nodeid&0xf) | (linkn<<4) | (mmio_max&0xffffff00); //limit
|
||||||
|
pci_write_config32(__f1_dev[0], reg+4, tempreg);
|
||||||
|
tempreg = 3 | (nodeid & 0x30) | (mmio_min&0xffffff00);
|
||||||
|
pci_write_config32(__f1_dev[0], reg, tempreg);
|
||||||
|
#if CONFIG_EXT_CONF_SUPPORT
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_t dev;
|
||||||
|
u32 j;
|
||||||
|
// if ht_c_index > 3, We should use extend space
|
||||||
|
// for nodeid at first
|
||||||
|
u32 enable;
|
||||||
|
|
||||||
|
if(mmio_min>mmio_max) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
enable = 1;
|
||||||
|
|
||||||
|
dev = __f1_dev[nodeid];
|
||||||
|
tempreg = ((mmio_min>>3) & 0x1fffff00)| (1<<6) | (linkn<<0);
|
||||||
|
pci_write_config32(dev, 0x110, index | (2<<28));
|
||||||
|
pci_write_config32(dev, 0x114, tempreg);
|
||||||
|
|
||||||
|
tempreg = ((mmio_max>>3) & 0x1fffff00) | enable;
|
||||||
|
pci_write_config32(dev, 0x110, index | (3<<28));
|
||||||
|
pci_write_config32(dev, 0x114, tempreg);
|
||||||
|
#endif // CONFIG_EXT_CONF_SUPPORT
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !defined(__PRE_RAM__)
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Sage Electronic Engineering, LLC
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _AGESA_FAM16KB_CHIP_H_
|
||||||
|
#define _AGESA_FAM16KB_CHIP_H_
|
||||||
|
|
||||||
|
struct northbridge_amd_agesa_family16kb_config
|
||||||
|
{
|
||||||
|
u8 spdAddrLookup[2][2][4];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <device/pci_def.h>
|
||||||
|
#include <device/device.h>
|
||||||
|
|
||||||
|
/* warning: Porting.h includes an open #pragma pack(1) */
|
||||||
|
#include "Porting.h"
|
||||||
|
#include "AGESA.h"
|
||||||
|
#include "amdlib.h"
|
||||||
|
#include "dimmSpd.h"
|
||||||
|
#include "chip.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define DIMENSION(array)(sizeof (array)/ sizeof (array [0]))
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* readSmbusByteData - read a single SPD byte from any offset
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int readSmbusByteData (int iobase, int address, char *buffer, int offset)
|
||||||
|
{
|
||||||
|
unsigned int status;
|
||||||
|
UINT64 limit;
|
||||||
|
|
||||||
|
address |= 1; // set read bit
|
||||||
|
|
||||||
|
__outbyte (iobase + 0, 0xFF); // clear error status
|
||||||
|
__outbyte (iobase + 1, 0x1F); // clear error status
|
||||||
|
__outbyte (iobase + 3, offset); // offset in eeprom
|
||||||
|
__outbyte (iobase + 4, address); // slave address and read bit
|
||||||
|
__outbyte (iobase + 2, 0x48); // read byte command
|
||||||
|
|
||||||
|
// time limit to avoid hanging for unexpected error status (should never happen)
|
||||||
|
limit = __rdtsc () + 2000000000 / 10;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
status = __inbyte (iobase);
|
||||||
|
if (__rdtsc () > limit) break;
|
||||||
|
if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
|
||||||
|
if ((status & 1) == 1) continue; // HostBusy set, keep waiting
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer [0] = __inbyte (iobase + 5);
|
||||||
|
if (status == 2) status = 0; // check for done with no errors
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* readSmbusByte - read a single SPD byte from the default offset
|
||||||
|
* this function is faster function readSmbusByteData
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int readSmbusByte (int iobase, int address, char *buffer)
|
||||||
|
{
|
||||||
|
unsigned int status;
|
||||||
|
UINT64 limit;
|
||||||
|
|
||||||
|
__outbyte (iobase + 0, 0xFF); // clear error status
|
||||||
|
__outbyte (iobase + 2, 0x44); // read command
|
||||||
|
|
||||||
|
// time limit to avoid hanging for unexpected error status
|
||||||
|
limit = __rdtsc () + 2000000000 / 10;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
status = __inbyte (iobase);
|
||||||
|
if (__rdtsc () > limit) break;
|
||||||
|
if ((status & 2) == 0) continue; // SMBusInterrupt not set, keep waiting
|
||||||
|
if ((status & 1) == 1) continue; // HostBusy set, keep waiting
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer [0] = __inbyte (iobase + 5);
|
||||||
|
if (status == 2) status = 0; // check for done with no errors
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* readspd - Read one or more SPD bytes from a DIMM.
|
||||||
|
* Start with offset zero and read sequentially.
|
||||||
|
* Optimization relies on autoincrement to avoid
|
||||||
|
* sending offset for every byte.
|
||||||
|
* Reads 128 bytes in 7-8 ms at 400 KHz.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int readspd (int iobase, int SmbusSlaveAddress, char *buffer, int count)
|
||||||
|
{
|
||||||
|
int index, error;
|
||||||
|
|
||||||
|
/* read the first byte using offset zero */
|
||||||
|
error = readSmbusByteData (iobase, SmbusSlaveAddress, buffer, 0);
|
||||||
|
if (error) return error;
|
||||||
|
|
||||||
|
/* read the remaining bytes using auto-increment for speed */
|
||||||
|
for (index = 1; index < count; index++)
|
||||||
|
{
|
||||||
|
error = readSmbusByte (iobase, SmbusSlaveAddress, &buffer [index]);
|
||||||
|
if (error) return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writePmReg (int reg, int data)
|
||||||
|
{
|
||||||
|
__outbyte (0xCD6, reg);
|
||||||
|
__outbyte (0xCD7, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setupFch (int ioBase)
|
||||||
|
{
|
||||||
|
writePmReg (0x2D, ioBase >> 8);
|
||||||
|
writePmReg (0x2C, ioBase | 1);
|
||||||
|
__outbyte (ioBase + 0x0E, 66000000 / 400000 / 4); // set SMBus clock to 400 KHz
|
||||||
|
}
|
||||||
|
|
||||||
|
AGESA_STATUS AmdMemoryReadSPD (UINT32 unused1, UINT32 unused2, AGESA_READ_SPD_PARAMS *info)
|
||||||
|
{
|
||||||
|
int spdAddress, ioBase;
|
||||||
|
ROMSTAGE_CONST struct device *dev = dev_find_slot(0, PCI_DEVFN(0x18, 2));
|
||||||
|
ROMSTAGE_CONST struct northbridge_amd_agesa_family16kb_config *config = dev->chip_info;
|
||||||
|
|
||||||
|
if ((dev == 0) || (config == 0))
|
||||||
|
return AGESA_ERROR;
|
||||||
|
|
||||||
|
if (info->SocketId >= DIMENSION(config->spdAddrLookup ))
|
||||||
|
return AGESA_ERROR;
|
||||||
|
if (info->MemChannelId >= DIMENSION(config->spdAddrLookup[0] ))
|
||||||
|
return AGESA_ERROR;
|
||||||
|
if (info->DimmId >= DIMENSION(config->spdAddrLookup[0][0]))
|
||||||
|
return AGESA_ERROR;
|
||||||
|
|
||||||
|
spdAddress = config->spdAddrLookup
|
||||||
|
[info->SocketId] [info->MemChannelId] [info->DimmId];
|
||||||
|
|
||||||
|
if (spdAddress == 0) return AGESA_ERROR;
|
||||||
|
ioBase = 0xB00;
|
||||||
|
setupFch (ioBase);
|
||||||
|
return readspd (ioBase, spdAddress, (void *) info->Buffer, 128);
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------------------
|
||||||
|
* M O D U L E S U S E D
|
||||||
|
*----------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DIMMSPD_H_
|
||||||
|
#define _DIMMSPD_H_
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------------------
|
||||||
|
* D E F I N I T I O N S A N D M A C R O S
|
||||||
|
*----------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------------------
|
||||||
|
* T Y P E D E F S A N D S T R U C T U R E S
|
||||||
|
*----------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------------------
|
||||||
|
* P R O T O T Y P E S O F L O C A L F U N C T I O N S
|
||||||
|
*----------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------------------
|
||||||
|
* E X P O R T E D F U N C T I O N S
|
||||||
|
*----------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
AGESA_STATUS
|
||||||
|
AmdMemoryReadSPD (IN UINT32 Func, IN UINT32 Data, IN OUT AGESA_READ_SPD_PARAMS *SpdData);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------------
|
||||||
|
* L O C A L F U N C T I O N S
|
||||||
|
*---------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,415 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "agesawrapper.h"
|
||||||
|
#include "amdlib.h"
|
||||||
|
#include "Ids.h"
|
||||||
|
#include "OptionsIds.h"
|
||||||
|
#include "heapManager.h"
|
||||||
|
#include "FchPlatform.h"
|
||||||
|
#include "cbfs.h"
|
||||||
|
#include "dimmSpd.h"
|
||||||
|
#include "fam16kb_callouts.h"
|
||||||
|
|
||||||
|
AGESA_STATUS fam16kb_AllocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
|
||||||
|
{
|
||||||
|
UINT32 AvailableHeapSize;
|
||||||
|
UINT8 *BiosHeapBaseAddr;
|
||||||
|
UINT32 CurrNodeOffset;
|
||||||
|
UINT32 PrevNodeOffset;
|
||||||
|
UINT32 FreedNodeOffset;
|
||||||
|
UINT32 BestFitNodeOffset;
|
||||||
|
UINT32 BestFitPrevNodeOffset;
|
||||||
|
UINT32 NextFreeOffset;
|
||||||
|
BIOS_BUFFER_NODE *CurrNodePtr;
|
||||||
|
BIOS_BUFFER_NODE *FreedNodePtr;
|
||||||
|
BIOS_BUFFER_NODE *BestFitNodePtr;
|
||||||
|
BIOS_BUFFER_NODE *BestFitPrevNodePtr;
|
||||||
|
BIOS_BUFFER_NODE *NextFreePtr;
|
||||||
|
BIOS_HEAP_MANAGER *BiosHeapBasePtr;
|
||||||
|
AGESA_BUFFER_PARAMS *AllocParams;
|
||||||
|
|
||||||
|
AllocParams = ((AGESA_BUFFER_PARAMS *) ConfigPtr);
|
||||||
|
AllocParams->BufferPointer = NULL;
|
||||||
|
|
||||||
|
AvailableHeapSize = BIOS_HEAP_SIZE - sizeof (BIOS_HEAP_MANAGER);
|
||||||
|
BiosHeapBaseAddr = (UINT8 *) GetHeapBase(&(AllocParams->StdHeader));
|
||||||
|
BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BiosHeapBaseAddr;
|
||||||
|
|
||||||
|
if (BiosHeapBasePtr->StartOfAllocatedNodes == 0) {
|
||||||
|
/* First allocation */
|
||||||
|
CurrNodeOffset = sizeof (BIOS_HEAP_MANAGER);
|
||||||
|
CurrNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + CurrNodeOffset);
|
||||||
|
CurrNodePtr->BufferHandle = AllocParams->BufferHandle;
|
||||||
|
CurrNodePtr->BufferSize = AllocParams->BufferLength;
|
||||||
|
CurrNodePtr->NextNodeOffset = 0;
|
||||||
|
AllocParams->BufferPointer = (UINT8 *) CurrNodePtr + sizeof (BIOS_BUFFER_NODE);
|
||||||
|
|
||||||
|
/* Update the remaining free space */
|
||||||
|
FreedNodeOffset = CurrNodeOffset + CurrNodePtr->BufferSize + sizeof (BIOS_BUFFER_NODE);
|
||||||
|
FreedNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + FreedNodeOffset);
|
||||||
|
FreedNodePtr->BufferSize = AvailableHeapSize - sizeof (BIOS_BUFFER_NODE) - CurrNodePtr->BufferSize;
|
||||||
|
FreedNodePtr->NextNodeOffset = 0;
|
||||||
|
|
||||||
|
/* Update the offsets for Allocated and Freed nodes */
|
||||||
|
BiosHeapBasePtr->StartOfAllocatedNodes = CurrNodeOffset;
|
||||||
|
BiosHeapBasePtr->StartOfFreedNodes = FreedNodeOffset;
|
||||||
|
} else {
|
||||||
|
/* Find out whether BufferHandle has been allocated on the heap. */
|
||||||
|
/* If it has, return AGESA_BOUNDS_CHK */
|
||||||
|
CurrNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
|
||||||
|
CurrNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + CurrNodeOffset);
|
||||||
|
|
||||||
|
while (CurrNodeOffset != 0) {
|
||||||
|
CurrNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + CurrNodeOffset);
|
||||||
|
if (CurrNodePtr->BufferHandle == AllocParams->BufferHandle) {
|
||||||
|
return AGESA_BOUNDS_CHK;
|
||||||
|
}
|
||||||
|
CurrNodeOffset = CurrNodePtr->NextNodeOffset;
|
||||||
|
/* If BufferHandle has not been allocated on the heap, CurrNodePtr here points
|
||||||
|
to the end of the allocated nodes list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
/* Find the node that best fits the requested buffer size */
|
||||||
|
FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes;
|
||||||
|
PrevNodeOffset = FreedNodeOffset;
|
||||||
|
BestFitNodeOffset = 0;
|
||||||
|
BestFitPrevNodeOffset = 0;
|
||||||
|
while (FreedNodeOffset != 0) {
|
||||||
|
FreedNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + FreedNodeOffset);
|
||||||
|
if (FreedNodePtr->BufferSize >= (AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE))) {
|
||||||
|
if (BestFitNodeOffset == 0) {
|
||||||
|
/* First node that fits the requested buffer size */
|
||||||
|
BestFitNodeOffset = FreedNodeOffset;
|
||||||
|
BestFitPrevNodeOffset = PrevNodeOffset;
|
||||||
|
} else {
|
||||||
|
/* Find out whether current node is a better fit than the previous nodes */
|
||||||
|
BestFitNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + BestFitNodeOffset);
|
||||||
|
if (BestFitNodePtr->BufferSize > FreedNodePtr->BufferSize) {
|
||||||
|
BestFitNodeOffset = FreedNodeOffset;
|
||||||
|
BestFitPrevNodeOffset = PrevNodeOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PrevNodeOffset = FreedNodeOffset;
|
||||||
|
FreedNodeOffset = FreedNodePtr->NextNodeOffset;
|
||||||
|
} /* end of while loop */
|
||||||
|
|
||||||
|
if (BestFitNodeOffset == 0) {
|
||||||
|
/* If we could not find a node that fits the requested buffer */
|
||||||
|
/* size, return AGESA_BOUNDS_CHK */
|
||||||
|
return AGESA_BOUNDS_CHK;
|
||||||
|
} else {
|
||||||
|
BestFitNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + BestFitNodeOffset);
|
||||||
|
BestFitPrevNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + BestFitPrevNodeOffset);
|
||||||
|
|
||||||
|
/* If BestFitNode is larger than the requested buffer, fragment the node further */
|
||||||
|
if (BestFitNodePtr->BufferSize > (AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE))) {
|
||||||
|
NextFreeOffset = BestFitNodeOffset + AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE);
|
||||||
|
|
||||||
|
NextFreePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + NextFreeOffset);
|
||||||
|
NextFreePtr->BufferSize = BestFitNodePtr->BufferSize - (AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE));
|
||||||
|
NextFreePtr->NextNodeOffset = BestFitNodePtr->NextNodeOffset;
|
||||||
|
} else {
|
||||||
|
/* Otherwise, next free node is NextNodeOffset of BestFitNode */
|
||||||
|
NextFreeOffset = BestFitNodePtr->NextNodeOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If BestFitNode is the first buffer in the list, then update
|
||||||
|
StartOfFreedNodes to reflect the new free node
|
||||||
|
*/
|
||||||
|
if (BestFitNodeOffset == BiosHeapBasePtr->StartOfFreedNodes) {
|
||||||
|
BiosHeapBasePtr->StartOfFreedNodes = NextFreeOffset;
|
||||||
|
} else {
|
||||||
|
BestFitPrevNodePtr->NextNodeOffset = NextFreeOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add BestFitNode to the list of Allocated nodes */
|
||||||
|
CurrNodePtr->NextNodeOffset = BestFitNodeOffset;
|
||||||
|
BestFitNodePtr->BufferSize = AllocParams->BufferLength;
|
||||||
|
BestFitNodePtr->BufferHandle = AllocParams->BufferHandle;
|
||||||
|
BestFitNodePtr->NextNodeOffset = 0;
|
||||||
|
|
||||||
|
/* Remove BestFitNode from list of Freed nodes */
|
||||||
|
AllocParams->BufferPointer = (UINT8 *) BestFitNodePtr + sizeof (BIOS_BUFFER_NODE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AGESA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
AGESA_STATUS fam16kb_DeallocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
|
||||||
|
{
|
||||||
|
|
||||||
|
UINT8 *BiosHeapBaseAddr;
|
||||||
|
UINT32 AllocNodeOffset;
|
||||||
|
UINT32 PrevNodeOffset;
|
||||||
|
UINT32 NextNodeOffset;
|
||||||
|
UINT32 FreedNodeOffset;
|
||||||
|
UINT32 EndNodeOffset;
|
||||||
|
BIOS_BUFFER_NODE *AllocNodePtr;
|
||||||
|
BIOS_BUFFER_NODE *PrevNodePtr;
|
||||||
|
BIOS_BUFFER_NODE *FreedNodePtr;
|
||||||
|
BIOS_BUFFER_NODE *NextNodePtr;
|
||||||
|
BIOS_HEAP_MANAGER *BiosHeapBasePtr;
|
||||||
|
AGESA_BUFFER_PARAMS *AllocParams;
|
||||||
|
|
||||||
|
AllocParams = (AGESA_BUFFER_PARAMS *) ConfigPtr;
|
||||||
|
|
||||||
|
BiosHeapBaseAddr = (UINT8 *) GetHeapBase(&(AllocParams->StdHeader));
|
||||||
|
BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BiosHeapBaseAddr;
|
||||||
|
|
||||||
|
/* Find target node to deallocate in list of allocated nodes.
|
||||||
|
Return AGESA_BOUNDS_CHK if the BufferHandle is not found
|
||||||
|
*/
|
||||||
|
AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
|
||||||
|
AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
|
||||||
|
PrevNodeOffset = AllocNodeOffset;
|
||||||
|
|
||||||
|
while (AllocNodePtr->BufferHandle != AllocParams->BufferHandle) {
|
||||||
|
if (AllocNodePtr->NextNodeOffset == 0) {
|
||||||
|
return AGESA_BOUNDS_CHK;
|
||||||
|
}
|
||||||
|
PrevNodeOffset = AllocNodeOffset;
|
||||||
|
AllocNodeOffset = AllocNodePtr->NextNodeOffset;
|
||||||
|
AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove target node from list of allocated nodes */
|
||||||
|
PrevNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + PrevNodeOffset);
|
||||||
|
PrevNodePtr->NextNodeOffset = AllocNodePtr->NextNodeOffset;
|
||||||
|
|
||||||
|
/* Zero out the buffer, and clear the BufferHandle */
|
||||||
|
LibAmdMemFill ((UINT8 *)AllocNodePtr + sizeof (BIOS_BUFFER_NODE), 0, AllocNodePtr->BufferSize, &(AllocParams->StdHeader));
|
||||||
|
AllocNodePtr->BufferHandle = 0;
|
||||||
|
AllocNodePtr->BufferSize += sizeof (BIOS_BUFFER_NODE);
|
||||||
|
|
||||||
|
/* Add deallocated node in order to the list of freed nodes */
|
||||||
|
FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes;
|
||||||
|
FreedNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + FreedNodeOffset);
|
||||||
|
|
||||||
|
EndNodeOffset = AllocNodeOffset + AllocNodePtr->BufferSize;
|
||||||
|
|
||||||
|
if (AllocNodeOffset < FreedNodeOffset) {
|
||||||
|
/* Add to the start of the freed list */
|
||||||
|
if (EndNodeOffset == FreedNodeOffset) {
|
||||||
|
/* If the freed node is adjacent to the first node in the list, concatenate both nodes */
|
||||||
|
AllocNodePtr->BufferSize += FreedNodePtr->BufferSize;
|
||||||
|
AllocNodePtr->NextNodeOffset = FreedNodePtr->NextNodeOffset;
|
||||||
|
|
||||||
|
/* Clear the BufferSize and NextNodeOffset of the previous first node */
|
||||||
|
FreedNodePtr->BufferSize = 0;
|
||||||
|
FreedNodePtr->NextNodeOffset = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* Otherwise, add freed node to the start of the list
|
||||||
|
Update NextNodeOffset and BufferSize to include the
|
||||||
|
size of BIOS_BUFFER_NODE
|
||||||
|
*/
|
||||||
|
AllocNodePtr->NextNodeOffset = FreedNodeOffset;
|
||||||
|
}
|
||||||
|
/* Update StartOfFreedNodes to the new first node */
|
||||||
|
BiosHeapBasePtr->StartOfFreedNodes = AllocNodeOffset;
|
||||||
|
} else {
|
||||||
|
/* Traverse list of freed nodes to find where the deallocated node
|
||||||
|
should be place
|
||||||
|
*/
|
||||||
|
NextNodeOffset = FreedNodeOffset;
|
||||||
|
NextNodePtr = FreedNodePtr;
|
||||||
|
while (AllocNodeOffset > NextNodeOffset) {
|
||||||
|
PrevNodeOffset = NextNodeOffset;
|
||||||
|
if (NextNodePtr->NextNodeOffset == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
NextNodeOffset = NextNodePtr->NextNodeOffset;
|
||||||
|
NextNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + NextNodeOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If deallocated node is adjacent to the next node,
|
||||||
|
concatenate both nodes
|
||||||
|
*/
|
||||||
|
if (NextNodeOffset == EndNodeOffset) {
|
||||||
|
NextNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + NextNodeOffset);
|
||||||
|
AllocNodePtr->BufferSize += NextNodePtr->BufferSize;
|
||||||
|
AllocNodePtr->NextNodeOffset = NextNodePtr->NextNodeOffset;
|
||||||
|
|
||||||
|
NextNodePtr->BufferSize = 0;
|
||||||
|
NextNodePtr->NextNodeOffset = 0;
|
||||||
|
} else {
|
||||||
|
/*AllocNodePtr->NextNodeOffset = FreedNodePtr->NextNodeOffset; */
|
||||||
|
AllocNodePtr->NextNodeOffset = NextNodeOffset;
|
||||||
|
}
|
||||||
|
/* If deallocated node is adjacent to the previous node,
|
||||||
|
concatenate both nodes
|
||||||
|
*/
|
||||||
|
PrevNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + PrevNodeOffset);
|
||||||
|
EndNodeOffset = PrevNodeOffset + PrevNodePtr->BufferSize;
|
||||||
|
if (AllocNodeOffset == EndNodeOffset) {
|
||||||
|
PrevNodePtr->NextNodeOffset = AllocNodePtr->NextNodeOffset;
|
||||||
|
PrevNodePtr->BufferSize += AllocNodePtr->BufferSize;
|
||||||
|
|
||||||
|
AllocNodePtr->BufferSize = 0;
|
||||||
|
AllocNodePtr->NextNodeOffset = 0;
|
||||||
|
} else {
|
||||||
|
PrevNodePtr->NextNodeOffset = AllocNodeOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AGESA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
AGESA_STATUS fam16kb_LocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
|
||||||
|
{
|
||||||
|
UINT32 AllocNodeOffset;
|
||||||
|
UINT8 *BiosHeapBaseAddr;
|
||||||
|
BIOS_BUFFER_NODE *AllocNodePtr;
|
||||||
|
BIOS_HEAP_MANAGER *BiosHeapBasePtr;
|
||||||
|
AGESA_BUFFER_PARAMS *AllocParams;
|
||||||
|
|
||||||
|
AllocParams = (AGESA_BUFFER_PARAMS *) ConfigPtr;
|
||||||
|
|
||||||
|
BiosHeapBaseAddr = (UINT8 *) GetHeapBase(&(AllocParams->StdHeader));
|
||||||
|
BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BiosHeapBaseAddr;
|
||||||
|
|
||||||
|
AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
|
||||||
|
AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
|
||||||
|
|
||||||
|
while (AllocParams->BufferHandle != AllocNodePtr->BufferHandle) {
|
||||||
|
if (AllocNodePtr->NextNodeOffset == 0) {
|
||||||
|
AllocParams->BufferPointer = NULL;
|
||||||
|
AllocParams->BufferLength = 0;
|
||||||
|
return AGESA_BOUNDS_CHK;
|
||||||
|
} else {
|
||||||
|
AllocNodeOffset = AllocNodePtr->NextNodeOffset;
|
||||||
|
AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AllocParams->BufferPointer = (UINT8 *) ((UINT8 *) AllocNodePtr + sizeof (BIOS_BUFFER_NODE));
|
||||||
|
AllocParams->BufferLength = AllocNodePtr->BufferSize;
|
||||||
|
|
||||||
|
return AGESA_SUCCESS;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CONST IDS_NV_ITEM IdsData[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
0xFFFF,
|
||||||
|
0xFFFF
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NUM_IDS_ENTRIES (sizeof (IdsData) / sizeof (IDS_NV_ITEM))
|
||||||
|
|
||||||
|
AGESA_STATUS fam16kb_GetIdsInitData (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
|
||||||
|
{
|
||||||
|
UINTN i;
|
||||||
|
IDS_NV_ITEM *IdsPtr;
|
||||||
|
|
||||||
|
IdsPtr = ((IDS_CALLOUT_STRUCT *) ConfigPtr)->IdsNvPtr;
|
||||||
|
|
||||||
|
if (Data == IDS_CALLOUT_INIT) {
|
||||||
|
for (i = 0; i < NUM_IDS_ENTRIES; i++) {
|
||||||
|
IdsPtr[i].IdsNvValue = IdsData[i].IdsNvValue;
|
||||||
|
IdsPtr[i].IdsNvId = IdsData[i].IdsNvId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AGESA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
AGESA_STATUS fam16kb_Reset (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
|
||||||
|
{
|
||||||
|
AGESA_STATUS Status;
|
||||||
|
UINT8 Value;
|
||||||
|
UINTN ResetType;
|
||||||
|
AMD_CONFIG_PARAMS *StdHeader;
|
||||||
|
|
||||||
|
ResetType = Data;
|
||||||
|
StdHeader = ConfigPtr;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Perform the RESET based upon the ResetType. In case of
|
||||||
|
// WARM_RESET_WHENVER and COLD_RESET_WHENEVER, the request will go to
|
||||||
|
// AmdResetManager. During the critical condition, where reset is required
|
||||||
|
// immediately, the reset will be invoked directly by writing 0x04 to port
|
||||||
|
// 0xCF9 (Reset Port).
|
||||||
|
//
|
||||||
|
switch (ResetType) {
|
||||||
|
case WARM_RESET_WHENEVER:
|
||||||
|
case COLD_RESET_WHENEVER:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WARM_RESET_IMMEDIATELY:
|
||||||
|
case COLD_RESET_IMMEDIATELY:
|
||||||
|
Value = 0x06;
|
||||||
|
LibAmdIoWrite (AccessWidth8, 0xCf9, &Value, StdHeader);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = 0;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
AGESA_STATUS fam16kb_RunFuncOnAp (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
|
||||||
|
{
|
||||||
|
AGESA_STATUS Status;
|
||||||
|
|
||||||
|
Status = agesawrapper_amdlaterunaptask (Func, Data, ConfigPtr);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call the host environment interface to provide a user hook opportunity. */
|
||||||
|
AGESA_STATUS fam16kb_HookBeforeDQSTraining (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
|
||||||
|
{
|
||||||
|
return AGESA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call the host environment interface to provide a user hook opportunity. */
|
||||||
|
AGESA_STATUS fam16kb_HookBeforeExitSelfRefresh (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
|
||||||
|
{
|
||||||
|
return AGESA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
AGESA_STATUS fam16kb_DefaultRet (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
|
||||||
|
{
|
||||||
|
return AGESA_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AGESA_STATUS fam16kb_HookGfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt)
|
||||||
|
{
|
||||||
|
GFX_VBIOS_IMAGE_INFO *pVbiosImageInfo = (GFX_VBIOS_IMAGE_INFO *)ConfigPrt;
|
||||||
|
pVbiosImageInfo->ImagePtr = cbfs_get_file_content(
|
||||||
|
CBFS_DEFAULT_MEDIA, "pci"CONFIG_VGA_BIOS_ID".rom",
|
||||||
|
CBFS_TYPE_OPTIONROM);
|
||||||
|
/* printk(BIOS_DEBUG, "IMGptr=%x\n", pVbiosImageInfo->ImagePtr); */
|
||||||
|
return pVbiosImageInfo->ImagePtr == NULL ? AGESA_WARNING : AGESA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
AGESA_STATUS fam16kb_ReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
|
||||||
|
{
|
||||||
|
AGESA_STATUS Status;
|
||||||
|
Status = AmdMemoryReadSPD (Func, Data, ConfigPtr);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CALLOUTS_AMD_AGESA_FAM16KB_H
|
||||||
|
#define CALLOUTS_AMD_AGESA_FAM16KB_H
|
||||||
|
|
||||||
|
#include "Porting.h"
|
||||||
|
#include "AGESA.h"
|
||||||
|
|
||||||
|
#define BIOS_HEAP_START_ADDRESS 0x010000000
|
||||||
|
#define BIOS_HEAP_SIZE 0x30000
|
||||||
|
#define BSP_STACK_BASE_ADDR 0x30000
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _BIOS_HEAP_MANAGER {
|
||||||
|
UINT32 StartOfAllocatedNodes;
|
||||||
|
UINT32 StartOfFreedNodes;
|
||||||
|
} BIOS_HEAP_MANAGER;
|
||||||
|
|
||||||
|
typedef struct _BIOS_BUFFER_NODE {
|
||||||
|
UINT32 BufferHandle;
|
||||||
|
UINT32 BufferSize;
|
||||||
|
UINT32 NextNodeOffset;
|
||||||
|
} BIOS_BUFFER_NODE;
|
||||||
|
|
||||||
|
AGESA_STATUS fam16kb_AllocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
|
||||||
|
AGESA_STATUS fam16kb_DeallocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
|
||||||
|
AGESA_STATUS fam16kb_LocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
|
||||||
|
AGESA_STATUS fam16kb_GetIdsInitData (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
|
||||||
|
AGESA_STATUS fam16kb_Reset (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
|
||||||
|
AGESA_STATUS fam16kb_RunFuncOnAp (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
|
||||||
|
AGESA_STATUS fam16kb_HookBeforeDQSTraining (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
|
||||||
|
AGESA_STATUS fam16kb_HookBeforeExitSelfRefresh (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
|
||||||
|
AGESA_STATUS fam16kb_DefaultRet (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
|
||||||
|
AGESA_STATUS fam16kb_HookGfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt);
|
||||||
|
AGESA_STATUS fam16kb_ReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr);
|
||||||
|
|
||||||
|
#endif /* CALLOUTS_AMD_AGESA_FAM16KB_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NORTHBRIDGE_AMD_AGESA_FAM16H_H
|
||||||
|
#define NORTHBRIDGE_AMD_AGESA_FAM16H_H
|
||||||
|
|
||||||
|
static struct device_operations pci_domain_ops;
|
||||||
|
static struct device_operations cpu_bus_ops;
|
||||||
|
|
||||||
|
#endif /* NORTHBRIDGE_AMD_AGESA_FAM16H_H */
|
Loading…
Reference in New Issue