xref: /OK3568_Linux_fs/u-boot/arch/x86/cpu/ivybridge/cpu.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (c) 2014 Google, Inc
3*4882a593Smuzhiyun  * (C) Copyright 2008
4*4882a593Smuzhiyun  * Graeme Russ, graeme.russ@gmail.com.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Some portions from coreboot src/mainboard/google/link/romstage.c
7*4882a593Smuzhiyun  * and src/cpu/intel/model_206ax/bootblock.c
8*4882a593Smuzhiyun  * Copyright (C) 2007-2010 coresystems GmbH
9*4882a593Smuzhiyun  * Copyright (C) 2011 Google Inc.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <common.h>
15*4882a593Smuzhiyun #include <dm.h>
16*4882a593Smuzhiyun #include <errno.h>
17*4882a593Smuzhiyun #include <fdtdec.h>
18*4882a593Smuzhiyun #include <pch.h>
19*4882a593Smuzhiyun #include <asm/cpu.h>
20*4882a593Smuzhiyun #include <asm/cpu_common.h>
21*4882a593Smuzhiyun #include <asm/intel_regs.h>
22*4882a593Smuzhiyun #include <asm/io.h>
23*4882a593Smuzhiyun #include <asm/lapic.h>
24*4882a593Smuzhiyun #include <asm/lpc_common.h>
25*4882a593Smuzhiyun #include <asm/microcode.h>
26*4882a593Smuzhiyun #include <asm/msr.h>
27*4882a593Smuzhiyun #include <asm/mtrr.h>
28*4882a593Smuzhiyun #include <asm/pci.h>
29*4882a593Smuzhiyun #include <asm/post.h>
30*4882a593Smuzhiyun #include <asm/processor.h>
31*4882a593Smuzhiyun #include <asm/arch/model_206ax.h>
32*4882a593Smuzhiyun #include <asm/arch/pch.h>
33*4882a593Smuzhiyun #include <asm/arch/sandybridge.h>
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
36*4882a593Smuzhiyun 
set_flex_ratio_to_tdp_nominal(void)37*4882a593Smuzhiyun static int set_flex_ratio_to_tdp_nominal(void)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	/* Minimum CPU revision for configurable TDP support */
40*4882a593Smuzhiyun 	if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
41*4882a593Smuzhiyun 		return -EINVAL;
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	return cpu_set_flex_ratio_to_tdp_nominal();
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun 
arch_cpu_init(void)46*4882a593Smuzhiyun int arch_cpu_init(void)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun 	post_code(POST_CPU_INIT);
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	return x86_cpu_init_f();
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun 
arch_cpu_init_dm(void)53*4882a593Smuzhiyun int arch_cpu_init_dm(void)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	struct pci_controller *hose;
56*4882a593Smuzhiyun 	struct udevice *bus, *dev;
57*4882a593Smuzhiyun 	int ret;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	post_code(0x70);
60*4882a593Smuzhiyun 	ret = uclass_get_device(UCLASS_PCI, 0, &bus);
61*4882a593Smuzhiyun 	post_code(0x71);
62*4882a593Smuzhiyun 	if (ret)
63*4882a593Smuzhiyun 		return ret;
64*4882a593Smuzhiyun 	post_code(0x72);
65*4882a593Smuzhiyun 	hose = dev_get_uclass_priv(bus);
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	/* TODO(sjg@chromium.org): Get rid of gd->hose */
68*4882a593Smuzhiyun 	gd->hose = hose;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	ret = uclass_first_device_err(UCLASS_LPC, &dev);
71*4882a593Smuzhiyun 	if (ret)
72*4882a593Smuzhiyun 		return ret;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	/*
75*4882a593Smuzhiyun 	 * We should do as little as possible before the serial console is
76*4882a593Smuzhiyun 	 * up. Perhaps this should move to later. Our next lot of init
77*4882a593Smuzhiyun 	 * happens in checkcpu() when we have a console
78*4882a593Smuzhiyun 	 */
79*4882a593Smuzhiyun 	ret = set_flex_ratio_to_tdp_nominal();
80*4882a593Smuzhiyun 	if (ret)
81*4882a593Smuzhiyun 		return ret;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	return 0;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun #define PCH_EHCI0_TEMP_BAR0 0xe8000000
87*4882a593Smuzhiyun #define PCH_EHCI1_TEMP_BAR0 0xe8000400
88*4882a593Smuzhiyun #define PCH_XHCI_TEMP_BAR0  0xe8001000
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun /*
91*4882a593Smuzhiyun  * Setup USB controller MMIO BAR to prevent the reference code from
92*4882a593Smuzhiyun  * resetting the controller.
93*4882a593Smuzhiyun  *
94*4882a593Smuzhiyun  * The BAR will be re-assigned during device enumeration so these are only
95*4882a593Smuzhiyun  * temporary.
96*4882a593Smuzhiyun  *
97*4882a593Smuzhiyun  * This is used to speed up the resume path.
98*4882a593Smuzhiyun  */
enable_usb_bar(struct udevice * bus)99*4882a593Smuzhiyun static void enable_usb_bar(struct udevice *bus)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	pci_dev_t usb0 = PCH_EHCI1_DEV;
102*4882a593Smuzhiyun 	pci_dev_t usb1 = PCH_EHCI2_DEV;
103*4882a593Smuzhiyun 	pci_dev_t usb3 = PCH_XHCI_DEV;
104*4882a593Smuzhiyun 	ulong cmd;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	/* USB Controller 1 */
107*4882a593Smuzhiyun 	pci_bus_write_config(bus, usb0, PCI_BASE_ADDRESS_0,
108*4882a593Smuzhiyun 			     PCH_EHCI0_TEMP_BAR0, PCI_SIZE_32);
109*4882a593Smuzhiyun 	pci_bus_read_config(bus, usb0, PCI_COMMAND, &cmd, PCI_SIZE_32);
110*4882a593Smuzhiyun 	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
111*4882a593Smuzhiyun 	pci_bus_write_config(bus, usb0, PCI_COMMAND, cmd, PCI_SIZE_32);
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	/* USB Controller 2 */
114*4882a593Smuzhiyun 	pci_bus_write_config(bus, usb1, PCI_BASE_ADDRESS_0,
115*4882a593Smuzhiyun 			     PCH_EHCI1_TEMP_BAR0, PCI_SIZE_32);
116*4882a593Smuzhiyun 	pci_bus_read_config(bus, usb1, PCI_COMMAND, &cmd, PCI_SIZE_32);
117*4882a593Smuzhiyun 	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
118*4882a593Smuzhiyun 	pci_bus_write_config(bus, usb1, PCI_COMMAND, cmd, PCI_SIZE_32);
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	/* USB3 Controller 1 */
121*4882a593Smuzhiyun 	pci_bus_write_config(bus, usb3, PCI_BASE_ADDRESS_0,
122*4882a593Smuzhiyun 			     PCH_XHCI_TEMP_BAR0, PCI_SIZE_32);
123*4882a593Smuzhiyun 	pci_bus_read_config(bus, usb3, PCI_COMMAND, &cmd, PCI_SIZE_32);
124*4882a593Smuzhiyun 	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
125*4882a593Smuzhiyun 	pci_bus_write_config(bus, usb3, PCI_COMMAND, cmd, PCI_SIZE_32);
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun 
checkcpu(void)128*4882a593Smuzhiyun int checkcpu(void)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE;
131*4882a593Smuzhiyun 	struct udevice *dev, *lpc;
132*4882a593Smuzhiyun 	uint32_t pm1_cnt;
133*4882a593Smuzhiyun 	uint16_t pm1_sts;
134*4882a593Smuzhiyun 	int ret;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	/* TODO: cmos_post_init() */
137*4882a593Smuzhiyun 	if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) {
138*4882a593Smuzhiyun 		debug("soft reset detected\n");
139*4882a593Smuzhiyun 		boot_mode = PEI_BOOT_SOFT_RESET;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 		/* System is not happy after keyboard reset... */
142*4882a593Smuzhiyun 		debug("Issuing CF9 warm reset\n");
143*4882a593Smuzhiyun 		reset_cpu(0);
144*4882a593Smuzhiyun 	}
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	ret = cpu_common_init();
147*4882a593Smuzhiyun 	if (ret) {
148*4882a593Smuzhiyun 		debug("%s: cpu_common_init() failed\n", __func__);
149*4882a593Smuzhiyun 		return ret;
150*4882a593Smuzhiyun 	}
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	/* Check PM1_STS[15] to see if we are waking from Sx */
153*4882a593Smuzhiyun 	pm1_sts = inw(DEFAULT_PMBASE + PM1_STS);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	/* Read PM1_CNT[12:10] to determine which Sx state */
156*4882a593Smuzhiyun 	pm1_cnt = inl(DEFAULT_PMBASE + PM1_CNT);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	if ((pm1_sts & WAK_STS) && ((pm1_cnt >> 10) & 7) == 5) {
159*4882a593Smuzhiyun 		debug("Resume from S3 detected, but disabled.\n");
160*4882a593Smuzhiyun 	} else {
161*4882a593Smuzhiyun 		/*
162*4882a593Smuzhiyun 		 * TODO: An indication of life might be possible here (e.g.
163*4882a593Smuzhiyun 		 * keyboard light)
164*4882a593Smuzhiyun 		 */
165*4882a593Smuzhiyun 	}
166*4882a593Smuzhiyun 	post_code(POST_EARLY_INIT);
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	/* Enable SPD ROMs and DDR-III DRAM */
169*4882a593Smuzhiyun 	ret = uclass_first_device_err(UCLASS_I2C, &dev);
170*4882a593Smuzhiyun 	if (ret) {
171*4882a593Smuzhiyun 		debug("%s: Failed to get I2C (ret=%d)\n", __func__, ret);
172*4882a593Smuzhiyun 		return ret;
173*4882a593Smuzhiyun 	}
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	/* Prepare USB controller early in S3 resume */
176*4882a593Smuzhiyun 	if (boot_mode == PEI_BOOT_RESUME) {
177*4882a593Smuzhiyun 		uclass_first_device(UCLASS_LPC, &lpc);
178*4882a593Smuzhiyun 		enable_usb_bar(pci_get_controller(lpc->parent));
179*4882a593Smuzhiyun 	}
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	gd->arch.pei_boot_mode = boot_mode;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	return 0;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun 
print_cpuinfo(void)186*4882a593Smuzhiyun int print_cpuinfo(void)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	char processor_name[CPU_MAX_NAME_LEN];
189*4882a593Smuzhiyun 	const char *name;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	/* Print processor name */
192*4882a593Smuzhiyun 	name = cpu_get_name(processor_name);
193*4882a593Smuzhiyun 	printf("CPU:   %s\n", name);
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	post_code(POST_CPU_INFO);
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	return 0;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
board_debug_uart_init(void)200*4882a593Smuzhiyun void board_debug_uart_init(void)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	/* This enables the debug UART */
203*4882a593Smuzhiyun 	pci_x86_write_config(NULL, PCH_LPC_DEV, LPC_EN, COMA_LPC_EN,
204*4882a593Smuzhiyun 			     PCI_SIZE_16);
205*4882a593Smuzhiyun }
206