blob: 6a242d7c8bfe857ceca25d189b5d7638939f55e9 [file] [log] [blame]
Simon Glass0b36ecd2014-11-12 22:42:07 -07001/*
2 * Copyright (c) 2014 Google, Inc
3 * (C) Copyright 2008
4 * Graeme Russ, graeme.russ@gmail.com.
5 *
6 * Some portions from coreboot src/mainboard/google/link/romstage.c
7 * Copyright (C) 2007-2010 coresystems GmbH
8 * Copyright (C) 2011 Google Inc.
9 *
10 * SPDX-License-Identifier: GPL-2.0
11 */
12
13#include <common.h>
Simon Glassdcfac352014-11-12 22:42:15 -070014#include <errno.h>
15#include <fdtdec.h>
Simon Glass0b36ecd2014-11-12 22:42:07 -070016#include <asm/cpu.h>
Simon Glassf226c412014-11-12 22:42:19 -070017#include <asm/io.h>
18#include <asm/msr.h>
19#include <asm/mtrr.h>
Simon Glass3274ae02014-11-12 22:42:13 -070020#include <asm/pci.h>
Simon Glass98f139b2014-11-12 22:42:10 -070021#include <asm/post.h>
Simon Glass0b36ecd2014-11-12 22:42:07 -070022#include <asm/processor.h>
Simon Glassf226c412014-11-12 22:42:19 -070023#include <asm/arch/model_206ax.h>
Simon Glassdcfac352014-11-12 22:42:15 -070024#include <asm/arch/pch.h>
Simon Glass0b36ecd2014-11-12 22:42:07 -070025
26DECLARE_GLOBAL_DATA_PTR;
27
Simon Glassf226c412014-11-12 22:42:19 -070028static void enable_port80_on_lpc(struct pci_controller *hose, pci_dev_t dev)
29{
30 /* Enable port 80 POST on LPC */
31 pci_hose_write_config_dword(hose, dev, PCH_RCBA_BASE, DEFAULT_RCBA | 1);
32 clrbits_le32(RCB_REG(GCS), 4);
33}
34
35/*
36 * Enable Prefetching and Caching.
37 */
38static void enable_spi_prefetch(struct pci_controller *hose, pci_dev_t dev)
39{
40 u8 reg8;
41
42 pci_hose_read_config_byte(hose, dev, 0xdc, &reg8);
43 reg8 &= ~(3 << 2);
44 reg8 |= (2 << 2); /* Prefetching and Caching Enabled */
45 pci_hose_write_config_byte(hose, dev, 0xdc, reg8);
46}
47
48static void set_var_mtrr(
49 unsigned reg, unsigned base, unsigned size, unsigned type)
50
51{
52 /* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
53 /* FIXME: It only support 4G less range */
54 wrmsr(MTRRphysBase_MSR(reg), base | type, 0);
55 wrmsr(MTRRphysMask_MSR(reg), ~(size - 1) | MTRRphysMaskValid,
56 (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1);
57}
58
59static void enable_rom_caching(void)
60{
61 disable_caches();
62 set_var_mtrr(1, 0xffc00000, 4 << 20, MTRR_TYPE_WRPROT);
63 enable_caches();
64
65 /* Enable Variable MTRRs */
66 wrmsr(MTRRdefType_MSR, 0x800, 0);
67}
68
69static int set_flex_ratio_to_tdp_nominal(void)
70{
71 msr_t flex_ratio, msr;
72 u8 nominal_ratio;
73
74 /* Minimum CPU revision for configurable TDP support */
75 if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
76 return -EINVAL;
77
78 /* Check for Flex Ratio support */
79 flex_ratio = msr_read(MSR_FLEX_RATIO);
80 if (!(flex_ratio.lo & FLEX_RATIO_EN))
81 return -EINVAL;
82
83 /* Check for >0 configurable TDPs */
84 msr = msr_read(MSR_PLATFORM_INFO);
85 if (((msr.hi >> 1) & 3) == 0)
86 return -EINVAL;
87
88 /* Use nominal TDP ratio for flex ratio */
89 msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
90 nominal_ratio = msr.lo & 0xff;
91
92 /* See if flex ratio is already set to nominal TDP ratio */
93 if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
94 return 0;
95
96 /* Set flex ratio to nominal TDP ratio */
97 flex_ratio.lo &= ~0xff00;
98 flex_ratio.lo |= nominal_ratio << 8;
99 flex_ratio.lo |= FLEX_RATIO_LOCK;
100 msr_write(MSR_FLEX_RATIO, flex_ratio);
101
102 /* Set flex ratio in soft reset data register bits 11:6 */
103 clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
104 (nominal_ratio & 0x3f) << 6);
105
106 /* Set soft reset control to use register value */
107 setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
108
109 /* Issue warm reset, will be "CPU only" due to soft reset data */
110 outb(0x0, PORT_RESET);
111 outb(0x6, PORT_RESET);
112 cpu_hlt();
113
114 /* Not reached */
115 return -EINVAL;
116}
117
118static void set_spi_speed(void)
119{
120 u32 fdod;
121
122 /* Observe SPI Descriptor Component Section 0 */
123 writel(0x1000, RCB_REG(SPI_DESC_COMP0));
124
125 /* Extract the1 Write/Erase SPI Frequency from descriptor */
126 fdod = readl(RCB_REG(SPI_FREQ_WR_ERA));
127 fdod >>= 24;
128 fdod &= 7;
129
130 /* Set Software Sequence frequency to match */
131 clrsetbits_8(RCB_REG(SPI_FREQ_SWSEQ), 7, fdod);
132}
133
Simon Glass0b36ecd2014-11-12 22:42:07 -0700134int arch_cpu_init(void)
135{
Simon Glassdcfac352014-11-12 22:42:15 -0700136 const void *blob = gd->fdt_blob;
Simon Glass3274ae02014-11-12 22:42:13 -0700137 struct pci_controller *hose;
Simon Glassdcfac352014-11-12 22:42:15 -0700138 int node;
Simon Glass0b36ecd2014-11-12 22:42:07 -0700139 int ret;
140
Simon Glass98f139b2014-11-12 22:42:10 -0700141 post_code(POST_CPU_INIT);
Simon Glass0b36ecd2014-11-12 22:42:07 -0700142 timer_set_base(rdtsc());
143
144 ret = x86_cpu_init_f();
145 if (ret)
146 return ret;
147
Simon Glass3274ae02014-11-12 22:42:13 -0700148 ret = pci_early_init_hose(&hose);
149 if (ret)
150 return ret;
151
Simon Glassdcfac352014-11-12 22:42:15 -0700152 node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_LPC);
153 if (node < 0)
154 return -ENOENT;
155 ret = lpc_early_init(gd->fdt_blob, node, PCH_LPC_DEV);
156 if (ret)
157 return ret;
158
Simon Glassf226c412014-11-12 22:42:19 -0700159 enable_spi_prefetch(hose, PCH_LPC_DEV);
160
161 /* This is already done in start.S, but let's do it in C */
162 enable_port80_on_lpc(hose, PCH_LPC_DEV);
163
164 /* already done in car.S */
165 if (false)
166 enable_rom_caching();
167
168 set_spi_speed();
169
170 /*
171 * We should do as little as possible before the serial console is
172 * up. Perhaps this should move to later. Our next lot of init
173 * happens in print_cpuinfo() when we have a console
174 */
175 ret = set_flex_ratio_to_tdp_nominal();
176 if (ret)
177 return ret;
178
Simon Glass0b36ecd2014-11-12 22:42:07 -0700179 return 0;
180}
181
Simon Glass367077a2014-11-12 22:42:20 -0700182static int report_bist_failure(void)
183{
184 if (gd->arch.bist != 0) {
185 printf("BIST failed: %08x\n", gd->arch.bist);
186 return -EFAULT;
187 }
188
189 return 0;
190}
191
Simon Glass0b36ecd2014-11-12 22:42:07 -0700192int print_cpuinfo(void)
193{
194 char processor_name[CPU_MAX_NAME_LEN];
195 const char *name;
Simon Glass367077a2014-11-12 22:42:20 -0700196 int ret;
197
198 /* Halt if there was a built in self test failure */
199 ret = report_bist_failure();
200 if (ret)
201 return ret;
Simon Glass0b36ecd2014-11-12 22:42:07 -0700202
203 /* Print processor name */
204 name = cpu_get_name(processor_name);
205 printf("CPU: %s\n", name);
206
207 return 0;
208}