bootblock.c
1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #include <stdint.h> 4 #include <arch/bootblock.h> 5 #include <cpu/x86/msr.h> 6 #include <arch/io.h> 7 #include <delay.h> 8 #include <halt.h> 9 10 #include "haswell.h" 11 12 #include <southbridge/intel/lynxpoint/pch.h> 13 14 static void set_flex_ratio_to_tdp_nominal(void) 15 { 16 msr_t flex_ratio, msr; 17 u32 soft_reset; 18 u8 nominal_ratio; 19 20 /* Check for Flex Ratio support */ 21 flex_ratio = rdmsr(MSR_FLEX_RATIO); 22 if (!(flex_ratio.lo & FLEX_RATIO_EN)) 23 return; 24 25 /* Check for >0 configurable TDPs */ 26 msr = rdmsr(MSR_PLATFORM_INFO); 27 if (((msr.hi >> 1) & 3) == 0) 28 return; 29 30 /* Use nominal TDP ratio for flex ratio */ 31 msr = rdmsr(MSR_CONFIG_TDP_NOMINAL); 32 nominal_ratio = msr.lo & 0xff; 33 34 /* See if flex ratio is already set to nominal TDP ratio */ 35 if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio) 36 return; 37 38 /* Set flex ratio to nominal TDP ratio */ 39 flex_ratio.lo &= ~0xff00; 40 flex_ratio.lo |= nominal_ratio << 8; 41 flex_ratio.lo |= FLEX_RATIO_LOCK; 42 wrmsr(MSR_FLEX_RATIO, flex_ratio); 43 44 /* Set flex ratio in soft reset data register bits 11:6. 45 * RCBA region is enabled in southbridge bootblock */ 46 soft_reset = RCBA32(SOFT_RESET_DATA); 47 soft_reset &= ~(0x3f << 6); 48 soft_reset |= (nominal_ratio & 0x3f) << 6; 49 RCBA32(SOFT_RESET_DATA) = soft_reset; 50 51 /* Set soft reset control to use register value */ 52 RCBA32_OR(SOFT_RESET_CTRL, 1); 53 54 /* Delay before reset to avoid potential TPM lockout */ 55 if (CONFIG(TPM)) 56 mdelay(30); 57 58 /* Issue warm reset, will be "CPU only" due to soft reset data */ 59 outb(0x0, 0xcf9); 60 outb(0x6, 0xcf9); 61 halt(); 62 } 63 64 void bootblock_early_cpu_init(void) 65 { 66 /* Set flex ratio and reset if needed */ 67 set_flex_ratio_to_tdp_nominal(); 68 }