broadwell: update processor power limits configuration
Update processor power limit configuration parameters based on common code base support for Intel Broadwell SoC based platforms. BRANCH=None BUG=None TEST=Build for broadwell based platform Change-Id: I97e38a533e74a122b6809e20a10f6e425827ab9c Signed-off-by: Sumeet R Pawnikar <sumeet.r.pawnikar@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/41234 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
This commit is contained in:
parent
71a9a7c70f
commit
fa42d568a0
|
@ -15,6 +15,7 @@ config CPU_SPECIFIC_OPTIONS
|
|||
select BOOT_DEVICE_SUPPORTS_WRITES
|
||||
select CACHE_MRC_SETTINGS
|
||||
select MRC_SETTINGS_PROTECT
|
||||
select CPU_INTEL_COMMON
|
||||
select CPU_INTEL_FIRMWARE_INTERFACE_TABLE
|
||||
select SUPPORT_CPU_UCODE_IN_CBFS
|
||||
select HAVE_SMI_HANDLER
|
||||
|
@ -34,10 +35,12 @@ config CPU_SPECIFIC_OPTIONS
|
|||
select UDELAY_TSC
|
||||
select TSC_MONOTONIC_TIMER
|
||||
select SOC_INTEL_COMMON
|
||||
select SOC_INTEL_COMMON_BLOCK
|
||||
select SOC_INTEL_COMMON_BLOCK_CPU
|
||||
select SOC_INTEL_COMMON_BLOCK_POWER_LIMIT
|
||||
select INTEL_DESCRIPTOR_MODE_CAPABLE
|
||||
select SOC_INTEL_COMMON_ACPI_WAKE_SOURCE
|
||||
select HAVE_SPI_CONSOLE_SUPPORT
|
||||
select CPU_INTEL_COMMON
|
||||
select INTEL_GMA_ACPI
|
||||
select HAVE_POWER_STATE_AFTER_FAILURE
|
||||
select HAVE_POWER_STATE_PREVIOUS_AFTER_FAILURE
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <soc/pm.h>
|
||||
#include <soc/systemagent.h>
|
||||
#include <soc/intel/broadwell/chip.h>
|
||||
#include <intelblocks/cpulib.h>
|
||||
|
||||
/*
|
||||
* List of supported C-states in this processor. Only the ULT parts support C8,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#define _SOC_INTEL_BROADWELL_CHIP_H_
|
||||
|
||||
#include <drivers/intel/gma/i915.h>
|
||||
#include <intelblocks/cfg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct soc_intel_broadwell_config {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <cpu/x86/name.h>
|
||||
#include <cpu/x86/smm.h>
|
||||
#include <delay.h>
|
||||
#include <intelblocks/cpulib.h>
|
||||
#include <soc/cpu.h>
|
||||
#include <soc/msr.h>
|
||||
#include <soc/pci_devs.h>
|
||||
|
@ -25,64 +26,6 @@
|
|||
#include <soc/intel/broadwell/chip.h>
|
||||
#include <cpu/intel/common/common.h>
|
||||
|
||||
/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
|
||||
static const u8 power_limit_time_sec_to_msr[] = {
|
||||
[0] = 0x00,
|
||||
[1] = 0x0a,
|
||||
[2] = 0x0b,
|
||||
[3] = 0x4b,
|
||||
[4] = 0x0c,
|
||||
[5] = 0x2c,
|
||||
[6] = 0x4c,
|
||||
[7] = 0x6c,
|
||||
[8] = 0x0d,
|
||||
[10] = 0x2d,
|
||||
[12] = 0x4d,
|
||||
[14] = 0x6d,
|
||||
[16] = 0x0e,
|
||||
[20] = 0x2e,
|
||||
[24] = 0x4e,
|
||||
[28] = 0x6e,
|
||||
[32] = 0x0f,
|
||||
[40] = 0x2f,
|
||||
[48] = 0x4f,
|
||||
[56] = 0x6f,
|
||||
[64] = 0x10,
|
||||
[80] = 0x30,
|
||||
[96] = 0x50,
|
||||
[112] = 0x70,
|
||||
[128] = 0x11,
|
||||
};
|
||||
|
||||
/* Convert POWER_LIMIT_1_TIME MSR value to seconds */
|
||||
static const u8 power_limit_time_msr_to_sec[] = {
|
||||
[0x00] = 0,
|
||||
[0x0a] = 1,
|
||||
[0x0b] = 2,
|
||||
[0x4b] = 3,
|
||||
[0x0c] = 4,
|
||||
[0x2c] = 5,
|
||||
[0x4c] = 6,
|
||||
[0x6c] = 7,
|
||||
[0x0d] = 8,
|
||||
[0x2d] = 10,
|
||||
[0x4d] = 12,
|
||||
[0x6d] = 14,
|
||||
[0x0e] = 16,
|
||||
[0x2e] = 20,
|
||||
[0x4e] = 24,
|
||||
[0x6e] = 28,
|
||||
[0x0f] = 32,
|
||||
[0x2f] = 40,
|
||||
[0x4f] = 48,
|
||||
[0x6f] = 56,
|
||||
[0x10] = 64,
|
||||
[0x30] = 80,
|
||||
[0x50] = 96,
|
||||
[0x70] = 112,
|
||||
[0x11] = 128,
|
||||
};
|
||||
|
||||
/* The core 100MHz BLCK is disabled in deeper c-states. One needs to calibrate
|
||||
* the 100MHz BCLCK against the 24MHz BLCK to restore the clocks properly
|
||||
* when a core is woken up. */
|
||||
|
@ -288,90 +231,6 @@ static void configure_pch_power_sharing(void)
|
|||
RCBA32(PMSYNC_CONFIG2) = pmsync2;
|
||||
}
|
||||
|
||||
int cpu_config_tdp_levels(void)
|
||||
{
|
||||
msr_t platform_info;
|
||||
|
||||
/* Bits 34:33 indicate how many levels supported */
|
||||
platform_info = rdmsr(MSR_PLATFORM_INFO);
|
||||
return (platform_info.hi >> 1) & 3;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure processor power limits if possible
|
||||
* This must be done AFTER set of BIOS_RESET_CPL
|
||||
*/
|
||||
void set_power_limits(u8 power_limit_1_time)
|
||||
{
|
||||
msr_t msr = rdmsr(MSR_PLATFORM_INFO);
|
||||
msr_t limit;
|
||||
unsigned int power_unit;
|
||||
unsigned int tdp, min_power, max_power, max_time;
|
||||
u8 power_limit_1_val;
|
||||
|
||||
if (power_limit_1_time >= ARRAY_SIZE(power_limit_time_sec_to_msr))
|
||||
power_limit_1_time = ARRAY_SIZE(power_limit_time_sec_to_msr) - 1;
|
||||
|
||||
if (!(msr.lo & PLATFORM_INFO_SET_TDP))
|
||||
return;
|
||||
|
||||
/* Get units */
|
||||
msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
|
||||
power_unit = 2 << ((msr.lo & 0xf) - 1);
|
||||
|
||||
/* Get power defaults for this SKU */
|
||||
msr = rdmsr(MSR_PKG_POWER_SKU);
|
||||
tdp = msr.lo & 0x7fff;
|
||||
min_power = (msr.lo >> 16) & 0x7fff;
|
||||
max_power = msr.hi & 0x7fff;
|
||||
max_time = (msr.hi >> 16) & 0x7f;
|
||||
|
||||
printk(BIOS_DEBUG, "CPU TDP: %u Watts\n", tdp / power_unit);
|
||||
|
||||
if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time)
|
||||
power_limit_1_time = power_limit_time_msr_to_sec[max_time];
|
||||
|
||||
if (min_power > 0 && tdp < min_power)
|
||||
tdp = min_power;
|
||||
|
||||
if (max_power > 0 && tdp > max_power)
|
||||
tdp = max_power;
|
||||
|
||||
power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time];
|
||||
|
||||
/* Set long term power limit to TDP */
|
||||
limit.lo = 0;
|
||||
limit.lo |= tdp & PKG_POWER_LIMIT_MASK;
|
||||
limit.lo |= PKG_POWER_LIMIT_EN;
|
||||
limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) <<
|
||||
PKG_POWER_LIMIT_TIME_SHIFT;
|
||||
|
||||
/* Set short term power limit to 1.25 * TDP */
|
||||
limit.hi = 0;
|
||||
limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK;
|
||||
limit.hi |= PKG_POWER_LIMIT_EN;
|
||||
/* Power limit 2 time is only programmable on server SKU */
|
||||
|
||||
wrmsr(MSR_PKG_POWER_LIMIT, limit);
|
||||
|
||||
/* Set power limit values in MCHBAR as well */
|
||||
MCHBAR32(MCH_PKG_POWER_LIMIT_LO) = limit.lo;
|
||||
MCHBAR32(MCH_PKG_POWER_LIMIT_HI) = limit.hi;
|
||||
|
||||
/* Set DDR RAPL power limit by copying from MMIO to MSR */
|
||||
msr.lo = MCHBAR32(MCH_DDR_POWER_LIMIT_LO);
|
||||
msr.hi = MCHBAR32(MCH_DDR_POWER_LIMIT_HI);
|
||||
wrmsr(MSR_DDR_RAPL_LIMIT, msr);
|
||||
|
||||
/* Use nominal TDP values for CPUs with configurable TDP */
|
||||
if (cpu_config_tdp_levels()) {
|
||||
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
|
||||
limit.hi = 0;
|
||||
limit.lo = msr.lo & 0xff;
|
||||
wrmsr(MSR_TURBO_ACTIVATION_RATIO, limit);
|
||||
}
|
||||
}
|
||||
|
||||
static void configure_c_states(void)
|
||||
{
|
||||
msr_t msr;
|
||||
|
|
|
@ -37,10 +37,6 @@
|
|||
C_STATE_LATENCY_MICRO_SECONDS(C_STATE_LATENCY_CONTROL_ ##reg## _LIMIT, \
|
||||
(IRTL_1024_NS >> 10))
|
||||
|
||||
/* Configure power limits for turbo mode */
|
||||
void set_power_limits(u8 power_limit_1_time);
|
||||
int cpu_config_tdp_levels(void);
|
||||
|
||||
/* CPU identification */
|
||||
u32 cpu_family_model(void);
|
||||
u32 cpu_stepping(void);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#ifndef _BROADWELL_MSR_H_
|
||||
#define _BROADWELL_MSR_H_
|
||||
|
||||
#include <intelblocks/msr.h>
|
||||
|
||||
#define MSR_PIC_MSG_CONTROL 0x2e
|
||||
#define MSR_CORE_THREAD_COUNT 0x35
|
||||
#define MSR_PLATFORM_INFO 0xce
|
||||
|
@ -45,14 +47,6 @@
|
|||
#define IRTL_RESPONSE_MASK (0x3ff)
|
||||
#define MSR_COUNTER_24_MHZ 0x637
|
||||
|
||||
/* long duration in low dword, short duration in high dword */
|
||||
#define MSR_PKG_POWER_LIMIT 0x610
|
||||
#define PKG_POWER_LIMIT_MASK 0x7fff
|
||||
#define PKG_POWER_LIMIT_EN (1 << 15)
|
||||
#define PKG_POWER_LIMIT_CLAMP (1 << 16)
|
||||
#define PKG_POWER_LIMIT_TIME_SHIFT 17
|
||||
#define PKG_POWER_LIMIT_TIME_MASK 0x7f
|
||||
|
||||
#define MSR_VR_CURRENT_CONFIG 0x601
|
||||
#define MSR_VR_MISC_CONFIG 0x603
|
||||
#define MSR_PKG_POWER_SKU_UNIT 0x606
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _SOC_BROADWELL_SOC_CHIP_H_
|
||||
#define _SOC_BROADWELL_SOC_CHIP_H_
|
||||
|
||||
#include "../../chip.h"
|
||||
|
||||
#endif /* _SOC_BROADWELL_SOC_CHIP_H_ */
|
|
@ -8,6 +8,7 @@
|
|||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <intelblocks/power_limit.h>
|
||||
#include <vendorcode/google/chromeos/chromeos.h>
|
||||
#include <soc/cpu.h>
|
||||
#include <soc/iomap.h>
|
||||
|
@ -404,6 +405,7 @@ static void systemagent_read_resources(struct device *dev)
|
|||
|
||||
static void systemagent_init(struct device *dev)
|
||||
{
|
||||
struct soc_power_limits_config *config;
|
||||
u8 bios_reset_cpl, pair;
|
||||
|
||||
/* Enable Power Aware Interrupt Routing */
|
||||
|
@ -423,7 +425,8 @@ static void systemagent_init(struct device *dev)
|
|||
|
||||
/* Configure turbo power limits 1ms after reset complete bit */
|
||||
mdelay(1);
|
||||
set_power_limits(28);
|
||||
config = config_of_soc();
|
||||
set_power_limits(MOBILE_SKU_PL1_TIME_SEC, config);
|
||||
}
|
||||
|
||||
static struct device_operations systemagent_ops = {
|
||||
|
|
Loading…
Reference in New Issue