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