1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <console/console.h>
5 #include <device/device.h>
7 #include <cpu/x86/mtrr.h>
8 #include <cpu/x86/msr.h>
9 #include <cpu/x86/lapic.h>
10 #include <cpu/x86/mp.h>
11 #include <cpu/intel/microcode.h>
12 #include <cpu/intel/speedstep.h>
13 #include <cpu/intel/turbo.h>
14 #include <cpu/x86/cache.h>
15 #include <cpu/x86/name.h>
16 #include "model_2065x.h"
18 #include <cpu/intel/smm_reloc.h>
19 #include <cpu/intel/common/common.h>
23 static void configure_thermal_target(struct device
*dev
)
25 struct cpu_intel_model_2065x_config
*conf
= dev
->upstream
->dev
->chip_info
;
28 /* Set TCC activation offset if supported */
29 msr
= rdmsr(MSR_PLATFORM_INFO
);
30 if ((msr
.lo
& (1 << 30)) && conf
->tcc_offset
) {
31 msr
= rdmsr(MSR_TEMPERATURE_TARGET
);
32 msr
.lo
&= ~(0xf << 24); /* Bits 27:24 */
33 msr
.lo
|= (conf
->tcc_offset
& 0xf) << 24;
34 wrmsr(MSR_TEMPERATURE_TARGET
, msr
);
38 static void configure_misc(void)
42 msr
= rdmsr(IA32_MISC_ENABLE
);
43 msr
.lo
|= (1 << 0); /* Fast String enable */
44 msr
.lo
|= (1 << 3); /* TM1/TM2/EMTTM enable */
45 msr
.lo
|= (1 << 16); /* Enhanced SpeedStep Enable */
46 wrmsr(IA32_MISC_ENABLE
, msr
);
48 /* Disable Thermal interrupts */
51 wrmsr(IA32_THERM_INTERRUPT
, msr
);
54 static void set_max_ratio(void)
60 /* Platform Info bits 15:8 give max ratio */
61 msr
= rdmsr(MSR_PLATFORM_INFO
);
62 perf_ctl
.lo
= msr
.lo
& 0xff00;
63 wrmsr(IA32_PERF_CTL
, perf_ctl
);
65 printk(BIOS_DEBUG
, "model_x065x: frequency set to %d\n",
66 ((perf_ctl
.lo
>> 8) & 0xff) * IRONLAKE_BCLK
);
69 static void model_2065x_init(struct device
*cpu
)
71 char processor_name
[49];
73 /* Clear out pending MCEs */
74 /* This should only be done on a cold boot */
77 /* Print processor name */
78 fill_processor_name(processor_name
);
79 printk(BIOS_INFO
, "CPU: %s.\n", processor_name
);
80 printk(BIOS_INFO
, "CPU:lapic=%d, boot_cpu=%d\n", lapicid(),
83 /* Setup Page Attribute Tables (PAT) */
88 /* Set virtualization based on Kconfig option */
93 /* Configure Enhanced SpeedStep and Thermal Sensors */
96 /* Thermal throttle activation offset */
97 configure_thermal_target(cpu
);
106 /* MP initialization support. */
107 static void pre_mp_init(void)
109 /* Setup MTRRs based on physical address size. */
110 x86_setup_mtrrs_with_detect();
114 static int get_cpu_count(void)
117 unsigned int num_threads
;
118 unsigned int num_cores
;
120 msr
= rdmsr(MSR_CORE_THREAD_COUNT
);
121 num_threads
= (msr
.lo
>> 0) & 0xffff;
122 num_cores
= (msr
.lo
>> 16) & 0xffff;
123 printk(BIOS_DEBUG
, "CPU has %u cores, %u threads enabled.\n",
124 num_cores
, num_threads
);
129 static void get_microcode_info(const void **microcode
, int *parallel
)
131 *microcode
= intel_microcode_find();
132 *parallel
= !intel_ht_supported();
135 static void per_cpu_smm_trigger(void)
137 /* Relocate the SMM handler. */
140 /* After SMM relocation a 2nd microcode load is required. */
141 const void *microcode_patch
= intel_microcode_find();
142 intel_microcode_load_unlocked(microcode_patch
);
145 static void post_mp_init(void)
147 /* Now that all APs have been relocated as well as the BSP let SMIs
151 /* Lock down the SMRAM space. */
155 static const struct mp_ops mp_ops
= {
156 .pre_mp_init
= pre_mp_init
,
157 .get_cpu_count
= get_cpu_count
,
158 .get_smm_info
= smm_info
,
159 .get_microcode_info
= get_microcode_info
,
160 .pre_mp_smm_init
= smm_initialize
,
161 .per_cpu_smm_trigger
= per_cpu_smm_trigger
,
162 .relocation_handler
= smm_relocation_handler
,
163 .post_mp_init
= post_mp_init
,
166 void mp_init_cpus(struct bus
*cpu_bus
)
168 /* TODO: Handle mp_init_with_smm failure? */
169 mp_init_with_smm(cpu_bus
, &mp_ops
);
172 static struct device_operations cpu_dev_ops
= {
173 .init
= model_2065x_init
,
176 /* Arrandale / Clarkdale CPU IDs */
177 static const struct cpu_device_id cpu_table
[] = {
178 { X86_VENDOR_INTEL
, 0x20650, CPUID_EXACT_MATCH_MASK
},
179 { X86_VENDOR_INTEL
, 0x20651, CPUID_EXACT_MATCH_MASK
},
180 { X86_VENDOR_INTEL
, 0x20652, CPUID_EXACT_MATCH_MASK
},
181 { X86_VENDOR_INTEL
, 0x20654, CPUID_EXACT_MATCH_MASK
},
182 { X86_VENDOR_INTEL
, 0x20655, CPUID_EXACT_MATCH_MASK
},
186 static const struct cpu_driver driver __cpu_driver
= {
188 .id_table
= cpu_table
,