]>
Commit | Line | Data |
---|---|---|
ede97093 SG |
1 | /* |
2 | * Copyright (C) 2015 Google, Inc | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | * | |
6 | * Based on code from coreboot | |
7 | */ | |
8 | ||
9 | #include <common.h> | |
10 | #include <cpu.h> | |
11 | #include <dm.h> | |
12 | #include <asm/cpu.h> | |
be3f06bc | 13 | #include <asm/cpu_x86.h> |
ede97093 | 14 | #include <asm/lapic.h> |
ede97093 SG |
15 | #include <asm/msr.h> |
16 | #include <asm/turbo.h> | |
17 | ||
ede97093 SG |
18 | static void set_max_freq(void) |
19 | { | |
20 | msr_t perf_ctl; | |
21 | msr_t msr; | |
22 | ||
23 | /* Enable speed step */ | |
24 | msr = msr_read(MSR_IA32_MISC_ENABLES); | |
25 | msr.lo |= (1 << 16); | |
26 | msr_write(MSR_IA32_MISC_ENABLES, msr); | |
27 | ||
28 | /* | |
29 | * Set guaranteed ratio [21:16] from IACORE_RATIOS to bits [15:8] of | |
30 | * the PERF_CTL | |
31 | */ | |
32 | msr = msr_read(MSR_IACORE_RATIOS); | |
33 | perf_ctl.lo = (msr.lo & 0x3f0000) >> 8; | |
34 | ||
35 | /* | |
36 | * Set guaranteed vid [21:16] from IACORE_VIDS to bits [7:0] of | |
37 | * the PERF_CTL | |
38 | */ | |
39 | msr = msr_read(MSR_IACORE_VIDS); | |
40 | perf_ctl.lo |= (msr.lo & 0x7f0000) >> 16; | |
41 | perf_ctl.hi = 0; | |
42 | ||
43 | msr_write(MSR_IA32_PERF_CTL, perf_ctl); | |
44 | } | |
45 | ||
46 | static int cpu_x86_baytrail_probe(struct udevice *dev) | |
47 | { | |
48 | debug("Init BayTrail core\n"); | |
49 | ||
50 | /* | |
51 | * On BayTrail the turbo disable bit is actually scoped at the | |
52 | * building-block level, not package. For non-BSP cores that are | |
53 | * within a building block, enable turbo. The cores within the BSP's | |
54 | * building block will just see it already enabled and move on. | |
55 | */ | |
56 | if (lapicid()) | |
57 | turbo_enable(); | |
58 | ||
59 | /* Dynamic L2 shrink enable and threshold */ | |
60 | msr_clrsetbits_64(MSR_PMG_CST_CONFIG_CONTROL, 0x3f000f, 0xe0008), | |
61 | ||
62 | /* Disable C1E */ | |
63 | msr_clrsetbits_64(MSR_POWER_CTL, 2, 0); | |
64 | msr_setbits_64(MSR_POWER_MISC, 0x44); | |
65 | ||
66 | /* Set this core to max frequency ratio */ | |
67 | set_max_freq(); | |
68 | ||
69 | return 0; | |
70 | } | |
71 | ||
72 | static unsigned bus_freq(void) | |
73 | { | |
74 | msr_t clk_info = msr_read(MSR_BSEL_CR_OVERCLOCK_CONTROL); | |
75 | switch (clk_info.lo & 0x3) { | |
76 | case 0: | |
77 | return 83333333; | |
78 | case 1: | |
79 | return 100000000; | |
80 | case 2: | |
81 | return 133333333; | |
82 | case 3: | |
83 | return 116666666; | |
84 | default: | |
85 | return 0; | |
86 | } | |
87 | } | |
88 | ||
89 | static unsigned long tsc_freq(void) | |
90 | { | |
91 | msr_t platform_info; | |
92 | ulong bclk = bus_freq(); | |
93 | ||
94 | if (!bclk) | |
95 | return 0; | |
96 | ||
97 | platform_info = msr_read(MSR_PLATFORM_INFO); | |
98 | ||
99 | return bclk * ((platform_info.lo >> 8) & 0xff); | |
100 | } | |
101 | ||
102 | static int baytrail_get_info(struct udevice *dev, struct cpu_info *info) | |
103 | { | |
104 | info->cpu_freq = tsc_freq(); | |
105 | info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU; | |
106 | ||
107 | return 0; | |
108 | } | |
109 | ||
6e6f4ce4 BM |
110 | static int baytrail_get_count(struct udevice *dev) |
111 | { | |
112 | int ecx = 0; | |
113 | ||
114 | /* | |
115 | * Use the algorithm described in Intel 64 and IA-32 Architectures | |
116 | * Software Developer's Manual Volume 3 (3A, 3B & 3C): System | |
117 | * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping | |
118 | * of CPUID Extended Topology Leaf. | |
119 | */ | |
120 | while (1) { | |
121 | struct cpuid_result leaf_b; | |
122 | ||
123 | leaf_b = cpuid_ext(0xb, ecx); | |
124 | ||
125 | /* | |
126 | * Bay Trail doesn't have hyperthreading so just determine the | |
127 | * number of cores by from level type (ecx[15:8] == * 2) | |
128 | */ | |
129 | if ((leaf_b.ecx & 0xff00) == 0x0200) | |
130 | return leaf_b.ebx & 0xffff; | |
131 | ||
132 | ecx++; | |
133 | } | |
134 | ||
135 | return 0; | |
136 | } | |
137 | ||
ede97093 | 138 | static const struct cpu_ops cpu_x86_baytrail_ops = { |
be3f06bc | 139 | .get_desc = cpu_x86_get_desc, |
ede97093 | 140 | .get_info = baytrail_get_info, |
6e6f4ce4 | 141 | .get_count = baytrail_get_count, |
ede97093 SG |
142 | }; |
143 | ||
144 | static const struct udevice_id cpu_x86_baytrail_ids[] = { | |
145 | { .compatible = "intel,baytrail-cpu" }, | |
146 | { } | |
147 | }; | |
148 | ||
149 | U_BOOT_DRIVER(cpu_x86_baytrail_drv) = { | |
150 | .name = "cpu_x86_baytrail", | |
151 | .id = UCLASS_CPU, | |
152 | .of_match = cpu_x86_baytrail_ids, | |
be3f06bc | 153 | .bind = cpu_x86_bind, |
ede97093 SG |
154 | .probe = cpu_x86_baytrail_probe, |
155 | .ops = &cpu_x86_baytrail_ops, | |
156 | }; |