2 * Copyright (c) 2014 Google, Inc
4 * Graeme Russ, graeme.russ@gmail.com.
6 * Some portions from coreboot src/mainboard/google/link/romstage.c
7 * Copyright (C) 2007-2010 coresystems GmbH
8 * Copyright (C) 2011 Google Inc.
10 * SPDX-License-Identifier: GPL-2.0
22 #include <asm/processor.h>
23 #include <asm/arch/model_206ax.h>
24 #include <asm/arch/microcode.h>
25 #include <asm/arch/pch.h>
27 DECLARE_GLOBAL_DATA_PTR;
29 static void enable_port80_on_lpc(struct pci_controller *hose, pci_dev_t dev)
31 /* Enable port 80 POST on LPC */
32 pci_hose_write_config_dword(hose, dev, PCH_RCBA_BASE, DEFAULT_RCBA | 1);
33 clrbits_le32(RCB_REG(GCS), 4);
37 * Enable Prefetching and Caching.
39 static void enable_spi_prefetch(struct pci_controller *hose, pci_dev_t dev)
43 pci_hose_read_config_byte(hose, dev, 0xdc, ®8);
45 reg8 |= (2 << 2); /* Prefetching and Caching Enabled */
46 pci_hose_write_config_byte(hose, dev, 0xdc, reg8);
49 static void set_var_mtrr(
50 unsigned reg, unsigned base, unsigned size, unsigned type)
53 /* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
54 /* FIXME: It only support 4G less range */
55 wrmsr(MTRRphysBase_MSR(reg), base | type, 0);
56 wrmsr(MTRRphysMask_MSR(reg), ~(size - 1) | MTRRphysMaskValid,
57 (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1);
60 static void enable_rom_caching(void)
63 set_var_mtrr(1, 0xffc00000, 4 << 20, MTRR_TYPE_WRPROT);
66 /* Enable Variable MTRRs */
67 wrmsr(MTRRdefType_MSR, 0x800, 0);
70 static int set_flex_ratio_to_tdp_nominal(void)
72 msr_t flex_ratio, msr;
75 /* Minimum CPU revision for configurable TDP support */
76 if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
79 /* Check for Flex Ratio support */
80 flex_ratio = msr_read(MSR_FLEX_RATIO);
81 if (!(flex_ratio.lo & FLEX_RATIO_EN))
84 /* Check for >0 configurable TDPs */
85 msr = msr_read(MSR_PLATFORM_INFO);
86 if (((msr.hi >> 1) & 3) == 0)
89 /* Use nominal TDP ratio for flex ratio */
90 msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
91 nominal_ratio = msr.lo & 0xff;
93 /* See if flex ratio is already set to nominal TDP ratio */
94 if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
97 /* Set flex ratio to nominal TDP ratio */
98 flex_ratio.lo &= ~0xff00;
99 flex_ratio.lo |= nominal_ratio << 8;
100 flex_ratio.lo |= FLEX_RATIO_LOCK;
101 msr_write(MSR_FLEX_RATIO, flex_ratio);
103 /* Set flex ratio in soft reset data register bits 11:6 */
104 clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
105 (nominal_ratio & 0x3f) << 6);
107 /* Set soft reset control to use register value */
108 setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
110 /* Issue warm reset, will be "CPU only" due to soft reset data */
111 outb(0x0, PORT_RESET);
112 outb(0x6, PORT_RESET);
119 static void set_spi_speed(void)
123 /* Observe SPI Descriptor Component Section 0 */
124 writel(0x1000, RCB_REG(SPI_DESC_COMP0));
126 /* Extract the1 Write/Erase SPI Frequency from descriptor */
127 fdod = readl(RCB_REG(SPI_FREQ_WR_ERA));
131 /* Set Software Sequence frequency to match */
132 clrsetbits_8(RCB_REG(SPI_FREQ_SWSEQ), 7, fdod);
135 int arch_cpu_init(void)
137 const void *blob = gd->fdt_blob;
138 struct pci_controller *hose;
142 post_code(POST_CPU_INIT);
143 timer_set_base(rdtsc());
145 ret = x86_cpu_init_f();
149 ret = pci_early_init_hose(&hose);
153 node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_LPC);
156 ret = lpc_early_init(gd->fdt_blob, node, PCH_LPC_DEV);
160 enable_spi_prefetch(hose, PCH_LPC_DEV);
162 /* This is already done in start.S, but let's do it in C */
163 enable_port80_on_lpc(hose, PCH_LPC_DEV);
165 /* already done in car.S */
167 enable_rom_caching();
172 * We should do as little as possible before the serial console is
173 * up. Perhaps this should move to later. Our next lot of init
174 * happens in print_cpuinfo() when we have a console
176 ret = set_flex_ratio_to_tdp_nominal();
183 static int report_bist_failure(void)
185 if (gd->arch.bist != 0) {
186 printf("BIST failed: %08x\n", gd->arch.bist);
193 int print_cpuinfo(void)
195 char processor_name[CPU_MAX_NAME_LEN];
199 /* Halt if there was a built in self test failure */
200 ret = report_bist_failure();
204 ret = microcode_update_intel();
205 if (ret && ret != -ENOENT && ret != -EEXIST)
208 /* Print processor name */
209 name = cpu_get_name(processor_name);
210 printf("CPU: %s\n", name);