blob: 948833c02857e6d98de58e57232b3be156aed9b2 [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
Simon Glass30580fc2014-11-12 22:42:23 -07007 * and src/cpu/intel/model_206ax/bootblock.c
Simon Glass0b36ecd2014-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 Glasse0e7b362015-03-05 12:25:33 -070015#include <dm.h>
Simon Glassdcfac352014-11-12 22:42:15 -070016#include <errno.h>
17#include <fdtdec.h>
Simon Glassa7b1d952016-01-17 16:11:13 -070018#include <pch.h>
Simon Glass0b36ecd2014-11-12 22:42:07 -070019#include <asm/cpu.h>
Simon Glassf226c412014-11-12 22:42:19 -070020#include <asm/io.h>
Simon Glassd22f5c92014-11-12 22:42:27 -070021#include <asm/lapic.h>
Simon Glassf226c412014-11-12 22:42:19 -070022#include <asm/msr.h>
23#include <asm/mtrr.h>
Simon Glass3274ae02014-11-12 22:42:13 -070024#include <asm/pci.h>
Simon Glass98f139b2014-11-12 22:42:10 -070025#include <asm/post.h>
Simon Glass0b36ecd2014-11-12 22:42:07 -070026#include <asm/processor.h>
Simon Glassf226c412014-11-12 22:42:19 -070027#include <asm/arch/model_206ax.h>
Simon Glassf79d5382014-11-12 22:42:21 -070028#include <asm/arch/microcode.h>
Simon Glassdcfac352014-11-12 22:42:15 -070029#include <asm/arch/pch.h>
Simon Glass30580fc2014-11-12 22:42:23 -070030#include <asm/arch/sandybridge.h>
Simon Glass0b36ecd2014-11-12 22:42:07 -070031
32DECLARE_GLOBAL_DATA_PTR;
33
Simon Glassf226c412014-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 Glass1375e9a2015-04-28 20:11:30 -060076 outb(SYS_RST | RST_CPU, PORT_RESET);
Simon Glassf226c412014-11-12 22:42:19 -070077 cpu_hlt();
78
79 /* Not reached */
80 return -EINVAL;
81}
82
Simon Glass0b36ecd2014-11-12 22:42:07 -070083int arch_cpu_init(void)
84{
Simon Glass7567f462015-03-05 12:25:17 -070085 post_code(POST_CPU_INIT);
Simon Glass7567f462015-03-05 12:25:17 -070086
87 return x86_cpu_init_f();
88}
89
90int arch_cpu_init_dm(void)
91{
Simon Glass3274ae02014-11-12 22:42:13 -070092 struct pci_controller *hose;
Simon Glass044f1a02016-01-17 16:11:10 -070093 struct udevice *bus, *dev;
Simon Glass0b36ecd2014-11-12 22:42:07 -070094 int ret;
95
Simon Glasse0e7b362015-03-05 12:25:33 -070096 post_code(0x70);
97 ret = uclass_get_device(UCLASS_PCI, 0, &bus);
98 post_code(0x71);
Simon Glass0b36ecd2014-11-12 22:42:07 -070099 if (ret)
100 return ret;
Simon Glasse0e7b362015-03-05 12:25:33 -0700101 post_code(0x72);
102 hose = dev_get_uclass_priv(bus);
Simon Glass0b36ecd2014-11-12 22:42:07 -0700103
Simon Glasse0e7b362015-03-05 12:25:33 -0700104 /* TODO(sjg@chromium.org): Get rid of gd->hose */
105 gd->hose = hose;
Simon Glass3274ae02014-11-12 22:42:13 -0700106
Simon Glass044f1a02016-01-17 16:11:10 -0700107 ret = uclass_first_device(UCLASS_LPC, &dev);
108 if (!dev)
109 return -ENODEV;
110
Simon Glassf226c412014-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 Glass0b36ecd2014-11-12 22:42:07 -0700120 return 0;
121}
122
Simon Glass30580fc2014-11-12 22:42:23 -0700123#define PCH_EHCI0_TEMP_BAR0 0xe8000000
124#define PCH_EHCI1_TEMP_BAR0 0xe8000400
125#define PCH_XHCI_TEMP_BAR0 0xe8001000
126
127/*
128 * Setup USB controller MMIO BAR to prevent the reference code from
129 * resetting the controller.
130 *
131 * The BAR will be re-assigned during device enumeration so these are only
132 * temporary.
133 *
134 * This is used to speed up the resume path.
135 */
Simon Glass18df7d02016-01-17 16:11:46 -0700136static void enable_usb_bar(struct udevice *bus)
Simon Glass30580fc2014-11-12 22:42:23 -0700137{
138 pci_dev_t usb0 = PCH_EHCI1_DEV;
139 pci_dev_t usb1 = PCH_EHCI2_DEV;
140 pci_dev_t usb3 = PCH_XHCI_DEV;
Simon Glass18df7d02016-01-17 16:11:46 -0700141 ulong cmd;
Simon Glass30580fc2014-11-12 22:42:23 -0700142
143 /* USB Controller 1 */
Simon Glass18df7d02016-01-17 16:11:46 -0700144 pci_bus_write_config(bus, usb0, PCI_BASE_ADDRESS_0,
145 PCH_EHCI0_TEMP_BAR0, PCI_SIZE_32);
146 pci_bus_read_config(bus, usb0, PCI_COMMAND, &cmd, PCI_SIZE_32);
Simon Glass30580fc2014-11-12 22:42:23 -0700147 cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
Simon Glass18df7d02016-01-17 16:11:46 -0700148 pci_bus_write_config(bus, usb0, PCI_COMMAND, cmd, PCI_SIZE_32);
Simon Glass30580fc2014-11-12 22:42:23 -0700149
Simon Glass18df7d02016-01-17 16:11:46 -0700150 /* USB Controller 2 */
151 pci_bus_write_config(bus, usb1, PCI_BASE_ADDRESS_0,
152 PCH_EHCI1_TEMP_BAR0, PCI_SIZE_32);
153 pci_bus_read_config(bus, usb1, PCI_COMMAND, &cmd, PCI_SIZE_32);
Simon Glass30580fc2014-11-12 22:42:23 -0700154 cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
Simon Glass18df7d02016-01-17 16:11:46 -0700155 pci_bus_write_config(bus, usb1, PCI_COMMAND, cmd, PCI_SIZE_32);
Simon Glass30580fc2014-11-12 22:42:23 -0700156
Simon Glass18df7d02016-01-17 16:11:46 -0700157 /* USB3 Controller 1 */
158 pci_bus_write_config(bus, usb3, PCI_BASE_ADDRESS_0,
159 PCH_XHCI_TEMP_BAR0, PCI_SIZE_32);
160 pci_bus_read_config(bus, usb3, PCI_COMMAND, &cmd, PCI_SIZE_32);
Simon Glass30580fc2014-11-12 22:42:23 -0700161 cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
Simon Glass18df7d02016-01-17 16:11:46 -0700162 pci_bus_write_config(bus, usb3, PCI_COMMAND, cmd, PCI_SIZE_32);
Simon Glass30580fc2014-11-12 22:42:23 -0700163}
164
Simon Glass367077a2014-11-12 22:42:20 -0700165static int report_bist_failure(void)
166{
167 if (gd->arch.bist != 0) {
Bin Meng642d2482014-12-12 21:05:30 +0800168 post_code(POST_BIST_FAILURE);
Simon Glass367077a2014-11-12 22:42:20 -0700169 printf("BIST failed: %08x\n", gd->arch.bist);
170 return -EFAULT;
171 }
172
173 return 0;
174}
175
Simon Glass0b36ecd2014-11-12 22:42:07 -0700176int print_cpuinfo(void)
177{
Simon Glass30580fc2014-11-12 22:42:23 -0700178 enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE;
Simon Glass0b36ecd2014-11-12 22:42:07 -0700179 char processor_name[CPU_MAX_NAME_LEN];
Simon Glassb20cf042016-01-17 16:11:19 -0700180 struct udevice *dev, *lpc;
Simon Glass0b36ecd2014-11-12 22:42:07 -0700181 const char *name;
Simon Glass30580fc2014-11-12 22:42:23 -0700182 uint32_t pm1_cnt;
183 uint16_t pm1_sts;
Simon Glass367077a2014-11-12 22:42:20 -0700184 int ret;
185
186 /* Halt if there was a built in self test failure */
187 ret = report_bist_failure();
188 if (ret)
189 return ret;
Simon Glass0b36ecd2014-11-12 22:42:07 -0700190
Simon Glassd22f5c92014-11-12 22:42:27 -0700191 enable_lapic();
192
Simon Glassf79d5382014-11-12 22:42:21 -0700193 ret = microcode_update_intel();
Simon Glass9281eb52015-01-01 16:18:14 -0700194 if (ret)
Simon Glassf79d5382014-11-12 22:42:21 -0700195 return ret;
196
Simon Glass30580fc2014-11-12 22:42:23 -0700197 /* Enable upper 128bytes of CMOS */
198 writel(1 << 2, RCB_REG(RC));
199
200 /* TODO: cmos_post_init() */
201 if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) {
202 debug("soft reset detected\n");
203 boot_mode = PEI_BOOT_SOFT_RESET;
204
205 /* System is not happy after keyboard reset... */
206 debug("Issuing CF9 warm reset\n");
Simon Glass1375e9a2015-04-28 20:11:30 -0600207 reset_cpu(0);
Simon Glass30580fc2014-11-12 22:42:23 -0700208 }
209
210 /* Early chipset init required before RAM init can work */
Simon Glassaa0f23e2016-01-17 16:11:16 -0700211 uclass_first_device(UCLASS_NORTHBRIDGE, &dev);
212
Simon Glassb20cf042016-01-17 16:11:19 -0700213 ret = uclass_first_device(UCLASS_LPC, &lpc);
Simon Glassa7b1d952016-01-17 16:11:13 -0700214 if (ret)
215 return ret;
216 if (!dev)
217 return -ENODEV;
Simon Glass30580fc2014-11-12 22:42:23 -0700218
Simon Glass5cc400b2016-01-17 16:11:35 -0700219 /* Cause the SATA device to do its early init */
220 uclass_first_device(UCLASS_DISK, &dev);
221
Simon Glass30580fc2014-11-12 22:42:23 -0700222 /* Check PM1_STS[15] to see if we are waking from Sx */
223 pm1_sts = inw(DEFAULT_PMBASE + PM1_STS);
224
225 /* Read PM1_CNT[12:10] to determine which Sx state */
226 pm1_cnt = inl(DEFAULT_PMBASE + PM1_CNT);
227
228 if ((pm1_sts & WAK_STS) && ((pm1_cnt >> 10) & 7) == 5) {
Simon Glass30580fc2014-11-12 22:42:23 -0700229 debug("Resume from S3 detected, but disabled.\n");
Simon Glass30580fc2014-11-12 22:42:23 -0700230 } else {
231 /*
232 * TODO: An indication of life might be possible here (e.g.
233 * keyboard light)
234 */
235 }
236 post_code(POST_EARLY_INIT);
237
238 /* Enable SPD ROMs and DDR-III DRAM */
Simon Glass9afcd962016-01-17 16:11:45 -0700239 ret = uclass_first_device(UCLASS_I2C, &dev);
Simon Glass30580fc2014-11-12 22:42:23 -0700240 if (ret)
241 return ret;
Simon Glass9afcd962016-01-17 16:11:45 -0700242 if (!dev)
243 return -ENODEV;
Simon Glass30580fc2014-11-12 22:42:23 -0700244
245 /* Prepare USB controller early in S3 resume */
246 if (boot_mode == PEI_BOOT_RESUME)
Simon Glass18df7d02016-01-17 16:11:46 -0700247 enable_usb_bar(pci_get_controller(lpc->parent));
Simon Glass30580fc2014-11-12 22:42:23 -0700248
249 gd->arch.pei_boot_mode = boot_mode;
250
Simon Glass0b36ecd2014-11-12 22:42:07 -0700251 /* Print processor name */
252 name = cpu_get_name(processor_name);
253 printf("CPU: %s\n", name);
254
Simon Glass30580fc2014-11-12 22:42:23 -0700255 post_code(POST_CPU_INFO);
256
Simon Glass0b36ecd2014-11-12 22:42:07 -0700257 return 0;
258}
Simon Glassf2dd4702015-10-18 19:51:27 -0600259
260void board_debug_uart_init(void)
261{
262 /* This enables the debug UART */
263 pci_x86_write_config(NULL, PCH_LPC_DEV, LPC_EN, COMA_LPC_EN,
264 PCI_SIZE_16);
265}