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
|
Reference in New Issue
Block a user