intel/apollolake: Enable turbo

This patch adds punit initialization code after
FspMemoryInit so that turbo can be initialized after
that.

BUG=chrome-os-partner:58158
BRANCH=None

Change-Id: I4939da47da82b9a728cf1b5cf6d5ec54b4f5b31d
Signed-off-by: Shaunak Saha <shaunak.saha@intel.com>
Reviewed-on: https://review.coreboot.org/17203
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Shaunak Saha 2016-10-10 12:34:28 -07:00 committed by Martin Roth
parent a09b338362
commit a012254d01
5 changed files with 124 additions and 0 deletions

View File

@ -23,6 +23,7 @@
#include <device/device.h>
void apollolake_init_cpus(struct device *dev);
void set_max_freq(void);
#endif
#define CPUID_APOLLOLAKE_A0 0x506c8
@ -88,4 +89,7 @@ void apollolake_init_cpus(struct device *dev);
/* Common Timer Copy (CTC) frequency - 19.2MHz. */
#define CTC_FREQ 19200000
/* This is burst mode BIT 38 in MSR_IA32_MISC_ENABLES MSR at offset 1A0h */
#define APL_BURST_MODE_DISABLE 0x40
#endif /* _SOC_APOLLOLAKE_CPU_H_ */

View File

@ -25,6 +25,12 @@
#define MCH_BASE_ADDR 0xfed10000
#define MCH_BASE_SIZE (32 * KiB)
#define P_CR_CORE_DISABLE_MASK_0_0_0_MCHBAR 0x7168
#define P_CR_BIOS_RESET_CPL_0_0_0_MCHBAR 0x7078
#define PUNIT_THERMAL_DEVICE_IRQ 0x700C
#define PUINT_THERMAL_DEVICE_IRQ_VEC_NUMBER 0x18
#define PUINT_THERMAL_DEVICE_IRQ_LOCK 0x80000000
#define ACPI_PMIO_BASE 0x400
#define ACPI_PMIO_SIZE 0x100
#define R_ACPI_PM1_TMR 0x8

View File

@ -34,6 +34,9 @@
#define NB_DEVFN _PCI_DEVFN(0, 0)
#define NB_DEV_ROOT _PCI_DEV(0x0, 0)
#define PUNIT_DEV _PCI_DEV(0, 1)
#define PUNIT_DEVFN _PCI_DEVFN(0x0, 1)
#define IGD_DEV _PCI_DEV(0x2, 0)
#define IGD_DEVFN _PCI_DEVFN(0x2, 0)

View File

@ -31,6 +31,7 @@
#include <fsp/api.h>
#include <fsp/memmap.h>
#include <fsp/util.h>
#include <soc/cpu.h>
#include <soc/iomap.h>
#include <soc/northbridge.h>
#include <soc/pci_devs.h>
@ -40,6 +41,9 @@
#include <soc/uart.h>
#include <string.h>
#include <timestamp.h>
#include <timer.h>
#include <delay.h>
#include "chip.h"
static struct chipset_power_state power_state CAR_GLOBAL;
@ -100,6 +104,65 @@ static void migrate_power_state(int is_recovery)
}
ROMSTAGE_CBMEM_INIT_HOOK(migrate_power_state);
/*
* Punit Initialization code. This all isn't documented, but
* this is the recipe.
*/
static bool punit_init(void)
{
uint32_t reg;
uint32_t data;
struct stopwatch sw;
/*
* Software Core Disable Mask (P_CR_CORE_DISABLE_MASK_0_0_0_MCHBAR).
* Enable all cores here.
*/
write32((void *)(MCH_BASE_ADDR + P_CR_CORE_DISABLE_MASK_0_0_0_MCHBAR),
0x0);
void *bios_rest_cpl = (void *)(MCH_BASE_ADDR +
P_CR_BIOS_RESET_CPL_0_0_0_MCHBAR);
/* P-Unit bring up */
reg = read32(bios_rest_cpl);
if (reg == 0xffffffff) {
/* P-unit not found */
printk(BIOS_DEBUG, "Punit MMIO not available \n");
return false;
} else {
/* Set Punit interrupt pin IPIN offset 3D */
pci_write_config8(PUNIT_DEVFN, PCI_INTERRUPT_PIN, 0x2);
/* Set PUINT IRQ to 24 and INTPIN LOCK */
write32((void *)(MCH_BASE_ADDR + PUNIT_THERMAL_DEVICE_IRQ),
PUINT_THERMAL_DEVICE_IRQ_VEC_NUMBER |
PUINT_THERMAL_DEVICE_IRQ_LOCK);
data = read32((void *)(MCH_BASE_ADDR + 0x7818));
data &= 0xFFFFE01F;
data |= 0x20 | 0x200;
write32((void *)(MCH_BASE_ADDR + 0x7818), data);
/* Stage0 BIOS Reset Complete (RST_CPL) */
write32(bios_rest_cpl, 0x1);
/*
* Poll for bit 8 in same reg (RST_CPL).
* We wait here till 1 ms for the bit to get set.
*/
stopwatch_init_msecs_expire(&sw, 1);
while (!(read32(bios_rest_cpl) & 0x100)) {
if (stopwatch_expired(&sw)) {
printk(BIOS_DEBUG,
"Failed to set RST_CPL bit\n");
return false;
}
udelay(100);
}
}
return true;
}
asmlinkage void car_stage_entry(void)
{
struct postcar_frame pcf;
@ -119,6 +182,12 @@ asmlinkage void car_stage_entry(void)
s3wake = fill_power_state(ps) == ACPI_S3;
fsp_memory_init(s3wake);
if (punit_init())
set_max_freq();
else
printk(BIOS_DEBUG, "Punit failed to initialize properly\n");
if (postcar_frame_init(&pcf, 1*KiB))
die("Unable to initialize postcar frame.\n");

View File

@ -14,12 +14,54 @@
* GNU General Public License for more details.
*/
#include <cpu/intel/speedstep.h>
#include <cpu/intel/turbo.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/tsc.h>
#include <soc/cpu.h>
#include <console/console.h>
#include <delay.h>
#include "chip.h"
unsigned long tsc_freq_mhz(void)
{
msr_t msr = rdmsr(MSR_PLATFORM_INFO);
return (BASE_CLOCK_MHZ * ((msr.lo >> 8) & 0xff));
}
void set_max_freq(void)
{
msr_t msr, msr_rd;
unsigned int eax;
eax = cpuid_eax(CPUID_LEAF_PM);
msr = rdmsr(MSR_IA32_MISC_ENABLES);
if (!(eax &= 0x2) && ((msr.hi & APL_BURST_MODE_DISABLE) == 0)) {
/* Burst Mode has been factory configured as disabled
* and is not available in this physical processor
* package.
*/
printk(BIOS_DEBUG, "Burst Mode is factory disabled\n");
return;
}
/* Enable burst mode */
msr.hi &= ~APL_BURST_MODE_DISABLE;
wrmsr(MSR_IA32_MISC_ENABLES, msr);
/* Enable speed step. */
msr = rdmsr(MSR_IA32_MISC_ENABLES);
msr.lo |= 1 << 16;
wrmsr(MSR_IA32_MISC_ENABLES, msr);
/* Set P-State ratio */
msr = rdmsr(IA32_PERF_CTL);
msr.lo &= ~0xff00;
/* Read the frequency limit ratio and set it properly in PERF_CTL */
msr_rd = rdmsr(FREQ_LIMIT_RATIO);
msr.lo |= (msr_rd.lo & 0xff) << 8;
wrmsr(IA32_PERF_CTL, msr);
}