Remove AMD K8 cpu and northbridge support

Change-Id: I9c53dfa93bf906334f5c80e4525a1c27153656a3
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/26673
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
This commit is contained in:
Kyösti Mälkki
2018-05-24 00:34:15 +03:00
parent 4979ffc5cb
commit d840eb5719
62 changed files with 2 additions and 20024 deletions

View File

@ -1,18 +1,11 @@
source src/cpu/amd/socket_754/Kconfig
source src/cpu/amd/socket_939/Kconfig
source src/cpu/amd/socket_940/Kconfig
source src/cpu/amd/socket_AM2/Kconfig
source src/cpu/amd/socket_AM2r2/Kconfig
source src/cpu/amd/socket_AM3/Kconfig
source src/cpu/amd/socket_C32/Kconfig
source src/cpu/amd/socket_FM2/Kconfig
source src/cpu/amd/socket_G34/Kconfig
source src/cpu/amd/socket_ASB2/Kconfig
source src/cpu/amd/socket_F/Kconfig
source src/cpu/amd/socket_F_1207/Kconfig
source src/cpu/amd/socket_S1G1/Kconfig
source src/cpu/amd/model_fxx/Kconfig
source src/cpu/amd/family_10h-family_15h/Kconfig
source src/cpu/amd/geode_lx/Kconfig

View File

@ -1,9 +1,4 @@
subdirs-$(CONFIG_CPU_AMD_SOCKET_F) += socket_F
subdirs-$(CONFIG_CPU_AMD_SOCKET_F_1207) += socket_F_1207
subdirs-$(CONFIG_CPU_AMD_SOCKET_754) += socket_754
subdirs-$(CONFIG_CPU_AMD_SOCKET_939) += socket_939
subdirs-$(CONFIG_CPU_AMD_SOCKET_940) += socket_940
subdirs-$(CONFIG_CPU_AMD_SOCKET_AM2) += socket_AM2
subdirs-$(CONFIG_CPU_AMD_SOCKET_AM2R2) += socket_AM2r2
subdirs-$(CONFIG_CPU_AMD_SOCKET_AM3) += socket_AM3
subdirs-$(CONFIG_CPU_AMD_SOCKET_ASB2) += socket_ASB2
@ -11,7 +6,6 @@ subdirs-$(CONFIG_CPU_AMD_SOCKET_C32_NON_AGESA) += socket_C32
subdirs-$(CONFIG_CPU_AMD_SOCKET_FM2_NON_AGESA) += socket_FM2
subdirs-$(CONFIG_CPU_AMD_SOCKET_G34_NON_AGESA) += socket_G34
subdirs-$(CONFIG_CPU_AMD_GEODE_LX) += geode_lx
subdirs-$(CONFIG_CPU_AMD_SOCKET_S1G1) += socket_S1G1
subdirs-$(CONFIG_CPU_AMD_AGESA) += agesa
subdirs-$(CONFIG_CPU_AMD_PI) += pi

View File

@ -31,11 +31,7 @@
#include "cpu/amd/car/disable_cache_as_ram.c"
// For set_sysinfo_in_ram()
#if IS_ENABLED(CONFIG_NORTHBRIDGE_AMD_AMDK8)
#include "northbridge/amd/amdk8/raminit.h"
#else
#include "northbridge/amd/amdfam10/raminit.h"
#endif
#if CONFIG_RAMTOP <= 0x100000
#error "You need to set CONFIG_RAMTOP greater than 1M"

View File

@ -1,2 +0,0 @@
# This is a leaf Makefile, no conditionals. If it is included it will be used.
ramstage-y += amd_sibling.c

View File

@ -1,130 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 2004.12 yhlu add dual core support
*
* 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 <cpu/cpu.h>
#include <cpu/x86/lapic.h>
#include <cpu/amd/multicore.h>
#include <device/device.h>
#include <device/pci.h>
#include <pc80/mc146818rtc.h>
#include <smp/spinlock.h>
#include <cpu/x86/mtrr.h>
#include <cpu/amd/msr.h>
#include <cpu/amd/model_fxx_rev.h>
#include <cpu/amd/amdk8_sysconf.h>
static int disable_siblings = !CONFIG_LOGICAL_CPUS;
#include "dualcore_id.c"
static int get_max_siblings(int nodes)
{
struct device *dev;
int nodeid;
int siblings=0;
//get max siblings from all the nodes
for (nodeid=0; nodeid<nodes; nodeid++){
int j;
dev = dev_find_slot(0, PCI_DEVFN(0x18+nodeid, 3));
j = (pci_read_config32(dev, 0xe8) >> 12) & 3;
if (siblings < j) {
siblings = j;
}
}
return siblings;
}
static void enable_apic_ext_id(int nodes)
{
struct device *dev;
int nodeid;
//enable APIC_EXIT_ID all the nodes
for (nodeid=0; nodeid<nodes; nodeid++){
uint32_t val;
dev = dev_find_slot(0, PCI_DEVFN(0x18+nodeid, 0));
val = pci_read_config32(dev, 0x68);
val |= (1 << 17)|(1 << 18);
pci_write_config32(dev, 0x68, val);
}
}
unsigned get_apicid_base(unsigned ioapic_num)
{
struct device *dev;
int nodes;
unsigned apicid_base;
int siblings;
unsigned nb_cfg_54;
int bsp_apic_id = lapicid(); // bsp apicid
get_option(&disable_siblings, "multi_core");
//get the nodes number
dev = dev_find_slot(0, PCI_DEVFN(0x18,0));
nodes = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1;
siblings = get_max_siblings(nodes);
if (bsp_apic_id > 0) { // IOAPIC could start from 0
return 0;
} else if (pci_read_config32(dev, 0x68) & ( (1 << 17) | (1 << 18)) ) { // enabled ext id but bsp = 0
return 1;
}
nb_cfg_54 = read_nb_cfg_54();
#if 0
//it is for all e0 single core and nc_cfg_54 low is set, but in the romstage.c stage we do not set that bit for it.
if (nb_cfg_54 && (!disable_siblings) && (siblings == 0)) {
//we need to check if e0 single core is there
int i;
for (i=0; i<nodes; i++) {
if (is_e0_later_in_bsp(i)) {
siblings = 1;
break;
}
}
}
#endif
//Construct apicid_base
if ((!disable_siblings) && (siblings>0) ) {
/* for 8 way dual core, we will used up apicid 16:16, actually 16 is not allowed by current kernel
and the kernel will try to get one that is small than 16 to make IOAPIC work.
I don't know when the kernel can support 256 APIC id. (APIC_EXT_ID is enabled) */
//4:10 for two way 8:12 for four way 16:16 for eight way
//Use CONFIG_MAX_PHYSICAL_CPUS instead of nodes for better consistency?
apicid_base = nb_cfg_54 ? (siblings+1) * nodes : 8 * siblings + nodes;
}
else {
apicid_base = nodes;
}
if ((apicid_base+ioapic_num-1)>0xf) {
// We need to enable APIC EXT ID
printk(BIOS_INFO, "if the IOAPIC device doesn't support 256 APIC id,\n you need to set CONFIG_ENABLE_APIC_EXT_ID in romstage.c so you can spare 16 id for IOAPIC\n");
enable_apic_ext_id(nodes);
}
return apicid_base;
}

View File

@ -1,76 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Yinghai Lu
*
* 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 "cpu/amd/dualcore/dualcore_id.c"
#include <pc80/mc146818rtc.h>
#if IS_ENABLED(CONFIG_HAVE_OPTION_TABLE)
#include "option_table.h"
#endif
static inline unsigned get_core_num_in_bsp(unsigned nodeid)
{
uint32_t dword;
dword = pci_read_config32(PCI_DEV(0, 0x18+nodeid, 3), 0xe8);
dword >>= 12;
dword &= 3;
return dword;
}
static inline uint8_t set_apicid_cpuid_lo(void)
{
#if !IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
if (is_cpu_pre_e0()) return 0; // pre_e0 can not be set
#endif
// set the NB_CFG[54]=1; why the OS will be happy with that ???
msr_t msr;
msr = rdmsr(NB_CFG_MSR);
msr.hi |= (1<<(54-32)); // InitApicIdCpuIdLo
wrmsr(NB_CFG_MSR, msr);
return 1;
}
static inline void real_start_other_core(unsigned nodeid)
{
uint32_t dword;
// set PCI_DEV(0, 0x18+nodeid, 3), 0x44 bit 27 to redirect all MC4 accesses and error logging to core0
dword = pci_read_config32(PCI_DEV(0, 0x18+nodeid, 3), 0x44);
dword |= 1 << 27; // NbMcaToMstCpuEn bit
pci_write_config32(PCI_DEV(0, 0x18+nodeid, 3), 0x44, dword);
// set PCI_DEV(0, 0x18+nodeid, 0), 0x68 bit 5 to start core1
dword = pci_read_config32(PCI_DEV(0, 0x18+nodeid, 0), 0x68);
dword |= 1 << 5;
pci_write_config32(PCI_DEV(0, 0x18+nodeid, 0), 0x68, dword);
}
//it is running on core0 of node0
static inline void start_other_cores(void)
{
unsigned nodes;
unsigned nodeid;
if (read_option(multi_core, 0)) {
return; // disable multi_core
}
nodes = get_nodes();
for (nodeid=0; nodeid<nodes; nodeid++) {
if ( get_core_num_in_bsp(nodeid) > 0) {
real_start_other_core(nodeid);
}
}
}

View File

@ -1,67 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2004 Yinghai Lu
*
* 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 <arch/cpu.h>
#include <cpu/amd/multicore.h>
#ifdef __PRE_RAM__
#include <cpu/amd/msr.h>
#endif
//called by bus_cpu_scan too
unsigned int read_nb_cfg_54(void)
{
msr_t msr;
msr = rdmsr(NB_CFG_MSR);
return ( ( msr.hi >> (54-32)) & 1);
}
u32 get_initial_apicid(void)
{
return ((cpuid_ebx(1) >> 24) & 0xf);
}
//called by amd_siblings too
#define CORE_ID_BIT 1
#define NODE_ID_BIT 3
struct node_core_id get_node_core_id(unsigned nb_cfg_54)
{
struct node_core_id id;
// get the apicid via cpuid(1) ebx[27:24]
if ( nb_cfg_54) {
// when NB_CFG[54] is set, nodeid = ebx[27:25], coreid = ebx[24]
id.coreid = (cpuid_ebx(1) >> 24) & 0xf;
id.nodeid = (id.coreid>>CORE_ID_BIT);
id.coreid &= ((1 << CORE_ID_BIT)-1);
}
else
{
// when NB_CFG[54] is clear, nodeid = ebx[26:24], coreid = ebx[27]
id.nodeid = (cpuid_ebx(1) >> 24) & 0xf;
id.coreid = (id.nodeid>>NODE_ID_BIT);
id.nodeid &= ((1 << NODE_ID_BIT)-1);
}
return id;
}
static inline unsigned get_core_num(void)
{
return (cpuid_ecx(0x80000008) & 0xff);
}
struct node_core_id get_node_core_id_x(void)
{
return get_node_core_id(read_nb_cfg_54()); // for pre_e0() nb_cfg_54 always be 0
}

View File

@ -1,58 +0,0 @@
config CPU_AMD_MODEL_FXX
bool
select ARCH_BOOTBLOCK_X86_32
select ARCH_VERSTAGE_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select MMX
select SSE
select SSE2
select TSC_SYNC_LFENCE
select UDELAY_LAPIC
select SUPPORT_CPU_UCODE_IN_CBFS
select ACPI_HUGE_LOWMEM_BACKUP
if CPU_AMD_MODEL_FXX
config CPU_ADDR_BITS
int
default 40
config MAX_PHYSICAL_CPUS
int
default 1
config LIFT_BSP_APIC_ID
bool
default n
config SET_FIDVID
bool
default y if K8_REV_F_SUPPORT
default n
config HW_SCRUBBER
bool
default n
config UDELAY_LAPIC_FIXED_FSB
int
default 200
if SET_FIDVID
config SET_FIDVID_DEBUG
bool
default n
config SET_FIDVID_CORE0_ONLY
bool
default y
config SET_FIDVID_ONE_BY_ONE
bool
default y
config SET_FIDVID_STORE_AP_APICID_AT_FIRST
bool
default y
endif
endif

View File

@ -1,10 +0,0 @@
romstage-y += ../../x86/mtrr/earlymtrr.c
romstage-y += ../car/post_cache_as_ram.c
# no conditionals here. If you include this file from a socket, then you get all the binaries.
ramstage-y += model_fxx_init.c
ramstage-y += model_fxx_update_microcode.c
ramstage-y += processor_name.c
ramstage-$(CONFIG_HAVE_ACPI_TABLES) += powernow_acpi.c
cpu_microcode_bins += 3rdparty/blobs/cpu/amd/model_fxx/microcode.bin

View File

@ -1,648 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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.
*/
#if IS_ENABLED(CONFIG_SET_FIDVID)
#ifndef SB_VFSMAF
#define SB_VFSMAF 1
#endif
#define FX_SUPPORT 1
static inline void print_debug_fv(const char *str, u32 val)
{
#if IS_ENABLED(CONFIG_SET_FIDVID_DEBUG)
printk(BIOS_DEBUG, "%s%x\n", str, val);
#endif
}
static inline void print_debug_fv_8(const char *str, u8 val)
{
#if IS_ENABLED(CONFIG_SET_FIDVID_DEBUG)
printk(BIOS_DEBUG, "%s%02x\n", str, val);
#endif
}
static inline void print_debug_fv_64(const char *str, u32 val, u32 val2)
{
#if IS_ENABLED(CONFIG_SET_FIDVID_DEBUG)
printk(BIOS_DEBUG, "%s%x%x\n", str, val, val2);
#endif
}
static void enable_fid_change(void)
{
u32 dword;
u32 nodes;
int i;
nodes = ((pci_read_config32(PCI_DEV(0, 0x18, 0), 0x60) >> 4) & 7) + 1;
for (i = 0; i < nodes; i++) {
dword = pci_read_config32(PCI_DEV(0, 0x18 + i, 3), 0xd8);
dword &= 0x8ff00000;
dword |= (2 << 28) | (0x02710);
pci_write_config32(PCI_DEV(0, 0x18 + i, 3), 0xd8, dword);
dword = 0x04e2a707;
pci_write_config32(PCI_DEV(0, 0x18 + i, 3), 0xd4, dword);
/* disable the DRAM interface at first, it will be enabled
* by raminit again (see also erratum #181) */
#if IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
dword = pci_read_config32(PCI_DEV(0, 0x18 + i, 2), 0x94);
dword |= (1 << 14);
pci_write_config32(PCI_DEV(0, 0x18 + i, 2), 0x94, dword);
#else
dword = pci_read_config32(PCI_DEV(0, 0x18 + i, 2), 0x90);
dword |= (1 << 24);
pci_write_config32(PCI_DEV(0, 0x18 + i, 2), 0x90, dword);
dword = pci_read_config32(PCI_DEV(0, 0x18 + i, 2), 0x94);
dword |= (1 << 25);
pci_write_config32(PCI_DEV(0, 0x18 + i, 2), 0x94, dword);
#endif
dword = 0x23070700; /* enable FID/VID change */
// dword = 0x00070000; /* enable FID/VID change */
pci_write_config32(PCI_DEV(0, 0x18 + i, 3), 0x80, dword);
#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
dword = 0x21132113;
#else
dword = 0x00132113;
#endif
pci_write_config32(PCI_DEV(0, 0x18 + i, 3), 0x84, dword);
}
}
#if !IS_ENABLED(CONFIG_SET_FIDVID_ONE_BY_ONE)
static unsigned set_fidvid_without_init(unsigned fidvid)
{
msr_t msr;
u32 vid;
u32 fid;
fid = (fidvid >> 8) & 0x3f;
vid = (fidvid >> 16) & 0x3f;
/* set new FID/VID */
msr.hi = 1;
msr.lo = (vid << 8) | fid;
wrmsr(0xc0010041, msr);
return fidvid;
}
#endif
static u32 set_fidvid(unsigned apicid, unsigned fidvid, int showmessage)
{
/* CurrentFID--> 4x(00h) 5x(02h) 6x(04h) 7x(06h) ...
* --------------------------------------
* TargetFID | Next_FID, Next_FID, Next_FID, Next_FID ...
* | | Next_FID, Next_FID, Next_FID, Next_FID ...
* \|/ | Next_FID, Next_FID, Next_FID, Next_FID ...
*/
static const u8 next_fid_200[] = {
/* x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 */
/* x4 */ 0, -1, -1, -1, 0, 0, 9, 10, 11, 12, 13, 14, 15, /* 800 */
/* x5 */ -1, 0, -1, -1, -1, 5, 5, 5, 11, 12, 13, 14, 15, /* 1000 */
/* x6 */ -1, -1, 0, -1, -1, -1, -1, 6, 6, 6, 13, 14, 15, /* 1200 */
/* x7 */ -1, -1, -1, 0, -1, -1, -1, -1, -1, 7, 7, 7, 15, /* 1400 */
/* lower table to upper table boarder (table 70 and 71 in BKDG) */
/* x8 */ 8, -1, -1, -1, 0, 8, 9, 10, 11, 12, 13, 14, 15, /* 1600 */
/* x9 */ 9, 9, -1, -1, 9, 0, 9, 10, 11, 12, 13, 14, 15, /* 1800 */
/*x10 */ 9, 10, -1, -1, 9, 10, 0, 10, 11, 12, 13, 14, 15, /* 2000 */
/*x11 */ 9, 11, 11, -1, 9, 10, 11, 0, 11, 12, 13, 14, 15, /* 2200 */
/*x12 */ 9, 11, 12, -1, 9, 10, 11, 12, 0, 12, 13, 14, 15, /* 2400 */
/*x13 */ 9, 11, 13, 13, 9, 10, 11, 12, 13, 0, 13, 14, 15, /* 2600 */
/*x14 */ 9, 11, 13, 14, 9, 10, 11, 12, 13, 14, 0, 14, 15, /* 2800 */
/*x15 */ 9, 11, 13, 15, 9, 10, 11, 12, 13, 14, 15, 0, 15, /* 3000 */
/*x15 */ 9, 11, 13, 15, 9, 10, 11, 12, 13, 14, 15, 16, 0, /* 3200 */
};
msr_t msr;
u32 vid_new;
u32 fid_new;
u32 vid_max;
u32 fid_max;
u32 vid_cur;
u32 fid_cur;
unsigned apicidx;
int step_limit;
int loop;
apicidx = lapicid();
if (apicid != apicidx) {
printk(BIOS_ERR,
"wrong apicid, we want change %x, but it is %x\n",
apicid, apicidx);
return fidvid;
}
fid_new = (fidvid >> 8) & 0x3f;
vid_new = (fidvid >> 16) & 0x3f;
msr = rdmsr(0xc0010042);
vid_cur = msr.hi & 0x3f;
fid_cur = msr.lo & 0x3f;
if ((vid_cur == vid_new) && (fid_cur == fid_new))
return fidvid;
vid_max = (msr.hi >> (48 - 32)) & 0x3f;
fid_max = ((msr.lo >> 16) & 0x3f); /* max fid */
#if FX_SUPPORT
if (fid_max >= ((25 - 4) * 2)) { /* FX max fid is 5G */
fid_max = ((msr.lo >> 8) & 0x3f) + 5 * 2; /* max FID is min fid + 1G */
if (fid_max >= ((25 - 4) * 2)) {
fid_max = (10 - 4) * 2; /* hard set to 2G */
}
}
#endif
/* set vid to max */
/* TODO - make this more correct. Not a big deal for setting max...
* BKDG figure 11
* if TargetFID > InitialFID
* TargetVID = FinalVID - RVO
* else
* if CurrentVID > FinalVID
* TargetVID = FinalVID - RVO
* else
* TargetVID = CurrentVIDD - RVO
*/
msr.hi = 1;
msr.lo = (vid_max << 8) | (fid_cur);
#if SB_VFSMAF == 1
msr.lo |= (1 << 16); /* init changes */
#endif
wrmsr(0xc0010041, msr);
#if SB_VFSMAF == 0
ldtstop_sb();
#endif
for (loop = 0; loop < 100000; loop++) {
msr = rdmsr(0xc0010042);
if (!(msr.lo & (1 << 31)))
break;
}
vid_cur = msr.hi & 0x3f;
/* BKDG figure 12 and 13
* if current fid is odd
* current fid -1 (next lower and even fid)(odd fid for rev G)
* if current fid in high-freq table
* while current fid < target fid
* transition to next higher fid in table
* else if target fid > VCO portal of current fid
* transition to highest portal fid in higher fid table
* while current fid < target fid
* transition to next higher fid in table
* else
* transition to target fid
*/
printk(BIOS_DEBUG, "Current fid_cur: 0x%x, fid_max: 0x%x\n", fid_cur,
fid_max);
printk(BIOS_DEBUG, "Requested fid_new: 0x%x\n", fid_new);
step_limit = 8; /* max 8 steps just in case... */
while ((fid_cur != fid_new) && (step_limit--)) {
u32 fid_temp;
int step;
if (fid_cur < fid_new)
/* Force Fid steps even. step == 0 means 100MHz step */
step = ((fid_new / 2) - (fid_cur / 2)) * 2;
else
step = ((fid_cur / 2) - (fid_new / 2)) * 2;
/* If 200MHz step OR past 3200 max table value */
if ((step == 2) || (fid_new >= 0x18 || fid_cur >= 0x18)) {
printk(BIOS_DEBUG, "200MHz step ");
/* Step +/- 200MHz at a time */
if (fid_cur < fid_new)
fid_temp = fid_cur + 2;
else
fid_temp = fid_cur - 2;
} else if (step > 2) { /* If more than a 200MHz step */
int temp;
/* look it up in the table */
printk(BIOS_DEBUG, "FidVid table step ");
temp =
next_fid_200[((fid_new / 2) * 13) + (fid_cur / 2)];
if (temp > 0)
fid_temp = (temp - 4) * 2; /* Table 108 */
else if (temp == 0)
fid_temp = fid_new;
else
break; /* table error */
} else { /* step < 2 (100MHz) */
printk(BIOS_DEBUG, "100MHz step ");
/* The table adjust in 200MHz increments. If requested,
* do the 100MHz increment if the CPU supports it.*/
if (cpuid_edx(0x80000007) & (1 << 6)) {
fid_temp = fid_cur + 1;
} else {
/* 100 MHz not supported. Get out of the loop */
printk(BIOS_DEBUG, "is not supported.\n");
break;
}
}
if (fid_temp > fid_max) {
printk(BIOS_DEBUG, "fid_temp 0x%x > fid_max 0x%x\n",
fid_temp, fid_max);
break;
}
printk(BIOS_DEBUG, "fidvid: 0x%x\n", fid_temp);
/* set target fid */
msr.hi = 0x190; /* 2 us for AMD NPT Family 0Fh Processors */
msr.lo = (vid_cur << 8) | fid_temp;
#if SB_VFSMAF == 1
msr.lo |= (1 << 16); /* init changes */
#endif
wrmsr(0xc0010041, msr);
#if SB_VFSMAF == 0
ldtstop_sb();
#endif
#if IS_ENABLED(CONFIG_SET_FIDVID_DEBUG)
if (showmessage) {
print_debug_fv_8("set_fidvid APICID = ", apicid);
print_debug_fv_64("fidvid ctrl msr ", msr.hi, msr.lo);
}
#endif
for (loop = 0; loop < 100000; loop++) {
msr = rdmsr(0xc0010042);
if (!(msr.lo & (1 << 31)))
break;
}
fid_cur = msr.lo & 0x3f;
#if IS_ENABLED(CONFIG_SET_FIDVID_DEBUG)
if (showmessage) {
print_debug_fv_64("fidvid status msr ", msr.hi, msr.lo);
}
#endif
}
/* set vid to final */
/* TODO - make this more correct. Not a big deal for setting max...
* BKDG figure 11
* if TargetFID > InitialFID
* TargetVID = FinalVID - RVO
* else
* if CurrentVID > FinalVID
* TargetVID = FinalVID - RVO
* else
* TargetVID = CurrentVIDD - RVO
*/
msr.hi = 1;
msr.lo = (vid_new << 8) | (fid_cur);
#if SB_VFSMAF == 1
msr.lo |= (1 << 16); // init changes
#endif
wrmsr(0xc0010041, msr);
#if SB_VFSMAF == 0
ldtstop_sb();
#endif
for (loop = 0; loop < 100000; loop++) {
msr = rdmsr(0xc0010042);
if (!(msr.lo & (1 << 31)))
break;
}
vid_cur = msr.hi & 0x3f;
fidvid = (vid_cur << 16) | (fid_cur << 8);
if (showmessage) {
if (vid_new != vid_cur) {
printk(BIOS_ERR, "set vid failed for apicid =%02x\n",
apicidx);
}
if (fid_new != fid_cur) {
printk(BIOS_ERR, "set fid failed for apicid =%02x\n",
apicidx);
}
}
return fidvid;
}
static void init_fidvid_ap(unsigned bsp_apicid, unsigned apicid)
{
u32 send;
u32 readback = 0;
unsigned timeout = 1;
msr_t msr;
u32 vid_cur;
u32 fid_cur;
u32 fid_max;
int loop;
if ((cpuid_edx(0x80000007) & 0x06) != 0x06)
return; /* FID/VID change not supported */
msr = rdmsr(0xc0010042);
fid_max = ((msr.lo >> 16) & 0x3f); /* max fid */
#if FX_SUPPORT
if (fid_max >= ((25 - 4) * 2)) { /* FX max fid is 5G */
fid_max = ((msr.lo >> 8) & 0x3f) + 5 * 2; /* maxFID = minFID + 1G */
if (fid_max >= ((25 - 4) * 2)) {
fid_max = (10 - 4) * 2; /* hard set to 2G */
}
}
#endif
send = fid_max << 8;
send |= ((msr.hi >> (48 - 32)) & 0x3f) << 16; /* max vid */
send |= (apicid << 24); /* ap apicid */
#if IS_ENABLED(CONFIG_SET_FIDVID_ONE_BY_ONE)
vid_cur = msr.hi & 0x3f;
fid_cur = msr.lo & 0x3f;
/* set to current */
msr.hi = 1;
msr.lo = (vid_cur << 8) | (fid_cur);
wrmsr(0xc0010041, msr);
#endif
timeout = wait_cpu_state(bsp_apicid, 1);
if (timeout) {
printk(BIOS_DEBUG, "fidvid_ap_stage1: time out while reading"
" from BSP on %02x\n", apicid);
}
/* send signal to BSP about this AP max fid and vid */
/* AP at state 1 that sent our fid and vid */
lapic_write(LAPIC_MSG_REG, send | 1);
// wait_cpu_state(bsp_apicid, 2); /* don't need we can use apicid directly */
loop = 1000000;
while (--loop > 0) {
/* remote read BSP signal that include vid/fid that need to set */
if (lapic_remote_read(bsp_apicid, LAPIC_MSG_REG, &readback) !=
0)
continue;
if (((readback >> 24) & 0xff) == apicid)
break; /* it is this CPU turn */
}
if (loop > 0) {
#if IS_ENABLED(CONFIG_SET_FIDVID_ONE_BY_ONE)
readback = set_fidvid(apicid, readback & 0xffff00, 1); // this AP
#else
readback = set_fidvid_without_init(readback & 0xffff00); // this AP
#endif
/* send signal to BSP that this AP fid/vid is set */
/* allow to change state2 is together with apicid */
/* AP at state that We set the requested fid/vid */
send = (apicid << 24) | (readback & 0x00ffff00);
} else {
printk(BIOS_DEBUG, "%s: time out while reading from BSP on %02x",
__func__, apicid);
}
lapic_write(LAPIC_MSG_REG, send | 2);
timeout = wait_cpu_state(bsp_apicid, 3);
if (timeout) {
printk(BIOS_DEBUG, "%s: time out while reading from BSP on %02x",
__func__, apicid);
}
}
static u32 calc_common_fidvid(unsigned fidvid, unsigned fidvidx)
{
/* FIXME: need to check the change path to verify if it is reachable
* when common fid is small than 1.6G */
if ((fidvid & 0xff00) <= (fidvidx & 0xff00)) {
return fidvid;
} else {
return fidvidx;
}
}
struct fidvid_st {
unsigned common_fidvid;
};
static void init_fidvid_bsp_stage1(u32 ap_apicid, void *gp)
{
u32 readback = 0;
u32 timeout = 1;
struct fidvid_st *fvp = gp;
int loop;
print_debug_fv("state 1: ap_apicid=", ap_apicid);
loop = 1000000;
while (--loop > 0) {
if (lapic_remote_read(ap_apicid, LAPIC_MSG_REG, &readback) != 0)
continue;
if ((readback & 0xff) == 1) {
timeout = 0;
break; /* target ap is in stage 1 */
}
}
if (timeout) {
printk(BIOS_DEBUG, "%s: timed out reading from ap %02x\n",
__func__, ap_apicid);
return;
}
print_debug_fv("\treadback = ", readback);
fvp->common_fidvid = calc_common_fidvid(fvp->common_fidvid, readback & 0xffff00);
print_debug_fv("\tcommon_fidvid=", fvp->common_fidvid);
}
static void init_fidvid_bsp_stage2(unsigned ap_apicid, void *gp)
{
unsigned readback = 0;
unsigned timeout = 1;
struct fidvid_st *fvp = gp;
int loop;
print_debug_fv("state 2: ap_apicid=", ap_apicid);
/* all set to state2 */
lapic_write(LAPIC_MSG_REG, fvp->common_fidvid | (ap_apicid << 24) | 2);
loop = 1000000;
while (--loop > 0) {
if (lapic_remote_read(ap_apicid, LAPIC_MSG_REG, &readback) != 0)
continue;
if ((readback & 0xff) == 2) {
timeout = 0;
break; /* target ap is stage 2, its FID has been set */
}
}
if (timeout) {
printk(BIOS_DEBUG, "%s: time out while reading from ap %02x",
__func__, ap_apicid);
return;
}
print_debug_fv("\treadback=", readback);
}
#if IS_ENABLED(CONFIG_SET_FIDVID_STORE_AP_APICID_AT_FIRST)
struct ap_apicid_st {
u32 num;
unsigned apicid[16]; /* 8 way dual core need 16 */
};
static void store_ap_apicid(unsigned ap_apicid, void *gp)
{
struct ap_apicid_st *p = gp;
p->apicid[p->num++] = ap_apicid;
}
#endif
static void init_fidvid_bsp(unsigned bsp_apicid)
{
u32 vid_max;
u32 fid_max;
struct fidvid_st fv;
#if IS_ENABLED(CONFIG_SET_FIDVID_STORE_AP_APICID_AT_FIRST)
struct ap_apicid_st ap_apicidx;
unsigned i;
#endif
if ((cpuid_edx(0x80000007) & 0x06) != 0x06)
return; /* FID/VID change not supported */
msr_t msr;
msr = rdmsr(0xc0010042);
fid_max = ((msr.lo >> 16) & 0x3f); /* max fid */
#if FX_SUPPORT == 1
if (fid_max >= ((25 - 4) * 2)) { /* FX max fid is 5G */
fid_max = ((msr.lo >> 8) & 0x3f) + 5 * 2; /* maxFID = minFID + 1G */
if (fid_max >= ((25 - 4) * 2)) {
fid_max = (10 - 4) * 2; /* hard set to 2G */
}
}
#endif
vid_max = ((msr.hi >> (48 - 32)) & 0x3f); //max vid
fv.common_fidvid = (fid_max << 8) | (vid_max << 16);
/* for all APs (We know the APIC ID of all APs even the APIC ID is lifted)
* remote read from AP about max fid/vid */
/* let all ap trains to state 1 */
lapic_write(LAPIC_MSG_REG, (bsp_apicid << 24) | 1);
/* calculate the common max fid/vid that could be used for
* all APs and BSP */
#if IS_ENABLED(CONFIG_SET_FIDVID_STORE_AP_APICID_AT_FIRST)
ap_apicidx.num = 0;
for_each_ap(bsp_apicid, CONFIG_SET_FIDVID_CORE0_ONLY, store_ap_apicid, &ap_apicidx);
for (i = 0; i < ap_apicidx.num; i++) {
init_fidvid_bsp_stage1(ap_apicidx.apicid[i], &fv);
}
#else
for_each_ap(bsp_apicid, CONFIG_SET_FIDVID_CORE0_ONLY, init_fidvid_bsp_stage1, &fv);
#endif
#if 0
unsigned fid, vid;
/* Can we use max only? So we can only set fid in one around,
* otherwise we need to set that to max after raminit */
/* set fid vid to DQS training required */
fid = (fv.common_fidvid >> 8) & 0x3f;
vid = (fv.common_fidvid >> 16) & 0x3f;
if (fid > (10 - 4) * 2) {
fid = (10 - 4) * 2; // x10
}
if (vid >= 0x1f) {
vid += 4; /* unit is 12.5mV */
} else {
vid += 2; /* unit is 25mV */
}
fv.common_fidvid = (fid << 8) | (vid << 16);
print_debug_fv("common_fidvid=", fv.common_fidvid);
#endif
#if IS_ENABLED(CONFIG_SET_FIDVID_ONE_BY_ONE)
/* set BSP fid and vid */
print_debug_fv("bsp apicid=", bsp_apicid);
fv.common_fidvid = set_fidvid(bsp_apicid, fv.common_fidvid, 1);
print_debug_fv("common_fidvid=", fv.common_fidvid);
#endif
/* For all APs ( We know the APIC ID of all AP even the APIC ID is lifted)
* send signal to the AP it could change it's fid/vid */
/* remote read signal from AP that AP is done */
fv.common_fidvid &= 0xffff00;
/* set state 2 allow is in init_fidvid_bsp_stage2 */
#if IS_ENABLED(CONFIG_SET_FIDVID_STORE_AP_APICID_AT_FIRST)
for (i = 0; i < ap_apicidx.num; i++) {
init_fidvid_bsp_stage2(ap_apicidx.apicid[i], &fv);
}
#else
for_each_ap(bsp_apicid, CONFIG_SET_FIDVID_CORE0_ONLY, init_fidvid_bsp_stage2, &fv);
#endif
#if !IS_ENABLED(CONFIG_SET_FIDVID_ONE_BY_ONE)
/* set BSP fid and vid */
print_debug_fv("bsp apicid=", bsp_apicid);
fv.common_fidvid = set_fidvid(bsp_apicid, fv.common_fidvid, 1);
print_debug_fv("common_fidvid=", fv.common_fidvid);
#endif
/* clear the state */
lapic_write(LAPIC_MSG_REG, fv.common_fidvid | (bsp_apicid << 24) | 3);
/* here wait a while, so last ap could read pack, and stop it, don't
* call init_timer too early or just don't use init_timer */
}
#endif

View File

@ -1,374 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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 <cpu/amd/mtrr.h>
#include <cpu/x86/lapic.h>
#include <cpu/x86/mtrr.h>
#include <northbridge/amd/amdk8/amdk8.h>
#include "cpu/amd/car/disable_cache_as_ram.c"
#if IS_ENABLED(CONFIG_HAVE_OPTION_TABLE)
#include "option_table.h"
#endif
#if IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
#include <northbridge/amd/amdk8/f.h>
#endif
typedef void (*process_ap_t) (u32 apicid, void *gp);
//core_range = 0 : all cores
//core range = 1 : core 0 only
//core range = 2 : cores other than core0
static void for_each_ap(u32 bsp_apicid, u32 core_range, process_ap_t process_ap,
void *gp)
{
// here assume the OS don't change our apicid
u32 ap_apicid;
u32 nodes;
u32 siblings = 0;
u32 disable_siblings;
u32 e0_later_single_core;
u32 nb_cfg_54;
int i, j;
/* get_nodes define in in_coherent_ht.c */
nodes = get_nodes();
if (!CONFIG_LOGICAL_CPUS ||
read_option(multi_core, 0) != 0) { // 0 means multi core
disable_siblings = 1;
} else {
disable_siblings = 0;
}
/* here I assume that all node are same stepping, otherwise we can use use nb_cfg_54 from bsp for all nodes */
nb_cfg_54 = read_nb_cfg_54();
for (i = 0; i < nodes; i++) {
e0_later_single_core = 0;
j = ((pci_read_config32(PCI_DEV(0, 0x18 + i, 3), 0xe8) >> 12) &
3);
if (nb_cfg_54) {
if (j == 0) { // if it is single core, we need to increase siblings for APIC calculation
#if !IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
e0_later_single_core = is_e0_later_in_bsp(i); // single core
#else
e0_later_single_core = is_cpu_f0_in_bsp(i); // We can read cpuid(1) from Func3
#endif
}
if (e0_later_single_core) {
j = 1;
}
}
siblings = j;
u32 jstart, jend;
if (core_range == 2) {
jstart = 1;
} else {
jstart = 0;
}
if (e0_later_single_core || disable_siblings
|| (core_range == 1)) {
jend = 0;
} else {
jend = siblings;
}
for (j = jstart; j <= jend; j++) {
ap_apicid =
i * (nb_cfg_54 ? (siblings + 1) : 1) +
j * (nb_cfg_54 ? 1 : 8);
#if IS_ENABLED(CONFIG_ENABLE_APIC_EXT_ID)
#if !IS_ENABLED(CONFIG_LIFT_BSP_APIC_ID)
if ((i != 0) || (j != 0)) /* except bsp */
#endif
ap_apicid += CONFIG_APIC_ID_OFFSET;
#endif
if (ap_apicid == bsp_apicid)
continue;
process_ap(ap_apicid, gp);
}
}
}
static inline int lapic_remote_read(int apicid, int reg, u32 *pvalue)
{
int timeout;
u32 status;
int result;
lapic_wait_icr_idle();
lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
/* Extra busy check compared to lapic.h */
timeout = 0;
do {
status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
} while (status == LAPIC_ICR_BUSY && timeout++ < 1000);
timeout = 0;
do {
status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
} while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
result = -1;
if (status == LAPIC_ICR_RR_VALID) {
*pvalue = lapic_read(LAPIC_RRR);
result = 0;
}
return result;
}
#define LAPIC_MSG_REG 0x380
#if IS_ENABLED(CONFIG_SET_FIDVID)
static void init_fidvid_ap(u32 bsp_apicid, u32 apicid);
#endif
static inline __attribute__((always_inline))
void print_apicid_nodeid_coreid(u32 apicid, struct node_core_id id,
const char *str)
{
printk(BIOS_DEBUG,
"%s --- { APICID = %02x NODEID = %02x COREID = %02x} ---\n", str,
apicid, id.nodeid, id.coreid);
}
static u32 wait_cpu_state(u32 apicid, u32 state)
{
u32 readback = 0;
u32 timeout = 1;
int loop = 2000000;
while (--loop > 0) {
if (lapic_remote_read(apicid, LAPIC_MSG_REG, &readback) != 0)
continue;
if ((readback & 0xff) == state) {
timeout = 0;
break; //target CPU is in stage started
}
}
if (timeout) {
if (readback) {
timeout = readback;
}
}
return timeout;
}
static void wait_ap_started(u32 ap_apicid, void *gp)
{
u32 timeout;
timeout = wait_cpu_state(ap_apicid, 0x33); // started
printk(BIOS_DEBUG, "* AP %02x", ap_apicid);
if (timeout) {
printk(BIOS_DEBUG, " timed out:%08x\n", timeout);
} else {
printk(BIOS_DEBUG, "started\n");
}
}
void wait_all_aps_started(u32 bsp_apicid)
{
for_each_ap(bsp_apicid, 0, wait_ap_started, (void *)0);
}
void wait_all_other_cores_started(u32 bsp_apicid)
{
// all aps other than core0
printk(BIOS_DEBUG, "started ap apicid: ");
for_each_ap(bsp_apicid, 2, wait_ap_started, (void *)0);
printk(BIOS_DEBUG, "\n");
}
void allow_all_aps_stop(u32 bsp_apicid)
{
// allow aps to stop
lapic_write(LAPIC_MSG_REG, (bsp_apicid << 24) | 0x44);
}
static void enable_apic_ext_id(u32 node)
{
u32 val;
val = pci_read_config32(NODE_HT(node), 0x68);
val |= (HTTC_APIC_EXT_SPUR | HTTC_APIC_EXT_ID | HTTC_APIC_EXT_BRD_CST);
pci_write_config32(NODE_HT(node), 0x68, val);
}
static void STOP_CAR_AND_CPU(void)
{
disable_cache_as_ram_real(0); // inline
/* stop all cores except node0/core0 the bsp .... */
stop_this_cpu();
}
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
static u32 init_cpus(u32 cpu_init_detectedx, struct sys_info *sysinfo)
#else
static u32 init_cpus(u32 cpu_init_detectedx)
#endif
{
u32 bsp_apicid = 0;
u32 apicid;
struct node_core_id id;
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
/* Please refer to the calculations and explaination in cache_as_ram.inc before modifying these values */
uint32_t max_ap_stack_region_size = CONFIG_MAX_CPUS * CONFIG_DCACHE_AP_STACK_SIZE;
uint32_t max_bsp_stack_region_size = CONFIG_DCACHE_BSP_STACK_SIZE + CONFIG_DCACHE_BSP_STACK_SLUSH;
uint32_t bsp_stack_region_upper_boundary = CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE;
uint32_t bsp_stack_region_lower_boundary = bsp_stack_region_upper_boundary - max_bsp_stack_region_size;
void * lower_stack_region_boundary = (void*)(bsp_stack_region_lower_boundary - max_ap_stack_region_size);
if (((void*)(sysinfo + 1)) > lower_stack_region_boundary)
printk(BIOS_WARNING,
"sysinfo extends into stack region (sysinfo range: [%p,%p] lower stack region boundary: %p)\n",
sysinfo, sysinfo + 1, lower_stack_region_boundary);
#endif
/*
* already set early mtrr in cache_as_ram.inc
*/
/* that is from initial apicid, we need nodeid and coreid
later */
id = get_node_core_id_x();
/* NB_CFG MSR is shared between cores, so we need make sure
core0 is done at first --- use wait_all_core0_started */
if (id.coreid == 0) {
set_apicid_cpuid_lo(); /* only set it on core0 */
if (IS_ENABLED(CONFIG_ENABLE_APIC_EXT_ID))
enable_apic_ext_id(id.nodeid);
}
enable_lapic();
// init_timer(); // We need TMICT to pass msg for FID/VID change
#if IS_ENABLED(CONFIG_ENABLE_APIC_EXT_ID)
u32 initial_apicid = get_initial_apicid();
#if !IS_ENABLED(CONFIG_LIFT_BSP_APIC_ID)
if (initial_apicid != 0) // other than bsp
#endif
{
/* use initial APIC id to lift it */
u32 dword = lapic_read(LAPIC_ID);
dword &= ~(0xff << 24);
dword |=
(((initial_apicid + CONFIG_APIC_ID_OFFSET) & 0xff) << 24);
lapic_write(LAPIC_ID, dword);
}
#if IS_ENABLED(CONFIG_LIFT_BSP_APIC_ID)
bsp_apicid += CONFIG_APIC_ID_OFFSET;
#endif
#endif
/* get the apicid, it may be lifted already */
apicid = lapicid();
// show our apicid, nodeid, and coreid
if (id.coreid == 0) {
if (id.nodeid != 0) //all core0 except bsp
print_apicid_nodeid_coreid(apicid, id, " core0: ");
} else { //all other cores
print_apicid_nodeid_coreid(apicid, id, " corex: ");
}
if (cpu_init_detectedx) {
print_apicid_nodeid_coreid(apicid, id,
"\n\n\nINIT detected from ");
printk(BIOS_DEBUG, "\nIssuing SOFT_RESET...\n");
soft_reset();
}
if (id.coreid == 0) {
distinguish_cpu_resets(id.nodeid);
// start_other_core(id.nodeid); // start second core in first CPU, only allowed for nb_cfg_54 is not set
}
//here don't need to wait
lapic_write(LAPIC_MSG_REG, (apicid << 24) | 0x33); // mark the CPU is started
if (apicid != bsp_apicid) {
u32 timeout = 1;
u32 loop = 100;
#if IS_ENABLED(CONFIG_SET_FIDVID)
#if IS_ENABLED(CONFIG_LOGICAL_CPUS) && IS_ENABLED(CONFIG_SET_FIDVID_CORE0_ONLY)
if (id.coreid == 0) // only need set fid for core0
#endif
init_fidvid_ap(bsp_apicid, apicid);
#endif
// We need to stop the CACHE as RAM for this CPU, really?
while (timeout && (loop-- > 0)) {
timeout = wait_cpu_state(bsp_apicid, 0x44);
}
if (timeout) {
printk(BIOS_DEBUG,
"while waiting for BSP signal to STOP, timeout in ap %02x\n",
apicid);
}
lapic_write(LAPIC_MSG_REG, (apicid << 24) | 0x44); // bsp can not check it before stop_this_cpu
set_var_mtrr(0, 0x00000000, CACHE_TMP_RAMTOP, MTRR_TYPE_WRBACK);
#if IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
#if CONFIG_MEM_TRAIN_SEQ == 1
train_ram_on_node(id.nodeid, id.coreid, sysinfo,
(unsigned)STOP_CAR_AND_CPU);
#endif
#endif
STOP_CAR_AND_CPU();
}
return bsp_apicid;
}
static u32 is_core0_started(u32 nodeid)
{
u32 htic;
pci_devfn_t device;
device = PCI_DEV(0, 0x18 + nodeid, 0);
htic = pci_read_config32(device, HT_INIT_CONTROL);
htic &= HTIC_INIT_Detect;
return htic;
}
void wait_all_core0_started(void)
{
/* When core0 is started, it will distingush_cpu_resets
* So wait for that to finish */
u32 i;
u32 nodes = get_nodes();
printk(BIOS_DEBUG, "core0 started: ");
for (i = 1; i < nodes; i++) { // skip bsp, because it is running on bsp
while (!is_core0_started(i)) {
}
printk(BIOS_DEBUG, " %02x", i);
}
printk(BIOS_DEBUG, "\n");
}

View File

@ -1,18 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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.
*/
unsigned char microcode[] __attribute__((aligned(16))) = {
#if !IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
#include "../../../../3rdparty/blobs/cpu/amd/model_fxx/microcode.h"
#endif
};

View File

@ -1,649 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 2004.11 yhlu add d0 e0 support
* 2004.12 yhlu add dual core support
* 2005.02 yhlu add e0 memory hole support
* Copyright 2005 AMD
* 2005.08 yhlu add microcode support
*
* 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.
*/
/* Needed so the AMD K8 runs correctly. */
#include <console/console.h>
#include <cpu/x86/msr.h>
#include <cpu/amd/mtrr.h>
#include <device/device.h>
#include <device/pci.h>
#include <string.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/pae.h>
#include <pc80/mc146818rtc.h>
#include <cpu/x86/lapic.h>
#include "northbridge/amd/amdk8/amdk8.h"
#include <cpu/amd/model_fxx_rev.h>
#include <cpu/amd/microcode.h>
#include <cpu/cpu.h>
#include <cpu/x86/cache.h>
#include <cpu/x86/mtrr.h>
#include <cpu/x86/smm.h>
#include <cpu/amd/multicore.h>
#include <cpu/amd/msr.h>
#if IS_ENABLED(CONFIG_WAIT_BEFORE_CPUS_INIT)
void cpus_ready_for_init(void)
{
#if IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
#if CONFIG_MEM_TRAIN_SEQ == 1
struct sys_info *sysinfox = (struct sys_info *)((CONFIG_RAMTOP) - sizeof(*sysinfox));
// wait for ap memory to trained
wait_all_core0_mem_trained(sysinfox);
#endif
#endif
}
#endif
int is_e0_later_in_bsp(int nodeid)
{
uint32_t val;
uint32_t val_old;
int e0_later;
if (IS_ENABLED(CONFIG_K8_REV_F_SUPPORT))
return 1;
if (nodeid == 0) { // we don't need to do that for node 0 in core0/node0
return !is_cpu_pre_e0();
}
// d0 will be treated as e0 with this methods, but the d0 nb_cfg_54 always 0
struct device *dev;
dev = dev_find_slot(0, PCI_DEVFN(0x18 + nodeid, 2));
if (!dev)
return 0;
val_old = pci_read_config32(dev, 0x80);
val = val_old;
val |= (1 << 3);
pci_write_config32(dev, 0x80, val);
val = pci_read_config32(dev, 0x80);
e0_later = !!(val & (1 << 3));
if (e0_later) { // pre_e0 bit 3 always be 0 and can not be changed
pci_write_config32(dev, 0x80, val_old); // restore it
}
return e0_later;
}
int is_cpu_f0_in_bsp(int nodeid)
{
uint32_t dword;
struct device *dev;
if (!IS_ENABLED(CONFIG_K8_REV_F_SUPPORT))
return 0;
dev = dev_find_slot(0, PCI_DEVFN(0x18 + nodeid, 3));
dword = pci_read_config32(dev, 0xfc);
return (dword & 0xfff00) == 0x40f00;
}
#define MCI_STATUS 0x401
#define MTRR_COUNT 8
#define ZERO_CHUNK_KB 0x800UL /* 2M */
#define TOLM_KB 0x400000UL
struct mtrr {
msr_t base;
msr_t mask;
};
struct mtrr_state {
struct mtrr mtrrs[MTRR_COUNT];
msr_t top_mem, top_mem2;
msr_t def_type;
};
static void save_mtrr_state(struct mtrr_state *state)
{
int i;
for (i = 0; i < MTRR_COUNT; i++) {
state->mtrrs[i].base = rdmsr(MTRR_PHYS_BASE(i));
state->mtrrs[i].mask = rdmsr(MTRR_PHYS_MASK(i));
}
state->top_mem = rdmsr(TOP_MEM);
state->top_mem2 = rdmsr(TOP_MEM2);
state->def_type = rdmsr(MTRR_DEF_TYPE_MSR);
}
static void restore_mtrr_state(struct mtrr_state *state)
{
int i;
disable_cache();
for (i = 0; i < MTRR_COUNT; i++) {
wrmsr(MTRR_PHYS_BASE(i), state->mtrrs[i].base);
wrmsr(MTRR_PHYS_MASK(i), state->mtrrs[i].mask);
}
wrmsr(TOP_MEM, state->top_mem);
wrmsr(TOP_MEM2, state->top_mem2);
wrmsr(MTRR_DEF_TYPE_MSR, state->def_type);
enable_cache();
}
#if 0
static void print_mtrr_state(struct mtrr_state *state)
{
int i;
for (i = 0; i < MTRR_COUNT; i++) {
printk(BIOS_DEBUG, "var mtrr %d: %08x%08x mask: %08x%08x\n",
i,
state->mtrrs[i].base.hi, state->mtrrs[i].base.lo,
state->mtrrs[i].mask.hi, state->mtrrs[i].mask.lo);
}
printk(BIOS_DEBUG, "top_mem: %08x%08x\n",
state->top_mem.hi, state->top_mem.lo);
printk(BIOS_DEBUG, "top_mem2: %08x%08x\n",
state->top_mem2.hi, state->top_mem2.lo);
printk(BIOS_DEBUG, "def_type: %08x%08x\n",
state->def_type.hi, state->def_type.lo);
}
#endif
static void set_init_ecc_mtrrs(void)
{
msr_t msr;
int i;
disable_cache();
/* First clear all of the msrs to be safe */
for (i = 0; i < MTRR_COUNT; i++) {
msr_t zero;
zero.lo = zero.hi = 0;
wrmsr(MTRR_PHYS_BASE(i), zero);
wrmsr(MTRR_PHYS_MASK(i), zero);
}
/* Write back cache from 0x0 to CACHE_TMP_RAMTOP. */
msr.hi = 0x00000000;
msr.lo = 0x00000000 | MTRR_TYPE_WRBACK;
wrmsr(MTRR_PHYS_BASE(0), msr);
msr.hi = 0x000000ff;
msr.lo = ~((CACHE_TMP_RAMTOP) - 1) | 0x800;
wrmsr(MTRR_PHYS_MASK(0), msr);
/* Set the default type to write combining */
msr.hi = 0x00000000;
msr.lo = 0xc00 | MTRR_TYPE_WRCOMB;
wrmsr(MTRR_DEF_TYPE_MSR, msr);
/* Set TOP_MEM to 4G */
msr.hi = 0x00000001;
msr.lo = 0x00000000;
wrmsr(TOP_MEM, msr);
enable_cache();
}
static inline void clear_2M_ram(unsigned long basek,
struct mtrr_state *mtrr_state)
{
unsigned long limitk;
unsigned long size;
void *addr;
/* Report every 64M */
if ((basek % (64 * 1024)) == 0) {
/* Restore the normal state */
map_2M_page(0);
restore_mtrr_state(mtrr_state);
enable_lapic();
/* Print a status message */
printk(BIOS_DEBUG, "%c", (basek >= TOLM_KB) ? '+' : '-');
/* Return to the initialization state */
set_init_ecc_mtrrs();
disable_lapic();
}
limitk = (basek + ZERO_CHUNK_KB) & ~(ZERO_CHUNK_KB - 1);
#if 0
/* couldn't happen, memory must on 2M boundary */
if (limitk > endk) {
limitk = enk;
}
#endif
size = (limitk - basek) << 10;
addr = map_2M_page(basek >> 11);
if (addr == MAPPING_ERROR) {
printk(BIOS_ERR, "Cannot map page: %lx\n", basek >> 11);
return;
}
/* clear memory 2M (limitk - basek) */
addr = (void *)(((uint32_t) addr) | ((basek & 0x7ff) << 10));
memset(addr, 0, size);
}
static void init_ecc_memory(unsigned node_id)
{
unsigned long startk, begink, endk;
unsigned long basek;
struct mtrr_state mtrr_state;
struct device *f1_dev, *f2_dev, *f3_dev;
int enable_scrubbing;
uint32_t dcl;
f1_dev = dev_find_slot(0, PCI_DEVFN(0x18 + node_id, 1));
if (!f1_dev) {
die("Cannot find CPU function 1\n");
}
f2_dev = dev_find_slot(0, PCI_DEVFN(0x18 + node_id, 2));
if (!f2_dev) {
die("Cannot find CPU function 2\n");
}
f3_dev = dev_find_slot(0, PCI_DEVFN(0x18 + node_id, 3));
if (!f3_dev) {
die("Cannot find CPU function 3\n");
}
/* See if we scrubbing should be enabled */
enable_scrubbing = CONFIG_HW_SCRUBBER;
get_option(&enable_scrubbing, "hw_scrubber");
/* Enable cache scrubbing at the lowest possible rate */
if (enable_scrubbing) {
pci_write_config32(f3_dev, SCRUB_CONTROL,
(SCRUB_84ms << 16) | (SCRUB_84ms << 8) |
(SCRUB_NONE << 0));
} else {
pci_write_config32(f3_dev, SCRUB_CONTROL,
(SCRUB_NONE << 16) | (SCRUB_NONE << 8) |
(SCRUB_NONE << 0));
printk(BIOS_DEBUG, "Scrubbing Disabled\n");
}
/* If ecc support is not enabled don't touch memory */
dcl = pci_read_config32(f2_dev, DRAM_CONFIG_LOW);
if (!(dcl & DCL_DimmEccEn)) {
printk(BIOS_DEBUG, "ECC Disabled\n");
return;
}
startk =
(pci_read_config32(f1_dev, 0x40 + (node_id * 8)) & 0xffff0000) >> 2;
endk =
((pci_read_config32(f1_dev, 0x44 + (node_id * 8)) & 0xffff0000) >>
2) + 0x4000;
#if CONFIG_HW_MEM_HOLE_SIZEK != 0
unsigned long hole_startk = 0;
if (IS_ENABLED(CONFIG_K8_REV_F_SUPPORT) || !is_cpu_pre_e0()) {
uint32_t val;
val = pci_read_config32(f1_dev, 0xf0);
if (val & 1) {
hole_startk = ((val & (0xff << 24)) >> 10);
}
}
#endif
/* Don't start too early */
begink = startk;
if (begink < (CONFIG_RAMTOP >> 10)) {
begink = (CONFIG_RAMTOP >> 10);
}
printk(BIOS_DEBUG, "Clearing memory %luK - %luK: ", begink, endk);
/* Save the normal state */
save_mtrr_state(&mtrr_state);
/* Switch to the init ecc state */
set_init_ecc_mtrrs();
disable_lapic();
/* Walk through 2M chunks and zero them */
#if CONFIG_HW_MEM_HOLE_SIZEK != 0
/* here hole_startk can not be equal to begink, never. Also hole_startk is in 2M boundary, 64M? */
if ((hole_startk != 0)
&& ((begink < hole_startk) && (endk > (4 * 1024 * 1024)))) {
for (basek = begink; basek < hole_startk;
basek = ((basek + ZERO_CHUNK_KB) & ~(ZERO_CHUNK_KB - 1))) {
clear_2M_ram(basek, &mtrr_state);
}
for (basek = 4 * 1024 * 1024; basek < endk;
basek = ((basek + ZERO_CHUNK_KB) & ~(ZERO_CHUNK_KB - 1))) {
clear_2M_ram(basek, &mtrr_state);
}
} else
#endif
for (basek = begink; basek < endk;
basek = ((basek + ZERO_CHUNK_KB) & ~(ZERO_CHUNK_KB - 1))) {
clear_2M_ram(basek, &mtrr_state);
}
/* Restore the normal state */
map_2M_page(0);
restore_mtrr_state(&mtrr_state);
enable_lapic();
/* Set the scrub base address registers */
pci_write_config32(f3_dev, SCRUB_ADDR_LOW, startk << 10);
pci_write_config32(f3_dev, SCRUB_ADDR_HIGH, startk >> 22);
/* Enable the scrubber? */
if (enable_scrubbing) {
/* Enable scrubbing at the lowest possible rate */
pci_write_config32(f3_dev, SCRUB_CONTROL,
(SCRUB_84ms << 16) | (SCRUB_84ms << 8) |
(SCRUB_84ms << 0));
}
printk(BIOS_DEBUG, " done\n");
}
static void k8_pre_f_errata(void)
{
msr_t msr;
if (is_cpu_pre_c0()) {
/* Erratum 63... */
msr = rdmsr(HWCR_MSR);
msr.lo |= (1 << 6);
wrmsr(HWCR_MSR, msr);
/* Erratum 69... */
msr = rdmsr_amd(BU_CFG_MSR);
msr.hi |= (1 << (45 - 32));
wrmsr_amd(BU_CFG_MSR, msr);
/* Erratum 81... */
msr = rdmsr_amd(DC_CFG_MSR);
msr.lo |= (1 << 10);
wrmsr_amd(DC_CFG_MSR, msr);
}
/* Erratum 97 ... */
if (!is_cpu_pre_c0() && is_cpu_pre_d0()) {
msr = rdmsr_amd(DC_CFG_MSR);
msr.lo |= 1 << 3;
wrmsr_amd(DC_CFG_MSR, msr);
}
/* Erratum 94 ... */
if (is_cpu_pre_d0()) {
msr = rdmsr_amd(IC_CFG_MSR);
msr.lo |= 1 << 11;
wrmsr_amd(IC_CFG_MSR, msr);
}
/* Erratum 91 prefetch miss is handled in the kernel */
/* Erratum 106 ... */
msr = rdmsr_amd(LS_CFG_MSR);
msr.lo |= 1 << 25;
wrmsr_amd(LS_CFG_MSR, msr);
/* Erratum 107 ... */
msr = rdmsr_amd(BU_CFG_MSR);
msr.hi |= 1 << (43 - 32);
wrmsr_amd(BU_CFG_MSR, msr);
/* Erratum 110 */
/* This erratum applies to D0 thru E6 revisions
* Revision F and later are unaffected. There are two fixes
* depending on processor revision.
*/
if (is_cpu_d0()) {
/* Erratum 110 ... */
msr = rdmsr_amd(CPU_ID_HYPER_EXT_FEATURES);
msr.hi |= 1;
wrmsr_amd(CPU_ID_HYPER_EXT_FEATURES, msr);
}
if (!is_cpu_pre_e0())
{
/* Erratum 110 ... */
msr = rdmsr_amd(CPU_ID_EXT_FEATURES_MSR);
msr.hi |= 1;
wrmsr_amd(CPU_ID_EXT_FEATURES_MSR, msr);
}
}
static void k8_errata(void)
{
msr_t msr;
/* I can't touch this msr on early buggy cpus */
if (!is_cpu_pre_b3()) {
msr = rdmsr(NB_CFG_MSR);
if (is_cpu_pre_d0() && !is_cpu_pre_c0()) {
/* D0 later don't need it */
/* Erratum 86 Disable data masking on C0 and
* later processor revs.
* FIXME this is only needed if ECC is enabled.
*/
msr.hi |= 1 << (36 - 32);
}
/* Erratum 89 ... */
/* Erratum 89 is mistakenly labeled as 88 in AMD pub #25759
* It is correctly labeled as 89 on page 49 of the document
* and in AMD pub#33610
*/
msr.lo |= 1 << 3;
/* Erratum 169 */
/* This supersedes erratum 131; 131 should not be applied with 169
* We also need to set some bits in the northbridge, handled in src/northbridge/amdk8/
*/
msr.hi |= 1;
wrmsr(NB_CFG_MSR, msr);
}
/* Erratum 122 */
msr = rdmsr(HWCR_MSR);
msr.lo |= 1 << 6;
wrmsr(HWCR_MSR, msr);
}
static void model_fxx_init(struct device *dev)
{
unsigned long i;
msr_t msr;
struct node_core_id id;
/* Turn on caching if we haven't already */
x86_enable_cache();
/* Initialize all variable MTRRs except the first pair */
msr.hi = 0x00000000;
msr.lo = 0x00000000;
disable_cache();
for (i = 0x2; i < 0x10; i++) {
wrmsr(0x00000200 | i, msr);
}
enable_cache();
amd_setup_mtrrs();
x86_mtrr_check();
/* Update the microcode */
update_microcode(dev->device);
disable_cache();
/* zero the machine check error status registers */
msr.lo = 0;
msr.hi = 0;
for (i = 0; i < 5; i++) {
wrmsr(MCI_STATUS + (i * 4), msr);
}
if (!IS_ENABLED(CONFIG_K8_REV_F_SUPPORT))
k8_pre_f_errata();
k8_errata();
enable_cache();
/* Set the processor name string */
init_processor_name();
/* Enable the local CPU APICs */
setup_lapic();
#if IS_ENABLED(CONFIG_LOGICAL_CPUS)
u32 siblings = cpuid_ecx(0x80000008) & 0xff;
if (siblings > 0) {
msr = rdmsr_amd(CPU_ID_FEATURES_MSR);
msr.lo |= 1 << 28;
wrmsr_amd(CPU_ID_FEATURES_MSR, msr);
msr = rdmsr_amd(LOGICAL_CPUS_NUM_MSR);
msr.lo = (siblings + 1) << 16;
wrmsr_amd(LOGICAL_CPUS_NUM_MSR, msr);
msr = rdmsr_amd(CPU_ID_EXT_FEATURES_MSR);
msr.hi |= 1 << (33 - 32);
wrmsr_amd(CPU_ID_EXT_FEATURES_MSR, msr);
}
printk(BIOS_DEBUG, "siblings = %02d, ", siblings);
#endif
id = get_node_core_id(read_nb_cfg_54()); // pre e0 nb_cfg_54 can not be set
/* Is this a bad location? In particular can another node prefetch
* data from this node before we have initialized it?
*/
if (id.coreid == 0)
init_ecc_memory(id.nodeid); // only do it for core 0
/* Set SMM base address for this CPU */
msr = rdmsr(SMM_BASE_MSR);
msr.lo = SMM_BASE - (lapicid() * 0x400);
wrmsr(SMM_BASE_MSR, msr);
/* Enable the SMM memory window */
msr = rdmsr(SMM_MASK_MSR);
msr.lo |= (1 << 0); /* Enable ASEG SMRAM Range */
wrmsr(SMM_MASK_MSR, msr);
/* Set SMMLOCK to avoid exploits messing with SMM */
msr = rdmsr(HWCR_MSR);
msr.lo |= (1 << 0);
wrmsr(HWCR_MSR, msr);
}
static struct device_operations cpu_dev_ops = {
.init = model_fxx_init,
};
static const struct cpu_device_id cpu_table[] = {
#if !IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
{ X86_VENDOR_AMD, 0xf40 }, /* SH-B0 (socket 754) */
{ X86_VENDOR_AMD, 0xf50 }, /* SH-B0 (socket 940) */
{ X86_VENDOR_AMD, 0xf51 }, /* SH-B3 (socket 940) */
{ X86_VENDOR_AMD, 0xf58 }, /* SH-C0 (socket 940) */
{ X86_VENDOR_AMD, 0xf48 }, /* SH-C0 (socket 754) */
{ X86_VENDOR_AMD, 0xf5a }, /* SH-CG (socket 940) */
{ X86_VENDOR_AMD, 0xf4a }, /* SH-CG (socket 754) */
{ X86_VENDOR_AMD, 0xf7a }, /* SH-CG (socket 939) */
{ X86_VENDOR_AMD, 0xfc0 }, /* DH-CG (socket 754) */
{ X86_VENDOR_AMD, 0xfe0 }, /* DH-CG (socket 754) */
{ X86_VENDOR_AMD, 0xff0 }, /* DH-CG (socket 939) */
{ X86_VENDOR_AMD, 0xf82 }, /* CH-CG (socket 754) */
{ X86_VENDOR_AMD, 0xfb2 }, /* CH-CG (socket 939) */
/* AMD D0 support */
{ X86_VENDOR_AMD, 0x10f50 }, /* SH-D0 (socket 940) */
{ X86_VENDOR_AMD, 0x10f40 }, /* SH-D0 (socket 754) */
{ X86_VENDOR_AMD, 0x10f70 }, /* SH-D0 (socket 939) */
{ X86_VENDOR_AMD, 0x10fc0 }, /* DH-D0 (socket 754) */
{ X86_VENDOR_AMD, 0x10ff0 }, /* DH-D0 (socket 939) */
{ X86_VENDOR_AMD, 0x10f80 }, /* CH-D0 (socket 754) */
{ X86_VENDOR_AMD, 0x10fb0 }, /* CH-D0 (socket 939) */
/* AMD E0 support */
{ X86_VENDOR_AMD, 0x20f50 }, /* SH-E0 */
{ X86_VENDOR_AMD, 0x20f40 },
{ X86_VENDOR_AMD, 0x20f70 },
{ X86_VENDOR_AMD, 0x20fc0 }, /* DH-E3 (socket 754) */
{ X86_VENDOR_AMD, 0x20ff0 }, /* DH-E3 (socket 939) */
{ X86_VENDOR_AMD, 0x20f10 }, /* JH-E1 (socket 940) */
{ X86_VENDOR_AMD, 0x20f51 }, /* SH-E4 (socket 940) */
{ X86_VENDOR_AMD, 0x20f71 }, /* SH-E4 (socket 939) */
{ X86_VENDOR_AMD, 0x20fb1 }, /* BH-E4 (socket 939) */
{ X86_VENDOR_AMD, 0x20f42 }, /* SH-E5 (socket 754) */
{ X86_VENDOR_AMD, 0x20ff2 }, /* DH-E6 (socket 939) */
{ X86_VENDOR_AMD, 0x20fc2 }, /* DH-E6 (socket 754) */
{ X86_VENDOR_AMD, 0x20f12 }, /* JH-E6 (socket 940) */
{ X86_VENDOR_AMD, 0x20f32 }, /* JH-E6 (socket 939) */
{ X86_VENDOR_AMD, 0x30ff2 }, /* E4 ? */
#endif
#if IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
/*
* AMD F0 support.
*
* See Revision Guide for AMD NPT Family 0Fh Processors,
* Publication #33610, Revision: 3.30, February 2008.
*
* http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/33610.pdf
*/
{ X86_VENDOR_AMD, 0x40f50 }, /* SH-F0 (socket F/1207) */
{ X86_VENDOR_AMD, 0x40f70 }, /* SH-F0 (socket AM2) */
{ X86_VENDOR_AMD, 0x40f40 }, /* SH-F0 (socket S1g1) */
{ X86_VENDOR_AMD, 0x40f11 }, /* JH-F1 (socket F/1207) */
{ X86_VENDOR_AMD, 0x40f31 }, /* JH-F1 (socket AM2) */
{ X86_VENDOR_AMD, 0x40f01 }, /* JH-F1 (socket S1g1) */
{ X86_VENDOR_AMD, 0x40f12 }, /* JH-F2 (socket F/1207) */
{ X86_VENDOR_AMD, 0x40f32 }, /* JH-F2 (socket AM2) */
{ X86_VENDOR_AMD, 0x40fb2 }, /* BH-F2 (socket AM2) */
{ X86_VENDOR_AMD, 0x40f82 }, /* BH-F2 (socket S1g1) */
{ X86_VENDOR_AMD, 0x40ff2 }, /* DH-F2 (socket AM2) */
{ X86_VENDOR_AMD, 0x50ff2 }, /* DH-F2 (socket AM2) */
{ X86_VENDOR_AMD, 0x40fc2 }, /* DH-F2 (socket S1g1) */
{ X86_VENDOR_AMD, 0x40f13 }, /* JH-F3 (socket F/1207) */
{ X86_VENDOR_AMD, 0x40f33 }, /* JH-F3 (socket AM2) */
{ X86_VENDOR_AMD, 0x50fd3 }, /* JH-F3 (socket F/1207) */
{ X86_VENDOR_AMD, 0xc0f13 }, /* JH-F3 (socket F/1207) */
{ X86_VENDOR_AMD, 0x50ff3 }, /* DH-F3 (socket AM2) */
{ X86_VENDOR_AMD, 0x60fb1 }, /* BH-G1 (socket AM2) */
{ X86_VENDOR_AMD, 0x60f81 }, /* BH-G1 (socket S1g1) */
{ X86_VENDOR_AMD, 0x60fb2 }, /* BH-G2 (socket AM2) */
{ X86_VENDOR_AMD, 0x60f82 }, /* BH-G2 (socket S1g1) */
{ X86_VENDOR_AMD, 0x70ff1 }, /* DH-G1 (socket AM2) */
{ X86_VENDOR_AMD, 0x60ff2 }, /* DH-G2 (socket AM2) */
{ X86_VENDOR_AMD, 0x70ff2 }, /* DH-G2 (socket AM2) */
{ X86_VENDOR_AMD, 0x60fc2 }, /* DH-G2 (socket S1g1) */
{ X86_VENDOR_AMD, 0x70fc2 }, /* DH-G2 (socket S1g1) */
#endif
{ 0, 0 },
};
static const struct cpu_driver model_fxx __cpu_driver = {
.ops = &cpu_dev_ops,
.id_table = cpu_table,
};

View File

@ -1,88 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2005 Advanced Micro Devices, Inc.
* Copyright (C) 2010 Advanced Micro Devices, Inc.
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <cpu/amd/microcode.h>
struct id_mapping {
uint32_t orig_id;
uint16_t new_id;
};
static u16 get_equivalent_processor_rev_id(u32 orig_id) {
static const struct id_mapping id_mapping_table[] = {
#if !IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
{ 0x0f48, 0x0048 },
{ 0x0f58, 0x0048 },
{ 0x0f4a, 0x004a },
{ 0x0f5a, 0x004a },
{ 0x0f7a, 0x004a },
{ 0x0f82, 0x004a },
{ 0x0fc0, 0x004a },
{ 0x0ff0, 0x004a },
{ 0x10f50, 0x0150 },
{ 0x10f70, 0x0150 },
{ 0x10f80, 0x0150 },
{ 0x10fc0, 0x0150 },
{ 0x10ff0, 0x0150 },
{ 0x20f10, 0x0210 },
{ 0x20f12, 0x0210 },
{ 0x20f32, 0x0210 },
{ 0x20fb1, 0x0210 },
#endif
#if IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
/* FIXME
* Microcode files for CPU revision 0xf do
* not seem to be available...
*/
{ 0x40f10, 0x0410 },
{ 0x40f13, 0x0410 },
#endif
/* Array terminator */
{ 0xffffff, 0x0000 },
};
unsigned new_id;
int i;
new_id = 0;
for (i = 0; id_mapping_table[i].orig_id != 0xffffff; i++ ) {
if (id_mapping_table[i].orig_id == orig_id) {
new_id = id_mapping_table[i].new_id;
break;
}
}
return new_id;
}
void update_microcode(uint32_t cpu_deviceid)
{
uint32_t equivalent_rev_id;
/* Update the microcode */
equivalent_rev_id = get_equivalent_processor_rev_id(cpu_deviceid);
amd_update_microcode_from_cbfs(equivalent_rev_id);
}

View File

@ -1,945 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008 Advanced Micro Devices, Inc.
* Copyright (C) 2009 Rudolf Marek <r.marek@assembler.cz>
*
* 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 <stdint.h>
#include <cpu/x86/msr.h>
#include <arch/acpigen.h>
#include <cpu/amd/powernow.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <cpu/x86/msr.h>
#include <cpu/amd/mtrr.h>
#include <cpu/amd/amdk8_sysconf.h>
#include <arch/cpu.h>
static void write_pstates_for_core(u8 pstate_num, u16 *pstate_feq,
u8 *pstate_vid, u8 *pstate_fid,
u32 *pstate_power, int coreID,
u32 pcontrol_blk, u8 plen, u8 onlyBSP,
u32 control)
{
int i;
if ((onlyBSP) && (coreID != 0)) {
plen = 0;
pcontrol_blk = 0;
}
acpigen_write_processor(coreID, pcontrol_blk, plen);
acpigen_write_empty_PCT();
acpigen_write_name("_PSS");
/* add later to total sum */
acpigen_write_package(pstate_num);
for (i = 0; i < pstate_num; i++) {
u32 status, c2;
c2 = control | (pstate_vid[i] << 6) |
pstate_fid[i];
status =
(pstate_vid[i] << 6) |
pstate_fid[i];
acpigen_write_PSS_package(pstate_feq[i],
pstate_power[i],
0x64,
0x7,
c2,
status);
}
/* update the package size */
acpigen_pop_len();
acpigen_write_PPC(pstate_num);
/* patch the whole Processor token length */
acpigen_pop_len();
}
#if IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
/*
* Details about this algorithm , refer to BDKG 10.5.1
* Two parts are included, the another is the DSDT reconstruction process
*/
static void pstates_algorithm(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
{
u8 processor_brand[49];
u32 *v, control;
struct cpuid_result cpuid1;
struct power_limit_encoding {
u8 socket_type;
u8 cmp_cap;
u8 pwr_lmt;
u32 power_limit;
};
u8 Max_fid, Max_vid, Start_fid, Start_vid, Min_fid, Min_vid;
u16 Max_feq;
u8 Pstate_fid[10];
u16 Pstate_feq[10];
u8 Pstate_vid[10];
u32 Pstate_power[10];
u32 Pstate_volt[10];
u8 PstateStep, PstateStep_coef;
u8 IntPstateSup;
u8 Pstate_num;
u16 Cur_feq;
u8 Cur_fid;
u8 cmp_cap, pwr_lmt;
u32 power_limit = 0;
u8 index;
uint8_t node_count;
uint8_t cores_per_node;
uint32_t total_core_count;
uint32_t dword;
msr_t msr;
u32 fid_multiplier;
static const struct power_limit_encoding TDP[] = {
{0x10, 0x1, 0x2, 45}, /* Opteron EE */
{0x10, 0x1, 0x6, 68}, /* Opteron HE */
{0x10, 0x1, 0xa, 95}, /* Opteron */
{0x10, 0x1, 0xc, 119}, /* Opteron SE */
{0x10, 0x1, 0xe, 125}, /* Athlon 64 FX-7x */
{0x11, 0x0, 0x8, 62},
{0x11, 0x1, 0x8, 89},
{0x11, 0x1, 0xa, 103},
{0x11, 0x1, 0xc, 125},
{0x11, 0x0, 0x2, 15},
{0x11, 0x0, 0x4, 35},
{0x11, 0x1, 0x2, 35},
{0x11, 0x0, 0x5, 45},
{0x11, 0x1, 0x7, 76},
{0x11, 0x1, 0x6, 65},
{0x11, 0x1, 0x8, 89},
{0x11, 0x0, 0x1, 8},
{0x11, 0x1, 0x1, 22},
{0x12, 0x0, 0x6, 25},
{0x12, 0x0, 0x1, 8},
{0x12, 0x0, 0x2, 9},
{0x12, 0x0, 0x4, 15},
{0x12, 0x0, 0xc, 35},
{0x12, 0x1, 0xc, 35},
{0x12, 0x1, 0x4, 20}
};
/* Get the Processor Brand String using
* cpuid(0x8000000x) command x=2,3,4
*/
cpuid1 = cpuid(0x80000002);
v = (u32 *) processor_brand;
v[0] = cpuid1.eax;
v[1] = cpuid1.ebx;
v[2] = cpuid1.ecx;
v[3] = cpuid1.edx;
cpuid1 = cpuid(0x80000003);
v[4] = cpuid1.eax;
v[5] = cpuid1.ebx;
v[6] = cpuid1.ecx;
v[7] = cpuid1.edx;
cpuid1 = cpuid(0x80000004);
v[8] = cpuid1.eax;
v[9] = cpuid1.ebx;
v[10] = cpuid1.ecx;
v[11] = cpuid1.edx;
processor_brand[48] = 0;
printk(BIOS_INFO, "processor_brand=%s\n", processor_brand);
/*
* Based on the CPU socket type,cmp_cap and pwr_lmt,
* get the power limit.
* socket_type : 0x10 SocketF; 0x11 AM2/ASB1; 0x12 S1G1
* cmp_cap : 0x0 SingleCore; 0x1 DualCore
*/
printk(BIOS_INFO, "Pstates Algorithm ...\n");
/* Get number of cores */
dword = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x18, 3)), 0xe8);
cmp_cap = (dword & 0x3000) >> 12;
/* Get number of nodes */
dword = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x18, 0)), 0x60);
node_count = ((dword & 0x70) >> 4) + 1;
cores_per_node = cmp_cap + 1;
/* Compute total number of cores installed in system */
total_core_count = cores_per_node * node_count;
cpuid1 = cpuid(0x80000001);
pwr_lmt = ((cpuid1.ebx & 0x1C0) >> 5) | ((cpuid1.ebx & 0x4000) >> 14);
for (index = 0; index < ARRAY_SIZE(TDP); index++)
if (TDP[index].socket_type == CONFIG_CPU_SOCKET_TYPE &&
TDP[index].cmp_cap == cmp_cap &&
TDP[index].pwr_lmt == pwr_lmt) {
power_limit = TDP[index].power_limit;
}
Pstate_num = 0;
/* See if the CPUID(0x80000007) returned EDX[2:1]==11b */
cpuid1 = cpuid(0x80000007);
if ((cpuid1.edx & 0x6) != 0x6) {
printk(BIOS_INFO, "No valid set of P-states\n");
goto write_pstates;
}
msr = rdmsr(0xc0010042);
Max_fid = (msr.lo & 0x3F0000) >> 16;
Start_fid = (msr.lo & 0x3F00) >> 8;
Max_vid = (msr.hi & 0x3F0000) >> 16;
Start_vid = (msr.hi & 0x3F00) >> 8;
PstateStep = (msr.hi & 0x1000000) >> 24;
IntPstateSup = (msr.hi & 0x20000000) >> 29;
/*
* The P1...P[Min+1] VID need PstateStep to calculate
* P[N] = P[N-1]VID + 2^PstateStep
* PstateStep_coef = 2^PstateStep
*/
if (PstateStep == 0)
PstateStep_coef = 1;
else
PstateStep_coef = 2;
/* Get the multiplier of the fid frequency */
/*
* Fid multiplier is always 100 revF and revG.
*/
fid_multiplier = 100;
/*
* Formula1: CPUFreq = FID * fid_multiplier + 800
* Formula2: CPUVolt = 1550 - VID * 25 (mv)
* Formula3: Power = (PwrLmt * P[N]Frequency*(P[N]Voltage^2))
/(P[0]Frequency * P[0]Voltage^2))
*/
/* Construct P0(P[Max]) state */
Max_feq = Max_fid * fid_multiplier + 800;
if (Max_fid == 0x2A && Max_vid != 0x0) {
Min_fid = 0x2;
/* Start Frequency + 1GHz */
Pstate_fid[0] = Start_fid + 0xA;
Pstate_feq[0] = Pstate_fid[0] * fid_multiplier + 800;
Min_vid = Start_vid;
Pstate_vid[0] = Max_vid + 0x2; /* Maximum Voltage - 50mV */
Pstate_volt[0] = 1550 - Pstate_vid[0] * 25;
Pstate_power[0] = power_limit * 1000; /* mw */
Pstate_num++;
} else {
Min_fid = Start_fid;
Pstate_fid[0] = Max_fid;
Pstate_feq[0] = Max_feq;
Min_vid = Start_vid;
Pstate_vid[0] = Max_vid + 0x2;
Pstate_volt[0] = 1550 - Pstate_vid[0] * 25;
Pstate_power[0] = power_limit * 1000; /* mw */
Pstate_num++;
}
if (IntPstateSup == 0) {
printk(BIOS_SPEW, "No intermediate P-states are supported\n");
goto nointpstatesup;
}
Cur_feq = Max_feq;
Cur_fid = Max_fid;
/* Construct P1 state */
/* if odd value */
if (((Max_fid & 0x1) != 0) && ((Max_fid - 0x1) >= (Min_fid + 0x8))) {
Pstate_fid[1] = Max_fid - 0x1;
Pstate_feq[1] = Pstate_fid[1] * fid_multiplier + 800;
Cur_fid = Pstate_fid[1];
Cur_feq = Pstate_feq[1];
/* if odd value */
if (((Pstate_vid[0] & 0x1) != 0) &&
((Pstate_vid[0] - 0x1) < Min_vid)) {
Pstate_vid[1] = Pstate_vid[0] + 0x1;
Pstate_volt[1] = 1550 - Pstate_vid[1] * 25;
Pstate_power[1] =
((unsigned long long)Pstate_power[0] *
Pstate_feq[1] * Pstate_volt[1] * Pstate_volt[1]) /
((unsigned long long)Pstate_feq[0] *
Pstate_volt[0] *
Pstate_volt[0]);
}
/* if even value */
if (((Pstate_vid[0] & 0x1) == 0) &&
((Pstate_vid[0] - 0x1) < Min_vid)) {
Pstate_vid[1] = Pstate_vid[0] + PstateStep_coef;
Pstate_volt[1] = 1550 - Pstate_vid[1] * 25;
Pstate_power[1] =
((unsigned long long)Pstate_power[0] *
Pstate_feq[1] * Pstate_volt[1] * Pstate_volt[1]) /
((unsigned long long)Pstate_feq[0] *
Pstate_volt[0] *
Pstate_volt[0]);
}
Pstate_num++;
}
/* if even value */
if (((Max_fid & 0x1) == 0) && ((Max_fid - 0x2) >= (Min_fid + 0x8))) {
Pstate_fid[1] = Max_fid - 0x2;
Pstate_feq[1] = Pstate_fid[1] * fid_multiplier + 800;
Cur_fid = Pstate_fid[1];
Cur_feq = Pstate_feq[1];
/* if odd value */
if (((Pstate_vid[0] & 0x1) != 0) &&
((Pstate_vid[0] - 0x1) < Min_vid)) {
Pstate_vid[1] = Pstate_vid[0] + 0x1;
Pstate_volt[1] = 1550 - Pstate_vid[1] * 25;
Pstate_power[1] =
((unsigned long long)Pstate_power[0] *
Pstate_feq[1] * Pstate_volt[1] * Pstate_volt[1]) /
((unsigned long long)Pstate_feq[0] *
Pstate_volt[0] *
Pstate_volt[0]);
}
/* if even value */
if (((Pstate_vid[0] & 0x1) == 0) &&
((Pstate_vid[0] - 0x1) < Min_vid)) {
Pstate_vid[1] = Pstate_vid[0] + PstateStep_coef;
Pstate_volt[1] = 1550 - Pstate_vid[1] * 25;
Pstate_power[1] =
((unsigned long long)Pstate_power[0] *
Pstate_feq[1] * Pstate_volt[1] * Pstate_volt[1]) /
((unsigned long long)Pstate_feq[0] *
Pstate_volt[0] *
Pstate_volt[0]);
}
Pstate_num++;
}
/* Construct P2...P[Min-1] state */
Cur_fid = Cur_fid - 0x2;
Cur_feq = Cur_fid * fid_multiplier + 800;
while (Cur_feq >= ((Min_fid * fid_multiplier) + 800) * 2) {
Pstate_fid[Pstate_num] = Cur_fid;
Pstate_feq[Pstate_num] =
Pstate_fid[Pstate_num] * fid_multiplier + 800;
Cur_fid = Cur_fid - 0x2;
Cur_feq = Cur_fid * fid_multiplier + 800;
if (Pstate_vid[Pstate_num - 1] >= Min_vid) {
Pstate_vid[Pstate_num] = Pstate_vid[Pstate_num - 1];
Pstate_volt[Pstate_num] = Pstate_volt[Pstate_num - 1];
Pstate_power[Pstate_num] = Pstate_power[Pstate_num - 1];
} else {
Pstate_vid[Pstate_num] =
Pstate_vid[Pstate_num - 1] + PstateStep_coef;
Pstate_volt[Pstate_num] =
1550 - Pstate_vid[Pstate_num] * 25;
Pstate_power[Pstate_num] =
((unsigned long long)Pstate_power[0] *
Pstate_feq[Pstate_num] * Pstate_volt[Pstate_num] *
Pstate_volt[Pstate_num]) /
((unsigned long long)Pstate_feq[0] *
Pstate_volt[0] * Pstate_volt[0]);
}
Pstate_num++;
}
nointpstatesup:
/* Construct P[Min] State */
if (Max_fid == 0x2A && Max_vid != 0x0) {
Pstate_fid[Pstate_num] = 0x2;
Pstate_feq[Pstate_num] =
Pstate_fid[Pstate_num] * fid_multiplier + 800;
Pstate_vid[Pstate_num] = Min_vid;
Pstate_volt[Pstate_num] = 1550 - Pstate_vid[Pstate_num] * 25;
Pstate_power[Pstate_num] =
((unsigned long long)Pstate_power[0] *
Pstate_feq[Pstate_num] * Pstate_volt[Pstate_num] *
Pstate_volt[Pstate_num]) /
((unsigned long long)Pstate_feq[0] * Pstate_volt[0] *
Pstate_volt[0]);
Pstate_num++;
} else {
Pstate_fid[Pstate_num] = Start_fid;
Pstate_feq[Pstate_num] =
Pstate_fid[Pstate_num] * fid_multiplier + 800;
Pstate_vid[Pstate_num] = Min_vid;
Pstate_volt[Pstate_num] = 1550 - Pstate_vid[Pstate_num] * 25;
Pstate_power[Pstate_num] =
((unsigned long long)Pstate_power[0] *
Pstate_feq[Pstate_num] * Pstate_volt[Pstate_num] *
Pstate_volt[Pstate_num]) /
((unsigned long long)Pstate_feq[0] * Pstate_volt[0] *
Pstate_volt[0]);
Pstate_num++;
}
/* Print Pstate freq,vid,volt,power */
for (index = 0; index < Pstate_num; index++) {
printk(BIOS_INFO, "Pstate_freq[%d] = %dMHz\t", index,
Pstate_feq[index]);
printk(BIOS_INFO, "Pstate_vid[%d] = %d\t",
index, Pstate_vid[index]);
printk(BIOS_INFO, "Pstate_volt[%d] = %dmv\t", index,
Pstate_volt[index]);
printk(BIOS_INFO, "Pstate_power[%d] = %dmw\n", index,
Pstate_power[index]);
}
write_pstates:
control = (0x3 << 30) | /* IRT */
(0x2 << 28) | /* RVO */
(0x1 << 27) | /* ExtType */
(0x2 << 20) | /* PLL_LOCK_TIME */
(0x0 << 18) | /* MVS */
(0x5 << 11); /* VST */
for (index = 0; index < total_core_count; index++) {
write_pstates_for_core(Pstate_num, Pstate_feq, Pstate_vid,
Pstate_fid, Pstate_power, index,
pcontrol_blk, plen, onlyBSP, control);
}
}
#else
static uint8_t vid_to_reg(uint32_t vid)
{
return (1550 - vid) / 25;
}
static uint32_t vid_from_reg(uint8_t val)
{
return (val == 0x1f ? 0 : 1550 - val * 25);
}
static uint8_t freq_to_fid(uint32_t freq)
{
return (freq - 800) / 100;
}
/* Return a frequency in MHz, given an input fid */
static uint32_t fid_to_freq(uint32_t fid)
{
return 800 + (fid * 100);
}
#define MAXP 7
struct pstate {
uint16_t freqMhz; /* in MHz */
uint16_t voltage; /* in mV */
uint16_t tdp; /* in W * 10 */
};
struct cpuentry {
/* numeric model value, unused in code */
uint16_t modelnr;
/* CPUID 8000_0001h EBX [11:6] (BrandID) */
uint8_t brandID;
/* CPUID 8000_0001h EAX [31:0] (CPUID) */
uint32_t cpuid;
/* FID/VID Status MaxFID Field */
uint8_t maxFID;
/* FID/VID Status StartFID Field */
uint8_t startFID;
/* Thermal Design Power of Max P-State *10 (fixed point) */
uint16_t pwr:12;
/* Other MAX P state are read from CPU,
* other P states in following table
*/
struct pstate pstates[MAXP];
};
struct cpuentry entr[] = {
/* rev E single core, check OSA152FAA5BK */
{152, 0xc, 0x20f51, 0x12, 0x12, 926,
{{2400, 1350, 900}, {2200, 1300, 766},
{2000, 1250, 651}, {1800, 1200, 522},
{1000, 1100, 320} } },
{252, 0x10, 0x20f51, 0x12, 0x12, 926,
{{2400, 1350, 900}, {2200, 1300, 766},
{2000, 1250, 651}, {1800, 1200, 522},
{1000, 1100, 320} } },
{852, 0x14, 0x20f51, 0x12, 0x12, 926,
{{2400, 1350, 900}, {2200, 1300, 766},
{2000, 1250, 651}, {1800, 1200, 522},
{1000, 1100, 320} } },
{254, 0x10, 0x20f51, 0x14, 0x14, 926,
{{2600, 1350, 902}, {2400, 1300, 770},
{2200, 1250, 657}, {2000, 1200, 559},
{1800, 1150, 476}, {1000, 1100, 361} } },
{854, 0x14, 0x20f51, 0x14, 0x14, 926,
{{2600, 1350, 902}, {2400, 1300, 770},
{2200, 1250, 657}, {2000, 1200, 559},
{1800, 1150, 476}, {1000, 1100, 361} } },
{242, 0x10, 0x20f51, 0x8, 0x8, 853,
{} },
{842, 0x10, 0x20f51, 0x8, 0x8, 853,
{} },
{244, 0x10, 0x20f51, 0xa, 0xa, 853,
{{1000, 1100, 378} } },
{844, 0x14, 0x20f51, 0xa, 0xa, 853,
{{1000, 1100, 378} } },
{246, 0x10, 0x20f51, 0xc, 0xc, 853,
{{1800, 1350, 853},
{1000, 1100, 378} } },
{846, 0x14, 0x20f51, 0xc, 0xc, 853,
{{1800, 1350, 853},
{1000, 1100, 378} } },
{242, 0x10, 0x20f51, 0x8, 0x8, 853,
{} },
{842, 0x14, 0x20f51, 0x8, 0x8, 853,
{} },
{244, 0x10, 0x20f51, 0xa, 0xa, 853,
{{1000, 1100, 378} } },
{844, 0x14, 0x20f51, 0xa, 0xa, 853,
{{1000, 1100, 378} } },
{246, 0x10, 0x20f51, 0xc, 0xc, 853,
{{1800, 1350, 827}, {1000, 1100, 366} } },
{846, 0x14, 0x20f51, 0xc, 0xc, 853,
{{1800, 1350, 827}, {1000, 1100, 366} } },
{248, 0x10, 0x20f51, 0xe, 0xe, 853,
{{2000, 1350, 827}, {1800, 1300, 700},
{1000, 1100, 366} } },
{848, 0x14, 0x20f51, 0xe, 0xe, 853,
{{2000, 1350, 827}, {1800, 1300, 700},
{1000, 1100, 366} } },
{250, 0x10, 0x20f51, 0x10, 0x10, 853,
{{2200, 1350, 853}, {2000, 1300, 827},
{1800, 1250, 702}, {1000, 1100, 301} } },
{850, 0x14, 0x20f51, 0x10, 0x10, 853,
{{2200, 1350, 853}, {2000, 1300, 827},
{1800, 1250, 702}, {1000, 1100, 301} } },
/* OSA248CEP5AU */
{248, 0x10, 0x00f5a, 0xe, 0xe, 890,
{{2000, 1400, 700}, {1800, 1300, 470},
{1000, 1200, 280} } },
/* begin OSK246FAA5BL */
{246, 0x12, 0x20f51, 0xc, 0xc, 547,
{{1800, 1350, 461}, {1000, 1100, 223} } },
{846, 0x16, 0x20f51, 0xc, 0xc, 547,
{{1800, 1350, 461}, {1000, 1100, 223} } },
{148, 0xe, 0x20f51, 0xe, 0xe, 547,
{{2000, 1350, 521}, {1800, 1300, 459},
{1000, 1100, 211} } },
{248, 0x12, 0x20f51, 0xe, 0xe, 547,
{{2000, 1350, 521}, {1800, 1300, 459},
{1000, 1100, 211} } },
{848, 0x16, 0x20f51, 0xe, 0xe, 547,
{{2000, 1350, 521}, {1800, 1300, 459},
{1000, 1100, 211} } },
{250, 0x12, 0x20f51, 0x10, 0x10, 547,
{{2200, 1350, 521}, {2000, 1300, 440},
{1800, 1250, 379}, {1000, 1100, 199} } },
{850, 0x16, 0x20f51, 0x10, 0x10, 547,
{{2200, 1350, 521}, {2000, 1300, 440},
{1800, 1250, 379}, {1000, 1100, 199} } },
{144, 0xc, 0x20f71, 0xa, 0xa, 670,
{{1000, 1100, 296} } },
{148, 0xc, 0x20f71, 0xe, 0xe, 853,
{{2000, 1350, 830}, {1800, 1300, 704},
{1000, 1100, 296} } },
{152, 0xc, 0x20f71, 0x12, 0x12, 104,
{{2400, 1350, 1016}, {2200, 1300, 863},
{2000, 1250, 732}, {1800, 1200, 621},
{1000, 1100, 419} } },
{146, 0xc, 0x20f71, 0xc, 0xc, 670,
{{1800, 1350, 647}, {1000, 1100, 286} } },
{150, 0xc, 0x20f71, 0x10, 0x10, 853,
{{2200, 1350, 830}, {2000, 1300, 706},
{1800, 1250, 596}, {1000, 1100, 350} } },
{154, 0xc, 0x20f71, 0x14, 0x14, 1040,
{{2600, 1350, 1017}, {2400, 1300, 868},
{2200, 1250, 740}, {2000, 1200, 630},
{1800, 1150, 537}, {1000, 1100, 416} } },
/* rev E dualcore */
{165, 0x2c, 0x20f12, 0xa, 0xa, 950,
{{1000, 1100, 406} } },
{265, 0x30, 0x20f12, 0xa, 0xa, 950,
{{1000, 1100, 406} } },
{865, 0x34, 0x20f12, 0xa, 0xa, 950,
{{1000, 1100, 406} } },
{270, 0x30, 0x20f12, 0xc, 0xc, 950,
{{1800, 1300, 903}, {1000, 1100, 383} } },
{870, 0x34, 0x20f12, 0xc, 0xc, 950,
{{1800, 1300, 903}, {1000, 1100, 383} } },
{275, 0x30, 0x20f12, 0xe, 0xe, 950,
{{2000, 1300, 903}, {1800, 1250, 759},
{1000, 1100, 361} } },
{875, 0x34, 0x20f12, 0xe, 0xe, 950,
{{2000, 1300, 903}, {1800, 1250, 759},
{1000, 1100, 361} } },
{280, 0x30, 0x20f12, 0x10, 0x10, 926,
{{2400, 1350, 900}, {2200, 1300, 766},
{1800, 1200, 552}, {1000, 1100, 320} } },
{880, 0x34, 0x20f12, 0x10, 0x10, 926,
{{2400, 1350, 900}, {2200, 1300, 766},
{1800, 1200, 552}, {1000, 1100, 320} } },
{170, 0x2c, 0x20f32, 0xc, 0xc, 1100,
{{1800, 1300, 1056}, {1000, 1100, 514} } },
{175, 0x2c, 0x20f32, 0xe, 0xe, 1100,
{{2000, 1300, 1056}, {1800, 1250, 891},
{1000, 1100, 490} } },
{260, 0x32, 0x20f32, 0x8, 0x8, 550,
{} },
{860, 0x36, 0x20f32, 0x8, 0x8, 550,
{} },
{165, 0x2e, 0x20f32, 0xa, 0xa, 550,
{{1000, 1100, 365} } },
{265, 0x32, 0x20f32, 0xa, 0xa, 550,
{{1000, 1100, 365} } },
{865, 0x36, 0x20f32, 0xa, 0xa, 550,
{{1000, 1100, 365} } },
{270, 0x32, 0x20f12, 0xc, 0xc, 550,
{{1800, 1150, 520}, {1000, 1100, 335} } },
{870, 0x36, 0x20f12, 0xc, 0xc, 550,
{{1800, 1150, 520}, {1000, 1100, 335} } },
{180, 0x2c, 0x20f32, 0x10, 0x10, 1100,
{{2200, 1300, 1056}, {2000, 1250, 891},
{1800, 1200, 748}, {1000, 1100, 466} } },
/* OSP280 */
{280, 0x31, 0x20f12, 0x10, 0x10, 680,
{{2200, 1250, 650}, {2000, 1200, 574},
{1800, 1150, 433}, {1000, 1100, 220} } },
/* AMA3000BEX5AR */
{3000, 0x4, 0xf4a, 0xa, 0x0, 815,
{{1600, 1400, 570}, {800, 1100, 190} } },
/* TMDML34BKX5LD, needs real TDP info */
{34, 0xa, 0x20f42, 0xa, 0x0, 350,
{{1600, 1400, 340}, {800, 1000, 330} } },
/* ADA3200AIO4BX */
{3200, 0x4, 0x20fc2, 0xe, 0xe, 670,
{{2000, 1350, 647}, {1800, 1300, 548}, {1000, 1100, 275} } },
/* ADA2800AEP4AP */
{2800, 0x4, 0xf48, 0xa, 0xa, 890,
{{800, 1300, 350} } },
/* ADA3000AEP4AP */
{3000, 0x4, 0xf48, 0xc, 0xc, 890,
{{1800, 1400, 660}, {800, 1300, 350} } },
/* ADA3200AEP5AP */
{3200, 0x4, 0xf48, 0xc, 0xc, 890,
{{1800, 1400, 660}, {800, 1300, 350} } },
/* ADA3400AEP5AP */
{3400, 0x4, 0xf48, 0xe, 0xe, 890,
{{2000, 1400, 700}, {800, 1300, 350} } },
/* ADA2800AEP4AR */
{2800, 0x4, 0xf4a, 0xa, 0xa, 890,
{{1000, 1100, 220} } },
/* ADA3000AEP4AR */
{3000, 0x4, 0xf4a, 0xc, 0xc, 890,
{{1800, 1400, 660}, {1000, 1100, 220} } },
/* ADA3700AEP5AR */
{3700, 0x4, 0xf4a, 0x10, 0x10, 890,
{{2200, 1400, 720}, {2000, 1300, 530},
{1800, 1200, 390}, {1000, 1100, 220} } },
/* ADA2800AEP4AX */
{2800, 0x4, 0xfc0, 0xa, 0xa, 890,
{{1000, 1100, 220} } },
/* ADA3000AEP4AX */
{3000, 0x4, 0xfc0, 0xc, 0xc, 890,
{{1800, 1400, 670}, {1000, 1100, 220} } },
/* ADA3200AEP4AX */
{3200, 0x4, 0xfc0, 0xe, 0xe, 890,
{{2000, 1400, 690}, {1800, 1300, 500}, {1000, 1100, 220} } },
/* ADA3400AEP4AX */
{3400, 0x4, 0xfc0, 0x10, 0x10, 890,
{{2200, 1400, 720}, {2000, 1300, 530},
{1800, 1200, 390}, {1000, 1100, 220} } },
/* ADA3500DEP4AS */
{3500, 0x4, 0xf7a, 0xe, 0xe, 890,
{{2000, 1400, 690}, {1800, 1300, 500}, {1000, 1100, 220} } },
/* ADA3500DEP4AW */
{3500, 0x4, 0xff0, 0xe, 0xe, 890,
{{2000, 1400, 690}, {1800, 1300, 500}, {1000, 1100, 220} } },
/* ADA3800DEP4AW */
{3800, 0x4, 0xff0, 0x10, 0x10, 890,
{{2200, 1400, 720}, {2000, 1300, 530},
{1800, 1200, 390}, {1000, 1100, 220} } },
/* ADA4000DEP5AS */
{4000, 0x4, 0xf7a, 0x10, 0x10, 890,
{{2200, 1400, 720}, {2000, 1300, 530},
{1800, 1200, 390}, {1000, 1100, 220} } },
/* ADA3500DAA4BN */
{3500, 0x4, 0x20f71, 0xe, 0xe, 670,
{{2000, 1350, 647}, {1800, 1300, 548}, {1000, 1100, 275} } },
/* ADA3700DAA5BN */
{3700, 0x4, 0x20f71, 0xe, 0xe, 853,
{{2000, 1350, 830}, {1800, 1300, 704}, {1000, 1100, 361} } },
/* ADA4000DAA5BN */
{4000, 0x4, 0x20f71, 0x10, 0x10, 853,
{{2200, 1350, 830}, {2000, 1300, 706},
{1800, 1250, 596}, {1000, 1100, 350} } },
/* ADA3700DKA5CF */
{3700, 0x4, 0x30f72, 0xe, 0xe, 853,
{{2000, 1350, 830}, {1800, 1300, 704}, {1000, 1100, 361} } },
/* ADA4000DKA5CF */
{4000, 0x4, 0x30f72, 0x10, 0x10, 853,
{{2200, 1350, 830}, {2000, 1300, 706},
{1800, 1250, 596}, {1000, 1100, 350} } },
/* ADA3800DAA4BP */
{3800, 0x4, 0x20ff0, 0x10, 0x10, 853,
{{2200, 1350, 830}, {2000, 1300, 706},
{1800, 1250, 596}, {1000, 1100, 350} } },
/* ADA3000DIK4BI */
{3000, 0x4, 0x10ff0, 0xa, 0xa, 670,
{{1000, 1100, 210} } },
/* ADA3200DIK4BI */
{3200, 0x4, 0x10ff0, 0xc, 0xc, 670,
{{1800, 1350, 560}, {1000, 1100, 210} } },
/* ADA3500DIK4BI */
{3500, 0x4, 0x10ff0, 0xe, 0xe, 670,
{{2000, 1350, 560}, {1800, 1300, 460}, {1000, 1100, 200} } },
/* ADA3000DAA4BP */
{3000, 0x4, 0x20ff0, 0xa, 0xa, 670,
{{1000, 1100, 296} } },
/* ADA3200DAA4BP */
{3200, 0x4, 0x20ff0, 0xc, 0xc, 670,
{{1800, 1350, 647}, {1000, 1100, 286} } },
/* ADA3500DAA4BP */
{3500, 0x4, 0x20ff0, 0xe, 0xe, 670,
{{2000, 1350, 647}, {1800, 1300, 548}, {1000, 1100, 275} } },
/* ADA3000DAA4BW */
{3000, 0x4, 0x20ff2, 0xa, 0xa, 670,
{{1000, 1100, 296} } },
/* ADA3200DAA4BW */
{3200, 0x4, 0x20ff2, 0xc, 0xc, 670,
{{1800, 1350, 647}, {1000, 1100, 286} } },
/* ADA3500DAA4BW */
{3500, 0x4, 0x20ff2, 0xe, 0xe, 670,
{{2000, 1350, 647}, {1800, 1300, 548}, {1000, 1100, 275} } },
/* ADA3200DKA4CG */
{3200, 0x4, 0x30ff2, 0xc, 0xc, 670,
{{1800, 1350, 647}, {1000, 1100, 286} } },
/* ADA3800DAA4BW */
{3800, 0x4, 0x20ff2, 0x10, 0x10, 853,
{{2200, 1350, 830}, {2000, 1300, 706},
{1800, 1250, 596}, {1000, 1100, 350} } },
/* ADA3000AIK4BX */
{3000, 0x4, 0x20fc2, 0xc, 0xc, 510,
{{1800, 1350, 428}, {1000, 1100, 189} } },
/* ADAFX53DEP5AS */
{53, 0x24, 0xf7a, 0x2a, 0x10, 890,
{{1200, 1100, 250} } },
/* ADAFX55DEI5AS */
{55, 0x24, 0xf7a, 0x2a, 0x12, 1040,
{{1200, 1100, 250} } },
/* ADAFX55DAA5BN */
{55, 0x24, 0x20f71, 0x2a, 0x12, 1040,
{{1200, 1100, 422} } },
/* ADAFX57DAA5BN */
{57, 0x24, 0x20f71, 0x2a, 0x14, 1040,
{{1200, 1100, 434} } },
/* SDA3100AIP3AX */
{3100, 0x22, 0xfc0, 0xa, 0xa, 620,
{{1000, 1100, 200} } },
/* SDA2600AIO2BA */
{2600, 0x22, 0x10fc0, 0x8, 0x8, 590,
{} },
/* SDA2800AIO3BA */
{2800, 0x22, 0x10fc0, 0x8, 0x8, 590,
{} },
/* SDA3000AIO2BA */
{3000, 0x22, 0x10fc0, 0xa, 0xa, 590,
{{1000, 1100, 190} } },
/* SDA3100AIO3BA */
{3100, 0x22, 0x10fc0, 0xa, 0xa, 590,
{{1000, 1100, 190} } },
/* SDA3300AIO2BA */
{3300, 0x22, 0x10fc0, 0xc, 0xc, 590,
{{1800, 1350, 488}, {1000, 1100, 180} } },
/* SDA2500AIO3BX */
{2500, 0x26, 0x20fc2, 0x6, 0x6, 590,
{} },
/* SDA2600AIO2BX */
{2600, 0x26, 0x20fc2, 0x8, 0x8, 590,
{} },
/* SDA2800AIO3BX */
{2800, 0x26, 0x20fc2, 0x8, 0x8, 590,
{} },
/* SDA3000AIO2BX */
{3000, 0x26, 0x20fc2, 0xa, 0xa, 590,
{{1000, 1100, 217} } },
/* SDA3100AIO3BX */
{3100, 0x26, 0x20fc2, 0xa, 0xa, 590,
{{1000, 1100, 217} } },
/* SDA3300AIO2BX */
{3300, 0x26, 0x20fc2, 0xc, 0xc, 590,
{{1800, 1350, 496}, {1000, 1100, 207} } },
/* SDA3400AIO3BX */
{3400, 0x26, 0x20fc2, 0xc, 0xc, 590,
{{1800, 1350, 496}, {1000, 1100, 207} } },
/* TMSMT32BQX4LD */
{32, 0xb, 0x20f42, 0xa, 0x0, 240,
{{1600, 1150, 199}, {800, 900, 77} } },
/* TMSMT34BQX5LD */
{34, 0xb, 0x20f42, 0xa, 0x0, 240,
{{1600, 1150, 199}, {800, 900, 79} } },
/* TMSMT37BQX5LD */
{37, 0xb, 0x20f42, 0xc, 0x0, 250,
{{1800, 1150, 209}, {1600, 1100, 175}, {800, 900, 79} } },
/* ADA4400DAA6CD */
{4400, 0x5, 0x20f32, 0xe, 0xe, 1100,
{{2000, 1300, 1056}, {1800, 1250, 891}, {1000, 1100, 490} } },
/* ADA4800DAA6CD */
{4800, 0x5, 0x20f32, 0x10, 0x10, 1100,
{{2200, 1300, 1056}, {2000, 1250, 891},
{1800, 1200, 748}, {1000, 1100, 466} } },
/* ADA3800DAA5BV */
{3800, 0x5, 0x20fb1, 0xc, 0xc, 890,
{{1800, 1300, 846}, {1000, 1100, 401} } },
/* ADA4200DAA5BV */
{4200, 0x5, 0x20fb1, 0xe, 0xe, 890,
{{2000, 1300, 846}, {1800, 1250, 709}, {1000, 1100, 376} } },
/* ADA4600DAA5BV */
{4600, 0x5, 0x20fb1, 0x10, 0x10, 1100,
{{2200, 1300, 1056}, {2000, 1250, 891},
{1800, 1200, 748}, {1000, 1100, 466} } },
};
static void pstates_algorithm(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
{
u8 cmp_cap;
struct cpuentry *data = NULL;
uint32_t control;
int i = 0, index = 0, Pstate_num = 0, dev = 0;
msr_t msr;
u8 Pstate_fid[MAXP+1];
u16 Pstate_feq[MAXP+1];
u8 Pstate_vid[MAXP+1];
u32 Pstate_power[MAXP+1];
u8 Max_fid, Start_fid, Max_vid;
struct cpuid_result cpuid1;
/* See if the CPUID(0x80000007) returned EDX[2:1]==11b */
cpuid1 = cpuid(0x80000007);
if ((cpuid1.edx & 0x6) != 0x6) {
printk(BIOS_INFO, "Processor not capable of performing P-state transitions\n");
return;
}
cpuid1 = cpuid(0x80000001);
/* It has been said that we can safely assume that all CPU's
* in the system have the same SYSCONF values
*/
msr = rdmsr(0xc0010042);
Max_fid = (msr.lo & 0x3F0000) >> 16;
Max_vid = (msr.hi & 0x3F0000) >> 16;
Start_fid = (msr.lo & 0x3F00) >> 8;
/* Start_vid = (msr.hi & 0x3F00) >> 8; */
cmp_cap =
(pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x18, 3)), 0xE8) &
0x3000) >> 12;
for (i = 0; i < ARRAY_SIZE(entr); i++) {
if ((entr[i].cpuid == cpuid1.eax)
&& (entr[i].startFID == Start_fid)
&& (entr[i].maxFID == Max_fid)
&& (entr[i].brandID == ((u8)((cpuid1.ebx >> 6) & 0xff)))) {
data = &entr[i];
break;
}
}
if (data == NULL) {
printk(BIOS_WARNING, "Unknown CPU, please update the powernow_acpi.c\n");
return;
}
#if CONFIG_MAX_PHYSICAL_CPUS
/* IRT 80us RVO = 50mV PLL_LOCK_TIME 2us, MVS 25mv, VST 100us */
control = (3 << 30) | (2 << 28) | (2 << 20) | (0 << 18) | (5 << 11);
#else
/* MP-systems should default to RVO=0mV (no ramp voltage) */
/* IRT 80us RVO = 0mV PLL_LOCK_TIME 2us, MVS 25mv, VST 100us */
control = (3 << 30) | (0 << 28) | (2 << 20) | (0 << 18) | (5 << 11);
#endif
/* RVO (Ramp Voltage Offset)
* 00 0mV (default for MP-systems)
* 01 25mV
* 10 50mV (default)
* 11 75mV
* IRT (Isochronous Release Time)
* 00 10uS
* 01 20uS
* 10 40uS
* 11 80uS (default)
* MVS (Maximum Voltage Step)
* 00 25mV (default)
* 01 50mV (reserved)
* 10 100mV (reserved)
* 11 200mV (reserved)
* VST (Voltage Stabilization Time)
* time = value*20uS (default value: 5 => 100uS)
* PLL_LOCK_TIME
* time = value*1uS (often seen value: 2uS)
*/
Pstate_fid[0] = Max_fid;
Pstate_feq[0] = fid_to_freq(Max_fid);
Pstate_vid[0] = Max_vid;
Pstate_power[0] = data->pwr * 100;
for (Pstate_num = 1;
(Pstate_num <= MAXP) &&
(data->pstates[Pstate_num - 1].freqMhz != 0);
Pstate_num++) {
Pstate_fid[Pstate_num] =
freq_to_fid(data->pstates[Pstate_num - 1].freqMhz) & 0x3f;
Pstate_feq[Pstate_num] =
data->pstates[Pstate_num - 1].freqMhz;
Pstate_vid[Pstate_num] =
vid_to_reg(data->pstates[Pstate_num - 1].voltage);
Pstate_power[Pstate_num] =
data->pstates[Pstate_num - 1].tdp * 100;
}
for (i = 0; i < Pstate_num; i++)
printk(BIOS_DEBUG,
"P#%d freq %d [MHz] voltage %d [mV] TDP %d [mW]\n",
i,
Pstate_feq[i],
vid_from_reg(Pstate_vid[i]),
Pstate_power[i]);
/* Loop over all CPU's */
for (dev = 0x18; dev < 0x1c; dev++) {
if (dev_find_slot(0, PCI_DEVFN(dev, 0)) == NULL)
continue;
for (i = 0; i < (cmp_cap + 1); i++) {
write_pstates_for_core(Pstate_num,
Pstate_feq, Pstate_vid,
Pstate_fid, Pstate_power, index+i,
pcontrol_blk, plen, onlyBSP, control);
}
index += i;
}
printk(BIOS_DEBUG, "%d Processor objects emitted to SSDT\n", index);
}
#endif
void amd_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
{
char pscope[] = "\\_PR";
acpigen_write_scope(pscope);
pstates_algorithm(pcontrol_blk, plen, onlyBSP);
acpigen_pop_len();
}

View File

@ -1,436 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2006 coresystems GmbH
* (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
* Copyright (C) 2007 University of Mannheim
* (Written by Sven Kapferer <skapfere@rumms.uni-mannheim.de> for Uni Ma.)
*
* 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.
*/
/*
* This code sets the Processor Name String for AMD64 CPUs.
*
* Written by Stefan Reinauer <stepan@coresystems.de> using
* the Revision Guide for AMD Athlon™ 64 and AMD Opteron™ Processors
* Document ID 25759 Rev 3.59, April 2006 (Public Version).
*
* Updated by Sven Kapferer <skapfere@rumms.uni-mannheim.de> using
* the Revision Guide for AMD NPT Family 0Fh Processors
* Document ID 33610 Rev 3.00, October 2006 (Public Version).
*/
#include <console/console.h>
#include <string.h>
#include <cpu/x86/msr.h>
#include <cpu/amd/mtrr.h>
#include <cpu/amd/model_fxx_rev.h>
/* The maximum length of CPU names is 48 bytes, including the final NULL byte.
* If you change these names your BIOS will _NOT_ pass the AMD validation and
* your mainboard will not be posted on the AMD Recommended Motherboard Website
*/
#if !IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
static const char *processor_names[]={
/* 0x00 */ "AMD Engineering Sample",
/* 0x01-0x03 */ NULL, NULL, NULL,
/* 0x04 */ "AMD Athlon(tm) 64 Processor XX00+",
/* 0x05 */ "AMD Athlon(tm) 64 X2 Dual Core Processor XX00+",
/* 0x06-0x07 */ NULL, NULL,
/* 0x08 */ "Mobile AMD Athlon(tm) 64 Processor XX00+",
/* 0x09 */ "Mobile AMD Athlon(tm) 64 Processor XX00+",
/* 0x0A */ "AMD Turion(tm) 64 Mobile Technology ML-XX",
/* 0x0B */ "AMD Turion(tm) 64 Mobile Technology MT-XX",
/* 0x0C */ "AMD Opteron(tm) Processor 1YY",
/* 0x0D */ "AMD Opteron(tm) Processor 1YY",
/* 0x0E */ "AMD Opteron(tm) Processor 1YY HE",
/* 0x0F */ "AMD Opteron(tm) Processor 1YY EE",
/* 0x10 */ "AMD Opteron(tm) Processor 2YY",
/* 0x11 */ "AMD Opteron(tm) Processor 2YY",
/* 0x12 */ "AMD Opteron(tm) Processor 2YY HE",
/* 0x13 */ "AMD Opteron(tm) Processor 2YY EE",
/* 0x14 */ "AMD Opteron(tm) Processor 8YY",
/* 0x15 */ "AMD Opteron(tm) Processor 8YY",
/* 0x16 */ "AMD Opteron(tm) Processor 8YY HE",
/* 0x17 */ "AMD Opteron(tm) Processor 8YY EE",
/* 0x18 */ "AMD Athlon(tm) 64 Processor VV00+",
/* 0x19-0x1C */ NULL, NULL, NULL, NULL,
/* 0x1D */ "Mobile AMD Athlon(tm) XP-M Processor XX00+",
/* 0x1E */ "Mobile AMD Athlon(tm) XP-M Processor XX00+",
/* 0x1F */ NULL,
/* 0x20 */ "AMD Athlon(tm) XP Processor XX00+",
/* 0x21 */ "Mobile AMD Sempron(tm) Processor TT00+",
/* 0x22 */ "AMD Sempron(tm) Processor TT00+",
/* 0x23 */ "Mobile AMD Sempron(tm) Processor TT00+",
/* 0x24 */ "AMD Athlon(tm) 64 FX-ZZ Processor",
/* 0x25 */ NULL,
/* 0x26 */ "AMD Sempron(tm) Processor TT00+",
/* 0x27-0x28 */ NULL, NULL,
/* 0x29 */ "Dual Core AMD Opteron(tm) Processor 1RR SE",
/* 0x2A */ "Dual Core AMD Opteron(tm) Processor 2RR SE",
/* 0x2B */ "Dual Core AMD Opteron(tm) Processor 8RR SE",
/* 0x2C */ "Dual Core AMD Opteron(tm) Processor 1RR",
/* 0x2D */ "Dual Core AMD Opteron(tm) Processor 1RR",
/* 0x2E */ "Dual Core AMD Opteron(tm) Processor 1RR HE",
/* 0x2F */ "Dual Core AMD Opteron(tm) Processor 1RR EE",
/* 0x30 */ "Dual Core AMD Opteron(tm) Processor 2RR",
/* 0x31 */ "Dual Core AMD Opteron(tm) Processor 2RR",
/* 0x32 */ "Dual Core AMD Opteron(tm) Processor 2RR HE",
/* 0x33 */ "Dual Core AMD Opteron(tm) Processor 2RR EE",
/* 0x34 */ "Dual Core AMD Opteron(tm) Processor 8RR",
/* 0x35 */ "Dual Core AMD Opteron(tm) Processor 8RR",
/* 0x36 */ "Dual Core AMD Opteron(tm) Processor 8RR HE",
/* 0x37 */ "Dual Core AMD Opteron(tm) Processor 8RR EE",
/* 0x38 */ "Dual Core AMD Opteron(tm) Processor 1RR",
/* 0x39 */ "Dual Core AMD Opteron(tm) Processor 2RR",
/* 0x3A */ "Dual Core AMD Opteron(tm) Processor 8RR"
#define MAX_CPU_NUMBER 0x3A
};
#endif
int init_processor_name(void)
{
#if !IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
u32 EightBitBrandId;
#endif
u32 BrandId;
u32 BrandTableIndex;
u32 NN;
u32 ModelNumber=0;
msr_t progmsr;
int i;
const char *processor_name_string=NULL;
char program_string[48];
unsigned int *program_values = (unsigned int *)program_string;
#if !IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
/* Find out which CPU brand it is */
EightBitBrandId = cpuid_ebx(0x00000001) & 0xff;
BrandId = cpuid_ebx(0x80000001) & 0xffff;
if (!EightBitBrandId && !BrandId) {
BrandTableIndex = 0;
NN = 0xffffff;
} else if (!EightBitBrandId) {
BrandTableIndex = (BrandId >> 6) & 0x3f; // BrandId[11:6]
NN = BrandId & 0x3f; // // BrandId[6:0]
} else {
BrandTableIndex = EightBitBrandId >> (5-2) & 0xfc; // { 0b, 8BitBrandId[7:5], 00b }
NN = EightBitBrandId & 0x1f; // 8BitBrandId[4:0]
}
/* Look up the CPU brand in above table */
if (BrandTableIndex <= MAX_CPU_NUMBER)
processor_name_string = processor_names[BrandTableIndex];
if (!processor_name_string)
processor_name_string = "AMD Processor model unknown";
#endif
#if IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
u32 Socket;
u32 CmpCap;
u32 PwrLmt;
BrandId = cpuid_ebx(0x80000001) & 0xffff;
Socket = (cpuid_eax(0x80000001) & 0x00000030) >> 4; // 00b = S1g1, 01b = F (1207), 11b = AM2
CmpCap = cpuid_ecx(0x80000008) & 0x03; // Number of CPU cores
PwrLmt = ((BrandId >> 14) & 0x01) | ((BrandId >> 5) & 0x0e); // BrandId[8:6,14]
BrandTableIndex = (BrandId >> 9) & 0x1f; // BrandId[13:9]
NN = ((BrandId >> 15) & 0x01) | (BrandId & 0x3f); // BrandId[15,5:0]
if (((BrandTableIndex == 0) && (PwrLmt == 0)) || (NN == 0)) {
processor_name_string = "AMD Engineering Sample";
} else {
/* Use all fields to identify CPU */
switch ((Socket << 16) | (CmpCap << 12) | (BrandTableIndex << 4)
| PwrLmt) {
/* Socket F */
case 0x10012:
processor_name_string =
"AMD Opteron(tm) Processor 22RR EE";
break;
case 0x11002:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 12RR EE";
break;
case 0x11006:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 12RR HE";
break;
case 0x11012:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 22RR EE";
break;
case 0x11016:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 22RR HE";
break;
case 0x1101a:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 22RR";
break;
case 0x1101c:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 22RR SE";
break;
case 0x11042:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 82RR EE";
break;
case 0x11046:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 82RR HE";
break;
case 0x1104a:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 82RR";
break;
case 0x1104c:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 82RR SE";
break;
case 0x1106e:
processor_name_string =
"AMD Athlon(tm) 64 Processor FX-ZZ Processor";
break;
/* Socket AM2 */
/* single core */
case 0x30015:
processor_name_string =
"AMD Sempron(tm) Processor LE-1RR0";
break;
case 0x30026:
processor_name_string =
"AMD Athlon(tm) Processor LE-1ZZ0";
break;
case 0x30036:
processor_name_string =
"AMD Athlon(tm) Processor 1ZZ0B";
break;
case 0x30041:
case 0x30042:
case 0x30043:
case 0x30044:
case 0x30045:
case 0x30048:
processor_name_string =
"AMD Athlon(tm) 64 Processor TT00+";
break;
case 0x30052:
processor_name_string =
"AMD Sempron(tm) Processor RR50p";
break;
case 0x30064:
case 0x30068:
processor_name_string =
"AMD Sempron(tm) Processor TT00+";
break;
case 0x30071:
case 0x30072:
processor_name_string =
"AMD Sempron(tm) Processor TT0U";
break;
case 0x30082:
case 0x30083:
processor_name_string =
"AMD Athlon(tm) Processor TT50e";
break;
case 0x30092:
processor_name_string =
"AMD Athlon(tm) Neo Processor MV-TT";
break;
case 0x300c2:
processor_name_string =
"AMD Sempron(tm) Processor 2RRU";
break;
/* dual-core */
case 0x31016:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 12RR HE";
break;
case 0x3101a:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 12RR";
break;
case 0x3101c:
processor_name_string =
"Dual-Core AMD Opteron(tm) Processor 12RR SE";
break;
case 0x31033:
processor_name_string =
"AMD Athlon(tm) X2 Dual Core Processor BE-2TT0";
break;
case 0x31041:
case 0x31042:
case 0x31046:
case 0x31048:
case 0x3104c:
processor_name_string =
"AMD Athlon(tm) 64 X2 Dual Core Processor TT00+";
break;
case 0x3105c:
processor_name_string =
"AMD Athlon(tm) 64 FX-ZZ Dual Core Processor";
break;
case 0x31066:
processor_name_string =
"AMD Sempron(tm) Dual Core Processor RR00";
break;
case 0x31073:
processor_name_string =
"AMD Athlon(tm) Dual Core Processor TT50e";
break;
case 0x31076:
case 0x31077:
processor_name_string =
"AMD Athlon(tm) Dual Core Processor TT00B";
break;
case 0x31083:
processor_name_string =
"AMD Athlon(tm) Dual Core Processor TT50B";
break;
case 0x31091:
processor_name_string =
"AMD Athlon(tm) X2 Dual Core Processor TT50e";
break;
case 0x310a1:
case 0x310a2:
processor_name_string =
"AMD Athlon(tm) Neo X2 Dual Core Processor TT50e";
break;
case 0x310b0:
case 0x310c0:
processor_name_string =
"AMD Turion(tm) Neo X2 Dual Core Processor L6RR";
break;
/* Socket S1g1 */
/* single core */
case 0x00012:
processor_name_string =
"AMD Athlon(tm) 64 Processor TT00+";
break;
case 0x0002c:
processor_name_string =
"AMD Turion(tm) 64 Mobile Technology MK-YY";
break;
case 0x00031:
processor_name_string =
"Mobile AMD Sempron(tm) Processor TT00+";
break;
case 0x00036:
processor_name_string =
"Mobile AMD Sempron(tm) Processor PP00+";
break;
case 0x0003c:
processor_name_string =
"Mobile AMD Sempron(tm) Processor PP00+";
break;
case 0x00042:
processor_name_string =
"AMD Sempron(tm) Processor TT00+";
break;
case 0x00064:
case 0x00066:
case 0x0006c:
processor_name_string =
"AMD Athlon(tm) Processor TF-TT";
break;
case 0x00073:
processor_name_string =
"AMD Athlon(tm) Processor L1RR";
break;
/* dual-core */
case 0x0101c:
processor_name_string =
"AMD Sempron(tm) Dual Core Processor TJ-YY";
break;
case 0x0102c:
processor_name_string =
"AMD Turion(tm) 64 X2 Mobile Technology TL-YY";
break;
case 0x01034:
case 0x0103c:
processor_name_string =
"AMD Athlon(tm) 64 X2 Dual-Core Processor TK-YY";
break;
case 0x01054:
processor_name_string =
"AMD Athlon(tm) 64 X2 Dual Core Processor TT00+";
break;
case 0x01062:
processor_name_string =
"AMD Athlon(tm) X2 Dual Core Processor L3RR";
break;
case 0x01074:
processor_name_string =
"AMD Athlon(tm) X2 Dual Core Processor L5RR";
break;
default:
processor_name_string = "AMD Processor model unknown";
}
}
#endif
memset(program_string, 0, 48);
strcpy(program_string, processor_name_string);
/* Now create a model number - See Table 4. Model Number Calculation
* in the Revision Guide. NOTE: #6, EE was changed to VV because
* otherwise it clashes with the brand names.
*/
for (i=0; i<47; i++) { // 48 -1
if (program_string[i] == program_string[i+1]) {
switch (program_string[i]) {
#if !IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
case 'X': ModelNumber = 22+ NN; break;
case 'Y': ModelNumber = 38 + (2*NN); break;
case 'Z':
case 'T': ModelNumber = 24 + NN; break;
case 'R': ModelNumber = 45 + (5*NN); break;
case 'V': ModelNumber = 9 + NN; break;
#endif
#if IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
case 'R': ModelNumber = NN - 1; break;
case 'P': ModelNumber = 26 + NN; break;
case 'T': ModelNumber = 15 + (CmpCap * 10) + NN; break;
case 'Z': ModelNumber = 57 + NN; break;
case 'Y': ModelNumber = 29 + NN; break;
#endif
}
if (ModelNumber && ModelNumber < 100) {
// No idea what to do with RR=100. According
// to the revision guide this is possible.
//
// --> "AMD Opteron(tm) Processor 8100"?
program_string[i]=(ModelNumber/10)+'0';
program_string[i+1]=(ModelNumber%10)+'0';
break;
}
}
}
printk(BIOS_DEBUG, "CPU model %s\n", program_string);
for (i=0; i<6; i++) {
progmsr.lo = program_values[(2*i)+0];
progmsr.hi = program_values[(2*i)+1];
wrmsr_amd(0xc0010030+i, progmsr);
}
return 0;
}

View File

@ -1,31 +0,0 @@
config CPU_AMD_SOCKET_754
bool
if CPU_AMD_SOCKET_754
config SOCKET_SPECIFIC_OPTIONS
def_bool y
select CPU_AMD_MODEL_FXX
select X86_AMD_FIXED_MTRRS
config DCACHE_RAM_BASE
hex
default 0xc8000
config DCACHE_RAM_SIZE
hex
default 0x08000
config DCACHE_BSP_STACK_SIZE
hex
default 0x2000
config DCACHE_BSP_STACK_SLUSH
hex
default 0x1000
config DCACHE_AP_STACK_SIZE
hex
default 0x400
endif # CPU_AMD_SOCKET_754

View File

@ -1,13 +0,0 @@
subdirs-y += ../model_fxx
subdirs-y += ../dualcore
subdirs-y += ../mtrr
subdirs-y += ../microcode
subdirs-y += ../../x86/tsc
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/pae
subdirs-y += ../../x86/smm
subdirs-y += ../smm
cpu_incs-y += $(src)/cpu/amd/car/cache_as_ram.inc

View File

@ -1,4 +0,0 @@
config CPU_AMD_SOCKET_939
bool
select CPU_AMD_MODEL_FXX
select X86_AMD_FIXED_MTRRS

View File

@ -1,13 +0,0 @@
subdirs-y += ../model_fxx
subdirs-y += ../dualcore
subdirs-y += ../mtrr
subdirs-y += ../microcode
subdirs-y += ../../x86/tsc
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/pae
subdirs-y += ../../x86/smm
subdirs-y += ../smm
cpu_incs-y += $(src)/cpu/amd/car/cache_as_ram.inc

View File

@ -1,32 +0,0 @@
config CPU_AMD_SOCKET_940
bool
if CPU_AMD_SOCKET_940
config SOCKET_SPECIFIC_OPTIONS
def_bool y
select K8_HT_FREQ_1G_SUPPORT
select CPU_AMD_MODEL_FXX
select X86_AMD_FIXED_MTRRS
config DCACHE_RAM_BASE
hex
default 0xc8000
config DCACHE_RAM_SIZE
hex
default 0x08000
config DCACHE_BSP_STACK_SIZE
hex
default 0x2000
config DCACHE_BSP_STACK_SLUSH
hex
default 0x1000
config DCACHE_AP_STACK_SIZE
hex
default 0x400
endif # CPU_AMD_SOCKET_940

View File

@ -1,13 +0,0 @@
subdirs-y += ../model_fxx
subdirs-y += ../dualcore
subdirs-y += ../mtrr
subdirs-y += ../microcode
subdirs-y += ../../x86/tsc
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/pae
subdirs-y += ../../x86/smm
subdirs-y += ../smm
cpu_incs-y += $(src)/cpu/amd/car/cache_as_ram.inc

View File

@ -1,12 +0,0 @@
config CPU_AMD_SOCKET_AM2
bool
select K8_REV_F_SUPPORT
# Opteron K8 1G HT support
select K8_HT_FREQ_1G_SUPPORT
select CPU_AMD_MODEL_FXX
select X86_AMD_FIXED_MTRRS
config CPU_SOCKET_TYPE
hex
default 0x11
depends on CPU_AMD_SOCKET_AM2

View File

@ -1,13 +0,0 @@
subdirs-y += ../model_fxx
subdirs-y += ../dualcore
subdirs-y += ../mtrr
subdirs-y += ../microcode
subdirs-y += ../../x86/tsc
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/pae
subdirs-y += ../../x86/smm
subdirs-y += ../smm
cpu_incs-y += $(src)/cpu/amd/car/cache_as_ram.inc

View File

@ -1,11 +0,0 @@
config CPU_AMD_SOCKET_F
bool
select K8_REV_F_SUPPORT
select K8_HT_FREQ_1G_SUPPORT
select CPU_AMD_MODEL_FXX
select X86_AMD_FIXED_MTRRS
config CPU_SOCKET_TYPE
hex
default 0x10
depends on CPU_AMD_SOCKET_F

View File

@ -1,13 +0,0 @@
subdirs-y += ../model_fxx
subdirs-y += ../dualcore
subdirs-y += ../mtrr
subdirs-y += ../microcode
subdirs-y += ../../x86/tsc
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/pae
subdirs-y += ../../x86/smm
subdirs-y += ../smm
cpu_incs-y += $(src)/cpu/amd/car/cache_as_ram.inc

View File

@ -1,42 +0,0 @@
config CPU_AMD_SOCKET_S1G1
bool
if CPU_AMD_SOCKET_S1G1
config SOCKET_SPECIFIC_OPTIONS
def_bool y
select K8_REV_F_SUPPORT
select K8_HT_FREQ_1G_SUPPORT
select CPU_AMD_MODEL_FXX
select X86_AMD_FIXED_MTRRS
config CPU_SOCKET_TYPE
hex
default 0x12
#DDR2 and REG, S1G1
config DIMM_SUPPORT
hex
default 0x0204
config DCACHE_RAM_BASE
hex
default 0xc8000
config DCACHE_RAM_SIZE
hex
default 0x08000
config DCACHE_BSP_STACK_SIZE
hex
default 0x2000
config DCACHE_BSP_STACK_SLUSH
hex
default 0x1000
config DCACHE_AP_STACK_SIZE
hex
default 0x400
endif

View File

@ -1,13 +0,0 @@
subdirs-y += ../model_fxx
subdirs-y += ../dualcore
subdirs-y += ../mtrr
subdirs-y += ../microcode
subdirs-y += ../../x86/tsc
subdirs-y += ../../x86/lapic
subdirs-y += ../../x86/cache
subdirs-y += ../../x86/pae
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/smm
subdirs-y += ../smm
cpu_incs-y += $(src)/cpu/amd/car/cache_as_ram.inc

View File

@ -1,30 +0,0 @@
#ifndef AMDK8_SYSCONF_H
#define AMDK8_SYSCONF_H
#define HC_POSSIBLE_NUM 8
struct amdk8_sysconf_t {
//ht
unsigned int nodes;
unsigned int hc_possible_num;
unsigned int pci1234[HC_POSSIBLE_NUM];
unsigned int hcdn[HC_POSSIBLE_NUM];
unsigned int hcid[HC_POSSIBLE_NUM]; //record ht chain type
unsigned int sbdn;
unsigned int sblk;
unsigned int hcdn_reg[4]; // it will be used by get_sblk_pci1234
int enabled_apic_ext_id;
unsigned int lift_bsp_apicid;
int apicid_offset;
void *mb; // pointer for mb related struct
};
extern struct amdk8_sysconf_t sysconf;
void get_sblk_pci1234(void);
void get_bus_conf(void);
#endif

View File

@ -1,131 +0,0 @@
#ifndef __CPU_AMD_MODEL_FXX_REV_H__
#define __CPU_AMD_MODEL_FXX_REV_H__
#include <arch/cpu.h>
#include <arch/io.h>
int init_processor_name(void);
static inline int is_cpu_rev_a0(void)
{
return (cpuid_eax(1) & 0xfffef) == 0x0f00;
}
static inline int is_cpu_pre_c0(void)
{
return (cpuid_eax(1) & 0xfffef) < 0x0f48;
}
static inline int is_cpu_c0(void)
{
return (cpuid_eax(1) & 0xfffef) == 0x0f48;
}
static inline int is_cpu_pre_b3(void)
{
return (cpuid_eax(1) & 0xfffef) < 0x0f41;
}
static inline int is_cpu_b3(void)
{
return (cpuid_eax(1) & 0xfffef) == 0x0f41;
}
//AMD_D0_SUPPORT
static inline int is_cpu_pre_d0(void)
{
return (cpuid_eax(1) & 0xfff0f) < 0x10f00;
}
static inline int is_cpu_d0(void)
{
return (cpuid_eax(1) & 0xfff0f) == 0x10f00;
}
//AMD_E0_SUPPORT
static inline int is_cpu_pre_e0(void)
{
return (cpuid_eax(1) & 0xfff0f) < 0x20f00;
}
static inline int is_cpu_e0(void)
{
return (cpuid_eax(1) & 0xfff00) == 0x20f00;
}
//AMD_F0_SUPPORT
static inline int is_cpu_pre_f0(void)
{
return (cpuid_eax(1) & 0xfff0f) < 0x40f00;
}
static inline int is_cpu_f0(void)
{
return (cpuid_eax(1) & 0xfff00) == 0x40f00;
}
static inline int is_cpu_pre_f2(void)
{
return (cpuid_eax(1) & 0xfff0f) < 0x40f02;
}
#ifdef __PRE_RAM__
static inline int is_e0_later_in_bsp(int nodeid)
{
uint32_t val;
uint32_t val_old;
int e0_later;
if (IS_ENABLED(CONFIG_K8_REV_F_SUPPORT))
return 1;
// we don't need to do that for node 0 in core0/node0
if (nodeid == 0)
return !is_cpu_pre_e0();
// d0 will be treated as e0 with this methods, but the d0 nb_cfg_54
// always 0
pci_devfn_t dev;
dev = PCI_DEV(0, 0x18+nodeid, 2);
val_old = pci_read_config32(dev, 0x80);
val = val_old;
val |= (1<<3);
pci_write_config32(dev, 0x80, val);
val = pci_read_config32(dev, 0x80);
e0_later = !!(val & (1<<3));
// pre_e0 bit 3 always be 0 and can not be changed
if (e0_later)
pci_write_config32(dev, 0x80, val_old); // restore it
return e0_later;
}
static inline int is_cpu_f0_in_bsp(int nodeid)
{
uint32_t dword;
pci_devfn_t dev;
if (!IS_ENABLED(CONFIG_K8_REV_F_SUPPORT))
return 0;
dev = PCI_DEV(0, 0x18+nodeid, 3);
dword = pci_read_config32(dev, 0xfc);
return (dword & 0xfff00) == 0x40f00;
}
static inline int is_cpu_pre_f2_in_bsp(int nodeid)
{
uint32_t dword;
pci_devfn_t dev;
if (!IS_ENABLED(CONFIG_K8_REV_F_SUPPORT))
return 1;
dev = PCI_DEV(0, 0x18+nodeid, 3);
dword = pci_read_config32(dev, 0xfc);
return (dword & 0xfff0f) < 0x40f02;
}
#else
int is_e0_later_in_bsp(int nodeid);
int is_cpu_f0_in_bsp(int nodeid);
#endif
#endif /* __CPU_AMD_MODEL_FXX_REV_H__ */

View File

@ -1,48 +0,0 @@
#include <lib.h> /* Prototypes */
/* Setup SDRAM */
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
void sdram_initialize(int controllers, const struct mem_controller *ctrl,
void *sysinfo)
#else
void sdram_initialize(int controllers, const struct mem_controller *ctrl)
#endif
{
int i;
/* Set the registers we can set once to reasonable values */
for (i = 0; i < controllers; i++) {
printk(BIOS_DEBUG, "Ram1.%02x\n", i);
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
sdram_set_registers(ctrl + i, sysinfo);
#else
sdram_set_registers(ctrl + i);
#endif
}
/* Now setup those things we can auto detect */
for (i = 0; i < controllers; i++) {
printk(BIOS_DEBUG, "Ram2.%02x\n", i);
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
sdram_set_spd_registers(ctrl + i, sysinfo);
#else
sdram_set_spd_registers(ctrl + i);
#endif
}
/* Now that everything is setup enable the SDRAM.
* Some chipsets do the work for us while on others
* we need to it by hand.
*/
printk(BIOS_DEBUG, "Ram3\n");
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
sdram_enable(controllers, ctrl, sysinfo);
#else
sdram_enable(controllers, ctrl);
#endif
printk(BIOS_DEBUG, "Ram4\n");
}

View File

@ -1,138 +0,0 @@
##
## 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.
##
config NORTHBRIDGE_AMD_AMDK8
bool
select HAVE_DEBUG_RAM_SETUP
select HAVE_DEBUG_SMBUS
select HAVE_DEBUG_CAR
select HYPERTRANSPORT_PLUGIN_SUPPORT
select LATE_CBMEM_INIT
if NORTHBRIDGE_AMD_AMDK8
config NO_MMCONF_SUPPORT
bool
default y
help
If you want to remove this, you need to make sure any access to CPU
nodes 0:18.0, 0:19.0, ... continue to use PCI IO config access.
config AGP_APERTURE_SIZE
hex
default 0x4000000
config K8_HT_FREQ_1G_SUPPORT
bool
default n
config RAMINIT_SYSINFO
bool
default n
config WAIT_BEFORE_CPUS_INIT
bool
default n
# Force 2T DRAM timing (vendor BIOS does it even for single DIMM setups and
# single DIMM is indeed unreliable without it).
config K8_FORCE_2T_DRAM_TIMING
bool
default n
config HW_MEM_HOLE_SIZEK
hex
default 0x100000
config HW_MEM_HOLE_SIZE_AUTO_INC
bool
default n
config BOOTBLOCK_NORTHBRIDGE_INIT
string
default "northbridge/amd/amdk8/bootblock.c"
config SB_HT_CHAIN_UNITID_OFFSET_ONLY
bool
default n
config HT_CHAIN_DISTRIBUTE
def_bool n
config QRANK_DIMM_SUPPORT
bool
default n
config K8_ALLOCATE_IO_RANGE
bool
default n
config K8_REV_F_SUPPORT
bool
select RAMINIT_SYSINFO
default n
if K8_REV_F_SUPPORT
config DIMM_DDR2
bool
default n
config DIMM_REGISTERED
bool
default n
if DIMM_DDR2
if DIMM_REGISTERED
config DIMM_SUPPORT
hex
default 0x0104
endif
if !DIMM_REGISTERED
config DIMM_SUPPORT
hex
default 0x0004
endif
endif #DIMM_DDR2
config MEM_TRAIN_SEQ
int
default 0
endif #K8_REV_F_SUPPORT
# TODO: Reservation for heap seems excessive
config HEAP_SIZE
hex
default 0x40000
config IOMMU
bool
default y
config CBB
hex
default 0x00
config CDB
hex
default 0x18
config MAX_REBOOT_CNT
int
default 6
endif #NORTHBRIDGE_AMD_K8

View File

@ -1,42 +0,0 @@
ifeq ($(CONFIG_NORTHBRIDGE_AMD_AMDK8),y)
ramstage-y += northbridge.c
ramstage-y += misc_control.c
ramstage-y += get_sblk_pci1234.c
ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
romstage-y += debug.c
ifeq ($(CONFIG_K8_REV_F_SUPPORT),y)
romstage-$(CONFIG_HAVE_ACPI_RESUME) += exit_from_self.c
romstage-y += raminit_f.c
endif
romstage-y += reset_test.c
romstage-y += coherent_ht.c
# Enable this if you want to check the values of the PCI routing registers.
# Call show_all_routes() anywhere amdk8.h is included.
#ramstage-y += util.c
# Not sure what to do with these yet. How did raminit_test even work?
# Should be a target in -y form.
#if IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
#
#makerule raminit_test
# depends "$(TOP)/src/northbridge/amd/amdk8/raminit_test.c"
# depends "$(TOP)/src/northbridge/amd/amdk8/raminit_f.c"
# action "$(HOSTCC) $(HOSTCFLAGS) $(CPUFLAGS) -Wno-unused-function -I$(TOP)/src/include -g $< -o $@"
#end
#
#else
#
#makerule raminit_test
# depends "$(TOP)/src/northbridge/amd/amdk8/raminit_test.c"
# depends "$(TOP)/src/northbridge/amd/amdk8/raminit.c"
# action "$(HOSTCC) $(HOSTCFLAGS) $(CPUFLAGS) -Wno-unused-function -I$(TOP)/src/include -g $< -o $@"
#end
#
#end
#
endif

View File

@ -1,311 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2005 Advanced Micro Devices, Inc.
* Copyright (C) 2010 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
/*
* Description: Add madt lapic creat dynamically and SRAT related by yhlu
*/
#include <console/console.h>
#include <string.h>
#include <arch/acpi.h>
#include <arch/acpigen.h>
#include <device/pci.h>
#include <cpu/x86/msr.h>
#include <cpu/amd/mtrr.h>
#include <cpu/amd/amdk8_sysconf.h>
#include "acpi.h"
//it seems some functions can be moved arch/x86/boot/acpi.c
unsigned long acpi_create_madt_lapic_nmis(unsigned long current, u16 flags, u8 lint)
{
struct device *cpu;
int cpu_index = 0;
for (cpu = all_devices; cpu; cpu = cpu->next) {
if ((cpu->path.type != DEVICE_PATH_APIC) ||
(cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
continue;
}
if (!cpu->enabled) {
continue;
}
current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)current, cpu_index, flags, lint);
cpu_index++;
}
return current;
}
unsigned long acpi_create_srat_lapics(unsigned long current)
{
struct device *cpu;
int cpu_index = 0;
for (cpu = all_devices; cpu; cpu = cpu->next) {
if ((cpu->path.type != DEVICE_PATH_APIC) ||
(cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
continue;
}
if (!cpu->enabled) {
continue;
}
printk(BIOS_DEBUG, "SRAT: lapic cpu_index=%02x, node_id=%02x, apic_id=%02x\n", cpu_index, cpu->path.apic.node_id, cpu->path.apic.apic_id);
current += acpi_create_srat_lapic((acpi_srat_lapic_t *)current, cpu->path.apic.node_id, cpu->path.apic.apic_id);
cpu_index++;
}
return current;
}
static unsigned long resk(uint64_t value)
{
unsigned long resultk;
if (value < (1ULL << 42)) {
resultk = value >> 10;
} else {
resultk = 0xffffffff;
}
return resultk;
}
struct acpi_srat_mem_state {
unsigned long current;
};
static void set_srat_mem(void *gp, struct device *dev, struct resource *res)
{
struct acpi_srat_mem_state *state = gp;
unsigned long basek, sizek;
basek = resk(res->base);
sizek = resk(res->size);
printk(BIOS_DEBUG, "set_srat_mem: dev %s, res->index=%04lx startk=%08lx, sizek=%08lx\n",
dev_path(dev), res->index, basek, sizek);
/*
* 0-640K must be on node 0
* next range is from 1M---
* So will cut off before 1M in the mem range
*/
if ((basek+sizek)<1024) return;
if (basek < 1024) {
sizek -= 1024 - basek;
basek = 1024;
}
// need to figure out NV
state->current += acpi_create_srat_mem((acpi_srat_mem_t *)state->current, (res->index & 0xf), basek, sizek, 1);
}
static unsigned long acpi_fill_srat(unsigned long current)
{
struct acpi_srat_mem_state srat_mem_state;
/* create all subtables for processors */
current = acpi_create_srat_lapics(current);
/* create all subteble for memory range */
/* 0-640K must be on node 0 */
current += acpi_create_srat_mem((acpi_srat_mem_t *)current, 0, 0, 640, 1);//enable
srat_mem_state.current = current;
search_global_resources(
IORESOURCE_MEM | IORESOURCE_CACHEABLE, IORESOURCE_MEM | IORESOURCE_CACHEABLE,
set_srat_mem, &srat_mem_state);
current = srat_mem_state.current;
return current;
}
static unsigned long acpi_fill_slit(unsigned long current)
{
/* need to find out the node num at first */
/* fill the first 8 byte with that num */
/* fill the next num*num byte with distance, local is 10, 1 hop mean 20, and 2 hop with 30.... */
/* because We has assume that we know the topology of the HT connection, So we can have set if we know the node_num */
static u8 hops_8[] = { 0, 1, 1, 2, 2, 3, 3, 4,
1, 0, 2, 1, 3, 2, 4, 3,
1, 2, 0, 1, 1, 2, 2, 3,
2, 1, 1, 0, 2, 1, 3, 2,
2, 3, 1, 2, 0, 1, 1, 2,
3, 2, 2, 1, 1, 0, 2, 1,
3, 4, 2, 3, 1, 2, 0, 1,
4, 4, 3, 2, 2, 1, 1, 0 };
u8 *p = (u8 *)current;
int nodes = sysconf.nodes;
int i,j;
memset(p, 0, 8+nodes*nodes);
*p = (u8) nodes;
p += 8;
for (i = 0; i < nodes; i++) {
for (j = 0; j < nodes; j++) {
if (i == j) {
p[i*nodes+j] = 10;
} else {
p[i*nodes+j] = hops_8[i*nodes+j] * 2 + 10;
}
}
}
current += 8+nodes*nodes;
return current;
}
unsigned long northbridge_write_acpi_tables(
struct device *device,
unsigned long start,
acpi_rsdp_t *rsdp)
{
unsigned long current;
acpi_srat_t *srat;
acpi_slit_t *slit;
current = start;
/* Fills sysconf structure needed for SRAT and SLIT. */
get_bus_conf();
current = ALIGN(current, 16);
srat = (acpi_srat_t *) current;
printk(BIOS_DEBUG, "ACPI: * SRAT @ %p\n", srat);
acpi_create_srat(srat, acpi_fill_srat);
current += srat->header.length;
acpi_add_table(rsdp, srat);
/* SLIT */
current = ALIGN(current, 16);
slit = (acpi_slit_t *) current;
printk(BIOS_DEBUG, "ACPI: * SLIT @ %p\n", slit);
acpi_create_slit(slit, acpi_fill_slit);
current+=slit->header.length;
acpi_add_table(rsdp,slit);
return current;
}
static void k8acpi_write_HT(void) {
int i;
acpigen_write_name("HCLK");
acpigen_write_package(HC_POSSIBLE_NUM);
for (i = 0; i < sysconf.hc_possible_num; i++) {
acpigen_write_dword(sysconf.pci1234[i]);
}
for (i = sysconf.hc_possible_num; i < HC_POSSIBLE_NUM; i++) { // in case we set array size to other than 8
acpigen_write_dword(0x0);
}
acpigen_pop_len();
acpigen_write_name("HCDN");
acpigen_write_package(HC_POSSIBLE_NUM);
for (i = 0; i < sysconf.hc_possible_num; i++) {
acpigen_write_dword(sysconf.hcdn[i]);
}
for (i = sysconf.hc_possible_num; i < HC_POSSIBLE_NUM; i++) { // in case we set array size to other than 8
acpigen_write_dword(0x20202020);
}
acpigen_pop_len();
}
static void k8acpi_write_pci_data(int dlen, const char *name, int offset) {
struct device *dev;
uint32_t dword;
int i;
dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
acpigen_write_name(name);
acpigen_write_package(dlen);
for (i = 0; i < dlen; i++) {
dword = pci_read_config32(dev, offset+i*4);
acpigen_write_dword(dword);
}
// minus the opcode
acpigen_pop_len();
}
void k8acpi_write_vars(struct device *device)
{
/*
* If more than one physical CPU is installed k8acpi_write_vars()
* is called more than once. If we don't prevent it, a SSDT table
* with duplicate variables will cause some ACPI parsers to be
* confused enough to fail.
*/
static uint8_t ssdt_generated = 0;
if (ssdt_generated)
return;
ssdt_generated = 1;
msr_t msr;
char pscope[] = "\\_SB.PCI0";
acpigen_write_scope(pscope);
k8acpi_write_pci_data(4, "BUSN", 0xe0);
k8acpi_write_pci_data(8, "PCIO", 0xc0);
k8acpi_write_pci_data(16, "MMIO", 0x80);
acpigen_write_name_byte("SBLK", sysconf.sblk);
acpigen_write_name_byte("CBST",
((sysconf.pci1234[0] >> 12) & 0xff) ? 0xf : 0x0);
acpigen_write_name_dword("SBDN", sysconf.sbdn);
msr = rdmsr(TOP_MEM);
acpigen_write_name_dword("TOM1", msr.lo);
msr = rdmsr(TOP_MEM2);
/*
* Since XP only implements parts of ACPI 2.0, we can't use a qword
* here.
* See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt
* slide 22ff.
* Shift value right by 20 bit to make it fit into 32bit,
* giving us 1MB granularity and a limit of almost 4Exabyte of memory.
*/
acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20);
k8acpi_write_HT();
//minus opcode
acpigen_pop_len();
}
void update_ssdtx(void *ssdtx, int i)
{
u8 *PCI;
u8 *HCIN;
u8 *UID;
PCI = ssdtx + 0x32;
HCIN = ssdtx + 0x39;
UID = ssdtx + 0x40;
if (i < 7) {
*PCI = (u8) ('4' + i - 1);
} else {
*PCI = (u8) ('A' + i - 1 - 6);
}
*HCIN = (u8) i;
*UID = (u8) (i + 3);
/* FIXME: need to update the GSI id in the ssdtx too */
}

View File

@ -1,25 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2009 Rudolf Marek <r.marek@assembler.cz>
*
* 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.
*/
#ifndef AMDK8_ACPI_H
#define AMDK8_ACPI_H
#include <arch/acpigen.h>
void k8acpi_write_vars(struct device *device);
unsigned long northbridge_write_acpi_tables(struct device *device,
unsigned long start,
acpi_rsdp_t *rsdp);
#endif

View File

@ -12,18 +12,9 @@
*/
#ifndef AMDK8_H
#define AMDK8_H
#if IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
#define K8_REV_F_SUPPORT_F0_F1_WORKAROUND 0
#include "f.h"
#else
#include "pre_f.h"
#endif
#define HT_INIT_CONTROL 0x6C
#define HTIC_ColdR_Detect (1<<4)
#define HTIC_BIOSR_Detect (1<<5)
#define HTIC_INIT_Detect (1<<6)
@ -32,25 +23,9 @@
#define NODE_MP(x) PCI_DEV(0,24+x,1)
#define NODE_MC(x) PCI_DEV(0,24+x,3)
#ifdef __PRE_RAM__
void showallroutes(int level, pci_devfn_t dev);
void setup_resource_map_offset(const unsigned int *register_values, int max, unsigned offset_pci_dev, unsigned offset_io_base);
void fill_mem_ctrl(int controllers, struct mem_controller *ctrl_a, const uint16_t *spd_addr);
int optimize_link_coherent_ht(void);
unsigned int get_nodes(void);
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
void setup_coherent_ht_domain(void);
#else
int setup_coherent_ht_domain(void);
#endif
#endif
void set_bios_reset(void);
void distinguish_cpu_resets(unsigned int nodeid);
unsigned int get_sblk(void);
unsigned int get_sbbusn(unsigned sblk);
void cpus_ready_for_init(void);
#endif /* AMDK8_H */

View File

@ -1,20 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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 <arch/io.h>
#include <device/pci_def.h>
#include "northbridge/amd/amdk8/early_ht.c"
static void bootblock_northbridge_init(void) {
enumerate_ht_chain();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,259 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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.
*/
/*
* generic K8 debug code, used by mainboard specific romstage.c
*
*/
#include "debug.h"
#include <console/console.h>
#include <arch/io.h>
#include <device/pci_def.h>
#include <delay.h>
#include "raminit.h"
void print_debug_addr(const char *str, void *val)
{
#if IS_ENABLED(CONFIG_DEBUG_CAR)
printk(BIOS_DEBUG, "------Address debug: %s%p------\n", str, val);
#endif
}
#if 1
void print_debug_pci_dev(unsigned dev)
{
printk(BIOS_DEBUG, "PCI: %02x:%02x.%02x", (dev>>20) & 0xff, (dev>>15) & 0x1f, (dev>>12) & 0x7);
}
void print_pci_devices(void)
{
pci_devfn_t dev;
for (dev = PCI_DEV(0, 0, 0);
dev <= PCI_DEV(0xff, 0x1f, 0x7);
dev += PCI_DEV(0,0,1)) {
uint32_t id;
id = pci_read_config32(dev, PCI_VENDOR_ID);
if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
(((id >> 16) & 0xffff) == 0xffff) ||
(((id >> 16) & 0xffff) == 0x0000)) {
continue;
}
print_debug_pci_dev(dev);
printk(BIOS_DEBUG, " %04x:%04x\n", (id & 0xffff), (id>>16));
if (((dev>>12) & 0x07) == 0) {
uint8_t hdr_type;
hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
if ((hdr_type & 0x80) != 0x80) {
dev += PCI_DEV(0,0,7);
}
}
}
}
void dump_pci_device(unsigned dev)
{
int i;
print_debug_pci_dev(dev);
for (i = 0; i < 256; i++) {
unsigned char val;
if ((i & 0x0f) == 0) {
printk(BIOS_DEBUG, "\n%02x:",i);
}
val = pci_read_config8(dev, i);
printk(BIOS_DEBUG, " %02x", val);
}
printk(BIOS_DEBUG, "\n");
}
#if IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
void dump_pci_device_index_wait(unsigned dev, uint32_t index_reg)
{
int i;
print_debug_pci_dev(dev);
printk(BIOS_DEBUG, " -- index_reg=%08x", index_reg);
for (i = 0; i < 0x40; i++) {
uint32_t val;
int j;
printk(BIOS_DEBUG, "\n%02x:",i);
val = pci_read_config32_index_wait(dev, index_reg, i);
for (j = 0; j < 4; j++) {
printk(BIOS_DEBUG, " %02x", val & 0xff);
val >>= 8;
}
}
printk(BIOS_DEBUG, "\n");
}
#endif
void dump_pci_devices(void)
{
pci_devfn_t dev;
for (dev = PCI_DEV(0, 0, 0);
dev <= PCI_DEV(0xff, 0x1f, 0x7);
dev += PCI_DEV(0,0,1)) {
uint32_t id;
id = pci_read_config32(dev, PCI_VENDOR_ID);
if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
(((id >> 16) & 0xffff) == 0xffff) ||
(((id >> 16) & 0xffff) == 0x0000)) {
continue;
}
dump_pci_device(dev);
if (((dev>>12) & 0x07) == 0) {
uint8_t hdr_type;
hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
if ((hdr_type & 0x80) != 0x80) {
dev += PCI_DEV(0,0,7);
}
}
}
}
void dump_pci_devices_on_bus(unsigned busn)
{
pci_devfn_t dev;
for (dev = PCI_DEV(busn, 0, 0);
dev <= PCI_DEV(busn, 0x1f, 0x7);
dev += PCI_DEV(0,0,1)) {
uint32_t id;
id = pci_read_config32(dev, PCI_VENDOR_ID);
if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
(((id >> 16) & 0xffff) == 0xffff) ||
(((id >> 16) & 0xffff) == 0x0000)) {
continue;
}
dump_pci_device(dev);
if (((dev>>12) & 0x07) == 0) {
uint8_t hdr_type;
hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
if ((hdr_type & 0x80) != 0x80) {
dev += PCI_DEV(0,0,7);
}
}
}
}
#if IS_ENABLED(CONFIG_DEBUG_SMBUS)
void dump_spd_registers(const struct mem_controller *ctrl)
{
int i;
printk(BIOS_DEBUG, "\n");
for (i = 0; i < 4; i++) {
unsigned device;
device = ctrl->channel0[i];
if (device) {
int j;
printk(BIOS_DEBUG, "dimm: %02x.0: %02x", i, device);
for (j = 0; j < 128; j++) {
int status;
unsigned char byte;
if ((j & 0xf) == 0) {
printk(BIOS_DEBUG, "\n%02x: ", j);
}
status = spd_read_byte(device, j);
if (status < 0) {
break;
}
byte = status & 0xff;
printk(BIOS_DEBUG, "%02x ", byte);
}
printk(BIOS_DEBUG, "\n");
}
device = ctrl->channel1[i];
if (device) {
int j;
printk(BIOS_DEBUG, "dimm: %02x.1: %02x", i, device);
for (j = 0; j < 128; j++) {
int status;
unsigned char byte;
if ((j & 0xf) == 0) {
printk(BIOS_DEBUG, "\n%02x: ", j);
}
status = spd_read_byte(device, j);
if (status < 0) {
break;
}
byte = status & 0xff;
printk(BIOS_DEBUG, "%02x ", byte);
}
printk(BIOS_DEBUG, "\n");
}
}
}
void dump_smbus_registers(void)
{
unsigned device;
printk(BIOS_DEBUG, "\n");
for (device = 1; device < 0x80; device++) {
int j;
if (spd_read_byte(device, 0) < 0)
continue;
printk(BIOS_DEBUG, "smbus: %02x", device);
for (j = 0; j < 256; j++) {
int status;
unsigned char byte;
status = spd_read_byte(device, j);
if (status < 0) {
break;
}
if ((j & 0xf) == 0) {
printk(BIOS_DEBUG, "\n%02x: ",j);
}
byte = status & 0xff;
printk(BIOS_DEBUG, "%02x ", byte);
}
printk(BIOS_DEBUG, "\n");
}
}
#endif
void dump_io_resources(unsigned port)
{
int i;
udelay(2000);
printk(BIOS_DEBUG, "%04x:\n", port);
for (i = 0; i < 256; i++) {
uint8_t val;
if ((i & 0x0f) == 0) {
printk(BIOS_DEBUG, "%02x:", i);
}
val = inb(port);
printk(BIOS_DEBUG, " %02x",val);
if ((i & 0x0f) == 0x0f) {
printk(BIOS_DEBUG, "\n");
}
port++;
}
}
void dump_mem(unsigned start, unsigned end)
{
unsigned i;
printk(BIOS_DEBUG, "dump_mem:");
for (i = start; i < end; i++) {
if ((i & 0xf) == 0) {
printk(BIOS_DEBUG, "\n%08x:", i);
}
printk(BIOS_DEBUG, " %02x", (unsigned char)*((unsigned char *)i));
}
printk(BIOS_DEBUG, "\n");
}
#endif

View File

@ -1,32 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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.
*/
#ifndef AMDK8_DEBUG_H
#define AMDK8_DEBUG_H
#include <inttypes.h>
#include <arch/io.h>
void print_debug_addr(const char *str, void *val);
void print_debug_pci_dev(unsigned int dev);
void print_pci_devices(void);
void dump_pci_device(unsigned int dev);
void dump_pci_device_index_wait(unsigned int dev, uint32_t index_reg);
uint32_t pci_read_config32_index_wait(pci_devfn_t dev,
uint32_t index_reg, uint32_t index);
void dump_pci_devices(void);
void dump_pci_devices_on_bus(unsigned int busn);
void dump_io_resources(unsigned int port);
void dump_mem(unsigned start, unsigned end);
#endif

View File

@ -1,154 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 2005.11 yhlu add let the real sb to use small unitid
*
* 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.
*/
// only for sb ht chain
static void enumerate_ht_chain(void)
{
#if CONFIG_HT_CHAIN_UNITID_BASE != 0
/* CONFIG_HT_CHAIN_UNITID_BASE could be 0 (only one ht device in the ht chain), if so, don't need to go through the chain */
/* Assumption the HT chain that is bus 0 has the HT I/O Hub on it.
* On most boards this just happens. If a CPU has multiple
* non Coherent links the appropriate bus registers for the
* links needs to be programed to point at bus 0.
*/
unsigned next_unitid, last_unitid;
pci_devfn_t dev;
#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
//let't record the device of last ht device, So we can set the Unitid to CONFIG_HT_CHAIN_END_UNITID_BASE
unsigned real_last_unitid = 0;
uint8_t real_last_pos = 0;
int ht_dev_num = 0; // except host_bridge
uint8_t end_used = 0;
#endif
dev = PCI_DEV(0,0,0);
next_unitid = CONFIG_HT_CHAIN_UNITID_BASE;
do {
uint32_t id;
uint8_t hdr_type, pos;
last_unitid = next_unitid;
id = pci_read_config32(dev, PCI_VENDOR_ID);
/* If the chain is enumerated quit */
if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
(((id >> 16) & 0xffff) == 0xffff) ||
(((id >> 16) & 0xffff) == 0x0000))
{
break;
}
hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
pos = 0;
hdr_type &= 0x7f;
if ((hdr_type == PCI_HEADER_TYPE_NORMAL) ||
(hdr_type == PCI_HEADER_TYPE_BRIDGE))
{
pos = pci_read_config8(dev, PCI_CAPABILITY_LIST);
}
while (pos != 0) {
uint8_t cap;
cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID);
if (cap == PCI_CAP_ID_HT) {
uint16_t flags;
/* Read and write and reread flags so the link
* direction bit is valid.
*/
flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags);
flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
if ((flags >> 13) == 0) {
unsigned count;
unsigned ctrl, ctrl_off;
pci_devfn_t devx;
#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
if (next_unitid >= 0x18) { // don't get mask out by k8, at this time BSP, RT is not enabled, it will response from 0x18,0--0x1f.
if (!end_used) {
next_unitid = CONFIG_HT_CHAIN_END_UNITID_BASE;
end_used = 1;
} else {
goto out;
}
}
real_last_unitid = next_unitid;
real_last_pos = pos;
ht_dev_num++;
#endif
flags &= ~0x1f;
flags |= next_unitid & 0x1f;
count = (flags >> 5) & 0x1f;
devx = PCI_DEV(0, next_unitid, 0);
pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags);
next_unitid += count;
flags = pci_read_config16(devx, pos + PCI_CAP_FLAGS);
/* Test for end of chain */
ctrl_off = ((flags >> 10) & 1)?
PCI_HT_CAP_SLAVE_CTRL0 : PCI_HT_CAP_SLAVE_CTRL1; // another end
do {
ctrl = pci_read_config16(devx, pos + ctrl_off);
/* Is this the end of the hypertransport chain? */
if (ctrl & (1 << 6)) {
goto out;
}
if (ctrl & ((1 << 4) | (1 << 8))) {
/*
* Either the link has failed, or we have
* a CRC error.
* Sometimes this can happen due to link
* retrain, so lets knock it down and see
* if its transient
*/
ctrl |= ((1 << 4) | (1 <<8)); // Link fail + Crc
pci_write_config16(devx, pos + ctrl_off, ctrl);
ctrl = pci_read_config16(devx, pos + ctrl_off);
if (ctrl & ((1 << 4) | (1 << 8))) {
// can not clear the error
break;
}
}
} while ((ctrl & (1 << 5)) == 0);
break;
}
}
pos = pci_read_config8(dev, pos + PCI_CAP_LIST_NEXT);
}
} while (last_unitid != next_unitid);
out:
;
#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
if ((ht_dev_num > 1) && (real_last_unitid != CONFIG_HT_CHAIN_END_UNITID_BASE) && !end_used) {
uint16_t flags;
dev = PCI_DEV(0,real_last_unitid, 0);
flags = pci_read_config16(dev, real_last_pos + PCI_CAP_FLAGS);
flags &= ~0x1f;
flags |= CONFIG_HT_CHAIN_END_UNITID_BASE & 0x1f;
pci_write_config16(dev, real_last_pos + PCI_CAP_FLAGS, flags);
}
#endif
#endif
}

View File

@ -1,193 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2009 Rudolf Marek <r.marek@assembler.cz>
*
* 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 <arch/io.h>
#include <console/console.h>
#include <cpu/x86/lapic.h>
#include <delay.h>
#include <cpu/amd/mtrr.h>
#include "raminit.h"
#include "f.h"
void exit_from_self(int controllers, const struct mem_controller *ctrl,
struct sys_info *sysinfo)
{
int i;
u32 dcl, dch;
u32 pcidev;
u8 bitmask;
u8 is_post_rev_g;
u32 local_cpuid;
for (i = 0; i < controllers; i++) {
if (!sysinfo->ctrl_present[i])
continue;
/* Skip everything if I don't have any memory on this controller */
dch = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_HIGH);
if (!(dch & DCH_MemClkFreqVal)) {
continue;
}
local_cpuid = pci_read_config32(ctrl[i].f3, 0xfc);
is_post_rev_g = ((local_cpuid & 0xfff00) > 0x50f00);
/* ChipKill */
dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
if (dcl & DCL_DimmEccEn) {
u32 mnc;
printk(BIOS_SPEW, "ECC enabled\n");
mnc = pci_read_config32(ctrl[i].f3, MCA_NB_CONFIG);
mnc |= MNC_ECC_EN;
if (dcl & DCL_Width128) {
mnc |= MNC_CHIPKILL_EN;
}
pci_write_config32(ctrl[i].f3, MCA_NB_CONFIG, mnc);
}
printk(BIOS_DEBUG, "before resume errata #%d\n",
(is_post_rev_g) ? 270 : 125);
/*
1. Restore memory controller registers as normal.
2. Set the DisAutoRefresh bit (Dev:2x8C[18]). (270 only)
3. Set the EnDramInit bit (Dev:2x7C[31]), clear all other bits in the same register).
4. Wait at least 750 us.
5. Clear the EnDramInit bit.
6. Clear the DisAutoRefresh bit. (270 only)
7. Read the value of Dev:2x80 and write that value back to Dev:2x80.
8. Set the exit from the self refresh bit (Dev:2x90[1]).
9. Clear the exit from self refresh bit immediately.
Note: Steps 8 and 9 must be executed in a single 64-byte aligned uninterrupted instruction stream.
*/
enable_lapic();
init_timer();
printk(BIOS_DEBUG, "before exit errata - timer enabled\n");
if (is_post_rev_g) {
dcl =
pci_read_config32(ctrl[i].f2,
DRAM_TIMING_HIGH);
dcl |= (1 << 18);
pci_write_config32(ctrl[i].f2, DRAM_TIMING_HIGH,
dcl);
}
dcl = DI_EnDramInit;
pci_write_config32(ctrl[i].f2, DRAM_INIT, dcl);
udelay(800);
printk(BIOS_DEBUG, "before exit errata - after mdelay\n");
dcl = pci_read_config32(ctrl[i].f2, DRAM_INIT);
dcl &= ~DI_EnDramInit;
pci_write_config32(ctrl[i].f2, DRAM_INIT, dcl);
if (is_post_rev_g) {
dcl =
pci_read_config32(ctrl[i].f2,
DRAM_TIMING_HIGH);
dcl &= ~(1 << 18);
pci_write_config32(ctrl[i].f2, DRAM_TIMING_HIGH,
dcl);
}
dcl = pci_read_config32(ctrl[i].f2, DRAM_BANK_ADDR_MAP);
pci_write_config32(ctrl[i].f2, DRAM_BANK_ADDR_MAP, dcl);
/* I was unable to do that like: ctrl[i].f2->path.pci.devfn << 8 */
pcidev =
0x80000000 | ((((ctrl[i].node_id + 0x18) << 3) | 0x2)
<< 8) | 0x90;
printk(BIOS_DEBUG, "pcidev is %x\n", pcidev);
bitmask = 2;
__asm__ __volatile__("pushl %0\n\t"
"movw $0xcf8, %%dx\n\t"
"out %%eax, (%%dx)\n\t"
"movw $0xcfc, %%dx\n\t"
"inl %%dx, %%eax\n\t"
"orb %1, %%al\n\t"
"not %1\n\t"
".align 64\n\t"
"outl %%eax, (%%dx)\n\t"
"andb %1, %%al\n\t"
"outl %%eax, (%%dx)\n\t"
"popl %0\n\t"::"a"(pcidev),
"q"(bitmask):"edx");
}
printk(BIOS_DEBUG, "after exit errata\n");
for (i = 0; i < controllers; i++) {
u32 dcm;
if (!sysinfo->ctrl_present[i])
continue;
/* Skip everything if I don't have any memory on this controller */
if (sysinfo->meminfo[i].dimm_mask == 0x00)
continue;
printk(BIOS_DEBUG, "Exiting memory from self refresh: ");
int loops = 0;
do {
loops++;
if ((loops & 1023) == 0) {
printk(BIOS_DEBUG, ".");
}
dcm =
pci_read_config32(ctrl[i].f2, DRAM_CTRL_MISC);
} while (((dcm & DCM_MemClrStatus) ==
0) /* || ((dcm & DCM_DramEnabled) == 0) */);
if (loops >= TIMEOUT_LOOPS) {
printk(BIOS_DEBUG, "timeout with with cntrl[%d]\n", i);
continue;
}
printk(BIOS_DEBUG, " done\n");
}
#if CONFIG_HW_MEM_HOLE_SIZEK != 0
/* init hw mem hole here */
/* DramHoleValid bit only can be set after MemClrStatus is set by Hardware */
set_hw_mem_hole(controllers, ctrl);
#endif
/* store tom to sysinfo, and it will be used by dqs_timing */
{
msr_t msr;
//[1M, TOM)
msr = rdmsr(TOP_MEM);
sysinfo->tom_k = ((msr.hi << 24) | (msr.lo >> 8)) >> 2;
//[4G, TOM2)
msr = rdmsr(TOP_MEM2);
sysinfo->tom2_k = ((msr.hi << 24) | (msr.lo >> 8)) >> 2;
}
for (i = 0; i < controllers; i++) {
if (!sysinfo->ctrl_present[i])
continue;
/* Skip everything if I don't have any memory on this controller */
if (sysinfo->meminfo[i].dimm_mask == 0x00)
continue;
dqs_restore_MC_NVRAM((ctrl + i)->f2);
sysinfo->mem_trained[i] = 1; // mem was trained
}
}

View File

@ -1,606 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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.
*/
#ifndef AMDK8_F_H
#define AMDK8_F_H
#include <compiler.h>
/* Definitions of various K8 registers */
/* Function 0 */
#define HT_TRANSACTION_CONTROL 0x68
#define HTTC_DIS_RD_B_P (1 << 0)
#define HTTC_DIS_RD_DW_P (1 << 1)
#define HTTC_DIS_WR_B_P (1 << 2)
#define HTTC_DIS_WR_DW_P (1 << 3)
#define HTTC_DIS_MTS (1 << 4)
#define HTTC_CPU1_EN (1 << 5)
#define HTTC_CPU_REQ_PASS_PW (1 << 6)
#define HTTC_CPU_RD_RSP_PASS_PW (1 << 7)
#define HTTC_DIS_P_MEM_C (1 << 8)
#define HTTC_DIS_RMT_MEM_C (1 << 9)
#define HTTC_DIS_FILL_P (1 << 10)
#define HTTC_RSP_PASS_PW (1 << 11)
#define HTTC_CHG_ISOC_TO_ORD (1 << 12)
#define HTTC_BUF_REL_PRI_SHIFT 13
#define HTTC_BUF_REL_PRI_MASK 3
#define HTTC_BUF_REL_PRI_64 0
#define HTTC_BUF_REL_PRI_16 1
#define HTTC_BUF_REL_PRI_8 2
#define HTTC_BUF_REL_PRI_2 3
#define HTTC_LIMIT_CLDT_CFG (1 << 15)
#define HTTC_LINT_EN (1 << 16)
#define HTTC_APIC_EXT_BRD_CST (1 << 17)
#define HTTC_APIC_EXT_ID (1 << 18)
#define HTTC_APIC_EXT_SPUR (1 << 19)
#define HTTC_SEQ_ID_SRC_NODE_EN (1 << 20)
#define HTTC_DS_NP_REQ_LIMIT_SHIFT 21
#define HTTC_DS_NP_REQ_LIMIT_MASK 3
#define HTTC_DS_NP_REQ_LIMIT_NONE 0
#define HTTC_DS_NP_REQ_LIMIT_1 1
#define HTTC_DS_NP_REQ_LIMIT_4 2
#define HTTC_DS_NP_REQ_LIMIT_8 3
#define HTTC_MED_PRI_BYP_CNT_SHIFT 24
#define HTTC_MED_PRI_BYP_CNT_MASK 3
#define HTTC_HI_PRI_BYP_CNT_SHIFT 26
#define HTTC_HI_PRI_BYP_CNT_MASK 3
/* Function 1 */
#define PCI_IO_BASE0 0xc0
#define PCI_IO_BASE1 0xc8
#define PCI_IO_BASE2 0xd0
#define PCI_IO_BASE3 0xd8
#define PCI_IO_BASE_VGA_EN (1 << 4)
#define PCI_IO_BASE_NO_ISA (1 << 5)
/* Function 2 */
#define DRAM_CSBASE 0x40
#define DRAM_CSMASK 0x60
#define DRAM_BANK_ADDR_MAP 0x80
#define DRAM_CTRL 0x78
#define DC_RdPtrInit_SHIFT 0
#define DC_RdPrtInit_MASK 0xf
#define DC_RdPadRcvFifoDly_SHIFT 4
#define DC_RdPadRcvFifoDly_MASK 7
#define DC_RdPadRcvFiloDly_1_5_CLK 2
#define DC_RdPadRcvFiloDly_2_CLK 3
#define DC_RdPadRcvFiloDly_2_5_CLK 4
#define DC_RdPadRcvFiloDly_3_CLK 5
#define DC_RdPadRcvFiloDly_3_5_CLK 6
#define DC_AltVidC3MemClkTriEn (1<<16)
#define DC_DllTempAdjTime_SHIFT 17
#define DC_DllTempAdjTime_MASK 1
#define DC_DllTempAdjTime_5_MS 0
#define DC_DllTempAdjTime_1_MS 1
#define DC_DqsRcvEnTrain (1<<18)
#define DRAM_INIT 0x7c
#define DI_MrsAddress_SHIFT 0
#define DI_MrsAddress_MASK 0xffff
#define DI_MrsBank_SHIFT 16
#define DI_MrsBank_MASK 7
#define DI_SendRchgAll (1<<24)
#define DI_SendAutoRefresh (1<<25)
#define DI_SendMrsCmd (1<<26)
#define DI_DeassertMemRstX (1<<27)
#define DI_AssertCke (1<<28)
#define DI_EnDramInit (1<<31)
#define DRAM_TIMING_LOW 0x88
#define DTL_TCL_SHIFT 0
#define DTL_TCL_MASK 7
#define DTL_TCL_BASE 1
#define DTL_TCL_MIN 3
#define DTL_TCL_MAX 6
#define DTL_TRCD_SHIFT 4
#define DTL_TRCD_MASK 3
#define DTL_TRCD_BASE 3
#define DTL_TRCD_MIN 3
#define DTL_TRCD_MAX 6
#define DTL_TRP_SHIFT 8
#define DTL_TRP_MASK 3
#define DTL_TRP_BASE 3
#define DTL_TRP_MIN 3
#define DTL_TRP_MAX 6
#define DTL_TRTP_SHIFT 11
#define DTL_TRTP_MASK 1
#define DTL_TRTP_BASE 2
#define DTL_TRTP_MIN 2 /* 4 for 64 bytes*/
#define DTL_TRTP_MAX 3 /* 5 for 64 bytes */
#define DTL_TRAS_SHIFT 12
#define DTL_TRAS_MASK 0xf
#define DTL_TRAS_BASE 3
#define DTL_TRAS_MIN 5
#define DTL_TRAS_MAX 18
#define DTL_TRC_SHIFT 16
#define DTL_TRC_MASK 0xf
#define DTL_TRC_BASE 11
#define DTL_TRC_MIN 11
#define DTL_TRC_MAX 26
#define DTL_TWR_SHIFT 20
#define DTL_TWR_MASK 3
#define DTL_TWR_BASE 3
#define DTL_TWR_MIN 3
#define DTL_TWR_MAX 6
#define DTL_TRRD_SHIFT 22
#define DTL_TRRD_MASK 3
#define DTL_TRRD_BASE 2
#define DTL_TRRD_MIN 2
#define DTL_TRRD_MAX 5
#define DTL_MemClkDis_SHIFT 24 /* Channel A */
#define DTL_MemClkDis3 (1 << 26)
#define DTL_MemClkDis2 (1 << 27)
#define DTL_MemClkDis1 (1 << 28)
#define DTL_MemClkDis0 (1 << 29)
#define DTL_MemClkDis1_AM2 (0x51 << 24)
#define DTL_MemClkDis0_AM2 (0xa2 << 24)
#define DTL_MemClkDis0_S1g1 (0xa2 << 24)
/* DTL_MemClkDis for m2 and s1g1 is different */
#define DRAM_TIMING_HIGH 0x8c
#define DTH_TRWTTO_SHIFT 4
#define DTH_TRWTTO_MASK 7
#define DTH_TRWTTO_BASE 2
#define DTH_TRWTTO_MIN 2
#define DTH_TRWTTO_MAX 9
#define DTH_TWTR_SHIFT 8
#define DTH_TWTR_MASK 3
#define DTH_TWTR_BASE 0
#define DTH_TWTR_MIN 1
#define DTH_TWTR_MAX 3
#define DTH_TWRRD_SHIFT 10
#define DTH_TWRRD_MASK 3
#define DTH_TWRRD_BASE 0
#define DTH_TWRRD_MIN 0
#define DTH_TWRRD_MAX 3
#define DTH_TWRWR_SHIFT 12
#define DTH_TWRWR_MASK 3
#define DTH_TWRWR_BASE 1
#define DTH_TWRWR_MIN 1
#define DTH_TWRWR_MAX 3
#define DTH_TRDRD_SHIFT 14
#define DTH_TRDRD_MASK 3
#define DTH_TRDRD_BASE 2
#define DTH_TRDRD_MIN 2
#define DTH_TRDRD_MAX 5
#define DTH_TREF_SHIFT 16
#define DTH_TREF_MASK 3
#define DTH_TREF_7_8_US 2
#define DTH_TREF_3_9_US 3
#define DTH_TRFC0_SHIFT 20 /* for Logical DIMM0 */
#define DTH_TRFC_MASK 7
#define DTH_TRFC_75_256M 0
#define DTH_TRFC_105_512M 1
#define DTH_TRFC_127_5_1G 2
#define DTH_TRFC_195_2G 3
#define DTH_TRFC_327_5_4G 4
#define DTH_TRFC1_SHIFT 23 /*for Logical DIMM1 */
#define DTH_TRFC2_SHIFT 26 /*for Logical DIMM2 */
#define DTH_TRFC3_SHIFT 29 /*for Logical DIMM3 */
#define DRAM_CONFIG_LOW 0x90
#define DCL_InitDram (1<<0)
#define DCL_ExitSelfRef (1<<1)
#define DCL_DramTerm_SHIFT 4
#define DCL_DramTerm_MASK 3
#define DCL_DramTerm_No 0
#define DCL_DramTerm_75_OH 1
#define DCL_DramTerm_150_OH 2
#define DCL_DramTerm_50_OH 3
#define DCL_DrvWeak (1<<7)
#define DCL_ParEn (1<<8)
#define DCL_SelfRefRateEn (1<<9)
#define DCL_BurstLength32 (1<<10)
#define DCL_Width128 (1<<11)
#define DCL_X4Dimm_SHIFT 12
#define DCL_X4Dimm_MASK 0xf
#define DCL_UnBuffDimm (1<<16)
#define DCL_DimmEccEn (1<<19)
#define DRAM_CONFIG_HIGH 0x94
#define DCH_MemClkFreq_SHIFT 0
#define DCH_MemClkFreq_MASK 7
#define DCH_MemClkFreq_200MHz 0
#define DCH_MemClkFreq_266MHz 1
#define DCH_MemClkFreq_333MHz 2
#define DCH_MemClkFreq_400MHz 3
#define DCH_MemClkFreqVal (1<<3)
#define DCH_MaxAsyncLat_SHIFT 4
#define DCH_MaxAsyncLat_MASK 0xf
#define DCH_MaxAsyncLat_BASE 0
#define DCH_MaxAsyncLat_MIN 0
#define DCH_MaxAsyncLat_MAX 15
#define DCH_RDqsEn (1<<12)
#define DCH_DisDramInterface (1<<14)
#define DCH_PowerDownEn (1<<15)
#define DCH_PowerDownMode_SHIFT 16
#define DCH_PowerDownMode_MASK 1
#define DCH_PowerDownMode_Channel_CKE 0
#define DCH_PowerDownMode_ChipSelect_CKE 1
#define DCH_FourRankSODimm (1<<17)
#define DCH_FourRankRDimm (1<<18)
#define DCH_SlowAccessMode (1<<19)
#define DCH_BankSwizzleMode (1<<22)
#define DCH_DcqBypassMax_SHIFT 24
#define DCH_DcqBypassMax_MASK 0xf
#define DCH_DcqBypassMax_BASE 0
#define DCH_DcqBypassMax_MIN 0
#define DCH_DcqBypassMax_MAX 15
#define DCH_FourActWindow_SHIFT 28
#define DCH_FourActWindow_MASK 0xf
#define DCH_FourActWindow_BASE 7
#define DCH_FourActWindow_MIN 8
#define DCH_FourActWindow_MAX 20
// for 0x98 index and 0x9c data
#define DRAM_CTRL_ADDI_DATA_OFFSET 0x98
#define DCAO_DctOffset_SHIFT 0
#define DCAO_DctOffset_MASK 0x3fffffff
#define DCAO_DctAccessWrite (1<<30)
#define DCAO_DctAccessDone (1<<31)
#define DRAM_CTRL_ADDI_DATA_PORT 0x9c
#define DRAM_OUTPUT_DRV_COMP_CTRL 0x00
#define DODCC_CkeDrvStren_SHIFT 0
#define DODCC_CkeDrvStren_MASK 3
#define DODCC_CkeDrvStren_1_0X 0
#define DODCC_CkeDrvStren_1_25X 1
#define DODCC_CkeDrvStren_1_5X 2
#define DODCC_CkeDrvStren_2_0X 3
#define DODCC_CsOdtDrvStren_SHIFT 4
#define DODCC_CsOdtDrvStren_MASK 3
#define DODCC_CsOdtDrvStren_1_0X 0
#define DODCC_CsOdtDrvStren_1_25X 1
#define DODCC_CsOdtDrvStren_1_5X 2
#define DODCC_CsOdtDrvStren_2_0X 3
#define DODCC_AddrCmdDrvStren_SHIFT 8
#define DODCC_AddrCmdDrvStren_MASK 3
#define DODCC_AddrCmdDrvStren_1_0X 0
#define DODCC_AddrCmdDrvStren_1_25X 1
#define DODCC_AddrCmdDrvStren_1_5X 2
#define DODCC_AddrCmdDrvStren_2_0X 3
#define DODCC_ClkDrvStren_SHIFT 12
#define DODCC_ClkDrvStren_MASK 3
#define DODCC_ClkDrvStren_0_75X 0
#define DODCC_ClkDrvStren_1_0X 1
#define DODCC_ClkDrvStren_1_25X 2
#define DODCC_ClkDrvStren_1_5X 3
#define DODCC_DataDrvStren_SHIFT 16
#define DODCC_DataDrvStren_MASK 3
#define DODCC_DataDrvStren_0_75X 0
#define DODCC_DataDrvStren_1_0X 1
#define DODCC_DataDrvStren_1_25X 2
#define DODCC_DataDrvStren_1_5X 3
#define DODCC_DqsDrvStren_SHIFT 20
#define DODCC_DqsDrvStren_MASK 3
#define DODCC_DqsDrvStren_0_75X 0
#define DODCC_DqsDrvStren_1_0X 1
#define DODCC_DqsDrvStren_1_25X 2
#define DODCC_DqsDrvStren_1_5X 3
#define DODCC_ProcOdt_SHIFT 28
#define DODCC_ProcOdt_MASK 3
#define DODCC_ProcOdt_300_OHMS 0
#define DODCC_ProcOdt_150_OHMS 1
#define DODCC_ProcOdt_75_OHMS 2
#define DRAM_WRITE_DATA_TIMING_CTRL_LOW 0x01
#define DWDTCL_WrDatTimeByte0_SHIFT 0
#define DWDTC_WrDatTimeByte_MASK 0x3f
#define DWDTC_WrDatTimeByte_BASE 0
#define DWDTC_WrDatTimeByte_MIN 0
#define DWDTC_WrDatTimeByte_MAX 47
#define DWDTCL_WrDatTimeByte1_SHIFT 8
#define DWDTCL_WrDatTimeByte2_SHIFT 16
#define DWDTCL_WrDatTimeByte3_SHIFT 24
#define DRAM_WRITE_DATA_TIMING_CTRL_HIGH 0x02
#define DWDTCH_WrDatTimeByte4_SHIFT 0
#define DWDTCH_WrDatTimeByte5_SHIFT 8
#define DWDTCH_WrDatTimeByte6_SHIFT 16
#define DWDTCH_WrDatTimeByte7_SHIFT 24
#define DRAM_WRITE_DATA_ECC_TIMING_CTRL 0x03
#define DWDETC_WrChkTime_SHIFT 0
#define DWDETC_WrChkTime_MASK 0x3f
#define DWDETC_WrChkTime_BASE 0
#define DWDETC_WrChkTime_MIN 0
#define DWDETC_WrChkTime_MAX 47
#define DRAM_ADDR_TIMING_CTRL 0x04
#define DATC_CkeFineDelay_SHIFT 0
#define DATC_CkeFineDelay_MASK 0x1f
#define DATC_CkeFineDelay_BASE 0
#define DATC_CkeFineDelay_MIN 0
#define DATC_CkeFineDelay_MAX 31
#define DATC_CkeSetup (1<<5)
#define DATC_CsOdtFineDelay_SHIFT 8
#define DATC_CsOdtFineDelay_MASK 0x1f
#define DATC_CsOdtFineDelay_BASE 0
#define DATC_CsOdtFineDelay_MIN 0
#define DATC_CsOdtFineDelay_MAX 31
#define DATC_CsOdtSetup (1<<13)
#define DATC_AddrCmdFineDelay_SHIFT 16
#define DATC_AddrCmdFineDelay_MASK 0x1f
#define DATC_AddrCmdFineDelay_BASE 0
#define DATC_AddrCmdFineDelay_MIN 0
#define DATC_AddrCmdFineDelay_MAX 31
#define DATC_AddrCmdSetup (1<<21)
#define DRAM_READ_DQS_TIMING_CTRL_LOW 0x05
#define DRDTCL_RdDqsTimeByte0_SHIFT 0
#define DRDTC_RdDqsTimeByte_MASK 0x3f
#define DRDTC_RdDqsTimeByte_BASE 0
#define DRDTC_RdDqsTimeByte_MIN 0
#define DRDTC_RdDqsTimeByte_MAX 47
#define DRDTCL_RdDqsTimeByte1_SHIFT 8
#define DRDTCL_RdDqsTimeByte2_SHIFT 16
#define DRDTCL_RdDqsTimeByte3_SHIFT 24
#define DRAM_READ_DQS_TIMING_CTRL_HIGH 0x06
#define DRDTCH_RdDqsTimeByte4_SHIFT 0
#define DRDTCH_RdDqsTimeByte5_SHIFT 8
#define DRDTCH_RdDqsTimeByte6_SHIFT 16
#define DRDTCH_RdDqsTimeByte7_SHIFT 24
#define DRAM_READ_DQS_ECC_TIMING_CTRL 0x07
#define DRDETC_RdDqsTimeCheck_SHIFT 0
#define DRDETC_RdDqsTimeCheck_MASK 0x3f
#define DRDETC_RdDqsTimeCheck_BASE 0
#define DRDETC_RdDqsTimeCheck_MIN 0
#define DRDETC_RdDqsTimeCheck_MAX 47
#define DRAM_DQS_RECV_ENABLE_TIME0 0x10
#define DDRET_DqsRcvEnDelay_SHIFT 0
#define DDRET_DqsRcvEnDelay_MASK 0xff
#define DDRET_DqsRcvEnDelay_BASE 0
#define DDRET_DqsRcvEnDelay_MIN 0
#define DDRET_DqsRcvEnDelay_MAX 0xae /* unit is 50ps */
#define DRAM_DQS_RECV_ENABLE_TIME1 0x13
#define DRAM_DQS_RECV_ENABLE_TIME2 0x16
#define DRAM_DQS_RECV_ENABLE_TIME3 0x19
/* there are index 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x30, 0x33, 0x36, 0x39
that are corresponding to 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x13, 0x16, 0x19
*/
#define DRAM_CTRL_MISC 0xa0
#define DCM_MemClrStatus (1<<0)
#define DCM_DisableJitter (1<<1)
#define DCM_RdWrQByp_SHIFT 2
#define DCM_RdWrQByp_MASK 3
#define DCM_RdWrQByp_2 0
#define DCM_RdWrQByp_4 1
#define DCM_RdWrQByp_8 2
#define DCM_RdWrQByp_16 3
#define DCM_Mode64BitMux (1<<4)
#define DCM_DCC_EN (1<<5)
#define DCM_ILD_lmt_SHIFT 6
#define DCM_ILD_lmt_MASK 7
#define DCM_ILD_lmt_0 0
#define DCM_ILD_lmt_4 1
#define DCM_ILD_lmt_8 2
#define DCM_ILD_lmt_16 3
#define DCM_ILD_lmt_32 4
#define DCM_ILD_lmt_64 5
#define DCM_ILD_lmt_128 6
#define DCM_ILD_lmt_256 7
#define DCM_DramEnabled (1<<9)
#define DCM_MemClkDis_SHIFT 24 /* Channel B */
#define DCM_MemClkDis3 (1 << 26)
#define DCM_MemClkDis2 (1 << 27)
#define DCM_MemClkDis1 (1 << 28)
#define DCM_MemClkDis0 (1 << 29)
/* Function 3 */
#define MCA_NB_CONFIG 0x44
#define MNC_ECC_EN (1 << 22)
#define MNC_CHIPKILL_EN (1 << 23)
#define SCRUB_CONTROL 0x58
#define SCRUB_NONE 0
#define SCRUB_40ns 1
#define SCRUB_80ns 2
#define SCRUB_160ns 3
#define SCRUB_320ns 4
#define SCRUB_640ns 5
#define SCRUB_1_28us 6
#define SCRUB_2_56us 7
#define SCRUB_5_12us 8
#define SCRUB_10_2us 9
#define SCRUB_20_5us 10
#define SCRUB_41_0us 11
#define SCRUB_81_9us 12
#define SCRUB_163_8us 13
#define SCRUB_327_7us 14
#define SCRUB_655_4us 15
#define SCRUB_1_31ms 16
#define SCRUB_2_62ms 17
#define SCRUB_5_24ms 18
#define SCRUB_10_49ms 19
#define SCRUB_20_97ms 20
#define SCRUB_42ms 21
#define SCRUB_84ms 22
#define SC_DRAM_SCRUB_RATE_SHFIT 0
#define SC_DRAM_SCRUB_RATE_MASK 0x1f
#define SC_L2_SCRUB_RATE_SHIFT 8
#define SC_L2_SCRUB_RATE_MASK 0x1f
#define SC_L1D_SCRUB_RATE_SHIFT 16
#define SC_L1D_SCRUB_RATE_MASK 0x1f
#define SCRUB_ADDR_LOW 0x5C
#define SCRUB_ADDR_HIGH 0x60
#define NORTHBRIDGE_CAP 0xE8
#define NBCAP_128Bit (1 << 0)
#define NBCAP_MP (1 << 1)
#define NBCAP_BIG_MP (1 << 2)
#define NBCAP_ECC (1 << 3)
#define NBCAP_CHIPKILL_ECC (1 << 4)
#define NBCAP_MEMCLK_SHIFT 5
#define NBCAP_MEMCLK_MASK 3
#define NBCAP_MEMCLK_200MHZ 3
#define NBCAP_MEMCLK_266MHZ 2
#define NBCAP_MEMCLK_333MHZ 1
#define NBCAP_MEMCLK_NOLIMIT 0
#define NBCAP_MEMCTRL (1 << 8)
#define NBCAP_HtcCap (1<<10)
#define NBCAP_CmpCap_SHIFT 12
#define NBCAP_CmpCap_MASK 3
#define LinkConnected (1 << 0)
#define InitComplete (1 << 1)
#define NonCoherent (1 << 2)
#define ConnectionPending (1 << 4)
#include "raminit.h"
//struct definitions
struct dimm_size {
uint8_t per_rank; // it is rows + col + bank_lines + data lines */
uint8_t rows;
uint8_t col;
uint8_t bank; //1, 2, 3 mean 2, 4, 8
uint8_t rank;
} __packed;
struct mem_info { // pernode
uint32_t dimm_mask;
struct dimm_size sz[DIMM_SOCKETS];
uint32_t x4_mask;
uint32_t x16_mask;
uint32_t single_rank_mask;
uint32_t page_1k_mask;
// uint32_t ecc_mask;
// uint32_t registered_mask;
uint8_t is_opteron;
uint8_t is_registered;
uint8_t is_ecc;
uint8_t is_Width128;
uint8_t is_64MuxMode;
uint8_t memclk_set; // we need to use this to retrieve the mem param
uint8_t rsv[2];
} __packed;
struct link_pair_st {
pci_devfn_t udev;
uint32_t upos;
uint32_t uoffs;
pci_devfn_t dev;
uint32_t pos;
uint32_t offs;
} __packed;
struct sys_info {
uint8_t ctrl_present[NODE_NUMS];
struct mem_info meminfo[NODE_NUMS];
struct mem_controller ctrl[NODE_NUMS];
uint8_t mem_trained[NODE_NUMS]; //0: no dimm, 1: trained, 0x80: not started, 0x81: recv1 fail, 0x82: Pos Fail, 0x83:recv2 fail
uint32_t tom_k;
uint32_t tom2_k;
uint32_t mem_base[NODE_NUMS];
uint32_t cs_base[NODE_NUMS*8]; //8 cs_idx
uint32_t hole_reg[NODE_NUMS]; // can we spare it to one, and put ctrl idx in it
uint8_t dqs_delay_a[NODE_NUMS*2*2*9]; //8 node channel 2, direction 2 , bytelane *9
uint8_t dqs_rcvr_dly_a[NODE_NUMS*2*8]; //8 node, channel 2, receiver 8
uint32_t nodes;
struct link_pair_st link_pair[16];// enough? only in_conherent
uint32_t link_pair_num;
uint32_t ht_c_num;
uint32_t sbdn;
uint32_t sblk;
uint32_t sbbusn;
} __packed;
#ifdef __PRE_RAM__
#include <arch/early_variables.h>
extern struct sys_info sysinfo_car;
#endif
#include <reset.h>
#if ((CONFIG_MEM_TRAIN_SEQ != 1) && defined(__PRE_RAM__)) || \
((CONFIG_MEM_TRAIN_SEQ == 1) && !defined(__PRE_RAM__))
static inline void wait_all_core0_mem_trained(struct sys_info *sysinfo)
{
int i;
uint32_t mask = 0;
unsigned needs_reset = 0;
if (sysinfo->nodes == 1) return; // in case only one CPU installed
for (i = 1; i < sysinfo->nodes; i++) {
/* Skip everything if I don't have any memory on this controller */
if (sysinfo->mem_trained[i]== 0x00) continue;
mask |= (1<<i);
}
i = 1;
while (1) {
if (mask & (1<<i)) {
if ((sysinfo->mem_trained[i])!=0x80) {
mask &= ~(1<<i);
}
}
if (!mask) break;
i++;
i%=sysinfo->nodes;
}
for (i = 0; i < sysinfo->nodes; i++) {
printk(BIOS_DEBUG, "mem_trained[%02x]=%02x\n", i, sysinfo->mem_trained[i]);
switch(sysinfo->mem_trained[i]) {
case 0: //don't need train
case 1: //trained
break;
case 0x81: //recv1: fail
case 0x82: //Pos :fail
case 0x83: //recv2: fail
needs_reset = 1;
break;
}
}
if (needs_reset) {
printk(BIOS_DEBUG, "mem trained failed\n");
#ifdef __PRE_RAM__
soft_reset();
#else
hard_reset();
#endif
}
}
#endif
void dqs_restore_MC_NVRAM(unsigned int dev);
void train_ram_on_node(unsigned nodeid, unsigned coreid,
struct sys_info *sysinfo, unsigned retcall);
#endif /* AMDK8_F_H */

View File

@ -1,73 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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.
*/
#ifndef AMDK8_F_PCI_C
#define AMDK8_F_PCI_C
#include "debug.h"
#ifdef UNUSED_CODE
/* bit [10,8] are dev func, bit[1,0] are dev index */
static uint32_t pci_read_config32_index(pci_devfn_t dev, uint32_t index_reg,
uint32_t index)
{
uint32_t dword;
pci_write_config32(dev, index_reg, index);
dword = pci_read_config32(dev, index_reg+0x4);
return dword;
}
static void pci_write_config32_index(pci_devfn_t dev, uint32_t index_reg,
uint32_t index, uint32_t data)
{
pci_write_config32(dev, index_reg, index);
pci_write_config32(dev, index_reg + 0x4, data);
}
#endif
uint32_t pci_read_config32_index_wait(pci_devfn_t dev,
uint32_t index_reg, uint32_t index)
{
uint32_t dword;
index &= ~(1<<30);
pci_write_config32(dev, index_reg, index);
do {
dword = pci_read_config32(dev, index_reg);
} while (!(dword & (1<<31)));
dword = pci_read_config32(dev, index_reg+0x4);
return dword;
}
static void pci_write_config32_index_wait(pci_devfn_t dev, uint32_t index_reg,
uint32_t index, uint32_t data)
{
uint32_t dword;
pci_write_config32(dev, index_reg + 0x4, data);
index |= (1<<30);
pci_write_config32(dev, index_reg, index);
do {
dword = pci_read_config32(dev, index_reg);
} while (!(dword & (1<<31)));
}
#endif

View File

@ -1,217 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2005 - 2008 Advanced Micro Devices, Inc.
* Copyright (C) 2007 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.
*/
// 2005.9 yhlu serengeti support
// 2005.9 yhlu modify that to more dynamic for AMD Opteron Based MB
// 2007.9 stepan improve code documentation
#include <console/console.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <string.h>
#include <stdint.h>
#include <cpu/amd/amdk8_sysconf.h>
/*
* Why we need the pci1234[] array
*
* It will keep the sequence of HT devices in the HT link registers even when a
* given HT I/O card is not installed.
*
* The final result for pci1234[] will be
*
* pci1234[0] will record the south bridge link and bus range
* pci1234[i] will record HT chain i.
*
* For example, on the Tyan S2885 ramstage will put the AMD8151 chain (HT
* link 0) into the register 0xE0, and the AMD8131/8111 HT chain into the
* register 0xE4.
*
* So we need to make sure that the south bridge link will always be on
* pci1234[0].
*
* Imagine a scenario with multiple HT I/O cards, where you don't install HT I/O 1,
* but you only install HT I/O 2 and HT I/O 3. The HT I/Os will end up in registers
* 0xE4 and 0xE8.
*
* But we want to leave pci1234[1] to HT I/O 1 (even though it is disabled),
* and let HT I/O 2 and HT I/O 3 still use pci1234[2] and pci1234[3].
*
* So we keep the sequence. You need to preset the pci1234[1], pci1234[2],
* pci1234[3] for this purpose.
*
* For this example you need to set
*
* unsigned pci1234[] = {
* 0x0000ff0,
* 0x0000f10, // HT IO 1 card always on node 1
* 0x0000f20, // HT IO 2 card always on node 2
* 0x0000f30 // HT IO 3 card always on node 3
* };
*
* For 2P + htio(n1) + htio(n0_1) + htio(n1_1), 2P + htio(n1) + 2P + htio(n2) + htio(n3):
* You need an array pci1234[6]:
*
* unsigned pci1234[] = {
* 0x0000ff0,
* 0x0000010, // HT IO 1 card always on node 1
* 0x0000f00, // HT IO 2 card always on node 0
* 0x0000110, // HT IO 3 card always on node 1
* 0x0000f20, // HT IO 4 card always on node 2
* 0x0000f30 // HT IO 5 card always on node 3
* };
*
*
* For 4p+htio(n1)+htio(n2)+htio(n3),4p+htio(n1)+4p+htio(n6)+htio(n7):
* You need an array pci1234[6]:
*
* unsigned pci1234[] = {
* 0x0000ff0,
* 0x0000f10, // HT IO 1 card always on node 1
* 0x0000f20, // HT IO 2 card always on node 2
* 0x0000f30, // HT IO 3 card always on node 3
* 0x0000f60, // HT IO 4 card always on node 6
* 0x0000f70 // HT IO 5 card always on node 7
* };
*
*
* For 2p + htio(n1) + htio(n0_1) + htio(n1_1), 2P + htio(n1) + 2P +
* htio(n2) + htio(n3), 2P + htio(n1) + 4P + htio(n4) + htio(n5),
* you need an array pci1234[8]:
*
* unsigned pci1234[] = {
* 0x0000ff0,
* 0x0000010, // HT IO 1 card always on node 1
* 0x0000f00, // HT IO 2 card always on node 0
* 0x0000110, // HT IO 3 card always on node 1
* 0x0000f20, // HT IO 4 card always on node 2
* 0x0000f30 // HT IO 5 card always on node 3
* 0x0000f40, // HT IO 6 card always on node 4
* 0x0000f50 // HT IO 7 card always on node 5
* };
*
*
* For 4P + htio(n1) + htio(n2) + htio(n3), 4p + htio(n1) + 2p + htio(n4) +
* htio(n5), 4p + htio(n1) + 4p + htio(n6) + htio(n7),
* you need an array pci1234[8]:
*
* unsigned pci1234[] = {
* 0x0000ff0,
* 0x0000f10, // HT IO 1 card always on node 1
* 0x0000f20, // HT IO 2 card always on node 2
* 0x0000f30, // HT IO 3 card always on node 3
* 0x0000f40, // HT IO 4 card always on node 4
* 0x0000f50 // HT IO 5 card always on node 5
* 0x0000f60, // HT IO 6 card always on node 6
* 0x0000f70 // HT IO 7 card always on node 7
* };
*
*
* So the maximum posible value of HC_POSSIBLE_NUM is 8. (FIXME Why?)
*
* 1n: 3
* 2n: 2x2 - 1
* 4n: 1x4 - 2
* 6n: 2
* 8n: 2
* Total: 12
*
* Just put all the possible HT Node/link to the list tp pci1234[] in
* src/mainboard/<vendor>/<mainboard>get_bus_conf.c
*
* What about co-processor in socket 1 on a 2 way system? Or socket 2 and
* socket 3 on a 4 way system? Treat that as an HC, too!
*
*/
void get_sblk_pci1234(void)
{
struct device *dev;
int i,j;
uint32_t dword;
/* read PCI_DEV(0,0x18,0) 0x64 bit [8:9] to find out SbLink m */
dev = dev_find_slot(0, PCI_DEVFN(0x18,0));
dword = pci_read_config32(dev, 0x64);
sysconf.sblk = (dword>>8) & 0x3;
dword &=0x0300;
dword |= 1;
sysconf.pci1234[0] = dword;
sysconf.hcid[0] = 0;
/* About hardcoded numbering for HT_IO support
*
* Set the node_id and link_id that could have a HT chain in the one
* array, (FIXME: which one?) then check if is enabled. Then update
* final value
*/
/* Here we need to set hcdn
*
* 1. hypertransport.c needs to record hcdn_reg together with 0xe0,
* 0xe4, 0xe8, 0xec when are set (FIXME: when WHAT is set?)
*
* 2. So at the same time we need update hcdn with hcdn_reg here. FIXME: Why?
*/
dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
for (j = 0; j < 4; j++) {
uint32_t dwordx;
dwordx = pci_read_config32(dev, 0xe0 + j*4);
dwordx &=0xffff0ff1; /* keep bus num, node_id, link_num, enable bits */
if ((dwordx & 0xff1) == dword) { /* SBLINK */
sysconf.pci1234[0] = dwordx;
sysconf.hcdn[0] = sysconf.hcdn_reg[j];
continue;
}
if ((dwordx & 1) == 1) {
/* We need to find out the number of HC
* for exact match
*/
for (i = 1; i < sysconf.hc_possible_num; i++) {
if ((dwordx & 0xff0) == (sysconf.pci1234[i] & 0xff0)) {
sysconf.pci1234[i] = dwordx;
sysconf.hcdn[i] = sysconf.hcdn_reg[j];
break;
}
}
/* For 0xff0 match or same node */
for (i = 1; i < sysconf.hc_possible_num; i++) {
if ((dwordx & 0xff0) == (dwordx & sysconf.pci1234[i] & 0xff0)) {
sysconf.pci1234[i] = dwordx;
sysconf.hcdn[i] = sysconf.hcdn_reg[j];
break;
}
}
}
}
for (i = 1; i < sysconf.hc_possible_num; i++) {
if ((sysconf.pci1234[i] & 1) != 1) {
sysconf.pci1234[i] = 0;
sysconf.hcdn[i] = 0x20202020;
}
sysconf.hcid[i] = 0;
}
}

View File

@ -1,821 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 2004.12 yhlu add multi ht chain dynamically support
* 2005.11 yhlu add let real sb to use small unitid
*
* 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 <device/pci_def.h>
#include <device/pci_ids.h>
#include <device/hypertransport_def.h>
#include <lib.h>
#include "amdk8.h"
// Do we need allocate MMIO? Current We direct last 64M to sblink only, We can not lose access to last 4M range to ROM
#ifndef K8_ALLOCATE_MMIO_RANGE
#define K8_ALLOCATE_MMIO_RANGE 0
#endif
static inline void print_linkn_in (const char *strval, uint8_t byteval)
{
printk(BIOS_DEBUG, "%s%02x\n", strval, byteval);
}
static uint8_t ht_lookup_capability(pci_devfn_t dev, uint16_t val)
{
uint8_t pos;
uint8_t hdr_type;
hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
pos = 0;
hdr_type &= 0x7f;
if ((hdr_type == PCI_HEADER_TYPE_NORMAL) ||
(hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
pos = PCI_CAPABILITY_LIST;
}
if (pos > PCI_CAP_LIST_NEXT) {
pos = pci_read_config8(dev, pos);
}
while (pos != 0) { /* loop through the linked list */
uint8_t cap;
cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID);
if (cap == PCI_CAP_ID_HT) {
uint16_t flags;
flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
if ((flags >> 13) == val) {
/* Entry is a slave or host , success... */
break;
}
}
pos = pci_read_config8(dev, pos + PCI_CAP_LIST_NEXT);
}
return pos;
}
static uint8_t ht_lookup_slave_capability(pci_devfn_t dev)
{
return ht_lookup_capability(dev, 0); // Slave/Primary Interface Block Format
}
static void ht_collapse_previous_enumeration(uint8_t bus, unsigned offset_unitid)
{
pci_devfn_t dev;
//actually, only for one HT device HT chain, and unitid is 0
#if !CONFIG_HT_CHAIN_UNITID_BASE
if (offset_unitid) {
return;
}
#endif
/* Check if is already collapsed */
if ((!offset_unitid) || (offset_unitid && (!((CONFIG_HT_CHAIN_END_UNITID_BASE == 0) && (CONFIG_HT_CHAIN_END_UNITID_BASE <CONFIG_HT_CHAIN_UNITID_BASE))))) {
uint32_t id;
dev = PCI_DEV(bus, 0, 0);
id = pci_read_config32(dev, PCI_VENDOR_ID);
if (!((id == 0xffffffff) || (id == 0x00000000) ||
(id == 0x0000ffff) || (id == 0xffff0000))) {
return;
}
}
/* Spin through the devices and collapse any previous
* hypertransport enumeration.
*/
for (dev = PCI_DEV(bus, 1, 0); dev <= PCI_DEV(bus, 0x1f, 0x7); dev += PCI_DEV(0, 1, 0)) {
uint32_t id;
uint8_t pos;
uint16_t flags;
id = pci_read_config32(dev, PCI_VENDOR_ID);
if ((id == 0xffffffff) || (id == 0x00000000) ||
(id == 0x0000ffff) || (id == 0xffff0000)) {
continue;
}
pos = ht_lookup_slave_capability(dev);
if (!pos) {
continue;
}
/* Clear the unitid */
flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
flags &= ~0x1f;
pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags);
}
}
static uint16_t ht_read_freq_cap(pci_devfn_t dev, uint8_t pos)
{
/* Handle bugs in valid hypertransport frequency reporting */
uint16_t freq_cap;
uint32_t id;
freq_cap = pci_read_config16(dev, pos);
printk(BIOS_SPEW, "pos=0x%x, unfiltered freq_cap=0x%x\n", pos, freq_cap);
freq_cap &= ~(1 << HT_FREQ_VENDOR); /* Ignore Vendor HT frequencies */
id = pci_read_config32(dev, 0);
/* AMD 8131 Errata 48 */
if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8131_PCIX << 16))) {
freq_cap &= ~(1 << HT_FREQ_800Mhz);
return freq_cap;
}
/* AMD 8151 Errata 23 */
if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8151_SYSCTRL << 16))) {
freq_cap &= ~(1 << HT_FREQ_800Mhz);
return freq_cap;
}
/* AMD K8 Unsupported 1GHz? */
if (id == (PCI_VENDOR_ID_AMD | (0x1100 << 16))) {
#if IS_ENABLED(CONFIG_K8_HT_FREQ_1G_SUPPORT)
#if !IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
if (is_cpu_pre_e0()) { // only E0 later support 1GHz
freq_cap &= ~(1 << HT_FREQ_1000Mhz);
}
#endif
#else
freq_cap &= ~(1 << HT_FREQ_1000Mhz);
#endif
}
printk(BIOS_SPEW, "pos=0x%x, filtered freq_cap=0x%x\n", pos, freq_cap);
return freq_cap;
}
static uint8_t ht_read_width_cap(pci_devfn_t dev, uint8_t pos)
{
uint8_t width_cap = pci_read_config8(dev, pos);
uint32_t id;
id = pci_read_config32(dev, 0);
/* netlogic micro cap doesn't support 16 bit yet */
if (id == (0x184e | (0x0001 << 16))) {
if ((width_cap & 0x77) == 0x11) {
width_cap &= 0x88;
}
}
return width_cap;
}
#define LINK_OFFS(CTRL, WIDTH,FREQ,FREQ_CAP) \
(((CTRL & 0xff) << 24) | ((WIDTH & 0xff) << 16) | ((FREQ & 0xff) << 8) | (FREQ_CAP & 0xFF))
#define LINK_CTRL(OFFS) ((OFFS >> 24) & 0xFF)
#define LINK_WIDTH(OFFS) ((OFFS >> 16) & 0xFF)
#define LINK_FREQ(OFFS) ((OFFS >> 8) & 0xFF)
#define LINK_FREQ_CAP(OFFS) ((OFFS) & 0xFF)
#define PCI_HT_HOST_OFFS LINK_OFFS( \
PCI_HT_CAP_HOST_CTRL, \
PCI_HT_CAP_HOST_WIDTH, \
PCI_HT_CAP_HOST_FREQ, \
PCI_HT_CAP_HOST_FREQ_CAP)
#define PCI_HT_SLAVE0_OFFS LINK_OFFS( \
PCI_HT_CAP_SLAVE_CTRL0, \
PCI_HT_CAP_SLAVE_WIDTH0, \
PCI_HT_CAP_SLAVE_FREQ0, \
PCI_HT_CAP_SLAVE_FREQ_CAP0)
#define PCI_HT_SLAVE1_OFFS LINK_OFFS( \
PCI_HT_CAP_SLAVE_CTRL1, \
PCI_HT_CAP_SLAVE_WIDTH1, \
PCI_HT_CAP_SLAVE_FREQ1, \
PCI_HT_CAP_SLAVE_FREQ_CAP1)
static int ht_optimize_link(
pci_devfn_t dev1, uint8_t pos1, unsigned offs1,
pci_devfn_t dev2, uint8_t pos2, unsigned offs2)
{
static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 };
static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 };
uint16_t freq_cap1, freq_cap2;
uint8_t width_cap1, width_cap2, width, old_width, ln_width1, ln_width2;
uint8_t freq, old_freq;
int needs_reset;
/* Set link width and frequency */
printk(BIOS_SPEW, "entering ht_optimize_link\n");
/* Initially assume everything is already optimized and I don't need a reset */
needs_reset = 0;
/* Get the frequency capabilities */
freq_cap1 = ht_read_freq_cap(dev1, pos1 + LINK_FREQ_CAP(offs1));
freq_cap2 = ht_read_freq_cap(dev2, pos2 + LINK_FREQ_CAP(offs2));
printk(BIOS_SPEW, "freq_cap1=0x%x, freq_cap2=0x%x\n", freq_cap1, freq_cap2);
/* Calculate the highest possible frequency */
freq = log2(freq_cap1 & freq_cap2);
/* See if I am changing the link freqency */
old_freq = pci_read_config8(dev1, pos1 + LINK_FREQ(offs1));
old_freq &= 0x0f;
needs_reset |= old_freq != freq;
printk(BIOS_SPEW, "dev1 old_freq=0x%x, freq=0x%x, needs_reset=0x%0x\n", old_freq, freq, needs_reset);
old_freq = pci_read_config8(dev2, pos2 + LINK_FREQ(offs2));
old_freq &= 0x0f;
needs_reset |= old_freq != freq;
printk(BIOS_SPEW, "dev2 old_freq=0x%x, freq=0x%x, needs_reset=0x%0x\n", old_freq, freq, needs_reset);
/* Set the Calculated link frequency */
pci_write_config8(dev1, pos1 + LINK_FREQ(offs1), freq);
pci_write_config8(dev2, pos2 + LINK_FREQ(offs2), freq);
/* Get the width capabilities */
width_cap1 = ht_read_width_cap(dev1, pos1 + LINK_WIDTH(offs1));
width_cap2 = ht_read_width_cap(dev2, pos2 + LINK_WIDTH(offs2));
printk(BIOS_SPEW, "width_cap1=0x%x, width_cap2=0x%x\n", width_cap1, width_cap2);
/* Calculate dev1's input width */
ln_width1 = link_width_to_pow2[width_cap1 & 7];
ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7];
printk(BIOS_SPEW, "dev1 input ln_width1=0x%x, ln_width2=0x%x\n", ln_width1, ln_width2);
if (ln_width1 > ln_width2) {
ln_width1 = ln_width2;
}
width = pow2_to_link_width[ln_width1];
printk(BIOS_SPEW, "dev1 input width=0x%x\n", width);
/* Calculate dev1's output width */
ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7];
ln_width2 = link_width_to_pow2[width_cap2 & 7];
printk(BIOS_SPEW, "dev1 output ln_width1=0x%x, ln_width2=0x%x\n", ln_width1, ln_width2);
if (ln_width1 > ln_width2) {
ln_width1 = ln_width2;
}
width |= pow2_to_link_width[ln_width1] << 4;
printk(BIOS_SPEW, "dev1 input|output width=0x%x\n", width);
/* See if I am changing dev1's width */
old_width = pci_read_config8(dev1, pos1 + LINK_WIDTH(offs1) + 1);
old_width &= 0x77;
needs_reset |= old_width != width;
printk(BIOS_SPEW, "old dev1 input|output width=0x%x\n", width);
/* Set dev1's widths */
pci_write_config8(dev1, pos1 + LINK_WIDTH(offs1) + 1, width);
/* Calculate dev2's width */
width = ((width & 0x70) >> 4) | ((width & 0x7) << 4);
printk(BIOS_SPEW, "dev2 input|output width=0x%x\n", width);
/* See if I am changing dev2's width */
old_width = pci_read_config8(dev2, pos2 + LINK_WIDTH(offs2) + 1);
old_width &= 0x77;
needs_reset |= old_width != width;
printk(BIOS_SPEW, "old dev2 input|output width=0x%x\n", width);
/* Set dev2's widths */
pci_write_config8(dev2, pos2 + LINK_WIDTH(offs2) + 1, width);
return needs_reset;
}
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
static void ht_setup_chainx(pci_devfn_t udev, uint8_t upos, uint8_t bus,
unsigned offset_unitid, struct sys_info *sysinfo)
#else
static int ht_setup_chainx(pci_devfn_t udev, uint8_t upos, uint8_t bus,
unsigned offset_unitid)
#endif
{
//even CONFIG_HT_CHAIN_UNITID_BASE == 0, we still can go through this function, because of end_of_chain check, also We need it to optimize link
uint8_t next_unitid, last_unitid;
unsigned uoffs;
#if !IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
int reset_needed = 0;
#endif
#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
//let't record the device of last ht device, So we can set the Unitid to CONFIG_HT_CHAIN_END_UNITID_BASE
unsigned real_last_unitid = 0;
uint8_t real_last_pos = 0;
int ht_dev_num = 0;
uint8_t end_used = 0;
#endif
uoffs = PCI_HT_HOST_OFFS;
next_unitid = (offset_unitid) ? CONFIG_HT_CHAIN_UNITID_BASE:1;
do {
uint32_t id;
uint8_t pos;
uint16_t flags, ctrl;
uint8_t count;
unsigned offs;
/* Wait until the link initialization is complete */
do {
ctrl = pci_read_config16(udev, upos + LINK_CTRL(uoffs));
/* Is this the end of the hypertransport chain? */
if (ctrl & (1 << 6)) {
goto end_of_chain;
}
if (ctrl & ((1 << 4) | (1 << 8))) {
/*
* Either the link has failed, or we have
* a CRC error.
* Sometimes this can happen due to link
* retrain, so lets knock it down and see
* if its transient
*/
ctrl |= ((1 << 4) | (1 <<8)); // Link fail + Crc
pci_write_config16(udev, upos + LINK_CTRL(uoffs), ctrl);
ctrl = pci_read_config16(udev, upos + LINK_CTRL(uoffs));
if (ctrl & ((1 << 4) | (1 << 8))) {
printk(BIOS_ERR, "Detected error on Hypertransport Link\n");
break;
}
}
} while ((ctrl & (1 << 5)) == 0);
pci_devfn_t dev = PCI_DEV(bus, 0, 0);
last_unitid = next_unitid;
id = pci_read_config32(dev, PCI_VENDOR_ID);
/* If the chain is enumerated quit */
if ((id == 0xffffffff) || (id == 0x00000000) ||
(id == 0x0000ffff) || (id == 0xffff0000))
{
break;
}
pos = ht_lookup_slave_capability(dev);
if (!pos) {
printk(BIOS_ERR, "udev=%08x", udev);
printk(BIOS_ERR, "\tupos=%08x", upos);
printk(BIOS_ERR, "\tuoffs=%08x", uoffs);
printk(BIOS_ERR, "\tHT link capability not found\n");
break;
}
#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
if (offset_unitid) {
if (next_unitid >= (bus ? 0x20:0x18)) {
if (!end_used) {
next_unitid = CONFIG_HT_CHAIN_END_UNITID_BASE;
end_used = 1;
} else {
goto out;
}
}
real_last_pos = pos;
real_last_unitid = next_unitid;
ht_dev_num++;
}
#endif
/* Update the Unitid of the current device */
flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
flags &= ~0x1f; /* mask out the base Unit ID */
flags |= next_unitid & 0x1f;
pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags);
/* Compute the number of unitids consumed */
count = (flags >> 5) & 0x1f;
/* Note the change in device number */
dev = PCI_DEV(bus, next_unitid, 0);
next_unitid += count;
/* Find which side of the ht link we are on,
* by reading which direction our last write to PCI_CAP_FLAGS
* came from.
*/
flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
offs = ((flags>>10) & 1) ? PCI_HT_SLAVE1_OFFS : PCI_HT_SLAVE0_OFFS;
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
/* store the link pair here and we will Setup the Hypertransport link later, after we get final FID/VID */
{
struct link_pair_st *link_pair = &sysinfo->link_pair[sysinfo->link_pair_num];
link_pair->udev = udev;
link_pair->upos = upos;
link_pair->uoffs = uoffs;
link_pair->dev = dev;
link_pair->pos = pos;
link_pair->offs = offs;
sysinfo->link_pair_num++;
}
#else
reset_needed |= ht_optimize_link(udev, upos, uoffs, dev, pos, offs);
#endif
/* Remeber the location of the last device */
udev = dev;
upos = pos;
uoffs = (offs != PCI_HT_SLAVE0_OFFS) ? PCI_HT_SLAVE0_OFFS : PCI_HT_SLAVE1_OFFS;
} while (last_unitid != next_unitid);
#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
out:
#endif
end_of_chain:;
#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
if (offset_unitid && (ht_dev_num > 1) && (real_last_unitid != CONFIG_HT_CHAIN_END_UNITID_BASE) && !end_used) {
uint16_t flags;
flags = pci_read_config16(PCI_DEV(bus,real_last_unitid,0), real_last_pos + PCI_CAP_FLAGS);
flags &= ~0x1f;
flags |= CONFIG_HT_CHAIN_END_UNITID_BASE & 0x1f;
pci_write_config16(PCI_DEV(bus, real_last_unitid, 0), real_last_pos + PCI_CAP_FLAGS, flags);
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
// Here need to change the dev in the array
int i;
for (i = 0; i < sysinfo->link_pair_num; i++)
{
struct link_pair_st *link_pair = &sysinfo->link_pair[i];
if (link_pair->udev == PCI_DEV(bus, real_last_unitid, 0)) {
link_pair->udev = PCI_DEV(bus, CONFIG_HT_CHAIN_END_UNITID_BASE, 0);
continue;
}
if (link_pair->dev == PCI_DEV(bus, real_last_unitid, 0)) {
link_pair->dev = PCI_DEV(bus, CONFIG_HT_CHAIN_END_UNITID_BASE, 0);
}
}
#endif
}
#endif
#if !IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
return reset_needed;
#endif
}
static int optimize_link_read_pointer(uint8_t node, uint8_t linkn, uint8_t linkt, uint8_t val)
{
uint32_t dword, dword_old;
uint8_t link_type;
/* This works on an Athlon64 because unimplemented links return 0 */
dword = pci_read_config32(PCI_DEV(0,0x18+node,0), 0x98 + (linkn * 0x20));
link_type = dword & 0xff;
if ((link_type & 7) == linkt) { /* Coherent Link only linkt = 3, ncoherent = 7*/
dword_old = dword = pci_read_config32(PCI_DEV(0,0x18+node,3), 0xdc);
dword &= ~(0xff<<(linkn *8));
dword |= val << (linkn *8);
if (dword != dword_old) {
pci_write_config32(PCI_DEV(0,0x18+node,3), 0xdc, dword);
return 1;
}
}
return 0;
}
static int optimize_link_read_pointers_chain(uint8_t ht_c_num)
{
int reset_needed;
uint8_t i;
reset_needed = 0;
/* First one is SB HT chain. */
for (i = 0; i < ht_c_num; i++) {
uint32_t reg;
uint8_t nodeid, linkn;
uint8_t busn;
uint8_t val;
unsigned devn;
reg = pci_read_config32(PCI_DEV(0,0x18,1), 0xe0 + i * 4);
nodeid = ((reg & 0xf0)>>4); // nodeid
linkn = ((reg & 0xf00)>>8); // link n
busn = (reg & 0xff0000)>>16; //busn
devn = offset_unit_id(i == 0) ? CONFIG_HT_CHAIN_UNITID_BASE : 1;
reg = pci_read_config32(PCI_DEV(busn, devn, 0), PCI_VENDOR_ID); // ? the chain dev maybe offseted
if ((reg & 0xffff) == PCI_VENDOR_ID_AMD) {
val = 0x25;
} else if ((reg & 0xffff) == PCI_VENDOR_ID_NVIDIA) {
val = 0x25;//???
} else {
continue;
}
reset_needed |= optimize_link_read_pointer(nodeid, linkn, 0x07, val);
}
return reset_needed;
}
#if IS_ENABLED(CONFIG_SOUTHBRIDGE_NVIDIA_CK804)
static int set_ht_link_buffer_count(uint8_t node, uint8_t linkn, uint8_t linkt, unsigned val)
{
uint32_t dword;
uint8_t link_type;
unsigned regpos;
pci_devfn_t dev;
/* This works on an Athlon64 because unimplemented links return 0 */
regpos = 0x98 + (linkn * 0x20);
dev = PCI_DEV(0,0x18+node,0);
dword = pci_read_config32(dev, regpos);
link_type = dword & 0xff;
if ((link_type & 0x7) == linkt) { /* Coherent Link only linkt = 3, ncoherent = 7*/
regpos = 0x90 + (linkn * 0x20);
dword = pci_read_config32(dev, regpos);
if (dword != val) {
pci_write_config32(dev, regpos, val);
return 1;
}
}
return 0;
}
static int set_ht_link_buffer_counts_chain(uint8_t ht_c_num, unsigned vendorid, unsigned val)
{
int reset_needed;
uint8_t i;
reset_needed = 0;
for (i = 0; i < ht_c_num; i++) {
uint32_t reg;
uint8_t nodeid, linkn;
uint8_t busn;
unsigned devn;
reg = pci_read_config32(PCI_DEV(0,0x18,1), 0xe0 + i * 4);
if ((reg & 3) != 3) continue; // not enabled
nodeid = ((reg & 0xf0)>>4); // nodeid
linkn = ((reg & 0xf00)>>8); // link n
busn = (reg & 0xff0000)>>16; //busn
for (devn = 0; devn < 0x20; devn++) {
reg = pci_read_config32(PCI_DEV(busn, devn, 0), PCI_VENDOR_ID); //1?
if ((reg & 0xffff) == vendorid) {
reset_needed |= set_ht_link_buffer_count(nodeid, linkn, 0x07,val);
break;
}
}
}
return reset_needed;
}
#endif
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
static void ht_setup_chains(uint8_t ht_c_num, struct sys_info *sysinfo)
#else
static int ht_setup_chains(uint8_t ht_c_num)
#endif
{
/* Assumption the HT chain that is bus 0 has the HT I/O Hub on it.
* On most boards this just happens. If a CPU has multiple
* non Coherent links the appropriate bus registers for the
* links needs to be programed to point at bus 0.
*/
uint8_t upos;
pci_devfn_t udev;
uint8_t i;
#if !IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
int reset_needed = 0;
#else
sysinfo->link_pair_num = 0;
#endif
/* First one is SB HT chain. */
for (i = 0; i < ht_c_num; i++) {
uint32_t reg;
uint8_t devpos;
unsigned regpos;
uint32_t dword;
uint8_t busn;
reg = pci_read_config32(PCI_DEV(0,0x18,1), 0xe0 + i * 4);
//We need setup 0x94, 0xb4, and 0xd4 according to the reg
devpos = ((reg & 0xf0)>>4)+0x18; // nodeid;it will decide 0x18 or 0x19
regpos = ((reg & 0xf00)>>8) * 0x20 + 0x94; // link n;it will decide 0x94 or 0xb4, 0x0xd4;
busn = (reg & 0xff0000)>>16;
dword = pci_read_config32(PCI_DEV(0, devpos, 0), regpos);
dword &= ~(0xffff<<8);
dword |= (reg & 0xffff0000)>>8;
pci_write_config32(PCI_DEV(0, devpos,0), regpos , dword);
/* Make certain the HT bus is not enumerated */
ht_collapse_previous_enumeration(busn, offset_unit_id(i == 0));
upos = ((reg & 0xf00)>>8) * 0x20 + 0x80;
udev = PCI_DEV(0, devpos, 0);
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
ht_setup_chainx(udev,upos,busn, offset_unit_id(i == 0), sysinfo); // all not
#else
reset_needed |= ht_setup_chainx(udev,upos,busn, offset_unit_id(i == 0)); //all not
#endif
}
#if !IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
reset_needed |= optimize_link_read_pointers_chain(ht_c_num);
return reset_needed;
#endif
}
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
static void ht_setup_chains_x(struct sys_info *sysinfo)
#else
static int ht_setup_chains_x(void)
#endif
{
uint8_t nodeid;
uint32_t reg;
uint32_t tempreg;
uint8_t next_busn;
uint8_t ht_c_num;
uint8_t nodes;
#if IS_ENABLED(CONFIG_K8_ALLOCATE_IO_RANGE)
unsigned next_io_base;
#endif
nodes = get_nodes();
/* read PCI_DEV(0,0x18,0) 0x64 bit [8:9] to find out SbLink m */
reg = pci_read_config32(PCI_DEV(0, 0x18, 0), 0x64);
/* update PCI_DEV(0, 0x18, 1) 0xe0 to 0x05000m03, and next_busn = 0x3f+1 */
print_linkn_in("SBLink=", ((reg>>8) & 3));
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
sysinfo->sblk = (reg>>8) & 3;
sysinfo->sbbusn = 0;
sysinfo->nodes = nodes;
#endif
tempreg = 3 | (0<<4) | (((reg>>8) & 3)<<8) | (0<<16)| (0x3f<<24);
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xe0, tempreg);
next_busn = 0x3f+1; /* 0 will be used ht chain with SB we need to keep SB in bus0 in auto stage*/
#if IS_ENABLED(CONFIG_K8_ALLOCATE_IO_RANGE)
/* io range allocation */
tempreg = 0 | (((reg>>8) & 0x3) << 4)| (0x3<<12); //limit
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xC4, tempreg);
tempreg = 3 | (3<<4) | (0<<12); //base
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xC0, tempreg);
next_io_base = 0x3+0x1;
#endif
/* clean others */
for (ht_c_num = 1;ht_c_num < 4; ht_c_num++) {
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xe0 + ht_c_num * 4, 0);
#if IS_ENABLED(CONFIG_K8_ALLOCATE_IO_RANGE)
/* io range allocation */
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xc4 + ht_c_num * 8, 0);
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xc0 + ht_c_num * 8, 0);
#endif
}
for (nodeid = 0; nodeid < nodes; nodeid++) {
pci_devfn_t dev;
uint8_t linkn;
dev = PCI_DEV(0, 0x18+nodeid,0);
for (linkn = 0; linkn < 3; linkn++) {
unsigned regpos;
regpos = 0x98 + 0x20 * linkn;
reg = pci_read_config32(dev, regpos);
if ((reg & 0x17) != 7) continue; /* it is not non conherent or not connected*/
print_linkn_in("NC node|link=", ((nodeid & 0xf)<<4)|(linkn & 0xf));
tempreg = 3 | (nodeid <<4) | (linkn<<8);
/*compare (temp & 0xffff), with (PCI(0, 0x18, 1) 0xe0 to 0xec & 0xfffff) */
for (ht_c_num = 0;ht_c_num < 4; ht_c_num++) {
reg = pci_read_config32(PCI_DEV(0, 0x18, 1), 0xe0 + ht_c_num * 4);
if (((reg & 0xffff) == (tempreg & 0xffff)) || ((reg & 0xffff) == 0x0000)) { /*we got it*/
break;
}
}
if (ht_c_num == 4) break; /*used up only 4 non conherent allowed*/
/*update to 0xe0...*/
if ((reg & 0xf) == 3) continue; /*SbLink so don't touch it */
print_linkn_in("\tbusn=", next_busn);
tempreg |= (next_busn<<16)|((next_busn+0x3f)<<24);
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xe0 + ht_c_num * 4, tempreg);
next_busn+=0x3f+1;
#if IS_ENABLED(CONFIG_K8_ALLOCATE_IO_RANGE)
/* io range allocation */
tempreg = nodeid | (linkn<<4) | ((next_io_base+0x3)<<12); //limit
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xC4 + ht_c_num * 8, tempreg);
tempreg = 3 /*| (3<<4)*/ | (next_io_base<<12); //base :ISA and VGA ?
pci_write_config32(PCI_DEV(0, 0x18, 1), 0xC0 + ht_c_num * 8, tempreg);
next_io_base += 0x3+0x1;
#endif
}
}
/*update 0xe0, 0xe4, 0xe8, 0xec from PCI_DEV(0, 0x18,1) to PCI_DEV(0, 0x19,1) to PCI_DEV(0, 0x1f,1);*/
for (nodeid = 1; nodeid < nodes; nodeid++) {
int i;
pci_devfn_t dev;
dev = PCI_DEV(0, 0x18+nodeid,1);
for (i = 0; i < 4; i++) {
unsigned regpos;
regpos = 0xe0 + i * 4;
reg = pci_read_config32(PCI_DEV(0, 0x18, 1), regpos);
pci_write_config32(dev, regpos, reg);
}
#if IS_ENABLED(CONFIG_K8_ALLOCATE_IO_RANGE)
/* io range allocation */
for (i = 0; i < 4; i++) {
unsigned regpos;
regpos = 0xc4 + i * 8;
reg = pci_read_config32(PCI_DEV(0, 0x18, 1), regpos);
pci_write_config32(dev, regpos, reg);
}
for (i = 0; i < 4; i++) {
unsigned regpos;
regpos = 0xc0 + i * 8;
reg = pci_read_config32(PCI_DEV(0, 0x18, 1), regpos);
pci_write_config32(dev, regpos, reg);
}
#endif
}
/* recount ht_c_num*/
uint8_t i = 0;
for (ht_c_num = 0;ht_c_num < 4; ht_c_num++) {
reg = pci_read_config32(PCI_DEV(0, 0x18, 1), 0xe0 + ht_c_num * 4);
if (((reg & 0xf) != 0x0)) {
i++;
}
}
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
sysinfo->ht_c_num = i;
ht_setup_chains(i, sysinfo);
sysinfo->sbdn = get_sbdn(sysinfo->sbbusn);
#else
return ht_setup_chains(i);
#endif
}
#if IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
static int optimize_link_incoherent_ht(struct sys_info *sysinfo)
{
// We need to use recorded link pair info to optimize the link
int i;
int reset_needed = 0;
unsigned link_pair_num = sysinfo->link_pair_num;
printk(BIOS_SPEW, "entering optimize_link_incoherent_ht\n");
printk(BIOS_SPEW, "sysinfo->link_pair_num=0x%x\n", link_pair_num);
for (i = 0; i < link_pair_num; i++) {
struct link_pair_st *link_pair= &sysinfo->link_pair[i];
reset_needed |= ht_optimize_link(link_pair->udev, link_pair->upos, link_pair->uoffs, link_pair->dev, link_pair->pos, link_pair->offs);
printk(BIOS_SPEW, "after ht_optimize_link for link pair %d, reset_needed=0x%x\n", i, reset_needed);
}
reset_needed |= optimize_link_read_pointers_chain(sysinfo->ht_c_num);
printk(BIOS_SPEW, "after optimize_link_read_pointers_chain, reset_needed=0x%x\n", reset_needed);
return reset_needed;
}
#endif

View File

@ -1,246 +0,0 @@
/*
* This file is part of the coreboot project.
*
* written in 2003 by Eric Biederman
*
* - Athlon64 workarounds by Stefan Reinauer
* - "reset once" logic by Yinghai Lu
*
* 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 <reset.h>
#include <pc80/mc146818rtc.h>
#include <lib.h>
#include <cpu/amd/model_fxx_rev.h>
#include "amdk8.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 resource 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 iommu;
/* Read the generic PCI resources */
pci_dev_read_resources(dev);
/* If we are not the first processor don't allocate the GART aperture */
if (dev->path.pci.devfn != PCI_DEVFN(0x18, 3)) {
return;
}
iommu = CONFIG_IOMMU;
get_option(&iommu, "iommu");
if (iommu) {
/* Add a GART aperture 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)
{
struct resource *resource;
resource = probe_resource(dev, 0x94);
if (resource) {
struct device *pdev;
uint32_t 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 northbridges */
pdev = 0;
while ((pdev = dev_find_device(PCI_VENDOR_ID_AMD, 0x1103, 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>");
}
}
}
static void mcf3_set_resources(struct device *dev)
{
/* Set the gart apeture */
set_agp_aperture(dev);
/* Set the generic PCI resources */
pci_dev_set_resources(dev);
}
static void misc_control_init(struct device *dev)
{
uint32_t cmd, cmd_ref;
int needs_reset;
struct device *f0_dev;
printk(BIOS_DEBUG, "NB: Function 3 Misc Control.. ");
needs_reset = 0;
/* Disable Machine checks from Invalid Locations.
* This is needed for PC backwards compatibility.
*/
cmd = pci_read_config32(dev, 0x44);
cmd |= (1<<6) | (1<<25);
pci_write_config32(dev, 0x44, cmd);
#if !IS_ENABLED(CONFIG_K8_REV_F_SUPPORT)
if (is_cpu_pre_c0()) {
/* Errata 58
* Disable CPU low power states C2, C1 and throttling
*/
cmd = pci_read_config32(dev, 0x80);
cmd &= ~(1<<0);
pci_write_config32(dev, 0x80, cmd);
cmd = pci_read_config32(dev, 0x84);
cmd &= ~(1<<24);
cmd &= ~(1<<8);
pci_write_config32(dev, 0x84, cmd);
/* Errata 66
* Limit the number of downstream posted requests to 1
*/
cmd = pci_read_config32(dev, 0x70);
if ((cmd & (3 << 0)) != 2) {
cmd &= ~(3<<0);
cmd |= (2<<0);
pci_write_config32(dev, 0x70, cmd);
needs_reset = 1;
}
cmd = pci_read_config32(dev, 0x7c);
if ((cmd & (3 << 4)) != 0) {
cmd &= ~(3<<4);
cmd |= (0<<4);
pci_write_config32(dev, 0x7c, cmd);
needs_reset = 1;
}
/* Clock Power/Timing Low */
cmd = pci_read_config32(dev, 0xd4);
if (cmd != 0x000D0001) {
cmd = 0x000D0001;
pci_write_config32(dev, 0xd4, cmd);
needs_reset = 1; /* Needed? */
}
}
else if (is_cpu_pre_d0()) {
struct device *f2_dev;
uint32_t dcl;
f2_dev = dev_find_slot(0, dev->path.pci.devfn - 3 + 2);
/* Errata 98
* Set Clk Ramp Hystersis to 7
* Clock Power/Timing Low
*/
cmd_ref = 0x04e20707; /* Registered */
dcl = pci_read_config32(f2_dev, DRAM_CONFIG_LOW);
if (dcl & DCL_UnBuffDimm) {
cmd_ref = 0x000D0701; /* Unbuffered */
}
cmd = pci_read_config32(dev, 0xd4);
if (cmd != cmd_ref) {
pci_write_config32(dev, 0xd4, cmd_ref);
needs_reset = 1; /* Needed? */
}
}
#endif
/* Optimize the Link read pointers */
f0_dev = dev_find_slot(0, dev->path.pci.devfn - 3);
if (f0_dev) {
int link;
cmd_ref = cmd = pci_read_config32(dev, 0xdc);
for (link = 0; link < 3; link++) {
uint32_t link_type;
unsigned reg;
/* This works on an Athlon64 because unimplemented links return 0 */
reg = 0x98 + (link * 0x20);
link_type = pci_read_config32(f0_dev, reg);
/* Only handle coherent link here please */
if ((link_type & (LinkConnected|InitComplete|NonCoherent))
== (LinkConnected|InitComplete))
{
cmd &= ~(0xff << (link *8));
/* FIXME this assumes the device on the other side is an AMD device */
cmd |= 0x25 << (link *8);
}
}
if (cmd != cmd_ref) {
pci_write_config32(dev, 0xdc, cmd);
needs_reset = 1;
}
}
else {
printk(BIOS_ERR, "Missing f0 device!\n");
}
if (needs_reset) {
printk(BIOS_DEBUG, "resetting cpu\n");
hard_reset();
}
printk(BIOS_DEBUG, "done.\n");
}
static struct device_operations mcf3_ops = {
.read_resources = mcf3_read_resources,
.set_resources = mcf3_set_resources,
.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,
.vendor = PCI_VENDOR_ID_AMD,
.device = 0x1103,
};

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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.
*/
#ifndef NORTHBRIDGE_AMD_AMDK8_H
#define NORTHBRIDGE_AMD_AMDK8_H
extern unsigned int amdk8_scan_root_bus(struct device *root, unsigned int max);
#endif /* NORTHBRIDGE_AMD_AMDK8_H */

View File

@ -1,285 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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.
*/
#ifndef AMDK8_PRE_F_H
#define AMDK8_PRE_F_H
#include <compiler.h>
/* Definitions of various K8 registers */
/* Function 0 */
#define HT_TRANSACTION_CONTROL 0x68
#define HTTC_DIS_RD_B_P (1 << 0)
#define HTTC_DIS_RD_DW_P (1 << 1)
#define HTTC_DIS_WR_B_P (1 << 2)
#define HTTC_DIS_WR_DW_P (1 << 3)
#define HTTC_DIS_MTS (1 << 4)
#define HTTC_CPU1_EN (1 << 5)
#define HTTC_CPU_REQ_PASS_PW (1 << 6)
#define HTTC_CPU_RD_RSP_PASS_PW (1 << 7)
#define HTTC_DIS_P_MEM_C (1 << 8)
#define HTTC_DIS_RMT_MEM_C (1 << 9)
#define HTTC_DIS_FILL_P (1 << 10)
#define HTTC_RSP_PASS_PW (1 << 11)
#define HTTC_CHG_ISOC_TO_ORD (1 << 12)
#define HTTC_BUF_REL_PRI_SHIFT 13
#define HTTC_BUF_REL_PRI_MASK 3
#define HTTC_BUF_REL_PRI_64 0
#define HTTC_BUF_REL_PRI_16 1
#define HTTC_BUF_REL_PRI_8 2
#define HTTC_BUF_REL_PRI_2 3
#define HTTC_LIMIT_CLDT_CFG (1 << 15)
#define HTTC_LINT_EN (1 << 16)
#define HTTC_APIC_EXT_BRD_CST (1 << 17)
#define HTTC_APIC_EXT_ID (1 << 18)
#define HTTC_APIC_EXT_SPUR (1 << 19)
#define HTTC_SEQ_ID_SRC_NODE_EN (1 << 20)
#define HTTC_DS_NP_REQ_LIMIT_SHIFT 21
#define HTTC_DS_NP_REQ_LIMIT_MASK 3
#define HTTC_DS_NP_REQ_LIMIT_NONE 0
#define HTTC_DS_NP_REQ_LIMIT_1 1
#define HTTC_DS_NP_REQ_LIMIT_4 2
#define HTTC_DS_NP_REQ_LIMIT_8 3
#define HTTC_MED_PRI_BYP_CNT_SHIFT 24
#define HTTC_MED_PRI_BYP_CNT_MASK 3
#define HTTC_HI_PRI_BYP_CNT_SHIFT 26
#define HTTC_HI_PRI_BYP_CNT_MASK 3
/* Function 1 */
#define PCI_IO_BASE0 0xc0
#define PCI_IO_BASE1 0xc8
#define PCI_IO_BASE2 0xd0
#define PCI_IO_BASE3 0xd8
#define PCI_IO_BASE_VGA_EN (1 << 4)
#define PCI_IO_BASE_NO_ISA (1 << 5)
/* Function 2 */
#define DRAM_CSBASE 0x40
#define DRAM_CSMASK 0x60
#define DRAM_BANK_ADDR_MAP 0x80
#define DRAM_TIMING_LOW 0x88
#define DTL_TCL_SHIFT 0
#define DTL_TCL_MASK 0x7
#define DTL_CL_2 1
#define DTL_CL_3 2
#define DTL_CL_2_5 5
#define DTL_TRC_SHIFT 4
#define DTL_TRC_MASK 0xf
#define DTL_TRC_BASE 7
#define DTL_TRC_MIN 7
#define DTL_TRC_MAX 22
#define DTL_TRFC_SHIFT 8
#define DTL_TRFC_MASK 0xf
#define DTL_TRFC_BASE 9
#define DTL_TRFC_MIN 9
#define DTL_TRFC_MAX 24
#define DTL_TRCD_SHIFT 12
#define DTL_TRCD_MASK 0x7
#define DTL_TRCD_BASE 0
#define DTL_TRCD_MIN 2
#define DTL_TRCD_MAX 6
#define DTL_TRRD_SHIFT 16
#define DTL_TRRD_MASK 0x7
#define DTL_TRRD_BASE 0
#define DTL_TRRD_MIN 2
#define DTL_TRRD_MAX 4
#define DTL_TRAS_SHIFT 20
#define DTL_TRAS_MASK 0xf
#define DTL_TRAS_BASE 0
#define DTL_TRAS_MIN 5
#define DTL_TRAS_MAX 15
#define DTL_TRP_SHIFT 24
#define DTL_TRP_MASK 0x7
#define DTL_TRP_BASE 0
#define DTL_TRP_MIN 2
#define DTL_TRP_MAX 6
#define DTL_TWR_SHIFT 28
#define DTL_TWR_MASK 0x1
#define DTL_TWR_BASE 2
#define DTL_TWR_MIN 2
#define DTL_TWR_MAX 3
#define DRAM_TIMING_HIGH 0x8c
#define DTH_TWTR_SHIFT 0
#define DTH_TWTR_MASK 0x1
#define DTH_TWTR_BASE 1
#define DTH_TWTR_MIN 1
#define DTH_TWTR_MAX 2
#define DTH_TRWT_SHIFT 4
#define DTH_TRWT_MASK 0x7
#define DTH_TRWT_BASE 1
#define DTH_TRWT_MIN 1
#define DTH_TRWT_MAX 6
#define DTH_TREF_SHIFT 8
#define DTH_TREF_MASK 0x1f
#define DTH_TREF_100MHZ_4K 0x00
#define DTH_TREF_133MHZ_4K 0x01
#define DTH_TREF_166MHZ_4K 0x02
#define DTH_TREF_200MHZ_4K 0x03
#define DTH_TREF_100MHZ_8K 0x08
#define DTH_TREF_133MHZ_8K 0x09
#define DTH_TREF_166MHZ_8K 0x0A
#define DTH_TREF_200MHZ_8K 0x0B
#define DTH_TWCL_SHIFT 20
#define DTH_TWCL_MASK 0x7
#define DTH_TWCL_BASE 1
#define DTH_TWCL_MIN 1
#define DTH_TWCL_MAX 2
#define DRAM_CONFIG_LOW 0x90
#define DCL_DLL_Disable (1<<0)
#define DCL_D_DRV (1<<1)
#define DCL_QFC_EN (1<<2)
#define DCL_DisDqsHys (1<<3)
#define DCL_Burst2Opt (1<<5)
#define DCL_DramInit (1<<8)
#define DCL_DualDIMMen (1<<9)
#define DCL_DramEnable (1<<10)
#define DCL_MemClrStatus (1<<11)
#define DCL_ESR (1<<12)
#define DCL_SRS (1<<13)
#define DCL_128BitEn (1<<16)
#define DCL_DimmEccEn (1<<17)
#define DCL_UnBuffDimm (1<<18)
#define DCL_32ByteEn (1<<19)
#define DCL_x4DIMM_SHIFT 20
#define DCL_DisInRcvrs (1<<24)
#define DCL_BypMax_SHIFT 25
#define DCL_En2T (1<<28)
#define DCL_UpperCSMap (1<<29)
#define DRAM_CONFIG_HIGH 0x94
#define DCH_ASYNC_LAT_SHIFT 0
#define DCH_ASYNC_LAT_MASK 0xf
#define DCH_ASYNC_LAT_BASE 0
#define DCH_ASYNC_LAT_MIN 0
#define DCH_ASYNC_LAT_MAX 15
#define DCH_RDPREAMBLE_SHIFT 8
#define DCH_RDPREAMBLE_MASK 0xf
#define DCH_RDPREAMBLE_BASE ((2<<1)+0) /* 2.0 ns */
#define DCH_RDPREAMBLE_MIN ((2<<1)+0) /* 2.0 ns */
#define DCH_RDPREAMBLE_MAX ((9<<1)+1) /* 9.5 ns */
#define DCH_IDLE_LIMIT_SHIFT 16
#define DCH_IDLE_LIMIT_MASK 0x7
#define DCH_IDLE_LIMIT_0 0
#define DCH_IDLE_LIMIT_4 1
#define DCH_IDLE_LIMIT_8 2
#define DCH_IDLE_LIMIT_16 3
#define DCH_IDLE_LIMIT_32 4
#define DCH_IDLE_LIMIT_64 5
#define DCH_IDLE_LIMIT_128 6
#define DCH_IDLE_LIMIT_256 7
#define DCH_DYN_IDLE_CTR_EN (1 << 19)
#define DCH_MEMCLK_SHIFT 20
#define DCH_MEMCLK_MASK 0x7
#define DCH_MEMCLK_100MHZ 0
#define DCH_MEMCLK_133MHZ 2
#define DCH_MEMCLK_166MHZ 5
#define DCH_MEMCLK_200MHZ 7
#define DCH_MEMCLK_VALID (1 << 25)
#define DCH_MEMCLK_EN0 (1 << 26)
#define DCH_MEMCLK_EN1 (1 << 27)
#define DCH_MEMCLK_EN2 (1 << 28)
#define DCH_MEMCLK_EN3 (1 << 29)
/* Function 3 */
#define MCA_NB_CONFIG 0x44
#define MNC_ECC_EN (1 << 22)
#define MNC_CHIPKILL_EN (1 << 23)
#define SCRUB_CONTROL 0x58
#define SCRUB_NONE 0
#define SCRUB_40ns 1
#define SCRUB_80ns 2
#define SCRUB_160ns 3
#define SCRUB_320ns 4
#define SCRUB_640ns 5
#define SCRUB_1_28us 6
#define SCRUB_2_56us 7
#define SCRUB_5_12us 8
#define SCRUB_10_2us 9
#define SCRUB_20_5us 10
#define SCRUB_41_0us 11
#define SCRUB_81_9us 12
#define SCRUB_163_8us 13
#define SCRUB_327_7us 14
#define SCRUB_655_4us 15
#define SCRUB_1_31ms 16
#define SCRUB_2_62ms 17
#define SCRUB_5_24ms 18
#define SCRUB_10_49ms 19
#define SCRUB_20_97ms 20
#define SCRUB_42ms 21
#define SCRUB_84ms 22
#define SC_DRAM_SCRUB_RATE_SHFIT 0
#define SC_DRAM_SCRUB_RATE_MASK 0x1f
#define SC_L2_SCRUB_RATE_SHIFT 8
#define SC_L2_SCRUB_RATE_MASK 0x1f
#define SC_L1D_SCRUB_RATE_SHIFT 16
#define SC_L1D_SCRUB_RATE_MASK 0x1f
#define SCRUB_ADDR_LOW 0x5C
#define SCRUB_ADDR_HIGH 0x60
#define NORTHBRIDGE_CAP 0xE8
#define NBCAP_128Bit (1 << 0)
#define NBCAP_MP (1 << 1)
#define NBCAP_BIG_MP (1 << 2)
#define NBCAP_ECC (1 << 3)
#define NBCAP_CHIPKILL_ECC (1 << 4)
#define NBCAP_MEMCLK_SHIFT 5
#define NBCAP_MEMCLK_MASK 3
#define NBCAP_MEMCLK_100MHZ 3
#define NBCAP_MEMCLK_133MHZ 2
#define NBCAP_MEMCLK_166MHZ 1
#define NBCAP_MEMCLK_200MHZ 0
#define NBCAP_MEMCTRL (1 << 8)
#define LinkConnected (1 << 0)
#define InitComplete (1 << 1)
#define NonCoherent (1 << 2)
#define ConnectionPending (1 << 4)
#include "raminit.h"
//struct definitions
struct link_pair_st {
pci_devfn_t udev;
uint32_t upos;
uint32_t uoffs;
pci_devfn_t dev;
uint32_t pos;
uint32_t offs;
} __packed;
struct sys_info {
uint8_t ctrl_present[NODE_NUMS];
struct mem_controller ctrl[NODE_NUMS];
uint32_t nodes;
struct link_pair_st link_pair[16];// enough? only in_conherent
uint32_t link_pair_num;
uint32_t ht_c_num;
uint32_t sbdn;
uint32_t sblk;
uint32_t sbbusn;
} __packed;
#ifdef __PRE_RAM__
#include <arch/early_variables.h>
extern struct sys_info sysinfo_car;
#endif
#endif /* AMDK8_PRE_F_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,60 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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.
*/
#ifndef RAMINIT_H
#define RAMINIT_H
#include <arch/io.h>
#define NODE_ID 0x60
#define HT_INIT_CONTROL 0x6c
#define NODE_NUMS 8
#define DIMM_SOCKETS 4
struct mem_controller {
unsigned node_id;
pci_devfn_t f0, f1, f2, f3;
uint16_t channel0[DIMM_SOCKETS];
uint16_t channel1[DIMM_SOCKETS];
};
struct sys_info;
void exit_from_self(int controllers, const struct mem_controller *ctrl, struct sys_info *sysinfo);
void setup_resource_map(const unsigned int *register_values, int max);
void set_hw_mem_hole(int controllers, const struct mem_controller *ctrl);
int spd_read_byte(unsigned device, unsigned address);
void activate_spd_rom(const struct mem_controller *ctrl);
void memreset(int controllers, const struct mem_controller *ctrl);
void set_sysinfo_in_ram(unsigned int val);
#define TIMEOUT_LOOPS 300000
#if defined(__PRE_RAM__) && IS_ENABLED(CONFIG_RAMINIT_SYSINFO)
void sdram_initialize(int controllers, const struct mem_controller *ctrl, void *sysinfo);
void sdram_enable(int controllers, const struct mem_controller *ctrl,
struct sys_info *sysinfo);
void sdram_set_registers(const struct mem_controller *ctrl, struct sys_info *sysinfo);
void sdram_set_spd_registers(const struct mem_controller *ctrl,
struct sys_info *sysinfo);
void dump_spd_registers(const struct mem_controller *ctrl);
void dump_smbus_registers(void);
#else
void sdram_set_registers(const struct mem_controller *ctrl);
void sdram_set_spd_registers(const struct mem_controller *ctrl);
void sdram_enable(int controllers, const struct mem_controller *ctrl);
void sdram_initialize(int controllers, const struct mem_controller *ctrl);
#endif
#endif /* RAMINIT_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,409 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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 <unistd.h>
#include <limits.h>
#include <lib.h>
#include <stdint.h>
#include <string.h>
#include <setjmp.h>
#include <device/pci_def.h>
#include <stdlib.h>
#include "amdk8.h"
jmp_buf end_buf;
static int is_cpu_pre_c0(void)
{
return 0;
}
#define PCI_ADDR(BUS, DEV, FN, WHERE) ( \
(((BUS) & 0xFF) << 16) | \
(((DEV) & 0x1f) << 11) | \
(((FN) & 0x07) << 8) | \
((WHERE) & 0xFF))
#define PCI_DEV(BUS, DEV, FN) ( \
(((BUS) & 0xFF) << 16) | \
(((DEV) & 0x1f) << 11) | \
(((FN) & 0x7) << 8))
#define PCI_ID(VENDOR_ID, DEVICE_ID) \
((((DEVICE_ID) & 0xFFFF) << 16) | ((VENDOR_ID) & 0xFFFF))
typedef unsigned device_t;
unsigned char pci_register[256*5*3*256];
static uint8_t pci_read_config8(device_t dev, unsigned where)
{
unsigned addr;
addr = dev | where;
return pci_register[addr];
}
static uint16_t pci_read_config16(device_t dev, unsigned where)
{
unsigned addr;
addr = dev | where;
return pci_register[addr] | (pci_register[addr + 1] << 8);
}
static uint32_t pci_read_config32(device_t dev, unsigned where)
{
unsigned addr;
uint32_t value;
addr = dev | where;
value = pci_register[addr] |
(pci_register[addr + 1] << 8) |
(pci_register[addr + 2] << 16) |
(pci_register[addr + 3] << 24);
return value;
}
static void pci_write_config8(device_t dev, unsigned where, uint8_t value)
{
unsigned addr;
addr = dev | where;
pci_register[addr] = value;
}
static void pci_write_config16(device_t dev, unsigned where, uint16_t value)
{
unsigned addr;
addr = dev | where;
pci_register[addr] = value & 0xff;
pci_register[addr + 1] = (value >> 8) & 0xff;
}
static void pci_write_config32(device_t dev, unsigned where, uint32_t value)
{
unsigned addr;
addr = dev | where;
pci_register[addr] = value & 0xff;
pci_register[addr + 1] = (value >> 8) & 0xff;
pci_register[addr + 2] = (value >> 16) & 0xff;
pci_register[addr + 3] = (value >> 24) & 0xff;
}
#define PCI_DEV_INVALID (0xffffffffU)
static device_t pci_locate_device(unsigned pci_id, device_t dev)
{
for (; dev <= PCI_DEV(255, 31, 7); dev += PCI_DEV(0,0,1)) {
unsigned int id;
id = pci_read_config32(dev, 0);
if (id == pci_id) {
return dev;
}
}
return PCI_DEV_INVALID;
}
static void uart_tx_byte(unsigned char data)
{
write(STDOUT_FILENO, &data, 1);
}
static void hlt(void)
{
longjmp(end_buf, 2);
}
#include "console/console.c"
unsigned long log2(unsigned long x)
{
// assume 8 bits per byte.
unsigned long i = 1 << (sizeof(x)*8 - 1);
unsigned long pow = sizeof(x) * 8 - 1;
if (! x) {
static const char errmsg[] = " called with invalid parameter of 0\n";
write(STDERR_FILENO, __func__, sizeof(__func__) - 1);
write(STDERR_FILENO, errmsg, sizeof(errmsg) - 1);
hlt();
}
for (; i > x; i >>= 1, pow--)
;
return pow;
}
typedef struct msr_struct
{
unsigned lo;
unsigned hi;
} msr_t;
static inline msr_t rdmsr(unsigned index)
{
msr_t result;
result.lo = 0;
result.hi = 0;
return result;
}
static inline void wrmsr(unsigned index, msr_t msr)
{
}
#include "raminit.h"
#define SIO_BASE 0x2e
static void hard_reset(void)
{
/* FIXME implement the hard reset case... */
longjmp(end_buf, 3);
}
static void memreset_setup(void)
{
/* Nothing to do */
}
static void memreset(int controllers, const struct mem_controller *ctrl)
{
/* Nothing to do */
}
void activate_spd_rom(const struct mem_controller *ctrl)
{
/* nothing to do */
}
static uint8_t spd_mt4lsdt464a[256] =
{
0x80, 0x08, 0x04, 0x0C, 0x08, 0x01, 0x40, 0x00, 0x01, 0x70,
0x54, 0x00, 0x80, 0x10, 0x00, 0x01, 0x8F, 0x04, 0x06, 0x01,
0x01, 0x00, 0x0E, 0x75, 0x54, 0x00, 0x00, 0x0F, 0x0E, 0x0F,
0x25, 0x08, 0x15, 0x08, 0x15, 0x08, 0x00, 0x12, 0x01, 0x4E,
0x9C, 0xE4, 0xB7, 0x46, 0x2C, 0xFF, 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x00,
};
static uint8_t spd_micron_512MB_DDR333[256] =
{
0x80, 0x08, 0x07, 0x0d, 0x0b, 0x02, 0x48, 0x00, 0x04, 0x60,
0x70, 0x02, 0x82, 0x04, 0x04, 0x01, 0x0e, 0x04, 0x0c, 0x01,
0x02, 0x26, 0xc0, 0x75, 0x70, 0x00, 0x00, 0x48, 0x30, 0x48,
0x2a, 0x80, 0x80, 0x80, 0x45, 0x45, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x48, 0x30, 0x28, 0x50, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x6f, 0x2c, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x01, 0x33, 0x36, 0x56, 0x44, 0x44, 0x46, 0x31,
0x32, 0x38, 0x37, 0x32, 0x47, 0x2d, 0x33, 0x33, 0x35, 0x43,
0x33, 0x03, 0x00, 0x03, 0x23, 0x17, 0x07, 0x5a, 0xb2, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
static uint8_t spd_micron_256MB_DDR333[256] =
{
0x80, 0x08, 0x07, 0x0d, 0x0b, 0x01, 0x48, 0x00, 0x04, 0x60,
0x70, 0x02, 0x82, 0x04, 0x04, 0x01, 0x0e, 0x04, 0x0c, 0x01,
0x02, 0x26, 0xc0, 0x75, 0x70, 0x00, 0x00, 0x48, 0x30, 0x48,
0x2a, 0x80, 0x80, 0x80, 0x45, 0x45, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x48, 0x30, 0x23, 0x50, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x58, 0x2c, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x01, 0x31, 0x38, 0x56, 0x44, 0x44, 0x46, 0x36,
0x34, 0x37, 0x32, 0x47, 0x2d, 0x33, 0x33, 0x35, 0x43, 0x31,
0x20, 0x01, 0x00, 0x03, 0x19, 0x17, 0x05, 0xb2, 0xf4, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
#define MAX_DIMMS 16
static uint8_t spd_data[MAX_DIMMS*256];
static unsigned spd_count, spd_fail_count;
static int spd_read_byte(unsigned device, unsigned address)
{
int result;
spd_count++;
if ((device < DIMM0) || (device >= (DIMM0 + MAX_DIMMS))) {
result = -1;
}
else {
device -= DIMM0; /* 0x50 */
if (address > 256) {
result = -1;
}
else if (spd_data[(device << 8) | 2] != 7) {
result = -1;
}
else {
result = spd_data[(device << 8) | address];
}
}
if (spd_count >= spd_fail_count) {
result = -1;
}
return result;
}
/* no specific code here. this should go away completely */
static void coherent_ht_mainboard(unsigned cpus)
{
}
#include "raminit.c"
#include "../../../lib/generic_sdram.c"
#define FIRST_CPU 1
#define SECOND_CPU 1
#define TOTAL_CPUS (FIRST_CPU + SECOND_CPU)
static void raminit_main(void)
{
/*
* GPIO28 of 8111 will control H0_MEMRESET_L
* GPIO29 of 8111 will control H1_MEMRESET_L
*/
static const struct mem_controller cpu[] = {
#if FIRST_CPU
{
.node_id = 0,
.f0 = PCI_DEV(0, 0x18, 0),
.f1 = PCI_DEV(0, 0x18, 1),
.f2 = PCI_DEV(0, 0x18, 2),
.f3 = PCI_DEV(0, 0x18, 3),
.channel0 = { DIMM0+0, DIMM0+2, DIMM0+4, DIMM0+6 },
.channel1 = { DIMM0+1, DIMM0+3, DIMM0+5, DIMM0+7 },
},
#endif
#if SECOND_CPU
{
.node_id = 1,
.f0 = PCI_DEV(0, 0x19, 0),
.f1 = PCI_DEV(0, 0x19, 1),
.f2 = PCI_DEV(0, 0x19, 2),
.f3 = PCI_DEV(0, 0x19, 3),
.channel0 = { DIMM0+8, DIMM0+10, DIMM0+12, DIMM0+14 },
.channel1 = { DIMM0+9, DIMM0+11, DIMM0+13, DIMM0+15 },
},
#endif
};
console_init();
memreset_setup();
sdram_initialize(ARRAY_SIZE(cpu), cpu);
}
static void reset_tests(void)
{
/* Clear the results of any previous tests */
memset(pci_register, 0, sizeof(pci_register));
memset(spd_data, 0, sizeof(spd_data));
spd_count = 0;
spd_fail_count = UINT_MAX;
pci_write_config32(PCI_DEV(0, 0x18, 3), NORTHBRIDGE_CAP,
NBCAP_128Bit |
NBCAP_MP| NBCAP_BIG_MP |
/* NBCAP_ECC | NBCAP_CHIPKILL_ECC | */
(NBCAP_MEMCLK_200MHZ << NBCAP_MEMCLK_SHIFT) |
NBCAP_MEMCTRL);
pci_write_config32(PCI_DEV(0, 0x19, 3), NORTHBRIDGE_CAP,
NBCAP_128Bit |
NBCAP_MP| NBCAP_BIG_MP |
/* NBCAP_ECC | NBCAP_CHIPKILL_ECC | */
(NBCAP_MEMCLK_200MHZ << NBCAP_MEMCLK_SHIFT) |
NBCAP_MEMCTRL);
}
static void test1(void)
{
reset_tests();
memcpy(&spd_data[0*256], spd_micron_512MB_DDR333, 256);
memcpy(&spd_data[1*256], spd_micron_512MB_DDR333, 256);
raminit_main();
}
static void do_test2(int i)
{
jmp_buf tmp_buf;
memcpy(&tmp_buf, &end_buf, sizeof(end_buf));
if (setjmp(end_buf) != 0) {
goto done;
}
reset_tests();
spd_fail_count = i;
printk(BIOS_DEBUG, "\nSPD will fail after: %d accesses.\n", %d);
memcpy(&spd_data[0*256], spd_micron_512MB_DDR333, 256);
memcpy(&spd_data[1*256], spd_micron_512MB_DDR333, 256);
raminit_main();
done:
memcpy(&end_buf, &tmp_buf, sizeof(end_buf));
}
static void test2(void)
{
int i;
for (i = 0; i < 0x48; i++) {
do_test2(i);
}
}
int main(int argc, char **argv)
{
if (setjmp(end_buf) != 0) {
return -1;
}
test1();
test2();
return 0;
}

View File

@ -1,271 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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.
*/
static void setup_default_resource_map(void)
{
static const unsigned int register_values[] = {
/* Careful set limit registers before base registers which contain the enables */
/* DRAM Limit i Registers
* F1:0x44 i = 0
* F1:0x4C i = 1
* F1:0x54 i = 2
* F1:0x5C i = 3
* F1:0x64 i = 4
* F1:0x6C i = 5
* F1:0x74 i = 6
* F1:0x7C i = 7
* [ 2: 0] Destination Node ID
* 000 = Node 0
* 001 = Node 1
* 010 = Node 2
* 011 = Node 3
* 100 = Node 4
* 101 = Node 5
* 110 = Node 6
* 111 = Node 7
* [ 7: 3] Reserved
* [10: 8] Interleave select
* specifies the values of A[14:12] to use with interleave enable.
* [15:11] Reserved
* [31:16] DRAM Limit Address i Bits 39-24
* This field defines the upper address bits of a 40 bit address
* that define the end of the DRAM region.
*/
PCI_ADDR(0, 0x18, 1, 0x44), 0x0000f8f8, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x4C), 0x0000f8f8, 0x00000001,
PCI_ADDR(0, 0x18, 1, 0x54), 0x0000f8f8, 0x00000002,
PCI_ADDR(0, 0x18, 1, 0x5C), 0x0000f8f8, 0x00000003,
PCI_ADDR(0, 0x18, 1, 0x64), 0x0000f8f8, 0x00000004,
PCI_ADDR(0, 0x18, 1, 0x6C), 0x0000f8f8, 0x00000005,
PCI_ADDR(0, 0x18, 1, 0x74), 0x0000f8f8, 0x00000006,
PCI_ADDR(0, 0x18, 1, 0x7C), 0x0000f8f8, 0x00000007,
/* DRAM Base i Registers
* F1:0x40 i = 0
* F1:0x48 i = 1
* F1:0x50 i = 2
* F1:0x58 i = 3
* F1:0x60 i = 4
* F1:0x68 i = 5
* F1:0x70 i = 6
* F1:0x78 i = 7
* [ 0: 0] Read Enable
* 0 = Reads Disabled
* 1 = Reads Enabled
* [ 1: 1] Write Enable
* 0 = Writes Disabled
* 1 = Writes Enabled
* [ 7: 2] Reserved
* [10: 8] Interleave Enable
* 000 = No interleave
* 001 = Interleave on A[12] (2 nodes)
* 010 = reserved
* 011 = Interleave on A[12] and A[14] (4 nodes)
* 100 = reserved
* 101 = reserved
* 110 = reserved
* 111 = Interleve on A[12] and A[13] and A[14] (8 nodes)
* [15:11] Reserved
* [13:16] DRAM Base Address i Bits 39-24
* This field defines the upper address bits of a 40-bit address
* that define the start of the DRAM region.
*/
PCI_ADDR(0, 0x18, 1, 0x40), 0x0000f8fc, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x48), 0x0000f8fc, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x50), 0x0000f8fc, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x58), 0x0000f8fc, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x60), 0x0000f8fc, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x68), 0x0000f8fc, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x70), 0x0000f8fc, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x78), 0x0000f8fc, 0x00000000,
/* Memory-Mapped I/O Limit i Registers
* F1:0x84 i = 0
* F1:0x8C i = 1
* F1:0x94 i = 2
* F1:0x9C i = 3
* F1:0xA4 i = 4
* F1:0xAC i = 5
* F1:0xB4 i = 6
* F1:0xBC i = 7
* [ 2: 0] Destination Node ID
* 000 = Node 0
* 001 = Node 1
* 010 = Node 2
* 011 = Node 3
* 100 = Node 4
* 101 = Node 5
* 110 = Node 6
* 111 = Node 7
* [ 3: 3] Reserved
* [ 5: 4] Destination Link ID
* 00 = Link 0
* 01 = Link 1
* 10 = Link 2
* 11 = Reserved
* [ 6: 6] Reserved
* [ 7: 7] Non-Posted
* 0 = CPU writes may be posted
* 1 = CPU writes must be non-posted
* [31: 8] Memory-Mapped I/O Limit Address i (39-16)
* This field defines the upp adddress bits of a 40-bit address that
* defines the end of a memory-mapped I/O region n
*/
PCI_ADDR(0, 0x18, 1, 0x84), 0x00000048, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x8C), 0x00000048, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x94), 0x00000048, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x9C), 0x00000048, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xA4), 0x00000048, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xAC), 0x00000048, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xB4), 0x00000048, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xBC), 0x00000048, 0x00ffff00,
/* Memory-Mapped I/O Base i Registers
* F1:0x80 i = 0
* F1:0x88 i = 1
* F1:0x90 i = 2
* F1:0x98 i = 3
* F1:0xA0 i = 4
* F1:0xA8 i = 5
* F1:0xB0 i = 6
* F1:0xB8 i = 7
* [ 0: 0] Read Enable
* 0 = Reads disabled
* 1 = Reads Enabled
* [ 1: 1] Write Enable
* 0 = Writes disabled
* 1 = Writes Enabled
* [ 2: 2] Cpu Disable
* 0 = Cpu can use this I/O range
* 1 = Cpu requests do not use this I/O range
* [ 3: 3] Lock
* 0 = base/limit registers i are read/write
* 1 = base/limit registers i are read-only
* [ 7: 4] Reserved
* [31: 8] Memory-Mapped I/O Base Address i (39-16)
* This field defines the upper address bits of a 40bit address
* that defines the start of memory-mapped I/O region i
*/
PCI_ADDR(0, 0x18, 1, 0x80), 0x000000f0, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x88), 0x000000f0, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x90), 0x000000f0, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0x98), 0x000000f0, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xA0), 0x000000f0, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xA8), 0x000000f0, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xB0), 0x000000f0, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xB8), 0x000000f0, 0x00fc0003,
/* PCI I/O Limit i Registers
* F1:0xC4 i = 0
* F1:0xCC i = 1
* F1:0xD4 i = 2
* F1:0xDC i = 3
* [ 2: 0] Destination Node ID
* 000 = Node 0
* 001 = Node 1
* 010 = Node 2
* 011 = Node 3
* 100 = Node 4
* 101 = Node 5
* 110 = Node 6
* 111 = Node 7
* [ 3: 3] Reserved
* [ 5: 4] Destination Link ID
* 00 = Link 0
* 01 = Link 1
* 10 = Link 2
* 11 = reserved
* [11: 6] Reserved
* [24:12] PCI I/O Limit Address i
* This field defines the end of PCI I/O region n
* [31:25] Reserved
*/
PCI_ADDR(0, 0x18, 1, 0xC4), 0xFE000FC8, 0x01fff000,
PCI_ADDR(0, 0x18, 1, 0xCC), 0xFE000FC8, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xD4), 0xFE000FC8, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xDC), 0xFE000FC8, 0x00000000,
/* PCI I/O Base i Registers
* F1:0xC0 i = 0
* F1:0xC8 i = 1
* F1:0xD0 i = 2
* F1:0xD8 i = 3
* [ 0: 0] Read Enable
* 0 = Reads Disabled
* 1 = Reads Enabled
* [ 1: 1] Write Enable
* 0 = Writes Disabled
* 1 = Writes Enabled
* [ 3: 2] Reserved
* [ 4: 4] VGA Enable
* 0 = VGA matches Disabled
* 1 = matches all address < 64K and where A[9:0] is in the
* range 3B0-3BB or 3C0-3DF independen of the base & limit registers
* [ 5: 5] ISA Enable
* 0 = ISA matches Disabled
* 1 = Blocks address < 64K and in the last 768 bytes of eack 1K block
* from matching agains this base/limit pair
* [11: 6] Reserved
* [24:12] PCI I/O Base i
* This field defines the start of PCI I/O region n
* [31:25] Reserved
*/
PCI_ADDR(0, 0x18, 1, 0xC0), 0xFE000FCC, 0x00000003,
PCI_ADDR(0, 0x18, 1, 0xC8), 0xFE000FCC, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xD0), 0xFE000FCC, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xD8), 0xFE000FCC, 0x00000000,
/* Config Base and Limit i Registers
* F1:0xE0 i = 0
* F1:0xE4 i = 1
* F1:0xE8 i = 2
* F1:0xEC i = 3
* [ 0: 0] Read Enable
* 0 = Reads Disabled
* 1 = Reads Enabled
* [ 1: 1] Write Enable
* 0 = Writes Disabled
* 1 = Writes Enabled
* [ 2: 2] Device Number Compare Enable
* 0 = The ranges are based on bus number
* 1 = The ranges are ranges of devices on bus 0
* [ 3: 3] Reserved
* [ 6: 4] Destination Node
* 000 = Node 0
* 001 = Node 1
* 010 = Node 2
* 011 = Node 3
* 100 = Node 4
* 101 = Node 5
* 110 = Node 6
* 111 = Node 7
* [ 7: 7] Reserved
* [ 9: 8] Destination Link
* 00 = Link 0
* 01 = Link 1
* 10 = Link 2
* 11 - Reserved
* [15:10] Reserved
* [23:16] Bus Number Base i
* This field defines the lowest bus number in configuration region i
* [31:24] Bus Number Limit i
* This field defines the highest bus number in configuration region i
*/
PCI_ADDR(0, 0x18, 1, 0xE0), 0x0000FC88, 0xff000003,
PCI_ADDR(0, 0x18, 1, 0xE4), 0x0000FC88, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xE8), 0x0000FC88, 0x00000000,
PCI_ADDR(0, 0x18, 1, 0xEC), 0x0000FC88, 0x00000000,
};
int max;
max = ARRAY_SIZE(register_values);
setup_resource_map(register_values, max);
}

View File

@ -1,117 +0,0 @@
/*
* This file is part of the coreboot project.
*
* 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 "amdk8.h"
#define RES_DEBUG 0
void setup_resource_map_offset(const unsigned int *register_values, int max, unsigned offset_pci_dev, unsigned offset_io_base)
{
int i;
#if RES_DEBUG
printk(BIOS_DEBUG, "setting up resource map offset....\n");
#endif
for (i = 0; i < max; i += 3) {
pci_devfn_t dev;
unsigned where;
unsigned long reg = 0;
#if RES_DEBUG
prink_debug("%08x <- %08x\n", register_values[i] + offset_pci_dev, register_values[i+2]);
#endif
dev = (register_values[i] & ~0xfff) + offset_pci_dev;
where = register_values[i] & 0xfff;
if (register_values[i+1])
reg = pci_read_config32(dev, where);
reg &= register_values[i+1];
reg |= register_values[i+2] + offset_io_base;
pci_write_config32(dev, where, reg);
}
#if RES_DEBUG
printk(BIOS_DEBUG, "done.\n");
#endif
}
#define RES_PCI_IO 0x10
#define RES_PORT_IO_8 0x22
#define RES_PORT_IO_32 0x20
#define RES_MEM_IO 0x40
static void setup_resource_map_x_offset(const unsigned int *register_values, int max, unsigned offset_pci_dev, unsigned offset_io_base)
{
int i;
#if RES_DEBUG
printk(BIOS_DEBUG, "setting up resource map ex offset....\n");
#endif
for (i = 0; i < max; i += 4) {
#if RES_DEBUG
printk(BIOS_DEBUG, "%04x: %02x %08x <- & %08x | %08x\n",
i>>2, register_values[i],
register_values[i+1] + ((register_values[i]==RES_PCI_IO) ? offset_pci_dev : 0),
register_values[i+2],
register_values[i+3] + (((register_values[i] & RES_PORT_IO_32) == RES_PORT_IO_32) ? offset_io_base : 0)
);
#endif
switch (register_values[i]) {
case RES_PCI_IO: //PCI
{
pci_devfn_t dev;
unsigned where;
unsigned long reg = 0;
dev = (register_values[i+1] & ~0xfff) + offset_pci_dev;
where = register_values[i+1] & 0xfff;
if (register_values[i+2])
reg = pci_read_config32(dev, where);
reg &= register_values[i+2];
reg |= register_values[i+3];
pci_write_config32(dev, where, reg);
}
break;
case RES_PORT_IO_8: // io 8
{
unsigned where;
unsigned reg = 0;
where = register_values[i+1] + offset_io_base;
if (register_values[i+2])
reg = inb(where);
reg &= register_values[i+2];
reg |= register_values[i+3];
outb(reg, where);
}
break;
case RES_PORT_IO_32: //io32
{
unsigned where;
unsigned long reg = 0;
where = register_values[i+1] + offset_io_base;
if (register_values[i+2])
reg = inl(where);
reg &= register_values[i+2];
reg |= register_values[i+3];
outl(reg, where);
}
break;
} // switch
}
#if RES_DEBUG
printk(BIOS_DEBUG, "done.\n");
#endif
}
static inline void setup_resource_map_x(const unsigned int *register_values, int max)
{
setup_resource_map_x_offset(register_values, max, 0, 0);
}

View File

@ -1,285 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2011 Christoph Grenz <christophg+cb@grenz-bonn.de>
*
* 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 this file into a mainboards DSDT inside the PCI device
* "K8 Miscellaneous Control" and it will expose the temperature
* sensors of the processor as thermal zones.
*
* If, for example, the K8 Misc. Control device is on 0:18.3, include the
* following inside the PCI0 device:
*
* Device(K8MC) {
* Name (_ADR, 0x00180003)
* #include northbridge/amd/amdk8/thermal_mixin.asl
* }
*
* Note: as only the current temperature and the trip temperature for
* "Software Thermal Control" are available in the PCI registers, but the
* linux driver for thermal zones needs a critical temperature value, a
* reasonable critical temperature is calculated by simply adding 6°C to
* the trip temperature.
*
* The used registers are documented in the "BIOS and Kernel Developer's
* Guide for AMD NPT Family 0Fh Processors"
* http://support.amd.com/us/Processor_TechDocs/32559.pdf
*
*/
#ifndef K8TEMP_CRITICAL_ADD
# define K8TEMP_CRITICAL_ADD 6
#endif
OperationRegion(K8TR, PCI_Config, 0xE4, 0x4)
Field(K8TR, DWordAcc, NoLock, Preserve) {
, 1,
THTP, 1, /* Temperature sensor trip occurred */
CORE, 1, /* Select Core */
TTS0, 1, /* Temperature sensor trip on CPU1 (or single core CPU0) */
TTS1, 1, /* Temperature sensor trip on CPU0 */
TTEN, 1, /* Temperature sensor trip enabled */
PLAC, 1, /* Select Sensor */
, 1,
DOFF, 6, /* Diode offset (signed 6bit-Integer) in °C */
TFRC, 2, /* Temperature fractions */
TVAL, 8, /* Temperature value in °C biased by -49 */
TJOF, 5,
, 2,
SWTT, 1, /* Induce a thermtrip event (for diagnostic purposes) */
}
OperationRegion(K8ST, PCI_Config, 0x70, 0x1)
Field(K8ST, ByteAcc, NoLock, Preserve) {
TMAX, 5, /* Maximum temperature for software thermal control, in °C, biased by 52 */
}
/* Calculates temperature in tenths Kelvin from given TVAL and TFRC values */
Method(K8PT, 2) {
Divide(Multiply(Arg1, 5), 2, , Local0)
Return (Add(Multiply(Add(Arg0, 224),10), Local0))
}
/* Calculates the diode offset from a DOFF value */
Method(K8PO, 1) {
If (And(Arg0, 0x20))
{
Return (Multiply(Subtract(Xor(Arg0, 0x3F), 1), 10))
}
Else {
Return (Multiply(Arg0, 10))
}
}
ThermalZone (K8T0) {
Name(_HID, EisaId("PNP0C11"))
Name(_UID, "k8-0")
Name(_STR, Unicode("K8 compatible CPU Core 1 Thermal Sensor 1"))
Method(_STA) {
Store(CORE, Local0)
Store(PLAC, Local1)
Store(Zero, CORE)
Store(Zero, PLAC)
If (LOr(PLAC, CORE)) {
Store(Local0, CORE)
Store(Local1, PLAC)
Return (0x00)
}
If (LOr(LNot(TVAL), LEqual(TVAL, 0xFF))) {
Return (0x00)
}
Store(Local0, CORE)
Store(Local1, PLAC)
Return (0x0F)
}
Method(_TMP) {
Store(CORE, Local0)
Store(PLAC, Local1)
Store(Zero, CORE)
Store(Zero, PLAC)
Store (K8PT(TVAL, TFRC), Local2)
Add (K8PO(DOFF), Local2, Local2)
Store(Local0, CORE)
Store(Local1, PLAC)
Return (Local2)
}
Method(_CRT) {
Add(TMAX, 325, Local0)
Add(Local0, K8TEMP_CRITICAL_ADD, Local0)
Return (Multiply(Local0, 10))
}
}
ThermalZone (K8T1) {
Name(_HID, EisaId("PNP0C11"))
Name(_UID, "k8-1")
Name(_STR, Unicode("K8 compatible CPU Core 1 Thermal Sensor 2"))
Name(_TZD, Package () {\_PR.CP00})
Method(_STA) {
Store(CORE, Local0)
Store(PLAC, Local1)
Store(Zero, CORE)
Store(Zero, PLAC)
If (LOr(PLAC, CORE)) {
Store(Local0, CORE)
Store(Local1, PLAC)
Return (0x00)
}
Store(One, PLAC)
If (LOr(LNot(TVAL), LEqual(TVAL, 0xFF))) {
Return (0x00)
}
Store(Local0, CORE)
Store(Local1, PLAC)
Return (0x0F)
}
Method(_TMP) {
Store(CORE, Local0)
Store(PLAC, Local1)
Store(Zero, CORE)
Store(One, PLAC)
Store (K8PT(TVAL, TFRC), Local2)
Add (K8PO(DOFF), Local2, Local2)
Store(Local0, CORE)
Store(Local1, PLAC)
Return (Local2)
}
Method(_CRT) {
Add(TMAX, 325, Local0)
Add(Local0, K8TEMP_CRITICAL_ADD, Local0)
Return (Multiply(Local0, 10))
}
}
ThermalZone (K8T2) {
Name(_HID, EisaId("PNP0C11"))
Name(_UID, "k8-2")
Name(_STR, Unicode("K8 compatible CPU Core 2 Thermal Sensor 1"))
Name(_TZD, Package () {\_PR.CP00})
Method(_STA) {
Store(CORE, Local0)
Store(PLAC, Local1)
Store(Zero, CORE)
Store(Zero, PLAC)
If (LOr(PLAC, CORE)) {
Store(Local0, CORE)
Store(Local1, PLAC)
Return (0x00)
}
Store(One, CORE)
If (LOr(LNot(TVAL), LEqual(TVAL, 0xFF))) {
Return (0x00)
}
Store(Local0, CORE)
Store(Local1, PLAC)
Return (0x0F)
}
Method(_TMP) {
Store(CORE, Local0)
Store(PLAC, Local1)
Store(One, CORE)
Store(Zero, PLAC)
Store (K8PT(TVAL, TFRC), Local2)
Add (K8PO(DOFF), Local2, Local2)
Store(Local0, CORE)
Store(Local1, PLAC)
Return (Local2)
}
Method(_CRT) {
Add(TMAX, 325, Local0)
Add(Local0, K8TEMP_CRITICAL_ADD, Local0)
Return (Multiply(Local0, 10))
}
}
ThermalZone (K8T3) {
Name(_HID, EisaId("PNP0C11"))
Name(_UID, "k8-3")
Name(_STR, Unicode("K8 compatible CPU Core 2 Thermal Sensor 2"))
Name(_TZD, Package () {\_PR.CP00})
Method(_STA) {
Store(CORE, Local0)
Store(PLAC, Local1)
Store(Zero, CORE)
Store(Zero, PLAC)
If (LOr(PLAC, CORE)) {
Store(Local0, CORE)
Store(Local1, PLAC)
Return (0x00)
}
Store(One, CORE)
Store(One, PLAC)
If (LOr(LNot(TVAL), LEqual(TVAL, 0xFF))) {
Return (0x00)
}
Store(Local0, CORE)
Store(Local1, PLAC)
Return (0x0F)
}
Method(_TMP) {
Store(CORE, Local0)
Store(PLAC, Local1)
Store(One, CORE)
Store(One, PLAC)
Store (K8PT(TVAL, TFRC), Local2)
Add (K8PO(DOFF), Local2, Local2)
Store(Local0, CORE)
Store(Local1, PLAC)
Return (Local2)
}
Method(_CRT) {
Add(TMAX, 325, Local0)
Add(Local0, K8TEMP_CRITICAL_ADD, Local0)
Return (Multiply(Local0, 10))
}
}

View File

@ -1,329 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2005 AMD
*
* 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.
*/
//AMD k8 util for BUSB and res range
Scope (\_SB)
{
Name (OSTB, Ones)
Method (OSVR, 0, NotSerialized)
{
If (LEqual (^OSTB, Ones))
{
Store (0x00, ^OSTB)
}
Return (^OSTB)
}
Method (SEQL, 2, Serialized)
{
Store (SizeOf (Arg0), Local0)
Store (SizeOf (Arg1), Local1)
If (LNot (LEqual (Local0, Local1))) { Return (Zero) }
Name (BUF0, Buffer (Local0) {})
Store (Arg0, BUF0)
Name (BUF1, Buffer (Local0) {})
Store (Arg1, BUF1)
Store (Zero, Local2)
While (LLess (Local2, Local0))
{
Store (DerefOf (Index (BUF0, Local2)), Local3)
Store (DerefOf (Index (BUF1, Local2)), Local4)
If (LNot (LEqual (Local3, Local4))) { Return (Zero) }
Increment (Local2)
}
Return (One)
}
Method (DADD, 2, NotSerialized)
{
Store(Arg1, Local0)
Store(Arg0, Local1)
Add(ShiftLeft(Local1,16), Local0, Local0)
Return (Local0)
}
Method (GHCE, 1, NotSerialized) // check if the HC enabled
{
Store (DerefOf (Index (\_SB.PCI0.HCLK, Arg0)), Local1)
if (LEqual (And(Local1, 0x01), 0x01)) { Return (0x0F) }
Else { Return (0x00) }
}
Method (GHCN, 1, NotSerialized) // get the node num for the HC
{
Store (0x00, Local0)
Store (DerefOf (Index (\_SB.PCI0.HCLK, Arg0)), Local1)
Store (ShiftRight(And (Local1, 0xf0), 0x04), Local0)
Return (Local0)
}
Method (GHCL, 1, NotSerialized) // get the link num on node for the HC
{
Store (0x00, Local0)
Store (DerefOf (Index (\_SB.PCI0.HCLK, Arg0)), Local1)
Store (ShiftRight(And (Local1, 0xf00), 0x08), Local0)
Return (Local0)
}
Method (GHCD, 2, NotSerialized) // get the unit id base for the HT device in HC
{
Store (0x00, Local0)
Store (DerefOf (Index (\_SB.PCI0.HCDN, Arg0)), Local1)
Store (Arg1, Local2) // Arg1 could be 3, 2, 1, 0
Multiply (Local2, 0x08, Local2) // change to 24, 16, 8, 0
Store (And (ShiftRight(Local1, Local2), 0xff), Local0)
Return (Local0)
}
/* GetBus(Node, Link) */
Method (GBUS, 2, NotSerialized)
{
Store (0x00, Local0)
While (LLess (Local0, 0x04))
{
Store (DerefOf (Index (\_SB.PCI0.BUSN, Local0)), Local1)
If (LEqual (And (Local1, 0x03), 0x03))
{
If (LEqual (Arg0, ShiftRight (And (Local1, 0x70), 0x04)))
{
If (LOr (LEqual (Arg1, 0xFF), LEqual (Arg1, ShiftRight (And (Local1, 0x0300), 0x08))))
{
Return (ShiftRight (And (Local1, 0x00FF0000), 0x10))
}
}
}
Increment (Local0)
}
Return (0x00)
}
/* GetBusResources(Node, Link) */
Method (GWBN, 2, Serialized)
{
Name (BUF0, ResourceTemplate ()
{
WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
0x0000, // Address Space Granularity
0x0000, // Address Range Minimum
0x0000, // Address Range Maximum
0x0000, // Address Translation Offset
0x0001,,,)
})
CreateWordField (BUF0, 0x08, BMIN)
CreateWordField (BUF0, 0x0A, BMAX)
CreateWordField (BUF0, 0x0E, BLEN)
Store (0x00, Local0)
While (LLess (Local0, 0x04))
{
Store (DerefOf (Index (\_SB.PCI0.BUSN, Local0)), Local1)
If (LEqual (And (Local1, 0x03), 0x03))
{
If (LEqual (Arg0, ShiftRight (And (Local1, 0x70), 0x04)))
{
If (LOr (LEqual (Arg1, 0xFF), LEqual (Arg1, ShiftRight (And (Local1, 0x0300), 0x08))))
{
Store (ShiftRight (And (Local1, 0x00FF0000), 0x10), BMIN)
Store (ShiftRight (Local1, 0x18), BMAX)
Subtract (BMAX, BMIN, BLEN)
Increment (BLEN)
Return (RTAG (BUF0))
}
}
}
Increment (Local0)
}
Return (RTAG (BUF0))
}
/* GetMemoryResources(Node, Link) */
Method (GMEM, 2, Serialized)
{
Name (BUF0, ResourceTemplate ()
{
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
0x00000000, // Address Space Granularity
0x00000000, // Address Range Minimum
0x00000000, // Address Range Maximum
0x00000000, // Address Translation Offset
0x00000001,,,
, AddressRangeMemory, TypeStatic)
})
CreateDWordField (BUF0, 0x0A, MMIN)
CreateDWordField (BUF0, 0x0E, MMAX)
CreateDWordField (BUF0, 0x16, MLEN)
Store (0x00, Local0)
Store (0x00, Local4)
Store (0x00, Local3)
While (LLess (Local0, 0x10))
{
/* Get value of the first register */
Store (DerefOf (Index (\_SB.PCI0.MMIO, Local0)), Local1)
Increment (Local0)
Store (DerefOf (Index (\_SB.PCI0.MMIO, Local0)), Local2)
If (LEqual (And (Local1, 0x03), 0x03)) /* Pair enabled? */
{
If (LEqual (Arg0, And (Local2, 0x07))) /* Node matches? */
{
/* If Link Matches (or we got passed 0xFF) */
If (LOr (LEqual (Arg1, 0xFF), LEqual (Arg1, ShiftRight (And (Local2, 0x30), 0x04))))
{
/* Extract the Base and Limit values */
Store (ShiftLeft (And (Local1, 0xFFFFFF00), 0x08), MMIN)
Store (ShiftLeft (And (Local2, 0xFFFFFF00), 0x08), MMAX)
Or (MMAX, 0xFFFF, MMAX)
Subtract (MMAX, MMIN, MLEN)
Increment (MLEN)
If (Local4) /* I've already done this once */
{
Concatenate (RTAG (BUF0), Local3, Local5)
Store (Local5, Local3)
}
Else
{
Store (RTAG (BUF0), Local3)
}
Increment (Local4)
}
}
}
Increment (Local0)
}
If (LNot (Local4)) /* No resources for this node and link. */
{
Store (RTAG (BUF0), Local3)
}
Return (Local3)
}
/* GetIOResources(Node, Link) */
Method (GIOR, 2, Serialized)
{
Name (BUF0, ResourceTemplate ()
{
DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x00000000, // Address Space Granularity
0x00000000, // Address Range Minimum
0x00000000, // Address Range Maximum
0x00000000, // Address Translation Offset
0x00000001,,,
, TypeStatic)
})
CreateDWordField (BUF0, 0x0A, PMIN)
CreateDWordField (BUF0, 0x0E, PMAX)
CreateDWordField (BUF0, 0x16, PLEN)
Store (0x00, Local0)
Store (0x00, Local4)
Store (0x00, Local3)
While (LLess (Local0, 0x08))
{
Store (DerefOf (Index (\_SB.PCI0.PCIO, Local0)), Local1)
Increment (Local0)
Store (DerefOf (Index (\_SB.PCI0.PCIO, Local0)), Local2)
If (LEqual (And (Local1, 0x03), 0x03)) /* Pair enabled? */
{
If (LEqual (Arg0, And (Local2, 0x07))) /* Node matches? */
{
/* If Link Matches (or we got passed 0xFF) */
If (LOr (LEqual (Arg1, 0xFF), LEqual (Arg1, ShiftRight (And (Local2, 0x30), 0x04))))
{
/* Extract the Base and Limit values */
Store (And (Local1, 0x01FFF000), PMIN)
Store (And (Local2, 0x01FFF000), PMAX)
Or (PMAX, 0x0FFF, PMAX)
Subtract (PMAX, PMIN, PLEN)
Increment (PLEN)
If (Local4) /* I've already done this once */
{
Concatenate (RTAG (BUF0), Local3, Local5)
Store (Local5, Local3)
}
Else
{
If (LGreater (PMAX, PMIN))
{
If (LOr (LAnd (LEqual (Arg1, 0xFF), LEqual (Arg0, 0x00)), LEqual (Arg1, \_SB.PCI0.SBLK)))
{
Store (0x0D00, PMIN)
Subtract (PMAX, PMIN, PLEN)
Increment (PLEN)
}
Store (RTAG (BUF0), Local3)
Increment (Local4)
}
If (And (Local1, 0x10))
{
Store (0x03B0, PMIN)
Store (0x03DF, PMAX)
Store (0x30, PLEN)
If (Local4)
{
Concatenate (RTAG (BUF0), Local3, Local5)
Store (Local5, Local3)
}
Else
{
Store (RTAG (BUF0), Local3)
}
}
}
Increment (Local4)
}
}
}
Increment (Local0)
}
If (LNot (Local4)) /* No resources for this node and link. */
{
Store (RTAG (BUF0), Local3)
}
Return (Local3)
}
Method (RTAG, 1, NotSerialized)
{
Store (Arg0, Local0)
Store (SizeOf (Local0), Local1)
Subtract (Local1, 0x02, Local1)
Multiply (Local1, 0x08, Local1)
CreateField (Local0, 0x00, Local1, RETB)
Store (RETB, Local2)
Return (Local2)
}
}

View File

@ -1,269 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008 Vincent Legoll <vincent.legoll@gmail.com>
* Copyright (C) 2008 Ronald G. Minnich <rminnich@gmail.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.
*/
/*
* K8 northbridge utilities (dump routing registers).
* Designed to be called at any time.
* It can be called before RAM is set up by including this file.
* It can be called after RAM is set up by including amdk8.h and enabling the
* compilation of this file in src/northbridge/amd/amdk8/Makefile.inc.
*/
#ifndef __PRE_RAM__
#include <console/console.h>
#include <device/pci.h>
#include <device/pci_ops.h>
#endif
#include "amdk8.h"
/* Function 1 */
/* the DRAM, MMIO,and PCIIO routing are 64-bit registers, hence the ending at
* 0x78, 0xb8, and 0xd8
*/
#define DRAM_ROUTE_START 0x40
#define DRAM_ROUTE_END 0x78
#define MMIO_ROUTE_START 0x80
#define MMIO_ROUTE_END 0xb8
#define PCIIO_ROUTE_START 0xc0
#define PCIIO_ROUTE_END 0xd8
#define CONFIG_ROUTE_START 0xe0
#define CONFIG_ROUTE_END 0xec
#define PCI_IO_BASE0 0xc0
#define PCI_IO_BASE1 0xc8
#define PCI_IO_BASE2 0xd0
#define PCI_IO_BASE3 0xd8
#define PCI_IO_BASE_VGA_EN (1 << 4)
#define PCI_IO_BASE_NO_ISA (1 << 5)
#define BITS(r, shift, mask) (((r>>shift)&mask))
/**
* Return "R" if the register has read-enable bit set.
*/
static const char *re(u32 i)
{
return ((i & 1) ? "R" : "");
}
/**
* Return "W" if the register has write-enable bit set.
*/
static const char *we(u32 i)
{
return ((i & 1) ? "W" : "");
}
/**
* Return a string containing the interleave settings.
*/
static const char *ileave(u32 base)
{
switch ((base >> 8) & 7) {
case 0:
return "No interleave";
case 1:
return "2 nodes";
case 3:
return "4 nodes";
case 7:
return "8 nodes";
default:
return "Reserved";
}
}
/**
* Return the node number.
* For one case (config registers) these are not the right bit fields.
*/
static int r_node(u32 reg)
{
return BITS(reg, 0, 0x7);
}
/**
* Return the link number.
* For one case (config registers) these are not the right bit fields.
*/
static int r_link(u32 reg)
{
return BITS(reg, 4, 0x3);
}
/**
* Print the DRAM routing info for one base/limit pair.
*
* Show base, limit, dest node, dest link on that node, read and write
* enable, and interleave information.
*
* @param level Printing level
* @param which Register number
* @param base Base register
* @param lim Limit register
*/
static void showdram(int level, u8 which, u32 base, u32 lim)
{
printk(level, "DRAM(%02x)%010llx-%010llx, ->(%d), %s, %s, %s, %d\n",
which, (((u64) base & 0xffff0000) << 8),
(((u64) lim & 0xffff0000) << 8) + 0xffffff,
r_node(lim), re(base), we(base), ileave(base), (lim >> 8) & 3);
}
/**
* Print the config routing info for a config register.
*
* Show base, limit, dest node, dest link on that node, read and write
* enable, and device number compare enable
*
* @param level Printing level
* @param which Register number
* @param reg Config register
*/
static void showconfig(int level, u8 which, u32 reg)
{
/* Don't use r_node() and r_link() here. */
printk(level, "CONFIG(%02x)%02x-%02x ->(%d,%d),%s %s (%s numbers)\n",
which, BITS(reg, 16, 0xff), BITS(reg, 24, 0xff),
BITS(reg, 4, 0x7), BITS(reg, 8, 0x3),
re(reg), we(reg),
BITS(reg, 2, 0x1)?"dev":"bus");
}
/**
* Print the PCIIO routing info for one base/limit pair.
*
* Show base, limit, dest node, dest link on that node, read and write
* enable, and VGA and ISA Enable.
*
* @param level Printing level
* @param which Register number
* @param base Base register
* @param lim Limit register
*/
static void showpciio(int level, u8 which, u32 base, u32 lim)
{
printk(level, "PCIIO(%02x)%07x-%07x, ->(%d,%d), %s, %s,VGA %d ISA %d\n",
which, BITS(base, 12, 0x3fff) << 12,
(BITS(lim, 12, 0x3fff) << 12) + 0xfff, r_node(lim), r_link(lim),
re(base), we(base), BITS(base, 4, 0x1), BITS(base, 5, 0x1));
}
/**
* Print the MMIO routing info for one base/limit pair.
*
* Show base, limit, dest node, dest link on that node, read and write
* enable, and CPU Disable, Lock, and Non-posted.
*
* @param level Printing level
* @param which Register number
* @param base Base register
* @param lim Limit register
*/
static void showmmio(int level, u8 which, u32 base, u32 lim)
{
printk(level, "MMIO(%02x)%010llx-%010llx, ->(%d,%d), %s, %s, "
"CPU disable %d, Lock %d, Non posted %d\n",
which, ((u64) BITS(base, 0, 0xffffff00)) << 8,
(((u64) BITS(lim, 0, 0xffffff00)) << 8) + 0xffff, r_node(lim),
r_link(lim), re(base), we(base), BITS(base, 4, 0x1),
BITS(base, 7, 0x1), BITS(lim, 7, 0x1));
}
/**
* Show all DRAM routing registers. This function is callable at any time.
*
* @param level The debug level.
* @param dev A 32-bit number in the standard bus/dev/fn format which is used
* raw config space.
*/
static void showalldram(int level, struct device *dev)
{
u8 reg;
for (reg = DRAM_ROUTE_START; reg <= DRAM_ROUTE_END; reg += 8) {
u32 base = pci_read_config32(dev, reg);
u32 lim = pci_read_config32(dev, reg + 4);
if (base || lim!=(reg-DRAM_ROUTE_START)/8)
showdram(level, reg, base, lim);
}
}
/**
* Show all MMIO routing registers. This function is callable at any time.
*
* @param level The debug level.
* @param dev A 32-bit number in the standard bus/dev/fn format which is used
* raw config space.
*/
static void showallmmio(int level, struct device *dev)
{
u8 reg;
for (reg = MMIO_ROUTE_START; reg <= MMIO_ROUTE_END; reg += 8) {
u32 base = pci_read_config32(dev, reg);
u32 lim = pci_read_config32(dev, reg + 4);
if (base || lim)
showmmio(level, reg, base, lim);
}
}
/**
* Show all PCIIO routing registers. This function is callable at any time.
*
* @param level The debug level.
* @param dev A 32-bit number in the standard bus/dev/fn format which is used
* raw config space.
*/
static void showallpciio(int level, struct device *dev)
{
u8 reg;
for (reg = PCIIO_ROUTE_START; reg <= PCIIO_ROUTE_END; reg += 8) {
u32 base = pci_read_config32(dev, reg);
u32 lim = pci_read_config32(dev, reg + 4);
if (base || lim)
showpciio(level, reg, base, lim);
}
}
/**
* Show all config routing registers. This function is callable at any time.
*
* @param level The debug level.
* @param dev A 32-bit number in the standard bus/dev/fn format which is used
* raw config space.
*/
static void showallconfig(int level, struct device *dev)
{
u8 reg;
for (reg = CONFIG_ROUTE_START; reg <= CONFIG_ROUTE_END; reg += 4) {
u32 val = pci_read_config32(dev, reg);
if (val)
showconfig(level, reg, val);
}
}
/**
* Show all routing registers. This function is callable at any time.
*
* @param level The debug level.
* @param dev A 32-bit number in the standard bus/dev/fn format which is used
* raw config space.
*/
void showallroutes(int level, struct device *dev)
{
showalldram(level, dev);
showallmmio(level, dev);
showallpciio(level, dev);
showallconfig(level, dev);
}

View File

@ -18,10 +18,8 @@
#include "ck804.h"
#if !IS_ENABLED(CONFIG_NORTHBRIDGE_AMD_AMDK8)
/* Someone messed up and snuck in some K8-specific code */
static int set_ht_link_buffer_counts_chain(uint8_t ht_c_num, unsigned vendorid, unsigned val) { return 0; /* stub */};
#endif
static int set_ht_link_ck804(u8 ht_c_num)
{
@ -138,7 +136,7 @@ static void ck804_early_setup(unsigned ck804_num, unsigned *busn,
CK804_MB_SETUP
#endif
#if IS_ENABLED(CONFIG_NORTHBRIDGE_AMD_AMDFAM10) || (IS_ENABLED(CONFIG_NORTHBRIDGE_AMD_AMDK8) && IS_ENABLED(CONFIG_CPU_AMD_SOCKET_F))
#if IS_ENABLED(CONFIG_NORTHBRIDGE_AMD_AMDFAM10)
/*
* Avoid crash (complete with severe memory corruption!) during initial CAR boot
* in ck804_early_setup_x() on Fam10h systems by not touching 0x78.

View File

@ -18,11 +18,7 @@
#include <arch/io.h>
#include <console/console.h>
#include <reset.h>
#if IS_ENABLED(CONFIG_NORTHBRIDGE_AMD_AMDK8)
#include <northbridge/amd/amdk8/amdk8.h>
#else /* CONFIG_NORTHBRIDGE_AMD_AMDFAM10 */
#include <northbridge/amd/amdfam10/amdfam10.h>
#endif
#include "mcp55.h"
void do_soft_reset(void)