]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/x86/cpu/baytrail/cpu.c
x86: baytrail: Support operation as an EFI payload
[karo-tx-uboot.git] / 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         if (!ll_boot_init())
49                 return 0;
50         debug("Init BayTrail core\n");
51
52         /*
53          * On BayTrail the turbo disable bit is actually scoped at the
54          * building-block level, not package. For non-BSP cores that are
55          * within a building block, enable turbo. The cores within the BSP's
56          * building block will just see it already enabled and move on.
57          */
58         if (lapicid())
59                 turbo_enable();
60
61         /* Dynamic L2 shrink enable and threshold */
62         msr_clrsetbits_64(MSR_PMG_CST_CONFIG_CONTROL, 0x3f000f, 0xe0008),
63
64         /* Disable C1E */
65         msr_clrsetbits_64(MSR_POWER_CTL, 2, 0);
66         msr_setbits_64(MSR_POWER_MISC, 0x44);
67
68         /* Set this core to max frequency ratio */
69         set_max_freq();
70
71         return 0;
72 }
73
74 static unsigned bus_freq(void)
75 {
76         msr_t clk_info = msr_read(MSR_BSEL_CR_OVERCLOCK_CONTROL);
77         switch (clk_info.lo & 0x3) {
78         case 0:
79                 return 83333333;
80         case 1:
81                 return 100000000;
82         case 2:
83                 return 133333333;
84         case 3:
85                 return 116666666;
86         default:
87                 return 0;
88         }
89 }
90
91 static unsigned long tsc_freq(void)
92 {
93         msr_t platform_info;
94         ulong bclk = bus_freq();
95
96         if (!bclk)
97                 return 0;
98
99         platform_info = msr_read(MSR_PLATFORM_INFO);
100
101         return bclk * ((platform_info.lo >> 8) & 0xff);
102 }
103
104 static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
105 {
106         info->cpu_freq = tsc_freq();
107         info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU;
108
109         return 0;
110 }
111
112 static int baytrail_get_count(struct udevice *dev)
113 {
114         int ecx = 0;
115
116         /*
117          * Use the algorithm described in Intel 64 and IA-32 Architectures
118          * Software Developer's Manual Volume 3 (3A, 3B & 3C): System
119          * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
120          * of CPUID Extended Topology Leaf.
121          */
122         while (1) {
123                 struct cpuid_result leaf_b;
124
125                 leaf_b = cpuid_ext(0xb, ecx);
126
127                 /*
128                  * Bay Trail doesn't have hyperthreading so just determine the
129                  * number of cores by from level type (ecx[15:8] == * 2)
130                  */
131                 if ((leaf_b.ecx & 0xff00) == 0x0200)
132                         return leaf_b.ebx & 0xffff;
133
134                 ecx++;
135         }
136
137         return 0;
138 }
139
140 static const struct cpu_ops cpu_x86_baytrail_ops = {
141         .get_desc       = cpu_x86_get_desc,
142         .get_info       = baytrail_get_info,
143         .get_count      = baytrail_get_count,
144 };
145
146 static const struct udevice_id cpu_x86_baytrail_ids[] = {
147         { .compatible = "intel,baytrail-cpu" },
148         { }
149 };
150
151 U_BOOT_DRIVER(cpu_x86_baytrail_drv) = {
152         .name           = "cpu_x86_baytrail",
153         .id             = UCLASS_CPU,
154         .of_match       = cpu_x86_baytrail_ids,
155         .bind           = cpu_x86_bind,
156         .probe          = cpu_x86_baytrail_probe,
157         .ops            = &cpu_x86_baytrail_ops,
158 };