Home | History | Annotate | Download | only in baytrail
      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 
     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  */
     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 
     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 
     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 
    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 
    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 
    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 
    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 };
    207