1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
4 #include <device/device.h>
6 #include <cpu/x86/msr.h>
7 #include <cpu/intel/speedstep.h>
8 #include <cpu/x86/cache.h>
9 #include <cpu/x86/name.h>
11 #define HIGHEST_CLEVEL 3
12 static void configure_c_states(void)
16 msr
= rdmsr(MSR_PKG_CST_CONFIG_CONTROL
);
17 msr
.lo
|= (1 << 15); // config lock until next reset
18 msr
.lo
|= (1 << 10); // Enable I/O MWAIT redirection for C-States
19 msr
.lo
&= ~(1 << 9); // Issue a single stop grant cycle upon stpclk
20 msr
.lo
|= (1 << 3); // dynamic L2
22 /* Number of supported C-States */
24 msr
.lo
|= HIGHEST_CLEVEL
; // support at most C3
26 wrmsr(MSR_PKG_CST_CONFIG_CONTROL
, msr
);
28 /* Set Processor MWAIT IO BASE (P_BLK) */
30 msr
.lo
= ((PMB0_BASE
+ 4) & 0xffff) | (((PMB1_BASE
+ 9) & 0xffff)
32 wrmsr(MSR_PMG_IO_BASE_ADDR
, msr
);
34 /* Set C_LVL controls and IO Capture Address */
36 // -2 because LVL0+1 aren't counted
37 msr
.lo
= (PMB0_BASE
+ 4) | ((HIGHEST_CLEVEL
- 2) << 16);
38 wrmsr(MSR_PMG_IO_CAPTURE_ADDR
, msr
);
41 static void configure_misc(void)
45 msr
= rdmsr(IA32_MISC_ENABLE
);
46 msr
.lo
|= (1 << 3); /* TM1 enable */
47 msr
.lo
|= (1 << 13); /* TM2 enable */
48 msr
.lo
|= (1 << 17); /* Bidirectional PROCHOT# */
50 msr
.lo
|= (1 << 10); /* FERR# multiplexing */
52 // TODO: Only if IA32_PLATFORM_ID[17] = 0 and IA32_PLATFORM_ID[50] = 1
53 msr
.lo
|= (1 << 16); /* Enhanced SpeedStep Enable */
59 msr
.hi
|= (1 << (32 - 32)); // C4E
60 msr
.hi
|= (1 << (33 - 32)); // Hard C4E
62 wrmsr(IA32_MISC_ENABLE
, msr
);
64 msr
.lo
|= (1 << 20); /* Lock Enhanced SpeedStep Enable */
65 wrmsr(IA32_MISC_ENABLE
, msr
);
67 // set maximum CPU speed
68 msr
= rdmsr(IA32_PERF_STATUS
);
69 int busratio_max
= (msr
.hi
>> (40-32)) & 0x1f;
71 msr
= rdmsr(IA32_PLATFORM_ID
);
72 int vid_max
= msr
.lo
& 0x3f;
75 msr
.lo
|= busratio_max
<< 8;
78 wrmsr(IA32_PERF_CTL
, msr
);
81 #define PIC_SENS_CFG 0x1aa
82 static void configure_pic_thermal_sensors(void)
86 msr
= rdmsr(PIC_SENS_CFG
);
88 msr
.lo
|= (1 << 21); // inter-core lock TM1
89 msr
.lo
|= (1 << 4); // Enable bypass filter
91 wrmsr(PIC_SENS_CFG
, msr
);
94 static void model_6ex_init(struct device
*cpu
)
96 char processor_name
[49];
98 /* Turn on caching if we haven't already */
101 /* Print processor name */
102 fill_processor_name(processor_name
);
103 printk(BIOS_INFO
, "CPU: %s.\n", processor_name
);
105 /* Setup Page Attribute Tables (PAT) */
108 /* Configure C States */
109 configure_c_states();
111 /* Configure Enhanced SpeedStep and Thermal Sensors */
114 /* PIC thermal sensor control */
115 configure_pic_thermal_sensors();
118 static struct device_operations cpu_dev_ops
= {
119 .init
= model_6ex_init
,
122 static const struct cpu_device_id cpu_table
[] = {
123 { X86_VENDOR_INTEL
, 0x06e0, CPUID_EXACT_MATCH_MASK
}, /* Intel Core Solo/Core Duo */
124 { X86_VENDOR_INTEL
, 0x06e8, CPUID_EXACT_MATCH_MASK
}, /* Intel Core Solo/Core Duo */
125 { X86_VENDOR_INTEL
, 0x06ec, CPUID_EXACT_MATCH_MASK
}, /* Intel Core Solo/Core Duo */
129 static const struct cpu_driver driver __cpu_driver
= {
131 .id_table
= cpu_table
,