diff options
Diffstat (limited to 'src/soc')
-rw-r--r-- | src/soc/intel/apollolake/include/soc/cpu.h | 4 | ||||
-rw-r--r-- | src/soc/intel/apollolake/include/soc/iomap.h | 6 | ||||
-rw-r--r-- | src/soc/intel/apollolake/include/soc/pci_devs.h | 3 | ||||
-rw-r--r-- | src/soc/intel/apollolake/romstage.c | 69 | ||||
-rw-r--r-- | src/soc/intel/apollolake/tsc_freq.c | 42 |
5 files changed, 124 insertions, 0 deletions
diff --git a/src/soc/intel/apollolake/include/soc/cpu.h b/src/soc/intel/apollolake/include/soc/cpu.h index e94972d90b..66fc29babc 100644 --- a/src/soc/intel/apollolake/include/soc/cpu.h +++ b/src/soc/intel/apollolake/include/soc/cpu.h @@ -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_ */ diff --git a/src/soc/intel/apollolake/include/soc/iomap.h b/src/soc/intel/apollolake/include/soc/iomap.h index d5d8f878ef..3c94d1b608 100644 --- a/src/soc/intel/apollolake/include/soc/iomap.h +++ b/src/soc/intel/apollolake/include/soc/iomap.h @@ -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 diff --git a/src/soc/intel/apollolake/include/soc/pci_devs.h b/src/soc/intel/apollolake/include/soc/pci_devs.h index 0d9e28847c..d058f8b946 100644 --- a/src/soc/intel/apollolake/include/soc/pci_devs.h +++ b/src/soc/intel/apollolake/include/soc/pci_devs.h @@ -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) diff --git a/src/soc/intel/apollolake/romstage.c b/src/soc/intel/apollolake/romstage.c index 1f6a38fecc..f1d4b57494 100644 --- a/src/soc/intel/apollolake/romstage.c +++ b/src/soc/intel/apollolake/romstage.c @@ -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"); diff --git a/src/soc/intel/apollolake/tsc_freq.c b/src/soc/intel/apollolake/tsc_freq.c index 9dd1dea990..96c3a0a709 100644 --- a/src/soc/intel/apollolake/tsc_freq.c +++ b/src/soc/intel/apollolake/tsc_freq.c @@ -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); +} |