xref: /openbmc/u-boot/arch/x86/cpu/baytrail/cpu.c (revision 1d6edcbf)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2015 Google, Inc
4  *
5  * Based on code from coreboot
6  */
7 
8 #include <common.h>
9 #include <cpu.h>
10 #include <dm.h>
11 #include <pci.h>
12 #include <asm/cpu.h>
13 #include <asm/cpu_x86.h>
14 #include <asm/io.h>
15 #include <asm/lapic.h>
16 #include <asm/msr.h>
17 #include <asm/turbo.h>
18 
19 #define BYT_PRV_CLK			0x800
20 #define BYT_PRV_CLK_EN			(1 << 0)
21 #define BYT_PRV_CLK_M_VAL_SHIFT		1
22 #define BYT_PRV_CLK_N_VAL_SHIFT		16
23 #define BYT_PRV_CLK_UPDATE		(1 << 31)
24 
hsuart_clock_set(void * base)25 static void hsuart_clock_set(void *base)
26 {
27 	u32 m, n, reg;
28 
29 	/*
30 	 * Configure the BayTrail UART clock for the internal HS UARTs
31 	 * (PCI devices) to 58982400 Hz
32 	 */
33 	m = 0x2400;
34 	n = 0x3d09;
35 	reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
36 	writel(reg, base + BYT_PRV_CLK);
37 	reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
38 	writel(reg, base + BYT_PRV_CLK);
39 }
40 
41 /*
42  * Configure the internal clock of both SIO HS-UARTs, if they are enabled
43  * via FSP
44  */
arch_cpu_init_dm(void)45 int arch_cpu_init_dm(void)
46 {
47 	struct udevice *dev;
48 	void *base;
49 	int ret;
50 	int i;
51 
52 	/* Loop over the 2 HS-UARTs */
53 	for (i = 0; i < 2; i++) {
54 		ret = dm_pci_bus_find_bdf(PCI_BDF(0, 0x1e, 3 + i), &dev);
55 		if (!ret) {
56 			base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0,
57 					      PCI_REGION_MEM);
58 			hsuart_clock_set(base);
59 		}
60 	}
61 
62 	return 0;
63 }
64 
set_max_freq(void)65 static void set_max_freq(void)
66 {
67 	msr_t perf_ctl;
68 	msr_t msr;
69 
70 	/* Enable speed step */
71 	msr = msr_read(MSR_IA32_MISC_ENABLES);
72 	msr.lo |= (1 << 16);
73 	msr_write(MSR_IA32_MISC_ENABLES, msr);
74 
75 	/*
76 	 * Set guaranteed ratio [21:16] from IACORE_RATIOS to bits [15:8] of
77 	 * the PERF_CTL
78 	 */
79 	msr = msr_read(MSR_IACORE_RATIOS);
80 	perf_ctl.lo = (msr.lo & 0x3f0000) >> 8;
81 
82 	/*
83 	 * Set guaranteed vid [22:16] from IACORE_VIDS to bits [7:0] of
84 	 * the PERF_CTL
85 	 */
86 	msr = msr_read(MSR_IACORE_VIDS);
87 	perf_ctl.lo |= (msr.lo & 0x7f0000) >> 16;
88 	perf_ctl.hi = 0;
89 
90 	msr_write(MSR_IA32_PERF_CTL, perf_ctl);
91 }
92 
cpu_x86_baytrail_probe(struct udevice * dev)93 static int cpu_x86_baytrail_probe(struct udevice *dev)
94 {
95 	if (!ll_boot_init())
96 		return 0;
97 	debug("Init BayTrail core\n");
98 
99 	/*
100 	 * On BayTrail the turbo disable bit is actually scoped at the
101 	 * building-block level, not package. For non-BSP cores that are
102 	 * within a building block, enable turbo. The cores within the BSP's
103 	 * building block will just see it already enabled and move on.
104 	 */
105 	if (lapicid())
106 		turbo_enable();
107 
108 	/* Dynamic L2 shrink enable and threshold */
109 	msr_clrsetbits_64(MSR_PMG_CST_CONFIG_CONTROL, 0x3f000f, 0xe0008),
110 
111 	/* Disable C1E */
112 	msr_clrsetbits_64(MSR_POWER_CTL, 2, 0);
113 	msr_setbits_64(MSR_POWER_MISC, 0x44);
114 
115 	/* Set this core to max frequency ratio */
116 	set_max_freq();
117 
118 	return 0;
119 }
120 
bus_freq(void)121 static unsigned bus_freq(void)
122 {
123 	msr_t clk_info = msr_read(MSR_BSEL_CR_OVERCLOCK_CONTROL);
124 	switch (clk_info.lo & 0x3) {
125 	case 0:
126 		return 83333333;
127 	case 1:
128 		return 100000000;
129 	case 2:
130 		return 133333333;
131 	case 3:
132 		return 116666666;
133 	default:
134 		return 0;
135 	}
136 }
137 
tsc_freq(void)138 static unsigned long tsc_freq(void)
139 {
140 	msr_t platform_info;
141 	ulong bclk = bus_freq();
142 
143 	if (!bclk)
144 		return 0;
145 
146 	platform_info = msr_read(MSR_PLATFORM_INFO);
147 
148 	return bclk * ((platform_info.lo >> 8) & 0xff);
149 }
150 
baytrail_get_info(struct udevice * dev,struct cpu_info * info)151 static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
152 {
153 	info->cpu_freq = tsc_freq();
154 	info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU;
155 
156 	return 0;
157 }
158 
baytrail_get_count(struct udevice * dev)159 static int baytrail_get_count(struct udevice *dev)
160 {
161 	int ecx = 0;
162 
163 	/*
164 	 * Use the algorithm described in Intel 64 and IA-32 Architectures
165 	 * Software Developer's Manual Volume 3 (3A, 3B & 3C): System
166 	 * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
167 	 * of CPUID Extended Topology Leaf.
168 	 */
169 	while (1) {
170 		struct cpuid_result leaf_b;
171 
172 		leaf_b = cpuid_ext(0xb, ecx);
173 
174 		/*
175 		 * Bay Trail doesn't have hyperthreading so just determine the
176 		 * number of cores by from level type (ecx[15:8] == * 2)
177 		 */
178 		if ((leaf_b.ecx & 0xff00) == 0x0200)
179 			return leaf_b.ebx & 0xffff;
180 
181 		ecx++;
182 	}
183 
184 	return 0;
185 }
186 
187 static const struct cpu_ops cpu_x86_baytrail_ops = {
188 	.get_desc	= cpu_x86_get_desc,
189 	.get_info	= baytrail_get_info,
190 	.get_count	= baytrail_get_count,
191 	.get_vendor	= cpu_x86_get_vendor,
192 };
193 
194 static const struct udevice_id cpu_x86_baytrail_ids[] = {
195 	{ .compatible = "intel,baytrail-cpu" },
196 	{ }
197 };
198 
199 U_BOOT_DRIVER(cpu_x86_baytrail_drv) = {
200 	.name		= "cpu_x86_baytrail",
201 	.id		= UCLASS_CPU,
202 	.of_match	= cpu_x86_baytrail_ids,
203 	.bind		= cpu_x86_bind,
204 	.probe		= cpu_x86_baytrail_probe,
205 	.ops		= &cpu_x86_baytrail_ops,
206 	.flags		= DM_FLAG_PRE_RELOC,
207 };
208