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