]> git.sur5r.net Git - u-boot/blob - arch/x86/cpu/baytrail/cpu.c
x86: Move MP initialization codes into a common place
[u-boot] / arch / x86 / cpu / baytrail / cpu.c
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>
13 #include <asm/cpu_x86.h>
14 #include <asm/lapic.h>
15 #include <asm/msr.h>
16 #include <asm/turbo.h>
17
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
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
138 static const struct cpu_ops cpu_x86_baytrail_ops = {
139         .get_desc       = cpu_x86_get_desc,
140         .get_info       = baytrail_get_info,
141         .get_count      = baytrail_get_count,
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,
153         .bind           = cpu_x86_bind,
154         .probe          = cpu_x86_baytrail_probe,
155         .ops            = &cpu_x86_baytrail_ops,
156 };