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:
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -1,2 +0,0 @@
|
||||
# This is a leaf Makefile, no conditionals. If it is included it will be used.
|
||||
ramstage-y += amd_sibling.c
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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");
|
||||
}
|
@ -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
|
||||
};
|
@ -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,
|
||||
};
|
@ -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);
|
||||
}
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
@ -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
|
@ -1,4 +0,0 @@
|
||||
config CPU_AMD_SOCKET_939
|
||||
bool
|
||||
select CPU_AMD_MODEL_FXX
|
||||
select X86_AMD_FIXED_MTRRS
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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__ */
|
@ -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");
|
||||
}
|
@ -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
|
@ -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
|
@ -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 */
|
||||
|
||||
}
|
@ -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
|
@ -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 */
|
||||
|
@ -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
@ -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
|
@ -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
|
@ -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
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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 */
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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
|
@ -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
@ -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 */
|
@ -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
@ -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
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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))
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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.
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user