2 * This file is part of the coreboot project.
4 * Copyright (C) 2014 Google Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <cpu/x86/cache.h>
18 #include <cpu/x86/msr.h>
19 #include <cpu/x86/mtrr.h>
22 #include <cpu/intel/microcode/microcode.c>
26 static void set_var_mtrr(unsigned int reg
, unsigned int base
, unsigned int size
,
29 /* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
31 basem
.lo
= base
| type
;
33 wrmsr(MTRR_PHYS_BASE(reg
), basem
);
34 maskm
.lo
= ~(size
- 1) | MTRR_PHYS_MASK_VALID
;
35 maskm
.hi
= (1 << (CONFIG_CPU_ADDR_BITS
- 32)) - 1;
36 wrmsr(MTRR_PHYS_MASK(reg
), maskm
);
39 static void enable_rom_caching(void)
44 set_var_mtrr(1, CACHE_ROM_BASE
, CACHE_ROM_SIZE
, MTRR_TYPE_WRPROT
);
47 /* Enable Variable MTRRs */
50 wrmsr(MTRR_DEF_TYPE_MSR
, msr
);
53 static void bootblock_mdelay(int ms
)
55 u32 target
= ms
* 24 * 1000;
57 msr_t start
= rdmsr(MSR_COUNTER_24_MHZ
);
60 current
= rdmsr(MSR_COUNTER_24_MHZ
);
61 } while ((current
.lo
- start
.lo
) < target
);
64 static void set_flex_ratio_to_tdp_nominal(void)
66 msr_t flex_ratio
, msr
;
70 /* Check for Flex Ratio support */
71 flex_ratio
= rdmsr(MSR_FLEX_RATIO
);
72 if (!(flex_ratio
.lo
& FLEX_RATIO_EN
))
75 /* Check for >0 configurable TDPs */
76 msr
= rdmsr(MSR_PLATFORM_INFO
);
77 if (((msr
.hi
>> 1) & 3) == 0)
80 /* Use nominal TDP ratio for flex ratio */
81 msr
= rdmsr(MSR_CONFIG_TDP_NOMINAL
);
82 nominal_ratio
= msr
.lo
& 0xff;
84 /* See if flex ratio is already set to nominal TDP ratio */
85 if (((flex_ratio
.lo
>> 8) & 0xff) == nominal_ratio
)
88 /* Set flex ratio to nominal TDP ratio */
89 flex_ratio
.lo
&= ~0xff00;
90 flex_ratio
.lo
|= nominal_ratio
<< 8;
91 flex_ratio
.lo
|= FLEX_RATIO_LOCK
;
92 wrmsr(MSR_FLEX_RATIO
, flex_ratio
);
94 /* Set flex ratio in soft reset data register bits 11:6.
95 * RCBA region is enabled in southbridge bootblock */
96 soft_reset
= RCBA32(SOFT_RESET_DATA
);
97 soft_reset
&= ~(0x3f << 6);
98 soft_reset
|= (nominal_ratio
& 0x3f) << 6;
99 RCBA32(SOFT_RESET_DATA
) = soft_reset
;
101 /* Set soft reset control to use register value */
102 RCBA32_OR(SOFT_RESET_CTRL
, 1);
104 /* Delay before reset to avoid potential TPM lockout */
105 bootblock_mdelay(30);
107 /* Issue warm reset, will be "CPU only" due to soft reset data */
113 static void check_for_clean_reset(void)
116 msr
= rdmsr(MTRR_DEF_TYPE_MSR
);
118 /* Use the MTRR default type MSR as a proxy for detecting INIT#.
119 * Reset the system if any known bits are set in that MSR. That is
120 * an indication of the CPU not being properly reset. */
121 if (msr
.lo
& (MTRR_DEF_TYPE_EN
| MTRR_DEF_TYPE_FIX_EN
)) {
128 static void bootblock_cpu_init(void)
130 /* Set flex ratio and reset if needed */
131 set_flex_ratio_to_tdp_nominal();
132 check_for_clean_reset();
133 enable_rom_caching();
134 intel_update_microcode_from_cbfs();