xref: /openbmc/u-boot/arch/x86/cpu/baytrail/cpu.c (revision 6e6f4ce4)
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 };
157