blob: 2a15fc02205c7562bc6138a6f077f2db2363bd1a [file] [log] [blame]
Simon Glass8ef07572014-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
Simon Glass8e0df062014-11-12 22:42:23 -07007 * and src/cpu/intel/model_206ax/bootblock.c
Simon Glass8ef07572014-11-12 22:42:07 -07008 * Copyright (C) 2007-2010 coresystems GmbH
9 * Copyright (C) 2011 Google Inc.
10 *
11 * SPDX-License-Identifier: GPL-2.0
12 */
13
14#include <common.h>
Simon Glassaad78d22015-03-05 12:25:33 -070015#include <dm.h>
Simon Glass2b605152014-11-12 22:42:15 -070016#include <errno.h>
17#include <fdtdec.h>
Simon Glass858361b2016-01-17 16:11:13 -070018#include <pch.h>
Simon Glass8ef07572014-11-12 22:42:07 -070019#include <asm/cpu.h>
Simon Glassf5fbbe92014-11-12 22:42:19 -070020#include <asm/io.h>
Simon Glass3eafce02014-11-12 22:42:27 -070021#include <asm/lapic.h>
Simon Glassf5fbbe92014-11-12 22:42:19 -070022#include <asm/msr.h>
23#include <asm/mtrr.h>
Simon Glass6e5b12b2014-11-12 22:42:13 -070024#include <asm/pci.h>
Simon Glass70a09c62014-11-12 22:42:10 -070025#include <asm/post.h>
Simon Glass8ef07572014-11-12 22:42:07 -070026#include <asm/processor.h>
Simon Glassf5fbbe92014-11-12 22:42:19 -070027#include <asm/arch/model_206ax.h>
Simon Glass77f9b1f2014-11-12 22:42:21 -070028#include <asm/arch/microcode.h>
Simon Glass2b605152014-11-12 22:42:15 -070029#include <asm/arch/pch.h>
Simon Glass8e0df062014-11-12 22:42:23 -070030#include <asm/arch/sandybridge.h>
Simon Glass8ef07572014-11-12 22:42:07 -070031
32DECLARE_GLOBAL_DATA_PTR;
33
Simon Glassf5fbbe92014-11-12 22:42:19 -070034static int set_flex_ratio_to_tdp_nominal(void)
35{
36 msr_t flex_ratio, msr;
37 u8 nominal_ratio;
38
39 /* Minimum CPU revision for configurable TDP support */
40 if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
41 return -EINVAL;
42
43 /* Check for Flex Ratio support */
44 flex_ratio = msr_read(MSR_FLEX_RATIO);
45 if (!(flex_ratio.lo & FLEX_RATIO_EN))
46 return -EINVAL;
47
48 /* Check for >0 configurable TDPs */
49 msr = msr_read(MSR_PLATFORM_INFO);
50 if (((msr.hi >> 1) & 3) == 0)
51 return -EINVAL;
52
53 /* Use nominal TDP ratio for flex ratio */
54 msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
55 nominal_ratio = msr.lo & 0xff;
56
57 /* See if flex ratio is already set to nominal TDP ratio */
58 if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
59 return 0;
60
61 /* Set flex ratio to nominal TDP ratio */
62 flex_ratio.lo &= ~0xff00;
63 flex_ratio.lo |= nominal_ratio << 8;
64 flex_ratio.lo |= FLEX_RATIO_LOCK;
65 msr_write(MSR_FLEX_RATIO, flex_ratio);
66
67 /* Set flex ratio in soft reset data register bits 11:6 */
68 clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
69 (nominal_ratio & 0x3f) << 6);
70
71 /* Set soft reset control to use register value */
72 setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
73
74 /* Issue warm reset, will be "CPU only" due to soft reset data */
75 outb(0x0, PORT_RESET);
Simon Glass5021c812015-04-28 20:11:30 -060076 outb(SYS_RST | RST_CPU, PORT_RESET);
Simon Glassf5fbbe92014-11-12 22:42:19 -070077 cpu_hlt();
78
79 /* Not reached */
80 return -EINVAL;
81}
82
Simon Glass8ef07572014-11-12 22:42:07 -070083int arch_cpu_init(void)
84{
Simon Glass161d2e42015-03-05 12:25:17 -070085 post_code(POST_CPU_INIT);
Simon Glass161d2e42015-03-05 12:25:17 -070086
87 return x86_cpu_init_f();
88}
89
90int arch_cpu_init_dm(void)
91{
Simon Glass6e5b12b2014-11-12 22:42:13 -070092 struct pci_controller *hose;
Simon Glass4acc83d2016-01-17 16:11:10 -070093 struct udevice *bus, *dev;
Simon Glass8ef07572014-11-12 22:42:07 -070094 int ret;
95
Simon Glassaad78d22015-03-05 12:25:33 -070096 post_code(0x70);
97 ret = uclass_get_device(UCLASS_PCI, 0, &bus);
98 post_code(0x71);
Simon Glass8ef07572014-11-12 22:42:07 -070099 if (ret)
100 return ret;
Simon Glassaad78d22015-03-05 12:25:33 -0700101 post_code(0x72);
102 hose = dev_get_uclass_priv(bus);
Simon Glass8ef07572014-11-12 22:42:07 -0700103
Simon Glassaad78d22015-03-05 12:25:33 -0700104 /* TODO(sjg@chromium.org): Get rid of gd->hose */
105 gd->hose = hose;
Simon Glass6e5b12b2014-11-12 22:42:13 -0700106
Simon Glass4acc83d2016-01-17 16:11:10 -0700107 ret = uclass_first_device(UCLASS_LPC, &dev);
108 if (!dev)
109 return -ENODEV;
110
Simon Glassf5fbbe92014-11-12 22:42:19 -0700111 /*
112 * We should do as little as possible before the serial console is
113 * up. Perhaps this should move to later. Our next lot of init
114 * happens in print_cpuinfo() when we have a console
115 */
116 ret = set_flex_ratio_to_tdp_nominal();
117 if (ret)
118 return ret;
119
Simon Glass8ef07572014-11-12 22:42:07 -0700120 return 0;
121}
122
Simon Glass8e0df062014-11-12 22:42:23 -0700123static int enable_smbus(void)
124{
125 pci_dev_t dev;
126 uint16_t value;
127
128 /* Set the SMBus device statically. */
129 dev = PCI_BDF(0x0, 0x1f, 0x3);
130
131 /* Check to make sure we've got the right device. */
Simon Glass31f57c22015-03-05 12:25:15 -0700132 value = x86_pci_read_config16(dev, 0x0);
Simon Glass8e0df062014-11-12 22:42:23 -0700133 if (value != 0x8086) {
134 printf("SMBus controller not found\n");
135 return -ENOSYS;
136 }
137
138 /* Set SMBus I/O base. */
Simon Glass31f57c22015-03-05 12:25:15 -0700139 x86_pci_write_config32(dev, SMB_BASE,
140 SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO);
Simon Glass8e0df062014-11-12 22:42:23 -0700141
142 /* Set SMBus enable. */
Simon Glass31f57c22015-03-05 12:25:15 -0700143 x86_pci_write_config8(dev, HOSTC, HST_EN);
Simon Glass8e0df062014-11-12 22:42:23 -0700144
145 /* Set SMBus I/O space enable. */
Simon Glass31f57c22015-03-05 12:25:15 -0700146 x86_pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO);
Simon Glass8e0df062014-11-12 22:42:23 -0700147
148 /* Disable interrupt generation. */
149 outb(0, SMBUS_IO_BASE + SMBHSTCTL);
150
151 /* Clear any lingering errors, so transactions can run. */
152 outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
153 debug("SMBus controller enabled\n");
154
155 return 0;
156}
157
158#define PCH_EHCI0_TEMP_BAR0 0xe8000000
159#define PCH_EHCI1_TEMP_BAR0 0xe8000400
160#define PCH_XHCI_TEMP_BAR0 0xe8001000
161
162/*
163 * Setup USB controller MMIO BAR to prevent the reference code from
164 * resetting the controller.
165 *
166 * The BAR will be re-assigned during device enumeration so these are only
167 * temporary.
168 *
169 * This is used to speed up the resume path.
170 */
171static void enable_usb_bar(void)
172{
173 pci_dev_t usb0 = PCH_EHCI1_DEV;
174 pci_dev_t usb1 = PCH_EHCI2_DEV;
175 pci_dev_t usb3 = PCH_XHCI_DEV;
176 u32 cmd;
177
178 /* USB Controller 1 */
Simon Glass31f57c22015-03-05 12:25:15 -0700179 x86_pci_write_config32(usb0, PCI_BASE_ADDRESS_0,
180 PCH_EHCI0_TEMP_BAR0);
181 cmd = x86_pci_read_config32(usb0, PCI_COMMAND);
Simon Glass8e0df062014-11-12 22:42:23 -0700182 cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
Simon Glass31f57c22015-03-05 12:25:15 -0700183 x86_pci_write_config32(usb0, PCI_COMMAND, cmd);
Simon Glass8e0df062014-11-12 22:42:23 -0700184
185 /* USB Controller 1 */
Simon Glass31f57c22015-03-05 12:25:15 -0700186 x86_pci_write_config32(usb1, PCI_BASE_ADDRESS_0,
187 PCH_EHCI1_TEMP_BAR0);
188 cmd = x86_pci_read_config32(usb1, PCI_COMMAND);
Simon Glass8e0df062014-11-12 22:42:23 -0700189 cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
Simon Glass31f57c22015-03-05 12:25:15 -0700190 x86_pci_write_config32(usb1, PCI_COMMAND, cmd);
Simon Glass8e0df062014-11-12 22:42:23 -0700191
192 /* USB3 Controller */
Simon Glass31f57c22015-03-05 12:25:15 -0700193 x86_pci_write_config32(usb3, PCI_BASE_ADDRESS_0,
194 PCH_XHCI_TEMP_BAR0);
195 cmd = x86_pci_read_config32(usb3, PCI_COMMAND);
Simon Glass8e0df062014-11-12 22:42:23 -0700196 cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
Simon Glass31f57c22015-03-05 12:25:15 -0700197 x86_pci_write_config32(usb3, PCI_COMMAND, cmd);
Simon Glass8e0df062014-11-12 22:42:23 -0700198}
199
Simon Glass94060ff2014-11-12 22:42:20 -0700200static int report_bist_failure(void)
201{
202 if (gd->arch.bist != 0) {
Bin Meng95a5a472014-12-12 21:05:30 +0800203 post_code(POST_BIST_FAILURE);
Simon Glass94060ff2014-11-12 22:42:20 -0700204 printf("BIST failed: %08x\n", gd->arch.bist);
205 return -EFAULT;
206 }
207
208 return 0;
209}
210
Simon Glass8ef07572014-11-12 22:42:07 -0700211int print_cpuinfo(void)
212{
Simon Glass8e0df062014-11-12 22:42:23 -0700213 enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE;
Simon Glass8ef07572014-11-12 22:42:07 -0700214 char processor_name[CPU_MAX_NAME_LEN];
Simon Glass858361b2016-01-17 16:11:13 -0700215 struct udevice *dev;
Simon Glass8ef07572014-11-12 22:42:07 -0700216 const char *name;
Simon Glass8e0df062014-11-12 22:42:23 -0700217 uint32_t pm1_cnt;
218 uint16_t pm1_sts;
Simon Glass94060ff2014-11-12 22:42:20 -0700219 int ret;
220
221 /* Halt if there was a built in self test failure */
222 ret = report_bist_failure();
223 if (ret)
224 return ret;
Simon Glass8ef07572014-11-12 22:42:07 -0700225
Simon Glass3eafce02014-11-12 22:42:27 -0700226 enable_lapic();
227
Simon Glass77f9b1f2014-11-12 22:42:21 -0700228 ret = microcode_update_intel();
Simon Glassc72f74e2015-01-01 16:18:14 -0700229 if (ret)
Simon Glass77f9b1f2014-11-12 22:42:21 -0700230 return ret;
231
Simon Glass8e0df062014-11-12 22:42:23 -0700232 /* Enable upper 128bytes of CMOS */
233 writel(1 << 2, RCB_REG(RC));
234
235 /* TODO: cmos_post_init() */
236 if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) {
237 debug("soft reset detected\n");
238 boot_mode = PEI_BOOT_SOFT_RESET;
239
240 /* System is not happy after keyboard reset... */
241 debug("Issuing CF9 warm reset\n");
Simon Glass5021c812015-04-28 20:11:30 -0600242 reset_cpu(0);
Simon Glass8e0df062014-11-12 22:42:23 -0700243 }
244
245 /* Early chipset init required before RAM init can work */
Simon Glass858361b2016-01-17 16:11:13 -0700246 ret = uclass_first_device(UCLASS_PCH, &dev);
247 if (ret)
248 return ret;
249 if (!dev)
250 return -ENODEV;
251
Simon Glass8e0df062014-11-12 22:42:23 -0700252 sandybridge_early_init(SANDYBRIDGE_MOBILE);
253
254 /* Check PM1_STS[15] to see if we are waking from Sx */
255 pm1_sts = inw(DEFAULT_PMBASE + PM1_STS);
256
257 /* Read PM1_CNT[12:10] to determine which Sx state */
258 pm1_cnt = inl(DEFAULT_PMBASE + PM1_CNT);
259
260 if ((pm1_sts & WAK_STS) && ((pm1_cnt >> 10) & 7) == 5) {
Simon Glass8e0df062014-11-12 22:42:23 -0700261 debug("Resume from S3 detected, but disabled.\n");
Simon Glass8e0df062014-11-12 22:42:23 -0700262 } else {
263 /*
264 * TODO: An indication of life might be possible here (e.g.
265 * keyboard light)
266 */
267 }
268 post_code(POST_EARLY_INIT);
269
270 /* Enable SPD ROMs and DDR-III DRAM */
271 ret = enable_smbus();
272 if (ret)
273 return ret;
274
275 /* Prepare USB controller early in S3 resume */
276 if (boot_mode == PEI_BOOT_RESUME)
277 enable_usb_bar();
278
279 gd->arch.pei_boot_mode = boot_mode;
280
281 /* TODO: Move this to the board or driver */
Simon Glass31f57c22015-03-05 12:25:15 -0700282 x86_pci_write_config32(PCH_LPC_DEV, GPIO_BASE, DEFAULT_GPIOBASE | 1);
283 x86_pci_write_config32(PCH_LPC_DEV, GPIO_CNTL, 0x10);
Simon Glass8e0df062014-11-12 22:42:23 -0700284
Simon Glass8ef07572014-11-12 22:42:07 -0700285 /* Print processor name */
286 name = cpu_get_name(processor_name);
287 printf("CPU: %s\n", name);
288
Simon Glass8e0df062014-11-12 22:42:23 -0700289 post_code(POST_CPU_INFO);
290
Simon Glass8ef07572014-11-12 22:42:07 -0700291 return 0;
292}
Simon Glass7b952522015-10-18 19:51:27 -0600293
294void board_debug_uart_init(void)
295{
296 /* This enables the debug UART */
297 pci_x86_write_config(NULL, PCH_LPC_DEV, LPC_EN, COMA_LPC_EN,
298 PCI_SIZE_16);
299}